Leverage the iSCSI mpath to get the WWN

Now that we search the multipath device even if we haven't been able to
find the WWN in the sysfs we can leverage the multipath daemon
information on sysfs to get the WWN.

Pass the mpath to "get_sysfs_wwn" method where we check the sysfs to get
the WWN.

Change-Id: Id1905bc174b8f2f3a345664d8a0a05284ca69927
This commit is contained in:
Gorka Eguileor 2020-06-01 19:07:47 +02:00 committed by Brian Rosmaita
parent 6974808cb5
commit 0cdd9bbbe2
4 changed files with 46 additions and 3 deletions

View File

@ -737,7 +737,7 @@ class ISCSIConnector(base.BaseLinuxConnector, base_iscsi.BaseISCSIConnector):
data['failed_logins'])):
# We have devices but we don't know the wwn yet
if not wwn and found:
wwn = self._linuxscsi.get_sysfs_wwn(found)
wwn = self._linuxscsi.get_sysfs_wwn(found, mpath)
if not mpath and found:
mpath = self._linuxscsi.find_sysfs_multipath_dm(found)
# We have the wwn but not a multipath
@ -778,6 +778,8 @@ class ISCSIConnector(base.BaseLinuxConnector, base_iscsi.BaseISCSIConnector):
if not mpath:
LOG.warning('No dm was created, connection to volume is probably '
'bad and will perform poorly.')
elif not wwn:
wwn = self._linuxscsi.get_sysfs_wwn(found, mpath)
return self._get_connect_result(connection_properties, wwn, found,
mpath)

View File

@ -127,8 +127,20 @@ class LinuxSCSI(executor.Executor):
LOG.debug('dev_info=%s', str(dev_info))
return dev_info
def get_sysfs_wwn(self, device_names):
def get_sysfs_wwn(self, device_names, mpath=None):
"""Return the wwid from sysfs in any of devices in udev format."""
# If we have a multipath DM we know that it has found the WWN
if mpath:
# We have the WWN in /uuid even with friendly names, unline /name
try:
with open('/sys/block/%s/dm/uuid' % mpath) as f:
# Contents are matph-WWN, so get the part we want
wwid = f.read().strip()[6:]
if wwid: # Check should not be needed, but just in case
return wwid
except Exception as exc:
LOG.warning('Failed to read the DM uuid: %s', exc)
wwid = self.get_sysfs_wwid(device_names)
glob_str = '/dev/disk/by-id/scsi-'
wwn_paths = glob.glob(glob_str + '*')

View File

@ -1206,6 +1206,8 @@ Setting up iSCSI targets: unused
result = list(get_wwn_mock.call_args[0][0])
result.sort()
self.assertEqual(['sda', 'sdb', 'sdc', 'sdd'], result)
# Check we pass the mpath
self.assertIsNone(get_wwn_mock.call_args[0][1])
add_wwid_mock.assert_called_once_with('wwn')
self.assertNotEqual(0, add_path_mock.call_count)
self.assertGreaterEqual(find_dm_mock.call_count, 2)
@ -1238,10 +1240,13 @@ Setting up iSCSI targets: unused
'path': '/dev/dm-0'}
self.assertEqual(expected, res)
self.assertEqual(2, get_wwn_mock.call_count)
self.assertEqual(3, get_wwn_mock.call_count)
result = list(get_wwn_mock.call_args[0][0])
result.sort()
self.assertEqual(['sda', 'sdb', 'sdc', 'sdd'], result)
# Initially mpath we pass is None, but on last call is the mpath
mpath_values = [c[1][1] for c in get_wwn_mock._mock_mock_calls]
self.assertEqual([None, None, 'dm-0'], mpath_values)
add_wwid_mock.assert_not_called()
add_path_mock.assert_not_called()
self.assertGreaterEqual(find_dm_mock.call_count, 2)

View File

@ -860,6 +860,16 @@ loop0 0"""
'id': '0',
'lun': '0'})
@mock.patch('six.moves.builtins.open')
def test_get_sysfs_wwn_mpath(self, open_mock):
wwn = '3600d0230000000000e13955cc3757800'
cm_open = open_mock.return_value.__enter__.return_value
cm_open.read.return_value = 'mpath-' + wwn
res = self.linuxscsi.get_sysfs_wwn(mock.sentinel.device_names, 'dm-1')
open_mock.assert_called_once_with('/sys/block/dm-1/dm/uuid')
self.assertEqual(wwn, res)
@mock.patch('glob.glob')
@mock.patch.object(linuxscsi.LinuxSCSI, 'get_sysfs_wwid')
def test_get_sysfs_wwn_single_designator(self, get_wwid_mock, glob_mock):
@ -871,6 +881,20 @@ loop0 0"""
glob_mock.assert_called_once_with('/dev/disk/by-id/scsi-*')
get_wwid_mock.assert_called_once_with(mock.sentinel.device_names)
@mock.patch('six.moves.builtins.open', side_effect=Exception)
@mock.patch('glob.glob')
@mock.patch.object(linuxscsi.LinuxSCSI, 'get_sysfs_wwid')
def test_get_sysfs_wwn_mpath_exc(self, get_wwid_mock, glob_mock,
open_mock):
glob_mock.return_value = ['/dev/disk/by-id/scsi-wwid1',
'/dev/disk/by-id/scsi-wwid2']
get_wwid_mock.return_value = 'wwid1'
res = self.linuxscsi.get_sysfs_wwn(mock.sentinel.device_names, 'dm-1')
open_mock.assert_called_once_with('/sys/block/dm-1/dm/uuid')
self.assertEqual('wwid1', res)
glob_mock.assert_called_once_with('/dev/disk/by-id/scsi-*')
get_wwid_mock.assert_called_once_with(mock.sentinel.device_names)
@mock.patch('os.listdir', return_value=['sda', 'sdd'])
@mock.patch('os.path.realpath', side_effect=('/other/path',
'/dev/dm-5',