From 1cb6d3e1f16d9bd63186fe1e7fcf706d084fa992 Mon Sep 17 00:00:00 2001 From: Gorka Eguileor Date: Wed, 11 May 2022 12:15:27 +0200 Subject: [PATCH] Support shared_targets tristate value Cinder microversion 3.69 adds an additional value to shared_targets beyond true and false. Now null/None is also a valid value that can be used to force locking. So we now have 3 possible values: - True ==> Lock if iSCSI initiator doesn't support manual scans - False ==> Never lock. - None ==> Always lock. This patch updates the guard_connection context manager to support the 3 possible values. With this Cinder can now force locking for NVMe-oF drivers that share subsystems. Closes-Bug: #1961102 Depends-On: I8cda6d9830f39e27ac700b1d8796fe0489fd7c0a Change-Id: Id872543ce08c934cefbbbdaff6ddc61e3828b1f1 --- os_brick/initiator/utils.py | 13 +++++++++++-- os_brick/tests/initiator/test_utils.py | 12 +++++++++++- .../notes/nvmeof-disconnect-83f9aaf17f8c8988.yaml | 8 ++++++++ 3 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 releasenotes/notes/nvmeof-disconnect-83f9aaf17f8c8988.yaml diff --git a/os_brick/initiator/utils.py b/os_brick/initiator/utils.py index 967c55761..8453c3f96 100644 --- a/os_brick/initiator/utils.py +++ b/os_brick/initiator/utils.py @@ -36,8 +36,17 @@ ISCSI_SUPPORTS_MANUAL_SCAN = check_manual_scan() @contextlib.contextmanager def guard_connection(device): - """Context Manager handling locks for attach/detach operations.""" - if ISCSI_SUPPORTS_MANUAL_SCAN or not device.get('shared_targets'): + """Context Manager handling locks for attach/detach operations. + + In Cinder microversion 3.69 the shared_targets field for volumes are + tristate: + + - True ==> Lock if iSCSI initiator doesn't support manual scans + - False ==> Never lock. + - None ==> Always lock. + """ + shared = device.get('shared_targets', False) + if (shared is not None and ISCSI_SUPPORTS_MANUAL_SCAN) or shared is False: yield else: # Cinder passes an OVO, but Nova passes a dictionary, so we use dict diff --git a/os_brick/tests/initiator/test_utils.py b/os_brick/tests/initiator/test_utils.py index a8fef0f6c..d6d7e471f 100644 --- a/os_brick/tests/initiator/test_utils.py +++ b/os_brick/tests/initiator/test_utils.py @@ -47,6 +47,16 @@ class InitiatorUtilsTestCase(base.TestCase): with utils.guard_connection({'shared_targets': True}): mock_lock.assert_not_called() + @mock.patch('oslo_concurrency.lockutils.lock') + def test_guard_connection_manual_scan_support_forced(self, mock_lock): + """Guard locks when cinder forces locking.""" + utils.ISCSI_SUPPORTS_MANUAL_SCAN = True + # We confirm that shared_targets is ignored + with utils.guard_connection({'service_uuid': mock.sentinel.uuid, + 'shared_targets': None}): + mock_lock.assert_called_once_with(mock.sentinel.uuid, 'os-brick-', + external=True) + @mock.patch('oslo_concurrency.lockutils.lock') def test_guard_connection_manual_scan_unsupported_not_shared(self, mock_lock): @@ -55,7 +65,7 @@ class InitiatorUtilsTestCase(base.TestCase): mock_lock.assert_not_called() @mock.patch('oslo_concurrency.lockutils.lock') - def test_guard_connection_manual_scan_unsupported_hared(self, mock_lock): + def test_guard_connection_manual_scan_unsupported_shared(self, mock_lock): utils.ISCSI_SUPPORTS_MANUAL_SCAN = False with utils.guard_connection({'service_uuid': mock.sentinel.uuid, 'shared_targets': True}): diff --git a/releasenotes/notes/nvmeof-disconnect-83f9aaf17f8c8988.yaml b/releasenotes/notes/nvmeof-disconnect-83f9aaf17f8c8988.yaml new file mode 100644 index 000000000..375f4e2ce --- /dev/null +++ b/releasenotes/notes/nvmeof-disconnect-83f9aaf17f8c8988.yaml @@ -0,0 +1,8 @@ +--- +fixes: + - | + NVMe-oF connector `bug #1961102 + `_: Fixed leaving + controller devices (i.e., /dev/nvme0) behind on hosts. Now NVMe-oF + subsytems are disconnected when disconnecting volumes if the subsytem + doesn't have additional volumes present in the host.