From a9405b14199edfc9e0d86fd08be6bf256c4ffaf8 Mon Sep 17 00:00:00 2001 From: Xing Yang Date: Mon, 27 Jul 2015 00:24:04 -0400 Subject: [PATCH] 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 --- .../tests/unit/v2/test_consistencygroups.py | 23 +++++++++++-- cinderclient/tests/unit/v2/test_shell.py | 33 +++++++++++++++++-- cinderclient/v2/consistencygroups.py | 6 ++-- cinderclient/v2/shell.py | 25 ++++++++++---- 4 files changed, 73 insertions(+), 14 deletions(-) diff --git a/cinderclient/tests/unit/v2/test_consistencygroups.py b/cinderclient/tests/unit/v2/test_consistencygroups.py index 390162e4e..0038d972a 100644 --- a/cinderclient/tests/unit/v2/test_consistencygroups.py +++ b/cinderclient/tests/unit/v2/test_consistencygroups.py @@ -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', diff --git a/cinderclient/tests/unit/v2/test_shell.py b/cinderclient/tests/unit/v2/test_shell.py index b80c91143..5f6e6d7d3 100644 --- a/cinderclient/tests/unit/v2/test_shell.py +++ b/cinderclient/tests/unit/v2/test_shell.py @@ -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"}}} diff --git a/cinderclient/v2/consistencygroups.py b/cinderclient/v2/consistencygroups.py index c833e96f8..122468582 100644 --- a/cinderclient/v2/consistencygroups.py +++ b/cinderclient/v2/consistencygroups.py @@ -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", diff --git a/cinderclient/v2/shell.py b/cinderclient/v2/shell.py index 8fd48e2d4..39e1be050 100644 --- a/cinderclient/v2/shell.py +++ b/cinderclient/v2/shell.py @@ -2047,6 +2047,9 @@ def do_consisgroup_create(cs, args): @utils.arg('--cgsnapshot', metavar='', help='Name or ID of a cgsnapshot. Default=None.') +@utils.arg('--source-cg', + metavar='', + help='Name or ID of a source CG. Default=None.') @utils.arg('--name', metavar='', 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)