LVM: Added NVMe TCP support for the nvmet target

This patch adds NVMe TCP transport protocol support to the LVM driver's
nvmet target helper.

Configuration option is ``target_protocol = nvmet_tcp`` when using
``nvmet`` as the ``target_helper``.

NVMe TCP has been supported since:

- RHEL 8
- CentOS 8-Stream
- Fedora 28
- Ubuntu 19.04
- SUSE Linux Enterprise Server 15
- openSUSE 15.1/15.2

No changes to OS-Brick are necessary, since the transport type is not
hardcoded in the connector and uses the value from 'transport_type'
present in the connection info dictionary instead.

Change-Id: Icc0ad567d304bf3de1e34873ad8562650ada9383
This commit is contained in:
Gorka Eguileor 2021-05-17 18:39:32 +02:00
parent 1e4002aa8b
commit eb1b23dc6c
6 changed files with 28 additions and 13 deletions

View File

@ -12,6 +12,7 @@
from unittest import mock from unittest import mock
import ddt
from oslo_utils import timeutils from oslo_utils import timeutils
from cinder import context from cinder import context
@ -20,12 +21,15 @@ from cinder import utils
from cinder.volume.targets import nvmet from cinder.volume.targets import nvmet
@ddt.ddt
class TestNVMETDriver(tf.TargetDriverFixture): class TestNVMETDriver(tf.TargetDriverFixture):
def setUp(self): def setUp(self):
super(TestNVMETDriver, self).setUp() super(TestNVMETDriver, self).setUp()
self.initialize('nvmet_rdma', 'rdma')
self.configuration.target_protocol = 'nvmet_rdma' def initialize(self, target_protocol, transport_type):
self.configuration.target_protocol = target_protocol
self.target = nvmet.NVMET(root_helper=utils.get_root_helper(), self.target = nvmet.NVMET(root_helper=utils.get_root_helper(),
configuration=self.configuration) configuration=self.configuration)
@ -34,7 +38,7 @@ class TestNVMETDriver(tf.TargetDriverFixture):
self.nvmet_subsystem_name = self.configuration.target_prefix self.nvmet_subsystem_name = self.configuration.target_prefix
self.nvmet_ns_id = self.configuration.nvmet_ns_id self.nvmet_ns_id = self.configuration.nvmet_ns_id
self.nvmet_port_id = self.configuration.nvmet_port_id self.nvmet_port_id = self.configuration.nvmet_port_id
self.nvme_transport_type = 'rdma' self.nvme_transport_type = transport_type
self.fake_volume_id = 'c446b9a2-c968-4260-b95f-a18a7b41c004' self.fake_volume_id = 'c446b9a2-c968-4260-b95f-a18a7b41c004'
self.testvol_path = ( self.testvol_path = (
@ -56,12 +60,16 @@ class TestNVMETDriver(tf.TargetDriverFixture):
'created_at': timeutils.utcnow(), 'created_at': timeutils.utcnow(),
'host': 'fake_host@lvm#lvm'}) 'host': 'fake_host@lvm#lvm'})
@ddt.data(('nvmet_rdma', 'rdma'), ('nvmet_tcp', 'tcp'))
@ddt.unpack
@mock.patch.object(nvmet.NVMET, '_get_nvmf_subsystem') @mock.patch.object(nvmet.NVMET, '_get_nvmf_subsystem')
@mock.patch.object(nvmet.NVMET, '_get_available_nvmf_subsystems') @mock.patch.object(nvmet.NVMET, '_get_available_nvmf_subsystems')
@mock.patch.object(nvmet.NVMET, '_add_nvmf_subsystem') @mock.patch.object(nvmet.NVMET, '_add_nvmf_subsystem')
def test_create_export(self, mock_add_nvmf_subsystem, def test_create_export(self, target_protocol, transport_type,
mock_add_nvmf_subsystem,
mock_get_available_nvmf_subsystems, mock_get_available_nvmf_subsystems,
mock_get_nvmf_subsystem): mock_get_nvmf_subsystem):
self.initialize(target_protocol, transport_type)
mock_testvol = self.testvol mock_testvol = self.testvol
mock_testvol_path = self.testvol_path mock_testvol_path = self.testvol_path
@ -75,7 +83,7 @@ class TestNVMETDriver(tf.TargetDriverFixture):
"portid": 1, "portid": 1,
"addr": "addr":
{"treq": "not specified", {"treq": "not specified",
"trtype": "rdma", "trtype": self.nvme_transport_type,
"adrfam": "ipv4", "adrfam": "ipv4",
"trsvcid": self.target_port, "trsvcid": self.target_port,
"traddr": "traddr":
@ -126,7 +134,7 @@ class TestNVMETDriver(tf.TargetDriverFixture):
"portid": 1, "portid": 1,
"addr": "addr":
{"treq": "not specified", {"treq": "not specified",
"trtype": "rdma", "trtype": self.nvme_transport_type,
"adrfam": "ipv4", "adrfam": "ipv4",
"trsvcid": self.target_port, "trsvcid": self.target_port,
"traddr": "traddr":
@ -180,7 +188,7 @@ class TestNVMETDriver(tf.TargetDriverFixture):
"portid": self.nvmet_port_id, "portid": self.nvmet_port_id,
"addr": "addr":
{"treq": "not specified", {"treq": "not specified",
"trtype": "rdma", "trtype": self.nvme_transport_type,
"adrfam": "ipv4", "adrfam": "ipv4",
"trsvcid": self.target_port, "trsvcid": self.target_port,
"traddr": self.target_ip}} "traddr": self.target_ip}}
@ -249,7 +257,7 @@ class TestNVMETDriver(tf.TargetDriverFixture):
"portid": self.nvmet_port_id, "portid": self.nvmet_port_id,
"addr": "addr":
{"treq": "not specified", {"treq": "not specified",
"trtype": "rdma", "trtype": self.nvme_transport_type,
"adrfam": "ipv4", "adrfam": "ipv4",
"trsvcid": self.target_port, "trsvcid": self.target_port,
"traddr": self.target_ip}} "traddr": self.target_ip}}

