Merge "api: Add response body schemas for migrations API"

This commit is contained in:
Zuul
2026-01-24 08:29:20 +00:00
committed by Gerrit Code Review
5 changed files with 117 additions and 29 deletions
+4 -2
View File
@@ -4806,7 +4806,8 @@ migrate_dest_host:
type: string
migrate_dest_node:
description: |
The target node for a migration.
The target node for a migration. This will be ``null`` if pre-migration
checks fail due to e.g. insufficient resources.
in: body
required: true
type: string
@@ -4854,7 +4855,8 @@ migrate_source_compute:
type: string
migrate_source_node:
description: |
The source node for a migration.
The source node for a migration. This will be ``null`` if pre-migration
checks fail due to e.g. insufficient resources.
in: body
required: true
type: string
+9 -5
View File
@@ -27,6 +27,7 @@ from nova.objects import fields
from nova.policies import migrations as migrations_policies
@validation.validated
class MigrationsController(wsgi.Controller):
"""Controller for accessing migrations in OpenStack API."""
@@ -179,11 +180,14 @@ class MigrationsController(wsgi.Controller):
@wsgi.expected_errors((), "2.1", "2.58")
@wsgi.expected_errors(400, "2.59")
@validation.query_schema(schema.list_query_schema_v20, "2.0", "2.22")
@validation.query_schema(schema.list_query_schema_v20, "2.23", "2.58")
@validation.query_schema(schema.list_query_params_v259, "2.59", "2.65")
@validation.query_schema(schema.list_query_params_v266, "2.66", "2.79")
@validation.query_schema(schema.list_query_params_v280, "2.80")
@validation.query_schema(schema.index_query_v20, "2.0", "2.58")
@validation.query_schema(schema.index_query_v259, "2.59", "2.65")
@validation.query_schema(schema.index_query_v266, "2.66", "2.79")
@validation.query_schema(schema.index_query_v280, "2.80")
@validation.response_body_schema(schema.index_response_v20, "2.0", "2.22")
@validation.response_body_schema(schema.index_response_v223, "2.23", "2.58") # noqa: E501
@validation.response_body_schema(schema.index_response_v259, "2.59", "2.79") # noqa: E501
@validation.response_body_schema(schema.index_response_v280, "2.80")
def index(self, req):
"""Return all migrations using the query parameters as filters."""
add_link = False
@@ -15,8 +15,10 @@
import copy
from nova.api.validation import parameter_types
from nova.api.validation import response_types
list_query_schema_v20 = {
index_query_v20 = {
'type': 'object',
'properties': {
'hidden': parameter_types.common_query_param,
@@ -30,8 +32,8 @@ list_query_schema_v20 = {
'additionalProperties': True
}
list_query_params_v259 = copy.deepcopy(list_query_schema_v20)
list_query_params_v259['properties'].update({
index_query_v259 = copy.deepcopy(index_query_v20)
index_query_v259['properties'].update({
# The 2.59 microversion added support for paging by limit and marker
# and filtering by changes-since.
'limit': parameter_types.single_param(
@@ -40,18 +42,97 @@ list_query_params_v259['properties'].update({
'changes-since': parameter_types.single_param(
{'type': 'string', 'format': 'date-time'}),
})
list_query_params_v259['additionalProperties'] = False
index_query_v259['additionalProperties'] = False
list_query_params_v266 = copy.deepcopy(list_query_params_v259)
list_query_params_v266['properties'].update({
index_query_v266 = copy.deepcopy(index_query_v259)
index_query_v266['properties'].update({
'changes-before': parameter_types.single_param(
{'type': 'string', 'format': 'date-time'}),
})
list_query_params_v280 = copy.deepcopy(list_query_params_v266)
list_query_params_v280['properties'].update({
index_query_v280 = copy.deepcopy(index_query_v266)
index_query_v280['properties'].update({
# The 2.80 microversion added support for filtering migrations
# by user_id and/or project_id
'user_id': parameter_types.single_param({'type': 'string'}),
'project_id': parameter_types.single_param({'type': 'string'}),
})
index_response_v20 = {
'type': 'object',
'properties': {
'migrations': {
'type': 'array',
'items': {
'type': 'object',
'properties': {
'created_at': {'type': 'string', 'format': 'date-time'},
'dest_compute': {'type': ['string', 'null']},
'dest_host': {'type': ['string', 'null']},
'dest_node': {'type': ['string', 'null']},
'id': {'type': 'integer'},
'instance_uuid': {'type': 'string', 'format': 'uuid'},
'new_instance_type_id': {'type': ['integer', 'null']},
'old_instance_type_id': {'type': ['integer', 'null']},
'source_compute': {'type': ['string', 'null']},
'source_node': {'type': ['string', 'null']},
'status': {'type': 'string'},
'updated_at': {
'type': ['string', 'null'], 'format': 'date-time'
},
},
'required': [
'created_at',
'dest_compute',
'dest_host',
'dest_node',
'id',
'instance_uuid',
'new_instance_type_id',
'old_instance_type_id',
'source_compute',
'source_node',
'status',
'updated_at',
],
'additionalProperties': False,
},
},
},
'required': ['migrations'],
'additionalProperties': False,
}
index_response_v223 = copy.deepcopy(index_response_v20)
index_response_v223['properties']['migrations']['items']['properties'].update({
'migration_type': {
'type': 'string',
'enum': [
'migration', 'resize', 'live-migration', 'evacuation'
],
},
'links': response_types.links,
})
index_response_v223['properties']['migrations']['items']['required'].append(
'migration_type'
)
index_response_v259 = copy.deepcopy(index_response_v223)
index_response_v259['properties'].update({
'migrations_links': response_types.collection_links,
})
index_response_v259['properties']['migrations']['items']['properties'].update({
'uuid': {'type': 'string', 'format': 'uuid'},
})
index_response_v259['properties']['migrations']['items']['required'].append(
'uuid'
)
index_response_v280 = copy.deepcopy(index_response_v259)
index_response_v280['properties']['migrations']['items']['properties'].update({
'project_id': parameter_types.project_id,
'user_id': parameter_types.user_id,
})
index_response_v280['properties']['migrations']['items']['required'].extend([
'project_id', 'user_id',
])
@@ -55,8 +55,8 @@ fake_migrations = [
'deleted': False,
'uuid': uuids.migration1,
'cross_cell_move': False,
'user_id': None,
'project_id': None
'user_id': uuids.user_id,
'project_id': uuids.project_id,
},
# non in-progress live migration
{
@@ -85,8 +85,8 @@ fake_migrations = [
'deleted': False,
'uuid': uuids.migration2,
'cross_cell_move': False,
'user_id': None,
'project_id': None
'user_id': uuids.user_id,
'project_id': uuids.project_id,
},
# in-progress resize
{
@@ -115,8 +115,8 @@ fake_migrations = [
'deleted': False,
'uuid': uuids.migration3,
'cross_cell_move': False,
'user_id': None,
'project_id': None
'user_id': uuids.user_id,
'project_id': uuids.project_id,
},
# non in-progress resize
{
@@ -145,8 +145,8 @@ fake_migrations = [
'deleted': False,
'uuid': uuids.migration4,
'cross_cell_move': False,
'user_id': None,
'project_id': None
'user_id': uuids.user_id,
'project_id': uuids.project_id,
}
]
+7 -6
View File
@@ -64,7 +64,7 @@ class MigrationsPolicyTest(base.BasePolicyTest):
'dest_compute': 'compute2',
'dest_host': '1.2.3.4',
'status': 'running',
'instance_uuid': 1234,
'instance_uuid': uuids.instance,
'old_instance_type_id': 1,
'new_instance_type_id': 2,
'migration_type': 'migration',
@@ -81,8 +81,8 @@ class MigrationsPolicyTest(base.BasePolicyTest):
'deleted': False,
'uuid': uuids.migration1,
'cross_cell_move': False,
'user_id': None,
'project_id': 'other_project'
'user_id': uuids.user_id,
'project_id': uuids.other_project_id,
}
]
if project_id is None:
@@ -239,17 +239,18 @@ class MigrationsPolicyTest(base.BasePolicyTest):
# NOTE(gmaan): Only Admin (not Project manager) can list the
# other project migrations.
for auth_cxtx in self.project_admin_authorized_contexts:
project_id = 'other_project'
project_id = uuids.other_project_id
req, _ = self.prepare_microversion_request(
auth_cxtx, mock_get, project_id=project_id)
resp = self.controller.index(req)
# NOTE(gmaan): Check their own project migrations are returned
self.assertEqual(1, len(resp['migrations']))
self.assertEqual('other_project',
self.assertEqual(project_id,
resp['migrations'][0]['project_id'])
for unauth_cxtx in (self.all_contexts -
set(self.project_admin_authorized_contexts)):
project_id = 'other_project'
project_id = uuids.other_project_id
req, _ = self.prepare_microversion_request(
unauth_cxtx, mock_get, project_id=project_id)
exc = self.assertRaises(