Skip to content

Commit d4dc1e4

Browse files
committed
feat(linstor): simplify get_controller_uri using ss command
A significant improvement to avoid relying on DRBD commands or XAPI plugins. This change uses `ss` to obtain the destination IP address of the LINSTOR satellite source port. Signed-off-by: Ronan Abhamon <ronan.abhamon@vates.tech>
1 parent f0e6601 commit d4dc1e4

File tree

2 files changed

+30
-69
lines changed

2 files changed

+30
-69
lines changed

drivers/linstor-manager

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,12 @@ import XenAPIPlugin
2929
from json import JSONEncoder
3030
from linstorjournaler import LinstorJournaler
3131
from linstorvhdutil import LinstorVhdUtil, check_ex
32-
from linstorvolumemanager import get_controller_uri, get_local_volume_openers, LinstorVolumeManager
32+
from linstorvolumemanager import (
33+
get_controller_uri,
34+
get_local_volume_openers,
35+
LinstorVolumeManager,
36+
LINSTOR_SATELLITE_PORT,
37+
)
3338
from lock import Lock
3439
import json
3540
import LinstorSR
@@ -42,7 +47,7 @@ LVM_PLUGIN = 'lvm.py'
4247
THIN_POOL = 'thin_pool'
4348

4449
FIREWALL_PORT_SCRIPT = '/etc/xapi.d/plugins/firewall-port'
45-
LINSTOR_PORTS = [3366, 3370, 3376, 3377, 8076, 8077]
50+
LINSTOR_PORTS = [LINSTOR_SATELLITE_PORT, 3370, 3376, 3377, 8076, 8077]
4651
DRBD_PORTS = '7000:8000'
4752

4853
DRBD_REACTOR_CONF = '/etc/drbd-reactor.d/sm-linstor.toml'

drivers/linstorvolumemanager.py

Lines changed: 23 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,13 @@
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
2125
import json
2226
import linstor
2327
import os.path
@@ -38,6 +42,8 @@
3842
DATABASE_PATH = '/var/lib/linstor'
3943
DATABASE_MKFS = 'mkfs.ext4'
4044

45+
LINSTOR_SATELLITE_PORT = 3366
46+
4147
REG_DRBDADM_PRIMARY = re.compile("([^\\s]+)\\s+role:Primary")
4248
REG_DRBDSETUP_IP = re.compile('[^\\s]+\\s+(.*):.*$')
4349

@@ -128,73 +134,23 @@ 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-
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]:
180138
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 []
182149

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 ""
198154

199155
def get_controller_uri():
200156
retries = 0

0 commit comments

Comments
 (0)