From 8d3e40b7cd0ee73cc422afddc0ad37a23673ef73 Mon Sep 17 00:00:00 2001 From: zengjia Date: Wed, 5 Jun 2019 13:47:16 +0800 Subject: [PATCH] Check path alive before get scsi wwn In FC environment, when disconnect volume, if the first path in the loop is failed, it will lead get scsi wwn to failure. So I think we need to add path validity check before get scsi wwn Change-Id: I9d3a9dac13dcd585330e7b891c61b2626e5aabec Closes-Bug: 1831621 (cherry picked from commit 3b8d5b7886b9a45df6b666ef594f4a337914856d) --- .../initiator/connectors/fibre_channel.py | 3 +- .../connectors/test_fibre_channel.py | 62 +++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/os_brick/initiator/connectors/fibre_channel.py b/os_brick/initiator/connectors/fibre_channel.py index c30267b8e..5d95b4fbe 100644 --- a/os_brick/initiator/connectors/fibre_channel.py +++ b/os_brick/initiator/connectors/fibre_channel.py @@ -336,7 +336,8 @@ class FibreChannelConnector(base.BaseLinuxConnector): mpath_path = None for path in volume_paths: real_path = self._linuxscsi.get_name_from_path(path) - if self.use_multipath and not mpath_path: + if (self.use_multipath and not mpath_path + and self.check_valid_device(path)): wwn = self._linuxscsi.get_scsi_wwn(path) mpath_path = self._linuxscsi.find_multipath_device_path(wwn) if mpath_path: diff --git a/os_brick/tests/initiator/connectors/test_fibre_channel.py b/os_brick/tests/initiator/connectors/test_fibre_channel.py index bb579c2aa..de41dff94 100644 --- a/os_brick/tests/initiator/connectors/test_fibre_channel.py +++ b/os_brick/tests/initiator/connectors/test_fibre_channel.py @@ -665,3 +665,65 @@ class FibreChannelConnectorTestCase(test_connector.ConnectorTestCase): self.assertIn('initiator_target_lun_map', connection_info) self.assertEqual(expected_map, connection_info['initiator_target_lun_map']) + + @mock.patch.object(linuxscsi.LinuxSCSI, 'find_multipath_device') + @mock.patch.object(linuxscsi.LinuxSCSI, 'wait_for_rw') + @mock.patch.object(os.path, 'exists', return_value=True) + @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_info') + @mock.patch.object(linuxscsi.LinuxSCSI, 'get_scsi_wwn') + @mock.patch.object(linuxscsi.LinuxSCSI, 'get_device_info') + @mock.patch.object(linuxscsi.LinuxSCSI, 'find_multipath_device_path') + @mock.patch.object(base.BaseLinuxConnector, 'check_valid_device') + def test_disconnect_volume(self, check_valid_device_mock, + find_mp_device_path_mock, + get_device_info_mock, + get_scsi_wwn_mock, + get_fc_hbas_info_mock, + get_fc_hbas_mock, + realpath_mock, + exists_mock, + wait_for_rw_mock, + find_mp_dev_mock): + + check_valid_device_mock.return_value = True + self.connector.use_multipath = True + get_fc_hbas_mock.side_effect = self.fake_get_fc_hbas + get_fc_hbas_info_mock.side_effect = self.fake_get_fc_hbas_info + + wwn = '1234567890' + multipath_devname = '/dev/md-1' + devices = {"device": multipath_devname, + "id": wwn, + "devices": [{'device': '/dev/sdb', + 'address': '1:0:0:1', + 'host': 1, 'channel': 0, + 'id': 0, 'lun': 1}, + {'device': '/dev/sdc', + 'address': '1:0:0:2', + 'host': 1, 'channel': 0, + 'id': 0, 'lun': 1}]} + get_device_info_mock.side_effect = devices['devices'] + get_scsi_wwn_mock.return_value = wwn + + location = '10.0.2.15:3260' + name = 'volume-00000001' + vol = {'id': 1, 'name': name} + initiator_wwn = ['1234567890123456', '1234567890123457'] + + find_mp_device_path_mock.return_value = '/dev/mapper/mpatha' + find_mp_dev_mock.return_value = {"device": "dm-3", + "id": wwn, + "name": "mpatha"} + + connection_info = self.fibrechan_connection(vol, location, + initiator_wwn) + self.connector.disconnect_volume(connection_info['data'], + devices['devices'][0]) + expected_commands = [ + 'multipath -f ' + find_mp_device_path_mock.return_value, + 'tee -a /sys/block/sdb/device/delete', + 'tee -a /sys/block/sdc/device/delete', + ] + self.assertEqual(expected_commands, self.cmds)