From 1f67ce24961a156dba56cacc75cbdd0800a7feee Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Tue, 29 Sep 2020 17:32:56 +0100 Subject: [PATCH] api: Drop statistics-style fields from os-hypervisors Introduce API microversion 2.88, which makes the following changes to a number of 'os-hypervisors'. Specifically, the following fields are dropped from both the '/os-hypervisors/detail' (detailed list) and '/os-hypervisors/{hypervisor_id}' (show) APIs: - current_workload - cpu_info - vcpus - vcpus_used - free_disk_gb - local_gb - local_gb_used - disk_available_least - free_ram_mb - memory_mb - memory_mb_used - running_vms In addition, the '/os-hypervisors/statistics' API, which provided a summary of the above stats but for all hypervisors in the deployment, is dropped entirely. Finally, the '/os-hypervisors/{hypervisor}/uptime' API, which provided a similar response to the '/os-hypervisors/{hypervisor}' API but with an additional 'uptime' field, has been removed in favour of including this field in the primary '/os-hypervisors/{hypervisor}' API. A small tweak to 'tox.ini' that allows us to share some venvs is included. Part of blueprint modernize-os-hypervisors-api Change-Id: I515e484ade6c6455f82a3067940a418a0d7d965a Signed-off-by: Stephen Finucane --- api-ref/source/os-hypervisors.inc | 52 +++- api-ref/source/parameters.yaml | 66 +++-- .../v2.88/hypervisors-detail-resp.json | 25 ++ .../hypervisors-detail-with-servers-resp.json | 29 +++ .../v2.88/hypervisors-list-resp.json | 16 ++ .../v2.88/hypervisors-search-resp.json | 10 + .../v2.88/hypervisors-show-resp.json | 17 ++ .../hypervisors-show-with-servers-resp.json | 27 ++ .../v2.88/hypervisors-with-servers-resp.json | 20 ++ .../versions/v21-version-get-resp.json | 2 +- .../versions/versions-get-resp.json | 2 +- nova/api/openstack/api_version_request.py | 6 +- nova/api/openstack/compute/hypervisors.py | 108 +++++--- .../compute/rest_api_version_history.rst | 35 ++- .../v2.88/hypervisors-detail-resp.json.tpl | 25 ++ ...ervisors-detail-with-servers-resp.json.tpl | 29 +++ .../v2.88/hypervisors-list-resp.json.tpl | 16 ++ .../v2.88/hypervisors-search-resp.json.tpl | 10 + .../v2.88/hypervisors-show-resp.json.tpl | 17 ++ ...ypervisors-show-with-servers-resp.json.tpl | 27 ++ .../hypervisors-with-servers-resp.json.tpl | 20 ++ .../hypervisors-without-servers-resp.json.tpl | 10 + .../api_sample_tests/test_hypervisors.py | 18 ++ nova/tests/functional/test_servers.py | 20 +- .../api/openstack/compute/test_hypervisors.py | 230 ++++++++++++------ .../microversion-2-88-7063636ed9c11a5d.yaml | 33 +++ tox.ini | 1 + 27 files changed, 722 insertions(+), 149 deletions(-) create mode 100644 doc/api_samples/os-hypervisors/v2.88/hypervisors-detail-resp.json create mode 100644 doc/api_samples/os-hypervisors/v2.88/hypervisors-detail-with-servers-resp.json create mode 100644 doc/api_samples/os-hypervisors/v2.88/hypervisors-list-resp.json create mode 100644 doc/api_samples/os-hypervisors/v2.88/hypervisors-search-resp.json create mode 100644 doc/api_samples/os-hypervisors/v2.88/hypervisors-show-resp.json create mode 100644 doc/api_samples/os-hypervisors/v2.88/hypervisors-show-with-servers-resp.json create mode 100644 doc/api_samples/os-hypervisors/v2.88/hypervisors-with-servers-resp.json create mode 100644 nova/tests/functional/api_sample_tests/api_samples/os-hypervisors/v2.88/hypervisors-detail-resp.json.tpl create mode 100644 nova/tests/functional/api_sample_tests/api_samples/os-hypervisors/v2.88/hypervisors-detail-with-servers-resp.json.tpl create mode 100644 nova/tests/functional/api_sample_tests/api_samples/os-hypervisors/v2.88/hypervisors-list-resp.json.tpl create mode 100644 nova/tests/functional/api_sample_tests/api_samples/os-hypervisors/v2.88/hypervisors-search-resp.json.tpl create mode 100644 nova/tests/functional/api_sample_tests/api_samples/os-hypervisors/v2.88/hypervisors-show-resp.json.tpl create mode 100644 nova/tests/functional/api_sample_tests/api_samples/os-hypervisors/v2.88/hypervisors-show-with-servers-resp.json.tpl create mode 100644 nova/tests/functional/api_sample_tests/api_samples/os-hypervisors/v2.88/hypervisors-with-servers-resp.json.tpl create mode 100644 nova/tests/functional/api_sample_tests/api_samples/os-hypervisors/v2.88/hypervisors-without-servers-resp.json.tpl create mode 100644 releasenotes/notes/microversion-2-88-7063636ed9c11a5d.yaml diff --git a/api-ref/source/os-hypervisors.inc b/api-ref/source/os-hypervisors.inc index 84e67e60cd4..6363b409b40 100644 --- a/api-ref/source/os-hypervisors.inc +++ b/api-ref/source/os-hypervisors.inc @@ -12,6 +12,7 @@ for a hypervisor, lists all servers on hypervisors that match the given ``hypervisor_hostname_pattern`` or searches for hypervisors by the given ``hypervisor_hostname_pattern``. + List Hypervisors ================ @@ -64,6 +65,7 @@ Response .. literalinclude:: ../../doc/api_samples/os-hypervisors/v2.53/hypervisors-with-servers-resp.json :language: javascript + List Hypervisors Details ======================== @@ -122,6 +124,7 @@ Response - service.id: service_id_body_2_52 - service.id: service_id_body_2_53 - service.disabled_reason: service_disable_reason + - uptime: hypervisor_uptime - vcpus: hypervisor_vcpus - vcpus_used: hypervisor_vcpus_used - hypervisor_links: hypervisor_links @@ -136,13 +139,25 @@ Response .. literalinclude:: ../../doc/api_samples/os-hypervisors/v2.53/hypervisors-detail-resp.json :language: javascript -Show Hypervisor Statistics -========================== +**Example List Hypervisors Details (v2.88): JSON response** + +.. literalinclude:: ../../doc/api_samples/os-hypervisors/v2.88/hypervisors-detail-resp.json + :language: javascript + + +Show Hypervisor Statistics (DEPRECATED) +======================================= .. rest_method:: GET /os-hypervisors/statistics + max_version: 2.87 Shows summary statistics for all enabled hypervisors over all compute nodes. +.. warning:: + + This API is deprecated and will fail with HTTP 404 starting with microversion + 2.88. Use placement to get information on resource usage across hypervisors. + Policy defaults enable only users with the administrative role to perform this operation. Cloud providers can change these permissions through the ``policy.json`` file. @@ -158,7 +173,7 @@ the ``policy.json`` file. Normal response codes: 200 -Error response codes: unauthorized(401), forbidden(403) +Error response codes: unauthorized(401), forbidden(403), itemNotFound(404) Response -------- @@ -167,7 +182,7 @@ Response - hypervisor_statistics: hypervisor_statistics - count: hypervisor_count - - current_workload: current_workload + - current_workload: current_workload_total - disk_available_least: disk_available_least_total - free_disk_gb: hypervisor_free_disk_gb_total - free_ram_mb: free_ram_mb_total @@ -184,6 +199,7 @@ Response .. literalinclude:: ../../doc/api_samples/os-hypervisors/hypervisors-statistics-resp.json :language: javascript + Show Hypervisor Details ======================= @@ -249,6 +265,7 @@ Response - service.id: service_id_body_2_52 - service.id: service_id_body_2_53 - service.disabled_reason: service_disable_reason + - uptime: hypervisor_uptime - vcpus: hypervisor_vcpus - vcpus_used: hypervisor_vcpus_used @@ -262,13 +279,26 @@ Response .. literalinclude:: ../../doc/api_samples/os-hypervisors/v2.53/hypervisors-show-with-servers-resp.json :language: javascript -Show Hypervisor Uptime -====================== +**Example Show Hypervisors Details (v2.88): JSON response** + +.. literalinclude:: ../../doc/api_samples/os-hypervisors/v2.88/hypervisors-show-with-servers-resp.json + :language: javascript + + +Show Hypervisor Uptime (DEPRECATED) +=================================== .. rest_method:: GET /os-hypervisors/{hypervisor_id}/uptime + max_version: 2.87 Shows the uptime for a given hypervisor. +.. warning:: + + This API is deprecated and will fail with HTTP 404 starting with + microversion 2.88. Use `Show Hypervisor Details`_ with microversion 2.88 + and later to get this information. + Policy defaults enable only users with the administrative role to perform this operation. Cloud providers can change these permissions through the ``policy.json`` file. @@ -308,8 +338,9 @@ Response .. literalinclude:: ../../doc/api_samples/os-hypervisors/v2.53/hypervisors-uptime-resp.json :language: javascript -Search Hypervisor -================= + +Search Hypervisor (DEPRECATED) +============================== .. rest_method:: GET /os-hypervisors/{hypervisor_hostname_pattern}/search max_version: 2.52 @@ -351,8 +382,9 @@ Response .. literalinclude:: ../../doc/api_samples/os-hypervisors/hypervisors-search-resp.json :language: javascript -List Hypervisor Servers -======================= + +List Hypervisor Servers (DEPRECATED) +==================================== .. rest_method:: GET /os-hypervisors/{hypervisor_hostname_pattern}/servers max_version: 2.52 diff --git a/api-ref/source/parameters.yaml b/api-ref/source/parameters.yaml index cc36fcbe8a8..13fbc541aa8 100644 --- a/api-ref/source/parameters.yaml +++ b/api-ref/source/parameters.yaml @@ -2226,6 +2226,7 @@ cpu_info: in: body required: true type: object + max_version: 2.87 create_info: description: | Information for snapshot creation. @@ -2280,9 +2281,20 @@ createImage: type: object current_workload: description: | - The current_workload is the number of tasks the hypervisor is responsible for. This will be - equal or greater than the number of active VMs on the system (it can be greater when VMs - are being deleted and the hypervisor is still cleaning up). + The current_workload is the number of tasks the hypervisor is responsible + for. This will be equal or greater than the number of active VMs on the + system (it can be greater when VMs are being deleted and the hypervisor is + still cleaning up). + in: body + required: true + type: integer + max_version: 2.87 +current_workload_total: + description: | + The current_workload is the number of tasks the hypervisors are responsible + for. This will be equal or greater than the number of active VMs on the + systems (it can be greater when VMs are being deleted and a hypervisor is + still cleaning up). in: body required: true type: integer @@ -2504,6 +2516,7 @@ disk_available_least: in: body required: true type: integer + max_version: 2.87 disk_available_least_total: description: | The actual free disk on all hypervisors(in GiB). If allocation ratios used @@ -3438,6 +3451,7 @@ free_ram_mb: in: body required: true type: integer + max_version: 2.87 free_ram_mb_total: description: | The free RAM on all hypervisors(in MiB). This does not take allocation @@ -3742,6 +3756,7 @@ hypervisor_free_disk_gb: in: body required: true type: integer + max_version: 2.87 hypervisor_free_disk_gb_total: description: | The free disk remaining on all hypervisors(in GiB). This does not take @@ -3752,8 +3767,8 @@ hypervisor_free_disk_gb_total: type: integer hypervisor_hostname: description: | - The hypervisor host name provided by the Nova virt driver. For the Ironic driver, - it is the Ironic node uuid. + The hypervisor host name provided by the Nova virt driver. For the Ironic + driver, it is the Ironic node uuid. in: body required: true type: string @@ -3853,17 +3868,26 @@ hypervisor_type_body: in: body required: true type: string +hypervisor_uptime: + description: | + The total uptime of the hypervisor and information about average load. Only + reported for active hosts where the virt driver supports this feature. + in: body + required: true + type: string + min_version: 2.88 hypervisor_vcpus: description: | - The number of vcpu in this hypervisor. This does not take allocation + The number of vCPU in this hypervisor. This does not take allocation ratios used for overcommit into account so there may be disparity between this and the used count. in: body required: true type: integer + max_version: 2.87 hypervisor_vcpus_total: description: | - The number of vcpu on all hypervisors. This does not take allocation + The number of vCPU on all hypervisors. This does not take allocation ratios used for overcommit into account so there may be disparity between this and the used count. in: body @@ -3871,13 +3895,14 @@ hypervisor_vcpus_total: type: integer hypervisor_vcpus_used: description: | - The number of vcpu used in this hypervisor. + The number of vCPU used in this hypervisor. in: body required: true type: integer + max_version: 2.87 hypervisor_vcpus_used_total: description: | - The number of vcpu used on all hypervisors. + The number of vCPU used on all hypervisors. in: body required: true type: integer @@ -4480,12 +4505,13 @@ links: type: array local_gb: description: | - The disk in this hypervisor(in GiB). This does not take allocation + The disk in this hypervisor (in GiB). This does not take allocation ratios used for overcommit into account so there may be disparity between this and the used count. in: body required: true type: integer + max_version: 2.87 local_gb_simple_tenant_usage: description: | The sum of the root disk size of the server and @@ -4502,7 +4528,7 @@ local_gb_simple_tenant_usage_optional: type: integer local_gb_total: description: | - The disk on all hypervisors(in GiB). This does not take allocation + The disk on all hypervisors (in GiB). This does not take allocation ratios used for overcommit into account so there may be disparity between this and the used count. in: body @@ -4510,13 +4536,14 @@ local_gb_total: type: integer local_gb_used: description: | - The disk used in this hypervisor(in GiB). + The disk used in this hypervisor (in GiB). in: body required: true type: integer + max_version: 2.87 local_gb_used_total: description: | - The disk used on all hypervisors(in GiB). + The disk used on all hypervisors (in GiB). in: body required: true type: integer @@ -4600,12 +4627,13 @@ memory_details_diagnostics: min_version: 2.48 memory_mb: description: | - The memory of this hypervisor(in MiB). This does not take allocation + The memory of this hypervisor (in MiB). This does not take allocation ratios used for overcommit into account so there may be disparity between this and the used count. in: body required: true type: integer + max_version: 2.87 memory_mb_simple_tenant_usage: description: | The memory size of the server (in MiB). @@ -4620,7 +4648,7 @@ memory_mb_simple_tenant_usage_optional: type: integer memory_mb_total: description: | - The memory of all hypervisors(in MiB). This does not take allocation + The memory of all hypervisors (in MiB). This does not take allocation ratios used for overcommit into account so there may be disparity between this and the used count. in: body @@ -4628,10 +4656,11 @@ memory_mb_total: type: integer memory_mb_used: description: | - The memory used in this hypervisor(in MiB). + The memory used in this hypervisor (in MiB). in: body required: true type: integer + max_version: 2.87 memory_mb_used_total: description: | The memory used on all hypervisors(in MiB). @@ -6020,13 +6049,14 @@ rules: type: array running_vms: description: | - The number of running vms on this hypervisor. + The number of running VMs on this hypervisor. in: body required: true type: integer + max_version: 2.87 running_vms_total: description: | - The total number of running vms on all hypervisors. + The total number of running VMs on all hypervisors. in: body required: true type: integer diff --git a/doc/api_samples/os-hypervisors/v2.88/hypervisors-detail-resp.json b/doc/api_samples/os-hypervisors/v2.88/hypervisors-detail-resp.json new file mode 100644 index 00000000000..a009a125ffc --- /dev/null +++ b/doc/api_samples/os-hypervisors/v2.88/hypervisors-detail-resp.json @@ -0,0 +1,25 @@ +{ + "hypervisors": [ + { + "host_ip": "192.168.1.135", + "hypervisor_hostname": "host2", + "hypervisor_type": "fake", + "hypervisor_version": 1000, + "id": "f6d28711-9c10-470e-8b31-c03f498b0032", + "service": { + "disabled_reason": null, + "host": "host2", + "id": "21bbb5fb-ec98-48b3-89cf-c94402c55611" + }, + "state": "up", + "status": "enabled", + "uptime": null + } + ], + "hypervisors_links": [ + { + "href": "http://openstack.example.com/v2.1/6f70656e737461636b20342065766572/os-hypervisors/detail?limit=1&marker=f6d28711-9c10-470e-8b31-c03f498b0032", + "rel": "next" + } + ] +} diff --git a/doc/api_samples/os-hypervisors/v2.88/hypervisors-detail-with-servers-resp.json b/doc/api_samples/os-hypervisors/v2.88/hypervisors-detail-with-servers-resp.json new file mode 100644 index 00000000000..26526b18cc2 --- /dev/null +++ b/doc/api_samples/os-hypervisors/v2.88/hypervisors-detail-with-servers-resp.json @@ -0,0 +1,29 @@ +{ + "hypervisors": [ + { + "host_ip": "192.168.1.135", + "hypervisor_hostname": "fake-mini", + "hypervisor_type": "fake", + "hypervisor_version": 1000, + "id": "28b0e607-d58a-4602-a511-efe18024f4d5", + "servers": [ + { + "name": "test_server1", + "uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + { + "name": "test_server2", + "uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb" + } + ], + "service": { + "disabled_reason": null, + "host": "compute", + "id": "40e769a5-7489-4cf3-be46-f6bd3e4e3c25" + }, + "state": "up", + "status": "enabled", + "uptime": null + } + ] +} diff --git a/doc/api_samples/os-hypervisors/v2.88/hypervisors-list-resp.json b/doc/api_samples/os-hypervisors/v2.88/hypervisors-list-resp.json new file mode 100644 index 00000000000..7c042bf8fa6 --- /dev/null +++ b/doc/api_samples/os-hypervisors/v2.88/hypervisors-list-resp.json @@ -0,0 +1,16 @@ +{ + "hypervisors": [ + { + "hypervisor_hostname": "host2", + "id": "bfb90ba3-e13e-4413-90ff-5cdbfea727e2", + "state": "up", + "status": "enabled" + } + ], + "hypervisors_links": [ + { + "href": "http://openstack.example.com/v2.1/6f70656e737461636b20342065766572/os-hypervisors?limit=1&marker=bfb90ba3-e13e-4413-90ff-5cdbfea727e2", + "rel": "next" + } + ] +} \ No newline at end of file diff --git a/doc/api_samples/os-hypervisors/v2.88/hypervisors-search-resp.json b/doc/api_samples/os-hypervisors/v2.88/hypervisors-search-resp.json new file mode 100644 index 00000000000..6190e428bd7 --- /dev/null +++ b/doc/api_samples/os-hypervisors/v2.88/hypervisors-search-resp.json @@ -0,0 +1,10 @@ +{ + "hypervisors": [ + { + "hypervisor_hostname": "fake-mini", + "id": "6b7876c5-9ae7-4fa7-a5c8-28c796d17381", + "state": "up", + "status": "enabled" + } + ] +} \ No newline at end of file diff --git a/doc/api_samples/os-hypervisors/v2.88/hypervisors-show-resp.json b/doc/api_samples/os-hypervisors/v2.88/hypervisors-show-resp.json new file mode 100644 index 00000000000..d1e566d6eb6 --- /dev/null +++ b/doc/api_samples/os-hypervisors/v2.88/hypervisors-show-resp.json @@ -0,0 +1,17 @@ +{ + "hypervisor": { + "host_ip": "192.168.1.135", + "hypervisor_hostname": "fake-mini", + "hypervisor_type": "fake", + "hypervisor_version": 1000, + "id": "f79c1cce-9972-44c6-aa30-1d9e6526ce37", + "service": { + "disabled_reason": null, + "host": "compute", + "id": "7e6b27b8-f563-4c21-baa4-a40d579ed8c4" + }, + "state": "up", + "status": "enabled", + "uptime": null + } +} diff --git a/doc/api_samples/os-hypervisors/v2.88/hypervisors-show-with-servers-resp.json b/doc/api_samples/os-hypervisors/v2.88/hypervisors-show-with-servers-resp.json new file mode 100644 index 00000000000..0196b9ca5ea --- /dev/null +++ b/doc/api_samples/os-hypervisors/v2.88/hypervisors-show-with-servers-resp.json @@ -0,0 +1,27 @@ +{ + "hypervisor": { + "host_ip": "192.168.1.135", + "hypervisor_hostname": "fake-mini", + "hypervisor_type": "fake", + "hypervisor_version": 1000, + "id": "a68a56ab-9c42-47c0-9309-879e4a6dbe86", + "servers": [ + { + "name": "test_server1", + "uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + { + "name": "test_server2", + "uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb" + } + ], + "service": { + "disabled_reason": null, + "host": "compute", + "id": "8495059a-a079-4ab4-ad6f-cf45b81c877d" + }, + "state": "up", + "status": "enabled", + "uptime": null + } +} diff --git a/doc/api_samples/os-hypervisors/v2.88/hypervisors-with-servers-resp.json b/doc/api_samples/os-hypervisors/v2.88/hypervisors-with-servers-resp.json new file mode 100644 index 00000000000..abaea1ffd4e --- /dev/null +++ b/doc/api_samples/os-hypervisors/v2.88/hypervisors-with-servers-resp.json @@ -0,0 +1,20 @@ +{ + "hypervisors": [ + { + "hypervisor_hostname": "fake-mini", + "id": "39b0c938-8e2f-49da-bb52-e85c78d4ff2a", + "servers": [ + { + "name": "test_server1", + "uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + { + "name": "test_server2", + "uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb" + } + ], + "state": "up", + "status": "enabled" + } + ] +} \ No newline at end of file diff --git a/doc/api_samples/versions/v21-version-get-resp.json b/doc/api_samples/versions/v21-version-get-resp.json index abfbcf4f352..80b3f335329 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.87", + "version": "2.88", "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 0e870df3ae2..68c6ec8a2a9 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.87", + "version": "2.88", "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 037b01124bc..456e19e403e 100644 --- a/nova/api/openstack/api_version_request.py +++ b/nova/api/openstack/api_version_request.py @@ -236,6 +236,10 @@ ``PUT /flavors/{flavor_id}/os-extra_specs/{id}`` APIs. * 2.87 - Adds support for rescuing boot from volume instances when the compute host reports the COMPUTE_BFV_RESCUE capability trait. + * 2.88 - Drop statistics-style fields from the ``/os-hypervisors/detail`` + and ``/os-hypervisors/{hypervisor_id}`` APIs, and remove the + ``/os-hypervisors/statistics`` and + ``/os-hypervisors/{hypervisor_id}/uptime`` APIs entirely. """ # The minimum and maximum versions of the API supported @@ -244,7 +248,7 @@ # Note(cyeoh): This only applies for the v2.1 API once microversions # support is fully merged. It does not affect the V2 API. _MIN_API_VERSION = '2.1' -_MAX_API_VERSION = '2.87' +_MAX_API_VERSION = '2.88' 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/hypervisors.py b/nova/api/openstack/compute/hypervisors.py index 8232fd9f4f1..63908bc81c1 100644 --- a/nova/api/openstack/compute/hypervisors.py +++ b/nova/api/openstack/compute/hypervisors.py @@ -49,57 +49,85 @@ def __init__(self): self.host_api = compute.HostAPI() self.servicegroup_api = servicegroup.API() - def _view_hypervisor(self, hypervisor, service, detail, req, servers=None, - with_servers=False, **kwargs): + def _view_hypervisor( + self, hypervisor, service, detail, req, servers=None, + with_servers=False, + ): alive = self.servicegroup_api.service_is_up(service) # The 2.53 microversion returns the compute node uuid rather than id. uuid_for_id = api_version_request.is_supported( req, min_version=UUID_FOR_ID_MIN_VERSION) + hyp_dict = { 'id': hypervisor.uuid if uuid_for_id else hypervisor.id, 'hypervisor_hostname': hypervisor.hypervisor_hostname, 'state': 'up' if alive else 'down', - 'status': ('disabled' if service.disabled - else 'enabled'), - } + 'status': 'disabled' if service.disabled else 'enabled', + } if detail: - for field in ('vcpus', 'memory_mb', 'local_gb', 'vcpus_used', - 'memory_mb_used', 'local_gb_used', - 'hypervisor_type', 'hypervisor_version', - 'free_ram_mb', 'free_disk_gb', 'current_workload', - 'running_vms', 'disk_available_least', 'host_ip'): + for field in ( + 'hypervisor_type', 'hypervisor_version', 'host_ip', + ): hyp_dict[field] = getattr(hypervisor, field) - service_id = service.uuid if uuid_for_id else service.id hyp_dict['service'] = { - 'id': service_id, + 'id': service.uuid if uuid_for_id else service.id, 'host': hypervisor.host, 'disabled_reason': service.disabled_reason, - } + } + + # The 2.88 microversion removed these fields, so only add them on older + # microversions + if detail and api_version_request.is_supported( + req, max_version='2.87', + ): + for field in ( + 'vcpus', 'memory_mb', 'local_gb', 'vcpus_used', + 'memory_mb_used', 'local_gb_used', 'free_ram_mb', + 'free_disk_gb', 'current_workload', 'running_vms', + 'disk_available_least', + ): + hyp_dict[field] = getattr(hypervisor, field) - if api_version_request.is_supported(req, min_version='2.28'): + if api_version_request.is_supported(req, max_version='2.27'): + hyp_dict['cpu_info'] = hypervisor.cpu_info + else: if hypervisor.cpu_info: hyp_dict['cpu_info'] = jsonutils.loads(hypervisor.cpu_info) else: hyp_dict['cpu_info'] = {} - else: - hyp_dict['cpu_info'] = hypervisor.cpu_info + + # The 2.88 microversion also *added* the 'uptime' field to the response + if detail and api_version_request.is_supported( + req, min_version='2.88', + ): + try: + hyp_dict['uptime'] = self.host_api.get_host_uptime( + req.environ['nova.context'], hypervisor.host) + except ( + NotImplementedError, + exception.ComputeServiceUnavailable, + exception.HostMappingNotFound, + exception.HostNotFound, + ): + # Not all virt drivers support this, and it's not generally + # possible to get uptime for a down host + hyp_dict['uptime'] = None if servers: - hyp_dict['servers'] = [dict(name=serv['name'], uuid=serv['uuid']) - for serv in servers] + hyp_dict['servers'] = [ + {'name': serv['name'], 'uuid': serv['uuid']} + for serv in servers + ] # The 2.75 microversion adds 'servers' field always in response. # Empty list if there are no servers on hypervisors and it is # requested in request. elif with_servers and api_version_request.is_supported( - req, min_version='2.75'): + req, min_version='2.75', + ): hyp_dict['servers'] = [] - # Add any additional info - if kwargs: - hyp_dict.update(kwargs) - return hyp_dict def _get_compute_nodes_by_name_pattern(self, context, hostname_match): @@ -184,10 +212,11 @@ def _get_hypervisors(self, req, detail=False, limit=None, marker=None, 'be manually cleaned up.', hyp.host) continue - hypervisors_list.append( - self._view_hypervisor( - hyp, service, detail, req, servers=instances, - with_servers=with_servers)) + hypervisor = self._view_hypervisor( + hyp, service, detail, req, servers=instances, + with_servers=with_servers, + ) + hypervisors_list.append(hypervisor) hypervisors_dict = dict(hypervisors=hypervisors_list) if links: @@ -339,11 +368,21 @@ def _show(self, req, id, with_servers=False): msg = _("Hypervisor with ID '%s' could not be found.") % id raise webob.exc.HTTPNotFound(explanation=msg) - return dict(hypervisor=self._view_hypervisor( - hyp, service, True, req, instances, with_servers)) + return { + 'hypervisor': self._view_hypervisor( + hyp, service, detail=True, req=req, servers=instances, + with_servers=with_servers, + ), + } + @wsgi.Controller.api_version('2.1', '2.87') @wsgi.expected_errors((400, 404, 501)) def uptime(self, req, id): + """Prior to microversion 2.88, you could retrieve a special version of + the hypervisor detail view that included uptime. Starting in 2.88, this + field is now included in the standard detail view, making this API + unnecessary. + """ context = req.environ['nova.context'] context.can(hv_policies.BASE_POLICY_NAME % 'uptime', target={}) @@ -383,8 +422,10 @@ def uptime(self, req, id): msg = _("Hypervisor with ID '%s' could not be found.") % id raise webob.exc.HTTPNotFound(explanation=msg) - return dict(hypervisor=self._view_hypervisor(hyp, service, False, req, - uptime=uptime)) + hypervisor = self._view_hypervisor(hyp, service, False, req) + hypervisor['uptime'] = uptime + + return {'hypervisor': hypervisor} @wsgi.Controller.api_version('2.1', '2.52') @wsgi.expected_errors(404) @@ -469,8 +510,13 @@ def servers(self, req, id): return {'hypervisors': hypervisors} + @wsgi.Controller.api_version('2.1', '2.87') @wsgi.expected_errors(()) def statistics(self, req): + """Prior to microversion 2.88, you could get statistics for the + hypervisor. Most of these are now accessible from placement and the few + that aren't as misleading and frequently misunderstood. + """ context = req.environ['nova.context'] context.can(hv_policies.BASE_POLICY_NAME % 'statistics', target={}) stats = self.host_api.compute_node_statistics(context) diff --git a/nova/api/openstack/compute/rest_api_version_history.rst b/nova/api/openstack/compute/rest_api_version_history.rst index 1390f05b349..0e142c6eaa1 100644 --- a/nova/api/openstack/compute/rest_api_version_history.rst +++ b/nova/api/openstack/compute/rest_api_version_history.rst @@ -748,7 +748,7 @@ The embedded flavor description will not be included in server representations. ---- Updates the POST request body for the ``migrate`` action to include the -the optional ``host`` string field defaulted to ``null``. If ``host`` is +optional ``host`` string field defaulted to ``null``. If ``host`` is set the migrate action verifies the provided host with the nova scheduler and uses it as the destination for the migration. @@ -1140,3 +1140,36 @@ Validation is only used for recognized extra spec namespaces, currently: Adds support for rescuing boot from volume instances when the compute host reports the ``COMPUTE_BFV_RESCUE`` capability trait. + +2.88 +---- + +The following fields are no longer included in responses for the +``GET /os-hypervisors/detail`` and ``GET /os-hypervisors/{hypervisor_id}`` +APIs: + +- ``current_workload`` +- ``cpu_info`` +- ``vcpus`` +- ``vcpus_used`` +- ``free_disk_gb`` +- ``local_gb`` +- ``local_gb_used`` +- ``disk_available_least`` +- ``free_ram_mb`` +- ``memory_mb`` +- ``memory_mb_used`` +- ``running_vms`` + +These fields were removed as the information they provided were frequently +misleading or outright wrong, and many can be better queried from placement. + +In addition, the ``GET /os-hypervisors/statistics`` API, which provided a +summary view with just the fields listed above, has been removed entirely and +will now raise a HTTP 404 with microversion 2.88 or greater. + +Finally, the ``GET /os-hypervisors/{hypervisor}/uptime`` API, which provided a +similar response to the ``GET /os-hypervisors/detail`` and ``GET +/os-hypervisors/{hypervisor_id}`` APIs but with an additional ``uptime`` field, +has been removed in favour of including this field in the primary ``GET +/os-hypervisors/detail`` and ``GET /os-hypervisors/{hypervisor_id}`` APIs. diff --git a/nova/tests/functional/api_sample_tests/api_samples/os-hypervisors/v2.88/hypervisors-detail-resp.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/os-hypervisors/v2.88/hypervisors-detail-resp.json.tpl new file mode 100644 index 00000000000..3f1e1ed863d --- /dev/null +++ b/nova/tests/functional/api_sample_tests/api_samples/os-hypervisors/v2.88/hypervisors-detail-resp.json.tpl @@ -0,0 +1,25 @@ +{ + "hypervisors": [ + { + "id": "%(hypervisor_id)s", + "status": "enabled", + "state": "up", + "host_ip": "%(ip)s", + "hypervisor_hostname": "host2", + "hypervisor_type": "fake", + "hypervisor_version": 1000, + "service": { + "host": "%(host_name)s", + "id": "%(service_id)s", + "disabled_reason": null + }, + "uptime": null + } + ], + "hypervisors_links": [ + { + "href": "http://openstack.example.com/v2.1/6f70656e737461636b20342065766572/os-hypervisors/detail?limit=1&marker=%(hypervisor_id)s", + "rel": "next" + } + ] +} diff --git a/nova/tests/functional/api_sample_tests/api_samples/os-hypervisors/v2.88/hypervisors-detail-with-servers-resp.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/os-hypervisors/v2.88/hypervisors-detail-with-servers-resp.json.tpl new file mode 100644 index 00000000000..bc079ae7dc2 --- /dev/null +++ b/nova/tests/functional/api_sample_tests/api_samples/os-hypervisors/v2.88/hypervisors-detail-with-servers-resp.json.tpl @@ -0,0 +1,29 @@ +{ + "hypervisors": [ + { + "id": "%(hypervisor_id)s", + "status": "enabled", + "state": "up", + "host_ip": "%(ip)s", + "hypervisor_hostname": "fake-mini", + "hypervisor_type": "fake", + "hypervisor_version": 1000, + "servers": [ + { + "name": "test_server1", + "uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + { + "name": "test_server2", + "uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb" + } + ], + "service": { + "host": "%(host_name)s", + "id": "%(service_id)s", + "disabled_reason": null + }, + "uptime": null + } + ] +} diff --git a/nova/tests/functional/api_sample_tests/api_samples/os-hypervisors/v2.88/hypervisors-list-resp.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/os-hypervisors/v2.88/hypervisors-list-resp.json.tpl new file mode 100644 index 00000000000..53371fb91fb --- /dev/null +++ b/nova/tests/functional/api_sample_tests/api_samples/os-hypervisors/v2.88/hypervisors-list-resp.json.tpl @@ -0,0 +1,16 @@ +{ + "hypervisors": [ + { + "id": "%(hypervisor_id)s", + "hypervisor_hostname": "host2", + "state": "up", + "status": "enabled" + } + ], + "hypervisors_links": [ + { + "href": "http://openstack.example.com/v2.1/6f70656e737461636b20342065766572/os-hypervisors?limit=1&marker=%(hypervisor_id)s", + "rel": "next" + } + ] +} diff --git a/nova/tests/functional/api_sample_tests/api_samples/os-hypervisors/v2.88/hypervisors-search-resp.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/os-hypervisors/v2.88/hypervisors-search-resp.json.tpl new file mode 100644 index 00000000000..52846dc1323 --- /dev/null +++ b/nova/tests/functional/api_sample_tests/api_samples/os-hypervisors/v2.88/hypervisors-search-resp.json.tpl @@ -0,0 +1,10 @@ +{ + "hypervisors": [ + { + "id": "%(hypervisor_id)s", + "state": "up", + "status": "enabled", + "hypervisor_hostname": "fake-mini" + } + ] +} diff --git a/nova/tests/functional/api_sample_tests/api_samples/os-hypervisors/v2.88/hypervisors-show-resp.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/os-hypervisors/v2.88/hypervisors-show-resp.json.tpl new file mode 100644 index 00000000000..a2ed1b18aef --- /dev/null +++ b/nova/tests/functional/api_sample_tests/api_samples/os-hypervisors/v2.88/hypervisors-show-resp.json.tpl @@ -0,0 +1,17 @@ +{ + "hypervisor": { + "id": "%(hypervisor_id)s", + "status": "enabled", + "state": "up", + "host_ip": "%(ip)s", + "hypervisor_hostname": "fake-mini", + "hypervisor_type": "fake", + "hypervisor_version": 1000, + "service": { + "host": "%(host_name)s", + "id": "%(service_id)s", + "disabled_reason": null + }, + "uptime": null + } +} diff --git a/nova/tests/functional/api_sample_tests/api_samples/os-hypervisors/v2.88/hypervisors-show-with-servers-resp.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/os-hypervisors/v2.88/hypervisors-show-with-servers-resp.json.tpl new file mode 100644 index 00000000000..778e0b4f131 --- /dev/null +++ b/nova/tests/functional/api_sample_tests/api_samples/os-hypervisors/v2.88/hypervisors-show-with-servers-resp.json.tpl @@ -0,0 +1,27 @@ +{ + "hypervisor": { + "id": "%(hypervisor_id)s", + "state": "up", + "status": "enabled", + "host_ip": "%(ip)s", + "hypervisor_hostname": "fake-mini", + "hypervisor_type": "fake", + "hypervisor_version": 1000, + "servers": [ + { + "name": "test_server1", + "uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + { + "name": "test_server2", + "uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb" + } + ], + "service": { + "host": "%(host_name)s", + "id": "%(service_id)s", + "disabled_reason": null + }, + "uptime": null + } +} diff --git a/nova/tests/functional/api_sample_tests/api_samples/os-hypervisors/v2.88/hypervisors-with-servers-resp.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/os-hypervisors/v2.88/hypervisors-with-servers-resp.json.tpl new file mode 100644 index 00000000000..925839ec7af --- /dev/null +++ b/nova/tests/functional/api_sample_tests/api_samples/os-hypervisors/v2.88/hypervisors-with-servers-resp.json.tpl @@ -0,0 +1,20 @@ +{ + "hypervisors": [ + { + "id": "%(hypervisor_id)s", + "hypervisor_hostname": "fake-mini", + "status": "enabled", + "state": "up", + "servers": [ + { + "name": "test_server1", + "uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + { + "name": "test_server2", + "uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb" + } + ] + } + ] +} diff --git a/nova/tests/functional/api_sample_tests/api_samples/os-hypervisors/v2.88/hypervisors-without-servers-resp.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/os-hypervisors/v2.88/hypervisors-without-servers-resp.json.tpl new file mode 100644 index 00000000000..89d27fed087 --- /dev/null +++ b/nova/tests/functional/api_sample_tests/api_samples/os-hypervisors/v2.88/hypervisors-without-servers-resp.json.tpl @@ -0,0 +1,10 @@ +{ + "hypervisors": [ + { + "id": "%(hypervisor_id)s", + "hypervisor_hostname": "fake-mini", + "status": "enabled", + "state": "up" + } + ] +} diff --git a/nova/tests/functional/api_sample_tests/test_hypervisors.py b/nova/tests/functional/api_sample_tests/test_hypervisors.py index ce4ca354d30..f402f9ebdeb 100644 --- a/nova/tests/functional/api_sample_tests/test_hypervisors.py +++ b/nova/tests/functional/api_sample_tests/test_hypervisors.py @@ -272,3 +272,21 @@ def test_hypervisors_show_with_servers(self, instance_get_all_by_host): hypervisor_id) self._verify_response('hypervisors-show-with-servers-resp', subs, response, 200) + + +class HypervisorsSampleJson288Tests(HypervisorsSampleJson253Tests): + microversion = '2.88' + scenarios = [('v2_88', {'api_major_version': 'v2.1'})] + + def test_hypervisors_uptime(self): + """The uptime route is deprecated in 2.88 and now returns a 404. + """ + hypervisor_id = '1' + response = self._do_get('os-hypervisors/%s/statistics' % hypervisor_id) + self.assertEqual(404, response.status_code) + + def test_hypervisors_statistics(self): + """The statistics route is deprecated in 2.88 and now returns a 404. + """ + response = self._do_get('os-hypervisors/statistics') + self.assertEqual(404, response.status_code) diff --git a/nova/tests/functional/test_servers.py b/nova/tests/functional/test_servers.py index 3f23b8ed923..4277fbd1dca 100644 --- a/nova/tests/functional/test_servers.py +++ b/nova/tests/functional/test_servers.py @@ -3956,10 +3956,12 @@ def test_ephemeral_has_disk_allocation(self): # 10gb root, 20gb ephemeral, 5gb swap expected_usage = 35 self.assertEqual(expected_usage, resources['DISK_GB']) - # Ensure the compute node is reporting the correct disk usage - self.assertEqual( - expected_usage, - self.admin_api.get_hypervisor_stats()['local_gb_used']) + # Ensure the compute node is reporting the correct disk usage. We're + # using v2.87 explicitly as the api returns 404 starting with 2.88 + with nova_utils.temporary_mutation(self.api, microversion='2.87'): + self.assertEqual( + expected_usage, + self.admin_api.get_hypervisor_stats()['local_gb_used']) def test_volume_backed_image_type_filter(self): # Enable the image type support filter and ensure that a @@ -3978,10 +3980,12 @@ def test_volume_backed_no_disk_allocation(self): # 0gb root, 20gb ephemeral, 5gb swap expected_usage = 25 self.assertEqual(expected_usage, resources['DISK_GB']) - # Ensure the compute node is reporting the correct disk usage - self.assertEqual( - expected_usage, - self.admin_api.get_hypervisor_stats()['local_gb_used']) + # Ensure the compute node is reporting the correct disk usage. We're + # using v2.87 explicitly as the api returns 404 starting with 2.88 + with nova_utils.temporary_mutation(self.api, microversion='2.87'): + self.assertEqual( + expected_usage, + self.admin_api.get_hypervisor_stats()['local_gb_used']) # Now let's hack the RequestSpec.is_bfv field to mimic migrating an # old instance created before RequestSpec.is_bfv was set in the API, diff --git a/nova/tests/unit/api/openstack/compute/test_hypervisors.py b/nova/tests/unit/api/openstack/compute/test_hypervisors.py index f46bca98b40..6dfb9a6220e 100644 --- a/nova/tests/unit/api/openstack/compute/test_hypervisors.py +++ b/nova/tests/unit/api/openstack/compute/test_hypervisors.py @@ -218,10 +218,11 @@ class HypervisorsTestV21(test.NoDBTestCase): state='up', status='enabled')] DETAIL_NULL_CPUINFO_DICT = {'': '', None: None} - def _get_request(self, use_admin_context, url=''): - return fakes.HTTPRequest.blank(url, - use_admin_context=use_admin_context, - version=self.api_version) + def _get_request(self, use_admin_context, url='', version=None): + return fakes.HTTPRequest.blank( + url, + use_admin_context=use_admin_context, + version=version or self.api_version) def _get_hyper_id(self): """Helper function to get the proper hypervisor id for a request @@ -542,7 +543,7 @@ def test_show_non_integer_id(self): req = self._get_request(True) self.assertRaises(exc.HTTPNotFound, self.controller.show, req, 'abc') - def test_show_withid(self): + def test_show_with_id(self): req = self._get_request(True) hyper_id = self._get_hyper_id() result = self.controller.show(req, hyper_id) @@ -552,7 +553,7 @@ def test_show_withid(self): def test_uptime(self): with mock.patch.object( self.controller.host_api, 'get_host_uptime', - return_value="fake uptime" + return_value='fake uptime', ) as mock_get_uptime: req = self._get_request(True) hyper_id = self._get_hyper_id() @@ -1161,45 +1162,16 @@ def test_search(self): req = self._get_request( use_admin_context=True, url='/os-hypervisors?hypervisor_hostname_pattern=shenzhen') - with mock.patch.object(self.controller.host_api, - 'compute_node_search_by_hypervisor', - return_value=objects.ComputeNodeList( - objects=[TEST_HYPERS_OBJ[0]])) as s: + with mock.patch.object( + self.controller.host_api, + 'compute_node_search_by_hypervisor', + return_value=objects.ComputeNodeList(objects=[TEST_HYPERS_OBJ[0]]) + ) as s: result = self.controller.detail(req) s.assert_called_once_with(req.environ['nova.context'], 'shenzhen') - expected = { - 'hypervisors': [ - {'cpu_info': {'arch': 'x86_64', - 'features': [], - 'model': '', - 'topology': {'cores': 1, - 'sockets': 1, - 'threads': 1}, - 'vendor': 'fake'}, - 'current_workload': 2, - 'disk_available_least': 100, - 'free_disk_gb': 125, - 'free_ram_mb': 5120, - 'host_ip': netaddr.IPAddress('1.1.1.1'), - 'hypervisor_hostname': 'hyper1', - 'hypervisor_type': 'xen', - 'hypervisor_version': 3, - 'id': TEST_HYPERS_OBJ[0].uuid, - 'local_gb': 250, - 'local_gb_used': 125, - 'memory_mb': 10240, - 'memory_mb_used': 5120, - 'running_vms': 2, - 'service': {'disabled_reason': None, - 'host': 'compute1', - 'id': TEST_SERVICES[0].uuid}, - 'state': 'up', - 'status': 'enabled', - 'vcpus': 4, - 'vcpus_used': 2} - ] - } + expected = {'hypervisors': [self.DETAIL_HYPERS_DICTS[0]]} + # There are no links when using the hypervisor_hostname_pattern # query string since we can't page using a pattern matcher. self.assertNotIn('hypervisors_links', result) @@ -1309,36 +1281,7 @@ def test_detail_pagination(self): link = ('http://localhost/v2/os-hypervisors/detail?limit=1&marker=%s' % TEST_HYPERS_OBJ[1].uuid) expected = { - 'hypervisors': [ - {'cpu_info': {'arch': 'x86_64', - 'features': [], - 'model': '', - 'topology': {'cores': 1, - 'sockets': 1, - 'threads': 1}, - 'vendor': 'fake'}, - 'current_workload': 2, - 'disk_available_least': 100, - 'free_disk_gb': 125, - 'free_ram_mb': 5120, - 'host_ip': netaddr.IPAddress('2.2.2.2'), - 'hypervisor_hostname': 'hyper2', - 'hypervisor_type': 'xen', - 'hypervisor_version': 3, - 'id': TEST_HYPERS_OBJ[1].uuid, - 'local_gb': 250, - 'local_gb_used': 125, - 'memory_mb': 10240, - 'memory_mb_used': 5120, - 'running_vms': 2, - 'service': {'disabled_reason': None, - 'host': 'compute2', - 'id': TEST_SERVICES[1].uuid}, - 'state': 'up', - 'status': 'enabled', - 'vcpus': 4, - 'vcpus_used': 2} - ], + 'hypervisors': [self.DETAIL_HYPERS_DICTS[1]], 'hypervisors_links': [{'href': link, 'rel': 'next'}] } self.assertEqual(expected, result) @@ -1446,12 +1389,15 @@ def _test_servers_with_no_server(self, func, version=None, **kwargs): """Tests GET APIs return 'servers' field in response even no servers on hypervisors. """ - with mock.patch.object(self.controller.host_api, - 'instance_get_all_by_host', - return_value=[]): - req = fakes.HTTPRequest.blank('/os-hypervisors?with_servers=1', - use_admin_context=True, - version=version or self.api_version) + with mock.patch.object( + self.controller.host_api, + 'instance_get_all_by_host', + return_value=[], + ): + req = self._get_request( + url='/os-hypervisors?with_servers=1', + use_admin_context=True, + version=version) result = func(req, **kwargs) return result @@ -1487,3 +1433,131 @@ def test_show_servers_with_empty_server_list(self): result = self._test_servers_with_no_server(self.controller.show, id=uuids.hyper1) self.assertEqual(0, len(result['hypervisor']['servers'])) + + +class HypervisorsTestV288(HypervisorsTestV275): + api_version = '2.88' + + DETAIL_HYPERS_DICTS = copy.deepcopy(HypervisorsTestV21.DETAIL_HYPERS_DICTS) + for hypervisor in DETAIL_HYPERS_DICTS: + for key in ( + 'cpu_info', 'current_workload', 'disk_available_least', + 'free_disk_gb', 'free_ram_mb', 'local_gb', 'local_gb_used', + 'memory_mb', 'memory_mb_used', 'running_vms', 'vcpus', + 'vcpus_used', + ): + del hypervisor[key] + hypervisor['uptime'] = 'fake uptime' + + def setUp(self): + super().setUp() + + self.controller.host_api.get_host_uptime = mock.MagicMock( + return_value='fake uptime') + + def test_view_hypervisor_detail_cpuinfo_empty_string(self): + # cpu_info is no longer included in the response, so skip this test + pass + + def test_view_hypervisor_detail_cpuinfo_none(self): + # cpu_info is no longer included in the response, so skip this test + pass + + def test_uptime(self): + req = self._get_request(True) + self.assertRaises( + exception.VersionNotFoundForAPIMethod, + self.controller.uptime, req) + + def test_uptime_old_version(self): + with mock.patch.object( + self.controller.host_api, 'get_host_uptime', + return_value='fake uptime', + ): + req = self._get_request(use_admin_context=True, version='2.87') + hyper_id = self._get_hyper_id() + + # no exception == pass + self.controller.uptime(req, hyper_id) + + def test_uptime_noid(self): + # the separate 'uptime' API has been removed, so skip this test + pass + + def test_uptime_not_implemented(self): + # the separate 'uptime' API has been removed, so skip this test + pass + + def test_uptime_implemented(self): + # the separate 'uptime' API has been removed, so skip this test + pass + + def test_uptime_integer_id(self): + # the separate 'uptime' API has been removed, so skip this test + pass + + def test_uptime_host_not_found(self): + # the separate 'uptime' API has been removed, so skip this test + pass + + def test_uptime_hypervisor_down(self): + # the separate 'uptime' API has been removed, so skip this test + pass + + def test_uptime_hypervisor_not_mapped_service_get(self): + # the separate 'uptime' API has been removed, so skip this test + pass + + def test_uptime_hypervisor_not_mapped(self): + # the separate 'uptime' API has been removed, so skip this test + pass + + def test_show_with_uptime_notimplemented(self): + with mock.patch.object( + self.controller.host_api, 'get_host_uptime', + side_effect=NotImplementedError, + ) as mock_get_uptime: + req = self._get_request(use_admin_context=True) + hyper_id = self._get_hyper_id() + + result = self.controller.show(req, hyper_id) + + expected_dict = copy.deepcopy(self.DETAIL_HYPERS_DICTS[0]) + expected_dict.update({'uptime': None}) + self.assertEqual({'hypervisor': expected_dict}, result) + self.assertEqual(1, mock_get_uptime.call_count) + + def test_show_with_uptime_hypervisor_down(self): + with mock.patch.object( + self.controller.host_api, 'get_host_uptime', + side_effect=exception.ComputeServiceUnavailable(host='dummy') + ) as mock_get_uptime: + req = self._get_request(use_admin_context=True) + hyper_id = self._get_hyper_id() + + result = self.controller.show(req, hyper_id) + + expected_dict = copy.deepcopy(self.DETAIL_HYPERS_DICTS[0]) + expected_dict.update({'uptime': None}) + self.assertEqual({'hypervisor': expected_dict}, result) + self.assertEqual(1, mock_get_uptime.call_count) + + def test_show_old_version(self): + # ensure things still work as expected here + req = self._get_request(use_admin_context=True, version='2.87') + hyper_id = self._get_hyper_id() + + result = self.controller.show(req, hyper_id) + + self.assertNotIn('uptime', result) + + def test_statistics(self): + req = self._get_request(use_admin_context=True) + self.assertRaises( + exception.VersionNotFoundForAPIMethod, + self.controller.statistics, req) + + def test_statistics_old_version(self): + req = self._get_request(use_admin_context=True, version='2.87') + # no exception == pass + self.controller.statistics(req) diff --git a/releasenotes/notes/microversion-2-88-7063636ed9c11a5d.yaml b/releasenotes/notes/microversion-2-88-7063636ed9c11a5d.yaml new file mode 100644 index 00000000000..b167cc7b585 --- /dev/null +++ b/releasenotes/notes/microversion-2-88-7063636ed9c11a5d.yaml @@ -0,0 +1,33 @@ +--- +deprecations: + - | + The 2.88 API microversion has been added. This microversion removes a + number of fields have been removed from the ``GET /os-hypervisors/detail`` + (detailed list) and ``GET /os-hypervisors/{hypervisor_id}`` (show) APIs:: + + - ``current_workload`` + - ``cpu_info`` + - ``vcpus`` + - ``vcpus_used`` + - ``free_disk_gb`` + - ``local_gb`` + - ``local_gb_used`` + - ``disk_available_least`` + - ``free_ram_mb`` + - ``memory_mb`` + - ``memory_mb_used`` + - ``running_vms`` + + The fields have been removed as the information they provided was + frequently misleading or outright wrong, and more accurate information can + now be queried from placement. + + In addition, the ``GET /os-hypervisors/statistics`` API, which provided a + summary view with just the fields listed above, has been removed entirely + and will now raise a HTTP 404 with microversion 2.88 or greater. + + Finally, the ``GET /os-hypervisors/{hypervisor}/uptime`` API, which + provided a similar response to the ``GET /os-hypervisors/{hypervisor}`` API + but with an additional ``uptime`` field, has been removed in favour of + including this field in the primary ``GET /os-hypervisors/{hypervisor}`` + API. diff --git a/tox.ini b/tox.ini index 05293e8f135..0f7b076e973 100644 --- a/tox.ini +++ b/tox.ini @@ -126,6 +126,7 @@ commands = {[testenv:functional]commands} [testenv:api-samples] +envdir = {toxworkdir}/functional setenv = {[testenv]setenv} GENERATE_SAMPLES=True