Dell PowerMax: NVMe/TCP suuport (follow-up)

Change-Id: I7ab8f7b57e13079f3d35354691c02e1f1ad930f4
Signed-off-by: Nilesh Thathagar <nilesh.thathagar@dell.com>
This commit is contained in:
Nilesh Thathagar
2025-08-30 04:55:29 +00:00
parent 4afd6cc377
commit 7926029d07
6 changed files with 69 additions and 12 deletions

View File

@@ -119,6 +119,13 @@ class PowerMaxData(object):
'nvme_hostid': nvme_tcp_hostid, 'nvme_hostid': nvme_tcp_hostid,
'nqn': nqn} 'nqn': nqn}
connector_without_host_id = {'ip': ip,
'initiator': initiator,
'wwpns': [wwpn1, wwpn2],
'wwnns': [wwnn1],
'host': 'HostX',
'nqn': nqn}
fabric_name_prefix = 'fakeFabric' fabric_name_prefix = 'fakeFabric'
end_point_map = {connector['wwpns'][0]: [wwpn1], end_point_map = {connector['wwpns'][0]: [wwpn1],
connector['wwpns'][1]: [wwpn1]} connector['wwpns'][1]: [wwpn1]}

View File

@@ -576,6 +576,13 @@ class PowerMaxMaskingTest(test.TestCase):
'0eaf7037479c432ba3d862e2889d768e', '0eaf7037479c432ba3d862e2889d768e',
foundinitiatornames[0]) foundinitiatornames[0])
def test_find_nvme_tcp_initiator_names_negative(self):
self.assertRaises(
exception.VolumeBackendAPIException,
self.driver_nvme_tcp.masking.find_initiator_names,
self.data.connector_without_host_id
)
def test_find_initiator_group_found(self): def test_find_initiator_group_found(self):
with mock.patch.object( with mock.patch.object(
rest.PowerMaxRest, 'get_initiator_list', rest.PowerMaxRest, 'get_initiator_list',

View File

@@ -157,6 +157,32 @@ class PowerMaxNVMeTCPTest(test.TestCase):
exception.InvalidConfigurationValue, exception.InvalidConfigurationValue,
self.driver.check_for_setup_error) self.driver.check_for_setup_error)
def test_check_for_setup_error_exception_without_unisphere_version(self):
with mock.patch.object(
self.common.rest, 'get_uni_version',
return_value=(None, None)) as mock_rest:
with mock.patch.object(
self.common.rest, 'get_vmax_model',
return_value=('Powermax_8500')) as mock_pmax_version:
mock_rest.assert_not_called()
mock_pmax_version.assert_not_called()
self.assertRaises(
exception.InvalidConfigurationValue,
self.driver.check_for_setup_error)
def test_check_for_setup_error_exception_without_powermax_version(self):
with mock.patch.object(
self.common.rest, 'get_uni_version',
return_value=('10.1.0.6', '101')) as mock_rest:
with mock.patch.object(
self.common.rest, 'get_vmax_model',
return_value=None) as mock_pmax_version:
mock_rest.assert_not_called()
mock_pmax_version.assert_not_called()
self.assertRaises(
exception.InvalidConfigurationValue,
self.driver.check_for_setup_error)
def test_ensure_export(self): def test_ensure_export(self):
self.driver.ensure_export('context', 'volume') self.driver.ensure_export('context', 'volume')

View File

