IBM storage: switch to generic volume group

For Pike, IBM storage driver needs to switch to generic volume group
from consistency group. Because IBM storage driver manages both
Spectrum Accelerate Family and DS8000 Family, this change will only
change the common code shared by these storages. Changes for these
storage systems will be in separate reviews.

Implements: blueprint ibm-storage-vg

Change-Id: Id9964f868c2dc14aaee37e4bcbba330fb4575492
This commit is contained in:
Jia Min 2017-03-15 03:04:05 -07:00
parent 180d8fe931
commit f22a4a3625
2 changed files with 165 additions and 178 deletions

View File

@ -33,7 +33,7 @@ FAKE2 = "fake2"
CANNOT_DELETE = "Can not delete" CANNOT_DELETE = "Can not delete"
TOO_BIG_VOLUME_SIZE = 12000 TOO_BIG_VOLUME_SIZE = 12000
POOL_SIZE = 100 POOL_SIZE = 100
CONSISTGROUP_ID = 1 GROUP_ID = 1
VOLUME = {'size': 16, VOLUME = {'size': 16,
'name': FAKE, 'name': FAKE,
'id': 1, 'id': 1,
@ -42,10 +42,10 @@ VOLUME2 = {'size': 32,
'name': FAKE2, 'name': FAKE2,
'id': 2, 'id': 2,
'status': 'available'} 'status': 'available'}
CG_VOLUME = {'size': 16, GROUP_VOLUME = {'size': 16,
'name': FAKE, 'name': FAKE,
'id': 3, 'id': 3,
'consistencygroup_id': CONSISTGROUP_ID, 'group_id': GROUP_ID,
'status': 'available'} 'status': 'available'}
MANAGED_FAKE = "managed_fake" MANAGED_FAKE = "managed_fake"
@ -70,10 +70,10 @@ FAKESNAPSHOT = 'fakesnapshot'
SNAPSHOT = {'name': 'fakesnapshot', SNAPSHOT = {'name': 'fakesnapshot',
'id': 3} 'id': 3}
CONSISTGROUP = {'id': CONSISTGROUP_ID, } GROUP = {'id': GROUP_ID, }
CG_SNAPSHOT_ID = 1 GROUP_SNAPSHOT_ID = 1
CG_SNAPSHOT = {'id': CG_SNAPSHOT_ID, GROUP_SNAPSHOT = {'id': GROUP_SNAPSHOT_ID,
'consistencygroup_id': CONSISTGROUP_ID} 'group_id': GROUP_ID}
CONNECTOR = {'initiator': "iqn.2012-07.org.fake:01:948f189c4695", } CONNECTOR = {'initiator': "iqn.2012-07.org.fake:01:948f189c4695", }
@ -182,21 +182,20 @@ class IBMStorageFakeProxyDriver(object):
volume['easytier'] = new_type['extra_specs']['easytier'] volume['easytier'] = new_type['extra_specs']['easytier']
return True, volume return True, volume
def create_consistencygroup(self, ctxt, group): def create_group(self, ctxt, group):
volumes = [volume for k, volume in self.volumes.items() volumes = [volume for k, volume in self.volumes.items()
if volume['consistencygroup_id'] == group['id']] if volume['group_id'] == group['id']]
if volumes: if volumes:
raise exception.CinderException( raise exception.CinderException(
message='The consistency group id of volume may be wrong.') message='The group id of volume may be wrong.')
return {'status': fields.ConsistencyGroupStatus.AVAILABLE} return {'status': fields.GroupStatus.AVAILABLE}
def delete_consistencygroup(self, ctxt, group, volumes): def delete_group(self, ctxt, group, volumes):
for volume in self.volumes.values(): for volume in self.volumes.values():
if (group.get('id', None) if group.get('id') == volume.get('group_id'):
== volume.get('consistencygroup_id', None)):
if volume['name'] == CANNOT_DELETE: if volume['name'] == CANNOT_DELETE:
raise exception.VolumeBackendAPIException( raise exception.VolumeBackendAPIException(
message='Volume can not be deleted') message='Volume can not be deleted')
@ -204,53 +203,44 @@ class IBMStorageFakeProxyDriver(object):
volume['status'] = 'deleted' volume['status'] = 'deleted'
volumes.append(volume) volumes.append(volume)
# Delete snapshots in consistency group # Delete snapshots in group
self.snapshots = {k: snap for k, snap in self.snapshots.items() self.snapshots = {k: snap for k, snap in self.snapshots.items()
if not(snap.get('consistencygroup_id', None) if not(snap.get('group_id') == group.get('id'))}
== group.get('id', None))}
# Delete volume in consistency group # Delete volume in group
self.volumes = {k: vol for k, vol in self.volumes.items() self.volumes = {k: vol for k, vol in self.volumes.items()
if not(vol.get('consistencygroup_id', None) if not(vol.get('group_id') == group.get('id'))}
== group.get('id', None))}
return {'status': 'deleted'}, volumes return {'status': fields.GroupStatus.DELETED}, volumes
def update_consistencygroup( def update_group(self, context, group, add_volumes, remove_volumes):
self, context, group, model_update = {'status': fields.GroupStatus.AVAILABLE}
add_volumes, remove_volumes):
model_update = {'status': fields.ConsistencyGroupStatus.AVAILABLE}
return model_update, None, None return model_update, None, None
def create_consistencygroup_from_src( def create_group_from_src(self, context, group, volumes, group_snapshot,
self, context, group, volumes, cgsnapshot, snapshots, snapshots, source_group=None, source_vols=None):
source_cg=None, source_vols=None):
return None, None return None, None
def create_cgsnapshot(self, ctxt, cgsnapshot, snapshots): def create_group_snapshot(self, ctxt, group_snapshot, snapshots):
for volume in self.volumes.values(): for volume in self.volumes.values():
if (cgsnapshot.get('consistencygroup_id', None) if group_snapshot.get('group_id') == volume.get('group_id'):
== volume.get('consistencygroup_id', None)):
if volume['size'] > POOL_SIZE / 2: if volume['size'] > POOL_SIZE / 2:
raise self.exception.VolumeBackendAPIException(data='blah') raise self.exception.VolumeBackendAPIException(data='blah')
snapshot = copy.deepcopy(volume) snapshot = copy.deepcopy(volume)
snapshot['name'] = CANNOT_DELETE \ snapshot['name'] = (
if snapshot['name'] == CANNOT_DELETE \ CANNOT_DELETE if snapshot['name'] == CANNOT_DELETE
else snapshot['name'] + 'Snapshot' else snapshot['name'] + 'Snapshot')
snapshot['status'] = 'available' snapshot['status'] = 'available'
snapshot['cgsnapshot_id'] = cgsnapshot.get('id', None) snapshot['group_snapshot_id'] = group_snapshot.get('id')
snapshot['consistencygroup_id'] = \ snapshot['group_id'] = group_snapshot.get('group_id')
cgsnapshot.get('consistencygroup_id', None)
self.snapshots[snapshot['name']] = snapshot self.snapshots[snapshot['name']] = snapshot
snapshots.append(snapshot) snapshots.append(snapshot)
return {'status': 'available'}, snapshots return {'status': fields.GroupSnapshotStatus.AVAILABLE}, snapshots
def delete_cgsnapshot(self, ctxt, cgsnapshot, snapshots): def delete_group_snapshot(self, ctxt, group_snapshot, snapshots):
updated_snapshots = [] updated_snapshots = []
for snapshot in snapshots: for snapshot in snapshots:
if snapshot['name'] == CANNOT_DELETE: if snapshot['name'] == CANNOT_DELETE:
@ -260,10 +250,10 @@ class IBMStorageFakeProxyDriver(object):
snapshot['status'] = 'deleted' snapshot['status'] = 'deleted'
updated_snapshots.append(snapshot) updated_snapshots.append(snapshot)
# Delete snapshots in consistency group # Delete snapshots in group
self.snapshots = {k: snap for k, snap in self.snapshots.items() self.snapshots = {k: snap for k, snap in self.snapshots.items()
if not(snap.get('consistencygroup_id', None) if not(snap.get('group_id')
== cgsnapshot.get('cgsnapshot_id', None))} == group_snapshot.get('group_snapshot_id'))}
return {'status': 'deleted'}, updated_snapshots return {'status': 'deleted'}, updated_snapshots
@ -587,272 +577,271 @@ class IBMStorageVolumeDriverTest(test.TestCase):
ctxt, volume, new_type, diff, host ctxt, volume, new_type, diff, host
) )
def test_create_consistencygroup(self): def test_create_group(self):
"""Test that create_consistencygroup return successfully.""" """Test that create_group return successfully."""
self.driver.do_setup(None) self.driver.do_setup(None)
ctxt = context.get_admin_context() ctxt = context.get_admin_context()
# Create consistency group # Create group
model_update = self.driver.create_consistencygroup(ctxt, CONSISTGROUP) model_update = self.driver.create_group(ctxt, GROUP)
self.assertEqual(fields.ConsistencyGroupStatus.AVAILABLE, self.assertEqual(fields.GroupStatus.AVAILABLE,
model_update['status'], model_update['status'],
"Consistency Group created failed") "Group created failed")
def test_create_consistencygroup_fail_on_cg_not_empty(self): def test_create_group_fail_on_group_not_empty(self):
"""Test create_consistencygroup with empty consistency group.""" """Test create_group with empty group."""
self.driver.do_setup(None) self.driver.do_setup(None)
ctxt = context.get_admin_context() ctxt = context.get_admin_context()
# Create volumes # Create volumes
# And add the volumes into the consistency group before creating cg # And add the volumes into the group before creating group
self.driver.create_volume(CG_VOLUME) self.driver.create_volume(GROUP_VOLUME)
self.assertRaises(exception.CinderException, self.assertRaises(exception.CinderException,
self.driver.create_consistencygroup, self.driver.create_group,
ctxt, CONSISTGROUP) ctxt, GROUP)
def test_delete_consistencygroup(self): def test_delete_group(self):
"""Test that delete_consistencygroup return successfully.""" """Test that delete_group return successfully."""
self.driver.do_setup(None) self.driver.do_setup(None)
ctxt = context.get_admin_context() ctxt = context.get_admin_context()
# Create consistency group # Create group
self.driver.create_consistencygroup(ctxt, CONSISTGROUP) self.driver.create_group(ctxt, GROUP)
# Create volumes and add them to consistency group # Create volumes and add them to group
self.driver.create_volume(CG_VOLUME) self.driver.create_volume(GROUP_VOLUME)
# Delete consistency group # Delete group
model_update, volumes = \ model_update, volumes = self.driver.delete_group(ctxt, GROUP,
self.driver.delete_consistencygroup( [GROUP_VOLUME])
ctxt, CONSISTGROUP, [CG_VOLUME])
# Verify the result # Verify the result
self.assertEqual(fields.ConsistencyGroupStatus.DELETED, self.assertEqual(fields.GroupStatus.DELETED,
model_update['status'], model_update['status'],
'Consistency Group deleted failed') 'Group deleted failed')
for volume in volumes: for volume in volumes:
self.assertEqual('deleted', self.assertEqual('deleted',
volume['status'], volume['status'],
'Consistency Group deleted failed') 'Group deleted failed')
def test_delete_consistencygroup_fail_on_volume_not_delete(self): def test_delete_group_fail_on_volume_not_delete(self):
"""Test delete_consistencygroup with volume delete failure.""" """Test delete_group with volume delete failure."""
self.driver.do_setup(None) self.driver.do_setup(None)
ctxt = context.get_admin_context() ctxt = context.get_admin_context()
# Create consistency group # Create group
self.driver.create_consistencygroup(ctxt, CONSISTGROUP) self.driver.create_group(ctxt, GROUP)
# Set the volume not to be deleted # Set the volume not to be deleted
volume = copy.deepcopy(CG_VOLUME) volume = copy.deepcopy(GROUP_VOLUME)
volume['name'] = CANNOT_DELETE volume['name'] = CANNOT_DELETE
# Create volumes and add them to consistency group # Create volumes and add them to group
self.driver.create_volume(volume) self.driver.create_volume(volume)
self.assertRaises(exception.VolumeBackendAPIException, self.assertRaises(exception.VolumeBackendAPIException,
self.driver.delete_consistencygroup, self.driver.delete_group,
ctxt, CONSISTGROUP, [volume]) ctxt, GROUP, [volume])
def test_create_cgsnapshot(self): def test_create_group_snapshot(self):
"""Test that create_cgsnapshot return successfully.""" """Test that create_group_snapshot return successfully."""
self.driver.do_setup(None) self.driver.do_setup(None)
ctxt = context.get_admin_context() ctxt = context.get_admin_context()
# Create consistency group # Create group
self.driver.create_consistencygroup(ctxt, CONSISTGROUP) self.driver.create_group(ctxt, GROUP)
# Create volumes and add them to consistency group # Create volumes and add them to group
self.driver.create_volume(VOLUME) self.driver.create_volume(VOLUME)
# Create consistency group snapshot # Create group snapshot
model_update, snapshots = \ model_update, snapshots = self.driver.create_group_snapshot(
self.driver.create_cgsnapshot(ctxt, CG_SNAPSHOT, [VOLUME]) ctxt, GROUP_SNAPSHOT, [VOLUME])
# Verify the result # Verify the result
self.assertEqual('available', self.assertEqual(fields.GroupSnapshotStatus.AVAILABLE,
model_update['status'], model_update['status'],
'Consistency Group Snapshot created failed') 'Group Snapshot created failed')
for snap in snapshots: for snap in snapshots:
self.assertEqual('available', self.assertEqual('available',
snap['status']) snap['status'])
# Clean the environment # Clean the environment
self.driver.delete_cgsnapshot(ctxt, CG_SNAPSHOT, [VOLUME]) self.driver.delete_group_snapshot(ctxt, GROUP_SNAPSHOT, [VOLUME])
self.driver.delete_consistencygroup(ctxt, CONSISTGROUP, [VOLUME]) self.driver.delete_group(ctxt, GROUP, [VOLUME])
def test_create_cgsnapshot_fail_on_no_pool_space_left(self): def test_create_group_snapshot_fail_on_no_pool_space_left(self):
"""Test that create_cgsnapshot return fail when no pool space left.""" """Test create_group_snapshot when no pool space left."""
self.driver.do_setup(None) self.driver.do_setup(None)
ctxt = context.get_admin_context() ctxt = context.get_admin_context()
# Create consistency group # Create group
self.driver.create_consistencygroup(ctxt, CONSISTGROUP) self.driver.create_group(ctxt, GROUP)
# Set the volume size # Set the volume size
volume = copy.deepcopy(CG_VOLUME) volume = copy.deepcopy(GROUP_VOLUME)
volume['size'] = POOL_SIZE / 2 + 1 volume['size'] = POOL_SIZE / 2 + 1
# Create volumes and add them to consistency group # Create volumes and add them to group
self.driver.create_volume(volume) self.driver.create_volume(volume)
self.assertRaises(exception.VolumeBackendAPIException, self.assertRaises(exception.VolumeBackendAPIException,
self.driver.create_cgsnapshot, self.driver.create_group_snapshot,
ctxt, CG_SNAPSHOT, [volume]) ctxt, GROUP_SNAPSHOT, [volume])
# Clean the environment # Clean the environment
self.driver.volumes = None self.driver.volumes = None
self.driver.delete_consistencygroup(ctxt, CONSISTGROUP, [volume]) self.driver.delete_group(ctxt, GROUP, [volume])
def test_delete_cgsnapshot(self): def test_delete_group_snapshot(self):
"""Test that delete_cgsnapshot return successfully.""" """Test that delete_group_snapshot return successfully."""
self.driver.do_setup(None) self.driver.do_setup(None)
ctxt = context.get_admin_context() ctxt = context.get_admin_context()
# Create consistency group # Create group
self.driver.create_consistencygroup(ctxt, CONSISTGROUP) self.driver.create_group(ctxt, GROUP)
# Create volumes and add them to consistency group # Create volumes and add them to group
self.driver.create_volume(CG_VOLUME) self.driver.create_volume(GROUP_VOLUME)
# Create consistency group snapshot # Create group snapshot
self.driver.create_cgsnapshot(ctxt, CG_SNAPSHOT, [CG_VOLUME]) self.driver.create_group_snapshot(ctxt, GROUP_SNAPSHOT, [GROUP_VOLUME])
# Delete consistency group snapshot # Delete group snapshot
model_update, snapshots = \ model_update, snapshots = self.driver.delete_group_snapshot(
self.driver.delete_cgsnapshot(ctxt, CG_SNAPSHOT, [CG_VOLUME]) ctxt, GROUP_SNAPSHOT, [GROUP_VOLUME])
# Verify the result # Verify the result
self.assertEqual('deleted', self.assertEqual(fields.GroupSnapshotStatus.DELETED,
model_update['status'], model_update['status'],
'Consistency Group Snapshot deleted failed') 'Group Snapshot deleted failed')
for snap in snapshots: for snap in snapshots:
self.assertEqual('deleted', self.assertEqual('deleted',
snap['status']) snap['status'])
# Clean the environment # Clean the environment
self.driver.delete_consistencygroup(ctxt, CONSISTGROUP, [CG_VOLUME]) self.driver.delete_group(ctxt, GROUP, [GROUP_VOLUME])
def test_delete_cgsnapshot_fail_on_snapshot_not_delete(self): def test_delete_group_snapshot_fail_on_snapshot_not_delete(self):
"""Test delete_cgsnapshot when the snapshot cannot be deleted.""" """Test delete_group_snapshot when the snapshot cannot be deleted."""
self.driver.do_setup(None) self.driver.do_setup(None)
ctxt = context.get_admin_context() ctxt = context.get_admin_context()
# Create consistency group # Create group
self.driver.create_consistencygroup(ctxt, CONSISTGROUP) self.driver.create_group(ctxt, GROUP)
# Set the snapshot not to be deleted # Set the snapshot not to be deleted
volume = copy.deepcopy(CG_VOLUME) volume = copy.deepcopy(GROUP_VOLUME)
volume['name'] = CANNOT_DELETE volume['name'] = CANNOT_DELETE
# Create volumes and add them to consistency group # Create volumes and add them to group
self.driver.create_volume(volume) self.driver.create_volume(volume)
# Create consistency group snapshot # Create group snapshot
self.driver.create_cgsnapshot(ctxt, CG_SNAPSHOT, [volume]) self.driver.create_group_snapshot(ctxt, GROUP_SNAPSHOT, [volume])
self.assertRaises(exception.VolumeBackendAPIException, self.assertRaises(exception.VolumeBackendAPIException,
self.driver.delete_cgsnapshot, self.driver.delete_group_snapshot,
ctxt, CG_SNAPSHOT, [volume]) ctxt, GROUP_SNAPSHOT, [volume])
def test_update_consistencygroup_without_volumes(self): def test_update_group_without_volumes(self):
"""Test update_consistencygroup when there are no volumes specified.""" """Test update_group when there are no volumes specified."""
self.driver.do_setup(None) self.driver.do_setup(None)
ctxt = context.get_admin_context() ctxt = context.get_admin_context()
# Update consistency group # Update group
model_update, added, removed = self.driver.update_consistencygroup( model_update, added, removed = self.driver.update_group(
ctxt, CONSISTGROUP, [], []) ctxt, GROUP, [], [])
self.assertEqual(fields.ConsistencyGroupStatus.AVAILABLE, self.assertEqual(fields.GroupStatus.AVAILABLE,
model_update['status'], model_update['status'],
"Consistency Group update failed") "Group update failed")
self.assertIsNone(added, self.assertIsNone(added,
"added volumes list is not empty") "added volumes list is not empty")
self.assertIsNone(removed, self.assertIsNone(removed,
"removed volumes list is not empty") "removed volumes list is not empty")
def test_update_consistencygroup_with_volumes(self): def test_update_group_with_volumes(self):
"""Test update_consistencygroup when there are volumes specified.""" """Test update_group when there are volumes specified."""
self.driver.do_setup(None) self.driver.do_setup(None)
ctxt = context.get_admin_context() ctxt = context.get_admin_context()
# Update consistency group # Update group
model_update, added, removed = self.driver.update_consistencygroup( model_update, added, removed = self.driver.update_group(
ctxt, CONSISTGROUP, [VOLUME], [VOLUME2]) ctxt, GROUP, [VOLUME], [VOLUME2])
self.assertEqual(fields.ConsistencyGroupStatus.AVAILABLE, self.assertEqual(fields.GroupStatus.AVAILABLE,
model_update['status'], model_update['status'],
"Consistency Group update failed") "Group update failed")
self.assertIsNone(added, self.assertIsNone(added,
"added volumes list is not empty") "added volumes list is not empty")
self.assertIsNone(removed, self.assertIsNone(removed,
"removed volumes list is not empty") "removed volumes list is not empty")
def test_create_consistencygroup_from_src_without_volumes(self): def test_create_group_from_src_without_volumes(self):
"""Test create_consistencygroup_from_src with no volumes specified.""" """Test create_group_from_src with no volumes specified."""
self.driver.do_setup(None) self.driver.do_setup(None)
ctxt = context.get_admin_context() ctxt = context.get_admin_context()
# Create consistency group from source # Create group from source
model_update, volumes_model_update = ( model_update, volumes_model_update = (
self.driver.create_consistencygroup_from_src( self.driver.create_group_from_src(
ctxt, CONSISTGROUP, [], CG_SNAPSHOT, [])) ctxt, GROUP, [], GROUP_SNAPSHOT, []))
# model_update can be None or return available in status # model_update can be None or return available in status
if model_update: if model_update:
self.assertEqual(fields.ConsistencyGroupStatus.AVAILABLE, self.assertEqual(fields.GroupStatus.AVAILABLE,
model_update['status'], model_update['status'],
"Consistency Group create from source failed") "Group create from source failed")
# volumes_model_update can be None or return available in status # volumes_model_update can be None or return available in status
if volumes_model_update: if volumes_model_update:
self.assertFalse(volumes_model_update, self.assertFalse(volumes_model_update,
"volumes list is not empty") "volumes list is not empty")
def test_create_consistencygroup_from_src_with_volumes(self): def test_create_group_from_src_with_volumes(self):
"""Test create_consistencygroup_from_src with volumes specified.""" """Test create_group_from_src with volumes specified."""
self.driver.do_setup(None) self.driver.do_setup(None)
ctxt = context.get_admin_context() ctxt = context.get_admin_context()
# Create consistency group from source # Create group from source
model_update, volumes_model_update = ( model_update, volumes_model_update = (
self.driver.create_consistencygroup_from_src( self.driver.create_group_from_src(
ctxt, CONSISTGROUP, [VOLUME], CG_SNAPSHOT, [SNAPSHOT])) ctxt, GROUP, [VOLUME], GROUP_SNAPSHOT, [SNAPSHOT]))
# model_update can be None or return available in status # model_update can be None or return available in status
if model_update: if model_update:
self.assertEqual(fields.ConsistencyGroupStatus.AVAILABLE, self.assertEqual(fields.GroupStatus.AVAILABLE,
model_update['status'], model_update['status'],
"Consistency Group create from source failed") "Group create from source failed")
# volumes_model_update can be None or return available in status # volumes_model_update can be None or return available in status
if volumes_model_update: if volumes_model_update:
self.assertEqual('available', self.assertEqual(fields.GroupStatus.AVAILABLE,
volumes_model_update['status'], volumes_model_update['status'],
"volumes list status failed") "volumes list status failed")

