From 4f0d6cebc1557f82c2138d74390888265ef28ec1 Mon Sep 17 00:00:00 2001 From: Lee Yarwood Date: Mon, 10 Jun 2019 19:02:19 +0100 Subject: [PATCH] linuxscsi: Stop waiting for multipath devices during extend_volume Previously linuxscsi.extend_volume would always attempt to wait for multipath devices to appear regardless of multipath actually being used by the connector. This change corrects this by passing down the existing use_multipath attribute from the iSCSI and FC connectors into linuxscsi.extend_volume. The same attribute is introduced to the NVMe connector to also allow it to skip this search for multipath devices. Conflicts: os_brick/initiator/connectors/nvme.py NOTE(lyarwood): Due to I6b70140be7023770b83603de723d6d2de3ebb747 not being present in stable/queens. Change-Id: I29d65ae036957f3a63cba93dd330b14e3361a1b9 Closes-bug: #1832247 (cherry picked from commit 9cf135c68640f81838e2898b4aef3e0445770089) (cherry picked from commit 3eee28ce33df69cb4605338f140d2fa6e22bcd88) --- .../initiator/connectors/fibre_channel.py | 3 +- os_brick/initiator/connectors/iscsi.py | 3 +- os_brick/initiator/connectors/nvme.py | 6 ++-- os_brick/initiator/linuxscsi.py | 36 ++++++++++--------- .../tests/initiator/connectors/test_nvme.py | 8 +++-- os_brick/tests/initiator/test_linuxscsi.py | 6 ++-- 6 files changed, 37 insertions(+), 25 deletions(-) diff --git a/os_brick/initiator/connectors/fibre_channel.py b/os_brick/initiator/connectors/fibre_channel.py index 5d95b4fbe..a46628137 100644 --- a/os_brick/initiator/connectors/fibre_channel.py +++ b/os_brick/initiator/connectors/fibre_channel.py @@ -176,7 +176,8 @@ class FibreChannelConnector(base.BaseLinuxConnector): volume_paths = self.get_volume_paths(connection_properties) if volume_paths: - return self._linuxscsi.extend_volume(volume_paths) + return self._linuxscsi.extend_volume( + volume_paths, use_multipath=self.use_multipath) else: LOG.warning("Couldn't find any volume paths on the host to " "extend volume for %(props)s", diff --git a/os_brick/initiator/connectors/iscsi.py b/os_brick/initiator/connectors/iscsi.py index d696dc105..05028c745 100644 --- a/os_brick/initiator/connectors/iscsi.py +++ b/os_brick/initiator/connectors/iscsi.py @@ -471,7 +471,8 @@ class ISCSIConnector(base.BaseLinuxConnector, base_iscsi.BaseISCSIConnector): volume_paths = self.get_volume_paths(connection_properties) LOG.info("Found paths for volume %s", volume_paths) if volume_paths: - return self._linuxscsi.extend_volume(volume_paths) + return self._linuxscsi.extend_volume( + volume_paths, use_multipath=self.use_multipath) else: LOG.warning("Couldn't find any volume paths on the host to " "extend volume for %(props)s", diff --git a/os_brick/initiator/connectors/nvme.py b/os_brick/initiator/connectors/nvme.py index 277ac2716..1ad51e2f7 100644 --- a/os_brick/initiator/connectors/nvme.py +++ b/os_brick/initiator/connectors/nvme.py @@ -34,7 +34,7 @@ class NVMeConnector(base.BaseLinuxConnector): """Connector class to attach/detach NVMe over fabric volumes.""" - def __init__(self, root_helper, driver=None, + def __init__(self, root_helper, driver=None, use_multipath=False, device_scan_attempts=initiator.DEVICE_SCAN_ATTEMPTS_DEFAULT, *args, **kwargs): super(NVMeConnector, self).__init__( @@ -42,6 +42,7 @@ class NVMeConnector(base.BaseLinuxConnector): driver=driver, device_scan_attempts=device_scan_attempts, *args, **kwargs) + self.use_multipath = use_multipath @staticmethod def get_connector_properties(root_helper, *args, **kwargs): @@ -182,7 +183,8 @@ class NVMeConnector(base.BaseLinuxConnector): """ volume_paths = self.get_volume_paths(connection_properties) if volume_paths: - return self._linuxscsi.extend_volume(volume_paths) + return self._linuxscsi.extend_volume( + volume_paths, use_multipath=self.use_multipath) else: LOG.warning("Couldn't find any volume paths on the host to " "extend volume for %(props)s", diff --git a/os_brick/initiator/linuxscsi.py b/os_brick/initiator/linuxscsi.py index 7c14ba5fb..9014bc71f 100644 --- a/os_brick/initiator/linuxscsi.py +++ b/os_brick/initiator/linuxscsi.py @@ -531,7 +531,7 @@ class LinuxSCSI(executor.Executor): root_helper=self._root_helper) return out - def extend_volume(self, volume_paths): + def extend_volume(self, volume_paths, use_multipath=False): """Signal the SCSI subsystem to test for volume resize. This function tries to signal the local system's kernel @@ -561,24 +561,26 @@ class LinuxSCSI(executor.Executor): LOG.debug("volume size after scsi device rescan %s", new_size) scsi_wwn = self.get_scsi_wwn(volume_paths[0]) - mpath_device = self.find_multipath_device_path(scsi_wwn) - if mpath_device: - # Force a reconfigure so that resize works - self.multipath_reconfigure() + if use_multipath: + mpath_device = self.find_multipath_device_path(scsi_wwn) + if mpath_device: + # Force a reconfigure so that resize works + self.multipath_reconfigure() - size = self.get_device_size(mpath_device) - LOG.info("mpath(%(device)s) current size %(size)s", - {'device': mpath_device, 'size': size}) - result = self.multipath_resize_map(scsi_wwn) - if 'fail' in result: - LOG.error("Multipathd failed to update the size mapping of " - "multipath device %(scsi_wwn)s volume %(volume)s", - {'scsi_wwn': scsi_wwn, 'volume': volume_paths}) - return None + size = self.get_device_size(mpath_device) + LOG.info("mpath(%(device)s) current size %(size)s", + {'device': mpath_device, 'size': size}) + result = self.multipath_resize_map(scsi_wwn) + if 'fail' in result: + LOG.error("Multipathd failed to update the size mapping " + "of multipath device %(scsi_wwn)s volume " + "%(volume)s", + {'scsi_wwn': scsi_wwn, 'volume': volume_paths}) + return None - new_size = self.get_device_size(mpath_device) - LOG.info("mpath(%(device)s) new size %(size)s", - {'device': mpath_device, 'size': new_size}) + new_size = self.get_device_size(mpath_device) + LOG.info("mpath(%(device)s) new size %(size)s", + {'device': mpath_device, 'size': new_size}) return new_size diff --git a/os_brick/tests/initiator/connectors/test_nvme.py b/os_brick/tests/initiator/connectors/test_nvme.py index 69cfcbb10..a988e3e16 100644 --- a/os_brick/tests/initiator/connectors/test_nvme.py +++ b/os_brick/tests/initiator/connectors/test_nvme.py @@ -36,7 +36,8 @@ class NVMeConnectorTestCase(test_connector.ConnectorTestCase): def setUp(self): super(NVMeConnectorTestCase, self).setUp() self.connector = nvme.NVMeConnector(None, - execute=self.fake_execute) + execute=self.fake_execute, + use_multipath=False) def _nvme_list_cmd(self, *args, **kwargs): return FAKE_NVME_LIST_OUTPUT, None @@ -153,9 +154,11 @@ class NVMeConnectorTestCase(test_connector.ConnectorTestCase): self.connector.extend_volume, connection_properties) + @mock.patch.object(linuxscsi.LinuxSCSI, 'find_multipath_device_path') @mock.patch.object(linuxscsi.LinuxSCSI, 'extend_volume') @mock.patch.object(nvme.NVMeConnector, 'get_volume_paths') - def test_extend_volume(self, mock_volume_paths, mock_scsi_extend): + def test_extend_volume(self, mock_volume_paths, mock_scsi_extend, + mock_scsi_find_mpath): fake_new_size = 1024 mock_volume_paths.return_value = ['/dev/vdx'] mock_scsi_extend.return_value = fake_new_size @@ -166,3 +169,4 @@ class NVMeConnectorTestCase(test_connector.ConnectorTestCase): 'transport_type': 'rdma'} new_size = self.connector.extend_volume(connection_properties) self.assertEqual(fake_new_size, new_size) + mock_scsi_find_mpath.assert_not_called() diff --git a/os_brick/tests/initiator/test_linuxscsi.py b/os_brick/tests/initiator/test_linuxscsi.py index 21d4beda0..583150b03 100644 --- a/os_brick/tests/initiator/test_linuxscsi.py +++ b/os_brick/tests/initiator/test_linuxscsi.py @@ -761,7 +761,8 @@ loop0 0""" mock_find_mpath_path.return_value = ('/dev/mapper/dm-uuid-mpath-%s' % wwn) - ret_size = self.linuxscsi.extend_volume(['/dev/fake1', '/dev/fake2']) + ret_size = self.linuxscsi.extend_volume(['/dev/fake1', '/dev/fake2'], + use_multipath=True) self.assertEqual(2048, ret_size) # because we don't mock out the echo_scsi_command @@ -795,7 +796,8 @@ loop0 0""" mock_mpath_resize_map.return_value = 'fail' - ret_size = self.linuxscsi.extend_volume(['/dev/fake1', '/dev/fake2']) + ret_size = self.linuxscsi.extend_volume(['/dev/fake1', '/dev/fake2'], + use_multipath=True) self.assertIsNone(ret_size) # because we don't mock out the echo_scsi_command