Fibre Channel: Fix invalid HBA adapter issues
The FC hbaapi library can report invalid HBAs, which it cannot handle. For example, in case of a VMWare based VM, it can report the SCSI controller as a FC HBA. We can avoid having issues because of this by simply ignoring adapters that could not be processed, logging a meaningful message. Change-Id: I46285521ceb60d05a4ccc50b1ccf692bd50d976c Closes-Bug: #1539702
This commit is contained in:
parent
829e2a2fa2
commit
661ea83ab8
|
@ -203,48 +203,65 @@ class FCUtilsTestCase(base.BaseTestCase):
|
|||
|
||||
self.assertEqual([], resulted_hba_ports)
|
||||
|
||||
@mock.patch.object(fc_utils.FCUtils, '_open_adapter')
|
||||
@mock.patch.object(fc_utils.FCUtils, '_close_adapter')
|
||||
@mock.patch.object(fc_utils.FCUtils, '_get_adapter_port_attributes')
|
||||
@mock.patch.object(fc_utils.FCUtils, '_get_adapter_attributes')
|
||||
@mock.patch.object(fc_utils.FCUtils, '_get_fc_hba_adapter_ports')
|
||||
@mock.patch.object(fc_utils.FCUtils, '_get_adapter_name')
|
||||
@mock.patch.object(fc_utils.FCUtils, 'get_fc_hba_count')
|
||||
def test_get_fc_hba_ports(self, mock_get_fc_hba_count,
|
||||
mock_get_adapter_name,
|
||||
mock_get_adapter_attributes,
|
||||
mock_get_adapter_port_attributes,
|
||||
mock_close_adapter,
|
||||
mock_open_adapter):
|
||||
mock_get_adapter_ports):
|
||||
fake_adapter_count = 2
|
||||
|
||||
mock_get_adapter_name.return_value = mock.sentinel.adapter_name
|
||||
mock_get_fc_hba_count.return_value = fake_adapter_count
|
||||
mock_get_adapter_ports.side_effect = [Exception,
|
||||
[mock.sentinel.port]]
|
||||
|
||||
expected_hba_ports = [mock.sentinel.port]
|
||||
resulted_hba_ports = self._fc_utils.get_fc_hba_ports()
|
||||
self.assertEqual(expected_hba_ports, resulted_hba_ports)
|
||||
self.assertEqual(expected_hba_ports, resulted_hba_ports)
|
||||
|
||||
mock_get_adapter_name.assert_has_calls(
|
||||
[mock.call(index) for index in range(fake_adapter_count)])
|
||||
mock_get_adapter_ports.assert_has_calls(
|
||||
[mock.call(mock.sentinel.adapter_name)] * fake_adapter_count)
|
||||
|
||||
@mock.patch.object(fc_utils.FCUtils, '_open_adapter')
|
||||
@mock.patch.object(fc_utils.FCUtils, '_close_adapter')
|
||||
@mock.patch.object(fc_utils.FCUtils, '_get_adapter_port_attributes')
|
||||
@mock.patch.object(fc_utils.FCUtils, '_get_adapter_attributes')
|
||||
def test_get_fc_hba_adapter_ports(self, mock_get_adapter_attributes,
|
||||
mock_get_adapter_port_attributes,
|
||||
mock_close_adapter,
|
||||
mock_open_adapter):
|
||||
fake_port_count = 1
|
||||
fake_port_index = 0
|
||||
fake_adapter_count = 1
|
||||
fake_adapter_index = 0
|
||||
# Local WWNs
|
||||
fake_node_wwn = list(range(3))
|
||||
fake_port_wwn = list(range(3))
|
||||
|
||||
mock_adapter_attributes = mock.MagicMock()
|
||||
mock_adapter_attributes.NumberOfPorts = fake_port_count
|
||||
mock_port_attributes = mock.MagicMock()
|
||||
|
||||
mock_port_attributes.NodeWWN = fake_node_wwn
|
||||
mock_port_attributes.PortWWN = fake_port_wwn
|
||||
mock_get_fc_hba_count.return_value = fake_adapter_count
|
||||
mock_adapter_attributes.NumberOfPorts = fake_port_count
|
||||
|
||||
mock_get_adapter_attributes.return_value = mock_adapter_attributes
|
||||
mock_get_adapter_port_attributes.return_value = mock_port_attributes
|
||||
|
||||
resulted_hba_ports = self._fc_utils.get_fc_hba_ports()
|
||||
resulted_hba_ports = self._fc_utils._get_fc_hba_adapter_ports(
|
||||
mock.sentinel.adapter_name)
|
||||
|
||||
expected_hba_ports = [{
|
||||
'node_name': self._fc_utils._wwn_array_to_hex_str(fake_node_wwn),
|
||||
'port_name': self._fc_utils._wwn_array_to_hex_str(fake_port_wwn)
|
||||
}]
|
||||
self.assertEqual(expected_hba_ports, resulted_hba_ports)
|
||||
mock_get_adapter_name.assert_called_once_with(fake_adapter_index)
|
||||
|
||||
mock_open_adapter.assert_called_once_with(
|
||||
adapter_name=mock_get_adapter_name.return_value)
|
||||
adapter_name=mock.sentinel.adapter_name)
|
||||
mock_close_adapter.assert_called_once_with(
|
||||
mock_open_adapter(mock_get_adapter_name.return_value))
|
||||
mock_open_adapter(mock.sentinel.adapter_nam))
|
||||
mock_get_adapter_attributes.assert_called_once_with(
|
||||
mock_open_adapter.return_value)
|
||||
mock_get_adapter_port_attributes.assert_called_once_with(
|
||||
|
|
|
@ -22,11 +22,15 @@ import textwrap
|
|||
if sys.platform == 'win32':
|
||||
hbaapi = ctypes.cdll.hbaapi
|
||||
|
||||
from os_win._i18n import _
|
||||
from oslo_log import log as logging
|
||||
|
||||
from os_win._i18n import _, _LW
|
||||
from os_win import exceptions
|
||||
from os_win.utils.storage.initiator import fc_structures as fc_struct
|
||||
from os_win.utils import win32utils
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
HBA_STATUS_OK = 0
|
||||
HBA_STATUS_ERROR_MORE_DATA = 7
|
||||
|
||||
|
@ -111,27 +115,38 @@ class FCUtils(object):
|
|||
hba_handle, ctypes.byref(hba_attributes))
|
||||
return hba_attributes
|
||||
|
||||
def _get_fc_hba_adapter_ports(self, adapter_name):
|
||||
hba_ports = []
|
||||
with self._get_hba_handle(
|
||||
adapter_name=adapter_name) as hba_handle:
|
||||
adapter_attributes = self._get_adapter_attributes(hba_handle)
|
||||
port_count = adapter_attributes.NumberOfPorts
|
||||
|
||||
for port_index in range(port_count):
|
||||
port_attributes = self._get_adapter_port_attributes(
|
||||
hba_handle,
|
||||
port_index)
|
||||
wwnn = self._wwn_array_to_hex_str(port_attributes.NodeWWN)
|
||||
wwpn = self._wwn_array_to_hex_str(port_attributes.PortWWN)
|
||||
|
||||
hba_port_info = dict(node_name=wwnn,
|
||||
port_name=wwpn)
|
||||
hba_ports.append(hba_port_info)
|
||||
return hba_ports
|
||||
|
||||
def get_fc_hba_ports(self):
|
||||
hba_ports = []
|
||||
|
||||
adapter_count = self.get_fc_hba_count()
|
||||
for adapter_index in range(adapter_count):
|
||||
adapter_name = self._get_adapter_name(adapter_index)
|
||||
with self._get_hba_handle(
|
||||
adapter_name=adapter_name) as hba_handle:
|
||||
adapter_attributes = self._get_adapter_attributes(hba_handle)
|
||||
port_count = adapter_attributes.NumberOfPorts
|
||||
|
||||
for port_index in range(port_count):
|
||||
port_attributes = self._get_adapter_port_attributes(
|
||||
hba_handle,
|
||||
port_index)
|
||||
wwnn = self._wwn_array_to_hex_str(port_attributes.NodeWWN)
|
||||
wwpn = self._wwn_array_to_hex_str(port_attributes.PortWWN)
|
||||
|
||||
hba_port_info = dict(node_name=wwnn,
|
||||
port_name=wwpn)
|
||||
hba_ports.append(hba_port_info)
|
||||
try:
|
||||
hba_ports += self._get_fc_hba_adapter_ports(adapter_name)
|
||||
except Exception as exc:
|
||||
msg = _LW("Could not retrieve FC HBA ports for "
|
||||
"adapter: %(adapter_name)s. "
|
||||
"Exception: %(exc)s")
|
||||
LOG.warning(msg, dict(adapter_name=adapter_name, exc=exc))
|
||||
|
||||
return hba_ports
|
||||
|
||||
|
|
Loading…
Reference in New Issue