Merge "Storwize: add CG capability to generic groups"
This commit is contained in:
commit
a5f3addc8b
@ -48,6 +48,7 @@ from cinder.volume.drivers.ibm.storwize_svc import storwize_const
|
||||
from cinder.volume.drivers.ibm.storwize_svc import storwize_svc_common
|
||||
from cinder.volume.drivers.ibm.storwize_svc import storwize_svc_fc
|
||||
from cinder.volume.drivers.ibm.storwize_svc import storwize_svc_iscsi
|
||||
from cinder.volume import group_types
|
||||
from cinder.volume import qos_specs
|
||||
from cinder.volume import utils as volume_utils
|
||||
from cinder.volume import volume_types
|
||||
@ -3685,54 +3686,55 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
|
||||
self.driver.delete_volume(volume)
|
||||
self.db.volume_destroy(self.ctxt, volume['id'])
|
||||
|
||||
def _create_consistencygroup_in_db(self, **kwargs):
|
||||
cg = testutils.create_consistencygroup(self.ctxt, **kwargs)
|
||||
def _create_group_in_db(self, **kwargs):
|
||||
cg = testutils.create_group(self.ctxt, **kwargs)
|
||||
return cg
|
||||
|
||||
def _create_consistencegroup(self, **kwargs):
|
||||
cg = self._create_consistencygroup_in_db(**kwargs)
|
||||
def _create_group(self, **kwargs):
|
||||
grp = self._create_group_in_db(**kwargs)
|
||||
|
||||
model_update = self.driver.create_consistencygroup(self.ctxt, cg)
|
||||
self.assertEqual(fields.ConsistencyGroupStatus.AVAILABLE,
|
||||
model_update = self.driver.create_group(self.ctxt, grp)
|
||||
self.assertEqual(fields.GroupStatus.AVAILABLE,
|
||||
model_update['status'],
|
||||
"CG created failed")
|
||||
return cg
|
||||
return grp
|
||||
|
||||
def _create_cgsnapshot_in_db(self, cg_id, **kwargs):
|
||||
cg_snapshot = testutils.create_cgsnapshot(self.ctxt,
|
||||
consistencygroup_id= cg_id,
|
||||
**kwargs)
|
||||
def _create_group_snapshot_in_db(self, group_id, **kwargs):
|
||||
group_snapshot = testutils.create_group_snapshot(self.ctxt,
|
||||
group_id=group_id,
|
||||
**kwargs)
|
||||
snapshots = []
|
||||
cg_id = cg_snapshot['consistencygroup_id']
|
||||
volumes = self.db.volume_get_all_by_group(self.ctxt.elevated(), cg_id)
|
||||
volumes = self.db.volume_get_all_by_generic_group(
|
||||
self.ctxt.elevated(), group_id)
|
||||
|
||||
if not volumes:
|
||||
msg = _("Consistency group is empty. No cgsnapshot "
|
||||
"will be created.")
|
||||
raise exception.InvalidConsistencyGroup(reason=msg)
|
||||
msg = _("Group is empty. No cgsnapshot will be created.")
|
||||
raise exception.InvalidGroup(reason=msg)
|
||||
|
||||
for volume in volumes:
|
||||
snapshots.append(testutils.create_snapshot(
|
||||
self.ctxt, volume['id'],
|
||||
cg_snapshot.id,
|
||||
cg_snapshot.name,
|
||||
cg_snapshot.id,
|
||||
group_snapshot.id,
|
||||
group_snapshot.name,
|
||||
group_snapshot.id,
|
||||
fields.SnapshotStatus.CREATING))
|
||||
return cg_snapshot, snapshots
|
||||
return group_snapshot, snapshots
|
||||
|
||||
def _create_cgsnapshot(self, cg_id, **kwargs):
|
||||
cg_snapshot, snapshots = self._create_cgsnapshot_in_db(cg_id, **kwargs)
|
||||
def _create_group_snapshot(self, cg_id, **kwargs):
|
||||
group_snapshot, snapshots = self._create_group_snapshot_in_db(
|
||||
cg_id, **kwargs)
|
||||
|
||||
model_update, snapshots_model = (
|
||||
self.driver.create_cgsnapshot(self.ctxt, cg_snapshot, snapshots))
|
||||
self.assertEqual('available',
|
||||
self.driver.create_group_snapshot(self.ctxt, group_snapshot,
|
||||
snapshots))
|
||||
self.assertEqual(fields.GroupSnapshotStatus.AVAILABLE,
|
||||
model_update['status'],
|
||||
"CGSnapshot created failed")
|
||||
|
||||
for snapshot in snapshots_model:
|
||||
self.assertEqual(fields.SnapshotStatus.AVAILABLE,
|
||||
snapshot['status'])
|
||||
return cg_snapshot, snapshots
|
||||
return group_snapshot, snapshots
|
||||
|
||||
def _create_test_vol(self, opts):
|
||||
ctxt = testutils.get_test_admin_context()
|
||||
@ -4065,8 +4067,7 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
|
||||
volume)
|
||||
|
||||
# Try to delete a volume that doesn't exist (should not fail)
|
||||
vol_no_exist = {'name': 'i_dont_exist',
|
||||
'id': '111111'}
|
||||
vol_no_exist = self._generate_vol_info(None, None)
|
||||
self.driver.delete_volume(vol_no_exist)
|
||||
# Ensure export for volume that doesn't exist (should not fail)
|
||||
self.driver.ensure_export(None, vol_no_exist)
|
||||
@ -4075,15 +4076,7 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
|
||||
self.driver.delete_volume(volume)
|
||||
|
||||
def test_storwize_svc_volume_name(self):
|
||||
# Create a volume with space in name
|
||||
pool = _get_test_pool()
|
||||
rand_id = six.text_type(random.randint(10000, 99999))
|
||||
volume = {'name': 'volume_ space',
|
||||
'size': 10,
|
||||
'id': '%s' % rand_id,
|
||||
'volume_type_id': None,
|
||||
'mdisk_grp_name': pool,
|
||||
'host': 'openstack@svc#%s' % pool}
|
||||
volume = self._generate_vol_info(None, None)
|
||||
self.driver.create_volume(volume)
|
||||
self.driver.ensure_export(None, volume)
|
||||
|
||||
@ -4295,6 +4288,7 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
|
||||
each_pool['thin_provisioning_support'])
|
||||
self.assertEqual(not is_thin_provisioning_enabled,
|
||||
each_pool['thick_provisioning_support'])
|
||||
self.assertTrue(each_pool['consistent_group_snapshot_enabled'])
|
||||
if self.USESIM:
|
||||
expected = 'storwize-svc-sim'
|
||||
self.assertEqual(expected, stats['volume_backend_name'])
|
||||
@ -4951,232 +4945,300 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
|
||||
attrs = self.driver._helpers.get_vdisk_attributes(vol2['name'])
|
||||
self.assertIn('openstack2', attrs['mdisk_grp_name'])
|
||||
|
||||
# Test groups operation ####
|
||||
@mock.patch('cinder.volume.utils.is_group_a_cg_snapshot_type')
|
||||
def test_storwize_group_create_with_replication(
|
||||
self, is_grp_a_cg_snapshot_type):
|
||||
"""Test group create."""
|
||||
is_grp_a_cg_snapshot_type.side_effect = True
|
||||
spec = {'replication_enabled': '<is> True',
|
||||
'replication_type': '<in> metro'}
|
||||
rep_type_ref = volume_types.create(self.ctxt, 'rep_type', spec)
|
||||
rep_group = testutils.create_group(
|
||||
self.ctxt, group_type_id=fake.GROUP_TYPE_ID,
|
||||
volume_type_ids=[rep_type_ref['id']])
|
||||
|
||||
model_update = self.driver.create_group(self.ctxt, rep_group)
|
||||
self.assertEqual(fields.GroupStatus.ERROR,
|
||||
model_update['status'])
|
||||
|
||||
self.assertFalse(is_grp_a_cg_snapshot_type.called)
|
||||
|
||||
@mock.patch('cinder.volume.utils.is_group_a_cg_snapshot_type')
|
||||
def test_storwize_group_create(self, is_grp_a_cg_snapshot_type):
|
||||
"""Test group create."""
|
||||
is_grp_a_cg_snapshot_type.side_effect = [False, True]
|
||||
group = mock.MagicMock()
|
||||
|
||||
self.assertRaises(NotImplementedError,
|
||||
self.driver.create_group, self.ctxt, group)
|
||||
|
||||
model_update = self.driver.create_group(self.ctxt, group)
|
||||
self.assertEqual(fields.GroupStatus.AVAILABLE,
|
||||
model_update['status'])
|
||||
|
||||
@mock.patch('oslo_service.loopingcall.FixedIntervalLoopingCall',
|
||||
new=testutils.ZeroIntervalLoopingCall)
|
||||
def test_storwize_consistency_group_snapshot(self):
|
||||
cg_type = self._create_consistency_group_volume_type()
|
||||
self.ctxt.user_id = fake.USER_ID
|
||||
self.ctxt.project_id = fake.PROJECT_ID
|
||||
cg = self._create_consistencygroup_in_db(volume_type_id=cg_type['id'])
|
||||
@mock.patch('cinder.volume.utils.is_group_a_cg_snapshot_type')
|
||||
def test_storwize_delete_group(self, is_grp_a_cg_snapshot_type):
|
||||
is_grp_a_cg_snapshot_type.side_effect = [False, True]
|
||||
type_ref = volume_types.create(self.ctxt, 'testtype', None)
|
||||
group = testutils.create_group(self.ctxt,
|
||||
group_type_id=fake.GROUP_TYPE_ID,
|
||||
volume_type_id=type_ref['id'])
|
||||
|
||||
model_update = self.driver.create_consistencygroup(self.ctxt, cg)
|
||||
self._create_volume(volume_type_id=type_ref['id'], group_id=group.id)
|
||||
self._create_volume(volume_type_id=type_ref['id'], group_id=group.id)
|
||||
volumes = self.db.volume_get_all_by_generic_group(
|
||||
self.ctxt.elevated(), group.id)
|
||||
self.assertRaises(NotImplementedError,
|
||||
self.driver.delete_group,
|
||||
self.ctxt, group, volumes)
|
||||
|
||||
self.assertEqual(fields.ConsistencyGroupStatus.AVAILABLE,
|
||||
model_update['status'],
|
||||
"CG created failed")
|
||||
|
||||
volumes = [
|
||||
self._create_volume(volume_type_id=cg_type['id'],
|
||||
consistencygroup_id=cg['id']),
|
||||
self._create_volume(volume_type_id=cg_type['id'],
|
||||
consistencygroup_id=cg['id']),
|
||||
self._create_volume(volume_type_id=cg_type['id'],
|
||||
consistencygroup_id=cg['id'])
|
||||
]
|
||||
|
||||
cg_snapshot, snapshots = self._create_cgsnapshot_in_db(cg['id'])
|
||||
|
||||
snapshots = objects.SnapshotList.get_all_for_cgsnapshot(
|
||||
self.ctxt, cg_snapshot.id)
|
||||
model_update = self.driver.create_cgsnapshot(self.ctxt, cg_snapshot,
|
||||
snapshots)
|
||||
self.assertEqual('available',
|
||||
model_update[0]['status'],
|
||||
"CGSnapshot created failed")
|
||||
|
||||
for snapshot in model_update[1]:
|
||||
self.assertEqual(fields.SnapshotStatus.AVAILABLE,
|
||||
snapshot['status'])
|
||||
|
||||
model_update = self.driver.delete_consistencygroup(self.ctxt,
|
||||
cg, volumes)
|
||||
|
||||
self.assertEqual(fields.ConsistencyGroupStatus.DELETED,
|
||||
model_update = self.driver.delete_group(self.ctxt, group, volumes)
|
||||
self.assertEqual(fields.GroupStatus.DELETED,
|
||||
model_update[0]['status'])
|
||||
for volume in model_update[1]:
|
||||
self.assertEqual('deleted', volume['status'])
|
||||
|
||||
@mock.patch('cinder.volume.utils.is_group_a_cg_snapshot_type')
|
||||
def test_storwize_group_update(self, is_grp_a_cg_snapshot_type):
|
||||
"""Test group update."""
|
||||
is_grp_a_cg_snapshot_type.side_effect = [False, True]
|
||||
group = mock.MagicMock()
|
||||
self.assertRaises(NotImplementedError, self.driver.update_group,
|
||||
self.ctxt, group, None, None)
|
||||
|
||||
(model_update, add_volumes_update,
|
||||
remove_volumes_update) = self.driver.update_group(self.ctxt, group)
|
||||
self.assertIsNone(model_update)
|
||||
self.assertIsNone(add_volumes_update)
|
||||
self.assertIsNone(remove_volumes_update)
|
||||
|
||||
@mock.patch('oslo_service.loopingcall.FixedIntervalLoopingCall',
|
||||
new=testutils.ZeroIntervalLoopingCall)
|
||||
def test_storwize_consistency_group_from_src_invalid(self):
|
||||
# Invalid input case for create cg from src
|
||||
cg_type = self._create_consistency_group_volume_type()
|
||||
self.ctxt.user_id = fake.USER_ID
|
||||
self.ctxt.project_id = fake.PROJECT_ID
|
||||
# create cg in db
|
||||
cg = self._create_consistencygroup_in_db(volume_type_id=cg_type['id'])
|
||||
@mock.patch('cinder.volume.utils.is_group_a_cg_snapshot_type')
|
||||
def test_storwize_create_group_snapshot(self, is_grp_a_cg_snapshot_type):
|
||||
is_grp_a_cg_snapshot_type.side_effect = [False, True]
|
||||
type_ref = volume_types.create(self.ctxt, 'testtype', None)
|
||||
group = testutils.create_group(self.ctxt,
|
||||
group_type_id=fake.GROUP_TYPE_ID,
|
||||
volume_type_id=type_ref['id'])
|
||||
|
||||
self._create_volume(volume_type_id=type_ref['id'], group_id=group.id)
|
||||
self._create_volume(volume_type_id=type_ref['id'], group_id=group.id)
|
||||
group_snapshot, snapshots = self._create_group_snapshot_in_db(
|
||||
group.id)
|
||||
self.assertRaises(NotImplementedError,
|
||||
self.driver.create_group_snapshot,
|
||||
self.ctxt, group_snapshot, snapshots)
|
||||
|
||||
(model_update,
|
||||
snapshots_model_update) = self.driver.create_group_snapshot(
|
||||
self.ctxt, group_snapshot, snapshots)
|
||||
self.assertEqual(fields.GroupSnapshotStatus.AVAILABLE,
|
||||
model_update['status'],
|
||||
"CGSnapshot created failed")
|
||||
|
||||
for snapshot in snapshots_model_update:
|
||||
self.assertEqual(fields.SnapshotStatus.AVAILABLE,
|
||||
snapshot['status'])
|
||||
|
||||
@mock.patch('oslo_service.loopingcall.FixedIntervalLoopingCall',
|
||||
new=testutils.ZeroIntervalLoopingCall)
|
||||
@mock.patch('cinder.volume.utils.is_group_a_cg_snapshot_type')
|
||||
def test_storwize_delete_group_snapshot(self, is_grp_a_cg_snapshot_type):
|
||||
is_grp_a_cg_snapshot_type.side_effect = [True, False, True]
|
||||
type_ref = volume_types.create(self.ctxt, 'testtype', None)
|
||||
group = testutils.create_group(self.ctxt,
|
||||
group_type_id=fake.GROUP_TYPE_ID,
|
||||
volume_type_id=type_ref['id'])
|
||||
|
||||
self._create_volume(volume_type_id=type_ref['id'], group_id=group.id)
|
||||
self._create_volume(volume_type_id=type_ref['id'], group_id=group.id)
|
||||
|
||||
group_snapshot, snapshots = self._create_group_snapshot(group.id)
|
||||
self.assertRaises(NotImplementedError,
|
||||
self.driver.delete_group_snapshot,
|
||||
self.ctxt, group_snapshot, snapshots)
|
||||
|
||||
model_update = self.driver.delete_group_snapshot(self.ctxt,
|
||||
group_snapshot,
|
||||
snapshots)
|
||||
self.assertEqual(fields.GroupSnapshotStatus.DELETED,
|
||||
model_update[0]['status'])
|
||||
for volume in model_update[1]:
|
||||
self.assertEqual(fields.SnapshotStatus.DELETED, volume['status'])
|
||||
|
||||
@mock.patch('oslo_service.loopingcall.FixedIntervalLoopingCall',
|
||||
new=testutils.ZeroIntervalLoopingCall)
|
||||
def test_storwize_create_group_from_src_invalid(self):
|
||||
# Invalid input case for create group from src
|
||||
type_ref = volume_types.create(self.ctxt, 'testtype', None)
|
||||
spec = {'consistent_group_snapshot_enabled': '<is> True'}
|
||||
cg_type_ref = group_types.create(self.ctxt, 'cg_type', spec)
|
||||
vg_type_ref = group_types.create(self.ctxt, 'vg_type', None)
|
||||
|
||||
# create group in db
|
||||
group = self._create_group_in_db(volume_type_id=type_ref.id,
|
||||
group_type_id=vg_type_ref.id)
|
||||
self.assertRaises(NotImplementedError,
|
||||
self.driver.create_group_from_src,
|
||||
self.ctxt, group, None, None, None,
|
||||
None, None)
|
||||
|
||||
group = self._create_group_in_db(volume_type_id=type_ref.id,
|
||||
group_type_id=cg_type_ref.id)
|
||||
|
||||
# create volumes in db
|
||||
vol1 = testutils.create_volume(self.ctxt, volume_type_id=cg_type['id'],
|
||||
consistencygroup_id=cg['id'])
|
||||
vol2 = testutils.create_volume(self.ctxt, volume_type_id=cg_type['id'],
|
||||
consistencygroup_id=cg['id'])
|
||||
vol1 = testutils.create_volume(self.ctxt, volume_type_id=type_ref.id,
|
||||
group_id=group.id)
|
||||
vol2 = testutils.create_volume(self.ctxt, volume_type_id=type_ref.id,
|
||||
group_id=group.id)
|
||||
volumes = [vol1, vol2]
|
||||
|
||||
source_cg = self._create_consistencegroup(volume_type_id=cg_type['id'])
|
||||
source_cg = self._create_group_in_db(volume_type_id=type_ref.id,
|
||||
group_type_id=cg_type_ref.id)
|
||||
|
||||
# Add volumes to source CG
|
||||
src_vol1 = self._create_volume(volume_type_id=cg_type['id'],
|
||||
consistencygroup_id=source_cg['id'])
|
||||
src_vol2 = self._create_volume(volume_type_id=cg_type['id'],
|
||||
consistencygroup_id=source_cg['id'])
|
||||
src_vol1 = self._create_volume(volume_type_id=type_ref.id,
|
||||
group_id=source_cg['id'])
|
||||
src_vol2 = self._create_volume(volume_type_id=type_ref.id,
|
||||
group_id=source_cg['id'])
|
||||
source_vols = [src_vol1, src_vol2]
|
||||
|
||||
cgsnapshot, snapshots = self._create_cgsnapshot(source_cg['id'])
|
||||
group_snapshot, snapshots = self._create_group_snapshot(
|
||||
source_cg['id'], group_type_id=cg_type_ref.id)
|
||||
|
||||
# Create cg from src with null input
|
||||
# Create group from src with null input
|
||||
self.assertRaises(exception.InvalidInput,
|
||||
self.driver.create_consistencygroup_from_src,
|
||||
self.ctxt, cg, volumes, None, None,
|
||||
self.driver.create_group_from_src,
|
||||
self.ctxt, group, volumes, None, None,
|
||||
None, None)
|
||||
|
||||
# Create cg from src with source_cg and empty source_vols
|
||||
self.assertRaises(exception.InvalidInput,
|
||||
self.driver.create_consistencygroup_from_src,
|
||||
self.ctxt, cg, volumes, None, None,
|
||||
self.driver.create_group_from_src,
|
||||
self.ctxt, group, volumes, None, None,
|
||||
source_cg, None)
|
||||
|
||||
# Create cg from src with source_vols and empty source_cg
|
||||
self.assertRaises(exception.InvalidInput,
|
||||
self.driver.create_consistencygroup_from_src,
|
||||
self.ctxt, cg, volumes, None, None,
|
||||
self.driver.create_group_from_src,
|
||||
self.ctxt, group, volumes, None, None,
|
||||
None, source_vols)
|
||||
|
||||
# Create cg from src with cgsnapshot and empty snapshots
|
||||
self.assertRaises(exception.InvalidInput,
|
||||
self.driver.create_consistencygroup_from_src,
|
||||
self.ctxt, cg, volumes, cgsnapshot, None,
|
||||
self.driver.create_group_from_src,
|
||||
self.ctxt, group, volumes, group_snapshot, None,
|
||||
None, None)
|
||||
# Create cg from src with snapshots and empty cgsnapshot
|
||||
self.assertRaises(exception.InvalidInput,
|
||||
self.driver.create_consistencygroup_from_src,
|
||||
self.ctxt, cg, volumes, None, snapshots,
|
||||
self.driver.create_group_from_src,
|
||||
self.ctxt, group, volumes, None, snapshots,
|
||||
None, None)
|
||||
|
||||
model_update = self.driver.delete_consistencygroup(self.ctxt,
|
||||
cg, volumes)
|
||||
model_update = self.driver.delete_group(self.ctxt, group, volumes)
|
||||
|
||||
self.assertEqual(fields.ConsistencyGroupStatus.DELETED,
|
||||
self.assertEqual(fields.GroupStatus.DELETED,
|
||||
model_update[0]['status'])
|
||||
for volume in model_update[1]:
|
||||
self.assertEqual('deleted', volume['status'])
|
||||
|
||||
model_update = (
|
||||
self.driver.delete_consistencygroup(self.ctxt,
|
||||
source_cg, source_vols))
|
||||
model_update = self.driver.delete_group(self.ctxt,
|
||||
source_cg, source_vols)
|
||||
|
||||
self.assertEqual(fields.ConsistencyGroupStatus.DELETED,
|
||||
self.assertEqual(fields.GroupStatus.DELETED,
|
||||
model_update[0]['status'])
|
||||
for volume in model_update[1]:
|
||||
self.assertEqual('deleted', volume['status'])
|
||||
|
||||
model_update = (
|
||||
self.driver.delete_consistencygroup(self.ctxt,
|
||||
cgsnapshot, snapshots))
|
||||
model_update = self.driver.delete_group(self.ctxt,
|
||||
group_snapshot, snapshots)
|
||||
|
||||
self.assertEqual(fields.ConsistencyGroupStatus.DELETED,
|
||||
self.assertEqual(fields.GroupStatus.DELETED,
|
||||
model_update[0]['status'])
|
||||
for volume in model_update[1]:
|
||||
self.assertEqual('deleted', volume['status'])
|
||||
|
||||
@mock.patch('oslo_service.loopingcall.FixedIntervalLoopingCall',
|
||||
new=testutils.ZeroIntervalLoopingCall)
|
||||
def test_storwize_consistency_group_from_src(self):
|
||||
def test_storwize_group_from_src(self):
|
||||
# Valid case for create cg from src
|
||||
cg_type = self._create_consistency_group_volume_type()
|
||||
self.ctxt.user_id = fake.USER_ID
|
||||
self.ctxt.project_id = fake.PROJECT_ID
|
||||
type_ref = volume_types.create(self.ctxt, 'testtype', None)
|
||||
spec = {'consistent_group_snapshot_enabled': '<is> True'}
|
||||
cg_type_ref = group_types.create(self.ctxt, 'cg_type', spec)
|
||||
pool = _get_test_pool()
|
||||
# Create cg in db
|
||||
cg = self._create_consistencygroup_in_db(volume_type_id=cg_type['id'])
|
||||
group = self._create_group_in_db(volume_type_id=type_ref.id,
|
||||
group_type_id=cg_type_ref.id)
|
||||
# Create volumes in db
|
||||
testutils.create_volume(self.ctxt, volume_type_id=cg_type['id'],
|
||||
consistencygroup_id=cg['id'],
|
||||
testutils.create_volume(self.ctxt, volume_type_id=type_ref.id,
|
||||
group_id=group.id,
|
||||
host='openstack@svc#%s' % pool)
|
||||
testutils.create_volume(self.ctxt, volume_type_id=cg_type['id'],
|
||||
consistencygroup_id=cg['id'],
|
||||
testutils.create_volume(self.ctxt, volume_type_id=type_ref.id,
|
||||
consistencygroup_id=group.id,
|
||||
host='openstack@svc#%s' % pool)
|
||||
volumes = (
|
||||
self.db.volume_get_all_by_group(self.ctxt.elevated(), cg['id']))
|
||||
volumes = self.db.volume_get_all_by_generic_group(
|
||||
self.ctxt.elevated(), group.id)
|
||||
|
||||
# Create source CG
|
||||
source_cg = self._create_consistencegroup(volume_type_id=cg_type['id'])
|
||||
source_cg = self._create_group_in_db(volume_type_id=type_ref.id,
|
||||
group_type_id=cg_type_ref.id)
|
||||
# Add volumes to source CG
|
||||
self._create_volume(volume_type_id=cg_type['id'],
|
||||
consistencygroup_id=source_cg['id'])
|
||||
self._create_volume(volume_type_id=cg_type['id'],
|
||||
consistencygroup_id=source_cg['id'])
|
||||
source_vols = self.db.volume_get_all_by_group(
|
||||
self._create_volume(volume_type_id=type_ref.id,
|
||||
group_id=source_cg['id'])
|
||||
self._create_volume(volume_type_id=type_ref.id,
|
||||
group_id=source_cg['id'])
|
||||
source_vols = self.db.volume_get_all_by_generic_group(
|
||||
self.ctxt.elevated(), source_cg['id'])
|
||||
|
||||
# Create cgsnapshot
|
||||
cgsnapshot, snapshots = self._create_cgsnapshot(source_cg['id'])
|
||||
group_snapshot, snapshots = self._create_group_snapshot(
|
||||
source_cg['id'], group_type_id=cg_type_ref.id)
|
||||
|
||||
# Create cg from source cg
|
||||
|
||||
model_update, volumes_model_update = (
|
||||
self.driver.create_consistencygroup_from_src(self.ctxt,
|
||||
cg,
|
||||
volumes,
|
||||
None, None,
|
||||
source_cg,
|
||||
source_vols))
|
||||
self.assertEqual(fields.ConsistencyGroupStatus.AVAILABLE,
|
||||
self.driver.create_group_from_src(self.ctxt, group, volumes, None,
|
||||
None, source_cg, source_vols))
|
||||
self.assertEqual(fields.GroupStatus.AVAILABLE,
|
||||
model_update['status'],
|
||||
"CG create from src created failed")
|
||||
|
||||
for each_vol in volumes_model_update:
|
||||
self.assertEqual('available', each_vol['status'])
|
||||
model_update = self.driver.delete_consistencygroup(self.ctxt,
|
||||
cg,
|
||||
volumes)
|
||||
|
||||
self.assertEqual(fields.ConsistencyGroupStatus.DELETED,
|
||||
model_update = self.driver.delete_group(self.ctxt, group, volumes)
|
||||
self.assertEqual(fields.GroupStatus.DELETED,
|
||||
model_update[0]['status'])
|
||||
for each_vol in model_update[1]:
|
||||
self.assertEqual('deleted', each_vol['status'])
|
||||
|
||||
# Create cg from cg snapshot
|
||||
model_update, volumes_model_update = (
|
||||
self.driver.create_consistencygroup_from_src(self.ctxt,
|
||||
cg,
|
||||
volumes,
|
||||
cgsnapshot,
|
||||
snapshots,
|
||||
None, None))
|
||||
self.assertEqual(fields.ConsistencyGroupStatus.AVAILABLE,
|
||||
self.driver.create_group_from_src(self.ctxt, group, volumes,
|
||||
group_snapshot, snapshots,
|
||||
None, None))
|
||||
self.assertEqual(fields.GroupStatus.AVAILABLE,
|
||||
model_update['status'],
|
||||
"CG create from src created failed")
|
||||
|
||||
for each_vol in volumes_model_update:
|
||||
self.assertEqual('available', each_vol['status'])
|
||||
|
||||
model_update = self.driver.delete_consistencygroup(self.ctxt,
|
||||
cg, volumes)
|
||||
|
||||
self.assertEqual(fields.ConsistencyGroupStatus.DELETED,
|
||||
model_update = self.driver.delete_group(self.ctxt, group, volumes)
|
||||
self.assertEqual(fields.GroupStatus.DELETED,
|
||||
model_update[0]['status'])
|
||||
for each_vol in model_update[1]:
|
||||
self.assertEqual('deleted', each_vol['status'])
|
||||
|
||||
model_update = self.driver.delete_consistencygroup(self.ctxt,
|
||||
cgsnapshot,
|
||||
snapshots)
|
||||
|
||||
self.assertEqual(fields.ConsistencyGroupStatus.DELETED,
|
||||
model_update = self.driver.delete_group_snapshot(self.ctxt,
|
||||
group_snapshot,
|
||||
snapshots)
|
||||
self.assertEqual(fields.GroupStatus.DELETED,
|
||||
model_update[0]['status'])
|
||||
for volume in model_update[1]:
|
||||
self.assertEqual('deleted', volume['status'])
|
||||
|
||||
model_update = self.driver.delete_consistencygroup(self.ctxt,
|
||||
source_cg,
|
||||
source_vols)
|
||||
|
||||
self.assertEqual(fields.ConsistencyGroupStatus.DELETED,
|
||||
model_update[0]['status'])
|
||||
for each_vol in model_update[1]:
|
||||
self.assertEqual('deleted', each_vol['status'])
|
||||
|
||||
def _create_volume_type_qos(self, extra_specs, fake_qos):
|
||||
# Generate a QoS volume type for volume.
|
||||
if extra_specs:
|
||||
@ -5871,27 +5933,20 @@ class StorwizeSVCReplicationTestCase(test.TestCase):
|
||||
is_vol_defined = self.driver._helpers.is_vdisk_defined(name)
|
||||
self.assertEqual(exists, is_vol_defined)
|
||||
|
||||
def _generate_vol_info(self, vol_name, vol_id, vol_type=None):
|
||||
def _generate_vol_info(self, vol_type=None, size=1):
|
||||
pool = _get_test_pool()
|
||||
rand_id = six.text_type(random.randint(10000, 99999))
|
||||
volume_type = self.non_replica_type
|
||||
if vol_type:
|
||||
volume_type = vol_type
|
||||
if vol_name:
|
||||
return {'name': 'snap_volume%s' % rand_id,
|
||||
'volume_name': vol_name,
|
||||
'id': rand_id,
|
||||
'volume_id': vol_id,
|
||||
'volume_size': 10,
|
||||
'mdisk_grp_name': pool}
|
||||
else:
|
||||
return {'name': 'test_volume%s' % rand_id,
|
||||
'size': 10,
|
||||
'id': '%s' % rand_id,
|
||||
'mdisk_grp_name': pool,
|
||||
'host': 'openstack@svc#%s' % pool,
|
||||
'volume_type_id': volume_type['id'],
|
||||
'volume_type': volume_type}
|
||||
volume_type = vol_type if vol_type else self.non_replica_type
|
||||
prop = {'size': size,
|
||||
'volume_type_id': volume_type.id,
|
||||
'host': 'openstack@svc#%s' % pool
|
||||
}
|
||||
vol = testutils.create_volume(self.ctxt, **prop)
|
||||
return vol
|
||||
|
||||
def _generate_snap_info(self, vol_id):
|
||||
prop = {'volume_id': vol_id}
|
||||
snap = testutils.create_snapshot(self.ctxt, **prop)
|
||||
return snap
|
||||
|
||||
def _create_replica_volume_type(self, enable,
|
||||
rep_type=storwize_const.METRO):
|
||||
@ -5910,8 +5965,7 @@ class StorwizeSVCReplicationTestCase(test.TestCase):
|
||||
type_name = "non_rep"
|
||||
|
||||
type_ref = volume_types.create(self.ctxt, type_name, spec)
|
||||
|
||||
replication_type = volume_types.get_volume_type(self.ctxt,
|
||||
replication_type = objects.VolumeType.get_by_id(self.ctxt,
|
||||
type_ref['id'])
|
||||
return replication_type
|
||||
|
||||
@ -5923,14 +5977,7 @@ class StorwizeSVCReplicationTestCase(test.TestCase):
|
||||
self.non_replica_type = self._create_replica_volume_type(False)
|
||||
|
||||
def _create_test_volume(self, rep_type):
|
||||
volume = self._generate_vol_info(None, None, rep_type)
|
||||
opts = {}
|
||||
for p in volume.keys():
|
||||
if p not in volume:
|
||||
opts[p] = volume[p]
|
||||
vol = testutils.create_volume(self.ctxt, **opts)
|
||||
volume['id'] = vol['id']
|
||||
volume['name'] = vol['name']
|
||||
volume = self._generate_vol_info(rep_type)
|
||||
model_update = self.driver.create_volume(volume)
|
||||
volume['status'] = 'available'
|
||||
return volume, model_update
|
||||
@ -6054,10 +6101,10 @@ class StorwizeSVCReplicationTestCase(test.TestCase):
|
||||
vol1, model_update = self._create_test_volume(self.mm_type)
|
||||
self.assertEqual('enabled', model_update['replication_status'])
|
||||
|
||||
snap = self._generate_vol_info(vol1['name'], vol1['id'])
|
||||
snap = testutils.create_snapshot(self.ctxt, vol1.id)
|
||||
self.driver.create_snapshot(snap)
|
||||
|
||||
vol2 = self._generate_vol_info(None, None, self.mm_type)
|
||||
vol2 = self._generate_vol_info(self.mm_type)
|
||||
model_update = self.driver.create_volume_from_snapshot(vol2, snap)
|
||||
self.assertEqual('enabled', model_update['replication_status'])
|
||||
self._validate_replic_vol_creation(vol2)
|
||||
@ -6076,7 +6123,7 @@ class StorwizeSVCReplicationTestCase(test.TestCase):
|
||||
src_volume, model_update = self._create_test_volume(self.mm_type)
|
||||
self.assertEqual('enabled', model_update['replication_status'])
|
||||
|
||||
volume = self._generate_vol_info(None, None, self.mm_type)
|
||||
volume = self._generate_vol_info(self.mm_type)
|
||||
|
||||
# Create a cloned volume from source volume.
|
||||
model_update = self.driver.create_cloned_volume(volume, src_volume)
|
||||
@ -6177,7 +6224,7 @@ class StorwizeSVCReplicationTestCase(test.TestCase):
|
||||
non_rep_volume, model_update = self._create_test_volume(
|
||||
self.non_replica_type)
|
||||
|
||||
new_volume = self._generate_vol_info(None, None)
|
||||
new_volume = self._generate_vol_info()
|
||||
|
||||
ref = {'source-name': rep_volume['name']}
|
||||
new_volume['volume_type_id'] = self.non_replica_type['id']
|
||||
@ -6213,7 +6260,7 @@ class StorwizeSVCReplicationTestCase(test.TestCase):
|
||||
uid_of_aux = self._get_vdisk_uid(
|
||||
storwize_const.REPLICA_AUX_VOL_PREFIX + rep_volume['name'])
|
||||
|
||||
new_volume = self._generate_vol_info(None, None)
|
||||
new_volume = self._generate_vol_info()
|
||||
ref = {'source-name': rep_volume['name']}
|
||||
new_volume['volume_type_id'] = self.mm_type['id']
|
||||
new_volume['volume_type'] = self.mm_type
|
||||
@ -6692,7 +6739,7 @@ class StorwizeSVCReplicationTestCase(test.TestCase):
|
||||
'start_relationship')
|
||||
def test_sync_replica_volumes_with_aux(self, start_relationship):
|
||||
# Create metro mirror replication.
|
||||
mm_vol = self._generate_vol_info(None, None, self.mm_type)
|
||||
mm_vol = self._generate_vol_info(self.mm_type)
|
||||
tgt_volume = storwize_const.REPLICA_AUX_VOL_PREFIX + mm_vol['name']
|
||||
|
||||
volumes = [mm_vol]
|
||||
@ -6741,7 +6788,7 @@ class StorwizeSVCReplicationTestCase(test.TestCase):
|
||||
new=testutils.ZeroIntervalLoopingCall)
|
||||
def test_wait_replica_vol_ready(self, get_relationship_info):
|
||||
# Create metro mirror replication.
|
||||
mm_vol = self._generate_vol_info(None, None, self.mm_type)
|
||||
mm_vol = self._generate_vol_info(self.mm_type)
|
||||
fake_info = {'volume': 'fake',
|
||||
'master_vdisk_name': 'fake',
|
||||
'aux_vdisk_name': 'fake',
|
||||
|
@ -1343,7 +1343,7 @@ class StorwizeHelpers(object):
|
||||
|
||||
def run_consistgrp_snapshots(self, fc_consistgrp, snapshots, state,
|
||||
config, timeout):
|
||||
model_update = {'status': fields.ConsistencyGroupStatus.AVAILABLE}
|
||||
model_update = {'status': fields.GroupSnapshotStatus.AVAILABLE}
|
||||
snapshots_model_update = []
|
||||
try:
|
||||
for snapshot in snapshots:
|
||||
@ -1362,7 +1362,7 @@ class StorwizeHelpers(object):
|
||||
# Cinder general will maintain the CG and snapshots relationship.
|
||||
self.delete_fc_consistgrp(fc_consistgrp)
|
||||
except exception.VolumeBackendAPIException as err:
|
||||
model_update['status'] = fields.ConsistencyGroupStatus.ERROR
|
||||
model_update['status'] = fields.GroupSnapshotStatus.ERROR
|
||||
# Release cg
|
||||
self.delete_fc_consistgrp(fc_consistgrp)
|
||||
LOG.error("Failed to create CGSnapshot. "
|
||||
@ -1377,7 +1377,7 @@ class StorwizeHelpers(object):
|
||||
|
||||
def delete_consistgrp_snapshots(self, fc_consistgrp, snapshots):
|
||||
"""Delete flashcopy maps and consistent group."""
|
||||
model_update = {'status': fields.ConsistencyGroupStatus.DELETED}
|
||||
model_update = {'status': fields.GroupSnapshotStatus.DELETED}
|
||||
snapshots_model_update = []
|
||||
|
||||
try:
|
||||
@ -1385,7 +1385,7 @@ class StorwizeHelpers(object):
|
||||
self.ssh.rmvdisk(snapshot['name'], True)
|
||||
except exception.VolumeBackendAPIException as err:
|
||||
model_update['status'] = (
|
||||
fields.ConsistencyGroupStatus.ERROR_DELETING)
|
||||
fields.GroupSnapshotStatus.ERROR_DELETING)
|
||||
LOG.error("Failed to delete the snapshot %(snap)s of "
|
||||
"CGSnapshot. Exception: %(exception)s.",
|
||||
{'snap': snapshot['name'], 'exception': err})
|
||||
@ -1429,7 +1429,7 @@ class StorwizeHelpers(object):
|
||||
LOG.debug('Enter: create_cg_from_source: cg %(cg)s'
|
||||
' source %(source)s, target %(target)s',
|
||||
{'cg': fc_consistgrp, 'source': sources, 'target': targets})
|
||||
model_update = {'status': fields.ConsistencyGroupStatus.AVAILABLE}
|
||||
model_update = {'status': fields.GroupStatus.AVAILABLE}
|
||||
ctxt = context.get_admin_context()
|
||||
try:
|
||||
for source, target in zip(sources, targets):
|
||||
@ -1447,7 +1447,7 @@ class StorwizeHelpers(object):
|
||||
volumes_model_update = self._get_volume_model_updates(
|
||||
ctxt, targets, group['id'], model_update['status'])
|
||||
except exception.VolumeBackendAPIException as err:
|
||||
model_update['status'] = fields.ConsistencyGroupStatus.ERROR
|
||||
model_update['status'] = fields.GroupStatus.ERROR
|
||||
volumes_model_update = self._get_volume_model_updates(
|
||||
ctxt, targets, group['id'], model_update['status'])
|
||||
with excutils.save_and_reraise_exception():
|
||||
@ -3065,13 +3065,13 @@ class StorwizeSVCCommonDriver(san.SanDriver,
|
||||
raise exception.InvalidInput(reason=msg)
|
||||
return replication_type
|
||||
|
||||
def _get_volume_replicated_type(self, ctxt, volume):
|
||||
def _get_volume_replicated_type(self, ctxt, volume, vol_type_id=None):
|
||||
replication_type = None
|
||||
if volume.get("volume_type_id"):
|
||||
volume_type = volume_types.get_volume_type(
|
||||
ctxt, volume["volume_type_id"])
|
||||
volume_type = (volume.volume_type if volume else
|
||||
objects.VolumeType.get_by_name_or_id(ctxt,
|
||||
vol_type_id))
|
||||
if volume_type:
|
||||
replication_type = self._get_specs_replicated_type(volume_type)
|
||||
|
||||
return replication_type
|
||||
|
||||
def _get_storwize_config(self):
|
||||
@ -3479,23 +3479,49 @@ class StorwizeSVCCommonDriver(san.SanDriver,
|
||||
|
||||
return self._stats
|
||||
|
||||
def create_consistencygroup(self, context, group):
|
||||
"""Create a consistency group.
|
||||
# Add CG capability to generic volume groups
|
||||
def create_group(self, context, group):
|
||||
"""Creates a group.
|
||||
|
||||
IBM Storwize will create CG until cg-snapshot creation,
|
||||
db will maintain the volumes and CG relationship.
|
||||
:param context: the context of the caller.
|
||||
:param group: the group object.
|
||||
:returns: model_update
|
||||
"""
|
||||
LOG.debug("Creating consistency group.")
|
||||
model_update = {'status': fields.ConsistencyGroupStatus.AVAILABLE}
|
||||
return model_update
|
||||
|
||||
def delete_consistencygroup(self, context, group, volumes):
|
||||
"""Deletes a consistency group.
|
||||
LOG.debug("Creating group.")
|
||||
model_update = {'status': fields.GroupStatus.AVAILABLE}
|
||||
|
||||
IBM Storwize will delete the volumes of the CG.
|
||||
for vol_type_id in group.volume_type_ids:
|
||||
replication_type = self._get_volume_replicated_type(
|
||||
context, None, vol_type_id)
|
||||
if replication_type:
|
||||
# An unsupported configuration
|
||||
LOG.error('Unable to create group: create group with '
|
||||
'replication volume type is not supported.')
|
||||
model_update = {'status': fields.GroupStatus.ERROR}
|
||||
return model_update
|
||||
|
||||
if utils.is_group_a_cg_snapshot_type(group):
|
||||
return {'status': fields.GroupStatus.AVAILABLE}
|
||||
# we'll rely on the generic group implementation if it is not a
|
||||
# consistency group request.
|
||||
raise NotImplementedError()
|
||||
|
||||
def delete_group(self, context, group, volumes):
|
||||
"""Deletes a group.
|
||||
|
||||
:param context: the context of the caller.
|
||||
:param group: the group object.
|
||||
:param volumes: a list of volume objects in the group.
|
||||
:returns: model_update, volumes_model_update
|
||||
"""
|
||||
LOG.debug("Deleting consistency group.")
|
||||
model_update = {'status': fields.ConsistencyGroupStatus.DELETED}
|
||||
LOG.debug("Deleting group.")
|
||||
if not utils.is_group_a_cg_snapshot_type(group):
|
||||
# we'll rely on the generic group implementation if it is
|
||||
# not a consistency group request.
|
||||
raise NotImplementedError()
|
||||
|
||||
model_update = {'status': fields.GroupStatus.DELETED}
|
||||
volumes_model_update = []
|
||||
|
||||
for volume in volumes:
|
||||
@ -3505,51 +3531,69 @@ class StorwizeSVCCommonDriver(san.SanDriver,
|
||||
{'id': volume['id'], 'status': 'deleted'})
|
||||
except exception.VolumeBackendAPIException as err:
|
||||
model_update['status'] = (
|
||||
fields.ConsistencyGroupStatus.ERROR_DELETING)
|
||||
fields.GroupStatus.ERROR_DELETING)
|
||||
LOG.error("Failed to delete the volume %(vol)s of CG. "
|
||||
"Exception: %(exception)s.",
|
||||
{'vol': volume['name'], 'exception': err})
|
||||
volumes_model_update.append(
|
||||
{'id': volume['id'], 'status': 'error_deleting'})
|
||||
{'id': volume['id'],
|
||||
'status': fields.GroupStatus.ERROR_DELETING})
|
||||
|
||||
return model_update, volumes_model_update
|
||||
|
||||
def update_consistencygroup(self, ctxt, group, add_volumes,
|
||||
remove_volumes):
|
||||
"""Adds or removes volume(s) to/from an existing consistency group."""
|
||||
|
||||
LOG.debug("Updating consistency group.")
|
||||
return None, None, None
|
||||
|
||||
def create_consistencygroup_from_src(self, context, group, volumes,
|
||||
cgsnapshot=None, snapshots=None,
|
||||
source_cg=None, source_vols=None):
|
||||
"""Creates a consistencygroup from source.
|
||||
def update_group(self, context, group, add_volumes=None,
|
||||
remove_volumes=None):
|
||||
"""Updates a group.
|
||||
|
||||
:param context: the context of the caller.
|
||||
:param group: the dictionary of the consistency group to be created.
|
||||
:param volumes: a list of volume dictionaries in the group.
|
||||
:param cgsnapshot: the dictionary of the cgsnapshot as source.
|
||||
:param snapshots: a list of snapshot dictionaries in the cgsnapshot.
|
||||
:param source_cg: the dictionary of a consistency group as source.
|
||||
:param source_vols: a list of volume dictionaries in the source_cg.
|
||||
:param group: the group object.
|
||||
:param add_volumes: a list of volume objects to be added.
|
||||
:param remove_volumes: a list of volume objects to be removed.
|
||||
:returns: model_update, add_volumes_update, remove_volumes_update
|
||||
"""
|
||||
|
||||
LOG.debug("Updating group.")
|
||||
if utils.is_group_a_cg_snapshot_type(group):
|
||||
return None, None, None
|
||||
|
||||
# we'll rely on the generic group implementation if it is not a
|
||||
# consistency group request.
|
||||
raise NotImplementedError()
|
||||
|
||||
def create_group_from_src(self, context, group, volumes,
|
||||
group_snapshot=None, snapshots=None,
|
||||
source_group=None, source_vols=None):
|
||||
"""Creates a group from source.
|
||||
|
||||
:param context: the context of the caller.
|
||||
:param group: the Group object to be created.
|
||||
:param volumes: a list of Volume objects in the group.
|
||||
:param group_snapshot: the GroupSnapshot object as source.
|
||||
:param snapshots: a list of snapshot objects in group_snapshot.
|
||||
:param source_group: the Group object as source.
|
||||
:param source_vols: a list of volume objects in the source_group.
|
||||
:returns: model_update, volumes_model_update
|
||||
"""
|
||||
LOG.debug('Enter: create_consistencygroup_from_src.')
|
||||
if cgsnapshot and snapshots:
|
||||
cg_name = 'cg-' + cgsnapshot.id
|
||||
LOG.debug('Enter: create_group_from_src.')
|
||||
if not utils.is_group_a_cg_snapshot_type(group):
|
||||
# we'll rely on the generic volume groups implementation if it is
|
||||
# not a consistency group request.
|
||||
raise NotImplementedError()
|
||||
|
||||
if group_snapshot and snapshots:
|
||||
cg_name = 'cg-' + group_snapshot.id
|
||||
sources = snapshots
|
||||
|
||||
elif source_cg and source_vols:
|
||||
cg_name = 'cg-' + source_cg.id
|
||||
elif source_group and source_vols:
|
||||
cg_name = 'cg-' + source_group.id
|
||||
sources = source_vols
|
||||
|
||||
else:
|
||||
error_msg = _("create_consistencygroup_from_src must be "
|
||||
"creating from a CG snapshot, or a source CG.")
|
||||
error_msg = _("create_group_from_src must be creating from a "
|
||||
"group snapshot, or a source group.")
|
||||
raise exception.InvalidInput(reason=error_msg)
|
||||
|
||||
LOG.debug('create_consistencygroup_from_src: cg_name %(cg_name)s'
|
||||
LOG.debug('create_group_from_src: cg_name %(cg_name)s'
|
||||
' %(sources)s', {'cg_name': cg_name, 'sources': sources})
|
||||
self._helpers.create_fc_consistgrp(cg_name)
|
||||
timeout = self.configuration.storwize_svc_flashcopy_timeout
|
||||
@ -3561,13 +3605,24 @@ class StorwizeSVCCommonDriver(san.SanDriver,
|
||||
self._state,
|
||||
self.configuration,
|
||||
timeout))
|
||||
LOG.debug("Leave: create_consistencygroup_from_src.")
|
||||
LOG.debug("Leave: create_group_from_src.")
|
||||
return model_update, snapshots_model
|
||||
|
||||
def create_cgsnapshot(self, ctxt, cgsnapshot, snapshots):
|
||||
"""Creates a cgsnapshot."""
|
||||
# Use cgsnapshot id as cg name
|
||||
cg_name = 'cg_snap-' + cgsnapshot.id
|
||||
def create_group_snapshot(self, context, group_snapshot, snapshots):
|
||||
"""Creates a group_snapshot.
|
||||
|
||||
:param context: the context of the caller.
|
||||
:param group_snapshot: the GroupSnapshot object to be created.
|
||||
:param snapshots: a list of Snapshot objects in the group_snapshot.
|
||||
:returns: model_update, snapshots_model_update
|
||||
"""
|
||||
if not utils.is_group_a_cg_snapshot_type(group_snapshot):
|
||||
# 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
|
||||
self._helpers.create_fc_consistgrp(cg_name)
|
||||
|
||||
@ -3582,9 +3637,21 @@ class StorwizeSVCCommonDriver(san.SanDriver,
|
||||
|
||||
return model_update, snapshots_model
|
||||
|
||||
def delete_cgsnapshot(self, context, cgsnapshot, snapshots):
|
||||
"""Deletes a cgsnapshot."""
|
||||
cgsnapshot_id = cgsnapshot['id']
|
||||
def delete_group_snapshot(self, context, group_snapshot, snapshots):
|
||||
"""Deletes a group_snapshot.
|
||||
|
||||
:param context: the context of the caller.
|
||||
:param group_snapshot: the GroupSnapshot object to be deleted.
|
||||
:param snapshots: a list of snapshot objects in the group_snapshot.
|
||||
:returns: model_update, snapshots_model_update
|
||||
"""
|
||||
|
||||
if not utils.is_group_a_cg_snapshot_type(group_snapshot):
|
||||
# we'll rely on the generic group implementation if it is not a
|
||||
# consistency group request.
|
||||
raise NotImplementedError()
|
||||
|
||||
cgsnapshot_id = group_snapshot.id
|
||||
cg_name = 'cg_snap-' + cgsnapshot_id
|
||||
|
||||
model_update, snapshots_model = (
|
||||
@ -3671,6 +3738,7 @@ class StorwizeSVCCommonDriver(san.SanDriver,
|
||||
'thin_provisioning_support': not use_thick_provisioning,
|
||||
'thick_provisioning_support': use_thick_provisioning,
|
||||
'max_over_subscription_ratio': over_sub_ratio,
|
||||
'consistent_group_snapshot_enabled': True,
|
||||
}
|
||||
if self._replica_enabled:
|
||||
pool_stats.update({
|
||||
|
@ -88,9 +88,10 @@ class StorwizeSVCFCDriver(storwize_common.StorwizeSVCCommonDriver):
|
||||
2.1 - Added replication V2 support to the global/metro mirror
|
||||
mode
|
||||
2.1.1 - Update replication to version 2.1
|
||||
2.2 - Add CG capability to generic volume groups
|
||||
"""
|
||||
|
||||
VERSION = "2.1.1"
|
||||
VERSION = "2.2"
|
||||
|
||||
# ThirdPartySystems wiki page
|
||||
CI_WIKI_NAME = "IBM_STORAGE_CI"
|
||||
|
@ -88,9 +88,10 @@ class StorwizeSVCISCSIDriver(storwize_common.StorwizeSVCCommonDriver):
|
||||
2.1 - Added replication V2 support to the global/metro mirror
|
||||
mode
|
||||
2.1.1 - Update replication to version 2.1
|
||||
2.2 - Add CG capability to generic volume groups
|
||||
"""
|
||||
|
||||
VERSION = "2.1.1"
|
||||
VERSION = "2.2"
|
||||
|
||||
# ThirdPartySystems wiki page
|
||||
CI_WIKI_NAME = "IBM_STORAGE_CI"
|
||||
|
@ -0,0 +1,4 @@
|
||||
---
|
||||
features:
|
||||
- Add consistency group capability to generic volume groups in Storwize
|
||||
drivers.
|
Loading…
Reference in New Issue
Block a user