Skip to content

Commit 76209bf

Browse files
NambrokWescoeur
andcommitted
feat(Linstor): rewrite linstorhostcall logic
Try to use host_OpaqueRef to access primary then try on the master host if it doesn't work, then find the primary with linstor API or if no primary, any other host. Signed-off-by: Damien Thenot <[email protected]> Co-authored-by: Ronan Abhamon <[email protected]>
1 parent 9989135 commit 76209bf

File tree

2 files changed

+59
-34
lines changed

2 files changed

+59
-34
lines changed

drivers/linstorvhdutil.py

Lines changed: 41 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -76,33 +76,6 @@ def wrapper(*args, **kwargs):
7676
self._linstor.get_volume_name(vdi_uuid)
7777
)
7878

79-
# A. Try a call using directly the DRBD device to avoid
80-
# remote request.
81-
82-
# Try to read locally if the device is not in use or if the device
83-
# is up to date and not diskless.
84-
(node_names, in_use_by) = \
85-
self._linstor.find_up_to_date_diskful_nodes(vdi_uuid)
86-
87-
local_e = None
88-
try:
89-
if not in_use_by or socket.gethostname() in node_names:
90-
return self._call_local_method(local_method, device_path, *args[2:], **kwargs)
91-
except ErofsLinstorCallException as e:
92-
local_e = e.cmd_err
93-
except Exception as e:
94-
local_e = e
95-
96-
util.SMlog(
97-
'unable to execute `{}` locally, retry using a readable host... (cause: {})'.format(
98-
remote_method, local_e if local_e else 'local diskless + in use or not up to date'
99-
)
100-
)
101-
102-
if in_use_by:
103-
node_names = {in_use_by}
104-
105-
# B. Execute the plugin on master or slave.
10679
remote_args = {
10780
'devicePath': device_path,
10881
'groupName': self._linstor.group_name
@@ -111,14 +84,48 @@ def wrapper(*args, **kwargs):
11184
remote_args = {str(key): str(value) for key, value in remote_args.iteritems()}
11285

11386
try:
114-
def remote_call():
115-
host_ref = self._get_readonly_host(vdi_uuid, device_path, node_names)
116-
return call_remote_method(self._session, host_ref, remote_method, device_path, remote_args)
117-
response = util.retry(remote_call, 5, 2)
118-
except Exception as remote_e:
119-
self._raise_openers_exception(device_path, local_e or remote_e)
87+
host_ref_attached = util.get_hosts_attached_on(self._session, [vdi_uuid])[0]
88+
if host_ref_attached:
89+
response = call_remote_method(
90+
self._session, host_ref_attached, remote_method, device_path, remote_args
91+
)
92+
return response_parser(self, vdi_uuid, response)
93+
except Exception as e:
94+
util.SMlog(
95+
'Failed to call method on attached host. Trying local access... (cause: {})'.format(e),
96+
priority=util.LOG_DEBUG
97+
)
98+
99+
try:
100+
master_ref = self._session.xenapi.pool.get_all_records().values()[0]['master']
101+
response = call_remote_method(self._session, master_ref, remote_method, device_path, remote_args)
102+
return response_parser(self, vdi_uuid, response)
103+
except Exception as e:
104+
util.SMlog(
105+
'Failed to call method on master host. Finding primary node... (cause: {})'.format(e),
106+
priority=util.LOG_DEBUG
107+
)
108+
109+
nodes, primary_hostname = self._linstor.find_up_to_date_diskful_nodes(vdi_uuid)
110+
if primary_hostname:
111+
try:
112+
host_ref = self._get_readonly_host(vdi_uuid, device_path, {primary_hostname})
113+
response = call_remote_method(self._session, host_ref, remote_method, device_path, remote_args)
114+
return response_parser(self, vdi_uuid, response)
115+
except Exception as remote_e:
116+
self._raise_openers_exception(device_path, remote_e)
117+
else:
118+
util.SMlog(
119+
'Couldn\'t get primary for {}. Trying with another node...'.format(vdi_uuid),
120+
priority=util.LOG_DEBUG
121+
)
122+
try:
123+
host = self._get_readonly_host(vdi_uuid, device_path, nodes)
124+
response = call_remote_method(self._session, host, remote_method, device_path, remote_args)
125+
return response_parser(self, vdi_uuid, response)
126+
except Exception as remote_e:
127+
self._raise_openers_exception(self, vdi_uuid, 'Couldn\'t make vhdutil call')
120128

121-
return response_parser(self, vdi_uuid, response)
122129
return wrapper
123130
return decorated
124131

drivers/linstorvolumemanager.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1431,6 +1431,24 @@ def find_up_to_date_diskful_nodes(self, volume_uuid):
14311431

14321432
return (node_names, in_use_by)
14331433

1434+
def get_primary(self, volume_uuid):
1435+
"""
1436+
Find the node that opened a volume, i.e. the primary.
1437+
:rtype: str
1438+
"""
1439+
volume_name = self.get_volume_name(volume_uuid)
1440+
1441+
resource_states = filter(
1442+
lambda resource_state: resource_state.name == volume_name,
1443+
self._get_resource_cache().resource_states
1444+
)
1445+
1446+
for resource_state in resource_states:
1447+
if resource_state.in_use:
1448+
return resource_state.node_name
1449+
1450+
return None
1451+
14341452
def invalidate_resource_cache(self):
14351453
"""
14361454
If resources are impacted by external commands like vhdutil,

0 commit comments

Comments
 (0)