FC: Ignore some HBAs from map for single WWNN
Current FC OS-Brick code only checks for single WWNN to exclude some HBAs from scanning when we don't receive an initiator_target_map from the backend. There are storage arrays,like XtremIO, that due to their architecture and design have all target ports automatically mapped to LUNs and are returning the initiator_target_map, but some of those ports may not be connected to our HBAs, so we end up with another case of bug #1765000. This patch makes sure that we always check if the target implements single WWNN, not only when we don't receive the initiator_target_map. With this we decrease the likelihood of ending with unexpected devices in our system, because now we will ignore unconnected HBAs (even if reported in the initiator_target_map) if we are working with single WWNN target. Related-Bug: #1765000 Closes-Bug: #1828440 Change-Id: I02c208142f5b342f894666831449243863eccbfe
This commit is contained in:
parent
8cb5fe3623
commit
70899a9aa3
@ -89,28 +89,28 @@ class LinuxFibreChannel(linuxscsi.LinuxSCSI):
|
||||
if ports:
|
||||
hbas = [hba for hba in hbas if hba['port_name'] in ports]
|
||||
LOG.debug('Using initiator target map to exclude HBAs')
|
||||
process = [(hba, get_ctsl(hba, connection_properties))
|
||||
for hba in hbas]
|
||||
|
||||
# With no target map we'll check if target implements single WWNN for
|
||||
# all ports, if it does we only use HBAs connected (info was found),
|
||||
# otherwise we are forced to blindly scan all HBAs.
|
||||
else:
|
||||
with_info = []
|
||||
no_info = []
|
||||
# Check if target implements single WWNN for all ports, if it does we
|
||||
# only use HBAs connected (info was found), otherwise we are forced to
|
||||
# blindly scan all HBAs. We also do this when we have
|
||||
# initiator_target_map, because some drivers return all HBAs but they
|
||||
# implement single WWNN and we avoid adding unrelated LUNs this way
|
||||
# (LP bug#1765000).
|
||||
with_info = []
|
||||
no_info = []
|
||||
|
||||
for hba in hbas:
|
||||
ctls = get_ctsl(hba, connection_properties)
|
||||
found_info = True
|
||||
for hba_channel, target_id, target_lun in ctls:
|
||||
if hba_channel == '-' or target_id == '-':
|
||||
found_info = False
|
||||
target_list = with_info if found_info else no_info
|
||||
target_list.append((hba, ctls))
|
||||
for hba in hbas:
|
||||
ctls = get_ctsl(hba, connection_properties)
|
||||
found_info = True
|
||||
for hba_channel, target_id, target_lun in ctls:
|
||||
if hba_channel == '-' or target_id == '-':
|
||||
found_info = False
|
||||
target_list = with_info if found_info else no_info
|
||||
target_list.append((hba, ctls))
|
||||
|
||||
process = with_info or no_info
|
||||
msg = "implements" if with_info else "doesn't implement"
|
||||
LOG.debug('FC target %s single WWNN for all ports.', msg)
|
||||
process = with_info or no_info
|
||||
msg = "implements" if with_info else "doesn't implement"
|
||||
LOG.debug('FC target %s single WWNN for all ports.', msg)
|
||||
|
||||
for hba, ctls in process:
|
||||
for hba_channel, target_id, target_lun in ctls:
|
||||
|
@ -295,6 +295,33 @@ class LinuxFCTestCase(base.TestCase):
|
||||
mock.call(hbas[1], con_props)]
|
||||
mock_get_chan.assert_has_calls(expected_calls)
|
||||
|
||||
def test_rescan_hosts_initiator_map_single_wwnn(self):
|
||||
"""Test FC rescan with initiator map and single WWNN."""
|
||||
get_chan_results = [[['2', '3', 1], ['4', '5', 1]], [['-', '-', 1]]]
|
||||
|
||||
hbas, con_props = self.__get_rescan_info(zone_manager=True)
|
||||
|
||||
with mock.patch.object(self.lfc, '_execute',
|
||||
return_value=None) as execute_mock, \
|
||||
mock.patch.object(self.lfc, '_get_hba_channel_scsi_target',
|
||||
side_effect=get_chan_results) as mock_get_chan:
|
||||
|
||||
self.lfc.rescan_hosts(hbas, con_props)
|
||||
expected_commands = [
|
||||
mock.call('tee', '-a', '/sys/class/scsi_host/host6/scan',
|
||||
process_input='2 3 1',
|
||||
root_helper=None, run_as_root=True),
|
||||
mock.call('tee', '-a', '/sys/class/scsi_host/host6/scan',
|
||||
process_input='4 5 1',
|
||||
root_helper=None, run_as_root=True)]
|
||||
|
||||
execute_mock.assert_has_calls(expected_commands)
|
||||
self.assertEqual(len(expected_commands), execute_mock.call_count)
|
||||
|
||||
expected_calls = [mock.call(hbas[0], con_props),
|
||||
mock.call(hbas[1], con_props)]
|
||||
mock_get_chan.assert_has_calls(expected_calls)
|
||||
|
||||
def test_rescan_hosts_wildcard(self):
|
||||
"""Test when we don't have initiator map or target is single WWNN."""
|
||||
get_chan_results = [[['-', '-', 1]], [['-', '-', 1]]]
|
||||
|
@ -0,0 +1,10 @@
|
||||
---
|
||||
fixes:
|
||||
- |
|
||||
Always check if we are dealing with a single WWNN Fibre Channel target,
|
||||
even when we receive an initiator_target_map.
|
||||
This allows us to exclude unconnected HBAs from our scan for storage arrays
|
||||
that automatically connect all target ports (due to their architecture and
|
||||
design) even if the Cinder driver returns the initiator_target_map,
|
||||
provided the target has a single WWNN.
|
||||
Excluding these HBAs prevents undesired volumes from being connected.
|
Loading…
Reference in New Issue
Block a user