summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEwan Mellor <ewan.mellor@citrix.com>2011-11-27 23:26:49 -0800
committerEwan Mellor <ewan.mellor@citrix.com>2011-11-27 23:37:06 -0800
commit4a76167e354eed4aa98232fbf6c845f86ce4cf22 (patch)
tree5fb0eb2aaf5731d48e7578ea9c30539c63450f7f
parent356ec713068b82af3cf449815ae76d82b4f86242 (diff)
downloadnova-4a76167e354eed4aa98232fbf6c845f86ce4cf22.tar.gz
nova-4a76167e354eed4aa98232fbf6c845f86ce4cf22.tar.xz
nova-4a76167e354eed4aa98232fbf6c845f86ce4cf22.zip
Bug #897091: "nova actions" fails with HTTP 400 / TypeError if a server action has been performed
Fix code in Controller.action that was overwriting the definition of the actions method with a dictionary. This meant that 'nova actions' would fail if 'nova reboot' had previously been called. Added two tests, one for the actions call in general, and one for this failure mode specifically. Change-Id: I695bb5c4dcfba96a5aba54125a8f3163e1a6a193
-rw-r--r--nova/api/openstack/v2/servers.py8
-rw-r--r--nova/tests/api/openstack/v2/test_servers.py33
2 files changed, 36 insertions, 5 deletions
diff --git a/nova/api/openstack/v2/servers.py b/nova/api/openstack/v2/servers.py
index 144566d33..5066633be 100644
--- a/nova/api/openstack/v2/servers.py
+++ b/nova/api/openstack/v2/servers.py
@@ -506,7 +506,7 @@ class Controller(wsgi.Controller):
@scheduler_api.redirect_handler
def action(self, req, id, body):
"""Multi-purpose method used to take actions on a server"""
- self.actions = {
+ _actions = {
'changePassword': self._action_change_password,
'reboot': self._action_reboot,
'resize': self._action_resize,
@@ -520,11 +520,11 @@ class Controller(wsgi.Controller):
admin_actions = {
'createBackup': self._action_create_backup,
}
- self.actions.update(admin_actions)
+ _actions.update(admin_actions)
for key in body:
- if key in self.actions:
- return self.actions[key](body, req, id)
+ if key in _actions:
+ return _actions[key](body, req, id)
else:
msg = _("There is no such server action: %s") % (key,)
raise exc.HTTPBadRequest(explanation=msg)
diff --git a/nova/tests/api/openstack/v2/test_servers.py b/nova/tests/api/openstack/v2/test_servers.py
index 9af7163d6..f6f78609d 100644
--- a/nova/tests/api/openstack/v2/test_servers.py
+++ b/nova/tests/api/openstack/v2/test_servers.py
@@ -32,6 +32,7 @@ from nova.compute import instance_types
from nova.compute import task_states
from nova.compute import vm_states
import nova.db
+from nova.db.sqlalchemy.models import InstanceActions
from nova.db.sqlalchemy.models import InstanceMetadata
from nova import flags
import nova.image.fake
@@ -153,6 +154,19 @@ def fake_compute_api(cls, req, id):
return True
+_fake_compute_actions = [
+ dict(
+ created_at=str(datetime.datetime(2010, 11, 11, 11, 0, 0)),
+ action='Fake Action',
+ error='Fake Error',
+ )
+ ]
+
+
+def fake_compute_actions(_1, _2, _3):
+ return [InstanceActions(**a) for a in _fake_compute_actions]
+
+
def find_host(self, context, instance_id):
return "nova"
@@ -192,7 +206,7 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(nova.db, 'instance_get_floating_address',
instance_addresses)
self.stubs.Set(nova.compute.API, "get_diagnostics", fake_compute_api)
- self.stubs.Set(nova.compute.API, "get_actions", fake_compute_api)
+ self.stubs.Set(nova.compute.API, "get_actions", fake_compute_actions)
self.config_drive = None
@@ -1154,6 +1168,23 @@ class ServersControllerTest(test.TestCase):
self.assertEqual(s['status'], 'BUILD')
self.assertEqual(s['metadata']['seq'], str(i))
+ def test_server_actions(self):
+ req = fakes.HTTPRequest.blank(
+ "/v2/fake/servers/%s/actions" % FAKE_UUID)
+ res_dict = self.controller.actions(req, FAKE_UUID)
+ self.assertEqual(res_dict, {'actions': _fake_compute_actions})
+
+ def test_server_actions_after_reboot(self):
+ """
+ Bug #897091 was this failure mode -- the /actions call failed if
+ /action had been called first.
+ """
+ body = dict(reboot=dict(type="HARD"))
+ req = fakes.HTTPRequest.blank(
+ '/v2/fake/servers/%s/action' % FAKE_UUID)
+ self.controller.action(req, FAKE_UUID, body)
+ self.test_server_actions()
+
def test_get_all_server_details_with_host(self):
'''
We want to make sure that if two instances are on the same host, then