Skip to content

Commit

Permalink
Add 0179-feat-Linstor-rewrite-linstorhostcall-logic.patch
Browse files Browse the repository at this point in the history
Signed-off-by: Damien Thenot <[email protected]>
  • Loading branch information
Nambrok committed Jul 31, 2024
1 parent 330c790 commit 9acfb02
Show file tree
Hide file tree
Showing 2 changed files with 173 additions and 1 deletion.
168 changes: 168 additions & 0 deletions SOURCES/0179-feat-Linstor-rewrite-linstorhostcall-logic.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
From 3f63f6aaa51aaf806de529c169d09b85ace85241 Mon Sep 17 00:00:00 2001
From: Damien Thenot <[email protected]>
Date: Fri, 19 Apr 2024 14:55:49 +0200
Subject: [PATCH 179/179] 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]>
---
drivers/linstorvhdutil.py | 86 ++++++++++++++++++---------------
drivers/linstorvolumemanager.py | 18 +++++++
2 files changed, 66 insertions(+), 38 deletions(-)

diff --git a/drivers/linstorvhdutil.py b/drivers/linstorvhdutil.py
index 7f8efa1..4b7115b 100644
--- a/drivers/linstorvhdutil.py
+++ b/drivers/linstorvhdutil.py
@@ -33,18 +33,21 @@ EMEDIUMTYPE = 124


