summaryrefslogtreecommitdiffstats
path: root/nova
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2013-01-15 21:05:32 +0000
committerGerrit Code Review <review@openstack.org>2013-01-15 21:05:32 +0000
commite98ec572f0989491ddfcb6de68a3e5bc7d4e0d73 (patch)
treebb10012517704ec6f6297f18547395b8f3ed14b5 /nova
parent73d32fedbd4dddc1bec9e036c2c546425bffc92c (diff)
parent4b9bd9112ffc335f33d77f75fc8e5b21fe18f594 (diff)
downloadnova-e98ec572f0989491ddfcb6de68a3e5bc7d4e0d73.tar.gz
nova-e98ec572f0989491ddfcb6de68a3e5bc7d4e0d73.tar.xz
nova-e98ec572f0989491ddfcb6de68a3e5bc7d4e0d73.zip
Merge "Cells: Add some cells support to admin_actions extension"
Diffstat (limited to 'nova')
-rw-r--r--nova/api/openstack/compute/contrib/admin_actions.py4
-rw-r--r--nova/compute/api.py14
-rw-r--r--nova/compute/cells_api.py44
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_admin_actions_with_cells.py89
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))