[SVf] : Enable support for mirror-pool option for replication volume-type

[Spectrum Virtualize family] Mirror-pool option is supported from SVC-
Flashsystem, but was blocked in cinder IBM SVC driver code.
As this is supported from the storage, needed to enable this from the IBM SVf driver code making sure volume operations do not break.

Closes-Bug: #2003300
Change-Id: I4f2adace8cca0d4f7ecbba38257f43a300b3a4ca
This commit is contained in:
haailani
2023-01-19 09:39:05 +00:00
parent cd795e4588
commit 2898304b05
4 changed files with 154 additions and 21 deletions

View File

@@ -5747,6 +5747,7 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
'flashcopy_rate': 49,
'clean_rate': 50,
'mirror_pool': None,
'aux_mirror_pool': None,
'volume_topology': None,
'peer_pool': None,
'storwize_portset': None,
@@ -11797,21 +11798,6 @@ class StorwizeSVCReplicationTestCase(test.TestCase):
self.driver._aux_backend_helpers)
self.assertTrue(self.driver._replica_enabled)
@mock.patch.object(storwize_svc_common.StorwizeHelpers,
'create_vdisk')
def test_storwize_svc_create_stretch_volume_with_replication(self,
create_vdisk):
spec = {'mirror_pool': 'openstack1',
'replication_enabled': '<is> True',
'replication_type': '<in> global'
}
vol_type = self._create_replica_volume_type(
False, opts=spec, vol_type_name='test_type')
vol = self._generate_vol_info(vol_type)
self.assertRaises(exception.InvalidInput,
self.driver.create_volume, vol)
self.assertFalse(create_vdisk.called)
def test_storwize_create_volume_with_mirror_replication(self):
# Set replication target.
self.driver.configuration.set_override('replication_device',
@@ -11855,6 +11841,105 @@ class StorwizeSVCReplicationTestCase(test.TestCase):
self._create_test_volume,
self.gmcv_with_cps86401_type)
def test_storwize_create_replication_volume_with_mirror_pool(self):
"""Create a replication volume with mirror_pool option"""
# Set replication target
self.driver.configuration.set_override('replication_device',
[self.rep_target])
self.driver.do_setup(self.ctxt)
# Create MM volume with mirror_pool
spec = {'replication_enabled': '<is> True',
'replication_type': '<in> metro',
'drivers:mirror_pool': 'openstack1'}
mm_mirror_type = self._create_replica_volume_type(
False, opts=spec, vol_type_name='mm_mirror_type')
mm_volume, model_update = self._create_test_volume(
mm_mirror_type)
# Check the parameters and their values
self.assertEqual(fields.ReplicationStatus.ENABLED,
model_update['replication_status'])
self.assertEqual('inconsistent_copying',
model_update['metadata']['Mirroring State'])
# Delete the MM volume
self.driver.delete_volume(mm_volume)
# Create GM volume with mirror_pool
spec = {'replication_enabled': '<is> True',
'replication_type': '<in> global',
'drivers:mirror_pool': 'openstack1'}
gm_mirror_type = self._create_replica_volume_type(
False, opts=spec, vol_type_name='gm_mirror_type')
gm_volume, model_update = self._create_test_volume(
gm_mirror_type)
# Check the parameters and their values
self.assertEqual(fields.ReplicationStatus.ENABLED,
model_update['replication_status'])
self.assertEqual('inconsistent_copying',
model_update['metadata']['Mirroring State'])
# Delete the GM volume
self.driver.delete_volume(gm_volume)
def test_storwize_retype_mm_replication_volume_with_mirror_pool(self):
"""Create a MM replication volume with mirror_pool option and retype
it to MM replication volume type without mirror pool option
"""
# Set replication target
self.driver.configuration.set_override('replication_device',
[self.rep_target])
self.driver.do_setup(self.ctxt)
host = {'host': 'openstack@svc#openstack'}
# Create MM volume
mm_volume, model_update = self._create_test_volume(self.mm_type)
self.assertEqual(fields.ReplicationStatus.ENABLED,
model_update['replication_status'])
# Create MM volume-type with mirror_pool option
spec = {'replication_enabled': '<is> True',
'replication_type': '<in> metro',
'drivers:mirror_pool': 'openstack1'}
mm_mirror_type = self._create_replica_volume_type(
False, opts=spec, vol_type_name='mm_mirror_type')
# Retype the MM-volume to volume-type with mirror_pool option
diff, _equal = volume_types.volume_types_diff(
self.ctxt, mm_mirror_type['id'], self.mm_type['id'])
retyped, model_update = self.driver.retype(
self.ctxt, mm_volume, mm_mirror_type, diff, host)
self.driver.delete_volume(mm_volume)
def test_storwize_retype_gm_replication_volume_with_mirror_pool(self):
"""Create a GM replication volume with mirror_pool option and retype
it to GM replication volume type without mirror pool option
"""
# Set replication target
self.driver.configuration.set_override('replication_device',
[self.rep_target])
self.driver.do_setup(self.ctxt)
host = {'host': 'openstack@svc#openstack'}
# Create GM volume
gm_volume, model_update = self._create_test_volume(self.gm_type)
self.assertEqual(fields.ReplicationStatus.ENABLED,
model_update['replication_status'])
# Create GM volume-type with mirror_pool option
spec = {'replication_enabled': '<is> True',
'replication_type': '<in> global',
'drivers:mirror_pool': 'openstack1'}
gm_mirror_type = self._create_replica_volume_type(
False, opts=spec, vol_type_name='gm_mirror_type')
# Retype the GM-volume to volume-type with mirror_pool option
diff, _equal = volume_types.volume_types_diff(
self.ctxt, gm_mirror_type['id'], self.gm_type['id'])
retyped, model_update = self.driver.retype(
self.ctxt, gm_volume, gm_mirror_type, diff, host)
self.driver.delete_volume(gm_volume)
@ddt.data((None, None),
(None, SVC_TARGET_CHILD_POOL), (SVC_SOURCE_CHILD_POOL, None),
(SVC_SOURCE_CHILD_POOL, SVC_TARGET_CHILD_POOL))

