[Pure Storage] Add TCP transport type to NVMe driver
Add NVMe-TCP to the existing NVMe driver, which currently supports RoCE. This change extends the parameter ``pure_nvme_transport`` to allow the option ``tcp``. Additional checks are performed on the backend to ensure that the network ports used for connections are of the correct NVMe service type. Change-Id: I76166b9305f340a6e085216490d4c6bbecc7d1c1
This commit is contained in:
parent
2e8aff660b
commit
dc77207e4c
@ -4934,14 +4934,54 @@ class PureNVMEDriverTestCase(PureBaseSharedDriverTestCase):
|
||||
self.driver.initialize_connection(vol, multipath_connector)
|
||||
|
||||
def test_get_target_nvme_ports(self):
|
||||
self.array.list_ports.return_value = NVME_PORTS
|
||||
ports = [{'name': 'CT0.ETH4',
|
||||
'wwn': None,
|
||||
'iqn': None,
|
||||
'nqn': TARGET_NQN},
|
||||
{'name': 'CT0.ETH5',
|
||||
'wwn': None,
|
||||
'iqn': TARGET_IQN,
|
||||
'nqn': None},
|
||||
{'name': 'CT0.ETH20',
|
||||
'wwn': None,
|
||||
'iqn': None,
|
||||
'nqn': TARGET_NQN},
|
||||
{'name': 'CT0.FC4',
|
||||
'wwn': TARGET_WWN,
|
||||
'iqn': None,
|
||||
'nqn': TARGET_NQN}]
|
||||
interfaces = [
|
||||
{'name': 'ct0.eth4', 'services': ['nvme-tcp']},
|
||||
{'name': 'ct0.eth5', 'services': ['iscsi']},
|
||||
{'name': 'ct0.eth20', 'services': ['nvme-roce']},
|
||||
{'name': 'ct0.fc4', 'services': ['nvme-fc']}
|
||||
]
|
||||
# Test for the nvme-tcp port
|
||||
self.driver.configuration.pure_nvme_transport = "tcp"
|
||||
self.array.get_network_interface.return_value = interfaces[0]
|
||||
self.array.list_ports.return_value = [ports[0]]
|
||||
ret = self.driver._get_target_nvme_ports(self.array)
|
||||
self.assertEqual(NVME_PORTS, ret)
|
||||
|
||||
def test_get_target_nvme_ports_with_nvme_and_fc(self):
|
||||
self.array.list_ports.return_value = NVME_PORTS_WITH
|
||||
self.assertEqual([ports[0]], ret)
|
||||
# Test for failure if no NVMe ports
|
||||
self.array.get_network_interface.return_value = interfaces[1]
|
||||
self.array.list_ports.return_value = [ports[1]]
|
||||
self.assertRaises(
|
||||
pure.PureDriverException,
|
||||
self.driver._get_target_nvme_ports,
|
||||
self.array,
|
||||
)
|
||||
# Test for the nvme-roce port
|
||||
self.driver.configuration.pure_nvme_transport = "roce"
|
||||
self.array.get_network_interface.return_value = interfaces[2]
|
||||
self.array.list_ports.return_value = [ports[2]]
|
||||
ret = self.driver._get_target_nvme_ports(self.array)
|
||||
self.assertEqual(NVME_PORTS, ret)
|
||||
self.assertEqual([ports[2]], ret)
|
||||
# Test for empty dict if only nvme-fc port
|
||||
self.driver.configuration.pure_nvme_transport = "roce"
|
||||
self.array.get_network_interface.return_value = interfaces[3]
|
||||
self.array.list_ports.return_value = [ports[3]]
|
||||
ret = self.driver._get_target_nvme_ports(self.array)
|
||||
self.assertEqual([], ret)
|
||||
|
||||
def test_get_target_nvme_ports_with_no_ports(self):
|
||||
# Should raise an exception if there are no ports
|
||||
|
@ -111,9 +111,8 @@ PURE_OPTS = [
|
||||
"IPv4 and IPv6 subnets. This parameter supersedes "
|
||||
"pure_nvme_cidr."),
|
||||
cfg.StrOpt("pure_nvme_transport", default="roce",
|
||||
choices=['roce'],
|
||||
help="The NVMe transport layer to be used by the NVMe driver. "
|
||||
"This only supports RoCE at this time."),
|
||||
choices=['roce', 'tcp'],
|
||||
help="The NVMe transport layer to be used by the NVMe driver."),
|
||||
cfg.BoolOpt("pure_eradicate_on_delete",
|
||||
default=False,
|
||||
help="When enabled, all Pure volumes, snapshots, and "
|
||||
@ -406,6 +405,13 @@ class PureBaseVolumeDriver(san.SanDriver):
|
||||
"unsupported. Please upgrade your backend to "
|
||||
"a supported version.")
|
||||
raise PureDriverException(msg)
|
||||
if version.parse(array_info["version"]) < version.parse(
|
||||
'6.4.2'
|
||||
) and self._storage_protocol == constants.NVMEOF_TCP:
|
||||
msg = _("FlashArray Purity version less than 6.4.2 "
|
||||
"unsupported for NVMe-TCP. Please upgrade your "
|
||||
"backend to a supported version.")
|
||||
raise PureDriverException(msg)
|
||||
|
||||
self._array.array_name = array_info["array_name"]
|
||||
self._array.array_id = array_info["id"]
|
||||
@ -3217,6 +3223,9 @@ class PureNVMEDriver(PureBaseVolumeDriver, driver.BaseVD):
|
||||
if self.configuration.pure_nvme_transport == "roce":
|
||||
self.transport_type = "rdma"
|
||||
self._storage_protocol = constants.NVMEOF_ROCE
|
||||
else:
|
||||
self.transport_type = "tcp"
|
||||
self._storage_protocol = constants.NVMEOF_TCP
|
||||
|
||||
def _get_nguid(self, pure_vol_name):
|
||||
"""Return the NGUID based on the volume's serial number
|
||||
@ -3331,14 +3340,24 @@ class PureNVMEDriver(PureBaseVolumeDriver, driver.BaseVD):
|
||||
return props
|
||||
|
||||
def _get_target_nvme_ports(self, array):
|
||||
"""Return list of nvme-enabled port descriptions."""
|
||||
"""Return list of correct nvme-enabled port descriptions."""
|
||||
ports = array.list_ports()
|
||||
valid_nvme_ports = []
|
||||
nvme_ports = [port for port in ports if port["nqn"]]
|
||||
for port in range(0, len(nvme_ports)):
|
||||
if "ETH" in nvme_ports[port]["name"]:
|
||||
port_detail = array.get_network_interface(
|
||||
interface=nvme_ports[port]["name"]
|
||||
)
|
||||
if port_detail["services"][0] == "nvme-" + \
|
||||
self.configuration.pure_nvme_transport:
|
||||
valid_nvme_ports.append(nvme_ports[port])
|
||||
if not nvme_ports:
|
||||
raise PureDriverException(
|
||||
reason=_("No nvme-enabled ports on target array.")
|
||||
reason=_("No %(type)s enabled ports on target array.") %
|
||||
{"type": self._storage_protocol}
|
||||
)
|
||||
return nvme_ports
|
||||
return valid_nvme_ports
|
||||
|
||||
@utils.retry(PureRetryableException, retries=HOST_CREATE_MAX_RETRIES)
|
||||
def _connect(self, array, vol_name, connector):
|
||||
|
@ -8,12 +8,12 @@ operations.
|
||||
|
||||
Support for iSCSI storage protocol is available with the PureISCSIDriver
|
||||
Volume Driver class, Fibre Channel with the PureFCDriver and
|
||||
NVMe-ROCE with the PureNVMEDriver.
|
||||
NVMe-ROCE or NVMe-TCP with the PureNVMEDriver.
|
||||
|
||||
iSCSI and Fibre Channel drivers are compatible with Purity FlashArrays
|
||||
that support the REST API version 1.6 and higher (Purity 4.7.0 and newer).
|
||||
The NVMe driver is compatible with Purity FlashArrays
|
||||
iSCSI, Fibre Channel and NVMe-RoCE drivers are compatible with FlashArrays
|
||||
that support the REST API version 1.16 and higher (Purity 5.2.0 and newer).
|
||||
The NVMe-TCP driver is compatible with FlashArrays
|
||||
that are running Purity 6.4.2 and higher.
|
||||
Some features may require newer versions of Purity.
|
||||
|
||||
Limitations and known issues
|
||||
@ -161,7 +161,7 @@ Pure Storage FlashArray as back-end storage.
|
||||
NVME connectivity.
|
||||
|
||||
If using the NVME driver, specify the ``pure_nvme_transport`` value.
|
||||
Currently only ``roce`` is supported.
|
||||
Supported values are ``roce`` or ``tcp``.
|
||||
|
||||
IP_PURE_MGMT
|
||||
The IP address of the Pure Storage array's management interface or a
|
||||
|
@ -175,7 +175,7 @@ title=Open-E JovianDSS Storage Driver (iSCSI)
|
||||
title=ProphetStor Flexvisor Driver (iSCSI, NFS)
|
||||
|
||||
[driver.pure]
|
||||
title=Pure Storage Driver (iSCSI, FC, NVMe-RoCE)
|
||||
title=Pure Storage Driver (iSCSI, FC, NVMe-RoCE, NVMe-TCP)
|
||||
|
||||
[driver.qnap]
|
||||
title=QNAP Storage Driver (iSCSI)
|
||||
|
4
releasenotes/notes/pure_nvme_tcp-a00efa8966a74f77.yaml
Normal file
4
releasenotes/notes/pure_nvme_tcp-a00efa8966a74f77.yaml
Normal file
@ -0,0 +1,4 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Pure Storage FlashArray driver: Added support NVMe-TCP transport layer.
|
Loading…
Reference in New Issue
Block a user