1515# along with this program. If not, see <https://www.gnu.org/licenses/>.
1616#
1717
18- from sm_typing import Any , Dict , override
18+ from sm_typing import (
19+ Any ,
20+ Dict ,
21+ List ,
22+ override ,
23+ )
1924
20- import errno
2125import json
2226import linstor
2327import os .path
3842DATABASE_PATH = '/var/lib/linstor'
3943DATABASE_MKFS = 'mkfs.ext4'
4044
45+ LINSTOR_SATELLITE_PORT = 3366
46+
4147REG_DRBDADM_PRIMARY = re .compile ("([^\\ s]+)\\ s+role:Primary" )
4248REG_DRBDSETUP_IP = re .compile ('[^\\ s]+\\ s+(.*):.*$' )
4349
@@ -128,73 +134,25 @@ def round_down(value, divisor):
128134
129135# ==============================================================================
130136
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-
137+ def _get_controller_addresses () -> List [str ]:
138138 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.
180- 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+ if ret == 0 :
143+ return [
144+ line .split ()[3 ].rsplit (":" , 1 )[0 ]
145+ for line in stdout .splitlines ()
146+ ]
147+ util .SMlog (f"Unexpected code { ret } : { stderr } " )
148+ except Exception as e :
149+ util .SMlog (f"Unable to get controller addresses: { e } " )
150+ return []
182151
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
152+ def _get_controller_uri () -> str :
153+ # TODO: Check that an IP address from the current pool is returned.
154+ addresses = _get_controller_addresses ()
155+ return "linstor://" + addresses [0 ] if addresses else ""
198156
199157def get_controller_uri ():
200158 retries = 0
@@ -204,7 +162,7 @@ def get_controller_uri():
204162 return uri
205163
206164 retries += 1
207- if retries >= 10 :
165+ if retries >= 30 :
208166 break
209167 time .sleep (1 )
210168
0 commit comments