def call_remote_method(session, host_ref, method, device_path, args):
+ host_rec = session.xenapi.host.get_record(host_ref)
+ host_uuid = host_rec['uuid']
+
try:
response = session.xenapi.host.call_plugin(
host_ref, MANAGER_PLUGIN, method, args
)
except Exception as e:
- util.SMlog('call-plugin ({} with {}) exception: {}'.format(
- method, args, e
+ util.SMlog('call-plugin on {} ({} with {}) exception: {}'.format(
+ host_uuid, method, args, e
))
raise util.SMException(str(e))

- util.SMlog('call-plugin ({} with {}) returned: {}'.format(
- method, args, response
+ util.SMlog('call-plugin on {} ({} with {}) returned: {}'.format(
+ host_uuid, method, args, response
))

return response
@@ -86,33 +89,6 @@ def linstorhostcall(local_method, remote_method):
self._linstor.get_volume_name(vdi_uuid)
)

- # A. Try a call using directly the DRBD device to avoid
- # remote request.
-
- # Try to read locally if the device is not in use or if the device
- # is up to date and not diskless.
- (node_names, in_use_by) = \
- self._linstor.find_up_to_date_diskful_nodes(vdi_uuid)
-
- local_e = None
- try:
- if not in_use_by or socket.gethostname() in node_names:
- return self._call_local_method(local_method, device_path, *args[2:], **kwargs)
- except ErofsLinstorCallException as e:
- local_e = e.cmd_err
- except Exception as e:
- local_e = e
-
- util.SMlog(
- 'unable to execute `{}` locally, retry using a readable host... (cause: {})'.format(
- remote_method, local_e if local_e else 'local diskless + in use or not up to date'
- )
- )
-
- if in_use_by:
- node_names = {in_use_by}
-
- # B. Execute the plugin on master or slave.
remote_args = {
'devicePath': device_path,
'groupName': self._linstor.group_name
@@ -121,14 +97,48 @@ def linstorhostcall(local_method, remote_method):
remote_args = {str(key): str(value) for key, value in remote_args.iteritems()}

try:
- def remote_call():
- host_ref = self._get_readonly_host(vdi_uuid, device_path, node_names)
- return call_remote_method(self._session, host_ref, remote_method, device_path, remote_args)
- response = util.retry(remote_call, 5, 2)
- except Exception as remote_e:
- self._raise_openers_exception(device_path, local_e or remote_e)
+ host_ref_attached = util.get_hosts_attached_on(self._session, [vdi_uuid])[0]
+ if host_ref_attached:
+ response = call_remote_method(
+ self._session, host_ref_attached, remote_method, device_path, remote_args
+ )
+ return response_parser(self, vdi_uuid, response)
+ except Exception as e:
+ util.SMlog(
+ 'Failed to call method on attached host. Trying local access... (cause: {})'.format(e),
+ priority=util.LOG_DEBUG
+ )
+
+ try:
+ master_ref = self._session.xenapi.pool.get_all_records().values()[0]['master']
+ response = call_remote_method(self._session, master_ref, remote_method, device_path, remote_args)
+ return response_parser(self, vdi_uuid, response)
+ except Exception as e:
+ util.SMlog(
+ 'Failed to call method on master host. Finding primary node... (cause: {})'.format(e),
+ priority=util.LOG_DEBUG
+ )
+
+ nodes, primary_hostname = self._linstor.find_up_to_date_diskful_nodes(vdi_uuid)
+ if primary_hostname:
+ try:
+ host_ref = self._get_readonly_host(vdi_uuid, device_path, {primary_hostname})
+ response = call_remote_method(self._session, host_ref, remote_method, device_path, remote_args)
+ return response_parser(self, vdi_uuid, response)
+ except Exception as remote_e:
+ self._raise_openers_exception(device_path, remote_e)
+ else:
+ util.SMlog(
+ 'Couldn\'t get primary for {}. Trying with another node...'.format(vdi_uuid),
+ priority=util.LOG_DEBUG
+ )
+ try:
+ host = self._get_readonly_host(vdi_uuid, device_path, nodes)
+ response = call_remote_method(self._session, host, remote_method, device_path, remote_args)
+ return response_parser(self, vdi_uuid, response)
+ except Exception as remote_e:
+ self._raise_openers_exception(device_path, remote_e)

- return response_parser(self, vdi_uuid, response)
return wrapper
return decorated

diff --git a/drivers/linstorvolumemanager.py b/drivers/linstorvolumemanager.py
index 8bfd1c1..fb47b09 100755
--- a/drivers/linstorvolumemanager.py
+++ b/drivers/linstorvolumemanager.py
@@ -1438,6 +1438,24 @@ class LinstorVolumeManager(object):

return (node_names, in_use_by)

+ def get_primary(self, volume_uuid):
+ """
+ Find the node that opened a volume, i.e. the primary.
+ :rtype: str
+ """
+ volume_name = self.get_volume_name(volume_uuid)
+
+ resource_states = filter(
+ lambda resource_state: resource_state.name == volume_name,
+ self._get_resource_cache().resource_states
+ )
+
+ for resource_state in resource_states:
+ if resource_state.in_use:
+ return resource_state.node_name
+
+ return None
+
def invalidate_resource_cache(self):
"""
If resources are impacted by external commands like vhdutil,
--
2.45.2

6 changes: 5 additions & 1 deletion SPECS/sm.spec
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
Summary: sm - XCP storage managers
Name: sm
Version: 2.30.8
Release: %{?xsrel}.1.0.linstor.4%{?dist}
Release: %{?xsrel}.1.0.linstor.5%{?dist}
Group: System/Hypervisor
License: LGPL
URL: https://github.com/xapi-project/sm
Expand Down Expand Up @@ -274,6 +274,7 @@ Patch1175: 0175-fix-LinstorSR-Misc-fixes-on-destroy.patch
Patch1176: 0176-fix-LinstorSR-open-non-leaf-volumes-in-RO-mode-creat.patch
Patch1177: 0177-fix-LinstorSR-ensure-_is_master-is-always-set.patch
Patch1178: 0178-fix-linstor-check-if-resource-is-tiebreaker-62.patch
Patch1179: 0179-feat-Linstor-rewrite-linstorhostcall-logic.patch

%description
This package contains storage backends used in XCP
Expand Down Expand Up @@ -690,6 +691,9 @@ cp -r htmlcov %{buildroot}/htmlcov
%{_unitdir}/linstor-monitor.service

%changelog
* Wed Jul 31 2024 Damien Thenot <[email protected]> 2.30.8-12.1.0.linstor.5
- Add 0179-feat-Linstor-rewrite-linstorhostcall-logic.patch

* Fri Jul 26 2024 Ronan Abhamon <[email protected]> 2.30.8-12.1.0.linstor.4
- Add 0177-fix-LinstorSR-ensure-_is_master-is-always-set.patch
- Add 0178-fix-linstor-check-if-resource-is-tiebreaker-62.patch
Expand Down

0 comments on commit 9acfb02

Please sign in to comment.