diff --git a/os_brick/initiator/connector.py b/os_brick/initiator/connector.py index 15bbccf0a..54d5f7c81 100644 --- a/os_brick/initiator/connector.py +++ b/os_brick/initiator/connector.py @@ -508,18 +508,20 @@ class BaseLinuxConnector(InitiatorConnector): multipath_id = None if path is None: + # find_multipath_device only accept realpath not symbolic path + device_realpath = os.path.realpath(device_name) mpath_info = self._linuxscsi.find_multipath_device( - device_name) + device_realpath) if mpath_info: device_path = mpath_info['device'] multipath_id = device_wwn else: # we didn't find a multipath device. # so we assume the kernel only sees 1 device - device_path = self.host_device + device_path = device_name LOG.debug("Unable to find multipath device name for " "volume. Using path %(device)s for volume.", - {'device': self.host_device}) + {'device': device_path}) else: device_path = path multipath_id = device_wwn diff --git a/os_brick/tests/initiator/test_connector.py b/os_brick/tests/initiator/test_connector.py index 65b6dfa84..0b2f9a4e3 100644 --- a/os_brick/tests/initiator/test_connector.py +++ b/os_brick/tests/initiator/test_connector.py @@ -493,6 +493,38 @@ class ISCSIConnectorTestCase(ConnectorTestCase): 'multipath_id': FAKE_SCSI_WWN} self.assertEqual(expected_result, result) + @mock.patch.object(linuxscsi.LinuxSCSI, 'find_multipath_device_path') + @mock.patch.object(linuxscsi.LinuxSCSI, 'find_multipath_device') + @mock.patch.object(os.path, 'realpath') + def test_discover_mpath_device_by_realpath(self, mock_realpath, + mock_multipath_device, + mock_multipath_device_path): + location1 = '10.0.2.15:3260' + location2 = '[2001:db8::1]:3260' + name1 = 'volume-00000001-1' + name2 = 'volume-00000001-2' + iqn1 = 'iqn.2010-10.org.openstack:%s' % name1 + iqn2 = 'iqn.2010-10.org.openstack:%s' % name2 + fake_multipath_dev = None + fake_raw_dev = '/dev/disk/by-path/fake-raw-lun' + vol = {'id': 1, 'name': name1} + connection_properties = self.iscsi_connection_multipath( + vol, [location1, location2], [iqn1, iqn2], [1, 2]) + mock_multipath_device_path.return_value = fake_multipath_dev + mock_multipath_device.return_value = { + 'device': '/dev/mapper/%s' % FAKE_SCSI_WWN} + mock_realpath.return_value = '/dev/sdvc' + (result_path, result_mpath_id) = ( + self.connector_with_multipath._discover_mpath_device( + FAKE_SCSI_WWN, + connection_properties['data'], + fake_raw_dev)) + mock_multipath_device.assert_called_with('/dev/sdvc') + result = {'path': result_path, 'multipath_id': result_mpath_id} + expected_result = {'path': '/dev/mapper/%s' % FAKE_SCSI_WWN, + 'multipath_id': FAKE_SCSI_WWN} + self.assertEqual(expected_result, result) + @mock.patch('time.sleep', mock.Mock()) def _test_connect_volume(self, extra_props, additional_commands, transport=None, disconnect_mock=None):