From e733bdb480d59e0ec61dbe7277893022bccf32c4 Mon Sep 17 00:00:00 2001 From: venkatakrishnathumu Date: Fri, 16 Apr 2021 04:15:51 +0000 Subject: [PATCH] [SVF] Manage GMCV volumes on separate pools [Spectrum Virtualize Family] Providing support to IBM Storwize cinder driver to manage GMCV change volumes on a separate child pool while primary and auxiliary volumes remain on the specified storage pool. Implements: blueprint ibm-svf-gmcv-childpool Change-Id: I29432986531678c533bc6b45e8bd1f7a35469ebe --- .../volume/drivers/ibm/test_storwize_svc.py | 408 +++++++++++++++++- .../drivers/ibm/storwize_svc/replication.py | 24 +- .../ibm/storwize_svc/storwize_svc_common.py | 16 +- ...olumes-on-childpools-9d2217e1e6f07a0e.yaml | 5 + 4 files changed, 444 insertions(+), 9 deletions(-) create mode 100644 releasenotes/notes/ibm-svf-manage-gmcv-change-volumes-on-childpools-9d2217e1e6f07a0e.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 1e3dc1d374b..782b4dc797f 100644 --- a/cinder/tests/unit/volume/drivers/ibm/test_storwize_svc.py +++ b/cinder/tests/unit/volume/drivers/ibm/test_storwize_svc.py @@ -54,6 +54,8 @@ from cinder.volume import volume_types from cinder.volume import volume_utils SVC_POOLS = ['openstack', 'openstack1'] +SVC_SOURCE_CHILD_POOL = 'openstack2' +SVC_TARGET_CHILD_POOL = 'openstack3' CONF = cfg.CONF @@ -5004,6 +5006,8 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase): 'mirror_pool': None, 'volume_topology': None, 'peer_pool': None, + 'storwize_svc_src_child_pool': None, + 'storwize_svc_target_child_pool': None, 'cycle_period_seconds': 300 } return opt @@ -10033,6 +10037,10 @@ class StorwizeSVCReplicationTestCase(test.TestCase): return words[1] return None + def _get_pool_volumes(self, pool): + vdisks = self.sim._cmd_lsvdisks_from_filter('mdisk_grp_name', pool) + return vdisks + def test_storwize_do_replication_setup_error(self): fake_targets = [self.rep_target, self.rep_target] self.driver.configuration.set_override('replication_device', @@ -10156,6 +10164,48 @@ class StorwizeSVCReplicationTestCase(test.TestCase): self._create_test_volume, self.gmcv_with_cps86401_type) + @ddt.data((None, None), + (None, SVC_TARGET_CHILD_POOL), (SVC_SOURCE_CHILD_POOL, None), + (SVC_SOURCE_CHILD_POOL, SVC_TARGET_CHILD_POOL)) + @ddt.unpack + def test_storwize_create_gmcv_volume_with_childpool( + self, svc_src_childpool, svc_tgt_childpool): + # Set replication target. + self.driver.configuration.set_override('replication_device', + [self.rep_target]) + self.driver.do_setup(self.ctxt) + + # Create gmcv volume with change volumes on child pools + spec = {'replication_enabled': ' True', + 'replication_type': ' gmcv', + 'drivers:storwize_svc_src_child_pool': svc_src_childpool, + 'drivers:storwize_svc_target_child_pool': svc_tgt_childpool} + gmcv_childpool_type = self._create_replica_volume_type( + False, opts=spec, vol_type_name='test_gmcv_childpool_type') + volume, model_update = self._create_test_volume( + gmcv_childpool_type) + self.assertEqual(fields.ReplicationStatus.ENABLED, + model_update['replication_status']) + self._validate_replic_vol_creation(volume, True) + + src_chg_vol_storage_pool = ( + svc_src_childpool if svc_src_childpool else _get_test_pool()) + tgt_chg_vol_storage_pool = ( + svc_tgt_childpool if svc_tgt_childpool else _get_test_pool()) + src_change_vol_name = (storwize_const.REPLICA_CHG_VOL_PREFIX + + volume.name) + src_childpool_vols = self._get_pool_volumes(src_chg_vol_storage_pool) + self.assertIn(src_change_vol_name, src_childpool_vols) + + tgt_change_vol_name = (storwize_const.REPLICA_CHG_VOL_PREFIX + + storwize_const.REPLICA_AUX_VOL_PREFIX + + volume.name) + tgt_childpool_vols = self._get_pool_volumes(tgt_chg_vol_storage_pool) + self.assertIn(tgt_change_vol_name, tgt_childpool_vols) + + self.driver.delete_volume(volume) + self._validate_replic_vol_deletion(volume, True) + @ddt.data(({"backend_id": "svc_aux_target_1", "san_ip": "192.168.10.22", "san_login": "admin", @@ -10354,10 +10404,12 @@ class StorwizeSVCReplicationTestCase(test.TestCase): self.driver.do_setup(self.ctxt) rep_type = getattr(self, vol_spec['mirror_type']) - # Create metro mirror replication volume. + # Create mirror replication volume. + is_gmcv = True if "gmcv" in vol_spec['mirror_type'] else False vol1, model_update = self._create_test_volume(rep_type) self.assertEqual(fields.ReplicationStatus.ENABLED, model_update['replication_status']) + self._validate_replic_vol_creation(vol1, isGMCV=is_gmcv) snap = testutils.create_snapshot(self.ctxt, vol1.id) self.driver.create_snapshot(snap) @@ -10366,10 +10418,7 @@ class StorwizeSVCReplicationTestCase(test.TestCase): model_update = self.driver.create_volume_from_snapshot(vol2, snap) self.assertEqual(fields.ReplicationStatus.ENABLED, model_update['replication_status']) - if "gmcv" in vol_spec['mirror_type']: - self._validate_replic_vol_creation(vol2, isGMCV=True) - else: - self._validate_replic_vol_creation(vol2) + self._validate_replic_vol_creation(vol2, isGMCV=is_gmcv) if self.USESIM: self.sim.error_injection('lsfcmap', 'speed_up') @@ -10377,6 +10426,61 @@ class StorwizeSVCReplicationTestCase(test.TestCase): self.driver.delete_snapshot(snap) self.driver.delete_volume(vol1) + @ddt.data((None, None), + (None, SVC_TARGET_CHILD_POOL), (SVC_SOURCE_CHILD_POOL, None), + (SVC_SOURCE_CHILD_POOL, SVC_TARGET_CHILD_POOL)) + @ddt.unpack + def test_storwize_create_snapshot_gmcv_volume_with_childpool( + self, svc_src_childpool, svc_tgt_childpool): + # Set replication target + self.driver.configuration.set_override('replication_device', + [self.rep_target]) + self.driver.do_setup(self.ctxt) + + # Create gmcv replication volume with change volumes on child pools + spec = {'replication_enabled': ' True', + 'replication_type': ' gmcv', + 'drivers:storwize_svc_src_child_pool': svc_src_childpool, + 'drivers:storwize_svc_target_child_pool': svc_tgt_childpool} + gmcv_childpool_type = self._create_replica_volume_type( + False, opts=spec, vol_type_name='test_gmcv_childpool_type') + vol1, model_update = self._create_test_volume(gmcv_childpool_type) + self.assertEqual(fields.ReplicationStatus.ENABLED, + model_update['replication_status']) + self._validate_replic_vol_creation(vol1, True) + + snap = testutils.create_snapshot(self.ctxt, vol1.id) + self.driver.create_snapshot(snap) + + vol2 = self._generate_vol_info(gmcv_childpool_type) + model_update = self.driver.create_volume_from_snapshot(vol2, snap) + self.assertEqual(fields.ReplicationStatus.ENABLED, + model_update['replication_status']) + self._validate_replic_vol_creation(vol2, True) + + src_chg_vol_storage_pool = ( + svc_src_childpool if svc_src_childpool else _get_test_pool()) + tgt_chg_vol_storage_pool = ( + svc_tgt_childpool if svc_tgt_childpool else _get_test_pool()) + src_change_vol_name = (storwize_const.REPLICA_CHG_VOL_PREFIX + + vol2.name) + src_childpool_vols = self._get_pool_volumes(src_chg_vol_storage_pool) + self.assertIn(src_change_vol_name, src_childpool_vols) + + tgt_change_vol_name = (storwize_const.REPLICA_CHG_VOL_PREFIX + + storwize_const.REPLICA_AUX_VOL_PREFIX + + vol2.name) + tgt_childpool_vols = self._get_pool_volumes(tgt_chg_vol_storage_pool) + self.assertIn(tgt_change_vol_name, tgt_childpool_vols) + + if self.USESIM: + self.sim.error_injection('lsfcmap', 'speed_up') + self.driver.delete_volume(vol2) + self._validate_replic_vol_deletion(vol2, True) + self.driver.delete_snapshot(snap) + self.driver.delete_volume(vol1) + self._validate_replic_vol_deletion(vol1, True) + def test_storwize_create_cloned_volume_with_mirror_replica(self): # Set replication target self.driver.configuration.set_override('replication_device', @@ -10437,6 +10541,59 @@ class StorwizeSVCReplicationTestCase(test.TestCase): self.driver.delete_volume(src_volume) self.driver.delete_volume(volume) + @ddt.data((None, None), + (None, SVC_TARGET_CHILD_POOL), (SVC_SOURCE_CHILD_POOL, None), + (SVC_SOURCE_CHILD_POOL, SVC_TARGET_CHILD_POOL)) + @ddt.unpack + def test_storwize_create_cloned_volume_from_gmcv_with_childpool( + self, svc_src_childpool, svc_tgt_childpool): + # Set replication target + self.driver.configuration.set_override('replication_device', + [self.rep_target]) + self.driver.do_setup(self.ctxt) + + # Create gmcv volume with change volumes on child pools + spec = {'replication_enabled': ' True', + 'replication_type': ' gmcv', + 'drivers:storwize_svc_src_child_pool': svc_src_childpool, + 'drivers:storwize_svc_target_child_pool': svc_tgt_childpool} + gmcv_childpool_type = self._create_replica_volume_type( + False, opts=spec, vol_type_name='test_gmcv_childpool_type') + src_volume, model_update = self._create_test_volume( + gmcv_childpool_type) + self.assertEqual(fields.ReplicationStatus.ENABLED, + model_update['replication_status']) + self._validate_replic_vol_creation(src_volume, True) + + # Create a cloned volume from source volume. + volume = self._generate_vol_info(gmcv_childpool_type) + model_update = self.driver.create_cloned_volume(volume, src_volume) + self.assertEqual(fields.ReplicationStatus.ENABLED, + model_update['replication_status']) + self._validate_replic_vol_creation(volume, True) + + src_chg_vol_storage_pool = ( + svc_src_childpool if svc_src_childpool else _get_test_pool()) + tgt_chg_vol_storage_pool = ( + svc_tgt_childpool if svc_tgt_childpool else _get_test_pool()) + src_change_vol_name = (storwize_const.REPLICA_CHG_VOL_PREFIX + + volume.name) + src_childpool_vols = self._get_pool_volumes(src_chg_vol_storage_pool) + self.assertIn(src_change_vol_name, src_childpool_vols) + + tgt_change_vol_name = (storwize_const.REPLICA_CHG_VOL_PREFIX + + storwize_const.REPLICA_AUX_VOL_PREFIX + + volume.name) + tgt_childpool_vols = self._get_pool_volumes(tgt_chg_vol_storage_pool) + self.assertIn(tgt_change_vol_name, tgt_childpool_vols) + + if self.USESIM: + self.sim.error_injection('lsfcmap', 'speed_up') + self.driver.delete_volume(src_volume) + self._validate_replic_vol_deletion(src_volume, True) + self.driver.delete_volume(volume) + self._validate_replic_vol_deletion(src_volume, True) + @ddt.data(({'replication_enabled': ' True', 'replication_type': ' global'}, {'replication_enabled': ' True', @@ -10696,6 +10853,60 @@ class StorwizeSVCReplicationTestCase(test.TestCase): self.driver.delete_volume(volume) self._validate_replic_vol_deletion(volume, True) + @ddt.data((None, None), + (None, SVC_TARGET_CHILD_POOL), (SVC_SOURCE_CHILD_POOL, None), + (SVC_SOURCE_CHILD_POOL, SVC_TARGET_CHILD_POOL)) + @ddt.unpack + def test_storwize_retype_from_none_to_gmcv_with_childpool( + self, svc_src_childpool, svc_tgt_childpool): + # Set replication target + self.driver.configuration.set_override('replication_device', + [self.rep_target]) + self.driver.do_setup(self.ctxt) + + # Create non-replica volume + volume, model_update = self._create_test_volume(self.non_replica_type) + self.assertEqual(fields.ReplicationStatus.NOT_CAPABLE, + model_update['replication_status']) + + # Retype to gmcv with childpool + spec = {'replication_enabled': ' True', + 'replication_type': ' gmcv', + 'drivers:storwize_svc_src_child_pool': svc_src_childpool, + 'drivers:storwize_svc_target_child_pool': svc_tgt_childpool} + gmcv_childpool_type = self._create_replica_volume_type( + False, opts=spec, vol_type_name='test_gmcv_childpool_type') + host = {'host': 'openstack@svc#openstack'} + diff, _equal = volume_types.volume_types_diff( + self.ctxt, self.non_replica_type['id'], + gmcv_childpool_type['id']) + retyped, model_update = self.driver.retype( + self.ctxt, volume, gmcv_childpool_type, diff, host) + volume['volume_type_id'] = gmcv_childpool_type['id'] + volume['volume_type'] = gmcv_childpool_type + + self.assertEqual(fields.ReplicationStatus.ENABLED, + model_update['replication_status']) + self._validate_replic_vol_creation(volume, True) + + src_chg_vol_storage_pool = ( + svc_src_childpool if svc_src_childpool else _get_test_pool()) + tgt_chg_vol_storage_pool = ( + svc_tgt_childpool if svc_tgt_childpool else _get_test_pool()) + src_change_vol_name = (storwize_const.REPLICA_CHG_VOL_PREFIX + + volume.name) + src_childpool_vols = self._get_pool_volumes(src_chg_vol_storage_pool) + self.assertIn(src_change_vol_name, src_childpool_vols) + + tgt_change_vol_name = (storwize_const.REPLICA_CHG_VOL_PREFIX + + storwize_const.REPLICA_AUX_VOL_PREFIX + + volume.name) + tgt_childpool_vols = self._get_pool_volumes(tgt_chg_vol_storage_pool) + self.assertIn(tgt_change_vol_name, tgt_childpool_vols) + + self.driver.delete_volume(volume) + self._validate_replic_vol_deletion(volume, True) + def test_storwize_retype_from_gmcv_to_gmcv_replication(self): # Set replication target self.driver.configuration.set_override('replication_device', @@ -12635,9 +12846,194 @@ class StorwizeSVCReplicationTestCase(test.TestCase): if vol_spec['replication_enabled'] == ' True': self.assertEqual(fields.GroupStatus.AVAILABLE, model_update['status']) - elif vol_spec['replication_enabled'] == ' False': + else: self.assertEqual(fields.GroupStatus.ERROR, model_update['status']) + @ddt.data((None, None), + (None, SVC_TARGET_CHILD_POOL), (SVC_SOURCE_CHILD_POOL, None), + (SVC_SOURCE_CHILD_POOL, SVC_TARGET_CHILD_POOL)) + @mock.patch('oslo_service.loopingcall.FixedIntervalLoopingCall', + new=testutils.ZeroIntervalLoopingCall) + @ddt.unpack + def test_create_group_from_src_with_gmcv_volume_with_childpool( + self, svc_src_childpool, svc_tgt_childpool): + # Set replication target + self.driver.configuration.set_override('replication_device', + [self.rep_target]) + self.driver.do_setup(self.ctxt) + + # Create new volume_type template for gmcv + pool = _get_test_pool() + spec = {'replication_enabled': ' True', + 'replication_type': ' gmcv', + 'drivers:storwize_svc_src_child_pool': svc_src_childpool, + 'drivers:storwize_svc_target_child_pool': svc_tgt_childpool} + gmcv_childpool_type = self._create_replica_volume_type( + False, opts=spec, vol_type_name='test_gmcv_childpool_type') + + # Create source group + src_group = testutils.create_group( + self.ctxt, volume_type_ids=[gmcv_childpool_type.id], + group_type_id=self.rccg_type.id) + model_update = self.driver.create_group(self.ctxt, src_group) + self.assertEqual(fields.GroupStatus.AVAILABLE, model_update['status']) + self.assertEqual(fields.ReplicationStatus.ENABLED, + model_update['replication_status']) + + # Create gmcv volume + src_volume = ( + testutils.create_volume(self.ctxt, + volume_type_id=gmcv_childpool_type.id, + group_id=src_group.id, + host='openstack@svc#%s' % pool)) + model_update = self.driver.create_volume(src_volume) + self.assertEqual(fields.ReplicationStatus.ENABLED, + model_update['replication_status']) + self._validate_replic_vol_creation(src_volume, True) + + # Check source gmcv change volumes are created on child storage pools + src_chg_vol_storage_pool = ( + svc_src_childpool if svc_src_childpool else _get_test_pool()) + tgt_chg_vol_storage_pool = ( + svc_tgt_childpool if svc_tgt_childpool else _get_test_pool()) + src_change_vol_name = (storwize_const.REPLICA_CHG_VOL_PREFIX + + src_volume.name) + src_childpool_vols = self._get_pool_volumes(src_chg_vol_storage_pool) + self.assertIn(src_change_vol_name, src_childpool_vols) + + tgt_change_vol_name = (storwize_const.REPLICA_CHG_VOL_PREFIX + + storwize_const.REPLICA_AUX_VOL_PREFIX + + src_volume.name) + tgt_childpool_vols = self._get_pool_volumes(tgt_chg_vol_storage_pool) + self.assertIn(tgt_change_vol_name, tgt_childpool_vols) + + rcrel = self.driver._helpers.get_relationship_info(src_volume.name) + self.sim._rc_state_transition('wait', rcrel) + src_volumes = self.db.volume_get_all_by_generic_group( + self.ctxt.elevated(), src_group.id) + + # Add volume to source group + add_volumes = [src_volume] + delete_volumes = [] + (model_update, add_volumes_update, + remove_volumes_update) = self.driver.update_group(self.ctxt, + src_group, + add_volumes, + delete_volumes) + + self.assertEqual(fields.GroupStatus.AVAILABLE, model_update['status']) + self.assertEqual([{'id': src_volume.id, 'group_id': src_group.id}], + add_volumes_update) + self.assertEqual([], remove_volumes_update) + + # Create clone group from source group + clone_group = ( + testutils.create_group( + self.ctxt, volume_type_ids=[gmcv_childpool_type.id], + group_type_id=self.rccg_type.id)) + clone_volume = ( + testutils.create_volume(self.ctxt, + volume_type_id=gmcv_childpool_type.id, + group_id=clone_group.id, + host='openstack@svc#%s' % pool)) + clone_volumes = self.db.volume_get_all_by_generic_group( + self.ctxt.elevated(), clone_group.id) + + model_update, volumes_model_update = ( + self.driver.create_group_from_src(self.ctxt, clone_group, + clone_volumes, None, None, + src_group, + src_volumes)) + + self.assertEqual(fields.GroupStatus.AVAILABLE, model_update['status']) + for vol_model_update in volumes_model_update: + self.assertEqual(fields.VolumeStatus.AVAILABLE, + vol_model_update['status']) + + src_chg_vol_storage_pool = ( + svc_src_childpool if svc_src_childpool else _get_test_pool()) + tgt_chg_vol_storage_pool = ( + svc_tgt_childpool if svc_tgt_childpool else _get_test_pool()) + src_change_vol_name = (storwize_const.REPLICA_CHG_VOL_PREFIX + + clone_volume.name) + src_childpool_vols = self._get_pool_volumes(src_chg_vol_storage_pool) + self.assertIn(src_change_vol_name, src_childpool_vols) + + tgt_change_vol_name = (storwize_const.REPLICA_CHG_VOL_PREFIX + + storwize_const.REPLICA_AUX_VOL_PREFIX + + clone_volume.name) + tgt_childpool_vols = self._get_pool_volumes(tgt_chg_vol_storage_pool) + self.assertIn(tgt_change_vol_name, tgt_childpool_vols) + + # Create group from source_group_snapshot + group_from_src_group_snapshot = ( + testutils.create_group( + self.ctxt, volume_type_ids=[gmcv_childpool_type.id], + group_type_id=self.rccg_type.id)) + vol_from_snapshot = ( + testutils.create_volume(self.ctxt, + volume_type_id=gmcv_childpool_type.id, + group_id=group_from_src_group_snapshot.id, + host='openstack@svc#%s' % pool)) + group_volumes = self.db.volume_get_all_by_generic_group( + self.ctxt.elevated(), group_from_src_group_snapshot.id) + + group_snapshot, snapshots = self._create_group_snapshot( + src_group.id, group_type_id=self.rccg_type.id) + model_update, volumes_model_update = ( + self.driver.create_group_from_src(self.ctxt, + group_from_src_group_snapshot, + group_volumes, + group_snapshot, + snapshots, None, None)) + + self.assertEqual(fields.GroupStatus.AVAILABLE, model_update['status']) + for vol_model_update in volumes_model_update: + self.assertEqual(fields.VolumeStatus.AVAILABLE, + vol_model_update['status']) + + src_chg_vol_storage_pool = ( + svc_src_childpool if svc_src_childpool else _get_test_pool()) + tgt_chg_vol_storage_pool = ( + svc_tgt_childpool if svc_tgt_childpool else _get_test_pool()) + src_change_vol_name = (storwize_const.REPLICA_CHG_VOL_PREFIX + + vol_from_snapshot.name) + src_childpool_vols = self._get_pool_volumes(src_chg_vol_storage_pool) + self.assertIn(src_change_vol_name, src_childpool_vols) + + tgt_change_vol_name = (storwize_const.REPLICA_CHG_VOL_PREFIX + + storwize_const.REPLICA_AUX_VOL_PREFIX + + vol_from_snapshot.name) + tgt_childpool_vols = self._get_pool_volumes(tgt_chg_vol_storage_pool) + self.assertIn(tgt_change_vol_name, tgt_childpool_vols) + + # Delete groups + model_update = self.driver.delete_group(self.ctxt, + group_from_src_group_snapshot, + group_volumes) + self.assertEqual(fields.GroupStatus.DELETED, model_update[0]['status']) + + with mock.patch( + 'cinder.volume.volume_utils.' + 'is_group_a_cg_snapshot_type') as is_group_a_cg_snapshot_type: + is_group_a_cg_snapshot_type.return_value = True + model_update = self.driver.delete_group_snapshot(self.ctxt, + group_snapshot, + snapshots) + self.assertEqual(fields.GroupSnapshotStatus.DELETED, + model_update[0]['status']) + for snapshot in model_update[1]: + self.assertEqual(fields.SnapshotStatus.DELETED, + snapshot['status']) + + model_update = self.driver.delete_group(self.ctxt, + clone_group, clone_volumes) + self.assertEqual(fields.GroupStatus.DELETED, model_update[0]['status']) + + model_update = self.driver.delete_group(self.ctxt, src_group, + src_volumes) + self.assertEqual(fields.GroupStatus.DELETED, model_update[0]['status']) + @ddt.data(({'volume_type': 'mm'}), ({'volume_type': 'gm'}), ({'volume_type': 'gmcv'}) diff --git a/cinder/volume/drivers/ibm/storwize_svc/replication.py b/cinder/volume/drivers/ibm/storwize_svc/replication.py index 75b3270728e..dcb84b80c97 100644 --- a/cinder/volume/drivers/ibm/storwize_svc/replication.py +++ b/cinder/volume/drivers/ibm/storwize_svc/replication.py @@ -154,7 +154,7 @@ class StorwizeSVCReplicationGMCV(StorwizeSVCReplicationGlobalMirror): super(StorwizeSVCReplicationGMCV, self).__init__( driver, replication_target, target_helpers) - def volume_replication_setup(self, context, vref): + def volume_replication_setup(self, context, vref, new_type=None): LOG.debug('enter: volume_replication_setup: volume %s', vref['name']) source_change_vol_name = (storwize_const.REPLICA_CHG_VOL_PREFIX + vref['name']) @@ -162,6 +162,9 @@ class StorwizeSVCReplicationGMCV(StorwizeSVCReplicationGlobalMirror): target_change_vol_name = (storwize_const.REPLICA_CHG_VOL_PREFIX + target_vol_name) try: + if new_type: + new_type_opts = self.driver._get_vdisk_params( + new_type['id'], volume_type=new_type) src_attr = self.driver._helpers.get_vdisk_attributes( vref['name']) # Create source change volume if it doesn't exist @@ -173,10 +176,19 @@ class StorwizeSVCReplicationGMCV(StorwizeSVCReplicationGlobalMirror): src_change_opts['iogrp'] = src_attr['IO_group_id'] # Change volumes would usually be thin-provisioned src_change_opts['autoexpand'] = True + src_change_pool = src_attr['mdisk_grp_name'] + if new_type: + src_child_pool = ( + new_type_opts['storwize_svc_src_child_pool']) + else: + src_child_pool = ( + src_change_opts['storwize_svc_src_child_pool']) + if src_child_pool: + src_change_pool = src_child_pool self.driver._helpers.create_vdisk(source_change_vol_name, six.text_type(vref['size']), 'gb', - src_attr['mdisk_grp_name'], + src_change_pool, src_change_opts) # Create target volume if it doesn't exist target_attr = self.target_helpers.get_vdisk_attributes( @@ -199,6 +211,14 @@ class StorwizeSVCReplicationGMCV(StorwizeSVCReplicationGlobalMirror): target_change_opts = self.driver._get_vdisk_params( vref['volume_type_id']) target_change_pool = self.target.get('pool_name') + if new_type: + target_child_pool = ( + new_type_opts['storwize_svc_target_child_pool']) + else: + target_child_pool = ( + target_change_opts['storwize_svc_target_child_pool']) + if target_child_pool: + target_change_pool = target_child_pool target_change_opts['iogrp'] = src_attr['IO_group_id'] # Change Volumes would usually be thin-provisioned target_change_opts['autoexpand'] = True 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 f482f1f78eb..8ae1eff42c4 100644 --- a/cinder/volume/drivers/ibm/storwize_svc/storwize_svc_common.py +++ b/cinder/volume/drivers/ibm/storwize_svc/storwize_svc_common.py @@ -127,6 +127,14 @@ storwize_svc_opts = [ default=None, help='Specifies the name of the pool in which mirrored copy ' 'is stored. Example: "pool2"'), + cfg.StrOpt('storwize_svc_src_child_pool', + default=None, + help='Specifies the name of the source child pool in which ' + 'global mirror source change volume is stored.'), + cfg.StrOpt('storwize_svc_target_child_pool', + default=None, + help='Specifies the name of the target child pool in which ' + 'global mirror auxiliary change volume is stored.'), cfg.StrOpt('storwize_peer_pool', default=None, help='Specifies the name of the peer pool for hyperswap ' @@ -1428,6 +1436,10 @@ class StorwizeHelpers(object): 'mirror_pool': config.storwize_svc_mirror_pool, 'volume_topology': None, 'peer_pool': config.storwize_peer_pool, + 'storwize_svc_src_child_pool': + config.storwize_svc_src_child_pool, + 'storwize_svc_target_child_pool': + config.storwize_svc_target_child_pool, 'cycle_period_seconds': config.cycle_period_seconds} return opt @@ -5357,12 +5369,14 @@ class StorwizeSVCCommonDriver(san.SanDriver, # Add replica if needed if not old_rep_type and new_rep_type: replica_obj = self._get_replica_obj(new_rep_type) - replica_obj.volume_replication_setup(ctxt, volume) if storwize_const.GMCV == new_rep_type: + replica_obj.volume_replication_setup(ctxt, volume, new_type) # Set cycle_period_seconds if needed self._helpers.change_relationship_cycleperiod( volume['name'], new_opts.get('cycle_period_seconds')) + else: + replica_obj.volume_replication_setup(ctxt, volume) model_update['replication_status'] = ( fields.ReplicationStatus.ENABLED) # Updating replication properties for a volume with replication diff --git a/releasenotes/notes/ibm-svf-manage-gmcv-change-volumes-on-childpools-9d2217e1e6f07a0e.yaml b/releasenotes/notes/ibm-svf-manage-gmcv-change-volumes-on-childpools-9d2217e1e6f07a0e.yaml new file mode 100644 index 00000000000..73281c8d969 --- /dev/null +++ b/releasenotes/notes/ibm-svf-manage-gmcv-change-volumes-on-childpools-9d2217e1e6f07a0e.yaml @@ -0,0 +1,5 @@ +--- +features: + - | + IBM Spectrum Virtualize Family driver: Added support to manage GMCV volumes + on separate storage pools.