summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--etc/nova/policy.json2
-rw-r--r--nova/api/openstack/compute/plugins/v3/instance_actions.py41
-rw-r--r--nova/tests/api/openstack/compute/plugins/v3/test_instance_actions.py74
-rw-r--r--nova/tests/fake_policy.py2
-rw-r--r--setup.cfg1
5 files changed, 74 insertions, 46 deletions
diff --git a/etc/nova/policy.json b/etc/nova/policy.json
index 995881eb44..6e4fb3b043 100644
--- a/etc/nova/policy.json
+++ b/etc/nova/policy.json
@@ -97,7 +97,9 @@
"compute_extension:v3:os-image-metadata": "",
"compute_extension:v3:os-images": "",
"compute_extension:instance_actions": "",
+ "compute_extension:v3:os-instance-actions": "",
"compute_extension:instance_actions:events": "rule:admin_api",
+ "compute_extension:v3:os-instance-actions:events": "rule:admin_api",
"compute_extension:instance_usage_audit_log": "rule:admin_api",
"compute_extension:v3:os-instance-usage-audit-log": "rule:admin_api",
"compute_extension:v3:ips:discoverable": "",
diff --git a/nova/api/openstack/compute/plugins/v3/instance_actions.py b/nova/api/openstack/compute/plugins/v3/instance_actions.py
index 3b15de2bac..94497c5e48 100644
--- a/nova/api/openstack/compute/plugins/v3/instance_actions.py
+++ b/nova/api/openstack/compute/plugins/v3/instance_actions.py
@@ -21,10 +21,11 @@ from nova.api.openstack import xmlutil
from nova import compute
from nova import exception
+ALIAS = "os-instance-actions"
authorize_actions = extensions.extension_authorizer('compute',
- 'instance_actions')
+ 'v3:' + ALIAS)
authorize_events = extensions.soft_extension_authorizer('compute',
- 'instance_actions:events')
+ 'v3:' + ALIAS + ':events')
ACTION_KEYS = ['action', 'instance_uuid', 'request_id', 'user_id',
'project_id', 'start_time', 'message']
@@ -47,17 +48,17 @@ def make_action(elem):
class InstanceActionsTemplate(xmlutil.TemplateBuilder):
def construct(self):
- root = xmlutil.TemplateElement('instanceActions')
- elem = xmlutil.SubTemplateElement(root, 'instanceAction',
- selector='instanceActions')
+ root = xmlutil.TemplateElement('instance_actions')
+ elem = xmlutil.SubTemplateElement(root, 'instance_action',
+ selector='instance_actions')
make_actions(elem)
return xmlutil.MasterTemplate(root, 1)
class InstanceActionTemplate(xmlutil.TemplateBuilder):
def construct(self):
- root = xmlutil.TemplateElement('instanceAction',
- selector='instanceAction')
+ root = xmlutil.TemplateElement('instance_action',
+ selector='instance_action')
make_action(root)
return xmlutil.MasterTemplate(root, 1)
@@ -92,18 +93,22 @@ class InstanceActionsController(wsgi.Controller):
authorize_actions(context, target=instance)
actions_raw = self.action_api.actions_get(context, instance)
actions = [self._format_action(action) for action in actions_raw]
- return {'instanceActions': actions}
+ return {'instance_actions': actions}
@wsgi.serializers(xml=InstanceActionTemplate)
def show(self, req, server_id, id):
"""Return data about the given instance action."""
context = req.environ['nova.context']
- instance = self.compute_api.get(context, server_id)
+ try:
+ instance = self.compute_api.get(context, server_id)
+ except exception.InstanceNotFound as err:
+ raise exc.HTTPNotFound(explanation=err.format_message())
authorize_actions(context, target=instance)
action = self.action_api.action_get_by_request_id(context, instance,
id)
if action is None:
- raise exc.HTTPNotFound()
+ msg = _("Action %s not found") % id
+ raise exc.HTTPNotFound(msg)
action_id = action['id']
action = self._format_action(action)
@@ -111,17 +116,17 @@ class InstanceActionsController(wsgi.Controller):
events_raw = self.action_api.action_events_get(context, instance,
action_id)
action['events'] = [self._format_event(evt) for evt in events_raw]
- return {'instanceAction': action}
+ return {'instance_action': action}
-class Instance_actions(extensions.ExtensionDescriptor):
+class InstanceActions(extensions.V3APIExtensionBase):
"""View a log of actions and events taken on an instance."""
name = "InstanceActions"
- alias = "os-instance-actions"
+ alias = ALIAS
namespace = ("http://docs.openstack.org/compute/ext/"
- "instance-actions/api/v1.1")
- updated = "2013-02-08T00:00:00+00:00"
+ "instance-actions/api/v3")
+ version = 1
def get_resources(self):
ext = extensions.ResourceExtension('os-instance-actions',
@@ -130,3 +135,9 @@ class Instance_actions(extensions.ExtensionDescriptor):
member_name='server',
collection_name='servers'))
return [ext]
+
+ def get_controller_extensions(self):
+ """It's an abstract function V3APIExtensionBase and the extension
+ will not be loaded without it.
+ """
+ return []
diff --git a/nova/tests/api/openstack/compute/plugins/v3/test_instance_actions.py b/nova/tests/api/openstack/compute/plugins/v3/test_instance_actions.py
index 12c3fab0ea..af1472fbd4 100644
--- a/nova/tests/api/openstack/compute/plugins/v3/test_instance_actions.py
+++ b/nova/tests/api/openstack/compute/plugins/v3/test_instance_actions.py
@@ -19,7 +19,7 @@ import uuid
from lxml import etree
from webob import exc
-from nova.api.openstack.compute.contrib import instance_actions
+from nova.api.openstack.compute.plugins.v3 import instance_actions
from nova.compute import api as compute_api
from nova import db
from nova.db.sqlalchemy import models
@@ -57,7 +57,7 @@ class InstanceActionsPolicyTest(test.TestCase):
def test_list_actions_restricted_by_project(self):
rules = policy.Rules({'compute:get': policy.parse_rule(''),
- 'compute_extension:instance_actions':
+ 'compute_extension:v3:os-instance-actions':
policy.parse_rule('project_id:%(project_id)s')})
policy.set_rules(rules)
@@ -68,13 +68,13 @@ class InstanceActionsPolicyTest(test.TestCase):
context.project_id})
self.stubs.Set(db, 'instance_get_by_uuid', fake_instance_get_by_uuid)
- req = fakes.HTTPRequest.blank('/v2/123/servers/12/os-instance-actions')
+ req = fakes.HTTPRequestV3.blank('/servers/12/os-instance-actions')
self.assertRaises(exception.NotAuthorized, self.controller.index, req,
str(uuid.uuid4()))
def test_get_action_restricted_by_project(self):
rules = policy.Rules({'compute:get': policy.parse_rule(''),
- 'compute_extension:instance_actions':
+ 'compute_extension:v3:os-instance-actions':
policy.parse_rule('project_id:%(project_id)s')})
policy.set_rules(rules)
@@ -85,8 +85,8 @@ class InstanceActionsPolicyTest(test.TestCase):
context.project_id})
self.stubs.Set(db, 'instance_get_by_uuid', fake_instance_get_by_uuid)
- req = fakes.HTTPRequest.blank(
- '/v2/123/servers/12/os-instance-actions/1')
+ req = fakes.HTTPRequestV3.blank(
+ '/servers/12/os-instance-actions/1')
self.assertRaises(exception.NotAuthorized, self.controller.show, req,
str(uuid.uuid4()), '1')
@@ -101,8 +101,11 @@ class InstanceActionsTest(test.TestCase):
def fake_get(self, context, instance_uuid):
return {'uuid': instance_uuid}
- def fake_instance_get_by_uuid(context, instance_id):
- return {'name': 'fake', 'project_id': context.project_id}
+ def fake_instance_get_by_uuid(context, instance_id,
+ columns_to_join=None):
+ return fake_instance.fake_db_instance(
+ **{'name': 'fake', 'project_id': '%s_unequal' %
+ context.project_id})
self.stubs.Set(compute_api.API, 'get', fake_get)
self.stubs.Set(db, 'instance_get_by_uuid', fake_instance_get_by_uuid)
@@ -117,9 +120,9 @@ class InstanceActionsTest(test.TestCase):
return actions
self.stubs.Set(db, 'actions_get', fake_get_actions)
- req = fakes.HTTPRequest.blank('/v2/123/servers/12/os-instance-actions')
+ req = fakes.HTTPRequestV3.blank('/servers/12/os-instance-actions')
res_dict = self.controller.index(req, FAKE_UUID)
- for res in res_dict['instanceActions']:
+ for res in res_dict['instance_actions']:
fake_action = self.fake_actions[FAKE_UUID][res['request_id']]
fake_action = format_action(fake_action)
self.assertEqual(fake_action, res)
@@ -140,8 +143,8 @@ class InstanceActionsTest(test.TestCase):
self.stubs.Set(db, 'action_get_by_request_id', fake_get_action)
self.stubs.Set(db, 'action_events_get', fake_get_events)
- req = fakes.HTTPRequest.blank(
- '/v2/123/servers/12/os-instance-actions/1',
+ req = fakes.HTTPRequestV3.blank(
+ '/servers/12/os-instance-actions/1',
use_admin_context=True)
res_dict = self.controller.show(req, FAKE_UUID, FAKE_REQUEST_ID)
fake_action = self.fake_actions[FAKE_UUID][FAKE_REQUEST_ID]
@@ -149,7 +152,7 @@ class InstanceActionsTest(test.TestCase):
fake_events = [format_event(event) for event in fake_events]
fake_action = format_action(fake_action)
fake_action['events'] = fake_events
- self.assertEqual(fake_action, res_dict['instanceAction'])
+ self.assertEqual(fake_action, res_dict['instance_action'])
def test_get_action_with_events_not_allowed(self):
def fake_get_action(context, uuid, request_id):
@@ -160,26 +163,27 @@ class InstanceActionsTest(test.TestCase):
self.stubs.Set(db, 'action_get_by_request_id', fake_get_action)
self.stubs.Set(db, 'action_events_get', fake_get_events)
- rules = policy.Rules({'compute:get': policy.parse_rule(''),
- 'compute_extension:instance_actions':
- policy.parse_rule(''),
- 'compute_extension:instance_actions:events':
- policy.parse_rule('is_admin:True')})
+ rules = policy.Rules({
+ 'compute:get': policy.parse_rule(''),
+ 'compute_extension:v3:os-instance-actions':
+ policy.parse_rule(''),
+ 'compute_extension:v3:os-instance-actions:events':
+ policy.parse_rule('is_admin:True')})
policy.set_rules(rules)
- req = fakes.HTTPRequest.blank(
- '/v2/123/servers/12/os-instance-actions/1')
+ req = fakes.HTTPRequestV3.blank(
+ '/servers/12/os-instance-actions/1')
res_dict = self.controller.show(req, FAKE_UUID, FAKE_REQUEST_ID)
fake_action = self.fake_actions[FAKE_UUID][FAKE_REQUEST_ID]
fake_action = format_action(fake_action)
- self.assertEqual(fake_action, res_dict['instanceAction'])
+ self.assertEqual(fake_action, res_dict['instance_action'])
def test_action_not_found(self):
def fake_no_action(context, uuid, action_id):
return None
self.stubs.Set(db, 'action_get_by_request_id', fake_no_action)
- req = fakes.HTTPRequest.blank(
- '/v2/123/servers/12/os-instance-actions/1')
+ req = fakes.HTTPRequestV3.blank(
+ '/servers/12/os-instance-actions/1')
self.assertRaises(exc.HTTPNotFound, self.controller.show, req,
FAKE_UUID, FAKE_REQUEST_ID)
@@ -187,10 +191,18 @@ class InstanceActionsTest(test.TestCase):
def fake_get(self, context, instance_uuid):
raise exception.InstanceNotFound(instance_id=instance_uuid)
self.stubs.Set(compute_api.API, 'get', fake_get)
- req = fakes.HTTPRequest.blank('/v2/123/servers/12/os-instance-actions')
+ req = fakes.HTTPRequestV3.blank('/servers/12/os-instance-actions')
self.assertRaises(exc.HTTPNotFound, self.controller.index, req,
FAKE_UUID)
+ def test_instance_not_found_in_show(self):
+ def fake_get(self, context, instance_uuid):
+ raise exception.InstanceNotFound(instance_id=instance_uuid)
+ self.stubs.Set(compute_api.API, 'get', fake_get)
+ req = fakes.HTTPRequestV3.blank('/servers/12/os-instance-actions/1')
+ self.assertRaises(exc.HTTPNotFound, self.controller.show, req,
+ FAKE_UUID, FAKE_REQUEST_ID)
+
class InstanceActionsSerializerTest(test.TestCase):
def setUp(self):
@@ -212,11 +224,11 @@ class InstanceActionsSerializerTest(test.TestCase):
def test_instance_action_serializer(self):
serializer = instance_actions.InstanceActionTemplate()
action = self.fake_actions[FAKE_UUID][FAKE_REQUEST_ID]
- text = serializer.serialize({'instanceAction': action})
+ text = serializer.serialize({'instance_action': action})
tree = etree.fromstring(text)
action = format_action(action)
- self.assertEqual('instanceAction', tree.tag)
+ self.assertEqual('instance_action', tree.tag)
self._verify_instance_action_attachment(action, tree)
found_events = False
for child in tree:
@@ -229,11 +241,11 @@ class InstanceActionsSerializerTest(test.TestCase):
action = self.fake_actions[FAKE_UUID][FAKE_REQUEST_ID]
event = self.fake_events[action['id']][0]
action['events'] = [event, event]
- text = serializer.serialize({'instanceAction': action})
+ text = serializer.serialize({'instance_action': action})
tree = etree.fromstring(text)
action = format_action(action)
- self.assertEqual('instanceAction', tree.tag)
+ self.assertEqual('instance_action', tree.tag)
self._verify_instance_action_attachment(action, tree)
event = format_event(event)
@@ -248,14 +260,14 @@ class InstanceActionsSerializerTest(test.TestCase):
def test_instance_actions_serializer(self):
serializer = instance_actions.InstanceActionsTemplate()
action_list = self.fake_actions[FAKE_UUID].values()
- text = serializer.serialize({'instanceActions': action_list})
+ text = serializer.serialize({'instance_actions': action_list})
tree = etree.fromstring(text)
action_list = [format_action(action) for action in action_list]
- self.assertEqual('instanceActions', tree.tag)
+ self.assertEqual('instance_actions', tree.tag)
self.assertEqual(len(action_list), len(tree))
for idx, child in enumerate(tree):
- self.assertEqual('instanceAction', child.tag)
+ self.assertEqual('instance_action', child.tag)
request_id = child.get('request_id')
self._verify_instance_action_attachment(
self.fake_actions[FAKE_UUID][request_id],
diff --git a/nova/tests/fake_policy.py b/nova/tests/fake_policy.py
index 86f6ddc9a7..b670c232f4 100644
--- a/nova/tests/fake_policy.py
+++ b/nova/tests/fake_policy.py
@@ -174,7 +174,9 @@ policy_data = """
"compute_extension:v3:os-image-metadata": "",
"compute_extension:v3:os-images": "",
"compute_extension:instance_actions": "",
+ "compute_extension:v3:os-instance-actions": "",
"compute_extension:instance_actions:events": "is_admin:True",
+ "compute_extension:v3:os-instance-actions:events": "is_admin:True",
"compute_extension:instance_usage_audit_log": "",
"compute_extension:v3:os-instance-usage-audit-log": "",
"compute_extension:keypairs": "",
diff --git a/setup.cfg b/setup.cfg
index f1eb12e597..228dbe968c 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -77,6 +77,7 @@ nova.api.v3.extensions =
hypervisors = nova.api.openstack.compute.plugins.v3.hypervisors:Hypervisors
image_metadata = nova.api.openstack.compute.plugins.v3.image_metadata:ImageMetadata
images = nova.api.openstack.compute.plugins.v3.images:Images
+ instance_actions = nova.api.openstack.compute.plugins.v3.instance_actions:InstanceActions
ips = nova.api.openstack.compute.plugins.v3.ips:IPs
instance_usage_audit_log = nova.api.openstack.compute.plugins.v3.instance_usage_audit_log:InstanceUsageAuditLog
keypairs = nova.api.openstack.compute.plugins.v3.keypairs:Keypairs