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 9cf135c686)
(cherry picked from commit 3eee28ce33)
This commit is contained in:
Lee Yarwood 2019-06-10 19:02:19 +01:00
parent 2e46deeaa1
commit 4f0d6cebc1
6 changed files with 37 additions and 25 deletions

View File

@ -176,7 +176,8 @@ class FibreChannelConnector(base.BaseLinuxConnector):
volume_paths = self.get_volume_paths(connection_properties) volume_paths = self.get_volume_paths(connection_properties)
if 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: else:
LOG.warning("Couldn't find any volume paths on the host to " LOG.warning("Couldn't find any volume paths on the host to "
"extend volume for %(props)s", "extend volume for %(props)s",

View File

@ -471,7 +471,8 @@ class ISCSIConnector(base.BaseLinuxConnector, base_iscsi.BaseISCSIConnector):
volume_paths = self.get_volume_paths(connection_properties) volume_paths = self.get_volume_paths(connection_properties)
LOG.info("Found paths for volume %s", volume_paths) LOG.info("Found paths for volume %s", volume_paths)
if 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: else:
LOG.warning("Couldn't find any volume paths on the host to " LOG.warning("Couldn't find any volume paths on the host to "
"extend volume for %(props)s", "extend volume for %(props)s",

View File

@ -34,7 +34,7 @@ class NVMeConnector(base.BaseLinuxConnector):
"""Connector class to attach/detach NVMe over fabric volumes.""" """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, device_scan_attempts=initiator.DEVICE_SCAN_ATTEMPTS_DEFAULT,
*args, **kwargs): *args, **kwargs):
super(NVMeConnector, self).__init__( super(NVMeConnector, self).__init__(
@ -42,6 +42,7 @@ class NVMeConnector(base.BaseLinuxConnector):
driver=driver, driver=driver,
device_scan_attempts=device_scan_attempts, device_scan_attempts=device_scan_attempts,
*args, **kwargs) *args, **kwargs)
self.use_multipath = use_multipath
@staticmethod @staticmethod
def get_connector_properties(root_helper, *args, **kwargs): def get_connector_properties(root_helper, *args, **kwargs):
@ -182,7 +183,8 @@ class NVMeConnector(base.BaseLinuxConnector):
""" """
volume_paths = self.get_volume_paths(connection_properties) volume_paths = self.get_volume_paths(connection_properties)
if 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: else:
LOG.warning("Couldn't find any volume paths on the host to " LOG.warning("Couldn't find any volume paths on the host to "
"extend volume for %(props)s", "extend volume for %(props)s",

View File

@ -531,7 +531,7 @@ class LinuxSCSI(executor.Executor):
root_helper=self._root_helper) root_helper=self._root_helper)
return out 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. """Signal the SCSI subsystem to test for volume resize.
This function tries to signal the local system's kernel 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) LOG.debug("volume size after scsi device rescan %s", new_size)
scsi_wwn = self.get_scsi_wwn(volume_paths[0]) scsi_wwn = self.get_scsi_wwn(volume_paths[0])
mpath_device = self.find_multipath_device_path(scsi_wwn) if use_multipath:
if mpath_device: mpath_device = self.find_multipath_device_path(scsi_wwn)
# Force a reconfigure so that resize works if mpath_device:
self.multipath_reconfigure() # Force a reconfigure so that resize works
self.multipath_reconfigure()
size = self.get_device_size(mpath_device) size = self.get_device_size(mpath_device)
LOG.info("mpath(%(device)s) current size %(size)s", LOG.info("mpath(%(device)s) current size %(size)s",
{'device': mpath_device, 'size': size}) {'device': mpath_device, 'size': size})
result = self.multipath_resize_map(scsi_wwn) result = self.multipath_resize_map(scsi_wwn)
if 'fail' in result: if 'fail' in result:
LOG.error("Multipathd failed to update the size mapping of " LOG.error("Multipathd failed to update the size mapping "
"multipath device %(scsi_wwn)s volume %(volume)s", "of multipath device %(scsi_wwn)s volume "
{'scsi_wwn': scsi_wwn, 'volume': volume_paths}) "%(volume)s",
return None {'scsi_wwn': scsi_wwn, 'volume': volume_paths})
return None
new_size = self.get_device_size(mpath_device) new_size = self.get_device_size(mpath_device)
LOG.info("mpath(%(device)s) new size %(size)s", LOG.info("mpath(%(device)s) new size %(size)s",
{'device': mpath_device, 'size': new_size}) {'device': mpath_device, 'size': new_size})
return new_size return new_size

View File

@ -36,7 +36,8 @@ class NVMeConnectorTestCase(test_connector.ConnectorTestCase):
def setUp(self): def setUp(self):
super(NVMeConnectorTestCase, self).setUp() super(NVMeConnectorTestCase, self).setUp()
self.connector = nvme.NVMeConnector(None, self.connector = nvme.NVMeConnector(None,
execute=self.fake_execute) execute=self.fake_execute,
use_multipath=False)
def _nvme_list_cmd(self, *args, **kwargs): def _nvme_list_cmd(self, *args, **kwargs):
return FAKE_NVME_LIST_OUTPUT, None return FAKE_NVME_LIST_OUTPUT, None
@ -153,9 +154,11 @@ class NVMeConnectorTestCase(test_connector.ConnectorTestCase):
self.connector.extend_volume, self.connector.extend_volume,
connection_properties) connection_properties)
@mock.patch.object(linuxscsi.LinuxSCSI, 'find_multipath_device_path')
@mock.patch.object(linuxscsi.LinuxSCSI, 'extend_volume') @mock.patch.object(linuxscsi.LinuxSCSI, 'extend_volume')
@mock.patch.object(nvme.NVMeConnector, 'get_volume_paths') @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 fake_new_size = 1024
mock_volume_paths.return_value = ['/dev/vdx'] mock_volume_paths.return_value = ['/dev/vdx']
mock_scsi_extend.return_value = fake_new_size mock_scsi_extend.return_value = fake_new_size
@ -166,3 +169,4 @@ class NVMeConnectorTestCase(test_connector.ConnectorTestCase):
'transport_type': 'rdma'} 'transport_type': 'rdma'}
new_size = self.connector.extend_volume(connection_properties) new_size = self.connector.extend_volume(connection_properties)
self.assertEqual(fake_new_size, new_size) self.assertEqual(fake_new_size, new_size)
mock_scsi_find_mpath.assert_not_called()

View File

@ -761,7 +761,8 @@ loop0 0"""
mock_find_mpath_path.return_value = ('/dev/mapper/dm-uuid-mpath-%s' % mock_find_mpath_path.return_value = ('/dev/mapper/dm-uuid-mpath-%s' %
wwn) 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) self.assertEqual(2048, ret_size)
# because we don't mock out the echo_scsi_command # because we don't mock out the echo_scsi_command
@ -795,7 +796,8 @@ loop0 0"""
mock_mpath_resize_map.return_value = 'fail' 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) self.assertIsNone(ret_size)
# because we don't mock out the echo_scsi_command # because we don't mock out the echo_scsi_command