@@ -1078,12 +1078,19 @@ class PowerMaxMasking(object):
raise exception.VolumeBackendAPIException(message=msg) raise exception.VolumeBackendAPIException(message=msg)
elif self.protocol.lower() == cinder_constants.NVMEOF_TCP.lower(): elif self.protocol.lower() == cinder_constants.NVMEOF_TCP.lower():
if 'nqn' in connector and connector['nqn']: if 'nqn' in connector and connector['nqn']:
foundinitiatornames.append(connector['nqn'] host_id = connector.get('nvme_hostid')
+ ":" if host_id:
+ str(connector. host_id = str(host_id).replace("-", "")
get('nvme_hostid')) initiator_name = connector['nqn'] + ":" + host_id
.replace("-", "")) foundinitiatornames.append(initiator_name)
name = 'nvme qualified name' else:
msg = (_("Failed to determine NVMe HostId "
"for connector NQN '%s'. "
"Ensure the host is properly "
"registered and HostId is available.")
% connector.get('nqn'))
LOG.error(msg)
raise exception.VolumeBackendAPIException(message=msg)
else: else:
msg = (_("NVMe/TCP is the protocol but nqn is " msg = (_("NVMe/TCP is the protocol but nqn is "
"not supplied by OpenStack.")) "not supplied by OpenStack."))

View File

@@ -87,8 +87,10 @@ class PowerMaxNVMETCPDriver(nvme.PowerMaxNVMEBaseDriver):
LOG.info("PowerMax version %(version)s", LOG.info("PowerMax version %(version)s",
{'version': powermax_version}) {'version': powermax_version})
if not running_version or not major_version or not powermax_version: if not running_version or not major_version or not powermax_version:
LOG.warning("Unable to validate Unisphere instance " msg = ("Unable to validate Unisphere instance "
"or PowerMax version.") "or PowerMax version.")
LOG.error(msg)
raise exception.InvalidConfigurationValue(message=msg)
else: else:
if (int(major_version) < int(U4P_100_VERSION) or if (int(major_version) < int(U4P_100_VERSION) or
(powermax_version.lower() != "powermax_2500" and (powermax_version.lower() != "powermax_2500" and
@@ -195,14 +197,13 @@ class PowerMaxNVMETCPDriver(nvme.PowerMaxNVMEBaseDriver):
(target_portals. (target_portals.
append((ip, utils.POWERMAX_NVME_TCP_PORT, append((ip, utils.POWERMAX_NVME_TCP_PORT,
utils.POWERMAX_NVME_TRANSPORT_PROTOCOL_TCP))) utils.POWERMAX_NVME_TRANSPORT_PROTOCOL_TCP)))
device_info['target_nqn'] = ( target_nqn = (self.common.get_target_nqn(target_portals,
self.common.get_target_nqn(target_portals, self.nvme_connector))
self.nvme_connector))
return { return {
"driver_volume_type": "nvmeof", "driver_volume_type": "nvmeof",
"data": { "data": {
"portals": target_portals, "portals": target_portals,
"target_nqn": device_info['target_nqn'], "target_nqn": target_nqn,
"volume_nguid": device_nguid, "volume_nguid": device_nguid,
"discard": True "discard": True
}, },

View File

@@ -60,6 +60,15 @@ Guide` at the `Dell Support`_ site.
| OpenStack | Unisphere | PowerMax OS | Supported Arrays | | OpenStack | Unisphere | PowerMax OS | Supported Arrays |
| release | for PowerMax | | | | release | for PowerMax | | |
+===========+==============+=============+================================+ +===========+==============+=============+================================+
| Flamingo | 10.2.0 | 10.2.0 | PowerMax 2500,8500 |
| | | (6079.275) | |
| +--------------+-------------+--------------------------------+
| | 10.1.0 | 10.1.0 | PowerMax 2500,8500 |
| | | (6079.225) | |
| +--------------+-------------+--------------------------------+
| | | 5978.711 | PowerMax 2000,8000 |
| | | | VMAX 250F, 450F, 850F, 950F |
+-----------+--------------+-------------+--------------------------------+
| Epoxy | 10.2.0 | 10.2.0 | PowerMax 2500,8500 | | Epoxy | 10.2.0 | 10.2.0 | PowerMax 2500,8500 |
| | | (6079.275) | | | | | (6079.275) | |
| +--------------+-------------+--------------------------------+ | +--------------+-------------+--------------------------------+