FC fix for scanning only connected HBA's

When provided an initiator target map and attempting a rescan
in LinuxFibreChannel.rescan_hosts(...) if the system doesn't
yet have /sys/class/fc_host/fc_transport/** directories then
we can get into a position where the call to
LinuxFibreChannel._get_hba_channel_scsi_target will return
"None". Later on when we iterate through "process" and attempt
to iterate on "cts" this will raise an exception. We used to
fall back to a wildcard scan, and still do if no target map
is provided. This fix will do just that, for cases where we
don't have enough other information we just use wildcards.

In testing it seems like this happens on first-time connections
to a target after the ACLs have been setup on the arrays for
the initiator. After that we can get the HBA channel and SCSI
target with the grep call in _get_hba_channel_scsi_target

Change-Id: Ifd79b055882bb513fccf21d584baaeb1d60e67f2
Closes-Bug: #1774283
This commit is contained in:
Patrick East 2018-06-01 18:23:09 -07:00
parent 6545454c7e
commit 50ef90251c
2 changed files with 14 additions and 8 deletions

View File

@ -40,9 +40,10 @@ class LinuxFibreChannel(linuxscsi.LinuxSCSI):
This method only works for Fibre Channel targets that implement a This method only works for Fibre Channel targets that implement a
single WWNN for all ports, so caller should expect us to return either single WWNN for all ports, so caller should expect us to return either
None or an empty list. explicit channel and targets or wild cards if we cannot determine them.
:returns: List or None :returns: List of lists with [c, t] entries, the channel and target
may be '-' wildcards if unable to determine them.
""" """
# We want the target's WWPNs, so we use the initiator_target_map if # We want the target's WWPNs, so we use the initiator_target_map if
# present for this hba or default to target_wwns if not present. # present for this hba or default to target_wwns if not present.
@ -74,7 +75,7 @@ class LinuxFibreChannel(linuxscsi.LinuxSCSI):
LOG.debug('Could not get HBA channel and SCSI target ID, path: ' LOG.debug('Could not get HBA channel and SCSI target ID, path: '
'%(path)s*, reason: %(reason)s', {'path': path, '%(path)s*, reason: %(reason)s', {'path': path,
'reason': exc}) 'reason': exc})
return None return [['-', '-']]
def rescan_hosts(self, hbas, connection_properties): def rescan_hosts(self, hbas, connection_properties):
LOG.debug('Rescaning HBAs %(hbas)s with connection properties ' LOG.debug('Rescaning HBAs %(hbas)s with connection properties '
@ -100,8 +101,11 @@ class LinuxFibreChannel(linuxscsi.LinuxSCSI):
for hba in hbas: for hba in hbas:
cts = get_cts(hba, connection_properties) cts = get_cts(hba, connection_properties)
target_list = with_info if cts else no_info found_info = True
cts = cts or [('-', '-')] for hba_channel, target_id in cts:
if hba_channel == '-' or target_id == '-':
found_info = False
target_list = with_info if found_info else no_info
target_list.append((hba, cts)) target_list.append((hba, cts))
process = with_info or no_info process = with_info or no_info

View File

@ -135,7 +135,7 @@ class LinuxFCTestCase(base.TestCase):
'grep -Gil "514f0c50023f6c00" ' 'grep -Gil "514f0c50023f6c00" '
'/sys/class/fc_transport/target6:*/port_name', '/sys/class/fc_transport/target6:*/port_name',
shell=True) shell=True)
self.assertIsNone(res) self.assertEqual([['-', '-']], res)
def test_rescan_hosts_initiator_map(self): def test_rescan_hosts_initiator_map(self):
"""Test FC rescan with initiator map and not every HBA connected.""" """Test FC rescan with initiator map and not every HBA connected."""
@ -177,7 +177,8 @@ class LinuxFCTestCase(base.TestCase):
def test_rescan_hosts_single_wwnn(self): def test_rescan_hosts_single_wwnn(self):
"""Test FC rescan with no initiator map and single WWNN for ports.""" """Test FC rescan with no initiator map and single WWNN for ports."""
get_chan_results = [[['2', '3'], ['4', '5']], [['6', '7']], None] get_chan_results = [[['2', '3'], ['4', '5']],
[['6', '7']], [['-', '-']]]
hbas, con_props = self.__get_rescan_info(zone_manager=True) hbas, con_props = self.__get_rescan_info(zone_manager=True)
# Remove the initiator map # Remove the initiator map
@ -215,11 +216,12 @@ class LinuxFCTestCase(base.TestCase):
def test_rescan_hosts_wildcard(self): def test_rescan_hosts_wildcard(self):
"""Test when we don't have initiator map or target is single WWNN.""" """Test when we don't have initiator map or target is single WWNN."""
get_chan_results = [[['-', '-']], [['-', '-']]]
hbas, con_props = self.__get_rescan_info(zone_manager=True) hbas, con_props = self.__get_rescan_info(zone_manager=True)
# Remove the initiator map # Remove the initiator map
con_props.pop('initiator_target_map') con_props.pop('initiator_target_map')
with mock.patch.object(self.lfc, '_get_hba_channel_scsi_target', with mock.patch.object(self.lfc, '_get_hba_channel_scsi_target',
side_effect=(None, [])), \ side_effect=get_chan_results), \
mock.patch.object(self.lfc, '_execute', mock.patch.object(self.lfc, '_execute',
side_effect=None) as execute_mock: side_effect=None) as execute_mock: