From 39931083520f8c6bb7e451438806caf9e0894997 Mon Sep 17 00:00:00 2001 From: gksk Date: Thu, 23 Feb 2023 08:40:54 +0000 Subject: [PATCH] [SVf] Adding Support for --delete-volumes flag for delete volume group [Spectrum Virtualize family] As part of Flashcopy 2.0 implementation, added --delete-volumes flag support for deleting VolumeGroup along with volumes. Implements: blueprint ibm-svf-volumegroup Change-Id: I805f8e2d055803090975ec3ac24da90d1948fa57 --- .../volume/drivers/ibm/test_storwize_svc.py | 64 ++++++++++++++++++- .../ibm/storwize_svc/storwize_svc_common.py | 51 ++++++++++++++- ...or-deletevolumegroup-4224db1ca798a3bf.yaml | 6 ++ 3 files changed, 116 insertions(+), 5 deletions(-) create mode 100644 releasenotes/notes/ibm-svf-delete-volume-flag-support-for-deletevolumegroup-4224db1ca798a3bf.yaml diff --git a/cinder/tests/unit/volume/drivers/ibm/test_storwize_svc.py b/cinder/tests/unit/volume/drivers/ibm/test_storwize_svc.py index 79d69cd0ce8..8581253b685 100644 --- a/cinder/tests/unit/volume/drivers/ibm/test_storwize_svc.py +++ b/cinder/tests/unit/volume/drivers/ibm/test_storwize_svc.py @@ -7257,7 +7257,7 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase): self.assertEqual(fields.GroupStatus.AVAILABLE, model_update['status']) # Delete Volume Group - model_update = self.driver.delete_group(self.ctxt, volumegroup, None) + model_update = self.driver.delete_group(self.ctxt, volumegroup, []) self.assertTrue(delete_volumegroup.called) self.assertEqual(fields.GroupStatus.DELETED, model_update[0]['status']) @@ -7374,7 +7374,7 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase): # Delete Volume Group model_update = self.driver.delete_group(self.ctxt, volumegroup, - None) + []) self.assertTrue(delete_volumegroup.called) self.assertEqual(fields.GroupStatus.DELETED, model_update[0]['status']) @@ -7461,6 +7461,66 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase): self.assertEqual(fields.GroupStatus.DELETED, model_update[0]['status']) + @mock.patch.object(storwize_svc_common.StorwizeHelpers, + 'get_system_info') + def test_storwize_delete_volumegroup_with_delete_volumes(self, + get_system_info): + """Test volume group creation and deletion""" + + fake_system_info = {'code_level': (8, 5, 1, 0), + 'system_name': 'storwize-svc-sim', + 'system_id': '0123456789ABCDEF'} + get_system_info.return_value = fake_system_info + self.driver.do_setup(None) + + # Seting the storwize_volume_group to True + self._set_flag('storwize_volume_group', True) + + # Create volumegroup type + volumegroup_spec = {'volume_group_enabled': ' True'} + volumegroup_type_ref = group_types.create(self.ctxt, + 'volumegroup_type', + volumegroup_spec) + volumegroup_type = objects.GroupType.get_by_id( + self.ctxt, volumegroup_type_ref['id']) + + # Create source volume + vol_type_ref = volume_types.create(self.ctxt, 'non_rep_type', {}) + vol_type = objects.VolumeType.get_by_id(self.ctxt, + vol_type_ref['id']) + source_vol = self._generate_vol_info(vol_type) + self.driver.create_volume(source_vol) + + # Create source volumegroup + source_volumegroup = testutils.create_group( + self.ctxt, group_type_id=volumegroup_type.id, + volume_type_ids=[vol_type_ref['id']]) + + model_update = self.driver.create_group(self.ctxt, source_volumegroup) + self.assertEqual(fields.GroupStatus.AVAILABLE, + model_update['status']) + + # Add source volumes to source volumegroup + (model_update, add_volumes_update, remove_volumes_update) = ( + self.driver.update_group(self.ctxt, source_volumegroup, + [source_vol], [])) + + self.assertEqual(fields.GroupStatus.AVAILABLE, + model_update['status']) + source_volumegroup_name = self.driver._get_volumegroup_name( + source_volumegroup) + self.assertEqual(source_volumegroup_name, + source_vol.metadata['Volume Group Name']) + + # Delete Volume Group + model_update = self.driver.delete_group(self.ctxt, + source_volumegroup, + [source_vol]) + self.assertEqual(fields.GroupStatus.DELETED, + model_update[0]['status']) + for volume in model_update[1]: + self.assertEqual('deleted', volume['status']) + @mock.patch.object(storwize_svc_common.StorwizeHelpers, 'get_system_info') @mock.patch.object(cinder.volume.volume_utils, diff --git a/cinder/volume/drivers/ibm/storwize_svc/storwize_svc_common.py b/cinder/volume/drivers/ibm/storwize_svc/storwize_svc_common.py index 4598e504e1f..93874115671 100644 --- a/cinder/volume/drivers/ibm/storwize_svc/storwize_svc_common.py +++ b/cinder/volume/drivers/ibm/storwize_svc/storwize_svc_common.py @@ -2921,6 +2921,18 @@ class StorwizeHelpers(object): return self.ssh.rmsnapshot(params) + def get_volume_name_from_metadata(self, volume): + """Get Volume name from metadata if metadata exists""" + if volume.metadata: + svc_volume_name = volume.metadata.get("Volume Name", None) + if svc_volume_name: + LOG.info('Volume %(cinder_id)s in cinder API is linked to ' + 'volume_name %(svc_volume_name)s in SVC', + {'cinder_id': volume.name, + 'svc_volume_name': svc_volume_name}) + volume.name_id = svc_volume_name.split("-", 1)[1] + return volume + def get_partnership_info(self, system_name): partnership = self.ssh.lspartnership(system_name) return partnership[0] if len(partnership) > 0 else None @@ -6375,7 +6387,8 @@ class StorwizeSVCCommonDriver(san.SanDriver, elif volume_utils.is_group_a_type(group, "volume_group_enabled"): self._helpers.check_codelevel_for_volumegroup( self._state['code_level']) - model_update = self._delete_volumegroup(group) + model_update, volumes_model_update = self._delete_volumegroup( + group, volumes) else: for volume in volumes: @@ -7102,9 +7115,41 @@ class StorwizeSVCCommonDriver(san.SanDriver, {'vol': volume.name, 'exception': err}) return model_update, added_vols, removed_vols - def _delete_volumegroup(self, group): + def _delete_volumegroup(self, group, volumes): model_update = {'status': fields.GroupStatus.DELETED} volumegroup_name = self._get_volumegroup_name(group) + volumes_model_update = [] + force_unmap = True + if self._state['code_level'] < (7, 7, 0, 0): + force_unmap = False + for volume in volumes: + volume = self._helpers.get_volume_name_from_metadata(volume) + if self._active_backend_id: + msg = (_('Error: deleting non-replicated volume in ' + 'failover mode is not allowed.')) + LOG.error(msg) + volume.name_id = None + raise exception.VolumeDriverException(message=msg) + else: + try: + self._helpers.delete_vdisk( + volume.name, + force_unmap=force_unmap, + force_delete=True) + volumes_model_update.append({'id': volume.id, + 'status': 'deleted'}) + except exception.VolumeBackendAPIException as err: + model_update['status'] = ( + fields.GroupStatus.ERROR_DELETING) + LOG.error("Failed to delete the volume %(vol)s of CG. " + "Exception: %(exception)s.", + {'vol': volume.name, 'exception': err}) + volume.name_id = None + volumes_model_update.append( + {'id': volume.id, + 'status': fields.GroupStatus.ERROR_DELETING}) + volume.name_id = None + try: self._helpers.delete_volumegroup(volumegroup_name) except exception.VolumeBackendAPIException as err: @@ -7113,7 +7158,7 @@ class StorwizeSVCCommonDriver(san.SanDriver, {'volumegroup': volumegroup_name, 'exception': err}) model_update = {'status': fields.GroupStatus.ERROR_DELETING} - return model_update + return model_update, volumes_model_update def _update_volumegroup(self, context, group, add_volumes, remove_volumes): diff --git a/releasenotes/notes/ibm-svf-delete-volume-flag-support-for-deletevolumegroup-4224db1ca798a3bf.yaml b/releasenotes/notes/ibm-svf-delete-volume-flag-support-for-deletevolumegroup-4224db1ca798a3bf.yaml new file mode 100644 index 00000000000..ca6eb86f8b3 --- /dev/null +++ b/releasenotes/notes/ibm-svf-delete-volume-flag-support-for-deletevolumegroup-4224db1ca798a3bf.yaml @@ -0,0 +1,6 @@ +--- +features: + - | + IBM Spectrum Virtualize Family driver: Added `--delete-volumes` flag + support for delete volumegroup operation. After adding support, + the volumes can optionally be deleted when the volume group is deleted.