From bc2b8bf1be95a8f45eca57e1f75dcc5f6504873a Mon Sep 17 00:00:00 2001 From: Gloria Gu Date: Fri, 31 Oct 2014 11:11:24 -0700 Subject: [PATCH] Added type description for volume type client This patch added client handling and unit tests for volume type description: * Added 2 client methods for volume type. default: to get the default volume type update: to upate an existing volume type to update description * Added 2 new command-line operations. type-update (adminitrator only) type-default * type-list should display description. * type-create should have an option for entering the description. The corresponding cinder APIs change volume-type-description: https://review.openstack.org/#/c/131871/ Implements: blueprint volume-type-description Change-Id: I2735d7050d90589d19f45e21096577febdcca8bb --- cinderclient/base.py | 4 +++- cinderclient/tests/v2/fakes.py | 7 +++++++ cinderclient/tests/v2/test_types.py | 15 +++++++++++++++ cinderclient/v2/shell.py | 27 +++++++++++++++++++++++++-- cinderclient/v2/volume_types.py | 28 +++++++++++++++++++++++++++- 5 files changed, 77 insertions(+), 4 deletions(-) diff --git a/cinderclient/base.py b/cinderclient/base.py index 5542e0a2e..f2ed7b85f 100644 --- a/cinderclient/base.py +++ b/cinderclient/base.py @@ -189,9 +189,11 @@ class Manager(utils.HookableMixin): def _delete(self, url): resp, body = self.api.client.delete(url) - def _update(self, url, body, **kwargs): + def _update(self, url, body, response_key=None, **kwargs): self.run_hooks('modify_body_for_update', body, **kwargs) resp, body = self.api.client.put(url, body=body) + if response_key: + return self.resource_class(self, body[response_key], loaded=True) return body diff --git a/cinderclient/tests/v2/fakes.py b/cinderclient/tests/v2/fakes.py index 8ca75a6fc..18dc30588 100644 --- a/cinderclient/tests/v2/fakes.py +++ b/cinderclient/tests/v2/fakes.py @@ -578,9 +578,13 @@ class FakeHTTPClient(base_client.HTTPClient): 'name': 'test-type-2', 'extra_specs': {}}}) + def get_types_default(self, **kw): + return self.get_types_1() + def post_types(self, body, **kw): return (202, {}, {'volume_type': {'id': 3, 'name': 'test-type-3', + 'description': 'test_type-3-desc', 'extra_specs': {}}}) def post_types_1_extra_specs(self, body, **kw): @@ -593,6 +597,9 @@ class FakeHTTPClient(base_client.HTTPClient): def delete_types_1(self, **kw): return (202, {}, None) + def put_types_1(self, **kw): + return self.get_types_1() + # # VolumeEncryptionTypes # diff --git a/cinderclient/tests/v2/test_types.py b/cinderclient/tests/v2/test_types.py index 2cfcce729..efe027ff3 100644 --- a/cinderclient/tests/v2/test_types.py +++ b/cinderclient/tests/v2/test_types.py @@ -33,6 +33,21 @@ class TypesTest(utils.TestCase): cs.assert_called('POST', '/types') self.assertIsInstance(t, volume_types.VolumeType) + def test_update(self): + t = cs.volume_types.update('1', 'test_desc_1') + cs.assert_called('PUT', '/types/1') + self.assertIsInstance(t, volume_types.VolumeType) + + def test_get(self): + t = cs.volume_types.get('1') + cs.assert_called('GET', '/types/1') + self.assertIsInstance(t, volume_types.VolumeType) + + def test_default(self): + t = cs.volume_types.default() + cs.assert_called('GET', '/types/default') + self.assertIsInstance(t, volume_types.VolumeType) + def test_set_key(self): t = cs.volume_types.get(1) t.set_keys({'k': 'v'}) diff --git a/cinderclient/v2/shell.py b/cinderclient/v2/shell.py index e6ec3715e..a0f697746 100644 --- a/cinderclient/v2/shell.py +++ b/cinderclient/v2/shell.py @@ -696,7 +696,7 @@ def do_snapshot_reset_state(cs, args): def _print_volume_type_list(vtypes): - utils.print_list(vtypes, ['ID', 'Name']) + utils.print_list(vtypes, ['ID', 'Name', 'Description']) @utils.service_type('volumev2') @@ -706,6 +706,26 @@ def do_type_list(cs, args): _print_volume_type_list(vtypes) +@utils.service_type('volumev2') +def do_type_default(cs, args): + """List the default volume type.""" + vtype = cs.volume_types.default() + _print_volume_type_list([vtype]) + + +@utils.arg('id', + metavar='', + help="ID of the volume type.") +@utils.arg('description', + metavar='', + help="Description of the volume type.") +@utils.service_type('volumev2') +def do_type_update(cs, args): + """Updates volume type description.""" + vtype = cs.volume_types.update(args.id, args.description) + _print_volume_type_list([vtype]) + + @utils.service_type('volumev2') def do_extra_specs_list(cs, args): """Lists current volume types and extra specs.""" @@ -716,10 +736,13 @@ def do_extra_specs_list(cs, args): @utils.arg('name', metavar='', help="Name of new volume type.") +@utils.arg('--description', + metavar='', + help="Description of new volume type.") @utils.service_type('volumev2') def do_type_create(cs, args): """Creates a volume type.""" - vtype = cs.volume_types.create(args.name) + vtype = cs.volume_types.create(args.name, args.description) _print_volume_type_list([vtype]) diff --git a/cinderclient/v2/volume_types.py b/cinderclient/v2/volume_types.py index dc2ec5bba..6b167d0fb 100644 --- a/cinderclient/v2/volume_types.py +++ b/cinderclient/v2/volume_types.py @@ -85,6 +85,13 @@ class VolumeTypeManager(base.ManagerWithFind): """ return self._get("/types/%s" % base.getid(volume_type), "volume_type") + def default(self): + """Get the default volume type. + + :rtype: :class:`VolumeType` + """ + return self._get("/types/default", "volume_type") + def delete(self, volume_type): """Deletes a specific volume_type. @@ -92,17 +99,36 @@ class VolumeTypeManager(base.ManagerWithFind): """ self._delete("/types/%s" % base.getid(volume_type)) - def create(self, name): + def create(self, name, description=None): """Creates a volume type. :param name: Descriptive name of the volume type + :param description: Description of the the volume type :rtype: :class:`VolumeType` """ body = { "volume_type": { "name": name, + "description": description } } return self._create("/types", body, "volume_type") + + def update(self, volume_type, description): + """Update the description for a volume type. + + :param volume_type: The ID of the :class:`VolumeType` to update. + :param description: Description of the the volume type. + :rtype: :class:`VolumeType` + """ + + body = { + "volume_type": { + "description": description + } + } + + return self._update("/types/%s" % base.getid(volume_type), + body, response_key="volume_type")