Merge "NetApp ONTAP: Fix iSCSI multiattach volume terminates connection" into stable/ussuri

This commit is contained in:
Zuul 2020-05-01 15:49:26 +00:00 committed by Gerrit Code Review
commit ab60c101f6
4 changed files with 105 additions and 0 deletions

View File

@ -538,6 +538,15 @@ test_snapshot.volume_id = 'fake_volume_id'
test_snapshot.provider_location = PROVIDER_LOCATION
class test_iscsi_attachment(object):
def __getattr__(self, key):
return getattr(self, key)
test_iscsi_attachment = test_iscsi_attachment()
test_iscsi_attachment.connector = ISCSI_CONNECTOR
def get_fake_net_interface_get_iter_response():
return etree.XML("""<results status="passed">
<num-records>1</num-records>

View File

@ -258,6 +258,33 @@ class NetAppBlockStorageLibraryTestCase(test.TestCase):
'fake_volume', fake.FC_FORMATTED_INITIATORS,
protocol, None)
def test__is_multiattached_true(self):
volume = copy.deepcopy(fake.test_volume)
volume.multiattach = True
volume.volume_attachment = [
fake.test_iscsi_attachment,
fake.test_iscsi_attachment,
]
self.assertTrue(self.library._is_multiattached(
volume,
fake.ISCSI_CONNECTOR))
def test__is_multiattached_false(self):
volume1 = copy.deepcopy(fake.test_volume)
volume1.multiattach = True
volume1.volume_attachment = []
volume2 = copy.deepcopy(fake.test_volume)
volume2.multiattach = False
volume2.volume_attachment = []
self.assertFalse(self.library._is_multiattached(
volume1,
fake.ISCSI_CONNECTOR))
self.assertFalse(self.library._is_multiattached(
volume2,
fake.ISCSI_CONNECTOR))
@mock.patch.object(block_base.NetAppBlockStorageLibrary,
'_find_mapped_lun_igroup')
def test_unmap_lun_empty(self, mock_find_mapped_lun_igroup):
@ -300,6 +327,50 @@ class NetAppBlockStorageLibraryTestCase(test.TestCase):
fake.ISCSI_MULTI_MAP_LIST[1]['initiator-group'])]
self.zapi_client.unmap_lun.assert_has_calls(calls)
@mock.patch.object(block_base.NetAppBlockStorageLibrary, '_unmap_lun')
def test_terminate_connection_iscsi_multiattach(self, mock_unmap_lun):
volume = copy.deepcopy(fake.test_volume)
volume.multiattach = True
volume.volume_attachment = [
fake.test_iscsi_attachment,
fake.test_iscsi_attachment,
]
self.library.terminate_connection_iscsi(volume, fake.ISCSI_CONNECTOR)
mock_unmap_lun.assert_not_called()
@mock.patch.object(block_base.NetAppBlockStorageLibrary, '_unmap_lun')
@mock.patch.object(block_base.NetAppBlockStorageLibrary, '_get_lun_attr')
def test_terminate_connection_iscsi_last_attachment(self,
mock_get_lun_attr,
mock_unmap_lun):
mock_get_lun_attr.return_value = {'Path': fake.PATH}
volume = copy.deepcopy(fake.test_volume)
volume.multiattach = True
volume.volume_attachment = [fake.test_iscsi_attachment]
self.library.terminate_connection_iscsi(volume, fake.ISCSI_CONNECTOR)
mock_unmap_lun.assert_called_once_with(
fake.PATH, [fake.ISCSI_CONNECTOR['initiator']])
@mock.patch.object(block_base.NetAppBlockStorageLibrary, '_unmap_lun')
@mock.patch.object(block_base.NetAppBlockStorageLibrary, '_get_lun_attr')
def test_terminate_connection_iscsi_all_initiators(self, mock_get_lun_attr,
mock_unmap_lun):
mock_get_lun_attr.return_value = {'Path': fake.PATH}
volume = copy.deepcopy(fake.test_volume)
volume.multiattach = True
volume.volume_attachment = [
fake.test_iscsi_attachment,
fake.test_iscsi_attachment,
]
self.library.terminate_connection_iscsi(volume, None)
mock_unmap_lun.assert_called_once_with(fake.PATH, [])
def test_find_mapped_lun_igroup(self):
self.assertRaises(NotImplementedError,
self.library._find_mapped_lun_igroup,

View File

@ -888,12 +888,30 @@ class NetAppBlockStorageLibrary(object):
targets = target_details_list
return targets
def _is_multiattached(self, volume, connector):
"""Returns whether the volume is multiattached.
Returns True if the volume is attached to multiple instances using the
same initiator as the given one.
Returns False otherwise.
"""
if not volume.multiattach or not volume.volume_attachment:
return False
same_connector = (True for at in volume.volume_attachment
if at.connector and
at.connector['initiator'] == connector['initiator'])
next(same_connector, False)
return next(same_connector, False)
def terminate_connection_iscsi(self, volume, connector, **kwargs):
"""Driver entry point to unattach a volume from an instance.
Unmask the LUN on the storage system so the given initiator can no
longer access it.
"""
if connector and self._is_multiattached(volume, connector):
return
name = volume['name']
if connector is None:

View File

@ -0,0 +1,7 @@
---
fixes:
- |
NetApp ONTAP: Fixes `bug 1839384
<https://bugs.launchpad.net/cinder/+bug/1839384>`__ Detaching any instance
from multiattached volume terminates connection. Now the connection is
terminated only if there're no other instances using the same initiator.