diff options
| author | Jenkins <jenkins@review.openstack.org> | 2013-01-15 21:05:32 +0000 |
|---|---|---|
| committer | Gerrit Code Review <review@openstack.org> | 2013-01-15 21:05:32 +0000 |
| commit | e98ec572f0989491ddfcb6de68a3e5bc7d4e0d73 (patch) | |
| tree | bb10012517704ec6f6297f18547395b8f3ed14b5 | |
| parent | 73d32fedbd4dddc1bec9e036c2c546425bffc92c (diff) | |
| parent | 4b9bd9112ffc335f33d77f75fc8e5b21fe18f594 (diff) | |
| download | nova-e98ec572f0989491ddfcb6de68a3e5bc7d4e0d73.tar.gz nova-e98ec572f0989491ddfcb6de68a3e5bc7d4e0d73.tar.xz nova-e98ec572f0989491ddfcb6de68a3e5bc7d4e0d73.zip | |
Merge "Cells: Add some cells support to admin_actions extension"
| -rw-r--r-- | nova/api/openstack/compute/contrib/admin_actions.py | 4 | ||||
| -rw-r--r-- | nova/compute/api.py | 14 | ||||
| -rw-r--r-- | nova/compute/cells_api.py | 44 | ||||
| -rw-r--r-- | nova/tests/api/openstack/compute/contrib/test_admin_actions_with_cells.py | 89 |
4 files changed, 140 insertions, 11 deletions
diff --git a/nova/api/openstack/compute/contrib/admin_actions.py b/nova/api/openstack/compute/contrib/admin_actions.py index f345d9617..fa7836b37 100644 --- a/nova/api/openstack/compute/contrib/admin_actions.py +++ b/nova/api/openstack/compute/contrib/admin_actions.py @@ -307,9 +307,7 @@ class AdminActionsController(wsgi.Controller): try: instance = self.compute_api.get(context, id) - self.compute_api.update(context, instance, - vm_state=state, - task_state=None) + self.compute_api.update_state(context, instance, state) except exception.InstanceNotFound: raise exc.HTTPNotFound(_("Server not found")) except Exception: diff --git a/nova/compute/api.py b/nova/compute/api.py index 7770bc9e6..8ba6b97aa 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -878,6 +878,20 @@ class API(base.Base): for host_name in host_names: self.compute_rpcapi.refresh_provider_fw_rules(context, host_name) + def update_state(self, context, instance, new_state): + """Updates the state of a compute instance. + For example to 'active' or 'error'. + Also sets 'task_state' to None. + Used by admin_actions api + + :param context: The security context + :param instance: The instance to update + :param new_state: A member of vm_state, eg. 'active' + """ + self.update(context, instance, + vm_state=new_state, + task_state=None) + @wrap_check_policy def update(self, context, instance, **kwargs): """Updates the instance in the datastore. diff --git a/nova/compute/cells_api.py b/nova/compute/cells_api.py index d547c363a..d1d9a11d2 100644 --- a/nova/compute/cells_api.py +++ b/nova/compute/cells_api.py @@ -144,17 +144,45 @@ class ComputeCellsAPI(compute_api.API): """ return super(ComputeCellsAPI, self).create(*args, **kwargs) - @validate_cell - def update(self, context, instance, **kwargs): - """Update an instance.""" + def update_state(self, context, instance, new_state): + """Updates the state of a compute instance. + For example to 'active' or 'error'. + Also sets 'task_state' to None. + Used by admin_actions api + + :param context: The security context + :param instance: The instance to update + :param new_state: A member of vm_state to change + the instance's state to, + eg. 'active' + """ + self.update(context, instance, + pass_on_state_change=True, + vm_state=new_state, + task_state=None) + + def update(self, context, instance, pass_on_state_change=False, **kwargs): + """ + Update an instance. + :param pass_on_state_change: if true, the state change will be passed + on to child cells + """ + cell_name = instance['cell_name'] + if cell_name and self._cell_read_only(cell_name): + raise exception.InstanceInvalidState( + attr="vm_state", + instance_uuid=instance['uuid'], + state="temporary_readonly", + method='update') rv = super(ComputeCellsAPI, self).update(context, instance, **kwargs) - # We need to skip vm_state/task_state updates... those will - # happen when via a a _cast_to_cells for running a different - # compute api method kwargs_copy = kwargs.copy() - kwargs_copy.pop('vm_state', None) - kwargs_copy.pop('task_state', None) + if not pass_on_state_change: + # We need to skip vm_state/task_state updates... those will + # happen via a _cast_to_cells when running a different + # compute api method + kwargs_copy.pop('vm_state', None) + kwargs_copy.pop('task_state', None) if kwargs_copy: try: self._cast_to_cells(context, instance, 'update', diff --git a/nova/tests/api/openstack/compute/contrib/test_admin_actions_with_cells.py b/nova/tests/api/openstack/compute/contrib/test_admin_actions_with_cells.py new file mode 100644 index 000000000..b8f4e6398 --- /dev/null +++ b/nova/tests/api/openstack/compute/contrib/test_admin_actions_with_cells.py @@ -0,0 +1,89 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright (c) 2012 Openstack, LLC. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +""" +Tests For Compute admin api w/ Cells +""" + +from nova.api.openstack.compute.contrib import admin_actions +from nova.compute import cells_api as compute_cells_api +from nova.compute import vm_states +from nova.openstack.common import log as logging +from nova.openstack.common import uuidutils +from nova import test +from nova.tests.api.openstack import fakes + +LOG = logging.getLogger('nova.tests.test_compute_cells') + +INSTANCE_IDS = {'inst_id': 1} + + +class CellsAdminAPITestCase(test.TestCase): + + def setUp(self): + super(CellsAdminAPITestCase, self).setUp() + + def _fake_cell_read_only(*args, **kwargs): + return False + + def _fake_validate_cell(*args, **kwargs): + return + + def _fake_compute_api_get(context, instance_id): + return {'id': 1, 'uuid': instance_id, 'vm_state': vm_states.ACTIVE, + 'task_state': None, 'cell_name': None} + + def _fake_instance_update_and_get_original(context, instance_uuid, + values): + inst = fakes.stub_instance(INSTANCE_IDS.get(instance_uuid), + name=values.get('display_name')) + return (inst, inst) + + def fake_cast_to_cells(context, instance, method, *args, **kwargs): + """ + Makes sure that the cells recieve the cast to update + the cell state + """ + self.cells_recieved_kwargs.update(kwargs) + + self.admin_api = admin_actions.AdminActionsController() + self.admin_api.compute_api = compute_cells_api.ComputeCellsAPI() + self.stubs.Set(self.admin_api.compute_api, '_cell_read_only', + _fake_cell_read_only) + self.stubs.Set(self.admin_api.compute_api, '_validate_cell', + _fake_validate_cell) + self.stubs.Set(self.admin_api.compute_api, 'get', + _fake_compute_api_get) + self.stubs.Set(self.admin_api.compute_api.db, + 'instance_update_and_get_original', + _fake_instance_update_and_get_original) + self.stubs.Set(self.admin_api.compute_api, '_cast_to_cells', + fake_cast_to_cells) + + self.uuid = uuidutils.generate_uuid() + url = '/fake/servers/%s/action' % self.uuid + self.request = fakes.HTTPRequest.blank(url) + self.cells_recieved_kwargs = {} + + def test_reset_active(self): + body = {"os-resetState": {"state": "error"}} + result = self.admin_api._reset_state(self.request, 'inst_id', body) + + self.assertEqual(result.status_int, 202) + # Make sure the cells recieved the update + self.assertEqual(self.cells_recieved_kwargs, + dict(vm_state=vm_states.ERROR, + task_state=None)) |
