Merge "Add support for updating instance type"
This commit is contained in:
commit
6065ebfa10
@ -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
|
||||
===================
|
||||
|
5
doc/api_samples/types/type-update-put-req.json
Normal file
5
doc/api_samples/types/type-update-put-req.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "updated_type",
|
||||
"description": "this is a type to be updated",
|
||||
"is_public": false
|
||||
}
|
19
doc/api_samples/types/type-update-put-resp.json
Normal file
19
doc/api_samples/types/type-update-put-resp.json
Normal 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"
|
||||
}
|
@ -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.
|
||||
|
@ -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."""
|
||||
|
@ -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]
|
||||
|
@ -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.
|
||||
|
@ -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'
|
||||
|
@ -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):
|
||||
instance_type = objects.InstanceType(self.context,
|
||||
**self.fake_type)
|
||||
self.assertRaises(exception.ObjectActionError,
|
||||
instance_type.save,
|
||||
self.context)
|
||||
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)
|
||||
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)
|
||||
|
Loading…
Reference in New Issue
Block a user