diff --git a/api-ref/source/os-migrations.inc b/api-ref/source/os-migrations.inc index 185e40292b6..2cfd948666f 100644 --- a/api-ref/source/os-migrations.inc +++ b/api-ref/source/os-migrations.inc @@ -39,6 +39,8 @@ Request - marker: migration_marker - changes-since: changes_since_migration - changes-before: changes_before_migration + - user_id: user_id_query_migrations + - project_id: project_id_query_migrations Response -------- @@ -62,19 +64,20 @@ Response - links: migration_links_2_23 - uuid: migration_uuid - migrations_links: migration_next_links_2_59 + - user_id: user_id_migration_2_80 + - project_id: project_id_migration_2_80 **Example List Migrations: JSON response** .. literalinclude:: ../../doc/api_samples/os-migrations/migrations-get.json :language: javascript -**Example List Migrations (v2.59):** +**Example List Migrations (v2.80):** -.. literalinclude:: ../../doc/api_samples/os-migrations/v2.59/migrations-get.json +.. literalinclude:: ../../doc/api_samples/os-migrations/v2.80/migrations-get.json :language: javascript -**Example List Migrations With Paging (v2.59):** +**Example List Migrations With Paging (v2.80):** -.. literalinclude:: ../../doc/api_samples/os-migrations/v2.59/migrations-get-with-limit.json +.. literalinclude:: ../../doc/api_samples/os-migrations/v2.80/migrations-get-with-limit.json :language: javascript - diff --git a/api-ref/source/parameters.yaml b/api-ref/source/parameters.yaml index 824059dd4f9..2f22b0eda3d 100644 --- a/api-ref/source/parameters.yaml +++ b/api-ref/source/parameters.yaml @@ -1133,6 +1133,13 @@ progress_query_server: in: query required: false type: integer +project_id_query_migrations: + description: | + Filter the migrations by the given project ID. + in: query + required: false + type: string + min_version: 2.80 project_id_query_server: description: | Filter the list of servers by the given project ID. @@ -1409,6 +1416,13 @@ usage_marker: required: false type: string min_version: 2.40 +user_id_query_migrations: + description: | + Filter the migrations by the given user ID. + in: query + required: false + type: string + min_version: 2.80 user_id_query_quota: description: | ID of user to list the quotas for. @@ -5697,6 +5711,14 @@ project_id: in: body required: false type: string +project_id_migration_2_80: + description: | + The ID of the project which initiated the server migration. The value + may be ``null`` for older migration records. + in: body + required: true + type: string + min_version: 2.80 project_id_server: description: | The ID of the project that this server belongs to. @@ -7113,6 +7135,14 @@ user_id: in: body required: true type: string +user_id_migration_2_80: + description: | + The ID of the user which initiated the server migration. The value + may be ``null`` for older migration records. + in: body + required: true + type: string + min_version: 2.80 user_id_server_action: description: | The ID of the user which initiated the server action. diff --git a/api-ref/source/server-migrations.inc b/api-ref/source/server-migrations.inc index 4a2ac97f4e1..7608937eb02 100644 --- a/api-ref/source/server-migrations.inc +++ b/api-ref/source/server-migrations.inc @@ -53,10 +53,12 @@ Response - status: migrate_status - updated_at: updated - uuid: migration_uuid + - user_id: user_id_migration_2_80 + - project_id: project_id_migration_2_80 -**Example List Migrations (2.59)** +**Example List Migrations (2.80)** -.. literalinclude:: ../../doc/api_samples/server-migrations/v2.59/migrations-index.json +.. literalinclude:: ../../doc/api_samples/server-migrations/v2.80/migrations-index.json :language: javascript Show Migration Details @@ -107,10 +109,12 @@ Response - status: migrate_status - updated_at: updated - uuid: migration_uuid + - user_id: user_id_migration_2_80 + - project_id: project_id_migration_2_80 -**Example Show Migration Details (2.59)** +**Example Show Migration Details (2.80)** -.. literalinclude:: ../../doc/api_samples/server-migrations/v2.59/migrations-get.json +.. literalinclude:: ../../doc/api_samples/server-migrations/v2.80/migrations-get.json :language: javascript Force Migration Complete Action (force_complete Action) diff --git a/doc/api_samples/os-migrations/v2.80/migrations-get-with-changes-before.json b/doc/api_samples/os-migrations/v2.80/migrations-get-with-changes-before.json new file mode 100644 index 00000000000..359d965c903 --- /dev/null +++ b/doc/api_samples/os-migrations/v2.80/migrations-get-with-changes-before.json @@ -0,0 +1,32 @@ +{ + "migrations": [ + { + "created_at": "2016-01-29T11:42:02.000000", + "dest_compute": "compute2", + "dest_host": "1.2.3.4", + "dest_node": "node2", + "id": 1, + "instance_uuid": "8600d31b-d1a1-4632-b2ff-45c2be1a70ff", + "links": [ + { + "href": "http://openstack.example.com/v2.1/6f70656e737461636b20342065766572/servers/8600d31b-d1a1-4632-b2ff-45c2be1a70ff/migrations/1", + "rel": "self" + }, + { + "href": "http://openstack.example.com/6f70656e737461636b20342065766572/servers/8600d31b-d1a1-4632-b2ff-45c2be1a70ff/migrations/1", + "rel": "bookmark" + } + ], + "new_instance_type_id": 1, + "old_instance_type_id": 1, + "source_compute": "compute1", + "source_node": "node1", + "status": "running", + "migration_type": "live-migration", + "updated_at": "2016-01-29T11:42:02.000000", + "uuid": "12341d4b-346a-40d0-83c6-5f4f6892b650", + "user_id": "5c48ebaa-193f-4c5d-948a-f559cc92cd5e", + "project_id": "ef92ccff-00f3-46e4-b015-811110e36ee4" + } + ] +} diff --git a/doc/api_samples/os-migrations/v2.80/migrations-get-with-changes-since.json b/doc/api_samples/os-migrations/v2.80/migrations-get-with-changes-since.json new file mode 100644 index 00000000000..86c52f863f1 --- /dev/null +++ b/doc/api_samples/os-migrations/v2.80/migrations-get-with-changes-since.json @@ -0,0 +1,40 @@ +{ + "migrations": [ + { + "created_at": "2016-06-23T14:42:02.000000", + "dest_compute": "compute20", + "dest_host": "5.6.7.8", + "dest_node": "node20", + "id": 4, + "instance_uuid": "9128d044-7b61-403e-b766-7547076ff6c1", + "new_instance_type_id": 6, + "old_instance_type_id": 5, + "source_compute": "compute10", + "source_node": "node10", + "status": "migrating", + "migration_type": "resize", + "updated_at": "2016-06-23T14:42:02.000000", + "uuid": "42341d4b-346a-40d0-83c6-5f4f6892b650", + "user_id": "78348f0e-97ee-4d70-ad34-189692673ea2", + "project_id": "9842f0f7-1229-4355-afe7-15ebdbb8c3d8" + }, + { + "created_at": "2016-06-23T13:42:02.000000", + "dest_compute": "compute20", + "dest_host": "5.6.7.8", + "dest_node": "node20", + "id": 3, + "instance_uuid": "9128d044-7b61-403e-b766-7547076ff6c1", + "new_instance_type_id": 6, + "old_instance_type_id": 5, + "source_compute": "compute10", + "source_node": "node10", + "status": "error", + "migration_type": "resize", + "updated_at": "2016-06-23T13:42:02.000000", + "uuid": "32341d4b-346a-40d0-83c6-5f4f6892b650", + "user_id": "78348f0e-97ee-4d70-ad34-189692673ea2", + "project_id": "9842f0f7-1229-4355-afe7-15ebdbb8c3d8" + } + ] +} diff --git a/doc/api_samples/os-migrations/v2.80/migrations-get-with-limit.json b/doc/api_samples/os-migrations/v2.80/migrations-get-with-limit.json new file mode 100644 index 00000000000..a2ed0e1e05b --- /dev/null +++ b/doc/api_samples/os-migrations/v2.80/migrations-get-with-limit.json @@ -0,0 +1,28 @@ + { + "migrations": [ + { + "created_at": "2016-06-23T14:42:02.000000", + "dest_compute": "compute20", + "dest_host": "5.6.7.8", + "dest_node": "node20", + "id": 4, + "instance_uuid": "9128d044-7b61-403e-b766-7547076ff6c1", + "new_instance_type_id": 6, + "old_instance_type_id": 5, + "source_compute": "compute10", + "source_node": "node10", + "status": "migrating", + "migration_type": "resize", + "updated_at": "2016-06-23T14:42:02.000000", + "uuid": "42341d4b-346a-40d0-83c6-5f4f6892b650", + "user_id": "78348f0e-97ee-4d70-ad34-189692673ea2", + "project_id": "9842f0f7-1229-4355-afe7-15ebdbb8c3d8" + } + ], + "migrations_links": [ + { + "href": "http://openstack.example.com/v2.1/6f70656e737461636b20342065766572/os-migrations?limit=1&marker=42341d4b-346a-40d0-83c6-5f4f6892b650", + "rel": "next" + } + ] +} diff --git a/doc/api_samples/os-migrations/v2.80/migrations-get-with-marker.json b/doc/api_samples/os-migrations/v2.80/migrations-get-with-marker.json new file mode 100644 index 00000000000..359d965c903 --- /dev/null +++ b/doc/api_samples/os-migrations/v2.80/migrations-get-with-marker.json @@ -0,0 +1,32 @@ +{ + "migrations": [ + { + "created_at": "2016-01-29T11:42:02.000000", + "dest_compute": "compute2", + "dest_host": "1.2.3.4", + "dest_node": "node2", + "id": 1, + "instance_uuid": "8600d31b-d1a1-4632-b2ff-45c2be1a70ff", + "links": [ + { + "href": "http://openstack.example.com/v2.1/6f70656e737461636b20342065766572/servers/8600d31b-d1a1-4632-b2ff-45c2be1a70ff/migrations/1", + "rel": "self" + }, + { + "href": "http://openstack.example.com/6f70656e737461636b20342065766572/servers/8600d31b-d1a1-4632-b2ff-45c2be1a70ff/migrations/1", + "rel": "bookmark" + } + ], + "new_instance_type_id": 1, + "old_instance_type_id": 1, + "source_compute": "compute1", + "source_node": "node1", + "status": "running", + "migration_type": "live-migration", + "updated_at": "2016-01-29T11:42:02.000000", + "uuid": "12341d4b-346a-40d0-83c6-5f4f6892b650", + "user_id": "5c48ebaa-193f-4c5d-948a-f559cc92cd5e", + "project_id": "ef92ccff-00f3-46e4-b015-811110e36ee4" + } + ] +} diff --git a/doc/api_samples/os-migrations/v2.80/migrations-get-with-user-or-project-id.json b/doc/api_samples/os-migrations/v2.80/migrations-get-with-user-or-project-id.json new file mode 100644 index 00000000000..f7994fd400c --- /dev/null +++ b/doc/api_samples/os-migrations/v2.80/migrations-get-with-user-or-project-id.json @@ -0,0 +1,50 @@ +{ + "migrations": [ + { + "created_at": "2016-01-29T12:42:02.000000", + "dest_compute": "compute2", + "dest_host": "1.2.3.4", + "dest_node": "node2", + "id": 2, + "instance_uuid": "8600d31b-d1a1-4632-b2ff-45c2be1a70ff", + "new_instance_type_id": 1, + "old_instance_type_id": 1, + "source_compute": "compute1", + "source_node": "node1", + "status": "error", + "migration_type": "live-migration", + "updated_at": "2016-01-29T12:42:02.000000", + "uuid": "22341d4b-346a-40d0-83c6-5f4f6892b650", + "user_id": "5c48ebaa-193f-4c5d-948a-f559cc92cd5e", + "project_id": "ef92ccff-00f3-46e4-b015-811110e36ee4" + }, + { + "created_at": "2016-01-29T11:42:02.000000", + "dest_compute": "compute2", + "dest_host": "1.2.3.4", + "dest_node": "node2", + "id": 1, + "instance_uuid": "8600d31b-d1a1-4632-b2ff-45c2be1a70ff", + "links": [ + { + "href": "http://openstack.example.com/v2.1/6f70656e737461636b20342065766572/servers/8600d31b-d1a1-4632-b2ff-45c2be1a70ff/migrations/1", + "rel": "self" + }, + { + "href": "http://openstack.example.com/6f70656e737461636b20342065766572/servers/8600d31b-d1a1-4632-b2ff-45c2be1a70ff/migrations/1", + "rel": "bookmark" + } + ], + "new_instance_type_id": 1, + "old_instance_type_id": 1, + "source_compute": "compute1", + "source_node": "node1", + "status": "running", + "migration_type": "live-migration", + "updated_at": "2016-01-29T11:42:02.000000", + "uuid": "12341d4b-346a-40d0-83c6-5f4f6892b650", + "user_id": "5c48ebaa-193f-4c5d-948a-f559cc92cd5e", + "project_id": "ef92ccff-00f3-46e4-b015-811110e36ee4" + } + ] +} diff --git a/doc/api_samples/os-migrations/v2.80/migrations-get.json b/doc/api_samples/os-migrations/v2.80/migrations-get.json new file mode 100644 index 00000000000..ca568263946 --- /dev/null +++ b/doc/api_samples/os-migrations/v2.80/migrations-get.json @@ -0,0 +1,86 @@ +{ + "migrations": [ + { + "created_at": "2016-06-23T14:42:02.000000", + "dest_compute": "compute20", + "dest_host": "5.6.7.8", + "dest_node": "node20", + "id": 4, + "instance_uuid": "9128d044-7b61-403e-b766-7547076ff6c1", + "new_instance_type_id": 6, + "old_instance_type_id": 5, + "source_compute": "compute10", + "source_node": "node10", + "status": "migrating", + "migration_type": "resize", + "updated_at": "2016-06-23T14:42:02.000000", + "uuid": "42341d4b-346a-40d0-83c6-5f4f6892b650", + "user_id": "78348f0e-97ee-4d70-ad34-189692673ea2", + "project_id": "9842f0f7-1229-4355-afe7-15ebdbb8c3d8" + }, + { + "created_at": "2016-06-23T13:42:02.000000", + "dest_compute": "compute20", + "dest_host": "5.6.7.8", + "dest_node": "node20", + "id": 3, + "instance_uuid": "9128d044-7b61-403e-b766-7547076ff6c1", + "new_instance_type_id": 6, + "old_instance_type_id": 5, + "source_compute": "compute10", + "source_node": "node10", + "status": "error", + "migration_type": "resize", + "updated_at": "2016-06-23T13:42:02.000000", + "uuid": "32341d4b-346a-40d0-83c6-5f4f6892b650", + "user_id": "78348f0e-97ee-4d70-ad34-189692673ea2", + "project_id": "9842f0f7-1229-4355-afe7-15ebdbb8c3d8" + }, + { + "created_at": "2016-01-29T12:42:02.000000", + "dest_compute": "compute2", + "dest_host": "1.2.3.4", + "dest_node": "node2", + "id": 2, + "instance_uuid": "8600d31b-d1a1-4632-b2ff-45c2be1a70ff", + "new_instance_type_id": 1, + "old_instance_type_id": 1, + "source_compute": "compute1", + "source_node": "node1", + "status": "error", + "migration_type": "live-migration", + "updated_at": "2016-01-29T12:42:02.000000", + "uuid": "22341d4b-346a-40d0-83c6-5f4f6892b650", + "user_id": "5c48ebaa-193f-4c5d-948a-f559cc92cd5e", + "project_id": "ef92ccff-00f3-46e4-b015-811110e36ee4" + }, + { + "created_at": "2016-01-29T11:42:02.000000", + "dest_compute": "compute2", + "dest_host": "1.2.3.4", + "dest_node": "node2", + "id": 1, + "instance_uuid": "8600d31b-d1a1-4632-b2ff-45c2be1a70ff", + "links": [ + { + "href": "http://openstack.example.com/v2.1/6f70656e737461636b20342065766572/servers/8600d31b-d1a1-4632-b2ff-45c2be1a70ff/migrations/1", + "rel": "self" + }, + { + "href": "http://openstack.example.com/6f70656e737461636b20342065766572/servers/8600d31b-d1a1-4632-b2ff-45c2be1a70ff/migrations/1", + "rel": "bookmark" + } + ], + "new_instance_type_id": 1, + "old_instance_type_id": 1, + "source_compute": "compute1", + "source_node": "node1", + "status": "running", + "migration_type": "live-migration", + "updated_at": "2016-01-29T11:42:02.000000", + "uuid": "12341d4b-346a-40d0-83c6-5f4f6892b650", + "user_id": "5c48ebaa-193f-4c5d-948a-f559cc92cd5e", + "project_id": "ef92ccff-00f3-46e4-b015-811110e36ee4" + } + ] +} diff --git a/doc/api_samples/server-migrations/v2.80/live-migrate-server.json b/doc/api_samples/server-migrations/v2.80/live-migrate-server.json new file mode 100644 index 00000000000..c2f5bf6c989 --- /dev/null +++ b/doc/api_samples/server-migrations/v2.80/live-migrate-server.json @@ -0,0 +1,6 @@ +{ + "os-migrateLive": { + "host": null, + "block_migration": "auto" + } +} diff --git a/doc/api_samples/server-migrations/v2.80/migrations-get.json b/doc/api_samples/server-migrations/v2.80/migrations-get.json new file mode 100644 index 00000000000..7de0e63201e --- /dev/null +++ b/doc/api_samples/server-migrations/v2.80/migrations-get.json @@ -0,0 +1,23 @@ +{ + "migration": { + "created_at": "2016-01-29T13:42:02.000000", + "dest_compute": "compute2", + "dest_host": "1.2.3.4", + "dest_node": "node2", + "id": 1, + "server_uuid": "4cfba335-03d8-49b2-8c52-e69043d1e8fe", + "source_compute": "compute1", + "source_node": "node1", + "status": "running", + "memory_total_bytes": 123456, + "memory_processed_bytes": 12345, + "memory_remaining_bytes": 111111, + "disk_total_bytes": 234567, + "disk_processed_bytes": 23456, + "disk_remaining_bytes": 211111, + "updated_at": "2016-01-29T13:42:02.000000", + "uuid": "12341d4b-346a-40d0-83c6-5f4f6892b650", + "user_id": "8dbaa0f0-ab95-4ffe-8cb4-9c89d2ac9d24", + "project_id": "5f705771-3aa9-4f4c-8660-0d9522ffdbea" + } +} diff --git a/doc/api_samples/server-migrations/v2.80/migrations-index.json b/doc/api_samples/server-migrations/v2.80/migrations-index.json new file mode 100644 index 00000000000..460529a5896 --- /dev/null +++ b/doc/api_samples/server-migrations/v2.80/migrations-index.json @@ -0,0 +1,25 @@ +{ + "migrations": [ + { + "created_at": "2016-01-29T13:42:02.000000", + "dest_compute": "compute2", + "dest_host": "1.2.3.4", + "dest_node": "node2", + "id": 1, + "server_uuid": "4cfba335-03d8-49b2-8c52-e69043d1e8fe", + "source_compute": "compute1", + "source_node": "node1", + "status": "running", + "memory_total_bytes": 123456, + "memory_processed_bytes": 12345, + "memory_remaining_bytes": 111111, + "disk_total_bytes": 234567, + "disk_processed_bytes": 23456, + "disk_remaining_bytes": 211111, + "updated_at": "2016-01-29T13:42:02.000000", + "uuid": "12341d4b-346a-40d0-83c6-5f4f6892b650", + "user_id": "8dbaa0f0-ab95-4ffe-8cb4-9c89d2ac9d24", + "project_id": "5f705771-3aa9-4f4c-8660-0d9522ffdbea" + } + ] +} diff --git a/doc/api_samples/versions/v21-version-get-resp.json b/doc/api_samples/versions/v21-version-get-resp.json index 8712419940b..a604ada7be2 100644 --- a/doc/api_samples/versions/v21-version-get-resp.json +++ b/doc/api_samples/versions/v21-version-get-resp.json @@ -19,7 +19,7 @@ } ], "status": "CURRENT", - "version": "2.79", + "version": "2.80", "min_version": "2.1", "updated": "2013-07-23T11:33:21Z" } diff --git a/doc/api_samples/versions/versions-get-resp.json b/doc/api_samples/versions/versions-get-resp.json index 59e804c6299..b9e556a075f 100644 --- a/doc/api_samples/versions/versions-get-resp.json +++ b/doc/api_samples/versions/versions-get-resp.json @@ -22,7 +22,7 @@ } ], "status": "CURRENT", - "version": "2.79", + "version": "2.80", "min_version": "2.1", "updated": "2013-07-23T11:33:21Z" } diff --git a/nova/api/openstack/api_version_request.py b/nova/api/openstack/api_version_request.py index a6982660ae9..f95e52010f6 100644 --- a/nova/api/openstack/api_version_request.py +++ b/nova/api/openstack/api_version_request.py @@ -211,6 +211,12 @@ this via the response from ``GET /servers/{server_id}/os-volume_attachments`` and ``GET /servers/{server_id}/os-volume_attachments/{volume_id}``. + * 2.80 - Adds support for optional query parameters ``user_id`` and + ``project_id`` to the ``GET /os-migrations`` API and exposes + ``user_id`` and ``project_id`` via the response from + ``GET /os-migrations``, + ``GET /servers/{server_id}/migrations``, and + ``GET /servers/{server_id}/migrations/{migration_id}``. """ # The minimum and maximum versions of the API supported @@ -219,7 +225,7 @@ # Note(cyeoh): This only applies for the v2.1 API once microversions # support is fully merged. It does not affect the V2 API. _MIN_API_VERSION = "2.1" -_MAX_API_VERSION = "2.79" +_MAX_API_VERSION = "2.80" DEFAULT_API_VERSION = _MIN_API_VERSION # Almost all proxy APIs which are related to network, images and baremetal diff --git a/nova/api/openstack/compute/migrations.py b/nova/api/openstack/compute/migrations.py index 5be64d6de21..b787bc2d661 100644 --- a/nova/api/openstack/compute/migrations.py +++ b/nova/api/openstack/compute/migrations.py @@ -13,6 +13,7 @@ from oslo_utils import timeutils from webob import exc +from nova.api.openstack import api_version_request from nova.api.openstack import common from nova.api.openstack.compute.schemas import migrations as schema_migrations from nova.api.openstack.compute.views import migrations as migrations_view @@ -35,7 +36,8 @@ def __init__(self): super(MigrationsController, self).__init__() self.compute_api = compute.API() - def _output(self, req, migrations_obj, add_link=False, add_uuid=False): + def _output(self, req, migrations_obj, add_link=False, + add_uuid=False, add_user_project=False): """Returns the desired output of the API from an object. From a MigrationsList's object this method returns a list of @@ -62,10 +64,11 @@ def _output(self, req, migrations_obj, add_link=False, add_uuid=False): if 'memory_total' in obj: for key in detail_keys: del obj[key] - if 'user_id' in obj: - del obj['user_id'] - if 'project_id' in obj: - del obj['project_id'] + if not add_user_project: + if 'user_id' in obj: + del obj['user_id'] + if 'project_id' in obj: + del obj['project_id'] # NOTE(Shaohe Feng) above version 2.23, add migration_type for all # kinds of migration, but we only add links just for in-progress # live-migration. @@ -127,7 +130,9 @@ def _index(self, req, add_link=False, next_link=False, add_uuid=False, migrations = self.compute_api.get_migrations( context, search_opts) - migrations = self._output(req, migrations, add_link, add_uuid) + add_user_project = api_version_request.is_supported(req, '2.80') + migrations = self._output(req, migrations, add_link, + add_uuid, add_user_project) migrations_dict = {'migrations': migrations} if next_link: @@ -168,7 +173,9 @@ def index(self, req): @wsgi.Controller.api_version("2.66") # noqa @wsgi.expected_errors(400) @validation.query_schema(schema_migrations.list_query_params_v266, - "2.66") + "2.66", "2.79") + @validation.query_schema(schema_migrations.list_query_params_v280, + "2.80") def index(self, req): """Return all migrations using the query parameters as filters.""" limit, marker = common.get_limit_and_marker(req) diff --git a/nova/api/openstack/compute/rest_api_version_history.rst b/nova/api/openstack/compute/rest_api_version_history.rst index bbb5aff2efa..8fbb3dba969 100644 --- a/nova/api/openstack/compute/rest_api_version_history.rst +++ b/nova/api/openstack/compute/rest_api_version_history.rst @@ -1029,3 +1029,22 @@ The affected APIs are as follows: * ``POST /servers/{server_id}/os-volume_attachments`` * ``GET /servers/{server_id}/os-volume_attachments`` * ``GET /servers/{server_id}/os-volume_attachments/{volume_id}`` + +2.80 +---- + +Microversion 2.80 changes the list migrations APIs and the os-migrations API. + +Expose the ``user_id`` and ``project_id`` fields in the following APIs: + +* ``GET /os-migrations`` +* ``GET /servers/{server_id}/migrations`` +* ``GET /servers/{server_id}/migrations/{migration_id}`` + +The ``GET /os-migrations`` API will also have optional ``user_id`` and +``project_id`` query parameters for filtering migrations by user and/or +project, for example: + +* ``GET /os-migrations?user_id=ef9d34b4-45d0-4530-871b-3fb535988394`` +* ``GET /os-migrations?project_id=011ee9f4-8f16-4c38-8633-a254d420fd54`` +* ``GET /os-migrations?user_id=ef9d34b4-45d0-4530-871b-3fb535988394&project_id=011ee9f4-8f16-4c38-8633-a254d420fd54`` diff --git a/nova/api/openstack/compute/schemas/migrations.py b/nova/api/openstack/compute/schemas/migrations.py index 6892aa07d0c..0979e58c9dd 100644 --- a/nova/api/openstack/compute/schemas/migrations.py +++ b/nova/api/openstack/compute/schemas/migrations.py @@ -47,3 +47,11 @@ '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({ + # 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'}), +}) diff --git a/nova/api/openstack/compute/server_migrations.py b/nova/api/openstack/compute/server_migrations.py index 6f92ac99bcc..1c2545adcb2 100644 --- a/nova/api/openstack/compute/server_migrations.py +++ b/nova/api/openstack/compute/server_migrations.py @@ -26,7 +26,7 @@ from nova.policies import servers_migrations as sm_policies -def output(migration, include_uuid=False): +def output(migration, include_uuid=False, include_user_project=False): """Returns the desired output of the API from an object. From a Migrations's object this method returns the primitive @@ -52,6 +52,9 @@ def output(migration, include_uuid=False): } if include_uuid: result['uuid'] = migration.uuid + if include_user_project: + result['user_id'] = migration.user_id + result['project_id'] = migration.project_id return result @@ -101,8 +104,11 @@ def index(self, req, server_id): context, server_id, 'live-migration') include_uuid = api_version_request.is_supported(req, '2.59') - return {'migrations': [output( - migration, include_uuid) for migration in migrations]} + + include_user_project = api_version_request.is_supported(req, '2.80') + return {'migrations': [ + output(migration, include_uuid, include_user_project) + for migration in migrations]} @wsgi.Controller.api_version("2.23") @wsgi.expected_errors(404) @@ -136,7 +142,10 @@ def show(self, req, server_id, id): raise exc.HTTPNotFound(explanation=msg) include_uuid = api_version_request.is_supported(req, '2.59') - return {'migration': output(migration, include_uuid)} + + include_user_project = api_version_request.is_supported(req, '2.80') + return {'migration': output(migration, include_uuid, + include_user_project)} @wsgi.Controller.api_version("2.24") @wsgi.response(202) diff --git a/nova/tests/functional/api/client.py b/nova/tests/functional/api/client.py index 63529ad6fdd..ed0975181af 100644 --- a/nova/tests/functional/api/client.py +++ b/nova/tests/functional/api/client.py @@ -499,8 +499,13 @@ def get_active_migrations(self, server_id): return self.api_get('/servers/%s/migrations' % server_id).body['migrations'] - def get_migrations(self): - return self.api_get('os-migrations').body['migrations'] + def get_migrations(self, user_id=None, project_id=None): + url = '/os-migrations?' + if user_id: + url += 'user_id=%s&' % user_id + if project_id: + url += 'project_id=%s&' % project_id + return self.api_get(url).body['migrations'] def force_complete_migration(self, server_id, migration_id): return self.api_post( diff --git a/nova/tests/functional/api_sample_tests/api_samples/os-migrations/v2.80/migrations-get-with-changes-before.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/os-migrations/v2.80/migrations-get-with-changes-before.json.tpl new file mode 100644 index 00000000000..6e4ed4c7566 --- /dev/null +++ b/nova/tests/functional/api_sample_tests/api_samples/os-migrations/v2.80/migrations-get-with-changes-before.json.tpl @@ -0,0 +1,32 @@ +{ + "migrations": [ + { + "created_at": "2016-01-29T11:42:02.000000", + "dest_compute": "compute2", + "dest_host": "1.2.3.4", + "dest_node": "node2", + "id": 1, + "instance_uuid": "%(instance_1)s", + "links": [ + { + "href": "%(host)s/v2.1/6f70656e737461636b20342065766572/servers/%(instance_1)s/migrations/1", + "rel": "self" + }, + { + "href": "%(host)s/6f70656e737461636b20342065766572/servers/%(instance_1)s/migrations/1", + "rel": "bookmark" + } + ], + "new_instance_type_id": 1, + "old_instance_type_id": 1, + "source_compute": "compute1", + "source_node": "node1", + "migration_type": "live-migration", + "status": "running", + "updated_at": "2016-01-29T11:42:02.000000", + "uuid": "12341d4b-346a-40d0-83c6-5f4f6892b650", + "user_id": "5c48ebaa-193f-4c5d-948a-f559cc92cd5e", + "project_id": "ef92ccff-00f3-46e4-b015-811110e36ee4" + } + ] +} diff --git a/nova/tests/functional/api_sample_tests/api_samples/os-migrations/v2.80/migrations-get-with-changes-since.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/os-migrations/v2.80/migrations-get-with-changes-since.json.tpl new file mode 100644 index 00000000000..3496a035257 --- /dev/null +++ b/nova/tests/functional/api_sample_tests/api_samples/os-migrations/v2.80/migrations-get-with-changes-since.json.tpl @@ -0,0 +1,40 @@ +{ + "migrations": [ + { + "created_at": "2016-06-23T14:42:02.000000", + "dest_compute": "compute20", + "dest_host": "5.6.7.8", + "dest_node": "node20", + "id": 4, + "instance_uuid": "%(instance_2)s", + "new_instance_type_id": 6, + "old_instance_type_id": 5, + "source_compute": "compute10", + "source_node": "node10", + "migration_type": "resize", + "status": "migrating", + "updated_at": "2016-06-23T14:42:02.000000", + "uuid": "42341d4b-346a-40d0-83c6-5f4f6892b650", + "user_id": "78348f0e-97ee-4d70-ad34-189692673ea2", + "project_id": "9842f0f7-1229-4355-afe7-15ebdbb8c3d8" + }, + { + "created_at": "2016-06-23T13:42:02.000000", + "dest_compute": "compute20", + "dest_host": "5.6.7.8", + "dest_node": "node20", + "id": 3, + "instance_uuid": "%(instance_2)s", + "new_instance_type_id": 6, + "old_instance_type_id": 5, + "source_compute": "compute10", + "source_node": "node10", + "migration_type": "resize", + "status": "error", + "updated_at": "2016-06-23T13:42:02.000000", + "uuid": "32341d4b-346a-40d0-83c6-5f4f6892b650", + "user_id": "78348f0e-97ee-4d70-ad34-189692673ea2", + "project_id": "9842f0f7-1229-4355-afe7-15ebdbb8c3d8" + } + ] +} diff --git a/nova/tests/functional/api_sample_tests/api_samples/os-migrations/v2.80/migrations-get-with-limit.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/os-migrations/v2.80/migrations-get-with-limit.json.tpl new file mode 100644 index 00000000000..62c0a614450 --- /dev/null +++ b/nova/tests/functional/api_sample_tests/api_samples/os-migrations/v2.80/migrations-get-with-limit.json.tpl @@ -0,0 +1,26 @@ +{ + "migrations": [ + { + "created_at": "2016-06-23T14:42:02.000000", + "dest_compute": "compute20", + "dest_host": "5.6.7.8", + "dest_node": "node20", + "id": 4, + "instance_uuid": "%(instance_2)s", + "new_instance_type_id": 6, + "old_instance_type_id": 5, + "source_compute": "compute10", + "source_node": "node10", + "status": "migrating", + "migration_type": "resize", + "updated_at": "2016-06-23T14:42:02.000000", + "uuid": "42341d4b-346a-40d0-83c6-5f4f6892b650", + "user_id": "78348f0e-97ee-4d70-ad34-189692673ea2", + "project_id": "9842f0f7-1229-4355-afe7-15ebdbb8c3d8" + } + ], + "migrations_links": [{ + "href": "%(host)s/v2.1/6f70656e737461636b20342065766572/os-migrations?limit=1&marker=42341d4b-346a-40d0-83c6-5f4f6892b650", + "rel": "next" + }] +} diff --git a/nova/tests/functional/api_sample_tests/api_samples/os-migrations/v2.80/migrations-get-with-marker.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/os-migrations/v2.80/migrations-get-with-marker.json.tpl new file mode 100644 index 00000000000..43239c8bc64 --- /dev/null +++ b/nova/tests/functional/api_sample_tests/api_samples/os-migrations/v2.80/migrations-get-with-marker.json.tpl @@ -0,0 +1,32 @@ +{ + "migrations": [ + { + "created_at": "2016-01-29T11:42:02.000000", + "dest_compute": "compute2", + "dest_host": "1.2.3.4", + "dest_node": "node2", + "id": 1, + "instance_uuid": "8600d31b-d1a1-4632-b2ff-45c2be1a70ff", + "links": [ + { + "href": "http://openstack.example.com/v2.1/6f70656e737461636b20342065766572/servers/8600d31b-d1a1-4632-b2ff-45c2be1a70ff/migrations/1", + "rel": "self" + }, + { + "href": "http://openstack.example.com/6f70656e737461636b20342065766572/servers/8600d31b-d1a1-4632-b2ff-45c2be1a70ff/migrations/1", + "rel": "bookmark" + } + ], + "migration_type": "live-migration", + "new_instance_type_id": 1, + "old_instance_type_id": 1, + "source_compute": "compute1", + "source_node": "node1", + "status": "running", + "updated_at": "2016-01-29T11:42:02.000000", + "uuid": "12341d4b-346a-40d0-83c6-5f4f6892b650", + "user_id": "5c48ebaa-193f-4c5d-948a-f559cc92cd5e", + "project_id": "ef92ccff-00f3-46e4-b015-811110e36ee4" + } + ] +} diff --git a/nova/tests/functional/api_sample_tests/api_samples/os-migrations/v2.80/migrations-get-with-user-or-project-id.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/os-migrations/v2.80/migrations-get-with-user-or-project-id.json.tpl new file mode 100644 index 00000000000..1a3448c0de4 --- /dev/null +++ b/nova/tests/functional/api_sample_tests/api_samples/os-migrations/v2.80/migrations-get-with-user-or-project-id.json.tpl @@ -0,0 +1,50 @@ +{ + "migrations": [ + { + "created_at": "2016-01-29T12:42:02.000000", + "dest_compute": "compute2", + "dest_host": "1.2.3.4", + "dest_node": "node2", + "id": 2, + "instance_uuid": "%(instance_1)s", + "new_instance_type_id": 1, + "old_instance_type_id": 1, + "source_compute": "compute1", + "source_node": "node1", + "migration_type": "live-migration", + "status": "error", + "updated_at": "2016-01-29T12:42:02.000000", + "uuid": "22341d4b-346a-40d0-83c6-5f4f6892b650", + "user_id": "5c48ebaa-193f-4c5d-948a-f559cc92cd5e", + "project_id": "ef92ccff-00f3-46e4-b015-811110e36ee4" + }, + { + "created_at": "2016-01-29T11:42:02.000000", + "dest_compute": "compute2", + "dest_host": "1.2.3.4", + "dest_node": "node2", + "id": 1, + "instance_uuid": "%(instance_1)s", + "links": [ + { + "href": "%(host)s/v2.1/6f70656e737461636b20342065766572/servers/%(instance_1)s/migrations/1", + "rel": "self" + }, + { + "href": "%(host)s/6f70656e737461636b20342065766572/servers/%(instance_1)s/migrations/1", + "rel": "bookmark" + } + ], + "new_instance_type_id": 1, + "old_instance_type_id": 1, + "source_compute": "compute1", + "source_node": "node1", + "migration_type": "live-migration", + "status": "running", + "updated_at": "2016-01-29T11:42:02.000000", + "uuid": "12341d4b-346a-40d0-83c6-5f4f6892b650", + "user_id": "5c48ebaa-193f-4c5d-948a-f559cc92cd5e", + "project_id": "ef92ccff-00f3-46e4-b015-811110e36ee4" + } + ] +} diff --git a/nova/tests/functional/api_sample_tests/api_samples/os-migrations/v2.80/migrations-get.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/os-migrations/v2.80/migrations-get.json.tpl new file mode 100644 index 00000000000..b20ab797ff2 --- /dev/null +++ b/nova/tests/functional/api_sample_tests/api_samples/os-migrations/v2.80/migrations-get.json.tpl @@ -0,0 +1,86 @@ +{ + "migrations": [ + { + "created_at": "2016-06-23T14:42:02.000000", + "dest_compute": "compute20", + "dest_host": "5.6.7.8", + "dest_node": "node20", + "id": 4, + "instance_uuid": "%(instance_2)s", + "new_instance_type_id": 6, + "old_instance_type_id": 5, + "source_compute": "compute10", + "source_node": "node10", + "migration_type": "resize", + "status": "migrating", + "updated_at": "2016-06-23T14:42:02.000000", + "uuid": "42341d4b-346a-40d0-83c6-5f4f6892b650", + "user_id": "78348f0e-97ee-4d70-ad34-189692673ea2", + "project_id": "9842f0f7-1229-4355-afe7-15ebdbb8c3d8" + }, + { + "created_at": "2016-06-23T13:42:02.000000", + "dest_compute": "compute20", + "dest_host": "5.6.7.8", + "dest_node": "node20", + "id": 3, + "instance_uuid": "%(instance_2)s", + "new_instance_type_id": 6, + "old_instance_type_id": 5, + "source_compute": "compute10", + "source_node": "node10", + "migration_type": "resize", + "status": "error", + "updated_at": "2016-06-23T13:42:02.000000", + "uuid": "32341d4b-346a-40d0-83c6-5f4f6892b650", + "user_id": "78348f0e-97ee-4d70-ad34-189692673ea2", + "project_id": "9842f0f7-1229-4355-afe7-15ebdbb8c3d8" + }, + { + "created_at": "2016-01-29T12:42:02.000000", + "dest_compute": "compute2", + "dest_host": "1.2.3.4", + "dest_node": "node2", + "id": 2, + "instance_uuid": "%(instance_1)s", + "new_instance_type_id": 1, + "old_instance_type_id": 1, + "source_compute": "compute1", + "source_node": "node1", + "migration_type": "live-migration", + "status": "error", + "updated_at": "2016-01-29T12:42:02.000000", + "uuid": "22341d4b-346a-40d0-83c6-5f4f6892b650", + "user_id": "5c48ebaa-193f-4c5d-948a-f559cc92cd5e", + "project_id": "ef92ccff-00f3-46e4-b015-811110e36ee4" + }, + { + "created_at": "2016-01-29T11:42:02.000000", + "dest_compute": "compute2", + "dest_host": "1.2.3.4", + "dest_node": "node2", + "id": 1, + "instance_uuid": "%(instance_1)s", + "links": [ + { + "href": "%(host)s/v2.1/6f70656e737461636b20342065766572/servers/%(instance_1)s/migrations/1", + "rel": "self" + }, + { + "href": "%(host)s/6f70656e737461636b20342065766572/servers/%(instance_1)s/migrations/1", + "rel": "bookmark" + } + ], + "new_instance_type_id": 1, + "old_instance_type_id": 1, + "source_compute": "compute1", + "source_node": "node1", + "migration_type": "live-migration", + "status": "running", + "updated_at": "2016-01-29T11:42:02.000000", + "uuid": "12341d4b-346a-40d0-83c6-5f4f6892b650", + "user_id": "5c48ebaa-193f-4c5d-948a-f559cc92cd5e", + "project_id": "ef92ccff-00f3-46e4-b015-811110e36ee4" + } + ] +} diff --git a/nova/tests/functional/api_sample_tests/api_samples/server-migrations/v2.80/live-migrate-server.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/server-migrations/v2.80/live-migrate-server.json.tpl new file mode 100644 index 00000000000..c2f5bf6c989 --- /dev/null +++ b/nova/tests/functional/api_sample_tests/api_samples/server-migrations/v2.80/live-migrate-server.json.tpl @@ -0,0 +1,6 @@ +{ + "os-migrateLive": { + "host": null, + "block_migration": "auto" + } +} diff --git a/nova/tests/functional/api_sample_tests/api_samples/server-migrations/v2.80/migrations-get.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/server-migrations/v2.80/migrations-get.json.tpl new file mode 100644 index 00000000000..3a7ef6edb47 --- /dev/null +++ b/nova/tests/functional/api_sample_tests/api_samples/server-migrations/v2.80/migrations-get.json.tpl @@ -0,0 +1,23 @@ +{ + "migration": { + "created_at": "2016-01-29T13:42:02.000000", + "dest_compute": "compute2", + "dest_host": "1.2.3.4", + "dest_node": "node2", + "id": 1, + "server_uuid": "%(server_uuid)s", + "source_compute": "compute1", + "source_node": "node1", + "status": "running", + "memory_total_bytes": 123456, + "memory_processed_bytes": 12345, + "memory_remaining_bytes": 111111, + "disk_total_bytes": 234567, + "disk_processed_bytes": 23456, + "disk_remaining_bytes": 211111, + "updated_at": "2016-01-29T13:42:02.000000", + "uuid": "12341d4b-346a-40d0-83c6-5f4f6892b650", + "user_id": "8dbaa0f0-ab95-4ffe-8cb4-9c89d2ac9d24", + "project_id": "5f705771-3aa9-4f4c-8660-0d9522ffdbea" + } +} diff --git a/nova/tests/functional/api_sample_tests/api_samples/server-migrations/v2.80/migrations-index.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/server-migrations/v2.80/migrations-index.json.tpl new file mode 100644 index 00000000000..1b1e2f7efdd --- /dev/null +++ b/nova/tests/functional/api_sample_tests/api_samples/server-migrations/v2.80/migrations-index.json.tpl @@ -0,0 +1,25 @@ +{ + "migrations": [ + { + "created_at": "2016-01-29T13:42:02.000000", + "dest_compute": "compute2", + "dest_host": "1.2.3.4", + "dest_node": "node2", + "id": 1, + "server_uuid": "%(server_uuid_1)s", + "source_compute": "compute1", + "source_node": "node1", + "status": "running", + "memory_total_bytes": 123456, + "memory_processed_bytes": 12345, + "memory_remaining_bytes": 111111, + "disk_total_bytes": 234567, + "disk_processed_bytes": 23456, + "disk_remaining_bytes": 211111, + "updated_at": "2016-01-29T13:42:02.000000", + "uuid": "12341d4b-346a-40d0-83c6-5f4f6892b650", + "user_id": "8dbaa0f0-ab95-4ffe-8cb4-9c89d2ac9d24", + "project_id": "5f705771-3aa9-4f4c-8660-0d9522ffdbea" + } + ] +} diff --git a/nova/tests/functional/api_sample_tests/test_migrations.py b/nova/tests/functional/api_sample_tests/test_migrations.py index 35bba5bf77c..20454ddebe2 100644 --- a/nova/tests/functional/api_sample_tests/test_migrations.py +++ b/nova/tests/functional/api_sample_tests/test_migrations.py @@ -315,3 +315,125 @@ def test_get_migrations_with_changes_before(self): self._verify_response( 'migrations-get-with-changes-before', {"instance_1": INSTANCE_UUID_1}, response, 200) + + +class MigrationsSamplesJsonTestV2_80(MigrationsSamplesJsonTestV2_66): + + microversion = '2.80' + scenarios = [('v2_80', {'api_major_version': 'v2.1'})] + USER_ID1 = "5c48ebaa-193f-4c5d-948a-f559cc92cd5e" + PROJECT_ID1 = "ef92ccff-00f3-46e4-b015-811110e36ee4" + USER_ID2 = "78348f0e-97ee-4d70-ad34-189692673ea2" + PROJECT_ID2 = "9842f0f7-1229-4355-afe7-15ebdbb8c3d8" + + fake_migrations = [ + # in-progress live-migration. + { + 'source_node': 'node1', + 'dest_node': 'node2', + 'source_compute': 'compute1', + 'dest_compute': 'compute2', + 'dest_host': '1.2.3.4', + 'status': 'running', + 'instance_uuid': INSTANCE_UUID_1, + 'old_instance_type_id': 1, + 'new_instance_type_id': 1, + 'migration_type': 'live-migration', + 'hidden': False, + 'created_at': datetime.datetime(2016, 0o1, 29, 11, 42, 2), + 'updated_at': datetime.datetime(2016, 0o1, 29, 11, 42, 2), + 'deleted_at': None, + 'deleted': False, + 'uuid': '12341d4b-346a-40d0-83c6-5f4f6892b650', + 'cross_cell_move': False, + 'user_id': USER_ID1, + 'project_id': PROJECT_ID1 + }, + # non in-progress live-migration. + { + 'source_node': 'node1', + 'dest_node': 'node2', + 'source_compute': 'compute1', + 'dest_compute': 'compute2', + 'dest_host': '1.2.3.4', + 'status': 'error', + 'instance_uuid': INSTANCE_UUID_1, + 'old_instance_type_id': 1, + 'new_instance_type_id': 1, + 'migration_type': 'live-migration', + 'hidden': False, + 'created_at': datetime.datetime(2016, 0o1, 29, 12, 42, 2), + 'updated_at': datetime.datetime(2016, 0o1, 29, 12, 42, 2), + 'deleted_at': None, + 'deleted': False, + 'uuid': '22341d4b-346a-40d0-83c6-5f4f6892b650', + 'cross_cell_move': False, + 'user_id': USER_ID1, + 'project_id': PROJECT_ID1 + }, + # non in-progress resize. + { + 'source_node': 'node10', + 'dest_node': 'node20', + 'source_compute': 'compute10', + 'dest_compute': 'compute20', + 'dest_host': '5.6.7.8', + 'status': 'error', + 'instance_uuid': INSTANCE_UUID_2, + 'old_instance_type_id': 5, + 'new_instance_type_id': 6, + 'migration_type': 'resize', + 'hidden': False, + 'created_at': datetime.datetime(2016, 0o6, 23, 13, 42, 2), + 'updated_at': datetime.datetime(2016, 0o6, 23, 13, 42, 2), + 'deleted_at': None, + 'deleted': False, + 'uuid': '32341d4b-346a-40d0-83c6-5f4f6892b650', + 'cross_cell_move': False, + 'user_id': USER_ID2, + 'project_id': PROJECT_ID2 + }, + # in-progress resize. + { + 'source_node': 'node10', + 'dest_node': 'node20', + 'source_compute': 'compute10', + 'dest_compute': 'compute20', + 'dest_host': '5.6.7.8', + 'status': 'migrating', + 'instance_uuid': INSTANCE_UUID_2, + 'old_instance_type_id': 5, + 'new_instance_type_id': 6, + 'migration_type': 'resize', + 'hidden': False, + 'created_at': datetime.datetime(2016, 0o6, 23, 14, 42, 2), + 'updated_at': datetime.datetime(2016, 0o6, 23, 14, 42, 2), + 'deleted_at': None, + 'deleted': False, + 'uuid': '42341d4b-346a-40d0-83c6-5f4f6892b650', + 'cross_cell_move': False, + 'user_id': USER_ID2, + 'project_id': PROJECT_ID2 + } + ] + + def test_get_migrations_with_user_id(self): + response = self._do_get('os-migrations?user_id=%s' % self.USER_ID1) + self.assertEqual(200, response.status_code) + self._verify_response('migrations-get-with-user-or-project-id', + {"instance_1": INSTANCE_UUID_1}, response, 200) + + def test_get_migrations_with_project_id(self): + response = self._do_get('os-migrations?project_id=%s' + % self.PROJECT_ID1) + self.assertEqual(200, response.status_code) + self._verify_response('migrations-get-with-user-or-project-id', + {"instance_1": INSTANCE_UUID_1}, response, 200) + + def test_get_migrations_with_user_and_project_id(self): + response = self._do_get('os-migrations?user_id=%s&project_id=%s' + % (self.USER_ID1, self.PROJECT_ID1)) + self.assertEqual(200, response.status_code) + self._verify_response( + 'migrations-get-with-user-or-project-id', + {"instance_1": INSTANCE_UUID_1}, response, 200) diff --git a/nova/tests/functional/api_sample_tests/test_server_migrations.py b/nova/tests/functional/api_sample_tests/test_server_migrations.py index f4a40ada401..f9a658feb0a 100644 --- a/nova/tests/functional/api_sample_tests/test_server_migrations.py +++ b/nova/tests/functional/api_sample_tests/test_server_migrations.py @@ -245,3 +245,64 @@ def test_live_migrate_abort_migration_queued(self, _live_migrate): uri = 'servers/%s/migrations/%s' % (self.uuid, self.migration.id) response = self._do_delete(uri) self.assertEqual(202, response.status_code) + + +class ServerMigrationsSampleJsonTestV2_80( + ServerMigrationsSampleJsonTestV2_65): + microversion = '2.80' + scenarios = [('v2_80', {'api_major_version': 'v2.1'})] + + UUID_1 = '4cfba335-03d8-49b2-8c52-e69043d1e8fe' + UUID_2 = '058fc419-a8a8-4e08-b62c-a9841ef9cd3f' + + USER_ID = '8dbaa0f0-ab95-4ffe-8cb4-9c89d2ac9d24' + PROJECT_ID = '5f705771-3aa9-4f4c-8660-0d9522ffdbea' + + fake_migrations = [ + { + 'source_node': 'node1', + 'dest_node': 'node2', + 'source_compute': 'compute1', + 'dest_compute': 'compute2', + 'dest_host': '1.2.3.4', + 'status': 'running', + 'instance_uuid': UUID_1, + 'migration_type': 'live-migration', + 'hidden': False, + 'memory_total': 123456, + 'memory_processed': 12345, + 'memory_remaining': 111111, + 'disk_total': 234567, + 'disk_processed': 23456, + 'disk_remaining': 211111, + 'created_at': datetime.datetime(2016, 0o1, 29, 13, 42, 2), + 'updated_at': datetime.datetime(2016, 0o1, 29, 13, 42, 2), + 'deleted_at': None, + 'deleted': False, + 'user_id': USER_ID, + 'project_id': PROJECT_ID + }, + { + 'source_node': 'node10', + 'dest_node': 'node20', + 'source_compute': 'compute10', + 'dest_compute': 'compute20', + 'dest_host': '5.6.7.8', + 'status': 'migrating', + 'instance_uuid': UUID_2, + 'migration_type': 'resize', + 'hidden': False, + 'memory_total': 456789, + 'memory_processed': 56789, + 'memory_remaining': 400000, + 'disk_total': 96789, + 'disk_processed': 6789, + 'disk_remaining': 90000, + 'created_at': datetime.datetime(2016, 0o1, 22, 13, 42, 2), + 'updated_at': datetime.datetime(2016, 0o1, 22, 13, 42, 2), + 'deleted_at': None, + 'deleted': False, + 'user_id': USER_ID, + 'project_id': PROJECT_ID + } + ] diff --git a/nova/tests/functional/test_servers.py b/nova/tests/functional/test_servers.py index f1ff6b540ec..cf30adc8858 100644 --- a/nova/tests/functional/test_servers.py +++ b/nova/tests/functional/test_servers.py @@ -1613,6 +1613,95 @@ def test_volume_backed_rebuild_different_image(self): 'volume-backed server', six.text_type(resp)) +class ServersTestV280(ServersTestBase): + api_major_version = 'v2.1' + + def setUp(self): + super(ServersTestV280, self).setUp() + api_fixture = self.useFixture(nova_fixtures.OSAPIFixture( + api_version='v2.1')) + self.api = api_fixture.api + self.admin_api = api_fixture.admin_api + + self.api.microversion = '2.80' + self.admin_api.microversion = '2.80' + + def test_get_migrations_after_cold_migrate_server_in_same_project( + self): + # Create a server by non-admin + server = self.api.post_server({ + 'server': { + 'flavorRef': 1, + 'imageRef': '155d900f-4e14-4e4c-a73d-069cbf4541e6', + 'name': 'migrate-server-test', + 'networks': 'none' + }}) + server_id = server['id'] + + # Check it's there + found_server = self.api.get_server(server_id) + self.assertEqual(server_id, found_server['id']) + + self.start_service('compute', host='host2') + + post = {'migrate': {}} + self.admin_api.post_server_action(server_id, post) + + # Get the migration records by admin + migrations = self.admin_api.get_migrations( + user_id=self.admin_api.auth_user) + self.assertEqual(1, len(migrations)) + self.assertEqual(server_id, migrations[0]['instance_uuid']) + + # Get the migration records by non-admin + migrations = self.admin_api.get_migrations( + user_id=self.api.auth_user) + self.assertEqual([], migrations) + + def test_get_migrations_after_live_migrate_server_in_different_project( + self): + # Create a server by non-admin + server = self.api.post_server({ + 'server': { + 'flavorRef': 1, + 'imageRef': '155d900f-4e14-4e4c-a73d-069cbf4541e6', + 'name': 'migrate-server-test', + 'networks': 'none' + }}) + server_id = server['id'] + + # Check it's there + found_server = self.api.get_server(server_id) + self.assertEqual(server_id, found_server['id']) + + server = self._wait_for_state_change(found_server, 'BUILD') + + self.start_service('compute', host='host2') + + project_id_1 = '4906260553374bf0a5d566543b320516' + project_id_2 = 'c850298c1b6b4796a8f197ac310b2469' + new_api_fixture = self.useFixture(nova_fixtures.OSAPIFixture( + api_version=self.api_major_version, project_id=project_id_1)) + new_admin_api = new_api_fixture.admin_api + new_admin_api.microversion = '2.80' + + post = { + 'os-migrateLive': { + 'host': 'host2', + 'block_migration': True + } + } + new_admin_api.post_server_action(server_id, post) + # Get the migration records + migrations = new_admin_api.get_migrations(project_id=project_id_1) + self.assertEqual(1, len(migrations)) + self.assertEqual(server_id, migrations[0]['instance_uuid']) + + # Get the migration records by not exist project_id + migrations = new_admin_api.get_migrations(project_id=project_id_2) + self.assertEqual([], migrations) + + class ServerMovingTests(integrated_helpers.ProviderUsageBaseTestCase): """Tests moving servers while checking the resource allocations and usages diff --git a/nova/tests/unit/api/openstack/compute/test_migrations.py b/nova/tests/unit/api/openstack/compute/test_migrations.py index a8f96a88d96..843b8965d8f 100644 --- a/nova/tests/unit/api/openstack/compute/test_migrations.py +++ b/nova/tests/unit/api/openstack/compute/test_migrations.py @@ -449,6 +449,63 @@ def test_index_with_changes_before_old_microversion(self, get_migrations): {'instance_uuid': uuids.instance_uuid}) +class MigrationsTestCaseV280(MigrationTestCaseV266): + wsgi_api_version = '2.80' + + def test_index(self): + migrations = {'migrations': self.controller._output( + self.req, migrations_obj, + add_link=True, add_uuid=True, + add_user_project=True)} + + for i, mig in enumerate(migrations['migrations']): + # first item is in-progress live migration + if i == 0: + self.assertIn('links', mig) + else: + self.assertNotIn('links', mig) + + self.assertIn('migration_type', mig) + self.assertIn('id', mig) + self.assertIn('uuid', mig) + self.assertIn('user_id', mig) + self.assertIn('project_id', mig) + self.assertNotIn('deleted', mig) + self.assertNotIn('deleted_at', mig) + + with mock.patch.object(self.controller.compute_api, + 'get_migrations_sorted') as m_get: + m_get.return_value = migrations_obj + response = self.controller.index(self.req) + self.assertEqual(migrations, response) + self.assertIn('links', response['migrations'][0]) + self.assertIn('migration_type', response['migrations'][0]) + + def test_index_filter_by_user_id_pre_v280(self): + """Tests that the migrations by user_id query parameter + is not allowed before microversion 2.80. + """ + req = fakes.HTTPRequest.blank( + '/os-migrations?user_id=%s' % uuids.user_id, + version='2.79', use_admin_context=True) + ex = self.assertRaises(exception.ValidationError, + self.controller.index, req) + self.assertIn('Additional properties are not allowed', + six.text_type(ex)) + + def test_index_filter_by_project_id_pre_v280(self): + """Tests that the migrations by project_id query parameter + is not allowed before microversion 2.80. + """ + req = fakes.HTTPRequest.blank( + '/os-migrations?project_id=%s' % uuids.project_id, + version='2.79', use_admin_context=True) + ex = self.assertRaises(exception.ValidationError, + self.controller.index, req) + self.assertIn('Additional properties are not allowed', + six.text_type(ex)) + + class MigrationsPolicyEnforcement(test.NoDBTestCase): def setUp(self): super(MigrationsPolicyEnforcement, self).setUp() @@ -476,3 +533,7 @@ def setUp(self): class MigrationsPolicyEnforcementV259(MigrationsPolicyEnforcementV223): wsgi_api_version = '2.59' + + +class MigrationsPolicyEnforcementV280(MigrationsPolicyEnforcementV259): + wsgi_api_version = '2.80' diff --git a/nova/tests/unit/api/openstack/compute/test_server_migrations.py b/nova/tests/unit/api/openstack/compute/test_server_migrations.py index 35d6a5db010..b84c4372814 100644 --- a/nova/tests/unit/api/openstack/compute/test_server_migrations.py +++ b/nova/tests/unit/api/openstack/compute/test_server_migrations.py @@ -368,6 +368,10 @@ def _do_test(mock_get, mock_abort): _do_test() +class ServerMigrationsTestsV280(ServerMigrationsTestsV265): + wsgi_api_version = '2.80' + + class ServerMigrationsPolicyEnforcementV21(test.NoDBTestCase): wsgi_api_version = '2.22' diff --git a/releasenotes/notes/bp-add-user-id-field-to-the-migrations-table-af5989e74634b9c4.yaml b/releasenotes/notes/bp-add-user-id-field-to-the-migrations-table-af5989e74634b9c4.yaml new file mode 100644 index 00000000000..5901d7929c1 --- /dev/null +++ b/releasenotes/notes/bp-add-user-id-field-to-the-migrations-table-af5989e74634b9c4.yaml @@ -0,0 +1,20 @@ +--- +features: + - | + Microversion 2.80 changes the list migrations APIs and the + os-migrations API. + + In this microversion, expose the ``user_id`` and ``project_id`` + fields in the following APIs: + + * ``GET /os-migrations`` + * ``GET /servers/{server_id}/migrations`` + * ``GET /servers/{server_id}/migrations/{migration_id}`` + + The ``GET /os-migrations`` API will also have optional ``user_id`` and + ``project_id`` query parameters for filtering migrations by user and/or + project, for example: + + * ``GET /os-migrations?user_id=ef9d34b4-45d0-4530-871b-3fb535988394`` + * ``GET /os-migrations?project_id=011ee9f4-8f16-4c38-8633-a254d420fd54`` + * ``GET /os-migrations?user_id=ef9d34b4-45d0-4530-871b-3fb535988394&project_id=011ee9f4-8f16-4c38-8633-a254d420fd54``