Merge "api: Add response body schemas for instance actions"
This commit is contained in:
@@ -38,6 +38,7 @@ ACTION_KEYS_V258 = ['action', 'instance_uuid', 'request_id', 'user_id',
|
||||
EVENT_KEYS = ['event', 'start_time', 'finish_time', 'result', 'traceback']
|
||||
|
||||
|
||||
@validation.validated
|
||||
class InstanceActionsController(wsgi.Controller):
|
||||
_view_builder_class = instance_actions_view.ViewBuilder
|
||||
|
||||
@@ -80,9 +81,11 @@ class InstanceActionsController(wsgi.Controller):
|
||||
|
||||
@wsgi.expected_errors(404, "2.1", "2.57")
|
||||
@wsgi.expected_errors((400, 404), "2.58")
|
||||
@validation.query_schema(schema.list_query, "2.1", "2.57")
|
||||
@validation.query_schema(schema.list_query_v258, "2.58", "2.65")
|
||||
@validation.query_schema(schema.list_query_v266, "2.66")
|
||||
@validation.query_schema(schema.index_query, "2.1", "2.57")
|
||||
@validation.query_schema(schema.index_query_v258, "2.58", "2.65")
|
||||
@validation.query_schema(schema.index_query_v266, "2.66")
|
||||
@validation.response_body_schema(schema.index_response, "2.1", "2.57")
|
||||
@validation.response_body_schema(schema.index_response_v258, "2.58")
|
||||
def index(self, req, server_id):
|
||||
"""Returns the list of actions recorded for a given instance."""
|
||||
context = req.environ["nova.context"]
|
||||
@@ -137,6 +140,11 @@ class InstanceActionsController(wsgi.Controller):
|
||||
|
||||
@wsgi.expected_errors(404)
|
||||
@validation.query_schema(schema.show_query)
|
||||
@validation.response_body_schema(schema.show_response, "2.1", "2.50")
|
||||
@validation.response_body_schema(schema.show_response_v251, "2.51", "2.57")
|
||||
@validation.response_body_schema(schema.show_response_v258, "2.58", "2.61")
|
||||
@validation.response_body_schema(schema.show_response_v262, "2.62", "2.83")
|
||||
@validation.response_body_schema(schema.show_response_v284, "2.84")
|
||||
def show(self, req, server_id, id):
|
||||
"""Return data about the given instance action."""
|
||||
context = req.environ['nova.context']
|
||||
@@ -154,6 +162,7 @@ class InstanceActionsController(wsgi.Controller):
|
||||
action = self._format_action(action, ACTION_KEYS_V258)
|
||||
else:
|
||||
action = self._format_action(action, ACTION_KEYS)
|
||||
|
||||
# Prior to microversion 2.51, events would only be returned in the
|
||||
# response for admins by default policy rules. Starting in
|
||||
# microversion 2.51, events are returned for admin_or_owner (of the
|
||||
@@ -167,7 +176,8 @@ class InstanceActionsController(wsgi.Controller):
|
||||
fatal=False):
|
||||
# For all microversions, the user can see all event details
|
||||
# including the traceback.
|
||||
show_events = show_traceback = True
|
||||
show_events = True
|
||||
show_traceback = True
|
||||
show_host = api_version_request.is_supported(req, '2.62')
|
||||
elif api_version_request.is_supported(req, '2.51'):
|
||||
# The user is not able to see all event details, but they can at
|
||||
|
||||
@@ -15,14 +15,15 @@
|
||||
import copy
|
||||
|
||||
from nova.api.validation import parameter_types
|
||||
from nova.api.validation import response_types
|
||||
|
||||
list_query = {
|
||||
index_query = {
|
||||
'type': 'object',
|
||||
'properties': {},
|
||||
'additionalProperties': True,
|
||||
}
|
||||
|
||||
list_query_v258 = {
|
||||
index_query_v258 = {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
# The 2.58 microversion added support for paging by limit and marker
|
||||
@@ -36,8 +37,8 @@ list_query_v258 = {
|
||||
'additionalProperties': False
|
||||
}
|
||||
|
||||
list_query_v266 = copy.deepcopy(list_query_v258)
|
||||
list_query_v266['properties'].update({
|
||||
index_query_v266 = copy.deepcopy(index_query_v258)
|
||||
index_query_v266['properties'].update({
|
||||
'changes-before': parameter_types.single_param(
|
||||
{'type': 'string', 'format': 'date-time'}),
|
||||
})
|
||||
@@ -47,3 +48,153 @@ show_query = {
|
||||
'properties': {},
|
||||
'additionalProperties': True,
|
||||
}
|
||||
|
||||
index_response = {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'instanceActions': {
|
||||
'type': 'array',
|
||||
'items': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'action': {'type': 'string'},
|
||||
'instance_uuid': {'type': 'string', 'format': 'uuid'},
|
||||
'message': {'type': ['null', 'string']},
|
||||
'project_id': {
|
||||
'type': ['null', 'string'],
|
||||
'pattern': '^[a-zA-Z0-9-]*$',
|
||||
'minLength': 1,
|
||||
'maxLength': 255,
|
||||
},
|
||||
'request_id': {'type': 'string'},
|
||||
'start_time': {'type': 'string', 'format': 'date-time'},
|
||||
'user_id': {
|
||||
'type': ['null', 'string'],
|
||||
'pattern': '^[a-zA-Z0-9-]*$',
|
||||
'minLength': 1,
|
||||
'maxLength': 255,
|
||||
},
|
||||
},
|
||||
'required': [
|
||||
'action',
|
||||
'instance_uuid',
|
||||
'message',
|
||||
'project_id',
|
||||
'request_id',
|
||||
'start_time',
|
||||
'user_id',
|
||||
],
|
||||
'additionalProperties': False,
|
||||
},
|
||||
},
|
||||
},
|
||||
'required': ['instanceActions'],
|
||||
'additionalProperties': False,
|
||||
}
|
||||
|
||||
index_response_v258 = copy.deepcopy(index_response)
|
||||
index_response_v258['properties']['instanceActions']['items'][
|
||||
'properties'
|
||||
].update({
|
||||
'updated_at': {'type': ['null', 'string'], 'format': 'date-time'},
|
||||
})
|
||||
index_response_v258['properties']['instanceActions']['items'][
|
||||
'required'
|
||||
].append('updated_at')
|
||||
index_response_v258['properties']['links'] = response_types.collection_links
|
||||
|
||||
show_response = {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'instanceAction': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'action': {'type': 'string'},
|
||||
'instance_uuid': {'type': 'string', 'format': 'uuid'},
|
||||
'events': {
|
||||
'type': 'array',
|
||||
'items': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'event': {'type': 'string'},
|
||||
'finish_time': {
|
||||
'type': ['string', 'null'],
|
||||
'format': 'date-time',
|
||||
},
|
||||
'result': {'type': ['string', 'null']},
|
||||
'start_time': {
|
||||
'type': 'string', 'format': 'date-time',
|
||||
},
|
||||
'traceback': {'type': ['null', 'string']},
|
||||
},
|
||||
'required': [
|
||||
'event',
|
||||
'finish_time',
|
||||
'result',
|
||||
'start_time',
|
||||
],
|
||||
'additionalProperties': False,
|
||||
},
|
||||
},
|
||||
'message': {'type': ['null', 'string']},
|
||||
'project_id': {
|
||||
'type': ['null', 'string'],
|
||||
'pattern': '^[a-zA-Z0-9-]*$',
|
||||
'minLength': 1,
|
||||
'maxLength': 255,
|
||||
},
|
||||
'request_id': {'type': 'string'},
|
||||
'start_time': {'type': 'string', 'format': 'date-time'},
|
||||
'user_id': {
|
||||
'type': ['null', 'string'],
|
||||
'pattern': '^[a-zA-Z0-9-]*$',
|
||||
'minLength': 1,
|
||||
'maxLength': 255,
|
||||
},
|
||||
},
|
||||
'required': [
|
||||
'action',
|
||||
'instance_uuid',
|
||||
'message',
|
||||
'project_id',
|
||||
'request_id',
|
||||
'start_time',
|
||||
'user_id',
|
||||
],
|
||||
'additionalProperties': False,
|
||||
},
|
||||
},
|
||||
'required': ['instanceAction'],
|
||||
'additionalProperties': False,
|
||||
}
|
||||
|
||||
show_response_v251 = copy.deepcopy(show_response)
|
||||
show_response_v251['properties']['instanceAction']['required'].append(
|
||||
'events'
|
||||
)
|
||||
|
||||
show_response_v258 = copy.deepcopy(show_response_v251)
|
||||
show_response_v258['properties']['instanceAction']['properties'].update({
|
||||
'updated_at': {'type': ['null', 'string'], 'format': 'date-time'},
|
||||
})
|
||||
show_response_v258['properties']['instanceAction']['required'].append(
|
||||
'updated_at'
|
||||
)
|
||||
|
||||
show_response_v262 = copy.deepcopy(show_response_v258)
|
||||
show_response_v262['properties']['instanceAction']['properties']['events'][
|
||||
'items'
|
||||
]['properties'].update({
|
||||
'hostId': {'type': 'string'},
|
||||
'host': {'type': 'string'},
|
||||
})
|
||||
show_response_v262['properties']['instanceAction']['properties']['events'][
|
||||
'items'
|
||||
]['required'].append('hostId')
|
||||
|
||||
show_response_v284 = copy.deepcopy(show_response_v262)
|
||||
show_response_v284['properties']['instanceAction']['properties']['events'][
|
||||
'items'
|
||||
]['properties'].update({
|
||||
'details': {'type': ['string', 'null']},
|
||||
})
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
# 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.
|
||||
|
||||
"""Common field types for validating API responses."""
|
||||
|
||||
links = {
|
||||
'type': 'array',
|
||||
'items': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'rel': {
|
||||
'type': 'string',
|
||||
'enum': ['self', 'bookmark'],
|
||||
},
|
||||
'href': {
|
||||
'type': 'string',
|
||||
'format': 'uri',
|
||||
},
|
||||
},
|
||||
'required': ['rel', 'href'],
|
||||
'additionalProperties': False,
|
||||
},
|
||||
}
|
||||
|
||||
collection_links = {
|
||||
'type': 'array',
|
||||
'items': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'rel': {
|
||||
'const': 'next',
|
||||
},
|
||||
'href': {
|
||||
'type': 'string',
|
||||
'format': 'uri',
|
||||
},
|
||||
},
|
||||
'required': ['rel', 'href'],
|
||||
'additionalProperties': False,
|
||||
},
|
||||
# there should be one and only one link object
|
||||
'minItems': 1,
|
||||
'maxItems': 1,
|
||||
}
|
||||
@@ -20,40 +20,44 @@ FAKE_REQUEST_ID1 = 'req-3293a3f1-b44c-4609-b8d2-d81b105636b8'
|
||||
FAKE_REQUEST_ID2 = 'req-25517360-b757-47d3-be45-0e8d2a01b36a'
|
||||
FAKE_ACTION_ID1 = 123
|
||||
FAKE_ACTION_ID2 = 456
|
||||
FAKE_HOST_ID1 = '74824069503a752aaa3abf194f73200fcdd117ef70ab28b576e5bf7a'
|
||||
FAKE_HOST_ID2 = '858f5ed465b4967dd1306a38078e9b83b8705bdedfa7f16f898119b4'
|
||||
# the value of the hostId fields depends on the value of the projectID field,
|
||||
# so we define these statically
|
||||
FAKE_PROJECT_ID1 = '9ccc9bd7-8b23-4d57-8421-291fe888bdc6'
|
||||
FAKE_PROJECT_ID2 = '427b71e6-49d2-4c30-a8a0-d23adfe772e2'
|
||||
FAKE_HOST_ID1 = 'b7e03ca48116ea93152de5d2eff1c69f515a5198f3cfbe59103faf17'
|
||||
FAKE_HOST_ID2 = '7bd9ecf0b8cec52cd1410aee9b4bee5370c698bfc11f9478b35b80e2'
|
||||
|
||||
FAKE_ACTIONS = {
|
||||
FAKE_UUID: {
|
||||
FAKE_REQUEST_ID1: {'id': FAKE_ACTION_ID1,
|
||||
'action': 'reboot',
|
||||
'instance_uuid': FAKE_UUID,
|
||||
'request_id': FAKE_REQUEST_ID1,
|
||||
'project_id': '147',
|
||||
'user_id': '789',
|
||||
'start_time': datetime.datetime(
|
||||
2012, 12, 5, 0, 0, 0, 0),
|
||||
'finish_time': None,
|
||||
'message': '',
|
||||
'created_at': None,
|
||||
'updated_at': None,
|
||||
'deleted_at': None,
|
||||
'deleted': False,
|
||||
FAKE_REQUEST_ID1: {
|
||||
'id': FAKE_ACTION_ID1,
|
||||
'action': 'reboot',
|
||||
'instance_uuid': FAKE_UUID,
|
||||
'request_id': FAKE_REQUEST_ID1,
|
||||
'project_id': FAKE_PROJECT_ID1,
|
||||
'user_id': '091d35ff-a42d-4717-8ba4-7dabfa7b13a4',
|
||||
'start_time': datetime.datetime(2012, 12, 5, 0, 0, 0, 0),
|
||||
'finish_time': None,
|
||||
'message': '',
|
||||
'created_at': None,
|
||||
'updated_at': None,
|
||||
'deleted_at': None,
|
||||
'deleted': False,
|
||||
},
|
||||
FAKE_REQUEST_ID2: {'id': FAKE_ACTION_ID2,
|
||||
'action': 'resize',
|
||||
'instance_uuid': FAKE_UUID,
|
||||
'request_id': FAKE_REQUEST_ID2,
|
||||
'user_id': '789',
|
||||
'project_id': '842',
|
||||
'start_time': datetime.datetime(
|
||||
2012, 12, 5, 1, 0, 0, 0),
|
||||
'finish_time': None,
|
||||
'message': '',
|
||||
'created_at': None,
|
||||
'updated_at': None,
|
||||
'deleted_at': None,
|
||||
'deleted': False,
|
||||
FAKE_REQUEST_ID2: {
|
||||
'id': FAKE_ACTION_ID2,
|
||||
'action': 'resize',
|
||||
'instance_uuid': FAKE_UUID,
|
||||
'request_id': FAKE_REQUEST_ID2,
|
||||
'project_id': FAKE_PROJECT_ID2,
|
||||
'user_id': 'c0ab3ebb-ad1b-4b60-8e63-b8a5656315d0',
|
||||
'start_time': datetime.datetime(2012, 12, 5, 1, 0, 0, 0),
|
||||
'finish_time': None,
|
||||
'message': '',
|
||||
'created_at': None,
|
||||
'updated_at': None,
|
||||
'deleted_at': None,
|
||||
'deleted': False,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user