Fix FC multipath cleanup

Cleanup order for multipath should be:
- Flush multipath (multipath -f device)
- Flush blockdev devices (blockdev --flushbufs device)
- Remove paths

But now we have:
- Flush blockdev devices (blockdev --flushbufs device)
- Flush multipath (multipath -f device)
- Remove paths

This patch sets the right order and adds a test to avoid regression.

Closes-Bug: #1502979
Change-Id: I065a79514e0fcaf722f57e2edd6f18f31878c711
This commit is contained in:
Gorka Eguileor 2015-10-05 20:17:20 +02:00
parent 8900ce1958
commit d937f64af2
2 changed files with 22 additions and 20 deletions

View File

@ -268,15 +268,15 @@ class FibreChannelConnector(base.BaseLinuxConnector):
device_info = self._linuxscsi.get_device_info(real_path) device_info = self._linuxscsi.get_device_info(real_path)
devices.append(device_info) devices.append(device_info)
LOG.debug("devices to remove = %s", devices)
self._remove_devices(connection_properties, devices)
if self.use_multipath: if self.use_multipath:
# There is a bug in multipath where the flushing # There is a bug in multipath where the flushing
# doesn't remove the entry if friendly names are on # doesn't remove the entry if friendly names are on
# we'll try anyway. # we'll try anyway.
self._linuxscsi.flush_multipath_device(wwn) self._linuxscsi.flush_multipath_device(wwn)
LOG.debug("devices to remove = %s", devices)
self._remove_devices(connection_properties, devices)
def _remove_devices(self, connection_properties, devices): def _remove_devices(self, connection_properties, devices):
# There may have been more than 1 device mounted # There may have been more than 1 device mounted
# by the kernel for this volume. We have to remove # by the kernel for this volume. We have to remove

View File

