commit 528af66ff2df65f972d02d2b0ef157cf1c054fc0 Author: sharathkacham Date: Fri Aug 7 06:24:58 2020 +0000 [SVF]:changes in create_group_from_src for replicated groups IBM Spectrum Virtualize Family: Code changes to make create_group_from_src work for replication_enabled or snapshot_enabled consistency groups. Change-Id: Ic71f5d934ee8169536d0aeda1e93269f18448339 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 31e9c3d..133ca9d 100644 --- a/cinder/tests/unit/volume/drivers/ibm/test_storwize_svc.py +++ b/cinder/tests/unit/volume/drivers/ibm/test_storwize_svc.py @@ -4556,7 +4556,6 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase): self.driver.set_fake_storage(self.sim) self.ctxt = context.get_admin_context() - else: self._reset_flags() self.ctxt = context.get_admin_context() @@ -4723,7 +4722,7 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase): mock_ssh_pool.side_effect = [ paramiko.SSHException, mock.MagicMock( - ip = self._driver.configuration.storwize_san_secondary_ip), + ip=self._driver.configuration.storwize_san_secondary_ip), mock.MagicMock()] mock_ssh_execute.side_effect = [processutils.ProcessExecutionError, mock.MagicMock()] @@ -6129,16 +6128,11 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase): # Test groups operation #### @ddt.data(({'group_replication_enabled': ' True'}, {}), ({'group_replication_enabled': ' True', - 'consistent_group_snapshot_enabled': ' True'}, {}), + 'consistent_group_snapshot_enabled': ' True'}, {}), ({'group_snapshot_enabled': ' True'}, {}), ({'consistent_group_snapshot_enabled': ' True'}, {'replication_enabled': ' True', - 'replication_type': ' metro'}), - ({'consistent_group_replication_enabled': ' True'}, - {'replication_enabled': ' Fasle'}), - ({'consistent_group_replication_enabled': ' True'}, - {'replication_enabled': ' True', - 'replication_type': ' gmcv'})) + 'replication_type': ' metro'})) @ddt.unpack def test_storwize_group_create_with_replication(self, grp_sepc, vol_spec): """Test group create.""" @@ -6148,7 +6142,6 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase): group = testutils.create_group(self.ctxt, group_type_id=gr_type.id, volume_type_ids=[vol_type_ref['id']]) - if 'group_snapshot_enabled' in grp_sepc: self.assertRaises(NotImplementedError, self.driver.create_group, self.ctxt, group) @@ -6318,7 +6311,7 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase): group_type_id=rccg_type_ref.id) vol1 = testutils.create_volume(self.ctxt, volume_type_id=type_ref.id, group_id=group.id) - self.assertRaises(exception.VolumeBackendAPIException, + self.assertRaises(exception.InvalidInput, self.driver.create_group_from_src, self.ctxt, group, [vol1]) @@ -6331,8 +6324,7 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase): group_id=group.id) self.assertRaises(exception.VolumeBackendAPIException, self.driver.create_group_from_src, - self.ctxt, group, vol1, None, None, - None, None) + self.ctxt, group, [vol1]) group = self._create_group_in_db(volume_type_id=type_ref.id, group_type_id=cg_type_ref.id) @@ -7124,26 +7116,25 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase): group2 = self._create_group_in_db(volume_type_ids=[type_ref.id], group_type_id=cg_type_ref.id) - # Create volume with replication group id will be failed + # Create volume with replication group id will be success vol1 = testutils.create_volume(self.ctxt, volume_type_id=type_ref.id, + host='openstack@svc#openstack', group_id=group1.id) - self.assertRaises(exception.VolumeDriverException, - self.driver.create_volume, - vol1) + self.driver.create_volume(vol1) # Create volume with cg_snapshot group id will success. vol2 = testutils.create_volume(self.ctxt, volume_type_id=type_ref.id, host='openstack@svc#openstack', group_id=group2.id) self.driver.create_volume(vol2) - # Create cloned volume with replication group id will be failed + # Create cloned volume with replication group id will be success vol3 = testutils.create_volume(self.ctxt, volume_type_id=type_ref.id, + host='openstack@svc#openstack', group_id=group1.id, source_volid=vol2.id) - self.assertRaises(exception.VolumeDriverException, - self.driver.create_cloned_volume, - vol3, vol2) - # Create cloned volume with cg_snapshot group id will success. + + self.driver.create_cloned_volume(vol3, vol2) + # Create cloned volume with cg_snapshot group id will be success. vol4 = testutils.create_volume(self.ctxt, volume_type_id=type_ref.id, group_id=group2.id, host='openstack@svc#openstack', @@ -7152,13 +7143,12 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase): snapshot = self._generate_snap_info(vol2.id) self.driver.create_snapshot(snapshot) - # Create volume from snapshot with replication group id will be failed + # Create volume from snapshot with replication group id will be success vol5 = testutils.create_volume(self.ctxt, volume_type_id=type_ref.id, + host='openstack@svc#openstack', group_id=group1.id, snapshot_id=snapshot.id) - self.assertRaises(exception.VolumeDriverException, - self.driver.create_volume_from_snapshot, - vol5, snapshot) + self.driver.create_volume_from_snapshot(vol5, snapshot) # Create volume from snapshot with cg_snapshot group id will success. vol6 = testutils.create_volume(self.ctxt, volume_type_id=type_ref.id, group_id=group2.id, @@ -7356,8 +7346,8 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase): self._assert_vol_exists(vol.name, True) vol2 = testutils.create_volume(self.ctxt, - host = 'openstack@svc#hyperswap1', - volume_type_id = vol.volume_type_id) + host='openstack@svc#hyperswap1', + volume_type_id=vol.volume_type_id) with mock.patch.object(storwize_svc_common.StorwizeHelpers, 'get_vdisk_attributes') as vdisk_attr: vdisk_attr.return_value = None @@ -11034,3 +11024,23 @@ class StorwizeSVCReplicationTestCase(test.TestCase): storwize_const.REPLICA_AUX_VOL_PREFIX + mm_vol.name) self.assertEqual(self.driver._aux_backend_helpers, backend_helper) self.assertEqual(self.driver._aux_state, node_state) + + @ddt.data(({'consistent_group_replication_enabled': ' True'}, + {'replication_enabled': ' False'}), + ({'consistent_group_replication_enabled': ' True'}, + {'replication_enabled': ' True', + 'replication_type': ' gmcv'})) + @ddt.unpack + def test_storwize_group_create_with_replication(self, grp_spec, vol_spec): + self.driver.configuration.set_override('replication_device', + [self.rep_target]) + self.driver.do_setup(self.ctxt) + """Test group create.""" + gr_type_ref = group_types.create(self.ctxt, 'gr_type', grp_spec) + gr_type = objects.GroupType.get_by_id(self.ctxt, gr_type_ref['id']) + vol_type_ref = volume_types.create(self.ctxt, 'vol_type', vol_spec) + group = testutils.create_group(self.ctxt, + group_type_id=gr_type.id, + volume_type_ids=[vol_type_ref['id']]) + model_update = self.driver.create_group(self.ctxt, group) + self.assertEqual(fields.GroupStatus.ERROR, model_update['status']) 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 26c3e9e..f38cf91 100644 --- a/cinder/volume/drivers/ibm/storwize_svc/storwize_svc_common.py +++ b/cinder/volume/drivers/ibm/storwize_svc/storwize_svc_common.py @@ -3045,7 +3045,9 @@ class StorwizeSVCCommonDriver(san.SanDriver, def _check_if_group_type_cg_snapshot(self, volume): if (volume.group_id and - not volume_utils.is_group_a_cg_snapshot_type(volume.group)): + (not volume_utils.is_group_a_cg_snapshot_type(volume.group) and + not volume_utils.is_group_a_type + (volume.group, "consistent_group_replication_enabled"))): msg = _('Create volume with a replication or hyperswap ' 'group_id is not supported. Please add volume to ' 'group after volume creation.') @@ -5249,6 +5251,7 @@ class StorwizeSVCCommonDriver(san.SanDriver, if volume_utils.is_group_a_type( group, "consistent_group_replication_enabled"): + self._validate_replication_enabled() rccg_type = None for vol_type_id in group.volume_type_ids: replication_type = self._get_volume_replicated_type( @@ -5424,15 +5427,6 @@ class StorwizeSVCCommonDriver(san.SanDriver, """ LOG.debug('Enter: create_group_from_src.') - if volume_utils.is_group_a_type( - group, - "consistent_group_replication_enabled"): - # An unsupported configuration - msg = _('Unable to create replication group: create replication ' - 'group from a replication group is not supported.') - LOG.exception(msg) - raise exception.VolumeBackendAPIException(data=msg) - if volume_utils.is_group_a_type(group, "hyperswap_group_enabled"): # An unsupported configuration msg = _('Unable to create hyperswap group: create hyperswap ' @@ -5440,7 +5434,9 @@ class StorwizeSVCCommonDriver(san.SanDriver, LOG.exception(msg) raise exception.VolumeBackendAPIException(data=msg) - if not volume_utils.is_group_a_cg_snapshot_type(group): + if (not volume_utils.is_group_a_cg_snapshot_type(group) and + not volume_utils.is_group_a_type + (group, "consistent_group_replication_enabled")): # we'll rely on the generic volume groups implementation if it is # not a consistency group request. raise NotImplementedError() @@ -5461,7 +5457,7 @@ class StorwizeSVCCommonDriver(san.SanDriver, ' %(sources)s', {'cg_name': cg_name, 'sources': sources}) self._helpers.create_fc_consistgrp(cg_name) timeout = self.configuration.storwize_svc_flashcopy_timeout - model_update, snapshots_model = ( + model_update, volumes_model = ( self._helpers.create_cg_from_source(group, cg_name, sources, @@ -5469,8 +5465,18 @@ class StorwizeSVCCommonDriver(san.SanDriver, self._state, self.configuration, timeout)) + + for vol in volumes: + rep_type = self._get_volume_replicated_type(context, + vol) + if rep_type: + replica_obj = self._get_replica_obj(rep_type) + replica_obj.volume_replication_setup(context, vol) + volumes_model[volumes.index(vol)]['replication_status'] = ( + fields.ReplicationStatus.ENABLED) + LOG.debug("Leave: create_group_from_src.") - return model_update, snapshots_model + return model_update, volumes_model def create_group_snapshot(self, context, group_snapshot, snapshots): """Creates a group_snapshot. @@ -5480,11 +5486,12 @@ class StorwizeSVCCommonDriver(san.SanDriver, :param snapshots: a list of Snapshot objects in the group_snapshot. :returns: model_update, snapshots_model_update """ - if not volume_utils.is_group_a_cg_snapshot_type(group_snapshot): + if (not volume_utils.is_group_a_cg_snapshot_type(group_snapshot) and + not volume_utils.is_group_a_type + (group_snapshot, "consistent_group_replication_enabled")): # we'll rely on the generic group implementation if it is not a # consistency group request. raise NotImplementedError() - # Use group_snapshot id as cg name cg_name = 'cg_snap-' + group_snapshot.id # Create new cg as cg_snapshot @@ -5730,8 +5737,16 @@ class StorwizeSVCCommonDriver(san.SanDriver, LOG.info("Update replication group: %(group)s. ", {'group': group.id}) rccg_name = self._get_rccg_name(group) - rccg = self._helpers.get_rccg(rccg_name) - if not rccg: + # This code block fails during remove of volumes from group + try: + rccg = self._helpers.get_rccg(rccg_name) + except Exception as ex: + if len(add_volumes) > 0: + LOG.exception("Unable to retrieve " + "replication group information. Failed " + "with exception %(ex)s", ex) + + if not rccg and len(add_volumes) > 0: LOG.error("Failed to update group: %(grp)s does not exist in " "backend.", {'grp': group.id}) model_update['status'] = fields.GroupStatus.ERROR diff --git a/releasenotes/notes/Code-changes-to-handle-groups-with-replication_enabled-or-snapshot_enabled-72f669fe2719ce3d.yaml b/releasenotes/notes/Code-changes-to-handle-groups-with-replication_enabled-or-snapshot_enabled-72f669fe2719ce3d.yaml new file mode 100644 index 0000000..3e4e2fa --- /dev/null +++ b/releasenotes/notes/Code-changes-to-handle-groups-with-replication_enabled-or-snapshot_enabled-72f669fe2719ce3d.yaml @@ -0,0 +1,6 @@ +--- +features: + - | + IBM Spectrum Virtualize: Added support to enable creating a group from + source, when source is a replicated group or consistency group snapshot + of a replicated group.