prepend platform info to by-path string

By default, udev will set device by-path name to its ID_PATH.

Looking at [1], most of the time, current code works,
but when system uses platform, then disk name will be prefixed by
'platform-xxxxx'.

[1]: a0be538616/src/udev/udev-builtin-path_id.c (L530)

Change-Id: I9b2c120f074f60b9af6dd81718a5287656040aba
Closes-Bug: #1862443
This commit is contained in:
shenjiatong 2020-02-10 16:35:15 +08:00 committed by ushen
parent df2a3969b7
commit 7c9020f006
5 changed files with 111 additions and 13 deletions

View File

@ -275,12 +275,13 @@ class FibreChannelConnector(base.BaseLinuxConnector):
def _get_host_devices(self, possible_devs):
"""Compute the device paths on the system with an id, wwn, and lun
:param possible_devs: list of (pci_id, wwn, lun) tuples
:param possible_devs: list of (platform, pci_id, wwn, lun) tuples
:return: list of device paths on the system based on the possible_devs
"""
host_devices = []
for pci_num, target_wwn, lun in possible_devs:
host_device = "/dev/disk/by-path/pci-%s-fc-%s-lun-%s" % (
for platform, pci_num, target_wwn, lun in possible_devs:
host_device = "/dev/disk/by-path/%spci-%s-fc-%s-lun-%s" % (
platform + '-' if platform else '',
pci_num,
target_wwn,
self._linuxscsi.process_lun_id(lun))
@ -293,7 +294,7 @@ class FibreChannelConnector(base.BaseLinuxConnector):
:param hbas: available hba devices.
:param targets: tuple of possible wwn addresses and lun combinations.
:returns: list of (pci_id, wwn, lun) tuples
:returns: list of (platform, pci_id, wwn, lun) tuples
Given one or more wwn (mac addresses for fibre channel) ports
do the matrix math to figure out a set of pci device, wwn
@ -303,11 +304,11 @@ class FibreChannelConnector(base.BaseLinuxConnector):
"""
raw_devices = []
for hba in hbas:
pci_num = self._get_pci_num(hba)
platform, pci_num = self._get_pci_num(hba)
if pci_num is not None:
for wwn, lun in targets:
target_wwn = "0x%s" % wwn.lower()
raw_devices.append((pci_num, target_wwn, lun))
raw_devices.append((platform, pci_num, target_wwn, lun))
return raw_devices
@utils.trace
@ -370,10 +371,18 @@ class FibreChannelConnector(base.BaseLinuxConnector):
# /sys/devices/pci0000:20/0000:20:03.0/0000:21:00.2/net/ens2f2/ctlr_2
# /host3/fc_host/host3
# we always want the value prior to the host or net value
# on non x86_64 device, pci devices may be appended on platform device,
# /sys/devices/platform/smb/smb:motherboard/80040000000.peu0-c0/pci0000:00/0000:00:03.0/0000:05:00.3/host2/fc_host/host2 # noqa
# so also return a platform id if it exists
platform = None
if hba is not None:
if "device_path" in hba:
device_path = hba['device_path'].split('/')
has_platform = (len(device_path) > 3
and device_path[3] == 'platform')
for index, value in enumerate(device_path):
if has_platform and value.startswith('pci'):
platform = "platform-%s" % device_path[index - 1]
if value.startswith('net') or value.startswith('host'):
return device_path[index - 1]
return None
return platform, device_path[index - 1]
return None, None

View File

@ -91,7 +91,7 @@ class FibreChannelConnectorS390X(fibre_channel.FibreChannelConnector):
hbas = self._linuxfc.get_fc_hbas_info()
targets = connection_properties['targets']
possible_devs = self._get_possible_devices(hbas, targets)
for pci_num, target_wwn, lun in possible_devs:
for platform, pci_num, target_wwn, lun in possible_devs:
target_lun = self._get_lun_string(lun)
self._linuxfc.deconfigure_scsi_device(pci_num,
target_wwn,

View File

@ -60,6 +60,32 @@ class FibreChannelConnectorTestCase(test_connector.ConnectorTestCase):
'vport_create': '<store method only>',
'vport_delete': '<store method only>'}]
def fake_get_fc_hbas_with_platform(self):
return [{'ClassDevice': 'host1',
'ClassDevicePath': '/sys/devices/platform/smb'
'/smb:motherboard/80040000000.peu0-c0'
'/pci0000:00/0000:00:03.0'
'/0000:05:00.2/host1/fc_host/host1',
'dev_loss_tmo': '30',
'fabric_name': '0x1000000533f55566',
'issue_lip': '<store method only>',
'max_npiv_vports': '255',
'maxframe_size': '2048 bytes',
'node_name': '0x200010604b019419',
'npiv_vports_inuse': '0',
'port_id': '0x680409',
'port_name': '0x100010604b019419',
'port_state': 'Online',
'port_type': 'NPort (fabric via point-to-point)',
'speed': '10 Gbit',
'supported_classes': 'Class 3',
'supported_speeds': '10 Gbit',
'symbolic_name': 'Emulex 554M FV4.0.493.0 DV8.3.27',
'tgtid_bind_type': 'wwpn (World Wide Port Name)',
'uevent': None,
'vport_create': '<store method only>',
'vport_delete': '<store method only>'}]
def fake_get_fc_hbas_info(self):
hbas = self.fake_get_fc_hbas()
info = [{'port_name': hbas[0]['port_name'].replace('0x', ''),
@ -68,6 +94,14 @@ class FibreChannelConnectorTestCase(test_connector.ConnectorTestCase):
'device_path': hbas[0]['ClassDevicePath']}]
return info
def fake_get_fc_hbas_info_with_platform(self):
hbas = self.fake_get_fc_hbas_with_platform()
info = [{'port_name': hbas[0]['port_name'].replace('0x', ''),
'node_name': hbas[0]['node_name'].replace('0x', ''),
'host_device': hbas[0]['ClassDevice'],
'device_path': hbas[0]['ClassDevicePath']}]
return info
def fibrechan_connection(self, volume, location, wwn, lun=1):
return {'driver_volume_type': 'fibrechan',
'data': {
@ -99,19 +133,45 @@ class FibreChannelConnectorTestCase(test_connector.ConnectorTestCase):
def test_get_pci_num(self):
hba = {'device_path': "/sys/devices/pci0000:00/0000:00:03.0"
"/0000:05:00.3/host2/fc_host/host2"}
pci_num = self.connector._get_pci_num(hba)
platform, pci_num = self.connector._get_pci_num(hba)
self.assertEqual("0000:05:00.3", pci_num)
self.assertIsNone(platform)
hba = {'device_path': "/sys/devices/pci0000:00/0000:00:03.0"
"/0000:05:00.3/0000:06:00.6/host2/fc_host/host2"}
pci_num = self.connector._get_pci_num(hba)
platform, pci_num = self.connector._get_pci_num(hba)
self.assertEqual("0000:06:00.6", pci_num)
self.assertIsNone(platform)
hba = {'device_path': "/sys/devices/pci0000:20/0000:20:03.0"
"/0000:21:00.2/net/ens2f2/ctlr_2/host3"
"/fc_host/host3"}
pci_num = self.connector._get_pci_num(hba)
platform, pci_num = self.connector._get_pci_num(hba)
self.assertEqual("0000:21:00.2", pci_num)
self.assertIsNone(platform)
def test_get_pci_num_with_platform(self):
hba = {'device_path': "/sys/devices/platform/smb/smb:motherboard/"
"80040000000.peu0-c0/pci0000:00/0000:00:03.0"
"/0000:05:00.3/host2/fc_host/host2"}
platform, pci_num = self.connector._get_pci_num(hba)
self.assertEqual("0000:05:00.3", pci_num)
self.assertEqual("platform-80040000000.peu0-c0", platform)
hba = {'device_path': "/sys/devices/platform/smb/smb:motherboard"
"/80040000000.peu0-c0/pci0000:00/0000:00:03.0"
"/0000:05:00.3/0000:06:00.6/host2/fc_host/host2"}
platform, pci_num = self.connector._get_pci_num(hba)
self.assertEqual("0000:06:00.6", pci_num)
self.assertEqual("platform-80040000000.peu0-c0", platform)
hba = {'device_path': "/sys/devices/platform/smb"
"/smb:motherboard/80040000000.peu0-c0/pci0000:20"
"/0000:20:03.0/0000:21:00.2"
"/net/ens2f2/ctlr_2/host3/fc_host/host3"}
platform, pci_num = self.connector._get_pci_num(hba)
self.assertEqual("0000:21:00.2", pci_num)
self.assertEqual("platform-80040000000.peu0-c0", platform)
@mock.patch.object(os.path, 'exists', return_value=True)
@mock.patch.object(linuxfc.LinuxFibreChannel, 'get_fc_hbas')
@ -135,6 +195,30 @@ class FibreChannelConnectorTestCase(test_connector.ConnectorTestCase):
'-fc-0x1234567890123456-lun-1']
self.assertEqual(expected, volume_paths)
@mock.patch.object(os.path, 'exists', return_value=True)
@mock.patch.object(linuxfc.LinuxFibreChannel, 'get_fc_hbas')
@mock.patch.object(linuxfc.LinuxFibreChannel, 'get_fc_hbas_info')
def test_get_volume_paths_with_platform(self, fake_fc_hbas_info,
fake_fc_hbas, fake_exists):
fake_fc_hbas.side_effect = self.fake_get_fc_hbas_with_platform
fake_fc_hbas_info.side_effect \
= self.fake_get_fc_hbas_info_with_platform
name = 'volume-00000001'
vol = {'id': 1, 'name': name}
location = '10.0.2.15:3260'
wwn = '1234567890123456'
connection_info = self.fibrechan_connection(vol, location, wwn)
conn_data = self.connector._add_targets_to_connection_properties(
connection_info['data']
)
volume_paths = self.connector.get_volume_paths(conn_data)
expected = ['/dev/disk/by-path'
'/platform-80040000000.peu0-c0-pci-0000:05:00.2'
'-fc-0x1234567890123456-lun-1']
self.assertEqual(expected, volume_paths)
@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')

View File

@ -59,7 +59,7 @@ class FibreChannelConnectorS390XTestCase(test_connector.ConnectorTestCase):
self.assertEqual(lunstring, "0x4020400a00000000")
@mock.patch.object(fibre_channel_s390x.FibreChannelConnectorS390X,
'_get_possible_devices', return_value=[(3, 5, 2), ])
'_get_possible_devices', return_value=[('', 3, 5, 2), ])
@mock.patch.object(linuxfc.LinuxFibreChannelS390X, 'get_fc_hbas_info',
return_value=[])
@mock.patch.object(linuxfc.LinuxFibreChannelS390X,

View File

@ -0,0 +1,5 @@
---
fixes:
- |
[`bug 1862433 <https://bugs.launchpad.net/os-brick/+bug/1862443>`_]
Fix an issue where platform id is needed to determine name of scsi disk.