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:
Lucian Petrut 2016-01-29 19:25:17 +02:00 committed by Claudiu Belu
parent 829e2a2fa2
commit 661ea83ab8
2 changed files with 65 additions and 33 deletions

View File

@ -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(

View File

@ -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