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>
This commit is contained in:
Stephen Finucane 2020-09-29 17:32:56 +01:00
parent ef7598ac28
commit 1f67ce2496
27 changed files with 722 additions and 149 deletions

View File

@ -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

View File

@ -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

View File

@ -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"
}
]
}

View File

@ -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
}
]
}

View File

@ -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"
}
]
}

View File

@ -0,0 +1,10 @@
{
"hypervisors": [
{
"hypervisor_hostname": "fake-mini",
"id": "6b7876c5-9ae7-4fa7-a5c8-28c796d17381",
"state": "up",
"status": "enabled"
}
]
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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"
}
]
}

View File

@ -19,7 +19,7 @@
}
],
"status": "CURRENT",
"version": "2.87",
"version": "2.88",
"min_version": "2.1",
"updated": "2013-07-23T11:33:21Z"
}

View File

@ -22,7 +22,7 @@
}
],
"status": "CURRENT",
"version": "2.87",
"version": "2.88",
"min_version": "2.1",
"updated": "2013-07-23T11:33:21Z"
}

View File

@ -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

View File

@ -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,
}
}
if api_version_request.is_supported(req, min_version='2.28'):
# 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, 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)

View File

@ -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.

View File

@ -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"
}
]
}

View File

@ -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
}
]
}

View File

@ -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"
}
]
}

View File

@ -0,0 +1,10 @@
{
"hypervisors": [
{
"id": "%(hypervisor_id)s",
"state": "up",
"status": "enabled",
"hypervisor_hostname": "fake-mini"
}
]
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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"
}
]
}
]
}

View File

@ -0,0 +1,10 @@
{
"hypervisors": [
{
"id": "%(hypervisor_id)s",
"hypervisor_hostname": "fake-mini",
"status": "enabled",
"state": "up"
}
]
}

View File

@ -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)

View File

@ -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,

View File

@ -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)

View File

<
@ -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``