Skip to content

Commit 19cdbf0

Browse files
committed
refactor(linstorvhdutil): simplify linstorhostcall
Signed-off-by: Ronan Abhamon <ronan.abhamon@vates.tech>
1 parent 0b419f4 commit 19cdbf0

1 file changed

Lines changed: 41 additions & 79 deletions

File tree

drivers/linstorvhdutil.py

Lines changed: 41 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -75,23 +75,14 @@ class NoPathLinstorCallException(LinstorCallException):
7575
pass
7676

7777
def log_successful_call(target_host, device_path, vdi_uuid, remote_method, response):
78-
util.SMlog(
79-
'Successful access on {} for device {} ({}): `{}` => {}'.format(target_host, device_path, vdi_uuid, remote_method, str(response)),
80-
priority=util.LOG_DEBUG
81-
)
78+
util.SMlog('Successful access on {} for device {} ({}): `{}` => {}'.format(
79+
target_host, device_path, vdi_uuid, remote_method, str(response)
80+
), priority=util.LOG_DEBUG)
8281

8382
def log_failed_call(target_host, next_target, device_path, vdi_uuid, remote_method, e):
84-
util.SMlog(
85-
'Failed to call method on {} for device {} ({}): {}. Trying accessing on {}... (cause: {})'.format(
86-
target_host,
87-
device_path,
88-
vdi_uuid,
89-
remote_method,
90-
next_target,
91-
e
92-
),
93-
priority=util.LOG_DEBUG
94-
)
83+
util.SMlog('Failed to call method on {} for device {} ({}): {}. Trying accessing on {}... (cause: {})'.format(
84+
target_host, device_path, vdi_uuid, remote_method, next_target, e
85+
), priority=util.LOG_DEBUG)
9586

9687
def linstorhostcall(local_method, remote_method):
9788
def decorated(response_parser):
@@ -110,52 +101,44 @@ def wrapper(*args, **kwargs):
110101
remote_args.update(**kwargs)
111102
remote_args = {str(key): str(value) for key, value in remote_args.items()}
112103

104+
def call_method(host_label, host_ref):
105+
response = call_remote_method(self._session, host_ref, remote_method, remote_args)
106+
log_successful_call(host_label, device_path, vdi_uuid, remote_method, response)
107+
return response_parser(self, vdi_uuid, response)
108+
109+
# 1. Try on attached host.
113110
try:
114111
host_ref_attached = next(iter(util.get_hosts_attached_on(self._session, [vdi_uuid])), None)
115112
if host_ref_attached:
116-
response = call_remote_method(
117-
self._session, host_ref_attached, remote_method, device_path, remote_args
118-
)
119-
log_successful_call('attached node', device_path, vdi_uuid, remote_method, response)
120-
return response_parser(self, vdi_uuid, response)
113+
return call_method('attached host', host_ref_attached)
121114
except Exception as e:
122-
log_failed_call('attached node', 'master', device_path, vdi_uuid, remote_method, e)
115+
log_failed_call('attached host', 'master', device_path, vdi_uuid, remote_method, e)
123116

117+
# 2. Try on master host.
124118
try:
125-
master_ref = util.get_master_ref(self._session)
126-
response = call_remote_method(self._session, master_ref, remote_method, device_path, remote_args)
127-
log_successful_call('master', device_path, vdi_uuid, remote_method, response)
128-
return response_parser(self, vdi_uuid, response)
119+
return call_method('master', util.get_master_ref(self._session))
129120
except Exception as e:
130121
log_failed_call('master', 'primary', device_path, vdi_uuid, remote_method, e)
131122

123+
# 3. Try on a primary.
124+
hosts = self._get_hosts(remote_method, device_path)
132125

133126
nodes, primary_hostname = self._linstor.find_up_to_date_diskful_nodes(vdi_uuid)
134127
if primary_hostname:
135128
try:
136-
host_ref = self._get_readonly_host(vdi_uuid, device_path, {primary_hostname})
137-
response = call_remote_method(self._session, host_ref, remote_method, device_path, remote_args)
138-
log_successful_call('primary', device_path, vdi_uuid, remote_method, response)
139-
return response_parser(self, vdi_uuid, response)
129+
return call_method('primary', self._find_host_ref_from_hostname(hosts, primary_hostname))
140130
except Exception as remote_e:
141131
self._raise_openers_exception(device_path, remote_e)
142-
else:
143-
log_failed_call(
144-
'primary',
145-
'another node',
146-
device_path,
147-
vdi_uuid,
148-
remote_method,
149-
'no primary'
150-
)
151132

