Merge "Add support for updating instance type"

This commit is contained in:
Jenkins 2017-01-03 16:02:18 +00:00 committed by Gerrit Code Review
commit 6065ebfa10
9 changed files with 143 additions and 11 deletions

View File

@ -94,6 +94,53 @@ Response
.. literalinclude:: ../../doc/api_samples/types/type-create-post-resp.json
:language: javascript
Update Type
===========
.. rest_method:: PUT /types/{type_uuid}
Updates a type.
Updating a type is typically only available to administrators of a
cloud because this has implications for scheduling efficiently in the cloud.
Normal response codes: 200
Error response codes: badRequest(400), unauthorized(401), forbidden(403),
conflict(409)
Request
-------
.. rest_parameters:: parameters.yaml
- name: type_name
- description: type_description
- is_public: type_is_public_not_required
**Example Update Type**
.. literalinclude:: ../../doc/api_samples/types/type-update-put-req.json
:language: javascript
Response
--------
.. rest_parameters:: parameters.yaml
- name: type_name
- links: links
- description: type_description
- uuid: type_uuid
- created_at: created_at
- updated_at: updated_at
- is_public: type_is_public
- extra_specs: type_extra_specs
**Example Update type**
.. literalinclude:: ../../doc/api_samples/types/type-update-put-resp.json
:language: javascript
Show Type Details
===================

View File

@ -0,0 +1,5 @@
{
"name": "updated_type",
"description": "this is a type to be updated",
"is_public": false
}

View File

@ -0,0 +1,19 @@
{
"description": "this is a type to be updated",
"links": [
{
"href": "http://10.3.150.17:6688/v1/types/7de2859d-ec6d-42c7-bb86-9d630ba5ac94",
"rel": "self"
},
{
"href": "http://10.3.150.17:6688/types/7de2859d-ec6d-42c7-bb86-9d630ba5ac94",
"rel": "bookmark"
}
],
"created_at": "2016-09-27T02:37:21.966342+00:00",
"uuid": "7de2859d-ec6d-42c7-bb86-9d630ba5ac94",
"updated_at": null,
"extra_specs": {},
"is_public": false,
"name": "updated_type"
}

View File

