CLI: Clone CG

This patch adds support for clone CG in cinderclient. It uses the
existing create CG from source command and adds an existing CG as a
source, in addition to a CG snapshot.

The server side patch is merged: https://review.openstack.org/#/c/203473/

Change-Id: I2a923de42348c22c6ae5ff5880cdbe6d719ea0ae
Partial-implements: blueprint clone-cg
This commit is contained in:
Xing Yang
2015-07-27 00:24:04 -04:00
parent 03542ee65a
commit a9405b1419
4 changed files with 73 additions and 14 deletions

View File

@@ -94,8 +94,8 @@ class ConsistencygroupsTest(utils.TestCase):
def test_update_consistencygroup_no_props(self):
cs.consistencygroups.update('1234')
def test_create_consistencygroup_from_src(self):
cs.consistencygroups.create_from_src('5678', name='cg')
def test_create_consistencygroup_from_src_snap(self):
cs.consistencygroups.create_from_src('5678', None, name='cg')
expected = {
'consistencygroup-from-src': {
'status': 'creating',
@@ -103,7 +103,24 @@ class ConsistencygroupsTest(utils.TestCase):
'user_id': None,
'name': 'cg',
'cgsnapshot_id': '5678',
'project_id': None
'project_id': None,
'source_cgid': None
}
}
cs.assert_called('POST', '/consistencygroups/create_from_src',
body=expected)
def test_create_consistencygroup_from_src_cg(self):
cs.consistencygroups.create_from_src(None, '5678', name='cg')
expected = {
'consistencygroup-from-src': {
'status': 'creating',
'description': None,
'user_id': None,
'name': 'cg',
'source_cgid': '5678',
'project_id': None,
'cgsnapshot_id': None
}
}
cs.assert_called('POST', '/consistencygroups/create_from_src',

View File

@@ -913,7 +913,7 @@ class ShellTest(utils.TestCase):
self.run_command,
'consisgroup-update 1234')
def test_consistencygroup_create_from_src(self):
def test_consistencygroup_create_from_src_snap(self):
self.run_command('consisgroup-create-from-src '
'--name cg '
'--cgsnapshot 1234')
@@ -924,18 +924,45 @@ class ShellTest(utils.TestCase):
'description': None,
'user_id': None,
'project_id': None,
'status': 'creating'
'status': 'creating',
'source_cgid': None
}
}
self.assert_called('POST', '/consistencygroups/create_from_src',
expected)
def test_consistencygroup_create_from_src_bad_request(self):
def test_consistencygroup_create_from_src_cg(self):
self.run_command('consisgroup-create-from-src '
'--name cg '
'--source-cg 1234')
expected = {
'consistencygroup-from-src': {
'name': 'cg',
'cgsnapshot_id': None,
'description': None,
'user_id': None,
'project_id': None,
'status': 'creating',
'source_cgid': '1234'
}
}
self.assert_called('POST', '/consistencygroups/create_from_src',
expected)
def test_consistencygroup_create_from_src_fail_no_snap_cg(self):
self.assertRaises(exceptions.BadRequest,
self.run_command,
'consisgroup-create-from-src '
'--name cg')
def test_consistencygroup_create_from_src_fail_both_snap_cg(self):
self.assertRaises(exceptions.BadRequest,
self.run_command,
'consisgroup-create-from-src '
'--name cg '
'--cgsnapshot 1234 '
'--source-cg 5678')
def test_set_image_metadata(self):
self.run_command('image-metadata 1234 set key1=val1')
expected = {"os-set_image_metadata": {"metadata": {"key1": "val1"}}}

View File

@@ -67,12 +67,13 @@ class ConsistencygroupManager(base.ManagerWithFind):
return self._create('/consistencygroups', body, 'consistencygroup')
def create_from_src(self, cgsnapshot_id, name=None,
def create_from_src(self, cgsnapshot_id, source_cgid, name=None,
description=None, user_id=None,
project_id=None):
"""Creates a consistencygroup from a cgsnapshot.
"""Creates a consistencygroup from a cgsnapshot or a source CG.
:param cgsnapshot_id: UUID of a CGSnapshot
:param source_cgid: UUID of a source CG
:param name: Name of the ConsistencyGroup
:param description: Description of the ConsistencyGroup
:param user_id: User id derived from context
@@ -82,6 +83,7 @@ class ConsistencygroupManager(base.ManagerWithFind):
body = {'consistencygroup-from-src': {'name': name,
'description': description,
'cgsnapshot_id': cgsnapshot_id,
'source_cgid': source_cgid,
'user_id': user_id,
'project_id': project_id,
'status': "creating",

View File

@@ -2047,6 +2047,9 @@ def do_consisgroup_create(cs, args):
@utils.arg('--cgsnapshot',
metavar='<cgsnapshot>',
help='Name or ID of a cgsnapshot. Default=None.')
@utils.arg('--source-cg',
metavar='<source-cg>',
help='Name or ID of a source CG. Default=None.')
@utils.arg('--name',
metavar='<name>',
help='Name of a consistency group. Default=None.')
@@ -2055,14 +2058,24 @@ def do_consisgroup_create(cs, args):
help='Description of a consistency group. Default=None.')
@utils.service_type('volumev2')
def do_consisgroup_create_from_src(cs, args):
"""Creates a consistency group from a cgsnapshot."""
if not args.cgsnapshot:
msg = ('Cannot create consistency group because the source '
'cgsnapshot is not provided.')
"""Creates a consistency group from a cgsnapshot or a source CG."""
if not args.cgsnapshot and not args.source_cg:
msg = ('Cannot create consistency group because neither '
'cgsnapshot nor source CG is provided.')
raise exceptions.BadRequest(code=400, message=msg)
cgsnapshot = _find_cgsnapshot(cs, args.cgsnapshot)
if args.cgsnapshot and args.source_cg:
msg = ('Cannot create consistency group because both '
'cgsnapshot and source CG are provided.')
raise exceptions.BadRequest(code=400, message=msg)
cgsnapshot = None
if args.cgsnapshot:
cgsnapshot = _find_cgsnapshot(cs, args.cgsnapshot)
source_cg = None
if args.source_cg:
source_cg = _find_consistencygroup(cs, args.source_cg)
info = cs.consistencygroups.create_from_src(
cgsnapshot.id,
cgsnapshot.id if cgsnapshot else None,
source_cg.id if source_cg else None,
args.name,
args.description)