Changes V3 server_actions extension into v2.1
This patch changes v3 server_actions API to v2.1, and also share v2.1 and v2 test case. rename server_actions back to instance_actions. The differences between v2 and v3 are described on the wiki page https://wiki.openstack.org/wiki/NovaAPIv2tov3 . Partially implements blueprint v2-on-v3-api Change-Id: I8f11dc5f199711e1c98badfbe0035883d9c15573
This commit is contained in:
parent
3ab81c9b3e
commit
2ca8b73dd5
@ -1,5 +1,5 @@
|
||||
{
|
||||
"server_action": {
|
||||
"instanceAction": {
|
||||
"action": "reboot",
|
||||
"events": [
|
||||
{
|
||||
@ -17,7 +17,7 @@
|
||||
"traceback": ""
|
||||
}
|
||||
],
|
||||
"server_uuid": "b48316c5-71e8-45e4-9884-6c78055b9b13",
|
||||
"instance_uuid": "b48316c5-71e8-45e4-9884-6c78055b9b13",
|
||||
"message": "",
|
||||
"project_id": "147",
|
||||
"request_id": "req-3293a3f1-b44c-4609-b8d2-d81b105636b8",
|
@ -1,8 +1,8 @@
|
||||
{
|
||||
"server_actions": [
|
||||
"instanceActions": [
|
||||
{
|
||||
"action": "resize",
|
||||
"server_uuid": "b48316c5-71e8-45e4-9884-6c78055b9b13",
|
||||
"instance_uuid": "b48316c5-71e8-45e4-9884-6c78055b9b13",
|
||||
"message": "",
|
||||
"project_id": "842",
|
||||
"request_id": "req-25517360-b757-47d3-be45-0e8d2a01b36a",
|
||||
@ -11,7 +11,7 @@
|
||||
},
|
||||
{
|
||||
"action": "reboot",
|
||||
"server_uuid": "b48316c5-71e8-45e4-9884-6c78055b9b13",
|
||||
"instance_uuid": "b48316c5-71e8-45e4-9884-6c78055b9b13",
|
||||
"message": "",
|
||||
"project_id": "147",
|
||||
"request_id": "req-3293a3f1-b44c-4609-b8d2-d81b105636b8",
|
@ -164,10 +164,10 @@
|
||||
"compute_extension:v3:os-hypervisors:discoverable": "",
|
||||
"compute_extension:image_size": "",
|
||||
"compute_extension:instance_actions": "",
|
||||
"compute_extension:v3:os-server-actions": "",
|
||||
"compute_extension:v3:os-server-actions:discoverable": "",
|
||||
"compute_extension:v3:os-instance-actions": "",
|
||||
"compute_extension:v3:os-instance-actions:discoverable": "",
|
||||
"compute_extension:instance_actions:events": "rule:admin_api",
|
||||
"compute_extension:v3:os-server-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:ips:discoverable": "",
|
||||
"compute_extension:keypairs": "",
|
||||
|
@ -21,7 +21,7 @@ from nova.api.openstack import wsgi
|
||||
from nova import compute
|
||||
from nova.i18n import _
|
||||
|
||||
ALIAS = "os-server-actions"
|
||||
ALIAS = "os-instance-actions"
|
||||
authorize_actions = extensions.extension_authorizer('compute',
|
||||
'v3:' + ALIAS)
|
||||
authorize_events = extensions.soft_extension_authorizer('compute',
|
||||
@ -32,20 +32,17 @@ ACTION_KEYS = ['action', 'instance_uuid', 'request_id', 'user_id',
|
||||
EVENT_KEYS = ['event', 'start_time', 'finish_time', 'result', 'traceback']
|
||||
|
||||
|
||||
class ServerActionsController(wsgi.Controller):
|
||||
class InstanceActionsController(wsgi.Controller):
|
||||
|
||||
def __init__(self):
|
||||
super(ServerActionsController, self).__init__()
|
||||
super(InstanceActionsController, self).__init__()
|
||||
self.compute_api = compute.API()
|
||||
self.action_api = compute.InstanceActionAPI()
|
||||
|
||||
def _format_action(self, action_raw):
|
||||
action = {}
|
||||
for key in ACTION_KEYS:
|
||||
if key == 'instance_uuid':
|
||||
action['server_uuid'] = action_raw.get(key)
|
||||
else:
|
||||
action[key] = action_raw.get(key)
|
||||
action[key] = action_raw.get(key)
|
||||
return action
|
||||
|
||||
def _format_event(self, event_raw):
|
||||
@ -62,7 +59,7 @@ class ServerActionsController(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 {'server_actions': actions}
|
||||
return {'instanceActions': actions}
|
||||
|
||||
@extensions.expected_errors(404)
|
||||
def show(self, req, server_id, id):
|
||||
@ -82,19 +79,19 @@ class ServerActionsController(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 {'server_action': action}
|
||||
return {'instanceAction': action}
|
||||
|
||||
|
||||
class ServerActions(extensions.V3APIExtensionBase):
|
||||
class InstanceActions(extensions.V3APIExtensionBase):
|
||||
"""View a log of actions and events taken on an instance."""
|
||||
|
||||
name = "ServerActions"
|
||||
name = "InstanceActions"
|
||||
alias = ALIAS
|
||||
version = 1
|
||||
|
||||
def get_resources(self):
|
||||
ext = extensions.ResourceExtension('os-server-actions',
|
||||
ServerActionsController(),
|
||||
ext = extensions.ResourceExtension(ALIAS,
|
||||
InstanceActionsController(),
|
||||
parent=dict(
|
||||
member_name='server',
|
||||
collection_name='servers'))
|
@ -19,7 +19,10 @@ import uuid
|
||||
from lxml import etree
|
||||
from webob import exc
|
||||
|
||||
from nova.api.openstack.compute.contrib import instance_actions
|
||||
from nova.api.openstack.compute.contrib import instance_actions \
|
||||
as instance_actions_v2
|
||||
from nova.api.openstack.compute.plugins.v3 import instance_actions \
|
||||
as instance_actions_v21
|
||||
from nova.compute import api as compute_api
|
||||
from nova import db
|
||||
from nova.db.sqlalchemy import models
|
||||
@ -66,17 +69,26 @@ def format_event(event):
|
||||
return event
|
||||
|
||||
|
||||
class InstanceActionsPolicyTest(test.NoDBTestCase):
|
||||
def setUp(self):
|
||||
super(InstanceActionsPolicyTest, self).setUp()
|
||||
self.controller = instance_actions.InstanceActionsController()
|
||||
class InstanceActionsPolicyTestV21(test.NoDBTestCase):
|
||||
instance_actions = instance_actions_v21
|
||||
|
||||
def test_list_actions_restricted_by_project(self):
|
||||
def setUp(self):
|
||||
super(InstanceActionsPolicyTestV21, self).setUp()
|
||||
self.controller = self.instance_actions.InstanceActionsController()
|
||||
|
||||
def _get_http_req(self, action):
|
||||
fake_url = '/servers/12/%s' % action
|
||||
return fakes.HTTPRequestV3.blank(fake_url)
|
||||
|
||||
def _set_policy_rules(self):
|
||||
rules = {'compute:get': common_policy.parse_rule(''),
|
||||
'compute_extension:instance_actions':
|
||||
'compute_extension:v3:os-instance-actions':
|
||||
common_policy.parse_rule('project_id:%(project_id)s')}
|
||||
policy.set_rules(rules)
|
||||
|
||||
def test_list_actions_restricted_by_project(self):
|
||||
self._set_policy_rules()
|
||||
|
||||
def fake_instance_get_by_uuid(context, instance_id,
|
||||
columns_to_join=None,
|
||||
use_slave=False):
|
||||
@ -85,15 +97,12 @@ class InstanceActionsPolicyTest(test.NoDBTestCase):
|
||||
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 = self._get_http_req('os-instance-actions')
|
||||
self.assertRaises(exception.Forbidden, self.controller.index, req,
|
||||
str(uuid.uuid4()))
|
||||
|
||||
def test_get_action_restricted_by_project(self):
|
||||
rules = {'compute:get': common_policy.parse_rule(''),
|
||||
'compute_extension:instance_actions':
|
||||
common_policy.parse_rule('project_id:%(project_id)s')}
|
||||
policy.set_rules(rules)
|
||||
self._set_policy_rules()
|
||||
|
||||
def fake_instance_get_by_uuid(context, instance_id,
|
||||
columns_to_join=None,
|
||||
@ -103,16 +112,31 @@ class InstanceActionsPolicyTest(test.NoDBTestCase):
|
||||
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 = self._get_http_req('os-instance-actions/1')
|
||||
self.assertRaises(exception.Forbidden, self.controller.show, req,
|
||||
str(uuid.uuid4()), '1')
|
||||
|
||||
|
||||
class InstanceActionsTest(test.NoDBTestCase):
|
||||
class InstanceActionsPolicyTestV2(InstanceActionsPolicyTestV21):
|
||||
instance_actions = instance_actions_v2
|
||||
|
||||
def _get_http_req(self, action):
|
||||
fake_url = '/123/servers/12/%s' % action
|
||||
return fakes.HTTPRequest.blank(fake_url)
|
||||
|
||||
def _set_policy_rules(self):
|
||||
rules = {'compute:get': common_policy.parse_rule(''),
|
||||
'compute_extension:instance_actions':
|
||||
common_policy.parse_rule('project_id:%(project_id)s')}
|
||||
policy.set_rules(rules)
|
||||
|
||||
|
||||
class InstanceActionsTestV21(test.NoDBTestCase):
|
||||
instance_actions = instance_actions_v21
|
||||
|
||||
def setUp(self):
|
||||
super(InstanceActionsTest, self).setUp()
|
||||
self.controller = instance_actions.InstanceActionsController()
|
||||
super(InstanceActionsTestV21, self).setUp()
|
||||
self.controller = self.instance_actions.InstanceActionsController()
|
||||
self.fake_actions = copy.deepcopy(fake_server_actions.FAKE_ACTIONS)
|
||||
self.fake_events = copy.deepcopy(fake_server_actions.FAKE_EVENTS)
|
||||
|
||||
@ -126,6 +150,19 @@ class InstanceActionsTest(test.NoDBTestCase):
|
||||
self.stubs.Set(compute_api.API, 'get', fake_get)
|
||||
self.stubs.Set(db, 'instance_get_by_uuid', fake_instance_get_by_uuid)
|
||||
|
||||
def _get_http_req(self, action, use_admin_context=False):
|
||||
fake_url = '/servers/12/%s' % action
|
||||
return fakes.HTTPRequestV3.blank(fake_url,
|
||||
use_admin_context=use_admin_context)
|
||||
|
||||
def _set_policy_rules(self):
|
||||
rules = {'compute:get': common_policy.parse_rule(''),
|
||||
'compute_extension:v3:os-instance-actions':
|
||||
common_policy.parse_rule(''),
|
||||
'compute_extension:v3:os-instance-actions:events':
|
||||
common_policy.parse_rule('is_admin:True')}
|
||||
policy.set_rules(rules)
|
||||
|
||||
def test_list_actions(self):
|
||||
def fake_get_actions(context, uuid):
|
||||
actions = []
|
||||
@ -136,7 +173,7 @@ class InstanceActionsTest(test.NoDBTestCase):
|
||||
return actions
|
||||
|
||||
self.stubs.Set(db, 'actions_get', fake_get_actions)
|
||||
req = fakes.HTTPRequest.blank('/v2/123/servers/12/os-instance-actions')
|
||||
req = self._get_http_req('os-instance-actions')
|
||||
res_dict = self.controller.index(req, FAKE_UUID)
|
||||
for res in res_dict['instanceActions']:
|
||||
fake_action = self.fake_actions[FAKE_UUID][res['request_id']]
|
||||
@ -158,8 +195,7 @@ class InstanceActionsTest(test.NoDBTestCase):
|
||||
|
||||
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 = self._get_http_req('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]
|
||||
@ -177,14 +213,9 @@ class InstanceActionsTest(test.NoDBTestCase):
|
||||
|
||||
self.stubs.Set(db, 'action_get_by_request_id', fake_get_action)
|
||||
self.stubs.Set(db, 'action_events_get', fake_get_events)
|
||||
rules = {'compute:get': common_policy.parse_rule(''),
|
||||
'compute_extension:instance_actions':
|
||||
common_policy.parse_rule(''),
|
||||
'compute_extension:instance_actions:events':
|
||||
common_policy.parse_rule('is_admin:True')}
|
||||
policy.set_rules(rules)
|
||||
req = fakes.HTTPRequest.blank(
|
||||
'/v2/123/servers/12/os-instance-actions/1')
|
||||
|
||||
self._set_policy_rules()
|
||||
req = self._get_http_req('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]
|
||||
self.assertEqual(format_action(fake_action),
|
||||
@ -195,8 +226,7 @@ class InstanceActionsTest(test.NoDBTestCase):
|
||||
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 = self._get_http_req('os-instance-actions/1')
|
||||
self.assertRaises(exc.HTTPNotFound, self.controller.show, req,
|
||||
FAKE_UUID, FAKE_REQUEST_ID)
|
||||
|
||||
@ -205,7 +235,7 @@ class InstanceActionsTest(test.NoDBTestCase):
|
||||
want_objects=False):
|
||||
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 = self._get_http_req('os-instance-actions')
|
||||
self.assertRaises(exc.HTTPNotFound, self.controller.index, req,
|
||||
FAKE_UUID)
|
||||
|
||||
@ -214,15 +244,31 @@ class InstanceActionsTest(test.NoDBTestCase):
|
||||
want_objects=False):
|
||||
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/fake')
|
||||
req = self._get_http_req('os-instance-actions/fake')
|
||||
self.assertRaises(exc.HTTPNotFound, self.controller.show, req,
|
||||
FAKE_UUID, 'fake')
|
||||
|
||||
|
||||
class InstanceActionsSerializerTest(test.NoDBTestCase):
|
||||
class InstanceActionsTestV2(InstanceActionsTestV21):
|
||||
instance_actions = instance_actions_v2
|
||||
|
||||
def _get_http_req(self, action, use_admin_context=False):
|
||||
fake_url = '/123/servers/12/%s' % action
|
||||
return fakes.HTTPRequest.blank(fake_url,
|
||||
use_admin_context=use_admin_context)
|
||||
|
||||
def _set_policy_rules(self):
|
||||
rules = {'compute:get': common_policy.parse_rule(''),
|
||||
'compute_extension:instance_actions':
|
||||
common_policy.parse_rule(''),
|
||||
'compute_extension:instance_actions:events':
|
||||
common_policy.parse_rule('is_admin:True')}
|
||||
policy.set_rules(rules)
|
||||
|
||||
|
||||
class InstanceActionsSerializerTestV2(test.NoDBTestCase):
|
||||
def setUp(self):
|
||||
super(InstanceActionsSerializerTest, self).setUp()
|
||||
super(InstanceActionsSerializerTestV2, self).setUp()
|
||||
self.fake_actions = copy.deepcopy(fake_server_actions.FAKE_ACTIONS)
|
||||
self.fake_events = copy.deepcopy(fake_server_actions.FAKE_EVENTS)
|
||||
|
||||
@ -238,7 +284,7 @@ class InstanceActionsSerializerTest(test.NoDBTestCase):
|
||||
'%s did not match' % key)
|
||||
|
||||
def test_instance_action_serializer(self):
|
||||
serializer = instance_actions.InstanceActionTemplate()
|
||||
serializer = instance_actions_v2.InstanceActionTemplate()
|
||||
action = self.fake_actions[FAKE_UUID][FAKE_REQUEST_ID]
|
||||
text = serializer.serialize({'instanceAction': action})
|
||||
tree = etree.fromstring(text)
|
||||
@ -253,7 +299,7 @@ class InstanceActionsSerializerTest(test.NoDBTestCase):
|
||||
self.assertFalse(found_events)
|
||||
|
||||
def test_instance_action_events_serializer(self):
|
||||
serializer = instance_actions.InstanceActionTemplate()
|
||||
serializer = instance_actions_v2.InstanceActionTemplate()
|
||||
action = self.fake_actions[FAKE_UUID][FAKE_REQUEST_ID]
|
||||
event = self.fake_events[action['id']][0]
|
||||
action['events'] = [dict(event), dict(event)]
|
||||
@ -274,7 +320,7 @@ class InstanceActionsSerializerTest(test.NoDBTestCase):
|
||||
self.assertTrue(found_events)
|
||||
|
||||
def test_instance_actions_serializer(self):
|
||||
serializer = instance_actions.InstanceActionsTemplate()
|
||||
serializer = instance_actions_v2.InstanceActionsTemplate()
|
||||
action_list = self.fake_actions[FAKE_UUID].values()
|
||||
text = serializer.serialize({'instanceActions': action_list})
|
||||
tree = etree.fromstring(text)
|
||||
|
@ -1,226 +0,0 @@
|
||||
# Copyright 2013 Rackspace Hosting
|
||||
# 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.
|
||||
|
||||
import copy
|
||||
import uuid
|
||||
|
||||
from webob import exc
|
||||
|
||||
from nova.api.openstack.compute.plugins.v3 import server_actions
|
||||
from nova.compute import api as compute_api
|
||||
from nova import db
|
||||
from nova.db.sqlalchemy import models
|
||||
from nova import exception
|
||||
from nova.openstack.common import policy as common_policy
|
||||
from nova import policy
|
||||
from nova import test
|
||||
from nova.tests.api.openstack import fakes
|
||||
from nova.tests import fake_instance
|
||||
from nova.tests import fake_server_actions
|
||||
|
||||
FAKE_UUID = fake_server_actions.FAKE_UUID
|
||||
FAKE_REQUEST_ID = fake_server_actions.FAKE_REQUEST_ID1
|
||||
|
||||
|
||||
def format_action(action):
|
||||
'''Remove keys that aren't serialized.'''
|
||||
to_delete = ('id', 'finish_time', 'created_at', 'updated_at', 'deleted_at',
|
||||
'deleted')
|
||||
for key in to_delete:
|
||||
if key in action:
|
||||
del(action[key])
|
||||
if 'start_time' in action:
|
||||
# NOTE(danms): Without WSGI above us, these will be just stringified,
|
||||
# and objects will have added a timezone, so strip that for comparison
|
||||
action['start_time'] = str(action['start_time'].replace(tzinfo=None))
|
||||
for event in action.get('events', []):
|
||||
format_event(event)
|
||||
|
||||
if 'instance_uuid' in action:
|
||||
action['server_uuid'] = action.pop('instance_uuid')
|
||||
return action
|
||||
|
||||
|
||||
def format_event(event):
|
||||
'''Remove keys that aren't serialized.'''
|
||||
to_delete = ('id', 'created_at', 'updated_at', 'deleted_at', 'deleted',
|
||||
'action_id')
|
||||
for key in to_delete:
|
||||
if key in event:
|
||||
del(event[key])
|
||||
if 'start_time' in event:
|
||||
# NOTE(danms): Without WSGI above us, these will be just stringified,
|
||||
# and objects will have added a timezone, so strip that for comparison
|
||||
event['start_time'] = str(event['start_time'].replace(tzinfo=None))
|
||||
if 'finish_time' in event:
|
||||
# NOTE(danms): Without WSGI above us, these will be just stringified,
|
||||
# and objects will have added a timezone, so strip that for comparison
|
||||
event['finish_time'] = str(event['finish_time'].replace(tzinfo=None))
|
||||
return event
|
||||
|
||||
|
||||
class ServerActionsPolicyTest(test.NoDBTestCase):
|
||||
def setUp(self):
|
||||
super(ServerActionsPolicyTest, self).setUp()
|
||||
self.controller = server_actions.ServerActionsController()
|
||||
|
||||
def test_list_actions_restricted_by_project(self):
|
||||
rules = {'compute:get': common_policy.parse_rule(''),
|
||||
'compute_extension:v3:os-server-actions':
|
||||
common_policy.parse_rule('project_id:%(project_id)s')}
|
||||
policy.set_rules(rules)
|
||||
|
||||
def fake_instance_get_by_uuid(context, instance_id,
|
||||
columns_to_join=None, use_slave=False):
|
||||
return fake_instance.fake_db_instance(
|
||||
**{'name': 'fake', 'project_id': '%s_unequal' %
|
||||
context.project_id})
|
||||
|
||||
self.stubs.Set(db, 'instance_get_by_uuid', fake_instance_get_by_uuid)
|
||||
req = fakes.HTTPRequestV3.blank('/servers/12/os-server-actions')
|
||||
self.assertRaises(exception.Forbidden, self.controller.index, req,
|
||||
str(uuid.uuid4()))
|
||||
|
||||
def test_get_action_restricted_by_project(self):
|
||||
rules = {'compute:get': common_policy.parse_rule(''),
|
||||
'compute_extension:v3:os-server-actions':
|
||||
common_policy.parse_rule('project_id:%(project_id)s')}
|
||||
policy.set_rules(rules)
|
||||
|
||||
def fake_instance_get_by_uuid(context, instance_id,
|
||||
columns_to_join=None, use_slave=False):
|
||||
return fake_instance.fake_db_instance(
|
||||
**{'name': 'fake', 'project_id': '%s_unequal' %
|
||||
context.project_id})
|
||||
|
||||
self.stubs.Set(db, 'instance_get_by_uuid', fake_instance_get_by_uuid)
|
||||
req = fakes.HTTPRequestV3.blank(
|
||||
'/servers/12/os-server-actions/1')
|
||||
self.assertRaises(exception.Forbidden, self.controller.show, req,
|
||||
str(uuid.uuid4()), '1')
|
||||
|
||||
|
||||
class ServerActionsTest(test.NoDBTestCase):
|
||||
def setUp(self):
|
||||
super(ServerActionsTest, self).setUp()
|
||||
self.controller = server_actions.ServerActionsController()
|
||||
self.fake_actions = copy.deepcopy(fake_server_actions.FAKE_ACTIONS)
|
||||
self.fake_events = copy.deepcopy(fake_server_actions.FAKE_EVENTS)
|
||||
|
||||
def fake_get(self, context, instance_uuid, expected_attrs=None,
|
||||
want_objects=False):
|
||||
return {'uuid': instance_uuid}
|
||||
|
||||
def fake_instance_get_by_uuid(context, instance_id,
|
||||
columns_to_join=None, use_slave=False):
|
||||
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)
|
||||
|
||||
def test_list_actions(self):
|
||||
def fake_get_actions(context, uuid):
|
||||
actions = []
|
||||
for act in self.fake_actions[uuid].itervalues():
|
||||
action = models.InstanceAction()
|
||||
action.update(act)
|
||||
actions.append(action)
|
||||
return actions
|
||||
|
||||
self.stubs.Set(db, 'actions_get', fake_get_actions)
|
||||
req = fakes.HTTPRequestV3.blank('/servers/12/os-server-actions')
|
||||
res_dict = self.controller.index(req, FAKE_UUID)
|
||||
for res in res_dict['server_actions']:
|
||||
fake_action = self.fake_actions[FAKE_UUID][res['request_id']]
|
||||
self.assertEqual(format_action(fake_action),
|
||||
format_action(res))
|
||||
|
||||
def test_get_action_with_events_allowed(self):
|
||||
def fake_get_action(context, uuid, request_id):
|
||||
action = models.InstanceAction()
|
||||
action.update(self.fake_actions[uuid][request_id])
|
||||
return action
|
||||
|
||||
def fake_get_events(context, action_id):
|
||||
events = []
|
||||
for evt in self.fake_events[action_id]:
|
||||
event = models.InstanceActionEvent()
|
||||
event.update(evt)
|
||||
events.append(event)
|
||||
return events
|
||||
|
||||
self.stubs.Set(db, 'action_get_by_request_id', fake_get_action)
|
||||
self.stubs.Set(db, 'action_events_get', fake_get_events)
|
||||
req = fakes.HTTPRequestV3.blank(
|
||||
'/servers/12/os-server-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]
|
||||
fake_events = self.fake_events[fake_action['id']]
|
||||
fake_action['events'] = fake_events
|
||||
self.assertEqual(format_action(fake_action),
|
||||
format_action(res_dict['server_action']))
|
||||
|
||||
def test_get_action_with_events_not_allowed(self):
|
||||
def fake_get_action(context, uuid, request_id):
|
||||
return self.fake_actions[uuid][request_id]
|
||||
|
||||
def fake_get_events(context, action_id):
|
||||
return self.fake_events[action_id]
|
||||
|
||||
self.stubs.Set(db, 'action_get_by_request_id', fake_get_action)
|
||||
self.stubs.Set(db, 'action_events_get', fake_get_events)
|
||||
rules = {'compute:get': common_policy.parse_rule(''),
|
||||
'compute_extension:v3:os-server-actions':
|
||||
common_policy.parse_rule(''),
|
||||
'compute_extension:v3:os-server-actions:events':
|
||||
common_policy.parse_rule('is_admin:True')}
|
||||
policy.set_rules(rules)
|
||||
req = fakes.HTTPRequestV3.blank(
|
||||
'/servers/12/os-server-actions/1')
|
||||
res_dict = self.controller.show(req, FAKE_UUID, FAKE_REQUEST_ID)
|
||||
fake_action = self.fake_actions[FAKE_UUID][FAKE_REQUEST_ID]
|
||||
self.assertEqual(format_action(fake_action),
|
||||
format_action(res_dict['server_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.HTTPRequestV3.blank(
|
||||
'/servers/12/os-server-actions/1')
|
||||
self.assertRaises(exc.HTTPNotFound, self.controller.show, req,
|
||||
FAKE_UUID, FAKE_REQUEST_ID)
|
||||
|
||||
def test_instance_not_found(self):
|
||||
def fake_get(self, context, instance_uuid, expected_attrs=None,
|
||||
want_objects=False):
|
||||
raise exception.InstanceNotFound(instance_id=instance_uuid)
|
||||
self.stubs.Set(compute_api.API, 'get', fake_get)
|
||||
req = fakes.HTTPRequestV3.blank('/servers/12/os-server-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, expected_attrs=None,
|
||||
want_objects=False):
|
||||
raise exception.InstanceNotFound(instance_id=instance_uuid)
|
||||
self.stubs.Set(compute_api.API, 'get', fake_get)
|
||||
req = fakes.HTTPRequestV3.blank('/servers/12/os-server-actions/1')
|
||||
self.assertRaises(exc.HTTPNotFound, self.controller.show, req,
|
||||
FAKE_UUID, FAKE_REQUEST_ID)
|
@ -222,9 +222,9 @@ policy_data = """
|
||||
"compute_extension:v3:os-hypervisors": "rule:admin_api",
|
||||
"compute_extension:image_size": "",
|
||||
"compute_extension:instance_actions": "",
|
||||
"compute_extension:v3:os-server-actions": "",
|
||||
"compute_extension:v3:os-instance-actions": "",
|
||||
"compute_extension:instance_actions:events": "is_admin:True",
|
||||
"compute_extension:v3:os-server-actions:events": "is_admin:True",
|
||||
"compute_extension:v3:os-instance-actions:events": "is_admin:True",
|
||||
"compute_extension:instance_usage_audit_log": "",
|
||||
"compute_extension:keypairs": "",
|
||||
"compute_extension:keypairs:index": "",
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"server_action": {
|
||||
"instanceAction": {
|
||||
"action": "%(action)s",
|
||||
"server_uuid": "%(instance_uuid)s",
|
||||
"instance_uuid": "%(instance_uuid)s",
|
||||
"request_id": "%(request_id)s",
|
||||
"user_id": "%(integer_id)s",
|
||||
"project_id": "%(integer_id)s",
|
@ -1,8 +1,8 @@
|
||||
{
|
||||
"server_actions": [
|
||||
"instanceActions": [
|
||||
{
|
||||
"action": "%(action)s",
|
||||
"server_uuid": "%(uuid)s",
|
||||
"instance_uuid": "%(uuid)s",
|
||||
"request_id": "%(request_id)s",
|
||||
"user_id": "%(integer_id)s",
|
||||
"project_id": "%(integer_id)s",
|
||||
@ -11,7 +11,7 @@
|
||||
},
|
||||
{
|
||||
"action": "%(action)s",
|
||||
"server_uuid": "%(uuid)s",
|
||||
"instance_uuid": "%(uuid)s",
|
||||
"request_id": "%(request_id)s",
|
||||
"user_id": "%(integer_id)s",
|
||||
"project_id": "%(integer_id)s",
|
@ -0,0 +1,27 @@
|
||||
{
|
||||
"instanceAction": {
|
||||
"action": "reboot",
|
||||
"events": [
|
||||
{
|
||||
"event": "schedule",
|
||||
"finish_time": "2012-12-05T01:02:00.000000",
|
||||
"result": "Success",
|
||||
"start_time": "2012-12-05T01:00:02.000000",
|
||||
"traceback": ""
|
||||
},
|
||||
{
|
||||
"event": "compute_create",
|
||||
"finish_time": "2012-12-05T01:04:00.000000",
|
||||
"result": "Success",
|
||||
"start_time": "2012-12-05T01:03:00.000000",
|
||||
"traceback": ""
|
||||
}
|
||||
],
|
||||
"instance_uuid": "b48316c5-71e8-45e4-9884-6c78055b9b13",
|
||||
"message": "",
|
||||
"project_id": "147",
|
||||
"request_id": "req-3293a3f1-b44c-4609-b8d2-d81b105636b8",
|
||||
"start_time": "2012-12-05T00:00:00.000000",
|
||||
"user_id": "789"
|
||||
}
|
||||
}
|
@ -23,7 +23,7 @@ from nova.tests import utils as test_utils
|
||||
|
||||
|
||||
class ServerActionsSampleJsonTest(api_sample_base.ApiSampleTestBaseV3):
|
||||
extension_name = 'os-server-actions'
|
||||
extension_name = 'os-instance-actions'
|
||||
|
||||
def setUp(self):
|
||||
super(ServerActionsSampleJsonTest, self).setUp()
|
||||
@ -31,14 +31,14 @@ class ServerActionsSampleJsonTest(api_sample_base.ApiSampleTestBaseV3):
|
||||
self.events = fake_server_actions.FAKE_EVENTS
|
||||
self.instance = test_utils.get_test_instance()
|
||||
|
||||
def fake_server_action_get_by_request_id(context, uuid, request_id):
|
||||
def fake_instance_action_get_by_request_id(context, uuid, request_id):
|
||||
return copy.deepcopy(self.actions[uuid][request_id])
|
||||
|
||||
def fake_server_actions_get(context, uuid):
|
||||
return [copy.deepcopy(value) for value in
|
||||
self.actions[uuid].itervalues()]
|
||||
|
||||
def fake_server_action_events_get(context, action_id):
|
||||
def fake_instance_action_events_get(context, action_id):
|
||||
return copy.deepcopy(self.events[action_id])
|
||||
|
||||
def fake_instance_get_by_uuid(context, instance_id):
|
||||
@ -48,19 +48,19 @@ class ServerActionsSampleJsonTest(api_sample_base.ApiSampleTestBaseV3):
|
||||
return {'uuid': instance_uuid}
|
||||
|
||||
self.stubs.Set(db, 'action_get_by_request_id',
|
||||
fake_server_action_get_by_request_id)
|
||||
fake_instance_action_get_by_request_id)
|
||||
self.stubs.Set(db, 'actions_get', fake_server_actions_get)
|
||||
self.stubs.Set(db, 'action_events_get',
|
||||
fake_server_action_events_get)
|
||||
fake_instance_action_events_get)
|
||||
self.stubs.Set(db, 'instance_get_by_uuid', fake_instance_get_by_uuid)
|
||||
self.stubs.Set(compute_api.API, 'get', fake_get)
|
||||
|
||||
def test_server_action_get(self):
|
||||
def test_instance_action_get(self):
|
||||
fake_uuid = fake_server_actions.FAKE_UUID
|
||||
fake_request_id = fake_server_actions.FAKE_REQUEST_ID1
|
||||
fake_action = self.actions[fake_uuid][fake_request_id]
|
||||
|
||||
response = self._do_get('servers/%s/os-server-actions/%s' %
|
||||
response = self._do_get('servers/%s/os-instance-actions/%s' %
|
||||
(fake_uuid, fake_request_id))
|
||||
subs = self._get_regexes()
|
||||
subs['action'] = '(reboot)|(resize)'
|
||||
@ -70,15 +70,15 @@ class ServerActionsSampleJsonTest(api_sample_base.ApiSampleTestBaseV3):
|
||||
subs['start_time'] = fake_action['start_time']
|
||||
subs['result'] = '(Success)|(Error)'
|
||||
subs['event'] = '(schedule)|(compute_create)'
|
||||
self._verify_response('server-action-get-resp', subs, response, 200)
|
||||
self._verify_response('instance-action-get-resp', subs, response, 200)
|
||||
|
||||
def test_server_actions_list(self):
|
||||
def test_instance_actions_list(self):
|
||||
fake_uuid = fake_server_actions.FAKE_UUID
|
||||
response = self._do_get('servers/%s/os-server-actions' % (fake_uuid))
|
||||
response = self._do_get('servers/%s/os-instance-actions' % (fake_uuid))
|
||||
subs = self._get_regexes()
|
||||
subs['action'] = '(reboot)|(resize)'
|
||||
subs['integer_id'] = '[0-9]+'
|
||||
subs['request_id'] = ('req-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}'
|
||||
'-[0-9a-f]{4}-[0-9a-f]{12}')
|
||||
self._verify_response('server-actions-list-resp', subs,
|
||||
self._verify_response('instance-actions-list-resp', subs,
|
||||
response, 200)
|
@ -86,7 +86,7 @@ nova.api.v3.extensions =
|
||||
hide_server_addresses = nova.api.openstack.compute.plugins.v3.hide_server_addresses:HideServerAddresses
|
||||
hosts = nova.api.openstack.compute.plugins.v3.hosts:Hosts
|
||||
hypervisors = nova.api.openstack.compute.plugins.v3.hypervisors:Hypervisors
|
||||
server_actions = nova.api.openstack.compute.plugins.v3.server_actions:ServerActions
|
||||
instance_actions = nova.api.openstack.compute.plugins.v3.instance_actions:InstanceActions
|
||||
ips = nova.api.openstack.compute.plugins.v3.ips:IPs
|
||||
keypairs = nova.api.openstack.compute.plugins.v3.keypairs:Keypairs
|
||||
lock_server = nova.api.openstack.compute.plugins.v3.lock_server:LockServer
|
||||
|
Loading…
Reference in New Issue
Block a user