@ -23,6 +23,8 @@ from nimble.api.controllers import base
from nimble.api.controllers import link
from nimble.api.controllers.v1 import types
from nimble.api import expose
from nimble.common import exception
from nimble.common.i18n import _
from nimble import objects
@ -161,6 +163,34 @@ class InstanceTypeController(rest.RestController):
new_instance_type.uuid)
return InstanceType.convert_with_links(new_instance_type)
@expose.expose(InstanceType, types.uuid, body=InstanceType)
def put(self, instance_type_uuid, instance_type):
"""Update an instance type.
:param instance_type_uuid: the uuid of instance_type to be updated.
:param instance_type: a instance type within the request body.
"""
try:
inst_type_in_db = objects.InstanceType.get(
pecan.request.context, instance_type_uuid)
except exception.InstanceTypeNotFound:
msg = (_("InstanceType %s could not be found") %
instance_type_uuid)
raise wsme.exc.ClientSideError(
msg, status_code=http_client.BAD_REQUEST)
need_to_update = False
for attr in ('name', 'description', 'is_public'):
if getattr(instance_type, attr) != wtypes.Unset:
need_to_update = True
setattr(inst_type_in_db, attr, getattr(instance_type, attr))
# don't need to call db_api if no update
if need_to_update:
inst_type_in_db.save()
# Set the HTTP Location Header
pecan.response.location = link.build_url('instance_type',
inst_type_in_db.uuid)
return InstanceType.convert_with_links(inst_type_in_db)
@expose.expose(None, types.uuid, status_code=http_client.NO_CONTENT)
def delete(self, instance_type_uuid):
"""Delete an instance type.

View File

@ -50,6 +50,9 @@ class Connection(object):
def instance_type_get(self, context, instance_type_uuid):
"""Get instance type by uuid."""
def instance_type_update(self, context, instance_type_id, values):
"""Update an instance type."""
@abc.abstractmethod
def instance_type_get_all(self, context):
"""Get all instance types."""

View File

@ -137,6 +137,19 @@ class Connection(api.Connection):
raise exception.InstanceTypeNotFound(
instance_type=instance_type_uuid)
def instance_type_update(self, context, instance_type_id, values):
with _session_for_write():
query = model_query(context, models.InstanceTypes)
query = add_identity_filter(query, instance_type_id)
try:
ref = query.with_lockmode('update').one()
except NoResultFound:
raise exception.InstanceTypeNotFound(
instance_type=instance_type_id)
ref.update(values)
return ref
def instance_type_get_all(self, context):
results = model_query(context, models.InstanceTypes)
return [_dict_with_extra_specs(i) for i in results]

View File

@ -16,7 +16,6 @@
from oslo_versionedobjects import base as object_base
from nimble.common import exception
from nimble.db import api as dbapi
from nimble.objects import base
from nimble.objects import fields as object_fields
@ -92,10 +91,6 @@ class InstanceType(base.NimbleObject, object_base.VersionedObjectDictCompat):
def save(self, context=None):
updates = self.obj_get_changes()
extra_specs = updates.pop('extra_specs', None)
if updates:
raise exception.ObjectActionError(
action='save', reason='read-only fields were changed')
if extra_specs is not None:
deleted_keys = (set(self._orig_extra_specs.keys()) -
set(extra_specs.keys()))
@ -105,6 +100,7 @@ class InstanceType(base.NimbleObject, object_base.VersionedObjectDictCompat):
if added_keys or deleted_keys:
self.save_extra_specs(context, self.extra_specs, deleted_keys)
self.dbapi.instance_type_update(context, self.uuid, updates)
def save_extra_specs(self, context, to_add=None, to_delete=None):
"""Add or delete extra_specs.

View File

@ -69,6 +69,19 @@ class TestInstanceType(v1_test.APITestV1):
resp = self.get_json('/types')
self.assertEqual(3, len(resp['types']))
def test_instance_type_update(self):
self._prepare_instance_types()
resp = self.get_json('/types/' + self.TYPE_UUIDS[0])
self.assertEqual('test0', resp['name'])
self.assertEqual('just test0', resp['description'])
values = {"name": "update_name", "description": "updated_description",
"is_public": False}
self.put_json('/types/' + self.TYPE_UUIDS[0], values, status=200)
resp = self.get_json('/types/' + self.TYPE_UUIDS[0])
self.assertEqual('update_name', resp['name'])
self.assertEqual('updated_description', resp['description'])
self.assertEqual(False, resp['is_public'])
class TestInstanceTypeExtra(v1_test.APITestV1):
TYPE_UUID = 'ff28b5a2-73e5-431c-b4b7-1b96b74bca7b'

View File

@ -14,7 +14,6 @@
import mock
from oslo_context import context
from nimble.common import exception
from nimble import objects
from nimble.tests.unit.db import base
from nimble.tests.unit.db import utils
@ -72,8 +71,15 @@ class TestInstanceTypeObject(base.DbTestCase):
mock_type_destroy.assert_called_once_with(self.context, uuid)
def test_save(self):
uuid = self.fake_type['uuid']
with mock.patch.object(self.dbapi, 'instance_type_update',
autospec=True) as mock_inst_type_update:
instance_type = objects.InstanceType(self.context,
**self.fake_type)
self.assertRaises(exception.ObjectActionError,
instance_type.save,
self.context)
instance_type.name = 'changed_name'
updates = instance_type.obj_get_changes()
instance_type.save(self.context)
updates.pop('extra_specs', None)
mock_inst_type_update.return_value = self.fake_type
mock_inst_type_update.assert_called_once_with(
self.context, uuid, updates)