summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Finucane <stephenfin@redhat.com>2020-09-29 17:32:56 +0100
committerStephen Finucane <stephenfin@redhat.com>2021-01-08 10:10:21 +0000
commit1f67ce24961a156dba56cacc75cbdd0800a7feee (patch)
tree0bb74f06d411299270524ac844e00c89886eea1b
parentef7598ac2896d08a89e50ccb82a47244e63d6248 (diff)
downloadnova-1f67ce24961a156dba56cacc75cbdd0800a7feee.tar.gz
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 <stephenfin@redhat.com>
-rw-r--r--api-ref/source/os-hypervisors.inc52
-rw-r--r--api-ref/source/parameters.yaml66
-rw-r--r--doc/api_samples/os-hypervisors/v2.88/hypervisors-detail-resp.json25
-rw-r--r--doc/api_samples/os-hypervisors/v2.88/hypervisors-detail-with-servers-resp.json29
-rw-r--r--doc/api_samples/os-hypervisors/v2.88/hypervisors-list-resp.json16
-rw-r--r--doc/api_samples/os-hypervisors/v2.88/hypervisors-search-resp.json10
-rw-r--r--doc/api_samples/os-hypervisors/v2.88/hypervisors-show-resp.json17
-rw-r--r--doc/api_samples/os-hypervisors/v2.88/hypervisors-show-with-servers-resp.json27
-rw-r--r--doc/api_samples/os-hypervisors/v2.88/hypervisors-with-servers-resp.json20
-rw-r--r--doc/api_samples/versions/v21-version-get-resp.json2
-rw-r--r--doc/api_samples/versions/versions-get-resp.json2
-rw-r--r--nova/api/openstack/api_version_request.py6
-rw-r--r--nova/api/openstack/compute/hypervisors.py108
-rw-r--r--nova/api/openstack/compute/rest_api_version_history.rst35
-rw-r--r--nova/tests/functional/api_sample_tests/api_samples/os-hypervisors/v2.88/hypervisors-detail-resp.json.tpl25
-rw-r--r--nova/tests/functional/api_sample_tests/api_samples/os-hypervisors/v2.88/hypervisors-detail-with-servers-resp.json.tpl29
-rw-r--r--nova/tests/functional/api_sample_tests/api_samples/os-hypervisors/v2.88/hypervisors-list-resp.json.tpl16
-rw-r--r--nova/tests/functional/api_sample_tests/api_samples/os-hypervisors/v2.88/hypervisors-search-resp.json.tpl10
-rw-r--r--nova/tests/functional/api_sample_tests/api_samples/os-hypervisors/v2.88/hypervisors-show-resp.json.tpl17
-rw-r--r--nova/tests/functional/api_sample_tests/api_samples/os-hypervisors/v2.88/hypervisors-show-with-servers-resp.json.tpl27
-rw-r--r--nova/tests/functional/api_sample_tests/api_samples/os-hypervisors/v2.88/hypervisors-with-servers-resp.json.tpl20
-rw-r--r--nova/tests/functional/api_sample_tests/api_samples/os-hypervisors/v2.88/hypervisors-without-servers-resp.json.tpl10
-rw-r--r--nova/tests/functional/api_sample_tests/test_hypervisors.py18
-rw-r--r--nova/tests/functional/test_servers.py20
-rw-r--r--nova/tests/unit/api/openstack/compute/test_hypervisors.py230
-rw-r--r--releasenotes/notes/microversion-2-88-7063636ed9c11a5d.yaml33
-rw-r--r--tox.ini1
27 files changed, 722 insertions, 149 deletions
diff --git a/api-ref/source/os-hypervisors.inc b/api-ref/source/os-hypervisors.inc
index 84e67e60cd..6363b409b4 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 cc36fcbe8a..13fbc541aa 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 0000000000..a009a125ff
--- /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 0000000000..26526b18cc
--- /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 0000000000..7c042bf8fa
--- /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 0000000000..6190e428bd
--- /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 0000000000..d1e566d6eb
--- /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 0000000000..0196b9ca5e
--- /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 0000000000..abaea1ffd4
--- /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 abfbcf4f35..80b3f33532 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 0e870df3ae..68c6ec8a2a 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 037b01124b..456e19e403 100644
--- a/nova/api/openstack/api_version_request.py
+++ b/nova/api/openstack/api_version_request.py
@@ -236,6 +236,10 @@ REST_API_VERSION_HISTORY = """REST API Version History:
``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 @@ 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.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 8232fd9f4f..63908bc81c 100644
--- a/nova/api/openstack/compute/hypervisors.py
+++ b/nova/api/openstack/compute/hypervisors.py
@@ -49,57 +49,85 @@ class HypervisorsController(wsgi.Controller):
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 @@ class HypervisorsController(wsgi.Controller):
'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 @@ class HypervisorsController(wsgi.Controller):
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 @@ class HypervisorsController(wsgi.Controller):
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 @@ class HypervisorsController(wsgi.Controller):
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 1390f05b34..0e142c6eaa 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 0000000000..3f1e1ed863
--- /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 0000000000..bc079ae7dc
--- /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 0000000000..53371fb91f
--- /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 0000000000..52846dc132
--- /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 0000000000..a2ed1b18ae
--- /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 0000000000..778e0b4f13
--- /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 0000000000..925839ec7a
--- /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 0000000000..89d27fed08
--- /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 ce4ca354d3..f402f9ebde 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 @@ class HypervisorsSampleJson253Tests(HypervisorsSampleJson228Tests):
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 3f23b8ed92..4277fbd1dc 100644
--- a/nova/tests/functional/test_servers.py
+++ b/nova/tests/functional/test_servers.py
@@ -3956,10 +3956,12 @@ class VolumeBackedServerTest(integrated_helpers.ProviderUsageBaseTestCase):
# 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 @@ class VolumeBackedServerTest(integrated_helpers.ProviderUsageBaseTestCase):
# 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 f46bca98b4..6dfb9a6220 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 @@ class HypervisorsTestV21(test.NoDBTestCase):
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 @@ class HypervisorsTestV21(test.NoDBTestCase):
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 @@ class HypervisorsTestV253(HypervisorsTestV252):
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 @@ class HypervisorsTestV253(HypervisorsTestV252):
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 @@ class HypervisorsTestV275(HypervisorsTestV253):
"""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 @@ class HypervisorsTestV275(HypervisorsTestV253):
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 0000000000..b167cc7b58
--- /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 05293e8f13..0f7b076e97 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