[SVF] Support volume-resize to hyperswap volume

[Spectrum Virtualize Family] Added support to extend a volume
which is created using hyperswap volume-type template

Implements: blueprint ibm-svf-hyperswap-volume-resize-support
Change-Id: I19bc034343bc106acb6a217bc5e53c7f60c58ef2
This commit is contained in:
venkatakrishnathumu 2021-02-09 06:56:04 +00:00
parent f602a1d00d
commit e832ddb061
3 changed files with 206 additions and 60 deletions

View File

@ -96,7 +96,8 @@ class StorwizeSVCManagementSimulator(object):
'lslicense': '',
'lsguicapabilities': '',
'lshost': '',
'lsrcrelationship': ''
'lsrcrelationship': '',
'expandvdisksize': ''
}
self._errors = {
'CMMVC5701E': ('', 'CMMVC5701E No object ID was specified.'),
@ -167,6 +168,14 @@ class StorwizeSVCManagementSimulator(object):
'is not in a group.'),
'CMMVC9012E': ('', 'CMMVC9012E The copy type differs from other '
'copies already in the consistency group.'),
'CMMVC9201E': ('', 'CMMVC9201E Task failed because volume has a '
'copy that is fully allocated and is part of a '
'Metro Mirror or Global Mirror relationship.'),
'CMMVC8587E': ('', 'CMMVC8587E The command failed because the '
'volume is fast formatting.'),
'CMMVC8783E': ('', 'CMMVC8783E The volume copy was not deleted '
'because the volume is part of a consistency '
'group.'),
}
self._fc_transitions = {'begin': {'make': 'idle_or_copied'},
'idle_or_copied': {'prepare': 'preparing',
@ -1037,6 +1046,14 @@ port_speed!N/A
if vol_name not in self._volumes_list:
return self._errors['CMMVC5753E']
vol = self._volumes_list[kwargs['obj']]
if self._next_cmd_error['expandvdisksize'] == 'fast_formatting':
if vol['RC_name']:
rcrel = self._rcrelationship_list[vol['RC_name']]
if rcrel.get('copy_type', None):
return self._errors['CMMVC9201E']
return self._errors['CMMVC8587E']
curr_size = int(self._volumes_list[vol_name]['capacity'])
addition = size * units.Gi
self._volumes_list[vol_name]['capacity'] = (
@ -2964,6 +2981,11 @@ port_speed!N/A
return self._errors['CMMVC5701E']
vol_name = kwargs['obj'].strip('\'\"')
site1_volume_info = self._volumes_list[vol_name]
if site1_volume_info['RC_name']:
rcrel = self._rcrelationship_list[site1_volume_info['RC_name']]
if rcrel.get('consistency_group_name', None):
return self._errors['CMMVC8783E']
site2_volume_info = self._volumes_list['site2' + vol_name]
del self._rcrelationship_list[self._volumes_list[vol_name]['RC_name']]
@ -2985,6 +3007,9 @@ port_speed!N/A
del self._fcmappings_list[site2fcmap['id']]
del site2_volume_info
del self._volumes_list['site2' + vol_name]
del self._volumes_list['fcsite1' + vol_name]
del self._volumes_list['fcsite2' + vol_name]
site1_volume_info['RC_name'] = ''
site1_volume_info['RC_id'] = ''
return ('', '')
@ -7643,12 +7668,78 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
'system_id': '0123456789ABCDEF'}
get_system_info.return_value = fake_system_info
self.driver.do_setup(None)
hyper_type = self._create_hyperswap_type('test_hyperswap_type')
vol = self._create_hyperswap_volume(hyper_type)
spec = {'drivers:volume_topology': 'hyperswap',
'peer_pool': 'hyperswap2'}
vol_type_ref = volume_types.create(self.ctxt, 'test_hyperswap_type',
spec)
vol = self._create_hyperswap_volume(vol_type_ref)
self._assert_vol_exists(vol.name, True)
self.assertRaises(exception.InvalidInput,
self.driver.extend_volume, vol, '16')
self.driver.extend_volume(vol, '13')
attrs = self.driver._helpers.get_vdisk_attributes(vol['name'])
vol_size = int(attrs['capacity']) / units.Gi
self.assertAlmostEqual(vol_size, 13)
self.driver.delete_volume(vol)
# Extend hyperswap volume with thick_provisioning_support.
spec = {'drivers:volume_topology': 'hyperswap',
'peer_pool': 'hyperswap2',
'drivers:rsize': -1}
hs_thick_type = volume_types.create(
self.ctxt, 'test_hyperswap_thick_type', spec)
hs_vol = self._create_hyperswap_volume(hs_thick_type)
self._assert_vol_exists(hs_vol.name, True)
if self.USESIM:
# tell expandvdisksize to fail while called extend_volume
# because volume is fast formatting
self.sim.error_injection('expandvdisksize', 'fast_formatting')
self.assertRaises(exception.VolumeDriverException,
self.driver.extend_volume, hs_vol, 15)
attrs = self.driver._helpers.get_vdisk_attributes(hs_vol['name'])
vol_size = int(attrs['capacity']) / units.Gi
self.assertAlmostEqual(vol_size, 1)
self.driver.delete_volume(hs_vol)
# Extend hyperswap volume that added to group.
with mock.patch.object(storwize_svc_common.StorwizeHelpers,
'extend_vdisk') as extend_vdisk:
group_specs = {'hyperswap_group_enabled': '<is> True'}
group_type_ref = group_types.create(self.ctxt, 'testgroup',
group_specs)
hyper_group = testutils.create_group(
self.ctxt, name='hypergroup',
group_type_id=group_type_ref['id'],
volume_type_ids=[vol_type_ref['id']])
model_update = self.driver.create_group(self.ctxt, hyper_group)
self.assertEqual(fields.GroupStatus.AVAILABLE,
model_update['status'])
vol = self._create_hyperswap_volume(vol_type_ref)
self.db.volume_update(context.get_admin_context(), vol['id'],
{'group_id': hyper_group.id})
add_volumes = [vol]
del_volumes = []
(model_update, add_volumes_update,
remove_volumes_update) = self.driver.update_group(self.ctxt,
hyper_group,
add_volumes,
del_volumes)
self.assertEqual(fields.GroupStatus.AVAILABLE,
model_update['status'])
self.assertEqual([{'id': vol.id, 'group_id': hyper_group.id}],
add_volumes_update)
self.assertEqual([], remove_volumes_update)
self.assertRaises(exception.VolumeDriverException,
self.driver.extend_volume, vol, 15)
self.assertFalse(extend_vdisk.called)
attrs = self.driver._helpers.get_vdisk_attributes(vol['name'])
vol_size = int(attrs['capacity']) / units.Gi
self.assertAlmostEqual(vol_size, 1)
self.driver.delete_volume(vol)
def test_migrate_hyperswap_volume(self):
with mock.patch.object(storwize_svc_common.StorwizeHelpers,

View File

@ -1680,7 +1680,8 @@ class StorwizeHelpers(object):
params.append('-compressed')
else:
params.append('-thin')
params.extend(['-grainsize', six.text_type(opts['grainsize'])])
params.extend(['-grainsize',
six.text_type(opts['grainsize'])])
return params
def create_hyperswap_volume(self, vol_name, size, units, pool, opts):
@ -1712,11 +1713,32 @@ class StorwizeHelpers(object):
pool = attr['mdisk_grp_name']
self.check_hyperswap_pool(pool, opts['peer_pool'])
hyper_pool = '%s' % opts['peer_pool']
is_dr_pool = self.is_volume_type_dr_pools(pool, opts)
if is_dr_pool and opts['rsize'] != -1:
params = []
if opts['rsize'] != -1:
is_dr_pool = self.is_volume_type_dr_pools(pool, opts)
if is_dr_pool:
self.check_data_reduction_pool_params(opts)
params = self._get_hyperswap_volume_create_params(opts,
is_dr_pool)
self.ssh.addvolumecopy(vol_name, hyper_pool, params)
def convert_extended_volume_to_hyperswap(self, vol_name, opts, state):
vol_name = '%s' % vol_name
attr = self.get_vdisk_attributes(vol_name)
if attr is None:
msg = (_('convert_volume_to_hyperswap: Failed to get '
'attributes for volume %s.') % vol_name)
LOG.error(msg)
raise exception.VolumeDriverException(message=msg)
hyper_pool = '%s' % opts['peer_pool']
params = []
if opts['rsize'] != -1:
is_dr_pool = self.is_volume_type_dr_pools(attr['mdisk_grp_name'],
opts)
if is_dr_pool:
self.check_data_reduction_pool_params(opts)
params = self._get_hyperswap_volume_create_params(opts, is_dr_pool)
self.ssh.addvolumecopy(vol_name, hyper_pool, params)
self.ssh.addvolumecopy(vol_name, hyper_pool, params)
def convert_hyperswap_volume_to_normal(self, vol_name, peer_pool):
vol_name = '%s' % vol_name
@ -3519,11 +3541,6 @@ class StorwizeSVCCommonDriver(san.SanDriver,
def _extend_volume_op(self, volume, new_size, old_size=None):
LOG.debug('enter: _extend_volume_op: volume %s', volume['id'])
volume_name = self._get_target_vol(volume)
if self.is_volume_hyperswap(volume):
msg = _('_extend_volume_op: Extending a hyperswap volume is '
'not supported.')
LOG.error(msg)
raise exception.InvalidInput(message=msg)
ret = self._helpers.ensure_vdisk_no_fc_mappings(volume_name,
allow_snaps=False)
@ -3540,51 +3557,84 @@ class StorwizeSVCCommonDriver(san.SanDriver,
rel_info = self._helpers.get_relationship_info(volume_name)
if rel_info:
LOG.warning('_extend_volume_op: Extending a volume with '
'remote copy is not recommended.')
try:
rep_type = rel_info['copy_type']
cyclingmode = rel_info['cycling_mode']
self._master_backend_helpers.delete_relationship(
volume.name)
tgt_vol = (storwize_const.REPLICA_AUX_VOL_PREFIX +
volume.name)
self._master_backend_helpers.extend_vdisk(volume.name,
extend_amt)
self._aux_backend_helpers.extend_vdisk(tgt_vol, extend_amt)
tgt_sys = self._aux_backend_helpers.get_system_info()
if storwize_const.GMCV_MULTI == cyclingmode:
tgt_change_vol = (
storwize_const.REPLICA_CHG_VOL_PREFIX +
tgt_vol)
source_change_vol = (
storwize_const.REPLICA_CHG_VOL_PREFIX +
volume.name)
self._master_backend_helpers.extend_vdisk(
source_change_vol, extend_amt)
self._aux_backend_helpers.extend_vdisk(
tgt_change_vol, extend_amt)
src_change_opts = self._get_vdisk_params(
volume.volume_type_id)
cycle_period_seconds = src_change_opts.get(
'cycle_period_seconds')
self._master_backend_helpers.create_relationship(
volume.name, tgt_vol, tgt_sys.get('system_name'),
True, True, source_change_vol, cycle_period_seconds)
self._aux_backend_helpers.change_relationship_changevolume(
tgt_vol, tgt_change_vol, False)
self._master_backend_helpers.start_relationship(
volume.name)
else:
self._master_backend_helpers.create_relationship(
volume.name, tgt_vol, tgt_sys.get('system_name'),
True if storwize_const.GLOBAL == rep_type else False)
except Exception as e:
msg = (_('Failed to extend a volume with remote copy '
'%(volume)s. Exception: '
'%(err)s.') % {'volume': volume.id,
'err': e})
LOG.error(msg)
raise exception.VolumeDriverException(message=msg)
'remote copy or with "active-active" relationship is '
'not recommended.')
rep_type = rel_info['copy_type']
cyclingmode = rel_info['cycling_mode']
master_helper = self._master_backend_helpers
target_helper = self._aux_backend_helpers
if rep_type == 'activeactive':
hs_opts = self._get_vdisk_params(volume['volume_type_id'],
volume_metadata=
volume.get(
'volume_matadata'))
try:
master_helper.convert_hyperswap_volume_to_normal(
volume_name, hs_opts['peer_pool'])
except Exception as e:
msg = (_('_extend_volume_op: Failed to convert hyperswap '
'volume to normal volume %(volume)s. Exception: '
'%(err)s.') % {'volume': volume.id, 'err': e})
LOG.error(msg)
raise exception.VolumeDriverException(message=msg)
try:
master_helper.extend_vdisk(volume_name, extend_amt)
except Exception as e:
msg = (_('_extend_volume_op: Failed to extend a hyperswap '
'volume %(volume)s. Exception: '
'%(err)s.') % {'volume': volume.id, 'err': e})
LOG.error(msg)
raise exception.VolumeDriverException(message=msg)
finally:
try:
master_helper.convert_extended_volume_to_hyperswap(
volume_name, hs_opts, self._state)
except Exception as e:
msg = (_('_extend_volume_op: Failed to convert volume '
'to hyperswap volume %(volume)s. Exception: '
'%(err)s.') % {'volume': volume.id, 'err': e})
LOG.error(msg)
raise exception.VolumeDriverException(message=msg)
else:
try:
master_helper.delete_relationship(volume.name)
tgt_vol = (storwize_const.REPLICA_AUX_VOL_PREFIX +
volume.name)
master_helper.extend_vdisk(volume.name, extend_amt)
target_helper.extend_vdisk(tgt_vol, extend_amt)
tgt_sys = target_helper.get_system_info()
if storwize_const.GMCV_MULTI == cyclingmode:
tgt_change_vol = (
storwize_const.REPLICA_CHG_VOL_PREFIX +
tgt_vol)
source_change_vol = (
storwize_const.REPLICA_CHG_VOL_PREFIX +
volume.name)
master_helper.extend_vdisk(source_change_vol,
extend_amt)
target_helper.extend_vdisk(tgt_change_vol, extend_amt)
src_change_opts = self._get_vdisk_params(
volume.volume_type_id)
cycle_period_seconds = src_change_opts.get(
'cycle_period_seconds')
master_helper.create_relationship(
volume.name, tgt_vol, tgt_sys.get('system_name'),
True, True, source_change_vol,
cycle_period_seconds)
target_helper.change_relationship_changevolume(
tgt_vol, tgt_change_vol, False)
master_helper.start_relationship(volume.name)
else:
master_helper.create_relationship(
volume.name, tgt_vol, tgt_sys.get('system_name'),
True if cyclingmode == 'none' else False)
except Exception as e:
msg = (_('Failed to extend a volume with remote copy '
'%(volume)s. Exception: '
'%(err)s.') % {'volume': volume.id, 'err': e})
LOG.error(msg)
raise exception.VolumeDriverException(message=msg)
else:
self._helpers.extend_vdisk(volume_name, extend_amt)
LOG.debug('leave: _extend_volume_op: volume %s', volume.id)

View File

@ -0,0 +1,5 @@
---
features:
- |
IBM Spectrum Virtualize Family driver: Added volume-extend support for
volumes created using a HyperSwap volume-type template.