[SVf] As part of Flashcopy 2.0 adding support for volumegroup snapshots
[Spectrum Virtualize family] As part of Flashcopy 2.0 implementation, added support for creation and deletion of volumegroup-snapshots. Implements: blueprint ibm-svf-volumegroup Change-Id: Ibb21dc473115ffc2e61fced0a6a7b2da8852fd58
This commit is contained in:
parent
489284400b
commit
64aabd439b
@ -82,6 +82,7 @@ class StorwizeSVCManagementSimulator(object):
|
||||
self._partnershipcandidate_list = {}
|
||||
self._rcconsistgrp_list = {}
|
||||
self._volumegroup_list = {}
|
||||
self._volumegroup_snapshot_list = {}
|
||||
self._system_list = {'storwize-svc-sim': {'id': '0123456789ABCDEF',
|
||||
'name': 'storwize-svc-sim'},
|
||||
'aux-svc-sim': {'id': 'ABCDEF0123456789',
|
||||
@ -377,7 +378,8 @@ class StorwizeSVCManagementSimulator(object):
|
||||
'removehostmappings',
|
||||
'removefcmaps',
|
||||
'removercrelationships',
|
||||
'novolumegroup'
|
||||
'novolumegroup',
|
||||
'ignorelegacy'
|
||||
]
|
||||
one_param_args = [
|
||||
'chapsecret',
|
||||
@ -418,7 +420,8 @@ class StorwizeSVCManagementSimulator(object):
|
||||
'pool',
|
||||
'site',
|
||||
'buffersize',
|
||||
'volumegroup'
|
||||
'volumegroup',
|
||||
'snapshot'
|
||||
]
|
||||
no_or_one_param_args = [
|
||||
'autoexpand',
|
||||
@ -2652,6 +2655,108 @@ port_speed!N/A
|
||||
del self._volumegroup_list[volumegroup_name]
|
||||
return ('', '')
|
||||
|
||||
def _cmd_addsnapshot(self, **kwargs):
|
||||
# Create a Volumegroup snapshot
|
||||
volumegroup_snapshot_info = {}
|
||||
volumegroup_snapshot_info['id'] = self._find_unused_id(
|
||||
self._volumegroup_snapshot_list)
|
||||
volumegroup_name = kwargs['volumegroup']
|
||||
if 'name' in kwargs:
|
||||
volumegroup_snapshot_info['name'] = kwargs["name"].strip('\'\"')
|
||||
else:
|
||||
volumegroup_snapshot_info['name'] = (
|
||||
'vg_snap-' + volumegroup_snapshot_info['id'])
|
||||
volumegroup_snapshot_info['volume_group_id'] = (
|
||||
self._volumegroup_list[volumegroup_name]['id'])
|
||||
volumegroup_snapshot_info['volume_group_name'] = volumegroup_name
|
||||
volumegroup_snapshot_info['time'] = ''
|
||||
volumegroup_snapshot_info['state'] = 'active'
|
||||
volumegroup_snapshot_info['matches_group'] = 'yes'
|
||||
volumegroup_snapshot_info['parent_uid'] = (
|
||||
self._volumegroup_list[volumegroup_name]['uid'])
|
||||
volumegroup_snapshot_info['expiration_time'] = ''
|
||||
volumegroup_snapshot_info['protection_provisioned_capacity'] = '1.00GB'
|
||||
volumegroup_snapshot_info['protection_written_capacity'] = '0.75MB'
|
||||
volumegroup_snapshot_info['operation_start_time'] = ''
|
||||
volumegroup_snapshot_info['operation_completion_estimate'] = ''
|
||||
volumegroup_snapshot_info['owner_id'] = ''
|
||||
volumegroup_snapshot_info['owner_name'] = ''
|
||||
volumegroup_snapshot_info['auto_snapshot'] = 'no'
|
||||
self._volumegroup_snapshot_list[volumegroup_snapshot_info['name']] = (
|
||||
volumegroup_snapshot_info)
|
||||
return ('Snapshot, id [' + volumegroup_snapshot_info['id'] +
|
||||
'], successfully created or triggered', '')
|
||||
|
||||
def _cmd_lsvolumegroupsnapshot(self, **kwargs):
|
||||
# List the volume group snapshot
|
||||
rows = []
|
||||
rows.append(['id', 'name', 'volume_group_id', 'volume_group_name',
|
||||
'time', 'state', 'matches_group', 'parent_uid',
|
||||
'expiration_time', 'protection_provisioned_capacity',
|
||||
'protection_written_capacity', 'operation_start_time',
|
||||
'operation_completion_estimate', 'owner_id',
|
||||
'owner_name', 'auto_snapshot'])
|
||||
if 'snapshot' and 'volumegroup' not in kwargs:
|
||||
found = False
|
||||
for volumegroup_snapshot in sorted(
|
||||
self._volumegroup_snapshot_list.keys()):
|
||||
volumegroup_snapshot_info = self._volumegroup_snapshot_list[
|
||||
volumegroup_snapshot]
|
||||
if 'filtervalue' not in kwargs:
|
||||
rows.append(
|
||||
[volumegroup_snapshot_info['id'],
|
||||
volumegroup_snapshot_info['name'],
|
||||
volumegroup_snapshot_info['volume_group_id'],
|
||||
volumegroup_snapshot_info['volume_group_name'],
|
||||
'', 'active', 'yes',
|
||||
volumegroup_snapshot_info['parent_uid'], '', '1.00GB',
|
||||
'0.75MB', '', '', '', '', 'no'])
|
||||
found = True
|
||||
if found:
|
||||
return self._print_info_cmd(rows=rows, **kwargs)
|
||||
else:
|
||||
return ('', '')
|
||||
else:
|
||||
volumegroup_snapshot_info = kwargs['snapshot'].strip('\'\"')
|
||||
if volumegroup_snapshot_info not in (
|
||||
self._volumegroup_snapshot_list):
|
||||
return self._errors['CMMVC5804E']
|
||||
volumegroup_snapshot_info = self._volumegroup_snapshot_list[
|
||||
volumegroup_snapshot_info]
|
||||
rows.append(
|
||||
[volumegroup_snapshot_info['id'],
|
||||
volumegroup_snapshot_info['name'],
|
||||
volumegroup_snapshot_info['volume_group_id'],
|
||||
volumegroup_snapshot_info['volume_group_name'],
|
||||
volumegroup_snapshot_info['time'],
|
||||
volumegroup_snapshot_info['state'],
|
||||
volumegroup_snapshot_info['matches_group'],
|
||||
volumegroup_snapshot_info['parent_uid'],
|
||||
volumegroup_snapshot_info['expiration_time'],
|
||||
volumegroup_snapshot_info['protection_provisioned_capacity'],
|
||||
volumegroup_snapshot_info['protection_written_capacity'],
|
||||
volumegroup_snapshot_info['operation_start_time'],
|
||||
volumegroup_snapshot_info['operation_completion_estimate'],
|
||||
volumegroup_snapshot_info['owner_id'],
|
||||
volumegroup_snapshot_info['owner_name'],
|
||||
volumegroup_snapshot_info['auto_snapshot']])
|
||||
|
||||
if 'delim' in kwargs:
|
||||
for index in range(len(rows)):
|
||||
rows[index] = kwargs['delim'].join(rows[index])
|
||||
return ('%s' % '\n'.join(rows), '')
|
||||
|
||||
def _cmd_rmsnapshot(self, **kwargs):
|
||||
# Delete a Volume Group snapshot
|
||||
if 'snapshot' and 'volumegroup' not in kwargs:
|
||||
return self._errors['CMMVC5701E']
|
||||
|
||||
volumegroup_snapshot_name = kwargs['snapshot'].strip('\'\"')
|
||||
if volumegroup_snapshot_name not in self._volumegroup_snapshot_list:
|
||||
return self._errors['CMMVC9755E']
|
||||
del self._volumegroup_snapshot_list[volumegroup_snapshot_name]
|
||||
return ('', '')
|
||||
|
||||
def _cmd_mkrcconsistgrp(self, **kwargs):
|
||||
master_sys = self._system_list['storwize-svc-sim']
|
||||
aux_sys = self._system_list['aux-svc-sim']
|
||||
@ -5563,6 +5668,31 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
|
||||
"CG created failed")
|
||||
return grp
|
||||
|
||||
def _create_volumegroup_type_and_volumegroup(self, vol_type_ref,
|
||||
is_pool=None,
|
||||
is_io_grp=None):
|
||||
# Create volumegroup type
|
||||
volumegroup_spec = {'volume_group_enabled': '<is> True'}
|
||||
if is_pool:
|
||||
volumegroup_spec.update({'volume_group_pool': is_pool})
|
||||
if is_io_grp:
|
||||
volumegroup_spec.update({'volume_group_iogrp': is_io_grp})
|
||||
|
||||
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 volumegroup
|
||||
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, volumegroup)
|
||||
return (volumegroup_type_ref, volumegroup_type,
|
||||
volumegroup, model_update)
|
||||
|
||||
def _create_group_snapshot_in_db(self, group_id, **kwargs):
|
||||
group_snapshot = testutils.create_group_snapshot(self.ctxt,
|
||||
group_id=group_id,
|
||||
@ -7206,6 +7336,139 @@ 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_create_and_delete_volumegroup_snapshot(
|
||||
self, get_system_info):
|
||||
"""Test creation and deletion of volumegroup snapshot"""
|
||||
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)
|
||||
|
||||
# Create 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'])
|
||||
volume = self._generate_vol_info(vol_type)
|
||||
self.driver.create_volume(volume)
|
||||
|
||||
# Create volumegroup type and volumegroup
|
||||
(volumegroup_type_ref, volumegroup_type, volumegroup,
|
||||
model_update) = self._create_volumegroup_type_and_volumegroup(
|
||||
vol_type_ref)
|
||||
self.assertEqual(fields.GroupStatus.AVAILABLE,
|
||||
model_update['status'])
|
||||
|
||||
# Add volumes to volumegroup
|
||||
add_vols = [volume]
|
||||
remove_vols = [volume]
|
||||
(model_update, add_volumes_update, remove_volumes_update) = (
|
||||
self.driver.update_group(self.ctxt, volumegroup, add_vols, []))
|
||||
|
||||
self.assertEqual(fields.GroupStatus.AVAILABLE,
|
||||
model_update['status'])
|
||||
|
||||
# Create group-snapshot
|
||||
group_snapshot, snapshots = self._create_group_snapshot_in_db(
|
||||
volumegroup.id, group_type_id=volumegroup_type_ref.id)
|
||||
|
||||
model_update, snapshots_model = (
|
||||
self.driver.create_group_snapshot(self.ctxt, group_snapshot,
|
||||
snapshots))
|
||||
self.assertEqual(fields.GroupSnapshotStatus.AVAILABLE,
|
||||
model_update['status'])
|
||||
|
||||
for snapshot in snapshots_model:
|
||||
self.assertEqual(fields.SnapshotStatus.AVAILABLE,
|
||||
snapshot['status'])
|
||||
|
||||
# Validating the snapshot_name property value
|
||||
# from metadata of the snapshot
|
||||
groupsnapshot_name = self.driver._get_volumegroup_snapshot_name(
|
||||
group_snapshot)
|
||||
for snapshot in snapshots:
|
||||
self.assertEqual(groupsnapshot_name,
|
||||
snapshot.metadata['snapshot_name'])
|
||||
|
||||
# Delete group-snapshot
|
||||
model_update, snapshots_model = self.driver.delete_group_snapshot(
|
||||
self.ctxt, group_snapshot, snapshots)
|
||||
self.assertEqual(fields.GroupSnapshotStatus.DELETED,
|
||||
model_update['status'])
|
||||
|
||||
for snapshot in snapshots_model:
|
||||
self.assertEqual(fields.SnapshotStatus.DELETED,
|
||||
snapshot['status'])
|
||||
|
||||
# Remove the volumes from volumegroup
|
||||
(model_update, add_volumes_update,
|
||||
remove_volumes_update) = self.driver.update_group(
|
||||
self.ctxt, volumegroup, [], remove_vols)
|
||||
|
||||
self.assertEqual(fields.GroupStatus.AVAILABLE,
|
||||
model_update['status'])
|
||||
|
||||
# Delete Volume Group
|
||||
model_update = self.driver.delete_group(self.ctxt, volumegroup,
|
||||
[])
|
||||
self.assertEqual(fields.GroupStatus.DELETED,
|
||||
model_update[0]['status'])
|
||||
|
||||
@mock.patch.object(storwize_svc_common.StorwizeHelpers,
|
||||
'get_system_info')
|
||||
@mock.patch.object(cinder.volume.volume_utils,
|
||||
'is_group_a_type')
|
||||
@mock.patch('cinder.volume.volume_utils.is_group_a_cg_snapshot_type')
|
||||
@mock.patch.object(storwize_svc_common.StorwizeHelpers,
|
||||
'create_volumegroup_snapshot')
|
||||
@mock.patch.object(storwize_svc_common.StorwizeHelpers,
|
||||
'delete_volumegroup_snapshot')
|
||||
def test_storwize_create_and_delete_volumegroup_snapshot_calls(
|
||||
self, delete_volumegroup_snapshot,
|
||||
create_volumegroup_snapshot, is_grp_a_cg_snapshot_type,
|
||||
vg_type, get_system_info):
|
||||
"""Test creation and deletion of volumegroup snapshot"""
|
||||
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)
|
||||
|
||||
# Mocking volume-group-enabled spec as true
|
||||
is_grp_a_cg_snapshot_type.side_effect = [False, False, False]
|
||||
vg_type.side_effect = [False, False, True, False, True,
|
||||
False, False, True, False, False, True]
|
||||
|
||||
# Create volume group
|
||||
type_ref = volume_types.create(self.ctxt, 'testtype', None)
|
||||
group = testutils.create_group(self.ctxt,
|
||||
group_type_id=fake.GROUP_TYPE_ID,
|
||||
volume_type_ids=[type_ref['id']])
|
||||
|
||||
# Create volume group snapshot
|
||||
group_snapshot, snapshots = self._create_group_snapshot_in_db(
|
||||
group.id)
|
||||
|
||||
model_update, snapshots_model = (
|
||||
self.driver.create_group_snapshot(self.ctxt, group_snapshot,
|
||||
snapshots))
|
||||
self.assertEqual(fields.GroupSnapshotStatus.AVAILABLE,
|
||||
model_update['status'])
|
||||
self.assertTrue(create_volumegroup_snapshot.called)
|
||||
|
||||
# Delete volume group snapshot
|
||||
model_update, snapshots_model = (
|
||||
self.driver.delete_group_snapshot(self.ctxt, group_snapshot,
|
||||
snapshots))
|
||||
self.assertEqual(fields.GroupSnapshotStatus.DELETED,
|
||||
model_update['status'])
|
||||
self.assertTrue(delete_volumegroup_snapshot.called)
|
||||
|
||||
# Delete volume group
|
||||
self.driver.delete_group(self.ctxt, group, [])
|
||||
|
||||
@mock.patch.object(storwize_svc_common.StorwizeHelpers,
|
||||
'create_rccg')
|
||||
def test_storwize_group_create(self, create_rccg):
|
||||
|
@ -50,6 +50,7 @@ RCCG_PREFIX = 'rccg-'
|
||||
HYPERCG_PREFIX = 'hycg-'
|
||||
|
||||
VG_PREFIX = 'vg-'
|
||||
VG_SNAPSHOT_PREFIX = 'vg_snap-'
|
||||
|
||||
# remote mirror copy status
|
||||
REP_CONSIS_SYNC = 'consistent_synchronized'
|
||||
|
@ -586,6 +586,64 @@ class StorwizeSSH(object):
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.exception('Failed to delete volumegroup.')
|
||||
|
||||
def lsvolumegroupsnapshot(self, params):
|
||||
"""Return volumegroup-snapshot attributes.
|
||||
|
||||
Return None if it doesn't exists
|
||||
"""
|
||||
|
||||
ssh_cmd = ['svcinfo', 'lsvolumegroupsnapshot']
|
||||
if "id" in params:
|
||||
ssh_cmd.append(params["id"])
|
||||
elif "name" and "volumegroup" in params:
|
||||
ssh_cmd.extend(['-snapshot', params["name"], '-volumegroup',
|
||||
params["volumegroup"]])
|
||||
# Add delimiter to parse the output
|
||||
ssh_cmd.extend(['-delim', ':'])
|
||||
out, err = self._ssh(ssh_cmd, check_exit_code=False)
|
||||
if not err:
|
||||
if not out:
|
||||
return None
|
||||
# Parse the lsvolumegroupsnapshot output
|
||||
output = out.split('\n')
|
||||
attributes = output[0].split(":")
|
||||
attribute_values = output[1].split(":")
|
||||
attrs = {key: val for key, val in zip(attributes,
|
||||
attribute_values)}
|
||||
return attrs
|
||||
# CMMVC5804E implies volumegroup-snapshot or volumegroup specified
|
||||
# does not exist in the SVC storage.
|
||||
if 'CMMVC5804E' in err:
|
||||
return None
|
||||
msg = (_('CLI Exception output:\n command: %(cmd)s\n '
|
||||
'stdout: %(out)s\n stderr: %(err)s.') %
|
||||
{'cmd': ssh_cmd,
|
||||
'out': out,
|
||||
'err': err})
|
||||
LOG.error(msg)
|
||||
raise exception.VolumeBackendAPIException(data=msg)
|
||||
|
||||
def addsnapshot(self, params):
|
||||
ssh_cmd = ['svctask', 'addsnapshot', '-ignorelegacy']
|
||||
if "volumegroup" in params:
|
||||
ssh_cmd.extend(['-volumegroup', params["volumegroup"]])
|
||||
if "name" in params:
|
||||
ssh_cmd.extend(['-name', params["name"]])
|
||||
try:
|
||||
return self.run_ssh_check_created(ssh_cmd)
|
||||
except Exception:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.exception('Failed to create volumegroup snapshot.')
|
||||
|
||||
def rmsnapshot(self, params):
|
||||
ssh_cmd = ['svctask', 'rmsnapshot']
|
||||
if "id" in params:
|
||||
ssh_cmd.extend(['-snapshotid', params["id"]])
|
||||
elif "name" and "volumegroup" in params:
|
||||
ssh_cmd.extend(['-snapshot', params["name"], '-volumegroup',
|
||||
params["volumegroup"]])
|
||||
self.run_ssh_assert_no_output(ssh_cmd)
|
||||
|
||||
def mkvdisk(self, name, size, units, pool, opts, params):
|
||||
ssh_cmd = ['svctask', 'mkvdisk', '-name', '"%s"' % name, '-mdiskgrp',
|
||||
'"%s"' % pool, '-iogrp', six.text_type(opts['iogrp']),
|
||||
@ -2844,6 +2902,21 @@ class StorwizeHelpers(object):
|
||||
LOG.error(msg)
|
||||
raise exception.VolumeDriverException(message=msg)
|
||||
|
||||
def create_volumegroup_snapshot(self, params):
|
||||
self.ssh.addsnapshot(params)
|
||||
|
||||
def is_volumegroup_snapshot_exists(self, params):
|
||||
"""Check if volumegroup snapshot exists."""
|
||||
attrs = self.ssh.lsvolumegroupsnapshot(params)
|
||||
return attrs is not None
|
||||
|
||||
def delete_volumegroup_snapshot(self, params):
|
||||
"""Delete volumegroup snapshot"""
|
||||
if not self.is_volumegroup_snapshot_exists(params):
|
||||
LOG.info('Tried to delete non-existent volumegroup snapshot.')
|
||||
return
|
||||
self.ssh.rmsnapshot(params)
|
||||
|
||||
def get_partnership_info(self, system_name):
|
||||
partnership = self.ssh.lspartnership(system_name)
|
||||
return partnership[0] if len(partnership) > 0 else None
|
||||
@ -3795,6 +3868,16 @@ class StorwizeSVCCommonDriver(san.SanDriver,
|
||||
volume.metadata['Volume Group Name'] = volumegroup_name
|
||||
volume.save()
|
||||
|
||||
def _update_volumegroup_snapshot_properties(self, ctxt, snapshot,
|
||||
group_snapshot=None):
|
||||
volumegroup_snapshot_name = (
|
||||
self._get_volumegroup_snapshot_name(group_snapshot)
|
||||
if group_snapshot else "")
|
||||
if not snapshot.metadata:
|
||||
snapshot.metadata = dict()
|
||||
snapshot.metadata['snapshot_name'] = volumegroup_snapshot_name
|
||||
snapshot.save()
|
||||
|
||||
def create_volume(self, volume):
|
||||
LOG.debug('enter: create_volume: volume %s', volume['name'])
|
||||
# Create a replication or hyperswap volume with group_id is not
|
||||
@ -6080,6 +6163,13 @@ class StorwizeSVCCommonDriver(san.SanDriver,
|
||||
vg = storwize_const.VG_PREFIX
|
||||
return vg + group_id[0:4] + '-' + group_id[-5:]
|
||||
|
||||
@staticmethod
|
||||
def _get_volumegroup_snapshot_name(group_snapshot, grp_snapshot_id=None):
|
||||
group_snapshot_id = (
|
||||
group_snapshot.id if group_snapshot else grp_snapshot_id)
|
||||
vg_snapshot = storwize_const.VG_SNAPSHOT_PREFIX
|
||||
return vg_snapshot + group_snapshot_id
|
||||
|
||||
# Add CG capability to generic volume groups
|
||||
def create_group(self, context, group):
|
||||
"""Creates a group.
|
||||
@ -6443,27 +6533,57 @@ 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) and
|
||||
not volume_utils.is_group_a_type
|
||||
|
||||
if (volume_utils.is_group_a_cg_snapshot_type(group_snapshot) or
|
||||
volume_utils.is_group_a_type
|
||||
(group_snapshot, "consistent_group_replication_enabled")
|
||||
and not volume_utils.is_group_a_type(
|
||||
or volume_utils.is_group_a_type(
|
||||
group_snapshot, "hyperswap_group_enabled")):
|
||||
# Use group_snapshot id as cg name
|
||||
cg_name = 'cg_snap-' + group_snapshot.id
|
||||
# Create new cg as cg_snapshot
|
||||
self._helpers.create_fc_consistgrp(cg_name)
|
||||
|
||||
timeout = self.configuration.storwize_svc_flashcopy_timeout
|
||||
|
||||
model_update, snapshots_model = (
|
||||
self._helpers.run_consistgrp_snapshots(cg_name,
|
||||
snapshots,
|
||||
self._state,
|
||||
self.configuration,
|
||||
timeout))
|
||||
elif volume_utils.is_group_a_type(
|
||||
group_snapshot, "volume_group_enabled"):
|
||||
try:
|
||||
self._helpers.check_codelevel_for_volumegroup(
|
||||
self._state['code_level'])
|
||||
params = dict()
|
||||
# Use group_snapshot id as volumegroup name
|
||||
volumegroup_snapshot_name = (
|
||||
self._get_volumegroup_snapshot_name(group_snapshot))
|
||||
params["name"] = volumegroup_snapshot_name
|
||||
volumegroup_name = self._get_volumegroup_name(
|
||||
None, grp_id=group_snapshot.group_id)
|
||||
params["volumegroup"] = volumegroup_name
|
||||
model_update = {'status': fields.GroupSnapshotStatus.AVAILABLE}
|
||||
snapshots_model = []
|
||||
self._helpers.create_volumegroup_snapshot(params)
|
||||
except exception.VolumeBackendAPIException as err:
|
||||
model_update['status'] = fields.GroupSnapshotStatus.ERROR
|
||||
LOG.error("Failed to create VolumeGroup Snapshot. "
|
||||
"Exception: %s.", err)
|
||||
for snapshot in snapshots:
|
||||
self._update_volumegroup_snapshot_properties(
|
||||
context, snapshot, group_snapshot)
|
||||
snapshots_model.append(
|
||||
{'id': snapshot['id'],
|
||||
'status': model_update['status'],
|
||||
'replication_status': fields.ReplicationStatus.NOT_CAPABLE
|
||||
})
|
||||
else:
|
||||
# we'll rely on the generic group implementation if it is not a
|
||||
# consistency group request.
|
||||
# consistency group/volumegroup request.
|
||||
raise NotImplementedError()
|
||||
# Use group_snapshot id as cg name
|
||||
cg_name = 'cg_snap-' + group_snapshot.id
|
||||
# Create new cg as cg_snapshot
|
||||
self._helpers.create_fc_consistgrp(cg_name)
|
||||
|
||||
timeout = self.configuration.storwize_svc_flashcopy_timeout
|
||||
|
||||
model_update, snapshots_model = (
|
||||
self._helpers.run_consistgrp_snapshots(cg_name,
|
||||
snapshots,
|
||||
self._state,
|
||||
self.configuration,
|
||||
timeout))
|
||||
|
||||
return model_update, snapshots_model
|
||||
|
||||
@ -6476,20 +6596,53 @@ class StorwizeSVCCommonDriver(san.SanDriver,
|
||||
:returns: model_update, snapshots_model_update
|
||||
"""
|
||||
|
||||
if (not volume_utils.is_group_a_cg_snapshot_type(group_snapshot) and
|
||||
not volume_utils.is_group_a_type(
|
||||
if (volume_utils.is_group_a_cg_snapshot_type(group_snapshot) or
|
||||
volume_utils.is_group_a_type(
|
||||
group_snapshot, "hyperswap_group_enabled")):
|
||||
|
||||
cgsnapshot_id = group_snapshot.id
|
||||
cg_name = 'cg_snap-' + cgsnapshot_id
|
||||
|
||||
model_update, snapshots_model = (
|
||||
self._helpers.delete_consistgrp_snapshots(cg_name,
|
||||
snapshots))
|
||||
elif volume_utils.is_group_a_type(
|
||||
group_snapshot, "volume_group_enabled"):
|
||||
try:
|
||||
self._helpers.check_codelevel_for_volumegroup(
|
||||
self._state['code_level'])
|
||||
params = dict()
|
||||
volumegroup_snapshot_name = (
|
||||
self._get_volumegroup_snapshot_name(group_snapshot))
|
||||
params["name"] = volumegroup_snapshot_name
|
||||
volumegroup_name = self._get_volumegroup_name(
|
||||
None, grp_id=group_snapshot.group_id)
|
||||
params["volumegroup"] = volumegroup_name
|
||||
model_update = {'status': fields.GroupSnapshotStatus.DELETED}
|
||||
snapshots_model = []
|
||||
self._helpers.delete_volumegroup_snapshot(params)
|
||||
for snapshot in snapshots:
|
||||
self._update_volumegroup_snapshot_properties(
|
||||
context, snapshot)
|
||||
snapshots_model.append(
|
||||
{'id': snapshot['id'],
|
||||
'status': fields.GroupSnapshotStatus.DELETED})
|
||||
except exception.VolumeBackendAPIException as err:
|
||||
model_update['status'] = (
|
||||
fields.GroupSnapshotStatus.ERROR_DELETING)
|
||||
for snapshot in snapshots:
|
||||
snapshots_model.append(
|
||||
{'id': snapshot['id'],
|
||||
'status': fields.GroupSnapshotStatus.ERROR_DELETING})
|
||||
LOG.error("Failed to delete the volume_group_snapshot %(snap) "
|
||||
"with Exception: %(exception)s.",
|
||||
{'snap': group_snapshot.group_id, 'exception': err})
|
||||
|
||||
else:
|
||||
# we'll rely on the generic group implementation if it is not a
|
||||
# consistency group request.
|
||||
# consistency group/volumegroup request.
|
||||
raise NotImplementedError()
|
||||
|
||||
cgsnapshot_id = group_snapshot.id
|
||||
cg_name = 'cg_snap-' + cgsnapshot_id
|
||||
|
||||
model_update, snapshots_model = (
|
||||
self._helpers.delete_consistgrp_snapshots(cg_name,
|
||||
snapshots))
|
||||
|
||||
return model_update, snapshots_model
|
||||
|
||||
@volume_utils.trace
|
||||
|
@ -0,0 +1,5 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
IBM Spectrum Virtualize Family driver: Added support for creation
|
||||
and deletion of volumegroup snapshots.
|
Loading…
Reference in New Issue
Block a user