From 28c1075b59031fa154b1e2222ab2485b2f78fc5f Mon Sep 17 00:00:00 2001 From: zhangbailin Date: Mon, 3 Sep 2018 10:55:05 +0800 Subject: [PATCH] Resource retrieving: add changes-before filter This adds the changes-before filter to the servers, os-instance-actions and os-migrations APIs for filtering resources which were last updated before or equal to the given time. The changes-before filter, like the changes-since filter, will return deleted server resources. Part of bp support-to-query-nova-resources-filter-by-changes-before Change-Id: If91c179e3823c8b0da744a9363906b0f7b05c326 --- .../polling_changes-since_parameter.rst | 87 ++++++-- api-guide/source/server_concepts.rst | 50 ++++- api-ref/source/os-instance-actions.inc | 1 + api-ref/source/os-migrations.inc | 1 + api-ref/source/parameters.yaml | 55 +++++ api-ref/source/servers.inc | 3 + .../instance-action-get-non-admin-resp.json | 21 ++ .../v2.66/instance-action-get-resp.json | 23 +++ .../v2.66/instance-actions-list-resp.json | 24 +++ ...ance-actions-list-with-changes-before.json | 24 +++ ...tance-actions-list-with-changes-since.json | 14 ++ ...instance-actions-list-with-limit-resp.json | 20 ++ ...nstance-actions-list-with-marker-resp.json | 14 ++ .../migrations-get-with-changes-before.json | 30 +++ .../migrations-get-with-changes-since.json | 36 ++++ .../v2.66/migrations-get-with-limit.json | 26 +++ .../v2.66/migrations-get-with-marker.json | 30 +++ .../os-migrations/v2.66/migrations-get.json | 78 +++++++ .../servers/v2.66/server-create-req.json | 28 +++ .../servers/v2.66/server-create-resp.json | 22 ++ .../servers/v2.66/server-get-resp.json | 184 +++++++++++++++++ .../servers/v2.66/servers-details-resp.json | 190 ++++++++++++++++++ .../servers-details-with-changes-before.json | 94 +++++++++ .../servers-list-with-changes-before.json | 18 ++ .../versions/v21-version-get-resp.json | 2 +- .../versions/versions-get-resp.json | 2 +- nova/api/openstack/api_version_request.py | 6 +- .../api/openstack/compute/instance_actions.py | 8 +- nova/api/openstack/compute/migrations.py | 31 ++- .../compute/rest_api_version_history.rst | 12 ++ .../compute/schemas/instance_actions.py | 8 + .../openstack/compute/schemas/migrations.py | 6 + nova/api/openstack/compute/schemas/servers.py | 6 + nova/api/openstack/compute/servers.py | 33 ++- nova/db/sqlalchemy/api.py | 54 +++-- ...nstance-action-get-non-admin-resp.json.tpl | 21 ++ .../v2.66/instance-action-get-resp.json.tpl | 23 +++ .../v2.66/instance-actions-list-resp.json.tpl | 24 +++ ...-actions-list-with-changes-before.json.tpl | 24 +++ ...e-actions-list-with-changes-since.json.tpl | 14 ++ ...ance-actions-list-with-limit-resp.json.tpl | 20 ++ ...nce-actions-list-with-marker-resp.json.tpl | 14 ++ ...igrations-get-with-changes-before.json.tpl | 30 +++ ...migrations-get-with-changes-since.json.tpl | 36 ++++ .../v2.66/migrations-get-with-limit.json.tpl | 24 +++ .../v2.66/migrations-get-with-marker.json.tpl | 30 +++ .../v2.66/migrations-get.json.tpl | 78 +++++++ .../servers/v2.66/server-create-req.json.tpl | 28 +++ .../servers/v2.66/server-create-resp.json.tpl | 22 ++ .../servers/v2.66/server-get-resp.json.tpl | 184 +++++++++++++++++ .../v2.66/servers-details-resp.json.tpl | 190 ++++++++++++++++++ ...rvers-details-with-changes-before.json.tpl | 94 +++++++++ .../servers-list-with-changes-before.json.tpl | 18 ++ .../api_sample_tests/test_instance_actions.py | 14 ++ .../api_sample_tests/test_migrations.py | 13 ++ .../api_sample_tests/test_servers.py | 42 ++++ .../compute/test_instance_actions.py | 33 +++ .../api/openstack/compute/test_migrations.py | 47 ++++- .../api/openstack/compute/test_serversV21.py | 91 +++++++++ nova/tests/unit/db/test_db_api.py | 101 ++++++++++ ...er-by-changes-before-e4942cde61070e28.yaml | 24 +++ 61 files changed, 2426 insertions(+), 54 deletions(-) create mode 100644 doc/api_samples/os-instance-actions/v2.66/instance-action-get-non-admin-resp.json create mode 100644 doc/api_samples/os-instance-actions/v2.66/instance-action-get-resp.json create mode 100644 doc/api_samples/os-instance-actions/v2.66/instance-actions-list-resp.json create mode 100644 doc/api_samples/os-instance-actions/v2.66/instance-actions-list-with-changes-before.json create mode 100644 doc/api_samples/os-instance-actions/v2.66/instance-actions-list-with-changes-since.json create mode 100644 doc/api_samples/os-instance-actions/v2.66/instance-actions-list-with-limit-resp.json create mode 100644 doc/api_samples/os-instance-actions/v2.66/instance-actions-list-with-marker-resp.json create mode 100644 doc/api_samples/os-migrations/v2.66/migrations-get-with-changes-before.json create mode 100644 doc/api_samples/os-migrations/v2.66/migrations-get-with-changes-since.json create mode 100644 doc/api_samples/os-migrations/v2.66/migrations-get-with-limit.json create mode 100644 doc/api_samples/os-migrations/v2.66/migrations-get-with-marker.json create mode 100644 doc/api_samples/os-migrations/v2.66/migrations-get.json create mode 100644 doc/api_samples/servers/v2.66/server-create-req.json create mode 100644 doc/api_samples/servers/v2.66/server-create-resp.json create mode 100644 doc/api_samples/servers/v2.66/server-get-resp.json create mode 100644 doc/api_samples/servers/v2.66/servers-details-resp.json create mode 100644 doc/api_samples/servers/v2.66/servers-details-with-changes-before.json create mode 100644 doc/api_samples/servers/v2.66/servers-list-with-changes-before.json create mode 100644 nova/tests/functional/api_sample_tests/api_samples/os-instance-actions/v2.66/instance-action-get-non-admin-resp.json.tpl create mode 100644 nova/tests/functional/api_sample_tests/api_samples/os-instance-actions/v2.66/instance-action-get-resp.json.tpl create mode 100644 nova/tests/functional/api_sample_tests/api_samples/os-instance-actions/v2.66/instance-actions-list-resp.json.tpl create mode 100644 nova/tests/functional/api_sample_tests/api_samples/os-instance-actions/v2.66/instance-actions-list-with-changes-before.json.tpl create mode 100644 nova/tests/functional/api_sample_tests/api_samples/os-instance-actions/v2.66/instance-actions-list-with-changes-since.json.tpl create mode 100644 nova/tests/functional/api_sample_tests/api_samples/os-instance-actions/v2.66/instance-actions-list-with-limit-resp.json.tpl create mode 100644 nova/tests/functional/api_sample_tests/api_samples/os-instance-actions/v2.66/instance-actions-list-with-marker-resp.json.tpl create mode 100644 nova/tests/functional/api_sample_tests/api_samples/os-migrations/v2.66/migrations-get-with-changes-before.json.tpl create mode 100644 nova/tests/functional/api_sample_tests/api_samples/os-migrations/v2.66/migrations-get-with-changes-since.json.tpl create mode 100644 nova/tests/functional/api_sample_tests/api_samples/os-migrations/v2.66/migrations-get-with-limit.json.tpl create mode 100644 nova/tests/functional/api_sample_tests/api_samples/os-migrations/v2.66/migrations-get-with-marker.json.tpl create mode 100644 nova/tests/functional/api_sample_tests/api_samples/os-migrations/v2.66/migrations-get.json.tpl create mode 100644 nova/tests/functional/api_sample_tests/api_samples/servers/v2.66/server-create-req.json.tpl create mode 100644 nova/tests/functional/api_sample_tests/api_samples/servers/v2.66/server-create-resp.json.tpl create mode 100644 nova/tests/functional/api_sample_tests/api_samples/servers/v2.66/server-get-resp.json.tpl create mode 100644 nova/tests/functional/api_sample_tests/api_samples/servers/v2.66/servers-details-resp.json.tpl create mode 100644 nova/tests/functional/api_sample_tests/api_samples/servers/v2.66/servers-details-with-changes-before.json.tpl create mode 100644 nova/tests/functional/api_sample_tests/api_samples/servers/v2.66/servers-list-with-changes-before.json.tpl create mode 100644 releasenotes/notes/support-to-query-nova-resources-filter-by-changes-before-e4942cde61070e28.yaml diff --git a/api-guide/source/polling_changes-since_parameter.rst b/api-guide/source/polling_changes-since_parameter.rst index 9bd0a258531c..bef656d39e5c 100644 --- a/api-guide/source/polling_changes-since_parameter.rst +++ b/api-guide/source/polling_changes-since_parameter.rst @@ -1,32 +1,81 @@ -================================================== -Efficient polling with the changes-since parameter -================================================== +================= +Efficient polling +================= The REST API allows you to poll for the status of certain operations by performing a **GET** on various elements. Rather than re-downloading and -re-parsing the full status at each polling interval, your REST client -may use the ``changes-since`` parameter to check for changes since a -previous request. +re-parsing the full status at each polling interval, your REST client may +use the ``changes-since`` and/or ``changes-before`` parameters to check +for changes within a specified time. -The ``changes-since`` time is specified as an `ISO -8601 `__ dateTime +The ``changes-since`` time or ``changes-before`` time is specified as +an `ISO 8601 `__ dateTime (2011-01-24T17:08Z). The form for the timestamp is **CCYY-MM-DDThh:mm:ss**. An optional time zone may be written in by appending the form ±hh:mm which describes the timezone as an offset from UTC. When the timezone is not specified (2011-01-24T17:08), the UTC timezone is assumed. -If nothing has changed since the ``changes-since`` time, an empty list is -returned. If data has changed, only the items changed since the -specified time are returned in the response. For example, performing a -**GET** against:: +The following situations need to be considered: - https://api.servers.openstack.org/v2.1/servers?changes-since=2015-01-24T17:08Z +* If nothing has changed since the ``changes-since`` time, an empty list is + returned. If data has changed, only the items changed since the specified + time are returned in the response. For example, performing a + **GET** against:: -would list all servers that have changed since Mon, 24 Jan 2015 17:08:00 UTC. + https://api.servers.openstack.org/v2.1/servers?changes-since=2015-01-24T17:08Z + + would list all servers that have changed since Mon, 24 Jan 2015 17:08:00 + UTC. + +* If nothing has changed earlier than or equal to the ``changes-before`` + time, an empty list is returned. If data has changed, only the items + changed earlier than or equal to the specified time are returned in the + response. For example, performing a **GET** against:: + + https://api.servers.openstack.org/v2.1/servers?changes-before=2015-01-24T17:08Z + + would list all servers that have changed earlier than or equal to + Mon, 24 Jan 2015 17:08:00 UTC. + +* If nothing has changed later than or equal to ``changes-since``, or + earlier than or equal to ``changes-before``, an empty list is returned. + If data has changed, only the items changed between ``changes-since`` + time and ``changes-before`` time are returned in the response. + For example, performing a **GET** against:: + + https://api.servers.openstack.org/v2.1/servers?changes-since=2015-01-24T17:08Z&changes-before=2015-01-25T17:08Z + + would list all servers that have changed later than or equal to Mon, + 24 Jan 2015 17:08:00 UTC, and earlier than or equal to Mon, 25 Jan 2015 + 17:08:00 UTC. + +Microversion change history for servers, instance actions and migrations +regarding ``changes-since`` and ``changes-before``: + +* The `2.21 microversion`_ allows reading instance actions for a deleted + server resource. +* The `2.58 microversion`_ allows filtering on ``changes-since`` when listing + instance actions for a server. +* The `2.59 microversion`_ allows filtering on ``changes-since`` when listing + migration records. +* The `2.66 microversion`_ adds the ``changes-before`` filter when listing + servers, instance actions and migrations. + +The ``changes-since`` filter nor the ``changes-before`` filter +change any read-deleted behavior in the os-instance-actions or +os-migrations APIs. The os-instance-actions API with the 2.21 microversion +allows retrieving instance actions for a deleted server resource. +The os-migrations API takes an optional ``instance_uuid`` filter parameter +but does not support returning deleted migration records. To allow clients to keep track of changes, the ``changes-since`` filter -displays items that have been *recently* deleted. Both images and -servers contain a ``DELETED`` status that indicates that the resource -has been removed. Implementations are not required to keep track of -deleted resources indefinitely, so sending a ``changes-since`` time in the -distant past may miss deletions. +and ``changes-before`` filter displays items that have been *recently* +deleted. Servers contain a ``DELETED`` status that indicates that the +resource has been removed. Implementations are not required to keep track +of deleted resources indefinitely, so sending a ``changes-since`` time or +a ``changes-before`` time in the distant past may miss deletions. + +.. _2.21 microversion: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id19 +.. _2.58 microversion: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id53 +.. _2.59 microversion: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id54 +.. _2.66 microversion: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id59 diff --git a/api-guide/source/server_concepts.rst b/api-guide/source/server_concepts.rst index dd79db137086..eb4204f6273f 100644 --- a/api-guide/source/server_concepts.rst +++ b/api-guide/source/server_concepts.rst @@ -132,9 +132,9 @@ For different user roles, the user has different query options set: - For general user, there is limited set of attributes of the servers can be used as query option. ``reservation_id``, ``name``, ``status``, ``image``, - ``flavor``, ``ip``, ``changes-since``, ``ip6``, ``tags``, ``tags-any``, - ``not-tags``, ``not-tags-any`` are supported options to be used. Other - options will be ignored by nova silently. + ``flavor``, ``ip``, ``changes-since``, ``changes-before``, ``ip6``, + ``tags``, ``tags-any``, ``not-tags``, ``not-tags-any`` are supported options + to be used. Other options will be ignored by nova silently. - For administrator, most of the server attributes can be used as query options. Before the Ocata release, the fields in the database schema of @@ -197,11 +197,14 @@ For different user roles, the user has different query options set: ] } -There are also some speical query options: +There are also some special query options: - ``changes-since`` returns the servers updated after the given time. Please see: :doc:`polling_changes-since_parameter` +- ``changes-before`` returns the servers updated before the given time. + Please see: :doc:`polling_changes-since_parameter` + - ``deleted`` returns (or excludes) deleted servers - ``soft_deleted`` modifies behavior of 'deleted' to either include or exclude @@ -212,7 +215,7 @@ There are also some speical query options: .. code:: - **Example: User query server with special keys changes-since** + **Example: User query server with special keys changes-since or changes-before** Precondition: GET /servers/detail @@ -221,13 +224,13 @@ There are also some speical query options: { "servers": [ { - "name": "t1" - "updated": "2015-12-15T15:55:52Z" + "name": "t1", + "updated": "2015-12-15T15:55:52Z", ... }, { "name": "t2", - "updated": "2015-12-17T15:55:52Z" + "updated": "2015-12-17T15:55:52Z", ... } ] @@ -239,11 +242,40 @@ There are also some speical query options: { { "name": "t2", - "updated": "2015-12-17T15:55:52Z" + "updated": "2015-12-17T15:55:52Z", ... } } + GET /servers/detail?changes-before='2015-12-16T15:55:52Z' + + Response: + { + { + "name": "t1", + "updated": "2015-12-15T15:55:52Z", + ... + } + } + + GET /servers/detail?changes-since='2015-12-10T15:55:52Z'&changes-before='2015-12-28T15:55:52Z' + + Response: + { + "servers": [ + { + "name": "t1", + "updated": "2015-12-15T15:55:52Z", + ... + }, + { + "name": "t2", + "updated": "2015-12-17T15:55:52Z", + ... + } + ] + } + There are two kinds of matching in query options: Exact matching and regex matching. diff --git a/api-ref/source/os-instance-actions.inc b/api-ref/source/os-instance-actions.inc index df961d45e9b1..636987fe6616 100644 --- a/api-ref/source/os-instance-actions.inc +++ b/api-ref/source/os-instance-actions.inc @@ -34,6 +34,7 @@ Request - limit: instance_action_limit - marker: instance_action_marker - changes-since: changes_since_instance_action + - changes-before: changes_before_instance_action Response -------- diff --git a/api-ref/source/os-migrations.inc b/api-ref/source/os-migrations.inc index c8bc587f83b0..2a9e457cbdb5 100644 --- a/api-ref/source/os-migrations.inc +++ b/api-ref/source/os-migrations.inc @@ -35,6 +35,7 @@ Request - limit: migration_limit - marker: migration_marker - changes-since: changes_since_migration + - changes-before: changes_before_migration Response -------- diff --git a/api-ref/source/parameters.yaml b/api-ref/source/parameters.yaml index 052af90783bc..116604688cc1 100644 --- a/api-ref/source/parameters.yaml +++ b/api-ref/source/parameters.yaml @@ -453,6 +453,61 @@ changes-since: in: query required: false type: string +changes_before_instance_action: + description: | + Filters the response by a date and time stamp when the instance actions last changed. + Those instances that changed before or equal to the specified date and time stamp + are returned. + + The date and time stamp format is `ISO 8601 `_: + :: + + CCYY-MM-DDThh:mm:ss±hh:mm + + The ``±hh:mm`` value, if included, returns the time zone as an offset from UTC. + For example, ``2015-08-27T09:49:58-05:00``. + If you omit the time zone, the UTC time zone is assumed. + in: query + required: false + type: string + min_version: 2.66 +changes_before_migration: + description: | + Filters the response by a date and time stamp when the migration last + changed. Those migrations that changed before or equal to the specified date and time + stamp are returned. + + The date and time stamp format is `ISO 8601 `_: + :: + + CCYY-MM-DDThh:mm:ss±hh:mm + + The ``±hh:mm`` value, if included, returns the time zone as an offset from UTC. + For example, ``2015-08-27T09:49:58-05:00``. + If you omit the time zone, the UTC time zone is assumed. + in: query + required: false + type: string + min_version: 2.66 +changes_before_server: + description: | + Filters the response by a date and time stamp when the server last changed. + Those servers that changed before or equal to the specified date and time stamp + are returned. To help keep track of changes this may also return recently deleted + servers. + + The date and time stamp format is `ISO 8601 `_: + :: + + CCYY-MM-DDThh:mm:ss±hh:mm + + The ``±hh:mm`` value, if included, returns the time zone as an offset from UTC. + For example, ``2015-08-27T09:49:58-05:00``. + If you omit the time zone, the UTC time zone is assumed. + in: query + required: false + type: string + min_version: 2.66 changes_since_instance_action: description: | Filters the response by a date and time stamp when the instance action last diff --git a/api-ref/source/servers.inc b/api-ref/source/servers.inc index 8883f9af0ac9..2ceb257501ec 100644 --- a/api-ref/source/servers.inc +++ b/api-ref/source/servers.inc @@ -169,6 +169,7 @@ whitelist will be silently ignored. - ``status`` - ``tags`` (New in version 2.26) - ``tags-any`` (New in version 2.26) + - ``changes-before`` (New in version 2.66) - For admin user, whitelist includes all filter keys mentioned in @@ -230,6 +231,7 @@ Request - not-tags-any: not_tags_any_query - tags: tags_query - tags-any: tags_any_query + - changes-before: changes_before_server Response -------- @@ -552,6 +554,7 @@ Request - not-tags-any: not_tags_any_query - tags: tags_query - tags-any: tags_any_query + - changes-before: changes_before_server Response -------- diff --git a/doc/api_samples/os-instance-actions/v2.66/instance-action-get-non-admin-resp.json b/doc/api_samples/os-instance-actions/v2.66/instance-action-get-non-admin-resp.json new file mode 100644 index 000000000000..115604d6ac89 --- /dev/null +++ b/doc/api_samples/os-instance-actions/v2.66/instance-action-get-non-admin-resp.json @@ -0,0 +1,21 @@ +{ + "instanceAction": { + "action": "stop", + "events": [ + { + "event": "compute_stop_instance", + "finish_time": "2018-04-25T01:26:34.784165", + "hostId": "2091634baaccdc4c5a1d57069c833e402921df696b7f970791b12ec6", + "result": "Success", + "start_time": "2018-04-25T01:26:34.612020" + } + ], + "instance_uuid": "79edaa44-ad4f-4af7-b994-154518c2b927", + "message": null, + "project_id": "6f70656e737461636b20342065766572", + "request_id": "req-8eb28d4a-db6c-4337-bab8-ce154e9c620e", + "start_time": "2018-04-25T01:26:34.388280", + "updated_at": "2018-04-25T01:26:34.784165", + "user_id": "fake" + } +} \ No newline at end of file diff --git a/doc/api_samples/os-instance-actions/v2.66/instance-action-get-resp.json b/doc/api_samples/os-instance-actions/v2.66/instance-action-get-resp.json new file mode 100644 index 000000000000..57ae490f023f --- /dev/null +++ b/doc/api_samples/os-instance-actions/v2.66/instance-action-get-resp.json @@ -0,0 +1,23 @@ +{ + "instanceAction": { + "action": "stop", + "events": [ + { + "event": "compute_stop_instance", + "finish_time": "2018-04-25T01:26:36.790544", + "host": "compute", + "hostId": "2091634baaccdc4c5a1d57069c833e402921df696b7f970791b12ec6", + "result": "Success", + "start_time": "2018-04-25T01:26:36.539271", + "traceback": null + } + ], + "instance_uuid": "4bf3473b-d550-4b65-9409-292d44ab14a2", + "message": null, + "project_id": "6f70656e737461636b20342065766572", + "request_id": "req-0d819d5c-1527-4669-bdf0-ffad31b5105b", + "start_time": "2018-04-25T01:26:36.341290", + "updated_at": "2018-04-25T01:26:36.790544", + "user_id": "admin" + } +} \ No newline at end of file diff --git a/doc/api_samples/os-instance-actions/v2.66/instance-actions-list-resp.json b/doc/api_samples/os-instance-actions/v2.66/instance-actions-list-resp.json new file mode 100644 index 000000000000..0b2254126b1d --- /dev/null +++ b/doc/api_samples/os-instance-actions/v2.66/instance-actions-list-resp.json @@ -0,0 +1,24 @@ +{ + "instanceActions": [ + { + "action": "stop", + "instance_uuid": "15835b6f-1e14-4cfa-9f66-1abea1a1c0d5", + "message": null, + "project_id": "6f70656e737461636b20342065766572", + "request_id": "req-f04d4b92-6241-42da-b82d-2cedb225c58d", + "start_time": "2018-04-25T01:26:36.036697", + "updated_at": "2018-04-25T01:26:36.525308", + "user_id": "admin" + }, + { + "action": "create", + "instance_uuid": "15835b6f-1e14-4cfa-9f66-1abea1a1c0d5", + "message": null, + "project_id": "6f70656e737461636b20342065766572", + "request_id": "req-d8790618-9bbf-4df0-8af8-fc9e24de29c0", + "start_time": "2018-04-25T01:26:33.692125", + "updated_at": "2018-04-25T01:26:35.993821", + "user_id": "admin" + } + ] +} \ No newline at end of file diff --git a/doc/api_samples/os-instance-actions/v2.66/instance-actions-list-with-changes-before.json b/doc/api_samples/os-instance-actions/v2.66/instance-actions-list-with-changes-before.json new file mode 100644 index 000000000000..28c58384e703 --- /dev/null +++ b/doc/api_samples/os-instance-actions/v2.66/instance-actions-list-with-changes-before.json @@ -0,0 +1,24 @@ +{ + "instanceActions": [ + { + "action": "stop", + "instance_uuid": "2150964c-30fe-4214-9547-8822375aa7d0", + "message": null, + "project_id": "6f70656e737461636b20342065766572", + "request_id": "req-0c3b2079-0a44-474d-a5b2-7466d4b4c642", + "start_time": "2018-04-25T01:26:29.594237", + "updated_at": "2018-04-25T01:26:30.065061", + "user_id": "admin" + }, + { + "action": "create", + "instance_uuid": "15835b6f-1e14-4cfa-9f66-1abea1a1c0d5", + "message": null, + "project_id": "6f70656e737461636b20342065766572", + "request_id": "req-d8790618-9bbf-4df0-8af8-fc9e24de29c0", + "start_time": "2018-04-25T01:26:33.692125", + "updated_at": "2018-04-25T01:26:35.993821", + "user_id": "admin" + } + ] +} diff --git a/doc/api_samples/os-instance-actions/v2.66/instance-actions-list-with-changes-since.json b/doc/api_samples/os-instance-actions/v2.66/instance-actions-list-with-changes-since.json new file mode 100644 index 000000000000..346c93af7a93 --- /dev/null +++ b/doc/api_samples/os-instance-actions/v2.66/instance-actions-list-with-changes-since.json @@ -0,0 +1,14 @@ +{ + "instanceActions": [ + { + "action": "stop", + "instance_uuid": "2150964c-30fe-4214-9547-8822375aa7d0", + "message": null, + "project_id": "6f70656e737461636b20342065766572", + "request_id": "req-0c3b2079-0a44-474d-a5b2-7466d4b4c642", + "start_time": "2018-04-25T01:26:29.594237", + "updated_at": "2018-04-25T01:26:30.065061", + "user_id": "admin" + } + ] +} \ No newline at end of file diff --git a/doc/api_samples/os-instance-actions/v2.66/instance-actions-list-with-limit-resp.json b/doc/api_samples/os-instance-actions/v2.66/instance-actions-list-with-limit-resp.json new file mode 100644 index 000000000000..7126a9f28200 --- /dev/null +++ b/doc/api_samples/os-instance-actions/v2.66/instance-actions-list-with-limit-resp.json @@ -0,0 +1,20 @@ +{ + "instanceActions": [ + { + "action": "stop", + "instance_uuid": "ca3d3be5-1a40-427f-9515-f5e181f479d0", + "message": null, + "project_id": "6f70656e737461636b20342065766572", + "request_id": "req-4dbefbb7-d743-4d42-b0a1-a79cbe256138", + "start_time": "2018-04-25T01:26:28.909887", + "updated_at": "2018-04-25T01:26:29.400606", + "user_id": "admin" + } + ], + "links": [ + { + "href": "http://openstack.example.com/v2.1/6f70656e737461636b20342065766572/servers/ca3d3be5-1a40-427f-9515-f5e181f479d0/os-instance-actions?limit=1&marker=req-4dbefbb7-d743-4d42-b0a1-a79cbe256138", + "rel": "next" + } + ] +} \ No newline at end of file diff --git a/doc/api_samples/os-instance-actions/v2.66/instance-actions-list-with-marker-resp.json b/doc/api_samples/os-instance-actions/v2.66/instance-actions-list-with-marker-resp.json new file mode 100644 index 000000000000..3f6921cb795e --- /dev/null +++ b/doc/api_samples/os-instance-actions/v2.66/instance-actions-list-with-marker-resp.json @@ -0,0 +1,14 @@ +{ + "instanceActions": [ + { + "action": "create", + "instance_uuid": "9bde1fd5-8435-45c5-afc1-bedd0605275b", + "message": null, + "project_id": "6f70656e737461636b20342065766572", + "request_id": "req-4510fb10-447f-4572-a64d-c2324547d86c", + "start_time": "2018-04-25T01:26:33.710291", + "updated_at": "2018-04-25T01:26:35.374936", + "user_id": "fake" + } + ] +} \ No newline at end of file diff --git a/doc/api_samples/os-migrations/v2.66/migrations-get-with-changes-before.json b/doc/api_samples/os-migrations/v2.66/migrations-get-with-changes-before.json new file mode 100644 index 000000000000..e829087f87da --- /dev/null +++ b/doc/api_samples/os-migrations/v2.66/migrations-get-with-changes-before.json @@ -0,0 +1,30 @@ +{ + "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" + } + ] +} diff --git a/doc/api_samples/os-migrations/v2.66/migrations-get-with-changes-since.json b/doc/api_samples/os-migrations/v2.66/migrations-get-with-changes-since.json new file mode 100644 index 000000000000..7d36fe4548bc --- /dev/null +++ b/doc/api_samples/os-migrations/v2.66/migrations-get-with-changes-since.json @@ -0,0 +1,36 @@ +{ + "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" + }, + { + "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" + } + ] +} diff --git a/doc/api_samples/os-migrations/v2.66/migrations-get-with-limit.json b/doc/api_samples/os-migrations/v2.66/migrations-get-with-limit.json new file mode 100644 index 000000000000..328106bb3f1a --- /dev/null +++ b/doc/api_samples/os-migrations/v2.66/migrations-get-with-limit.json @@ -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": "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" + } + ], + "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.66/migrations-get-with-marker.json b/doc/api_samples/os-migrations/v2.66/migrations-get-with-marker.json new file mode 100644 index 000000000000..e829087f87da --- /dev/null +++ b/doc/api_samples/os-migrations/v2.66/migrations-get-with-marker.json @@ -0,0 +1,30 @@ +{ + "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" + } + ] +} diff --git a/doc/api_samples/os-migrations/v2.66/migrations-get.json b/doc/api_samples/os-migrations/v2.66/migrations-get.json new file mode 100644 index 000000000000..42ffca89638a --- /dev/null +++ b/doc/api_samples/os-migrations/v2.66/migrations-get.json @@ -0,0 +1,78 @@ +{ + "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" + }, + { + "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" + }, + { + "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" + }, + { + "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" + } + ] +} diff --git a/doc/api_samples/servers/v2.66/server-create-req.json b/doc/api_samples/servers/v2.66/server-create-req.json new file mode 100644 index 000000000000..5523ce8d349e --- /dev/null +++ b/doc/api_samples/servers/v2.66/server-create-req.json @@ -0,0 +1,28 @@ +{ + "server" : { + "accessIPv4": "1.2.3.4", + "accessIPv6": "80fe::", + "name" : "new-server-test", + "imageRef" : "70a599e0-31e7-49b7-b260-868f441e862b", + "flavorRef" : "6", + "availability_zone": "nova", + "OS-DCF:diskConfig": "AUTO", + "metadata" : { + "My Server Name" : "Apache1" + }, + "security_groups": [ + { + "name": "default" + } + ], + "user_data" : "IyEvYmluL2Jhc2gKL2Jpbi9zdQplY2hvICJJIGFtIGluIHlvdSEiCg==", + "networks": "auto", + "trusted_image_certificates": [ + "0b5d2c72-12cc-4ba6-a8d7-3ff5cc1d8cb8", + "674736e3-f25c-405c-8362-bbf991e0ce0a" + ] + }, + "OS-SCH-HNT:scheduler_hints": { + "same_host": "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}" + } +} \ No newline at end of file diff --git a/doc/api_samples/servers/v2.66/server-create-resp.json b/doc/api_samples/servers/v2.66/server-create-resp.json new file mode 100644 index 000000000000..7400eb332720 --- /dev/null +++ b/doc/api_samples/servers/v2.66/server-create-resp.json @@ -0,0 +1,22 @@ +{ + "server": { + "OS-DCF:diskConfig": "AUTO", + "adminPass": "wKLKinb9u7GM", + "id": "aab35fd0-b459-4b59-9308-5a23147f3165", + "links": [ + { + "href": "http://openstack.example.com/v2.1/6f70656e737461636b20342065766572/servers/aab35fd0-b459-4b59-9308-5a23147f3165", + "rel": "self" + }, + { + "href": "http://openstack.example.com/6f70656e737461636b20342065766572/servers/aab35fd0-b459-4b59-9308-5a23147f3165", + "rel": "bookmark" + } + ], + "security_groups": [ + { + "name": "default" + } + ] + } +} \ No newline at end of file diff --git a/doc/api_samples/servers/v2.66/server-get-resp.json b/doc/api_samples/servers/v2.66/server-get-resp.json new file mode 100644 index 000000000000..f34f34b02197 --- /dev/null +++ b/doc/api_samples/servers/v2.66/server-get-resp.json @@ -0,0 +1,184 @@ +{ + "server": [ + { + "OS-DCF:diskConfig": "AUTO", + "OS-EXT-AZ:availability_zone": "nova", + "OS-EXT-SRV-ATTR:host": "compute", + "OS-EXT-SRV-ATTR:hostname": "new-server-test", + "OS-EXT-SRV-ATTR:hypervisor_hostname": "fake-mini", + "OS-EXT-SRV-ATTR:instance_name": "instance-00000001", + "OS-EXT-SRV-ATTR:kernel_id": "", + "OS-EXT-SRV-ATTR:launch_index": 0, + "OS-EXT-SRV-ATTR:ramdisk_id": "", + "OS-EXT-SRV-ATTR:reservation_id": "r-ov3q80zj", + "OS-EXT-SRV-ATTR:root_device_name": "/dev/sda", + "OS-EXT-SRV-ATTR:user_data": "IyEvYmluL2Jhc2gKL2Jpbi9zdQplY2hvICJJIGFtIGluIHlvdSEiCg==", + "OS-EXT-STS:power_state": 1, + "OS-EXT-STS:task_state": null, + "OS-EXT-STS:vm_state": "active", + "OS-SRV-USG:launched_at": "2018-02-14T19:23:59.895661", + "OS-SRV-USG:terminated_at": null, + "accessIPv4": "1.2.3.4", + "accessIPv6": "80fe::", + "addresses": { + "private": [ + { + "OS-EXT-IPS-MAC:mac_addr": "aa:bb:cc:dd:ee:ff", + "OS-EXT-IPS:type": "fixed", + "addr": "192.168.0.3", + "version": 4 + } + ] + }, + "config_drive": "", + "created": "2018-02-14T15:23:58Z", + "description": null, + "flavor": { + "disk": 1, + "ephemeral": 0, + "extra_specs": { + "hw:cpu_policy": "dedicated", + "hw:mem_page_size": "2048" + }, + "original_name": "m1.tiny.specs", + "ram": 512, + "swap": 0, + "vcpus": 1 + }, + "hostId": "2091634baaccdc4c5a1d57069c833e402921df696b7f970791b12ec6", + "host_status": "UP", + "id": "9168b536-cd40-4630-b43f-b259807c6e87", + "image": { + "id": "70a599e0-31e7-49b7-b260-868f441e862b", + "links": [ + { + "href": "http://openstack.example.com/6f70656e737461636b20342065766572/images/70a599e0-31e7-49b7-b260-868f441e862b", + "rel": "bookmark" + } + ] + }, + "key_name": null, + "links": [ + { + "href": "http://openstack.example.com/v2.1/6f70656e737461636b20342065766572/servers/9168b536-cd40-4630-b43f-b259807c6e87", + "rel": "self" + }, + { + "href": "http://openstack.example.com/6f70656e737461636b20342065766572/servers/9168b536-cd40-4630-b43f-b259807c6e87", + "rel": "bookmark" + } + ], + "locked": false, + "metadata": { + "My Server Name": "Apache1" + }, + "name": "new-server-test", + "os-extended-volumes:volumes_attached": [], + "progress": 0, + "security_groups": [ + { + "name": "default" + } + ], + "status": "ACTIVE", + "tags": [], + "tenant_id": "6f70656e737461636b20342065766572", + "trusted_image_certificates": [ + "0b5d2c72-12cc-4ba6-a8d7-3ff5cc1d8cb8", + "674736e3-f25c-405c-8362-bbf991e0ce0a" + ], + "updated": "2018-02-14T15:24:00Z", + "user_id": "fake" + }, + { + "OS-DCF:diskConfig": "AUTO", + "OS-EXT-AZ:availability_zone": "nova", + "OS-EXT-SRV-ATTR:host": "compute", + "OS-EXT-SRV-ATTR:hostname": "new-server-test", + "OS-EXT-SRV-ATTR:hypervisor_hostname": "fake-mini", + "OS-EXT-SRV-ATTR:instance_name": "instance-00000002", + "OS-EXT-SRV-ATTR:kernel_id": "", + "OS-EXT-SRV-ATTR:launch_index": 0, + "OS-EXT-SRV-ATTR:ramdisk_id": "", + "OS-EXT-SRV-ATTR:reservation_id": "r-ov3q80zj", + "OS-EXT-SRV-ATTR:root_device_name": "/dev/sda", + "OS-EXT-SRV-ATTR:user_data": "IyEvYmluL2Jhc2gKL2Jpbi9zdQplY2hvICJJIGFtIGluIHlvdSEiCg==", + "OS-EXT-STS:power_state": 1, + "OS-EXT-STS:task_state": null, + "OS-EXT-STS:vm_state": "active", + "OS-SRV-USG:launched_at": "2018-02-14T19:23:59.895661", + "OS-SRV-USG:terminated_at": null, + "accessIPv4": "1.2.3.4", + "accessIPv6": "80fe::", + "addresses": { + "private": [ + { + "OS-EXT-IPS-MAC:mac_addr": "aa:bb:cc:dd:ee:ff", + "OS-EXT-IPS:type": "fixed", + "addr": "192.168.0.2", + "version": 4 + } + ] + }, + "config_drive": "", + "created": "2018-02-14T17:23:58Z", + "description": null, + "flavor": { + "disk": 1, + "ephemeral": 0, + "extra_specs": { + "hw:cpu_policy": "dedicated", + "hw:mem_page_size": "2048" + }, + "original_name": "m1.tiny.specs", + "ram": 512, + "swap": 0, + "vcpus": 1 + }, + "hostId": "2091634baaccdc4c5a1d57069c833e402921df696b7f970791b12ec6", + "host_status": "UP", + "id": "9168b536-cd40-4630-b43f-b259807c6e83", + "image": { + "id": "70a599e0-31e7-49b7-b260-868f441e862b", + "links": [ + { + "href": "http://openstack.example.com/6f70656e737461636b20342065766572/images/70a599e0-31e7-49b7-b260-868f441e862b", + "rel": "bookmark" + } + ] + }, + "key_name": null, + "links": [ + { + "href": "http://openstack.example.com/v2.1/6f70656e737461636b20342065766572/servers/9168b536-cd40-4630-b43f-b259807c6e87", + "rel": "self" + }, + { + "href": "http://openstack.example.com/6f70656e737461636b20342065766572/servers/9168b536-cd40-4630-b43f-b259807c6e87", + "rel": "bookmark" + } + ], + "locked": false, + "metadata": { + "My Server Name": "Apache1" + }, + "name": "new-server-test", + "os-extended-volumes:volumes_attached": [], + "progress": 0, + "security_groups": [ + { + "name": "default" + } + ], + "status": "ACTIVE", + "tags": [], + "tenant_id": "6f70656e737461636b20342065766572", + "trusted_image_certificates": [ + "0b5d2c72-12cc-4ba6-a8d7-3ff5cc1d8cb8", + "674736e3-f25c-405c-8362-bbf991e0ce0a" + ], + "updated": "2018-02-14T17:24:00Z", + "user_id": "fake" + } + ] +} diff --git a/doc/api_samples/servers/v2.66/servers-details-resp.json b/doc/api_samples/servers/v2.66/servers-details-resp.json new file mode 100644 index 000000000000..055be12fb716 --- /dev/null +++ b/doc/api_samples/servers/v2.66/servers-details-resp.json @@ -0,0 +1,190 @@ +{ + "servers": [ + { + "OS-DCF:diskConfig": "AUTO", + "OS-EXT-AZ:availability_zone": "nova", + "OS-EXT-SRV-ATTR:host": "compute", + "OS-EXT-SRV-ATTR:hostname": "new-server-test", + "OS-EXT-SRV-ATTR:hypervisor_hostname": "fake-mini", + "OS-EXT-SRV-ATTR:instance_name": "instance-00000001", + "OS-EXT-SRV-ATTR:kernel_id": "", + "OS-EXT-SRV-ATTR:launch_index": 0, + "OS-EXT-SRV-ATTR:ramdisk_id": "", + "OS-EXT-SRV-ATTR:reservation_id": "r-y0w4v32k", + "OS-EXT-SRV-ATTR:root_device_name": "/dev/sda", + "OS-EXT-SRV-ATTR:user_data": "IyEvYmluL2Jhc2gKL2Jpbi9zdQplY2hvICJJIGFtIGluIHlvdSEiCg==", + "OS-EXT-STS:power_state": 1, + "OS-EXT-STS:task_state": null, + "OS-EXT-STS:vm_state": "active", + "OS-SRV-USG:launched_at": "2018-10-10T15:49:09.516729", + "OS-SRV-USG:terminated_at": null, + "accessIPv4": "1.2.3.4", + "accessIPv6": "80fe::", + "addresses": { + "private": [ + { + "OS-EXT-IPS-MAC:mac_addr": "aa:bb:cc:dd:ee:ff", + "OS-EXT-IPS:type": "fixed", + "addr": "192.168.0.1", + "version": 4 + } + ] + }, + "config_drive": "", + "created": "2018-10-10T15:49:08Z", + "description": null, + "flavor": { + "disk": 1, + "ephemeral": 0, + "extra_specs": { + "hw:cpu_policy": "dedicated", + "hw:mem_page_size": "2048" + }, + "original_name": "m1.tiny.specs", + "ram": 512, + "swap": 0, + "vcpus": 1 + }, + "hostId": "2091634baaccdc4c5a1d57069c833e402921df696b7f970791b12ec6", + "host_status": "UP", + "id": "569f39f9-7c76-42a1-9c2d-8394e2638a6e", + "image": { + "id": "70a599e0-31e7-49b7-b260-868f441e862b", + "links": [ + { + "href": "http://openstack.example.com/6f70656e737461636b20342065766572/images/70a599e0-31e7-49b7-b260-868f441e862b", + "rel": "bookmark" + } + ] + }, + "key_name": null, + "links": [ + { + "href": "http://openstack.example.com/v2.1/6f70656e737461636b20342065766572/servers/569f39f9-7c76-42a1-9c2d-8394e2638a6d", + "rel": "self" + }, + { + "href": "http://openstack.example.com/6f70656e737461636b20342065766572/servers/569f39f9-7c76-42a1-9c2d-8394e2638a6d", + "rel": "bookmark" + } + ], + "locked": false, + "metadata": { + "My Server Name": "Apache1" + }, + "name": "new-server-test", + "os-extended-volumes:volumes_attached": [], + "progress": 0, + "security_groups": [ + { + "name": "default" + } + ], + "status": "ACTIVE", + "tags": [], + "tenant_id": "6f70656e737461636b20342065766572", + "trusted_image_certificates": [ + "0b5d2c72-12cc-4ba6-a8d7-3ff5cc1d8cb8", + "674736e3-f25c-405c-8362-bbf991e0ce0a" + ], + "updated": "2018-10-10T15:49:09Z", + "user_id": "fake" + }, + { + "OS-DCF:diskConfig": "AUTO", + "OS-EXT-AZ:availability_zone": "nova", + "OS-EXT-SRV-ATTR:host": "compute", + "OS-EXT-SRV-ATTR:hostname": "new-server-test", + "OS-EXT-SRV-ATTR:hypervisor_hostname": "fake-mini", + "OS-EXT-SRV-ATTR:instance_name": "instance-00000002", + "OS-EXT-SRV-ATTR:kernel_id": "", + "OS-EXT-SRV-ATTR:launch_index": 0, + "OS-EXT-SRV-ATTR:ramdisk_id": "", + "OS-EXT-SRV-ATTR:reservation_id": "r-y0w4v32k", + "OS-EXT-SRV-ATTR:root_device_name": "/dev/sda", + "OS-EXT-SRV-ATTR:user_data": "IyEvYmluL2Jhc2gKL2Jpbi9zdQplY2hvICJJIGFtIGluIHlvdSEiCg==", + "OS-EXT-STS:power_state": 1, + "OS-EXT-STS:task_state": null, + "OS-EXT-STS:vm_state": "active", + "OS-SRV-USG:launched_at": "2018-10-10T17:49:09.516729", + "OS-SRV-USG:terminated_at": null, + "accessIPv4": "1.2.3.4", + "accessIPv6": "80fe::", + "addresses": { + "private": [ + { + "OS-EXT-IPS-MAC:mac_addr": "aa:bb:cc:dd:ee:ff", + "OS-EXT-IPS:type": "fixed", + "addr": "192.168.0.2", + "version": 4 + } + ] + }, + "config_drive": "", + "created": "2018-10-10T17:49:08Z", + "description": null, + "flavor": { + "disk": 1, + "ephemeral": 0, + "extra_specs": { + "hw:cpu_policy": "dedicated", + "hw:mem_page_size": "2048" + }, + "original_name": "m1.tiny.specs", + "ram": 512, + "swap": 0, + "vcpus": 1 + }, + "hostId": "2091634baaccdc4c5a1d57069c833e402921df696b7f970791b12ec6", + "host_status": "UP", + "id": "569f39f9-7c76-42a1-9c2d-8394e2638a6f", + "image": { + "id": "70a599e0-31e7-49b7-b260-868f441e862b", + "links": [ + { + "href": "http://openstack.example.com/6f70656e737461636b20342065766572/images/70a599e0-31e7-49b7-b260-868f441e862b", + "rel": "bookmark" + } + ] + }, + "key_name": null, + "links": [ + { + "href": "http://openstack.example.com/v2.1/6f70656e737461636b20342065766572/servers/569f39f9-7c76-42a1-9c2d-8394e2638a6d", + "rel": "self" + }, + { + "href": "http://openstack.example.com/6f70656e737461636b20342065766572/servers/569f39f9-7c76-42a1-9c2d-8394e2638a6d", + "rel": "bookmark" + } + ], + "locked": false, + "metadata": { + "My Server Name": "Apache1" + }, + "name": "new-server-test", + "os-extended-volumes:volumes_attached": [], + "progress": 0, + "security_groups": [ + { + "name": "default" + } + ], + "status": "ACTIVE", + "tags": [], + "tenant_id": "6f70656e737461636b20342065766572", + "trusted_image_certificates": [ + "0b5d2c72-12cc-4ba6-a8d7-3ff5cc1d8cb8", + "674736e3-f25c-405c-8362-bbf991e0ce0a" + ], + "updated": "2018-10-10T17:49:09Z", + "user_id": "fake" + } + ], + "servers_links": [ + { + "href": "http://openstack.example.com/v2.1/6f70656e737461636b20342065766572/servers/detail?limit=1&marker=569f39f9-7c76-42a1-9c2d-8394e2638a6d", + "rel": "next" + } + ] +} diff --git a/doc/api_samples/servers/v2.66/servers-details-with-changes-before.json b/doc/api_samples/servers/v2.66/servers-details-with-changes-before.json new file mode 100644 index 000000000000..69d360dadbb3 --- /dev/null +++ b/doc/api_samples/servers/v2.66/servers-details-with-changes-before.json @@ -0,0 +1,94 @@ +{ + "servers": [ + { + "OS-DCF:diskConfig": "AUTO", + "OS-EXT-AZ:availability_zone": "nova", + "OS-EXT-SRV-ATTR:host": "compute", + "OS-EXT-SRV-ATTR:hostname": "new-server-test", + "OS-EXT-SRV-ATTR:hypervisor_hostname": "fake-mini", + "OS-EXT-SRV-ATTR:instance_name": "instance-00000001", + "OS-EXT-SRV-ATTR:kernel_id": "", + "OS-EXT-SRV-ATTR:launch_index": 0, + "OS-EXT-SRV-ATTR:ramdisk_id": "", + "OS-EXT-SRV-ATTR:reservation_id": "r-y0w4v32k", + "OS-EXT-SRV-ATTR:root_device_name": "/dev/sda", + "OS-EXT-SRV-ATTR:user_data": "IyEvYmluL2Jhc2gKL2Jpbi9zdQplY2hvICJJIGFtIGluIHlvdSEiCg==", + "OS-EXT-STS:power_state": 1, + "OS-EXT-STS:task_state": null, + "OS-EXT-STS:vm_state": "active", + "OS-SRV-USG:launched_at": "2018-10-10T15:49:09.516729", + "OS-SRV-USG:terminated_at": null, + "accessIPv4": "1.2.3.4", + "accessIPv6": "80fe::", + "addresses": { + "private": [ + { + "OS-EXT-IPS-MAC:mac_addr": "aa:bb:cc:dd:ee:ff", + "OS-EXT-IPS:type": "fixed", + "addr": "192.168.0.1", + "version": 4 + } + ] + }, + "config_drive": "", + "created": "2018-10-10T15:49:08Z", + "description": null, + "flavor": { + "disk": 1, + "ephemeral": 0, + "extra_specs": { + "hw:cpu_policy": "dedicated", + "hw:mem_page_size": "2048" + }, + "original_name": "m1.tiny.specs", + "ram": 512, + "swap": 0, + "vcpus": 1 + }, + "hostId": "2091634baaccdc4c5a1d57069c833e402921df696b7f970791b12ec6", + "host_status": "UP", + "id": "569f39f9-7c76-42a1-9c2d-8394e2638a6e", + "image": { + "id": "70a599e0-31e7-49b7-b260-868f441e862b", + "links": [ + { + "href": "http://openstack.example.com/6f70656e737461636b20342065766572/images/70a599e0-31e7-49b7-b260-868f441e862b", + "rel": "bookmark" + } + ] + }, + "key_name": null, + "links": [ + { + "href": "http://openstack.example.com/v2.1/6f70656e737461636b20342065766572/servers/569f39f9-7c76-42a1-9c2d-8394e2638a6d", + "rel": "self" + }, + { + "href": "http://openstack.example.com/6f70656e737461636b20342065766572/servers/569f39f9-7c76-42a1-9c2d-8394e2638a6d", + "rel": "bookmark" + } + ], + "locked": false, + "metadata": { + "My Server Name": "Apache1" + }, + "name": "new-server-test", + "os-extended-volumes:volumes_attached": [], + "progress": 0, + "security_groups": [ + { + "name": "default" + } + ], + "status": "ACTIVE", + "tags": [], + "tenant_id": "6f70656e737461636b20342065766572", + "trusted_image_certificates": [ + "0b5d2c72-12cc-4ba6-a8d7-3ff5cc1d8cb8", + "674736e3-f25c-405c-8362-bbf991e0ce0a" + ], + "updated": "2018-10-10T15:49:09Z", + "user_id": "fake" + } + ] +} diff --git a/doc/api_samples/servers/v2.66/servers-list-with-changes-before.json b/doc/api_samples/servers/v2.66/servers-list-with-changes-before.json new file mode 100644 index 000000000000..d86d5ea9485f --- /dev/null +++ b/doc/api_samples/servers/v2.66/servers-list-with-changes-before.json @@ -0,0 +1,18 @@ +{ + "servers": [ + { + "id": "6e3a87e6-a133-452e-86e1-a31291c1b1c8", + "links": [ + { + "href": "http://openstack.example.com/v2.1/6f70656e737461636b20342065766572/servers/6e3a87e6-a133-452e-86e1-a31291c1b1c8", + "rel": "self" + }, + { + "href": "http://openstack.example.com/6f70656e737461636b20342065766572/servers/6e3a87e6-a133-452e-86e1-a31291c1b1c8", + "rel": "bookmark" + } + ], + "name": "new-server-test" + } + ] +} diff --git a/doc/api_samples/versions/v21-version-get-resp.json b/doc/api_samples/versions/v21-version-get-resp.json index 7e2434ee3325..43e4ef47c9cc 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.65", + "version": "2.66", "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 8fb2d2430cf4..65dfad432f77 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.65", + "version": "2.66", "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 058945ae5b15..7598b156b628 100644 --- a/nova/api/openstack/api_version_request.py +++ b/nova/api/openstack/api_version_request.py @@ -158,6 +158,10 @@ REST_API_VERSION_HISTORY = """REST API Version History: /os-server-groups/{group_id} API. * 2.65 - Add support for abort live migrations in ``queued`` and ``preparing`` status. + * 2.66 - Add ``changes-before`` to support users to specify the + ``updated_at`` time to filter nova resources, the resources + include the servers API, os-instance-action API and + os-migrations API. """ # The minimum and maximum versions of the API supported @@ -166,7 +170,7 @@ REST_API_VERSION_HISTORY = """REST API Version History: # 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.65" +_MAX_API_VERSION = "2.66" 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/instance_actions.py b/nova/api/openstack/compute/instance_actions.py index aef7440340ce..656fca2ece3e 100644 --- a/nova/api/openstack/compute/instance_actions.py +++ b/nova/api/openstack/compute/instance_actions.py @@ -92,8 +92,10 @@ class InstanceActionsController(wsgi.Controller): @wsgi.Controller.api_version("2.58") # noqa @wsgi.expected_errors((400, 404)) + @validation.query_schema(schema_instance_actions.list_query_params_v266, + "2.66") @validation.query_schema(schema_instance_actions.list_query_params_v258, - "2.58") + "2.58", "2.65") def index(self, req, server_id): """Returns the list of actions recorded for a given instance.""" context = req.environ["nova.context"] @@ -105,6 +107,10 @@ class InstanceActionsController(wsgi.Controller): search_opts['changes-since'] = timeutils.parse_isotime( search_opts['changes-since']) + if 'changes-before' in search_opts: + search_opts['changes-before'] = timeutils.parse_isotime( + search_opts['changes-before']) + limit, marker = common.get_limit_and_marker(req) try: actions_raw = self.action_api.actions_get(context, instance, diff --git a/nova/api/openstack/compute/migrations.py b/nova/api/openstack/compute/migrations.py index e4a6a6edfbda..98ee3adbdc79 100644 --- a/nova/api/openstack/compute/migrations.py +++ b/nova/api/openstack/compute/migrations.py @@ -75,7 +75,7 @@ class MigrationsController(wsgi.Controller): def _index(self, req, add_link=False, next_link=False, add_uuid=False, sort_dirs=None, sort_keys=None, limit=None, marker=None, - allow_changes_since=False): + allow_changes_since=False, allow_changes_before=False): context = req.environ['nova.context'] context.can(migrations_policies.POLICY_ROOT % 'index') search_opts = {} @@ -92,6 +92,17 @@ class MigrationsController(wsgi.Controller): # it from search_opts. del search_opts['changes-since'] + if 'changes-before' in search_opts: + if allow_changes_before: + search_opts['changes-before'] = timeutils.parse_isotime( + search_opts['changes-before']) + else: + # Before microversion 2.59 the schema allowed + # additionalProperties=True, so a user could pass + # changes-before before 2.59 and filter by the updated_at + # field if we don't remove it from search_opts. + del search_opts['changes-before'] + if sort_keys: try: migrations = self.compute_api.get_migrations_sorted( @@ -129,10 +140,10 @@ class MigrationsController(wsgi.Controller): """Return all migrations using the query parameters as filters.""" return self._index(req, add_link=True) - @wsgi.Controller.api_version("2.59") # noqa + @wsgi.Controller.api_version("2.59", "2.65") # noqa @wsgi.expected_errors(400) @validation.query_schema(schema_migrations.list_query_params_v259, - "2.59") + "2.59", "2.65") def index(self, req): """Return all migrations using the query parameters as filters.""" limit, marker = common.get_limit_and_marker(req) @@ -141,3 +152,17 @@ class MigrationsController(wsgi.Controller): sort_dirs=['desc', 'desc'], limit=limit, marker=marker, allow_changes_since=True) + + @wsgi.Controller.api_version("2.66") # noqa + @wsgi.expected_errors(400) + @validation.query_schema(schema_migrations.list_query_params_v266, + "2.66") + def index(self, req): + """Return all migrations using the query parameters as filters.""" + limit, marker = common.get_limit_and_marker(req) + return self._index(req, add_link=True, next_link=True, add_uuid=True, + sort_keys=['created_at', 'id'], + sort_dirs=['desc', 'desc'], + limit=limit, marker=marker, + allow_changes_since=True, + allow_changes_before=True) diff --git a/nova/api/openstack/compute/rest_api_version_history.rst b/nova/api/openstack/compute/rest_api_version_history.rst index f8a7442cdd39..a3757beacf77 100644 --- a/nova/api/openstack/compute/rest_api_version_history.rst +++ b/nova/api/openstack/compute/rest_api_version_history.rst @@ -842,3 +842,15 @@ in server group APIs: Add support for abort live migrations in ``queued`` and ``preparing`` status for API ``DELETE /servers/{server_id}/migrations/{migration_id}``. + +2.66 +---- + +The ``changes-before`` filter can be included as a request parameter of the +following APIs to filter by changes before or equal to the resource +``updated_at`` time: + +* ``GET /servers`` +* ``GET /servers/detail`` +* ``GET /servers/{server_id}/os-instance-actions`` +* ``GET /os-migrations`` diff --git a/nova/api/openstack/compute/schemas/instance_actions.py b/nova/api/openstack/compute/schemas/instance_actions.py index 25e61ff61ac6..dc1f49a567fd 100644 --- a/nova/api/openstack/compute/schemas/instance_actions.py +++ b/nova/api/openstack/compute/schemas/instance_actions.py @@ -12,6 +12,8 @@ # License for the specific language governing permissions and limitations # under the License. +import copy + from nova.api.validation import parameter_types list_query_params_v258 = { @@ -27,3 +29,9 @@ list_query_params_v258 = { }, 'additionalProperties': False } + +list_query_params_v266 = copy.deepcopy(list_query_params_v258) +list_query_params_v266['properties'].update({ + 'changes-before': parameter_types.single_param( + {'type': 'string', 'format': 'date-time'}), +}) diff --git a/nova/api/openstack/compute/schemas/migrations.py b/nova/api/openstack/compute/schemas/migrations.py index 31f07b0ce39d..6892aa07d0ce 100644 --- a/nova/api/openstack/compute/schemas/migrations.py +++ b/nova/api/openstack/compute/schemas/migrations.py @@ -41,3 +41,9 @@ list_query_params_v259['properties'].update({ {'type': 'string', 'format': 'date-time'}), }) list_query_params_v259['additionalProperties'] = False + +list_query_params_v266 = copy.deepcopy(list_query_params_v259) +list_query_params_v266['properties'].update({ + 'changes-before': parameter_types.single_param( + {'type': 'string', 'format': 'date-time'}), +}) diff --git a/nova/api/openstack/compute/schemas/servers.py b/nova/api/openstack/compute/schemas/servers.py index 768288725fc7..025f8de58b42 100644 --- a/nova/api/openstack/compute/schemas/servers.py +++ b/nova/api/openstack/compute/schemas/servers.py @@ -621,3 +621,9 @@ query_params_v226['properties'].update({ 'not-tags': parameter_types.common_query_regex_param, 'not-tags-any': parameter_types.common_query_regex_param, }) + +query_params_v266 = copy.deepcopy(query_params_v226) +query_params_v266['properties'].update({ + 'changes-before': multi_params({'type': 'string', + 'format': 'date-time'}), +}) diff --git a/nova/api/openstack/compute/servers.py b/nova/api/openstack/compute/servers.py index 8736e00651b8..e8e90075d516 100644 --- a/nova/api/openstack/compute/servers.py +++ b/nova/api/openstack/compute/servers.py @@ -78,7 +78,8 @@ class ServersController(wsgi.Controller): self.compute_api = compute.API() @wsgi.expected_errors((400, 403)) - @validation.query_schema(schema_servers.query_params_v226, '2.26') + @validation.query_schema(schema_servers.query_params_v266, '2.66') + @validation.query_schema(schema_servers.query_params_v226, '2.26', '2.65') @validation.query_schema(schema_servers.query_params_v21, '2.1', '2.25') def index(self, req): """Returns a list of server names and ids for a given user.""" @@ -91,7 +92,8 @@ class ServersController(wsgi.Controller): return servers @wsgi.expected_errors((400, 403)) - @validation.query_schema(schema_servers.query_params_v226, '2.26') + @validation.query_schema(schema_servers.query_params_v266, '2.66') + @validation.query_schema(schema_servers.query_params_v226, '2.26', '2.65') @validation.query_schema(schema_servers.query_params_v21, '2.1', '2.25') def detail(self, req): """Returns a list of server details for a given user.""" @@ -154,15 +156,32 @@ class ServersController(wsgi.Controller): msg = _("Invalid filter field: changes-since.") raise exc.HTTPBadRequest(explanation=msg) + if 'changes-before' in search_opts: + try: + search_opts['changes-before'] = timeutils.parse_isotime( + search_opts['changes-before']) + changes_since = search_opts.get('changes-since') + if changes_since and search_opts['changes-before'] < \ + search_opts['changes-since']: + msg = _('The value of changes-since must be' + ' less than or equal to changes-before.') + raise exc.HTTPBadRequest(explanation=msg) + except ValueError: + msg = _("Invalid filter field: changes-before.") + raise exc.HTTPBadRequest(explanation=msg) + # By default, compute's get_all() will return deleted instances. # If an admin hasn't specified a 'deleted' search option, we need # to filter out deleted instances by setting the filter ourselves. - # ... Unless 'changes-since' is specified, because 'changes-since' - # should return recently deleted instances according to the API spec. + # ... Unless 'changes-since' or 'changes-before' is specified, + # because those will return recently deleted instances according to + # the API spec. if 'deleted' not in search_opts: - if 'changes-since' not in search_opts: - # No 'changes-since', so we only want non-deleted servers + if 'changes-since' not in search_opts and \ + 'changes-before' not in search_opts: + # No 'changes-since' or 'changes-before', so we only + # want non-deleted servers search_opts['deleted'] = False else: # Convert deleted filter value to a valid boolean. @@ -1090,6 +1109,8 @@ class ServersController(wsgi.Controller): opt_list += ('ip6',) if api_version_request.is_supported(req, min_version='2.26'): opt_list += TAG_SEARCH_FILTERS + if api_version_request.is_supported(req, min_version='2.66'): + opt_list += ('changes-before',) return opt_list def _get_instance(self, context, instance_uuid): diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index d170555d8d3d..3f327ff7b9b0 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -2003,6 +2003,32 @@ def instance_get_all_by_filters(context, filters, sort_key, sort_dir, sort_dirs=[sort_dir]) +def _get_query_nova_resource_by_changes_time(query, filters, model_object): + """Filter resources by changes-since or changes-before. + + Special keys are used to tweek the query further:: + + | 'changes-since' - only return resources updated after + | 'changes-before' - only return resources updated before + + Return query results. + + :param query: query to apply filters to. + :param filters: dictionary of filters with regex values. + :param model_object: object of the operation target. + """ + for change_filter in ['changes-since', 'changes-before']: + if filters and filters.get(change_filter): + changes_filter_time = timeutils.normalize_time( + filters.get(change_filter)) + updated_at = getattr(model_object, 'updated_at') + if change_filter == 'changes-since': + query = query.filter(updated_at >= changes_filter_time) + else: + query = query.filter(updated_at <= changes_filter_time) + return query + + @require_context @pick_context_manager_reader_allow_async def instance_get_all_by_filters_sort(context, filters, limit=None, marker=None, @@ -2036,6 +2062,7 @@ def instance_get_all_by_filters_sort(context, filters, limit=None, marker=None, Special keys are used to tweek the query further:: | 'changes-since' - only return instances updated after + | 'changes-before' - only return instances updated before | 'deleted' - only return (or exclude) deleted instances | 'soft_deleted' - modify behavior of 'deleted' to either | include or exclude instances whose @@ -2097,10 +2124,10 @@ def instance_get_all_by_filters_sort(context, filters, limit=None, marker=None, # be modifying it and we shouldn't affect the caller's use of it. filters = copy.deepcopy(filters) - if 'changes-since' in filters: - changes_since = timeutils.normalize_time(filters['changes-since']) - query_prefix = query_prefix.\ - filter(models.Instance.updated_at >= changes_since) + model_object = models.Instance + query_prefix = _get_query_nova_resource_by_changes_time(query_prefix, + filters, + model_object) if 'deleted' in filters: # Instances can be soft or hard deleted and the query needs to @@ -4371,10 +4398,12 @@ def migration_get_all_by_filters(context, filters, uuid = filters["uuid"] uuid = [uuid] if isinstance(uuid, six.string_types) else uuid query = query.filter(models.Migration.uuid.in_(uuid)) - if 'changes-since' in filters: - changes_since = timeutils.normalize_time(filters['changes-since']) - query = query. \ - filter(models.Migration.updated_at >= changes_since) + + model_object = models.Migration + query = _get_query_nova_resource_by_changes_time(query, + filters, + model_object) + if "status" in filters: status = filters["status"] status = [status] if isinstance(status, six.string_types) else status @@ -5117,10 +5146,11 @@ def actions_get(context, instance_uuid, limit=None, marker=None, query_prefix = model_query(context, models.InstanceAction).\ filter_by(instance_uuid=instance_uuid) - if filters and 'changes-since' in filters: - changes_since = timeutils.normalize_time(filters['changes-since']) - query_prefix = query_prefix. \ - filter(models.InstanceAction.updated_at >= changes_since) + + model_object = models.InstanceAction + query_prefix = _get_query_nova_resource_by_changes_time(query_prefix, + filters, + model_object) if marker is not None: marker = action_get_by_request_id(context, instance_uuid, marker) diff --git a/nova/tests/functional/api_sample_tests/api_samples/os-instance-actions/v2.66/instance-action-get-non-admin-resp.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/os-instance-actions/v2.66/instance-action-get-non-admin-resp.json.tpl new file mode 100644 index 000000000000..7641428d17e6 --- /dev/null +++ b/nova/tests/functional/api_sample_tests/api_samples/os-instance-actions/v2.66/instance-action-get-non-admin-resp.json.tpl @@ -0,0 +1,21 @@ +{ + "instanceAction": { + "action": "stop", + "instance_uuid": "%(uuid)s", + "request_id": "%(request_id)s", + "user_id": "%(user_id)s", + "project_id": "%(project_id)s", + "start_time": "%(strtime)s", + "updated_at": "%(strtime)s", + "message": null, + "events": [ + { + "event": "compute_stop_instance", + "start_time": "%(strtime)s", + "finish_time": "%(strtime)s", + "result": "Success", + "hostId": "%(event_hostId)s" + } + ] + } +} diff --git a/nova/tests/functional/api_sample_tests/api_samples/os-instance-actions/v2.66/instance-action-get-resp.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/os-instance-actions/v2.66/instance-action-get-resp.json.tpl new file mode 100644 index 000000000000..fe3a4eec8fcd --- /dev/null +++ b/nova/tests/functional/api_sample_tests/api_samples/os-instance-actions/v2.66/instance-action-get-resp.json.tpl @@ -0,0 +1,23 @@ +{ + "instanceAction": { + "action": "stop", + "instance_uuid": "%(uuid)s", + "request_id": "%(request_id)s", + "user_id": "%(user_id)s", + "project_id": "%(project_id)s", + "start_time": "%(strtime)s", + "updated_at": "%(strtime)s", + "message": null, + "events": [ + { + "event": "compute_stop_instance", + "start_time": "%(strtime)s", + "finish_time": "%(strtime)s", + "result": "Success", + "traceback": null, + "host": "%(event_host)s", + "hostId": "%(event_hostId)s" + } + ] + } +} diff --git a/nova/tests/functional/api_sample_tests/api_samples/os-instance-actions/v2.66/instance-actions-list-resp.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/os-instance-actions/v2.66/instance-actions-list-resp.json.tpl new file mode 100644 index 000000000000..19161da37483 --- /dev/null +++ b/nova/tests/functional/api_sample_tests/api_samples/os-instance-actions/v2.66/instance-actions-list-resp.json.tpl @@ -0,0 +1,24 @@ +{ + "instanceActions": [ + { + "action": "stop", + "instance_uuid": "%(uuid)s", + "request_id": "%(request_id)s", + "user_id": "%(user_id)s", + "project_id": "%(project_id)s", + "start_time": "%(strtime)s", + "updated_at": "%(strtime)s", + "message": null + }, + { + "action": "create", + "instance_uuid": "%(uuid)s", + "request_id": "%(request_id)s", + "user_id": "%(user_id)s", + "project_id": "%(project_id)s", + "start_time": "%(strtime)s", + "updated_at": "%(strtime)s", + "message": null + } + ] +} diff --git a/nova/tests/functional/api_sample_tests/api_samples/os-instance-actions/v2.66/instance-actions-list-with-changes-before.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/os-instance-actions/v2.66/instance-actions-list-with-changes-before.json.tpl new file mode 100644 index 000000000000..19161da37483 --- /dev/null +++ b/nova/tests/functional/api_sample_tests/api_samples/os-instance-actions/v2.66/instance-actions-list-with-changes-before.json.tpl @@ -0,0 +1,24 @@ +{ + "instanceActions": [ + { + "action": "stop", + "instance_uuid": "%(uuid)s", + "request_id": "%(request_id)s", + "user_id": "%(user_id)s", + "project_id": "%(project_id)s", + "start_time": "%(strtime)s", + "updated_at": "%(strtime)s", + "message": null + }, + { + "action": "create", + "instance_uuid": "%(uuid)s", + "request_id": "%(request_id)s", + "user_id": "%(user_id)s", + "project_id": "%(project_id)s", + "start_time": "%(strtime)s", + "updated_at": "%(strtime)s", + "message": null + } + ] +} diff --git a/nova/tests/functional/api_sample_tests/api_samples/os-instance-actions/v2.66/instance-actions-list-with-changes-since.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/os-instance-actions/v2.66/instance-actions-list-with-changes-since.json.tpl new file mode 100644 index 000000000000..4b81af86b045 --- /dev/null +++ b/nova/tests/functional/api_sample_tests/api_samples/os-instance-actions/v2.66/instance-actions-list-with-changes-since.json.tpl @@ -0,0 +1,14 @@ +{ + "instanceActions": [ + { + "action": "stop", + "instance_uuid": "%(uuid)s", + "request_id": "%(request_id)s", + "user_id": "%(user_id)s", + "project_id": "%(project_id)s", + "start_time": "%(strtime)s", + "updated_at": "%(strtime)s", + "message": null + } + ] +} diff --git a/nova/tests/functional/api_sample_tests/api_samples/os-instance-actions/v2.66/instance-actions-list-with-limit-resp.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/os-instance-actions/v2.66/instance-actions-list-with-limit-resp.json.tpl new file mode 100644 index 000000000000..dedbd8d8addc --- /dev/null +++ b/nova/tests/functional/api_sample_tests/api_samples/os-instance-actions/v2.66/instance-actions-list-with-limit-resp.json.tpl @@ -0,0 +1,20 @@ +{ + "instanceActions": [ + { + "action": "stop", + "instance_uuid": "%(uuid)s", + "request_id": "%(request_id)s", + "user_id": "%(user_id)s", + "project_id": "%(project_id)s", + "start_time": "%(strtime)s", + "updated_at": "%(strtime)s", + "message": null + } + ], + "links": [ + { + "href": "%(versioned_compute_endpoint)s/servers/%(uuid)s/os-instance-actions?limit=1&marker=%(request_id)s", + "rel": "next" + } + ] +} diff --git a/nova/tests/functional/api_sample_tests/api_samples/os-instance-actions/v2.66/instance-actions-list-with-marker-resp.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/os-instance-actions/v2.66/instance-actions-list-with-marker-resp.json.tpl new file mode 100644 index 000000000000..3e1f1efa8bb0 --- /dev/null +++ b/nova/tests/functional/api_sample_tests/api_samples/os-instance-actions/v2.66/instance-actions-list-with-marker-resp.json.tpl @@ -0,0 +1,14 @@ +{ + "instanceActions": [ + { + "action": "create", + "instance_uuid": "%(uuid)s", + "request_id": "%(request_id)s", + "user_id": "%(user_id)s", + "project_id": "%(project_id)s", + "start_time": "%(strtime)s", + "updated_at": "%(strtime)s", + "message": null + } + ] +} diff --git a/nova/tests/functional/api_sample_tests/api_samples/os-migrations/v2.66/migrations-get-with-changes-before.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/os-migrations/v2.66/migrations-get-with-changes-before.json.tpl new file mode 100644 index 000000000000..ff0ecd91d5a0 --- /dev/null +++ b/nova/tests/functional/api_sample_tests/api_samples/os-migrations/v2.66/migrations-get-with-changes-before.json.tpl @@ -0,0 +1,30 @@ +{ + "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" + } + ] +} diff --git a/nova/tests/functional/api_sample_tests/api_samples/os-migrations/v2.66/migrations-get-with-changes-since.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/os-migrations/v2.66/migrations-get-with-changes-since.json.tpl new file mode 100644 index 000000000000..f2e7ba5b263f --- /dev/null +++ b/nova/tests/functional/api_sample_tests/api_samples/os-migrations/v2.66/migrations-get-with-changes-since.json.tpl @@ -0,0 +1,36 @@ +{ + "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" + }, + { + "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" + } + ] +} diff --git a/nova/tests/functional/api_sample_tests/api_samples/os-migrations/v2.66/migrations-get-with-limit.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/os-migrations/v2.66/migrations-get-with-limit.json.tpl new file mode 100644 index 000000000000..e98614278f15 --- /dev/null +++ b/nova/tests/functional/api_sample_tests/api_samples/os-migrations/v2.66/migrations-get-with-limit.json.tpl @@ -0,0 +1,24 @@ +{ + "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" + } + ], + "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.66/migrations-get-with-marker.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/os-migrations/v2.66/migrations-get-with-marker.json.tpl new file mode 100644 index 000000000000..ff0ecd91d5a0 --- /dev/null +++ b/nova/tests/functional/api_sample_tests/api_samples/os-migrations/v2.66/migrations-get-with-marker.json.tpl @@ -0,0 +1,30 @@ +{ + "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" + } + ] +} diff --git a/nova/tests/functional/api_sample_tests/api_samples/os-migrations/v2.66/migrations-get.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/os-migrations/v2.66/migrations-get.json.tpl new file mode 100644 index 000000000000..78033a615577 --- /dev/null +++ b/nova/tests/functional/api_sample_tests/api_samples/os-migrations/v2.66/migrations-get.json.tpl @@ -0,0 +1,78 @@ +{ + "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" + }, + { + "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" + }, + { + "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" + }, + { + "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" + } + ] +} diff --git a/nova/tests/functional/api_sample_tests/api_samples/servers/v2.66/server-create-req.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/servers/v2.66/server-create-req.json.tpl new file mode 100644 index 000000000000..7e2addb0fb5a --- /dev/null +++ b/nova/tests/functional/api_sample_tests/api_samples/servers/v2.66/server-create-req.json.tpl @@ -0,0 +1,28 @@ +{ + "server" : { + "accessIPv4": "%(access_ip_v4)s", + "accessIPv6": "%(access_ip_v6)s", + "name" : "%(name)s", + "imageRef" : "%(image_id)s", + "flavorRef" : "6", + "availability_zone": "nova", + "OS-DCF:diskConfig": "AUTO", + "metadata" : { + "My Server Name" : "Apache1" + }, + "security_groups": [ + { + "name": "default" + } + ], + "user_data" : "%(user_data)s", + "networks": "auto", + "trusted_image_certificates": [ + "0b5d2c72-12cc-4ba6-a8d7-3ff5cc1d8cb8", + "674736e3-f25c-405c-8362-bbf991e0ce0a" + ] + }, + "OS-SCH-HNT:scheduler_hints": { + "same_host": "%(uuid)s" + } +} diff --git a/nova/tests/functional/api_sample_tests/api_samples/servers/v2.66/server-create-resp.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/servers/v2.66/server-create-resp.json.tpl new file mode 100644 index 000000000000..4b30e0cfbdb8 --- /dev/null +++ b/nova/tests/functional/api_sample_tests/api_samples/servers/v2.66/server-create-resp.json.tpl @@ -0,0 +1,22 @@ +{ + "server": { + "OS-DCF:diskConfig": "AUTO", + "adminPass": "%(password)s", + "id": "%(id)s", + "links": [ + { + "href": "%(versioned_compute_endpoint)s/servers/%(uuid)s", + "rel": "self" + }, + { + "href": "%(compute_endpoint)s/servers/%(uuid)s", + "rel": "bookmark" + } + ], + "security_groups": [ + { + "name": "default" + } + ] + } +} diff --git a/nova/tests/functional/api_sample_tests/api_samples/servers/v2.66/server-get-resp.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/servers/v2.66/server-get-resp.json.tpl new file mode 100644 index 000000000000..360365fee4e5 --- /dev/null +++ b/nova/tests/functional/api_sample_tests/api_samples/servers/v2.66/server-get-resp.json.tpl @@ -0,0 +1,184 @@ +{ + "server": [ + { + "accessIPv4": "%(access_ip_v4)s", + "accessIPv6": "%(access_ip_v6)s", + "addresses": { + "private": [ + { + "addr": "%(ip)s", + "OS-EXT-IPS-MAC:mac_addr": "aa:bb:cc:dd:ee:ff", + "OS-EXT-IPS:type": "fixed", + "version": 4 + } + ] + }, + "created": "%(isotime)s", + "description": null, + "host_status": "UP", + "locked": false, + "tags": [], + "flavor": { + "disk": 1, + "ephemeral": 0, + "extra_specs": { + "hw:cpu_policy": "dedicated", + "hw:mem_page_size": "2048" + }, + "original_name": "m1.tiny.specs", + "ram": 512, + "swap": 0, + "vcpus": 1 + }, + "hostId": "%(hostid)s", + "id": "%(id)s", + "image": { + "id": "%(uuid)s", + "links": [ + { + "href": "%(compute_endpoint)s/images/%(uuid)s", + "rel": "bookmark" + } + ] + }, + "key_name": null, + "links": [ + { + "href": "%(versioned_compute_endpoint)s/servers/%(uuid)s", + "rel": "self" + }, + { + "href": "%(compute_endpoint)s/servers/%(uuid)s", + "rel": "bookmark" + } + ], + "metadata": { + "My Server Name": "Apache1" + }, + "name": "new-server-test", + "config_drive": "%(cdrive)s", + "OS-DCF:diskConfig": "AUTO", + "OS-EXT-AZ:availability_zone": "nova", + "OS-EXT-SRV-ATTR:host": "%(compute_host)s", + "OS-EXT-SRV-ATTR:hostname": "%(hostname)s", + "OS-EXT-SRV-ATTR:hypervisor_hostname": "%(hypervisor_hostname)s", + "OS-EXT-SRV-ATTR:instance_name": "%(instance_name)s", + "OS-EXT-SRV-ATTR:kernel_id": "", + "OS-EXT-SRV-ATTR:launch_index": 0, + "OS-EXT-SRV-ATTR:ramdisk_id": "", + "OS-EXT-SRV-ATTR:reservation_id": "%(reservation_id)s", + "OS-EXT-SRV-ATTR:root_device_name": "/dev/sda", + "OS-EXT-SRV-ATTR:user_data": "%(user_data)s", + "OS-EXT-STS:power_state": 1, + "OS-EXT-STS:task_state": null, + "OS-EXT-STS:vm_state": "active", + "os-extended-volumes:volumes_attached": [], + "OS-SRV-USG:launched_at": "%(strtime)s", + "OS-SRV-USG:terminated_at": null, + "progress": 0, + "security_groups": [ + { + "name": "default" + } + ], + "status": "ACTIVE", + "tenant_id": "6f70656e737461636b20342065766572", + "updated": "%(isotime)s", + "user_id": "fake", + "trusted_image_certificates": [ + "0b5d2c72-12cc-4ba6-a8d7-3ff5cc1d8cb8", + "674736e3-f25c-405c-8362-bbf991e0ce0a" + ] + }, + { + "accessIPv4": "%(access_ip_v4)s", + "accessIPv6": "%(access_ip_v6)s", + "addresses": { + "private": [ + { + "addr": "%(ip)s", + "OS-EXT-IPS-MAC:mac_addr": "aa:bb:cc:dd:ee:ff", + "OS-EXT-IPS:type": "fixed", + "version": 4 + } + ] + }, + "created": "%(isotime)s", + "description": null, + "host_status": "UP", + "locked": false, + "tags": [], + "flavor": { + "disk": 1, + "ephemeral": 0, + "extra_specs": { + "hw:cpu_policy": "dedicated", + "hw:mem_page_size": "2048" + }, + "original_name": "m1.tiny.specs", + "ram": 512, + "swap": 0, + "vcpus": 1 + }, + "hostId": "%(hostid)s", + "id": "%(id)s", + "image": { + "id": "%(uuid)s", + "links": [ + { + "href": "%(compute_endpoint)s/images/%(uuid)s", + "rel": "bookmark" + } + ] + }, + "key_name": null, + "links": [ + { + "href": "%(versioned_compute_endpoint)s/servers/%(uuid)s", + "rel": "self" + }, + { + "href": "%(compute_endpoint)s/servers/%(uuid)s", + "rel": "bookmark" + } + ], + "metadata": { + "My Server Name": "Apache1" + }, + "name": "new-server-test", + "config_drive": "%(cdrive)s", + "OS-DCF:diskConfig": "AUTO", + "OS-EXT-AZ:availability_zone": "nova", + "OS-EXT-SRV-ATTR:host": "%(compute_host)s", + "OS-EXT-SRV-ATTR:hostname": "%(hostname)s", + "OS-EXT-SRV-ATTR:hypervisor_hostname": "%(hypervisor_hostname)s", + "OS-EXT-SRV-ATTR:instance_name": "%(instance_name)s", + "OS-EXT-SRV-ATTR:kernel_id": "", + "OS-EXT-SRV-ATTR:launch_index": 0, + "OS-EXT-SRV-ATTR:ramdisk_id": "", + "OS-EXT-SRV-ATTR:reservation_id": "%(reservation_id)s", + "OS-EXT-SRV-ATTR:root_device_name": "/dev/sda", + "OS-EXT-SRV-ATTR:user_data": "%(user_data)s", + "OS-EXT-STS:power_state": 1, + "OS-EXT-STS:task_state": null, + "OS-EXT-STS:vm_state": "active", + "os-extended-volumes:volumes_attached": [], + "OS-SRV-USG:launched_at": "%(strtime)s", + "OS-SRV-USG:terminated_at": null, + "progress": 0, + "security_groups": [ + { + "name": "default" + } + ], + "status": "ACTIVE", + "tenant_id": "6f70656e737461636b20342065766572", + "updated": "%(isotime)s", + "user_id": "fake", + "trusted_image_certificates": [ + "0b5d2c72-12cc-4ba6-a8d7-3ff5cc1d8cb8", + "674736e3-f25c-405c-8362-bbf991e0ce0a" + ] + } + ] +} diff --git a/nova/tests/functional/api_sample_tests/api_samples/servers/v2.66/servers-details-resp.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/servers/v2.66/servers-details-resp.json.tpl new file mode 100644 index 000000000000..bf4aa02a56c6 --- /dev/null +++ b/nova/tests/functional/api_sample_tests/api_samples/servers/v2.66/servers-details-resp.json.tpl @@ -0,0 +1,190 @@ +{ + "servers": [ + { + "accessIPv4": "%(access_ip_v4)s", + "accessIPv6": "%(access_ip_v6)s", + "addresses": { + "private": [ + { + "addr": "%(ip)s", + "OS-EXT-IPS-MAC:mac_addr": "aa:bb:cc:dd:ee:ff", + "OS-EXT-IPS:type": "fixed", + "version": 4 + } + ] + }, + "created": "%(isotime)s", + "description": null, + "host_status": "UP", + "locked": false, + "tags": [], + "flavor": { + "disk": 1, + "ephemeral": 0, + "extra_specs": { + "hw:mem_page_size": "2048", + "hw:cpu_policy": "dedicated" + }, + "original_name": "m1.tiny.specs", + "ram": 512, + "swap": 0, + "vcpus": 1 + }, + "hostId": "%(hostid)s", + "id": "%(id)s", + "image": { + "id": "%(uuid)s", + "links": [ + { + "href": "%(compute_endpoint)s/images/%(uuid)s", + "rel": "bookmark" + } + ] + }, + "key_name": null, + "links": [ + { + "href": "%(versioned_compute_endpoint)s/servers/%(uuid)s", + "rel": "self" + }, + { + "href": "%(compute_endpoint)s/servers/%(id)s", + "rel": "bookmark" + } + ], + "metadata": { + "My Server Name": "Apache1" + }, + "name": "new-server-test", + "config_drive": "%(cdrive)s", + "OS-DCF:diskConfig": "AUTO", + "OS-EXT-AZ:availability_zone": "nova", + "OS-EXT-SRV-ATTR:host": "%(compute_host)s", + "OS-EXT-SRV-ATTR:hostname": "%(hostname)s", + "OS-EXT-SRV-ATTR:hypervisor_hostname": "%(hypervisor_hostname)s", + "OS-EXT-SRV-ATTR:instance_name": "%(instance_name)s", + "OS-EXT-SRV-ATTR:kernel_id": "", + "OS-EXT-SRV-ATTR:launch_index": 0, + "OS-EXT-SRV-ATTR:ramdisk_id": "", + "OS-EXT-SRV-ATTR:reservation_id": "%(reservation_id)s", + "OS-EXT-SRV-ATTR:root_device_name": "/dev/sda", + "OS-EXT-SRV-ATTR:user_data": "%(user_data)s", + "OS-EXT-STS:power_state": 1, + "OS-EXT-STS:task_state": null, + "OS-EXT-STS:vm_state": "active", + "os-extended-volumes:volumes_attached": [], + "OS-SRV-USG:launched_at": "%(strtime)s", + "OS-SRV-USG:terminated_at": null, + "progress": 0, + "security_groups": [ + { + "name": "default" + } + ], + "status": "ACTIVE", + "tenant_id": "6f70656e737461636b20342065766572", + "trusted_image_certificates": [ + "0b5d2c72-12cc-4ba6-a8d7-3ff5cc1d8cb8", + "674736e3-f25c-405c-8362-bbf991e0ce0a" + ], + "updated": "%(isotime)s", + "user_id": "fake" + }, + { + "accessIPv4": "%(access_ip_v4)s", + "accessIPv6": "%(access_ip_v6)s", + "addresses": { + "private": [ + { + "addr": "%(ip)s", + "OS-EXT-IPS-MAC:mac_addr": "aa:bb:cc:dd:ee:ff", + "OS-EXT-IPS:type": "fixed", + "version": 4 + } + ] + }, + "created": "%(isotime)s", + "description": null, + "host_status": "UP", + "locked": false, + "tags": [], + "flavor": { + "disk": 1, + "ephemeral": 0, + "extra_specs": { + "hw:mem_page_size": "2048", + "hw:cpu_policy": "dedicated" + }, + "original_name": "m1.tiny.specs", + "ram": 512, + "swap": 0, + "vcpus": 1 + }, + "hostId": "%(hostid)s", + "id": "%(id)s", + "image": { + "id": "%(uuid)s", + "links": [ + { + "href": "%(compute_endpoint)s/images/%(uuid)s", + "rel": "bookmark" + } + ] + }, + "key_name": null, + "links": [ + { + "href": "%(versioned_compute_endpoint)s/servers/%(uuid)s", + "rel": "self" + }, + { + "href": "%(compute_endpoint)s/servers/%(id)s", + "rel": "bookmark" + } + ], + "metadata": { + "My Server Name": "Apache1" + }, + "name": "new-server-test", + "config_drive": "%(cdrive)s", + "OS-DCF:diskConfig": "AUTO", + "OS-EXT-AZ:availability_zone": "nova", + "OS-EXT-SRV-ATTR:host": "%(compute_host)s", + "OS-EXT-SRV-ATTR:hostname": "%(hostname)s", + "OS-EXT-SRV-ATTR:hypervisor_hostname": "%(hypervisor_hostname)s", + "OS-EXT-SRV-ATTR:instance_name": "%(instance_name)s", + "OS-EXT-SRV-ATTR:kernel_id": "", + "OS-EXT-SRV-ATTR:launch_index": 0, + "OS-EXT-SRV-ATTR:ramdisk_id": "", + "OS-EXT-SRV-ATTR:reservation_id": "%(reservation_id)s", + "OS-EXT-SRV-ATTR:root_device_name": "/dev/sda", + "OS-EXT-SRV-ATTR:user_data": "%(user_data)s", + "OS-EXT-STS:power_state": 1, + "OS-EXT-STS:task_state": null, + "OS-EXT-STS:vm_state": "active", + "os-extended-volumes:volumes_attached": [], + "OS-SRV-USG:launched_at": "%(strtime)s", + "OS-SRV-USG:terminated_at": null, + "progress": 0, + "security_groups": [ + { + "name": "default" + } + ], + "status": "ACTIVE", + "tenant_id": "6f70656e737461636b20342065766572", + "trusted_image_certificates": [ + "0b5d2c72-12cc-4ba6-a8d7-3ff5cc1d8cb8", + "674736e3-f25c-405c-8362-bbf991e0ce0a" + ], + "updated": "%(isotime)s", + "user_id": "fake" + } + ], + "servers_links": [ + { + "href": "%(versioned_compute_endpoint)s/servers/detail?limit=1&marker=%(id)s", + "rel": "next" + } + ] +} diff --git a/nova/tests/functional/api_sample_tests/api_samples/servers/v2.66/servers-details-with-changes-before.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/servers/v2.66/servers-details-with-changes-before.json.tpl new file mode 100644 index 000000000000..a64e4c48b15d --- /dev/null +++ b/nova/tests/functional/api_sample_tests/api_samples/servers/v2.66/servers-details-with-changes-before.json.tpl @@ -0,0 +1,94 @@ +{ + "servers": [ + { + "accessIPv4": "%(access_ip_v4)s", + "accessIPv6": "%(access_ip_v6)s", + "addresses": { + "private": [ + { + "addr": "%(ip)s", + "OS-EXT-IPS-MAC:mac_addr": "aa:bb:cc:dd:ee:ff", + "OS-EXT-IPS:type": "fixed", + "version": 4 + } + ] + }, + "created": "%(isotime)s", + "description": null, + "host_status": "UP", + "locked": false, + "tags": [], + "flavor": { + "disk": 1, + "ephemeral": 0, + "extra_specs": { + "hw:mem_page_size": "2048", + "hw:cpu_policy": "dedicated" + }, + "original_name": "m1.tiny.specs", + "ram": 512, + "swap": 0, + "vcpus": 1 + }, + "hostId": "%(hostid)s", + "id": "%(id)s", + "image": { + "id": "%(uuid)s", + "links": [ + { + "href": "%(compute_endpoint)s/images/%(uuid)s", + "rel": "bookmark" + } + ] + }, + "key_name": null, + "links": [ + { + "href": "%(versioned_compute_endpoint)s/servers/%(uuid)s", + "rel": "self" + }, + { + "href": "%(compute_endpoint)s/servers/%(id)s", + "rel": "bookmark" + } + ], + "metadata": { + "My Server Name": "Apache1" + }, + "name": "new-server-test", + "config_drive": "%(cdrive)s", + "OS-DCF:diskConfig": "AUTO", + "OS-EXT-AZ:availability_zone": "nova", + "OS-EXT-SRV-ATTR:host": "%(compute_host)s", + "OS-EXT-SRV-ATTR:hostname": "%(hostname)s", + "OS-EXT-SRV-ATTR:hypervisor_hostname": "%(hypervisor_hostname)s", + "OS-EXT-SRV-ATTR:instance_name": "%(instance_name)s", + "OS-EXT-SRV-ATTR:kernel_id": "", + "OS-EXT-SRV-ATTR:launch_index": 0, + "OS-EXT-SRV-ATTR:ramdisk_id": "", + "OS-EXT-SRV-ATTR:reservation_id": "%(reservation_id)s", + "OS-EXT-SRV-ATTR:root_device_name": "/dev/sda", + "OS-EXT-SRV-ATTR:user_data": "%(user_data)s", + "OS-EXT-STS:power_state": 1, + "OS-EXT-STS:task_state": null, + "OS-EXT-STS:vm_state": "active", + "os-extended-volumes:volumes_attached": [], + "OS-SRV-USG:launched_at": "%(strtime)s", + "OS-SRV-USG:terminated_at": null, + "progress": 0, + "security_groups": [ + { + "name": "default" + } + ], + "status": "ACTIVE", + "tenant_id": "6f70656e737461636b20342065766572", + "trusted_image_certificates": [ + "0b5d2c72-12cc-4ba6-a8d7-3ff5cc1d8cb8", + "674736e3-f25c-405c-8362-bbf991e0ce0a" + ], + "updated": "%(isotime)s", + "user_id": "fake" + } + ] +} diff --git a/nova/tests/functional/api_sample_tests/api_samples/servers/v2.66/servers-list-with-changes-before.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/servers/v2.66/servers-list-with-changes-before.json.tpl new file mode 100644 index 000000000000..f78d963d5d02 --- /dev/null +++ b/nova/tests/functional/api_sample_tests/api_samples/servers/v2.66/servers-list-with-changes-before.json.tpl @@ -0,0 +1,18 @@ +{ + "servers": [ + { + "id": "%(id)s", + "links": [ + { + "href": "%(versioned_compute_endpoint)s/servers/%(id)s", + "rel": "self" + }, + { + "href": "%(compute_endpoint)s/servers/%(id)s", + "rel": "bookmark" + } + ], + "name": "new-server-test" + } + ] +} diff --git a/nova/tests/functional/api_sample_tests/test_instance_actions.py b/nova/tests/functional/api_sample_tests/test_instance_actions.py index 596a45288ead..796ca1ce5026 100644 --- a/nova/tests/functional/api_sample_tests/test_instance_actions.py +++ b/nova/tests/functional/api_sample_tests/test_instance_actions.py @@ -139,3 +139,17 @@ class ServerActionsV262SampleJsonTest(ServerActionsV258SampleJsonTest): class ServerActionsV262NonAdminSampleJsonTest(ServerActionsV262SampleJsonTest): ADMIN_API = False + + +class ServerActionsV266SampleJsonTest(ServerActionsV262SampleJsonTest): + microversion = '2.66' + scenarios = [('v2_66', {'api_major_version': 'v2.1'})] + + def test_instance_actions_with_changes_before(self): + stop_action_time = self.action_stop['updated_at'] + response = self._do_get( + 'servers/%s/os-instance-actions' + '?changes-before=%s' % (self.uuid, stop_action_time)) + self._verify_response( + 'instance-actions-list-with-changes-before', + self._get_subs(), response, 200) diff --git a/nova/tests/functional/api_sample_tests/test_migrations.py b/nova/tests/functional/api_sample_tests/test_migrations.py index d860ffa37cc4..fc9ac1224ed0 100644 --- a/nova/tests/functional/api_sample_tests/test_migrations.py +++ b/nova/tests/functional/api_sample_tests/test_migrations.py @@ -292,3 +292,16 @@ class MigrationsSamplesJsonTestV2_59(MigrationsSamplesJsonTestV2_23): self._verify_response( 'migrations-get-with-changes-since', {"instance_2": INSTANCE_UUID_2}, response, 200) + + +class MigrationsSamplesJsonTestV2_66(MigrationsSamplesJsonTestV2_59): + microversion = '2.66' + scenarios = [('v2_66', {'api_major_version': 'v2.1'})] + + def test_get_migrations_with_changes_before(self): + response = self._do_get( + 'os-migrations?changes-before=2016-01-29T11:42:02.000000') + self.assertEqual(200, response.status_code) + self._verify_response( + 'migrations-get-with-changes-before', + {"instance_1": INSTANCE_UUID_1}, response, 200) diff --git a/nova/tests/functional/api_sample_tests/test_servers.py b/nova/tests/functional/api_sample_tests/test_servers.py index f1c42b8fabbb..f901b6929016 100644 --- a/nova/tests/functional/api_sample_tests/test_servers.py +++ b/nova/tests/functional/api_sample_tests/test_servers.py @@ -16,6 +16,7 @@ import base64 import time +from oslo_utils import timeutils import six from nova.api.openstack import api_version_request as avr @@ -311,6 +312,47 @@ class ServersSampleJson263Test(ServersSampleBase): self._verify_response('server-update-resp', subs, response, 200) +class ServersSampleJson266Test(ServersSampleBase): + microversion = '2.66' + scenarios = [('v2_66', {'api_major_version': 'v2.1'})] + + def setUp(self): + super(ServersSampleJson266Test, self).setUp() + self.common_subs = { + 'hostid': '[a-f0-9]+', + 'instance_name': 'instance-\d{8}', + 'hypervisor_hostname': r'[\w\.\-]+', + 'hostname': r'[\w\.\-]+', + 'access_ip_v4': '1.2.3.4', + 'access_ip_v6': '80fe::', + 'user_data': (self.user_data if six.PY2 + else self.user_data.decode('utf-8')), + 'cdrive': '.*', + } + + def test_get_servers_list_with_changes_before(self): + uuid = self._post_server(use_common_server_api_samples=False) + current_time = timeutils.parse_isotime(timeutils.utcnow().isoformat()) + response = self._do_get( + 'servers?changes-before=%s' % timeutils.normalize_time( + current_time)) + subs = self.common_subs.copy() + subs['id'] = uuid + self._verify_response( + 'servers-list-with-changes-before', subs, response, 200) + + def test_get_servers_detail_with_changes_before(self): + uuid = self._post_server(use_common_server_api_samples=False) + current_time = timeutils.parse_isotime(timeutils.utcnow().isoformat()) + response = self._do_get( + 'servers/detail?changes-before=%s' % timeutils.normalize_time( + current_time)) + subs = self.common_subs.copy() + subs['id'] = uuid + self._verify_response( + 'servers-details-with-changes-before', subs, response, 200) + + class ServersUpdateSampleJsonTest(ServersSampleBase): def test_update_server(self): diff --git a/nova/tests/unit/api/openstack/compute/test_instance_actions.py b/nova/tests/unit/api/openstack/compute/test_instance_actions.py index 3c0f1e67d3a9..9865b9d03391 100644 --- a/nova/tests/unit/api/openstack/compute/test_instance_actions.py +++ b/nova/tests/unit/api/openstack/compute/test_instance_actions.py @@ -145,6 +145,13 @@ class InstanceActionsTestV21(test.NoDBTestCase): use_admin_context=use_admin_context, version=self.wsgi_api_version) + def _get_http_req_with_version(self, action, use_admin_context=False, + version="2.21"): + fake_url = '/123/servers/12/%s' % action + return fakes.HTTPRequest.blank(fake_url, + use_admin_context=use_admin_context, + version=version) + def _set_policy_rules(self): rules = {'compute:get': '', 'os_compute_api:os-instance-actions': '', @@ -319,3 +326,29 @@ class InstanceActionsTestV262(InstanceActionsTestV251): wsgi_api_version = "2.62" expect_event_hostId = True expect_event_host = True + + +class InstanceActionsTestV266(InstanceActionsTestV258): + wsgi_api_version = "2.66" + + def test_get_action_with_invalid_changes_before(self): + """Tests get paging with a invalid changes-before.""" + req = self._get_http_req('os-instance-actions?' + 'changes-before=wrong_time') + ex = self.assertRaises(exception.ValidationError, + self.controller.index, req) + self.assertIn('Invalid input for query parameters changes-before', + six.text_type(ex)) + + def test_get_action_with_changes_before_old_microversion(self): + """Tests that the changes-before query parameter is an error before + microversion 2.66. + """ + param = 'changes-before=2018-09-13T15:13:03Z' + req = self._get_http_req_with_version('os-instance-actions?%s' % + param, use_admin_context=True, + version="2.65") + ex = self.assertRaises(exception.ValidationError, + self.controller.index, req) + detail = 'Additional properties are not allowed' + self.assertIn(detail, six.text_type(ex)) diff --git a/nova/tests/unit/api/openstack/compute/test_migrations.py b/nova/tests/unit/api/openstack/compute/test_migrations.py index 387d7f9217f7..188ebed347f0 100644 --- a/nova/tests/unit/api/openstack/compute/test_migrations.py +++ b/nova/tests/unit/api/openstack/compute/test_migrations.py @@ -336,7 +336,7 @@ class MigrationsTestCaseV259(MigrationsTestCaseV223): @mock.patch('nova.compute.api.API.get_migrations', return_value=objects.MigrationList()) def test_index_with_changes_since_old_microversion(self, get_migrations): - """Tests that the changes-since query parameteris ignored before + """Tests that the changes-since query parameter is ignored before microversion 2.59. """ # Also use a valid filter (instance_uuid) to make sure only @@ -352,6 +352,51 @@ class MigrationsTestCaseV259(MigrationsTestCaseV223): {'instance_uuid': uuids.instance_uuid}) +class MigrationTestCaseV266(MigrationsTestCaseV259): + wsgi_api_version = '2.66' + + def test_index_with_invalid_changes_before(self): + """Tests detail paging with an invalid changes-before value.""" + req = fakes.HTTPRequest.blank( + '/os-migrations?changes-before=wrong_time', + version=self.wsgi_api_version, use_admin_context=True) + self.assertRaises(exception.ValidationError, + self.controller.index, req) + + def test_index_with_changes_before_old_microversion_failed(self): + """Tests that the changes-before query parameter is an error before + microversion 2.66. + """ + # Also use a valid filter (instance_uuid) to make sure + # changes-before is an additional property. + req = fakes.HTTPRequest.blank( + '/os-migrations?changes-before=2018-01-10T16:59:24.138939&' + 'instance_uuid=%s' % uuids.instance_uuid, + version='2.65', use_admin_context=True) + ex = self.assertRaises(exception.ValidationError, + self.controller.index, req) + self.assertIn('Additional properties are not allowed', + six.text_type(ex)) + + @mock.patch('nova.compute.api.API.get_migrations', + return_value=objects.MigrationList()) + def test_index_with_changes_before_old_microversion(self, get_migrations): + """Tests that the changes-before query parameter is ignored before + microversion 2.59. + """ + # Also use a valid filter (instance_uuid) to make sure only + # changes-before is removed. + req = fakes.HTTPRequest.blank( + '/os-migrations?changes-before=2018-01-10T16:59:24.138939&' + 'instance_uuid=%s' % uuids.instance_uuid, + version='2.58', use_admin_context=True) + result = self.controller.index(req) + self.assertEqual({'migrations': []}, result) + get_migrations.assert_called_once_with( + req.environ['nova.context'], + {'instance_uuid': uuids.instance_uuid}) + + class MigrationsPolicyEnforcement(test.NoDBTestCase): def setUp(self): super(MigrationsPolicyEnforcement, self).setUp() diff --git a/nova/tests/unit/api/openstack/compute/test_serversV21.py b/nova/tests/unit/api/openstack/compute/test_serversV21.py index d8e0723a3cce..6664832d9bde 100644 --- a/nova/tests/unit/api/openstack/compute/test_serversV21.py +++ b/nova/tests/unit/api/openstack/compute/test_serversV21.py @@ -2054,6 +2054,97 @@ class ServerControllerTestV247(ControllerTest): self.assertEqual(s['flavor'], expected_flavor) +class ServerControllerTestV266(ControllerTest): + """Server controller test for microversion 2.66 + + Add changes-before parameter to get servers or servers details of + 2.66 microversion. + + Filters the response by a date and time stamp when the server last + changed. Those changed before the specified date and time stamp are + returned. + """ + wsgi_api_version = '2.66' + + def req(self, url, use_admin_context=False): + return fakes.HTTPRequest.blank(url, + use_admin_context=use_admin_context, + version=self.wsgi_api_version) + + def test_get_servers_allows_changes_before(self): + def fake_get_all(context, search_opts=None, + limit=None, marker=None, + expected_attrs=None, sort_keys=None, sort_dirs=None): + self.assertIsNotNone(search_opts) + self.assertIn('changes-before', search_opts) + changes_before = datetime.datetime(2011, 1, 24, 17, 8, 1, + tzinfo=iso8601.iso8601.UTC) + self.assertEqual(search_opts['changes-before'], changes_before) + self.assertNotIn('deleted', search_opts) + return objects.InstanceList( + objects=[fakes.stub_instance_obj(100, uuid=uuids.fake)]) + + self.mock_get_all.side_effect = fake_get_all + + params = 'changes-before=2011-01-24T17:08:01Z' + req = self.req('/fake/servers?%s' % params) + req.api_version_request = api_version_request.APIVersionRequest('2.66') + servers = self.controller.index(req)['servers'] + + self.assertEqual(1, len(servers)) + self.assertEqual(uuids.fake, servers[0]['id']) + + def test_get_servers_allows_changes_before_bad_value(self): + params = 'changes-before=asdf' + req = self.req('/fake/servers?%s' % params) + req.api_version_request = api_version_request.APIVersionRequest('2.66') + self.assertRaises(exception.ValidationError, self.controller.index, + req) + + def test_get_servers_allows_changes_before_bad_value_on_compat_mode(self): + params = 'changes-before=asdf' + req = self.req('/fake/servers?%s' % params) + req.api_version_request = api_version_request.APIVersionRequest('2.66') + req.set_legacy_v2() + self.assertRaises(webob.exc.HTTPBadRequest, self.controller.index, req) + + def test_get_servers_allows_changes_since_and_changes_before(self): + def fake_get_all(context, search_opts=None, + limit=None, marker=None, + expected_attrs=None, sort_keys=None, sort_dirs=None): + self.assertIsNotNone(search_opts) + self.assertIn('changes-since', search_opts) + changes_since = datetime.datetime(2011, 1, 23, 17, 8, 1, + tzinfo=iso8601.iso8601.UTC) + self.assertIn('changes-before', search_opts) + changes_before = datetime.datetime(2011, 1, 24, 17, 8, 1, + tzinfo=iso8601.iso8601.UTC) + self.assertEqual(search_opts['changes-since'], changes_since) + self.assertEqual(search_opts['changes-before'], changes_before) + self.assertNotIn('deleted', search_opts) + return objects.InstanceList( + objects=[fakes.stub_instance_obj(100, uuid=uuids.fake)]) + + self.mock_get_all.side_effect = fake_get_all + + params = 'changes-since=2011-01-23T17:08:01Z&' \ + 'changes-before=2011-01-24T17:08:01Z' + req = self.req('/fake/servers?%s' % params) + req.api_version_request = api_version_request.APIVersionRequest('2.66') + servers = self.controller.index(req)['servers'] + + self.assertEqual(1, len(servers)) + self.assertEqual(uuids.fake, servers[0]['id']) + + def test_get_servers_filters_with_distinct_changes_time_bad_request(self): + changes_since = '2018-09-04T05:45:27Z' + changes_before = '2018-09-03T05:45:27Z' + req = self.req('/fake/servers?changes-since=%s&changes-before=%s' % + (changes_since, changes_before)) + req.api_version_request = api_version_request.APIVersionRequest('2.66') + self.assertRaises(webob.exc.HTTPBadRequest, self.controller.index, req) + + class ServersControllerDeleteTest(ControllerTest): def setUp(self): diff --git a/nova/tests/unit/db/test_db_api.py b/nova/tests/unit/db/test_db_api.py index fc9a4972b4fe..1db653c460b9 100644 --- a/nova/tests/unit/db/test_db_api.py +++ b/nova/tests/unit/db/test_db_api.py @@ -1375,6 +1375,19 @@ class MigrationTestCase(test.TestCase): self.assertEqual(migrations[0]['uuid'], uuidsentinel.uuid_time2) self.assertEqual(migrations[1]['uuid'], uuidsentinel.uuid_time3) + def test_get_migrations_by_filters_with_changes_before(self): + changes_time = timeutils.utcnow(with_timezone=True) + self._create_3_migration_after_time(changes_time) + after_3day_2hours = datetime.timedelta(days=3, hours=2) + filters = {"changes-before": changes_time + after_3day_2hours} + migrations = db.migration_get_all_by_filters( + self.ctxt, filters, + sort_keys=['updated_at'], sort_dirs=['asc']) + self.assertEqual(3, len(migrations)) + self.assertEqual(migrations[0]['uuid'], uuidsentinel.uuid_time1) + self.assertEqual(migrations[1]['uuid'], uuidsentinel.uuid_time2) + self.assertEqual(migrations[2]['uuid'], uuidsentinel.uuid_time3) + class ModelsObjectComparatorMixin(object): def _dict_from_object(self, obj, ignored_keys): @@ -2144,6 +2157,65 @@ class InstanceTestCase(test.TestCase, ModelsObjectComparatorMixin): filters) self._assertEqualListsOfInstances([i2], result) + def test_instance_get_all_by_filters_changes_before(self): + i1 = self.create_instance_with_args(updated_at= + '2013-12-05T15:03:25.000000') + i2 = self.create_instance_with_args(updated_at= + '2013-12-05T15:03:26.000000') + changes_before = iso8601.parse_date('2013-12-05T15:03:26.000000') + result = db.instance_get_all_by_filters(self.ctxt, + {'changes-before': + changes_before}) + self._assertEqualListsOfInstances([i1, i2], result) + + changes_before = iso8601.parse_date('2013-12-05T15:03:25.000000') + result = db.instance_get_all_by_filters(self.ctxt, + {'changes-before': + changes_before}) + self._assertEqualListsOfInstances([i1], result) + + db.instance_destroy(self.ctxt, i2['uuid']) + filters = {} + filters['changes-before'] = changes_before + filters['marker'] = i2['uuid'] + result = db.instance_get_all_by_filters(self.ctxt, + filters) + self._assertEqualListsOfInstances([i1], result) + + def test_instance_get_all_by_filters_changes_time_period(self): + i1 = self.create_instance_with_args(updated_at= + '2013-12-05T15:03:25.000000') + i2 = self.create_instance_with_args(updated_at= + '2013-12-05T15:03:26.000000') + i3 = self.create_instance_with_args(updated_at= + '2013-12-05T15:03:27.000000') + changes_since = iso8601.parse_date('2013-12-05T15:03:25.000000') + changes_before = iso8601.parse_date('2013-12-05T15:03:27.000000') + result = db.instance_get_all_by_filters(self.ctxt, + {'changes-since': + changes_since, + 'changes-before': + changes_before}) + self._assertEqualListsOfInstances([i1, i2, i3], result) + + changes_since = iso8601.parse_date('2013-12-05T15:03:26.000000') + changes_before = iso8601.parse_date('2013-12-05T15:03:27.000000') + result = db.instance_get_all_by_filters(self.ctxt, + {'changes-since': + changes_since, + 'changes-before': + changes_before}) + self._assertEqualListsOfInstances([i2, i3], result) + + db.instance_destroy(self.ctxt, i1['uuid']) + filters = {} + filters['changes-since'] = changes_since + filters['changes-before'] = changes_before + filters['marker'] = i1['uuid'] + result = db.instance_get_all_by_filters(self.ctxt, + filters) + self._assertEqualListsOfInstances([i2, i3], result) + def test_instance_get_all_by_filters_exact_match(self): instance = self.create_instance_with_args(host='host1') self.create_instance_with_args(host='host12') @@ -3590,6 +3662,35 @@ class InstanceActionTestCase(test.TestCase, ModelsObjectComparatorMixin): self.assertEqual(1, len(actions)) self._assertEqualListsOfObjects([action2], actions) + def test_instance_actions_get_with_changes_before(self): + """Test list instance actions can support timestamp filter.""" + uuid1 = uuidsentinel.uuid1 + + expected = [] + extra = { + 'created_at': timeutils.utcnow() + } + + action_values = self._create_action_values(uuid1, extra=extra) + action = db.action_start(self.ctxt, action_values) + expected.append(action) + + timestamp = timeutils.utcnow() + action_values['start_time'] = timestamp + action_values['updated_at'] = timestamp + action_values['action'] = 'delete' + action = db.action_start(self.ctxt, action_values) + expected.append(action) + + actions = db.actions_get(self.ctxt, uuid1) + self.assertEqual(2, len(actions)) + self.assertNotEqual(actions[0]['updated_at'], + actions[1]['updated_at']) + actions = db.actions_get( + self.ctxt, uuid1, filters={'changes-before': timestamp}) + self.assertEqual(2, len(actions)) + self._assertEqualListsOfObjects(expected, actions) + def test_instance_actions_get_with_not_found_marker(self): self.assertRaises(exception.MarkerNotFound, db.actions_get, self.ctxt, uuidsentinel.uuid1, diff --git a/releasenotes/notes/support-to-query-nova-resources-filter-by-changes-before-e4942cde61070e28.yaml b/releasenotes/notes/support-to-query-nova-resources-filter-by-changes-before-e4942cde61070e28.yaml new file mode 100644 index 000000000000..a2baaa035461 --- /dev/null +++ b/releasenotes/notes/support-to-query-nova-resources-filter-by-changes-before-e4942cde61070e28.yaml @@ -0,0 +1,24 @@ +--- +features: + - | + Microversion 2.66 adds the optional filter parameter ``changes-before`` + which can be used to get resources changed before or equal to the + specified date and time. + + Like the ``changes-since`` filter, the ``changes-before`` filter will + also return deleted servers. + + This parameter (``changes-before``) does not change any read-deleted + behavior in the os-instance-actions or os-migrations APIs. + The os-instance-actions API with the 2.21 microversion allows retrieving + instance actions for a deleted server resource. The os-migrations API + takes an optional ``instance_uuid`` filter parameter but does not support + returning deleted migration records. + + The ``changes-before`` request parameter can be passed to the servers, + os-instance-action and os-migrations APIs: + + * ``GET /servers`` + * ``GET /servers/detail`` + * ``GET /servers/{server_id}/os-instance-actions`` + * ``GET /os-migrations``