View File

@@ -102,6 +102,7 @@ class StorwizeSVCReplicationGlobalMirror(StorwizeSVCReplication):
src_attr = self.driver._helpers.get_vdisk_attributes(
vref['name'])
opts['iogrp'] = src_attr['IO_group_id']
opts['mirror_pool'] = None
try:
self.target_helpers.create_vdisk(target_vol_name,
str(vref['size']),

View File

@@ -132,6 +132,10 @@ storwize_svc_opts = [
default=None,
help='Specifies the name of the pool in which mirrored copy '
'is stored. Example: "pool2"'),
cfg.StrOpt('storwize_svc_aux_mirror_pool',
default=None,
help='Specifies the name of the pool in which mirrored copy '
'is stored for aux volume. Example: "pool2"'),
cfg.StrOpt('storwize_portset',
default=None,
help='Specifies the name of the portset in which '
@@ -1671,6 +1675,7 @@ class StorwizeHelpers(object):
'flashcopy_rate': config.storwize_svc_flashcopy_rate,
'clean_rate': config.storwize_svc_clean_rate,
'mirror_pool': config.storwize_svc_mirror_pool,
'aux_mirror_pool': config.storwize_svc_aux_mirror_pool,
'volume_topology': None,
'peer_pool': config.storwize_peer_pool,
'storwize_portset': config.storwize_portset,
@@ -2013,7 +2018,7 @@ class StorwizeHelpers(object):
else:
params.extend(['-grainsize', str(opts['grainsize'])])
if add_copies and opts['mirror_pool']:
if add_copies and (opts['mirror_pool'] or opts['aux_mirror_pool']):
params.extend(['-copies', '2'])
if not is_dr_pool:
@@ -2032,6 +2037,15 @@ class StorwizeHelpers(object):
# mdiskgrp for mirror volume
mdiskgrp = '%s:%s' % (pool, opts['mirror_pool'])
if opts['aux_mirror_pool']:
if not self.is_pool_defined(opts['aux_mirror_pool']):
raise exception.InvalidInput(
reason=_('The pool %s in which aux mirrored copy is '
'stored is invalid') % opts['aux_mirror_pool'])
# The syntax of pool SVC expects is pool:aux_mirror_pool in
# mdiskgrp for aux mirror volume
mdiskgrp = '%s:%s' % (pool, opts['aux_mirror_pool'])
is_dr_pool = False
if opts['rsize'] != -1:
is_dr_pool = self.is_volume_type_dr_pools(pool, opts)
@@ -2039,7 +2053,8 @@ class StorwizeHelpers(object):
self.check_data_reduction_pool_params(opts)
params = self._get_vdisk_create_params(
opts, is_dr_pool,
add_copies=True if opts['mirror_pool'] else False)
add_copies=True if (opts['mirror_pool'] or opts['aux_mirror_pool'])
else False)
self.ssh.mkvdisk(name, size, units, mdiskgrp, opts, params)
LOG.debug('Leave: _create_vdisk: volume %s.', name)
@@ -3932,12 +3947,9 @@ class StorwizeSVCCommonDriver(san.SanDriver,
model_update = self._update_replication_properties(ctxt, volume,
model_update)
else:
if opts['mirror_pool'] and rep_type:
reason = _('Create mirror volume with replication enabled is '
'not supported.')
raise exception.InvalidInput(reason=reason)
opts['iogrp'] = self._helpers.select_io_group(self._state,
opts, pool)
opts['aux_mirror_pool'] = None
self._helpers.create_vdisk(volume['name'], str(volume['size']),
'gb', pool, opts)
if opts['qos']:
@@ -5709,6 +5721,7 @@ class StorwizeSVCCommonDriver(san.SanDriver,
vdisk_changes,
new_opts, self._state)
# flake8: noqa: C901
def retype(self, ctxt, volume, new_type, diff, host):
"""Convert the volume to be of the new type.
@@ -5745,6 +5758,7 @@ class StorwizeSVCCommonDriver(san.SanDriver,
vdisk_changes = []
need_copy = False
change_mirror = False
aux_change_mirror = False
for key in all_keys:
if old_opts[key] != new_opts[key]:
@@ -5762,6 +5776,9 @@ class StorwizeSVCCommonDriver(san.SanDriver,
if old_opts['mirror_pool'] != new_opts['mirror_pool']:
change_mirror = True
if old_opts['aux_mirror_pool'] != new_opts['aux_mirror_pool']:
aux_change_mirror = True
# Check if retype affects volume replication
model_update = dict()
new_rep_type = self._get_specs_replicated_type(new_type)
@@ -5881,6 +5898,8 @@ class StorwizeSVCCommonDriver(san.SanDriver,
self._helpers.delete_vdisk(
storwize_const.REPLICA_CHG_VOL_PREFIX + volume['name'],
force_unmap=force_unmap, force_delete=False)
if aux_change_mirror:
aux_change_mirror = False
model_update['replication_status'] = (
fields.ReplicationStatus.DISABLED)
model_update['replication_driver_data'] = None
@@ -5907,6 +5926,27 @@ class StorwizeSVCCommonDriver(san.SanDriver,
model_update = self._update_replication_properties(ctxt, volume,
model_update)
if aux_change_mirror:
target_volume, rel_info = (
self._helpers.get_target_volume_information(volume))
aux_copies = self._aux_backend_helpers.get_vdisk_copies(
target_volume)
if (old_rep_type and new_rep_type) or (not old_rep_type
and new_rep_type):
# retype from non-mirror-rep to mirror-rep
if (not old_opts['aux_mirror_pool'] and
new_opts['aux_mirror_pool']):
self._aux_backend_helpers.add_vdisk_copy(
target_volume, new_opts['aux_mirror_pool'],
new_type, self._aux_state, self.configuration)
# retype from mirror-rep to non-mirror-rep
elif (old_opts['aux_mirror_pool'] and not
new_opts['aux_mirror_pool']):
aux_secondary = aux_copies['secondary']
if aux_secondary:
self._aux_backend_helpers.rm_vdisk_copy(
target_volume, aux_secondary['copy_id'])
LOG.debug('exit: retype: ild=%(id)s, new_type=%(new_type)s,'
'diff=%(diff)s, host=%(host)s', {'id': volume['id'],
'new_type': new_type,

View File

@@ -0,0 +1,7 @@
---
fixes:
- |
IBM Spectrum Virtualize Family driver: `Bug #2003300
<https://bugs.launchpad.net/cinder/+bug/2003300>`_:
Enable support for mirror-pool option for metro-mirror
replication and global-mirror replication volume-types.