From 90233982d249486aebaa996db744e3820aee1ddb Mon Sep 17 00:00:00 2001 From: Miriam Yumi Date: Wed, 22 Aug 2018 13:23:05 -0300 Subject: [PATCH] NetApp SolidFire: Fix force_detach Fixes force_detach for SolidFire driver. Change-Id: Iaf8a3f0bed5af053d5ea7796d84d5d77f1608458 Closes-Bug: #1788458 (cherry picked from commit a5edf0b62215fa3335f60115303cae9210408385) --- .../drivers/solidfire/test_solidfire.py | 41 ++++++++++++++++++- cinder/volume/drivers/solidfire.py | 41 ++++++++++++------- ...-netapp-force_detach-36bdf75dd2c9a030.yaml | 3 ++ 3 files changed, 69 insertions(+), 16 deletions(-) create mode 100644 releasenotes/notes/fix-netapp-force_detach-36bdf75dd2c9a030.yaml diff --git a/cinder/tests/unit/volume/drivers/solidfire/test_solidfire.py b/cinder/tests/unit/volume/drivers/solidfire/test_solidfire.py index 2d7c4d1b014..356994c2575 100644 --- a/cinder/tests/unit/volume/drivers/solidfire/test_solidfire.py +++ b/cinder/tests/unit/volume/drivers/solidfire/test_solidfire.py @@ -1290,6 +1290,45 @@ class SolidFireVolumeTestCase(test.TestCase): sfv._sf_terminate_connection(testvol, connector, False) rem_vag.assert_called_with(vol_id, vag_id) + def test_sf_term_conn_without_connector(self): + # Verify we correctly force the deletion of a volume. + mod_conf = self.configuration + mod_conf.sf_enable_vag = True + sfv = solidfire.SolidFireDriver(configuration=mod_conf) + testvol = {'project_id': 'testprjid', + 'name': 'testvol', + 'size': 1, + 'id': 'a720b3c0-d1f0-11e1-9b23-0800200c9a66', + 'volume_type_id': None, + 'provider_location': '10.10.7.1:3260 iqn.2010-01.com.' + 'solidfire:87hg.uuid-2cc06226-cc' + '74-4cb7-bd55-14aed659a0cc.4060 0', + 'provider_auth': 'CHAP stack-1-a60e2611875f40199931f2' + 'c76370d66b 2FE0CQ8J196R', + 'provider_geometry': '4096 4096', + 'created_at': timeutils.utcnow(), + 'provider_id': "1 1 1", + 'multiattach': False + } + provider_id = testvol['provider_id'] + vol_id = int(provider_id.split()[0]) + vag_id = 1 + vags = [{'attributes': {}, + 'deletedVolumes': [], + 'initiators': ['iqn.2012-07.org.fake:01'], + 'name': 'fakeiqn', + 'volumeAccessGroupID': vag_id, + 'volumes': [1, 2], + 'virtualNetworkIDs': []}] + + with mock.patch.object(sfv, + '_get_vags_by_volume', + return_value=vags), \ + mock.patch.object(sfv, + '_remove_volume_from_vags') as rem_vags: + sfv._sf_terminate_connection(testvol, None, False) + rem_vags.assert_called_with(vol_id) + def test_safe_create_vag_simple(self): # Test the sunny day call straight into _create_vag. sfv = solidfire.SolidFireDriver(configuration=self.configuration) @@ -1531,7 +1570,7 @@ class SolidFireVolumeTestCase(test.TestCase): 'volumes': [vol_id, 43]}] with mock.patch.object(sfv, - '_base_get_vags', + '_get_vags_by_volume', return_value=vags), \ mock.patch.object(sfv, '_remove_volume_from_vag') as rem_vol: diff --git a/cinder/volume/drivers/solidfire.py b/cinder/volume/drivers/solidfire.py index 57cba0d23b6..354861f0422 100644 --- a/cinder/volume/drivers/solidfire.py +++ b/cinder/volume/drivers/solidfire.py @@ -1104,6 +1104,13 @@ class SolidFireDriver(san.SanISCSIDriver): matching_vags = [vag for vag in vags if vag['name'] == vag_name] return matching_vags + def _get_vags_by_volume(self, vol_id): + params = {"volumeID": vol_id} + vags = self._issue_api_request( + 'GetVolumeStats', + params)['result']['volumeStats']['volumeAccessGroups'] + return vags + def _add_initiator_to_vag(self, iqn, vag_id): # Added a vag_id return as there is a chance that we might have to # create a new VAG if our target VAG is deleted underneath us. @@ -1161,9 +1168,8 @@ class SolidFireDriver(san.SanISCSIDriver): def _remove_volume_from_vags(self, vol_id): # Due to all sorts of uncertainty around multiattach, on volume # deletion we make a best attempt at removing the vol_id from VAGs. - vags = self._base_get_vags() - targets = [v for v in vags if vol_id in v['volumes']] - for vag in targets: + vags = self._get_vags_by_volume(vol_id) + for vag in vags: self._remove_volume_from_vag(vol_id, vag['volumeAccessGroupID']) def _remove_vag(self, vag_id): @@ -2190,21 +2196,26 @@ class SolidFireISCSI(iscsi_driver.SanISCSITarget): If the VAG is empty then the VAG is also removed. """ if self.configuration.sf_enable_vag: - iqn = properties['initiator'] - vag = self._get_vags_by_name(iqn) provider_id = volume['provider_id'] vol_id = int(provider_id.split()[0]) - if vag and not volume['multiattach']: - # Multiattach causes problems with removing volumes from VAGs. - # Compromise solution for now is to remove multiattach volumes - # from VAGs during volume deletion. - vag = vag[0] - vag_id = vag['volumeAccessGroupID'] - if [vol_id] == vag['volumes']: - self._remove_vag(vag_id) - elif vol_id in vag['volumes']: - self._remove_volume_from_vag(vol_id, vag_id) + if properties: + iqn = properties['initiator'] + vag = self._get_vags_by_name(iqn) + + if vag and not volume['multiattach']: + # Multiattach causes problems with removing volumes from + # VAGs. + # Compromise solution for now is to remove multiattach + # volumes from VAGs during volume deletion. + vag = vag[0] + vag_id = vag['volumeAccessGroupID'] + if [vol_id] == vag['volumes']: + self._remove_vag(vag_id) + elif vol_id in vag['volumes']: + self._remove_volume_from_vag(vol_id, vag_id) + else: + self._remove_volume_from_vags(vol_id) return super(SolidFireISCSI, self).terminate_connection(volume, properties, diff --git a/releasenotes/notes/fix-netapp-force_detach-36bdf75dd2c9a030.yaml b/releasenotes/notes/fix-netapp-force_detach-36bdf75dd2c9a030.yaml new file mode 100644 index 00000000000..4ea36bf12a1 --- /dev/null +++ b/releasenotes/notes/fix-netapp-force_detach-36bdf75dd2c9a030.yaml @@ -0,0 +1,3 @@ +--- +fixes: + - Fixes force_detach behavior for volumes in NetApp SolidFire driver.