View File

@ -223,41 +223,39 @@ class IBMStorageDriver(san.SanDriver,
return self.proxy.retype(ctxt, volume, new_type, diff, host) return self.proxy.retype(ctxt, volume, new_type, diff, host)
def create_consistencygroup(self, context, group): def create_group(self, context, group):
"""Creates a consistency group.""" """Creates a group."""
return self.proxy.create_consistencygroup(context, group) return self.proxy.create_group(context, group)
def delete_consistencygroup(self, context, group, volumes): def delete_group(self, context, group, volumes):
"""Deletes a consistency group.""" """Deletes a group."""
return self.proxy.delete_consistencygroup( return self.proxy.delete_group(context, group, volumes)
context, group, volumes)
def create_cgsnapshot(self, context, cgsnapshot, snapshots): def create_group_snapshot(self, context, group_snapshot, snapshots):
"""Creates a consistency group snapshot.""" """Creates a group snapshot."""
return self.proxy.create_cgsnapshot( return self.proxy.create_group_snapshot(
context, cgsnapshot, snapshots) context, group_snapshot, snapshots)
def delete_cgsnapshot(self, context, cgsnapshot, snapshots): def delete_group_snapshot(self, context, group_snapshot, snapshots):
"""Deletes a consistency group snapshot.""" """Deletes a group snapshot."""
return self.proxy.delete_cgsnapshot( return self.proxy.delete_group_snapshot(
context, cgsnapshot, snapshots) context, group_snapshot, snapshots)
def update_consistencygroup(self, context, group, def update_group(self, context, group, add_volumes, remove_volumes):
add_volumes, remove_volumes): """Adds or removes volume(s) to/from an existing group."""
"""Adds or removes volume(s) to/from an existing consistency group."""
return self.proxy.update_consistencygroup( return self.proxy.update_group(
context, group, add_volumes, remove_volumes) context, group, add_volumes, remove_volumes)
def create_consistencygroup_from_src( def create_group_from_src(
self, context, group, volumes, cgsnapshot, snapshots, self, context, group, volumes, group_snapshot, snapshots,
source_cg=None, source_vols=None): source_cg=None, source_vols=None):
"""Creates a consistencygroup from source.""" """Creates a group from source."""
return self.proxy.create_consistencygroup_from_src( return self.proxy.create_group_from_src(
context, group, volumes, cgsnapshot, snapshots, context, group, volumes, group_snapshot, snapshots,
source_cg, source_vols) source_cg, source_vols)