152-
try:
153-
host = self._get_readonly_host(vdi_uuid, device_path, nodes)
154-
response = call_remote_method(self._session, host, remote_method, device_path, remote_args)
155-
log_successful_call('another node', device_path, vdi_uuid, remote_method, response)
156-
return response_parser(self, vdi_uuid, response)
157-
except Exception as remote_e:
158-
self._raise_openers_exception(device_path, remote_e)
133+
log_failed_call('primary', 'another node', device_path, vdi_uuid, remote_method, 'no primary')
134+
135+
# 4. Try on any host with local data.
136+
try:
137+
return call_method('another node', next(filter(None,
138+
(self._find_host_ref_from_hostname(hosts, hostname) for hostname in nodes)
139+
), None))
140+
except Exception as remote_e:
141+
self._raise_openers_exception(device_path, remote_e)
159142

160143
return wrapper
161144
return decorated
@@ -463,35 +446,22 @@ def _extract_uuid(self, device_path):
463446
device_path.rstrip('\n')
464447
)
465448

466-
def _get_readonly_host(self, vdi_uuid, device_path, node_names):
467-
"""
468-
When vhd-util is called to fetch VDI info we must find a
469-
diskful DRBD disk to read the data. It's the goal of this function.
470-
Why? Because when a VHD is open in RO mode, the LVM layer is used
471-
directly to bypass DRBD verifications (we can have only one process
472-
that reads/writes to disk with DRBD devices).
473-
"""
474-
475-
if not node_names:
449+
def _get_hosts(self, remote_method, device_path):
450+
try:
451+
return self._session.xenapi.host.get_all_records()
452+
except Exception as e:
476453
raise xs_errors.XenError(
477454
'VDIUnavailable',
478-
opterr='Unable to find diskful node: {} (path={})'
479-
.format(vdi_uuid, device_path)
455+
opterr='Unable to get host list to run vhdutil command `{}` (path={}): {}'
456+
.format(remote_method, device_path, e)
480457
)
481458

482-
hosts = self._session.xenapi.host.get_all_records()
483-
for host_ref, host_record in hosts.items():
484-
if host_record['hostname'] in node_names:
485-
return host_ref
486-
487-
raise xs_errors.XenError(
488-
'VDIUnavailable',
489-
opterr='Unable to find a valid host from VDI: {} (path={})'
490-
.format(vdi_uuid, device_path)
491-
)
492-
493459
# --------------------------------------------------------------------------
494460

461+
@staticmethod
462+
def _find_host_ref_from_hostname(hosts, hostname):
463+
return next((ref for ref, rec in hosts.items() if rec['hostname'] == hostname), None)
464+
495465
def _raise_openers_exception(self, device_path, e):
496466
if isinstance(e, util.CommandException):
497467
e_str = 'cmd: `{}`, code: `{}`, reason: `{}`'.format(e.cmd, e.code, e.reason)
@@ -560,14 +530,7 @@ def _call_method(self, local_method, remote_method, device_path, use_parent, *ar
560530

561531
# B. Execute the command on another host.
562532
# B.1. Get host list.
563-
try:
564-
hosts = self._session.xenapi.host.get_all_records()
565-
except Exception as e:
566-
raise xs_errors.XenError(
567-
'VDIUnavailable',
568-
opterr='Unable to get host list to run vhd-util command `{}` (path={}): {}'
569-
.format(remote_method, device_path, e)
570-
)
533+
hosts = self._get_hosts(remote_method, device_path)
571534

572535
# B.2. Prepare remote args.
573536
remote_args = {
@@ -602,9 +565,8 @@ def remote_call():
602565
if not openers:
603566
continue
604567

605-
try:
606-
host_ref = next(ref for ref, rec in hosts.items() if rec['hostname'] == hostname)
607-
except StopIteration:
568+
host_ref = self._find_host_ref_from_hostname(hosts, hostname)
569+
if not host_ref:
608570
continue
609571

610572
no_host_found = False

0 commit comments

Comments
 (0)