diff --git a/cinderclient/tests/unit/v2/fakes.py b/cinderclient/tests/unit/v2/fakes.py index e0a3cfef3..82cdc9c57 100644 --- a/cinderclient/tests/unit/v2/fakes.py +++ b/cinderclient/tests/unit/v2/fakes.py @@ -493,6 +493,12 @@ class FakeHTTPClient(base_client.HTTPClient): def post_consistencygroups_1234_delete(self, **kw): return (202, {}, {}) + def post_consistencygroups_create_from_src(self, **kw): + return (200, + {}, + {'consistencygroup': _stub_consistencygroup( + id='1234', cgsnapshot_id='1234')}) + # # Cgsnapshots # diff --git a/cinderclient/tests/unit/v2/test_consistencygroups.py b/cinderclient/tests/unit/v2/test_consistencygroups.py index 32f57bd97..390162e4e 100644 --- a/cinderclient/tests/unit/v2/test_consistencygroups.py +++ b/cinderclient/tests/unit/v2/test_consistencygroups.py @@ -94,6 +94,21 @@ 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') + expected = { + 'consistencygroup-from-src': { + 'status': 'creating', + 'description': None, + 'user_id': None, + 'name': 'cg', + 'cgsnapshot_id': '5678', + 'project_id': None + } + } + cs.assert_called('POST', '/consistencygroups/create_from_src', + body=expected) + def test_list_consistencygroup(self): cs.consistencygroups.list() cs.assert_called('GET', '/consistencygroups/detail') diff --git a/cinderclient/tests/unit/v2/test_shell.py b/cinderclient/tests/unit/v2/test_shell.py index 66777987e..1434221d2 100644 --- a/cinderclient/tests/unit/v2/test_shell.py +++ b/cinderclient/tests/unit/v2/test_shell.py @@ -819,3 +819,26 @@ class ShellTest(utils.TestCase): self.assertRaises(exceptions.BadRequest, self.run_command, 'consisgroup-update 1234') + + def test_consistencygroup_create_from_src(self): + self.run_command('consisgroup-create-from-src ' + '--name cg ' + '--cgsnapshot 1234') + expected = { + 'consistencygroup-from-src': { + 'name': 'cg', + 'cgsnapshot_id': '1234', + 'description': None, + 'user_id': None, + 'project_id': None, + 'status': 'creating' + } + } + self.assert_called('POST', '/consistencygroups/create_from_src', + expected) + + def test_consistencygroup_create_from_src_bad_request(self): + self.assertRaises(exceptions.BadRequest, + self.run_command, + 'consisgroup-create-from-src ' + '--name cg') diff --git a/cinderclient/v2/consistencygroups.py b/cinderclient/v2/consistencygroups.py index b20cb8b6f..c833e96f8 100644 --- a/cinderclient/v2/consistencygroups.py +++ b/cinderclient/v2/consistencygroups.py @@ -67,6 +67,32 @@ class ConsistencygroupManager(base.ManagerWithFind): return self._create('/consistencygroups', body, 'consistencygroup') + def create_from_src(self, cgsnapshot_id, name=None, + description=None, user_id=None, + project_id=None): + """Creates a consistencygroup from a cgsnapshot. + + :param cgsnapshot_id: UUID of a CGSnapshot + :param name: Name of the ConsistencyGroup + :param description: Description of the ConsistencyGroup + :param user_id: User id derived from context + :param project_id: Project id derived from context + :rtype: :class:`Consistencygroup` + """ + body = {'consistencygroup-from-src': {'name': name, + 'description': description, + 'cgsnapshot_id': cgsnapshot_id, + 'user_id': user_id, + 'project_id': project_id, + 'status': "creating", + }} + + self.run_hooks('modify_body_for_update', body, + 'consistencygroup-from-src') + resp, body = self.api.client.post( + "/consistencygroups/create_from_src", body=body) + return body['consistencygroup'] + def get(self, group_id): """Get a consistencygroup. diff --git a/cinderclient/v2/shell.py b/cinderclient/v2/shell.py index be5f9b7c1..2bb10241a 100644 --- a/cinderclient/v2/shell.py +++ b/cinderclient/v2/shell.py @@ -1945,6 +1945,32 @@ def do_consisgroup_create(cs, args): utils.print_dict(info) +@utils.arg('--cgsnapshot', + metavar='', + help='Name or ID of a cgsnapshot. Default=None.') +@utils.arg('--name', + metavar='', + help='Name of a consistency group. Default=None.') +@utils.arg('--description', + metavar='', + 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.') + raise exceptions.BadRequest(code=400, message=msg) + cgsnapshot = _find_cgsnapshot(cs, args.cgsnapshot) + info = cs.consistencygroups.create_from_src( + cgsnapshot.id, + args.name, + args.description) + + info.pop('links', None) + utils.print_dict(info) + + @utils.arg('consistencygroup', metavar='', nargs='+', help='Name or ID of one or more consistency groups '