@ -195,7 +195,6 @@ class FibreChannelConnectorTestCase(test_connector.ConnectorTestCase):
def _test_connect_volume_multipath(self, get_device_info_mock, def _test_connect_volume_multipath(self, get_device_info_mock,
get_scsi_wwn_mock, get_scsi_wwn_mock,
remove_device_mock,
get_fc_hbas_info_mock, get_fc_hbas_info_mock,
get_fc_hbas_mock, get_fc_hbas_mock,
realpath_mock, realpath_mock,
@ -215,8 +214,12 @@ class FibreChannelConnectorTestCase(test_connector.ConnectorTestCase):
"devices": [{'device': '/dev/sdb', "devices": [{'device': '/dev/sdb',
'address': '1:0:0:1', 'address': '1:0:0:1',
'host': 1, 'channel': 0, 'host': 1, 'channel': 0,
'id': 0, 'lun': 1},
{'device': '/dev/sdc',
'address': '1:0:0:2',
'host': 1, 'channel': 0,
'id': 0, 'lun': 1}]} 'id': 0, 'lun': 1}]}
get_device_info_mock.return_value = devices['devices'][0] get_device_info_mock.side_effect = devices['devices']
get_scsi_wwn_mock.return_value = wwn get_scsi_wwn_mock.return_value = wwn
location = '10.0.2.15:3260' location = '10.0.2.15:3260'
@ -233,6 +236,17 @@ class FibreChannelConnectorTestCase(test_connector.ConnectorTestCase):
self.connector.connect_volume(connection_info['data']) self.connector.connect_volume(connection_info['data'])
self.assertEqual(should_wait_for_rw, wait_for_rw_mock.called) self.assertEqual(should_wait_for_rw, wait_for_rw_mock.called)
self.connector.disconnect_volume(connection_info['data'],
devices['devices'][0])
expected_commands = [
'multipath -f ' + wwn,
'blockdev --flushbufs /dev/sdb',
'tee -a /sys/block/sdb/device/delete',
'blockdev --flushbufs /dev/sdc',
'tee -a /sys/block/sdc/device/delete',
]
self.assertEqual(expected_commands, self.cmds)
return connection_info return connection_info
@mock.patch.object(linuxscsi.LinuxSCSI, 'find_multipath_device') @mock.patch.object(linuxscsi.LinuxSCSI, 'find_multipath_device')
@ -241,12 +255,10 @@ class FibreChannelConnectorTestCase(test_connector.ConnectorTestCase):
@mock.patch.object(os.path, 'realpath', return_value='/dev/sdb') @mock.patch.object(os.path, 'realpath', return_value='/dev/sdb')
@mock.patch.object(linuxfc.LinuxFibreChannel, 'get_fc_hbas') @mock.patch.object(linuxfc.LinuxFibreChannel, 'get_fc_hbas')
@mock.patch.object(linuxfc.LinuxFibreChannel, 'get_fc_hbas_info') @mock.patch.object(linuxfc.LinuxFibreChannel, 'get_fc_hbas_info')
@mock.patch.object(linuxscsi.LinuxSCSI, 'remove_scsi_device')
@mock.patch.object(linuxscsi.LinuxSCSI, 'get_scsi_wwn') @mock.patch.object(linuxscsi.LinuxSCSI, 'get_scsi_wwn')
@mock.patch.object(linuxscsi.LinuxSCSI, 'get_device_info') @mock.patch.object(linuxscsi.LinuxSCSI, 'get_device_info')
def test_connect_volume_multipath_rw(self, get_device_info_mock, def test_connect_volume_multipath_rw(self, get_device_info_mock,
get_scsi_wwn_mock, get_scsi_wwn_mock,
remove_device_mock,
get_fc_hbas_info_mock, get_fc_hbas_info_mock,
get_fc_hbas_mock, get_fc_hbas_mock,
realpath_mock, realpath_mock,
@ -256,7 +268,6 @@ class FibreChannelConnectorTestCase(test_connector.ConnectorTestCase):
self._test_connect_volume_multipath(get_device_info_mock, self._test_connect_volume_multipath(get_device_info_mock,
get_scsi_wwn_mock, get_scsi_wwn_mock,
remove_device_mock,
get_fc_hbas_info_mock, get_fc_hbas_info_mock,
get_fc_hbas_mock, get_fc_hbas_mock,
realpath_mock, realpath_mock,
@ -272,13 +283,11 @@ class FibreChannelConnectorTestCase(test_connector.ConnectorTestCase):
@mock.patch.object(os.path, 'realpath', return_value='/dev/sdb') @mock.patch.object(os.path, 'realpath', return_value='/dev/sdb')
@mock.patch.object(linuxfc.LinuxFibreChannel, 'get_fc_hbas') @mock.patch.object(linuxfc.LinuxFibreChannel, 'get_fc_hbas')
@mock.patch.object(linuxfc.LinuxFibreChannel, 'get_fc_hbas_info') @mock.patch.object(linuxfc.LinuxFibreChannel, 'get_fc_hbas_info')
@mock.patch.object(linuxscsi.LinuxSCSI, 'remove_scsi_device')
@mock.patch.object(linuxscsi.LinuxSCSI, 'get_scsi_wwn') @mock.patch.object(linuxscsi.LinuxSCSI, 'get_scsi_wwn')
@mock.patch.object(linuxscsi.LinuxSCSI, 'get_device_info') @mock.patch.object(linuxscsi.LinuxSCSI, 'get_device_info')
def test_connect_volume_multipath_no_access_mode(self, def test_connect_volume_multipath_no_access_mode(self,
get_device_info_mock, get_device_info_mock,
get_scsi_wwn_mock, get_scsi_wwn_mock,
remove_device_mock,
get_fc_hbas_info_mock, get_fc_hbas_info_mock,
get_fc_hbas_mock, get_fc_hbas_mock,
realpath_mock, realpath_mock,
@ -288,7 +297,6 @@ class FibreChannelConnectorTestCase(test_connector.ConnectorTestCase):
self._test_connect_volume_multipath(get_device_info_mock, self._test_connect_volume_multipath(get_device_info_mock,
get_scsi_wwn_mock, get_scsi_wwn_mock,
remove_device_mock,
get_fc_hbas_info_mock, get_fc_hbas_info_mock,
get_fc_hbas_mock, get_fc_hbas_mock,
realpath_mock, realpath_mock,
@ -304,12 +312,10 @@ class FibreChannelConnectorTestCase(test_connector.ConnectorTestCase):
@mock.patch.object(os.path, 'realpath', return_value='/dev/sdb') @mock.patch.object(os.path, 'realpath', return_value='/dev/sdb')
@mock.patch.object(linuxfc.LinuxFibreChannel, 'get_fc_hbas') @mock.patch.object(linuxfc.LinuxFibreChannel, 'get_fc_hbas')
@mock.patch.object(linuxfc.LinuxFibreChannel, 'get_fc_hbas_info') @mock.patch.object(linuxfc.LinuxFibreChannel, 'get_fc_hbas_info')
@mock.patch.object(linuxscsi.LinuxSCSI, 'remove_scsi_device')
@mock.patch.object(linuxscsi.LinuxSCSI, 'get_scsi_wwn') @mock.patch.object(linuxscsi.LinuxSCSI, 'get_scsi_wwn')
@mock.patch.object(linuxscsi.LinuxSCSI, 'get_device_info') @mock.patch.object(linuxscsi.LinuxSCSI, 'get_device_info')
def test_connect_volume_multipath_ro(self, get_device_info_mock, def test_connect_volume_multipath_ro(self, get_device_info_mock,
get_scsi_wwn_mock, get_scsi_wwn_mock,
remove_device_mock,
get_fc_hbas_info_mock, get_fc_hbas_info_mock,
get_fc_hbas_mock, get_fc_hbas_mock,
realpath_mock, realpath_mock,
@ -319,7 +325,6 @@ class FibreChannelConnectorTestCase(test_connector.ConnectorTestCase):
self._test_connect_volume_multipath(get_device_info_mock, self._test_connect_volume_multipath(get_device_info_mock,
get_scsi_wwn_mock, get_scsi_wwn_mock,
remove_device_mock,
get_fc_hbas_info_mock, get_fc_hbas_info_mock,
get_fc_hbas_mock, get_fc_hbas_mock,
realpath_mock, realpath_mock,
@ -336,13 +341,11 @@ class FibreChannelConnectorTestCase(test_connector.ConnectorTestCase):
@mock.patch.object(os.path, 'realpath', return_value='/dev/sdb') @mock.patch.object(os.path, 'realpath', return_value='/dev/sdb')
@mock.patch.object(linuxfc.LinuxFibreChannel, 'get_fc_hbas') @mock.patch.object(linuxfc.LinuxFibreChannel, 'get_fc_hbas')
@mock.patch.object(linuxfc.LinuxFibreChannel, 'get_fc_hbas_info') @mock.patch.object(linuxfc.LinuxFibreChannel, 'get_fc_hbas_info')
@mock.patch.object(linuxscsi.LinuxSCSI, 'remove_scsi_device')
@mock.patch.object(linuxscsi.LinuxSCSI, 'get_scsi_wwn') @mock.patch.object(linuxscsi.LinuxSCSI, 'get_scsi_wwn')
@mock.patch.object(linuxscsi.LinuxSCSI, 'get_device_info') @mock.patch.object(linuxscsi.LinuxSCSI, 'get_device_info')
def test_connect_volume_multipath_not_found(self, def test_connect_volume_multipath_not_found(self,
get_device_info_mock, get_device_info_mock,
get_scsi_wwn_mock, get_scsi_wwn_mock,
remove_device_mock,
get_fc_hbas_info_mock, get_fc_hbas_info_mock,
get_fc_hbas_mock, get_fc_hbas_mock,
realpath_mock, realpath_mock,
@ -354,10 +357,9 @@ class FibreChannelConnectorTestCase(test_connector.ConnectorTestCase):
None) None)
connection_info = self._test_connect_volume_multipath( connection_info = self._test_connect_volume_multipath(
get_device_info_mock, get_scsi_wwn_mock, remove_device_mock, get_device_info_mock, get_scsi_wwn_mock, get_fc_hbas_info_mock,
get_fc_hbas_info_mock, get_fc_hbas_mock, realpath_mock, get_fc_hbas_mock, realpath_mock, exists_mock, wait_for_rw_mock,
exists_mock, wait_for_rw_mock, find_mp_dev_mock, find_mp_dev_mock, 'rw', False)
'rw', False)
self.assertNotIn('multipathd_id', connection_info['data']) self.assertNotIn('multipathd_id', connection_info['data'])