View File

@ -136,13 +136,13 @@ volume_opts = [
'as is to the underlying tool.'), 'as is to the underlying tool.'),
cfg.StrOpt('target_protocol', cfg.StrOpt('target_protocol',
default='iscsi', default='iscsi',
choices=['iscsi', 'iser', 'nvmet_rdma'], choices=['iscsi', 'iser', 'nvmet_rdma', 'nvmet_tcp'],
help='Determines the target protocol for new volumes, ' help='Determines the target protocol for new volumes, '
'created with tgtadm, lioadm and nvmet target helpers. ' 'created with tgtadm, lioadm and nvmet target helpers. '
'In order to enable RDMA, this parameter should be set ' 'In order to enable RDMA, this parameter should be set '
'with the value "iser". The supported iSCSI protocol ' 'with the value "iser". The supported iSCSI protocol '
'values are "iscsi" and "iser", in case of nvmet target ' 'values are "iscsi" and "iser", in case of nvmet target '
'set to "nvmet_rdma".'), 'set to "nvmet_rdma" or "nvmet_tcp".'),
cfg.StrOpt('driver_client_cert_key', cfg.StrOpt('driver_client_cert_key',
help='The path to the client certificate key for verification, ' help='The path to the client certificate key for verification, '
'if the driver supports it.'), 'if the driver supports it.'),

View File

@ -125,7 +125,7 @@ class LVMVolumeDriver(driver.VolumeDriver):
'target_port', 'target_port',
'iscsi_write_cache', 'iscsi_target_flags', # TGT 'iscsi_write_cache', 'iscsi_target_flags', # TGT
'iet_conf', 'iscsi_iotype', # IET 'iet_conf', 'iscsi_iotype', # IET
'nvmet_port_id', # NVMET 'nvmet_port_id', 'nvmet_ns_id', # NVMET
'scst_target_iqn_name', 'scst_target_driver', # SCST 'scst_target_iqn_name', 'scst_target_driver', # SCST
'spdk_rpc_ip', 'spdk_rpc_port', 'spdk_rpc_username', # SPDKNVMF 'spdk_rpc_ip', 'spdk_rpc_port', 'spdk_rpc_username', # SPDKNVMF
'spdk_rpc_password', 'spdk_max_queue_depth', # SPDKNVMF 'spdk_rpc_password', 'spdk_max_queue_depth', # SPDKNVMF

View File

@ -34,6 +34,7 @@ class NVMeOF(driver.Target):
protocol = 'nvmeof' protocol = 'nvmeof'
target_protocol_map = { target_protocol_map = {
'nvmet_rdma': 'rdma', 'nvmet_rdma': 'rdma',
'nvmet_tcp': 'tcp',
} }
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):

View File

@ -62,7 +62,7 @@ class NVMET(nvmeof.NVMeOF):
target_port, target_port,
nvmet_port_id, nvmet_port_id,
subsystem_name, subsystem_name,
ns_id, volume_id, volume_path) ns_id, volume_id, volume_path, transport_type)
if newly_added_subsystem is None: if newly_added_subsystem is None:
LOG.error('Failed to add subsystem: %s', subsystem_name) LOG.error('Failed to add subsystem: %s', subsystem_name)
raise NVMETTargetAddError(subsystem=subsystem_name) raise NVMETTargetAddError(subsystem=subsystem_name)
@ -93,7 +93,7 @@ class NVMET(nvmeof.NVMeOF):
def _add_nvmf_subsystem(self, nvmf_subsystems, target_ip, target_port, def _add_nvmf_subsystem(self, nvmf_subsystems, target_ip, target_port,
nvmet_port_id, nvmet_subsystem_name, nvmet_ns_id, nvmet_port_id, nvmet_subsystem_name, nvmet_ns_id,
volume_id, volume_path): volume_id, volume_path, transport_type):
subsystem_name = self._get_target_info(nvmet_subsystem_name, volume_id) subsystem_name = self._get_target_info(nvmet_subsystem_name, volume_id)
# Create JSON sections for the new subsystem to be created # Create JSON sections for the new subsystem to be created
@ -104,7 +104,7 @@ class NVMET(nvmeof.NVMeOF):
"traddr": target_ip, "traddr": target_ip,
"treq": "not specified", "treq": "not specified",
"trsvcid": target_port, "trsvcid": target_port,
"trtype": "rdma" "trtype": transport_type,
}, },
"portid": nvmet_port_id, "portid": nvmet_port_id,
"referrals": [], "referrals": [],

View File

@ -0,0 +1,6 @@
---
features:
- |
LVM driver: Added support for the NVMe TCP transport protocol.
Configuration option is ``target_protocol = nvmet_tcp`` when using
``nvmet`` as the ``target_helper``.