|
15 | 15 | # along with this program. If not, see <https://www.gnu.org/licenses/>. |
16 | 16 | # |
17 | 17 |
|
18 | | -from sm_typing import Any, Dict, override |
| 18 | +from sm_typing import ( |
| 19 | + Any, |
| 20 | + Dict, |
| 21 | + List, |
| 22 | + override, |
| 23 | +) |
19 | 24 |
|
20 | | -import errno |
21 | 25 | import json |
22 | 26 | import linstor |
23 | 27 | import os.path |
|
38 | 42 | DATABASE_PATH = '/var/lib/linstor' |
39 | 43 | DATABASE_MKFS = 'mkfs.ext4' |
40 | 44 |
|
| 45 | +LINSTOR_SATELLITE_PORT = 3366 |
| 46 | + |
41 | 47 | REG_DRBDADM_PRIMARY = re.compile("([^\\s]+)\\s+role:Primary") |
42 | 48 | REG_DRBDSETUP_IP = re.compile('[^\\s]+\\s+(.*):.*$') |
43 | 49 |
|
@@ -128,73 +134,23 @@ def round_down(value, divisor): |
128 | 134 |
|
129 | 135 | # ============================================================================== |
130 | 136 |
|
131 | | -def get_remote_host_ip(node_name): |
132 | | - (ret, stdout, stderr) = util.doexec([ |
133 | | - 'drbdsetup', 'show', DATABASE_VOLUME_NAME, '--json' |
134 | | - ]) |
135 | | - if ret != 0: |
136 | | - return |
137 | | - |
138 | | - try: |
139 | | - conf = json.loads(stdout) |
140 | | - if not conf: |
141 | | - return |
142 | | - |
143 | | - for connection in conf[0]['connections']: |
144 | | - if connection['net']['_name'] == node_name: |
145 | | - value = connection['path']['_remote_host'] |
146 | | - res = REG_DRBDSETUP_IP.match(value) |
147 | | - if res: |
148 | | - return res.groups()[0] |
149 | | - break |
150 | | - except Exception: |
151 | | - pass |
152 | | - |
153 | | - |
154 | | -def _get_controller_uri(): |
155 | | - PLUGIN_CMD = 'hasControllerRunning' |
156 | | - |
157 | | - # Try to find controller using drbdadm. |
158 | | - (ret, stdout, stderr) = util.doexec([ |
159 | | - 'drbdadm', 'status', DATABASE_VOLUME_NAME |
160 | | - ]) |
161 | | - if ret == 0: |
162 | | - # If we are here, the database device exists locally. |
163 | | - |
164 | | - if stdout.startswith('{} role:Primary'.format(DATABASE_VOLUME_NAME)): |
165 | | - # Nice case, we have the controller running on this local host. |
166 | | - return 'linstor://localhost' |
167 | | - |
168 | | - # Try to find the host using DRBD connections. |
169 | | - res = REG_DRBDADM_PRIMARY.search(stdout) |
170 | | - if res: |
171 | | - node_name = res.groups()[0] |
172 | | - ip = get_remote_host_ip(node_name) |
173 | | - if ip: |
174 | | - return 'linstor://' + ip |
175 | | - |
176 | | - # Worst case: we use many hosts in the pool (>= 4), so we can't find the |
177 | | - # primary using drbdadm because we don't have all connections to the |
178 | | - # replicated volume. `drbdadm status xcp-persistent-database` returns |
179 | | - # 3 connections by default. |
| 137 | +def _get_controller_addresses() -> List[str]: |
180 | 138 | try: |
181 | | - session = util.timeout_call(10, util.get_localAPI_session) |
| 139 | + (ret, stdout, stderr) = util.doexec([ |
| 140 | + "/usr/sbin/ss", "-tnpH", "state", "established", f"( sport = :{LINSTOR_SATELLITE_PORT} )" |
| 141 | + ]) |
| 142 | + return [ |
| 143 | + line.split()[3].split(":")[0] |
| 144 | + for line in stdout.splitlines() |
| 145 | + ] |
| 146 | + except Exception as e: |
| 147 | + util.SMlog(f"Unable to get controller addresses: {e}") |
| 148 | + return [] |
182 | 149 |
|
183 | | - for host_ref, host_record in session.xenapi.host.get_all_records().items(): |
184 | | - node_name = host_record['hostname'] |
185 | | - try: |
186 | | - if util.strtobool( |
187 | | - session.xenapi.host.call_plugin(host_ref, PLUGIN, PLUGIN_CMD, {}) |
188 | | - ): |
189 | | - return 'linstor://' + host_record['address'] |
190 | | - except Exception as e: |
191 | | - # Can throw and exception if a host is offline. So catch it. |
192 | | - util.SMlog('Unable to search controller on `{}`: {}'.format( |
193 | | - node_name, e |
194 | | - )) |
195 | | - except: |
196 | | - # Not found, maybe we are trying to create the SR... |
197 | | - pass |
| 150 | +def _get_controller_uri() -> str: |
| 151 | + # TODO: Check that an IP address from the current pool is returned. |
| 152 | + addresses = _get_controller_addresses() |
| 153 | + return "linstor://" + addresses[0] if addresses else "" |
198 | 154 |
|
199 | 155 | def get_controller_uri(): |
200 | 156 | retries = 0 |
|
0 commit comments