Add support for microversion v2.88
The key change here is that the 'GET /os-hypervisors/{id}/uptime' API will now returns a HTTP 404 starting in 2.88. The 'GET /os-hypervisors/{id}' will instead now include an 'uptime' value. The 'novaclient.v2.hypervisors.HypervisorManager.uptime' method is updated to handle this. Change-Id: Ib99fbd820a586c14527ff64b319df0b7a44e1b8b Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
This commit is contained in:
parent
e459539278
commit
54d4da112a
@ -25,4 +25,4 @@ API_MIN_VERSION = api_versions.APIVersion("2.1")
|
|||||||
# when client supported the max version, and bumped sequentially, otherwise
|
# when client supported the max version, and bumped sequentially, otherwise
|
||||||
# the client may break due to server side new version may include some
|
# the client may break due to server side new version may include some
|
||||||
# backward incompatible change.
|
# backward incompatible change.
|
||||||
API_MAX_VERSION = api_versions.APIVersion("2.87")
|
API_MAX_VERSION = api_versions.APIVersion("2.88")
|
||||||
|
@ -27,15 +27,41 @@ class V1(base.Fixture):
|
|||||||
service_id_1 = 1
|
service_id_1 = 1
|
||||||
service_id_2 = 2
|
service_id_2 = 2
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _transform_hypervisor_details(hypervisor):
|
||||||
|
"""Transform a detailed hypervisor view from 2.53 to 2.88."""
|
||||||
|
del hypervisor['current_workload']
|
||||||
|
del hypervisor['disk_available_least']
|
||||||
|
del hypervisor['free_ram_mb']
|
||||||
|
del hypervisor['free_disk_gb']
|
||||||
|
del hypervisor['local_gb']
|
||||||
|
del hypervisor['local_gb_used']
|
||||||
|
del hypervisor['memory_mb']
|
||||||
|
del hypervisor['memory_mb_used']
|
||||||
|
del hypervisor['running_vms']
|
||||||
|
del hypervisor['vcpus']
|
||||||
|
del hypervisor['vcpus_used']
|
||||||
|
hypervisor['uptime'] = 'fake uptime'
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(V1, self).setUp()
|
super(V1, self).setUp()
|
||||||
uuid_as_id = (api_versions.APIVersion(self.api_version) >=
|
|
||||||
api_versions.APIVersion('2.53'))
|
api_version = api_versions.APIVersion(self.api_version)
|
||||||
|
|
||||||
get_os_hypervisors = {
|
get_os_hypervisors = {
|
||||||
'hypervisors': [
|
'hypervisors': [
|
||||||
{'id': self.hyper_id_1, 'hypervisor_hostname': 'hyper1'},
|
{
|
||||||
{'id': self.hyper_id_2, 'hypervisor_hostname': 'hyper2'},
|
'id': self.hyper_id_1,
|
||||||
|
'hypervisor_hostname': 'hyper1',
|
||||||
|
'state': 'up',
|
||||||
|
'status': 'enabled',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'id': self.hyper_id_2,
|
||||||
|
'hypervisor_hostname': 'hyper2',
|
||||||
|
'state': 'up',
|
||||||
|
'status': 'enabled',
|
||||||
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,7 +93,9 @@ class V1(base.Fixture):
|
|||||||
'current_workload': 2,
|
'current_workload': 2,
|
||||||
'running_vms': 2,
|
'running_vms': 2,
|
||||||
'cpu_info': 'cpu_info',
|
'cpu_info': 'cpu_info',
|
||||||
'disk_available_least': 100
|
'disk_available_least': 100,
|
||||||
|
'state': 'up',
|
||||||
|
'status': 'enabled',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'id': self.hyper_id_2,
|
'id': self.hyper_id_2,
|
||||||
@ -89,11 +117,17 @@ class V1(base.Fixture):
|
|||||||
'current_workload': 2,
|
'current_workload': 2,
|
||||||
'running_vms': 2,
|
'running_vms': 2,
|
||||||
'cpu_info': 'cpu_info',
|
'cpu_info': 'cpu_info',
|
||||||
'disk_available_least': 100
|
'disk_available_least': 100,
|
||||||
|
'state': 'up',
|
||||||
|
'status': 'enabled',
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if api_version >= api_versions.APIVersion('2.88'):
|
||||||
|
for hypervisor in get_os_hypervisors_detail['hypervisors']:
|
||||||
|
self._transform_hypervisor_details(hypervisor)
|
||||||
|
|
||||||
self.requests_mock.get(self.url('detail'),
|
self.requests_mock.get(self.url('detail'),
|
||||||
json=get_os_hypervisors_detail,
|
json=get_os_hypervisors_detail,
|
||||||
headers=self.headers)
|
headers=self.headers)
|
||||||
@ -121,12 +155,22 @@ class V1(base.Fixture):
|
|||||||
|
|
||||||
get_os_hypervisors_search = {
|
get_os_hypervisors_search = {
|
||||||
'hypervisors': [
|
'hypervisors': [
|
||||||
{'id': self.hyper_id_1, 'hypervisor_hostname': 'hyper1'},
|
{
|
||||||
{'id': self.hyper_id_2, 'hypervisor_hostname': 'hyper2'}
|
'id': self.hyper_id_1,
|
||||||
|
'hypervisor_hostname': 'hyper1',
|
||||||
|
'state': 'up',
|
||||||
|
'status': 'enabled',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'id': self.hyper_id_2,
|
||||||
|
'hypervisor_hostname': 'hyper2',
|
||||||
|
'state': 'up',
|
||||||
|
'status': 'enabled',
|
||||||
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
if uuid_as_id:
|
if api_version >= api_versions.APIVersion('2.53'):
|
||||||
url = self.url(hypervisor_hostname_pattern='hyper')
|
url = self.url(hypervisor_hostname_pattern='hyper')
|
||||||
else:
|
else:
|
||||||
url = self.url('hyper', 'search')
|
url = self.url('hyper', 'search')
|
||||||
@ -134,7 +178,7 @@ class V1(base.Fixture):
|
|||||||
json=get_os_hypervisors_search,
|
json=get_os_hypervisors_search,
|
||||||
headers=self.headers)
|
headers=self.headers)
|
||||||
|
|
||||||
if uuid_as_id:
|
if api_version >= api_versions.APIVersion('2.53'):
|
||||||
get_os_hypervisors_search_u_v2_53 = {
|
get_os_hypervisors_search_u_v2_53 = {
|
||||||
'error_name': 'BadRequest',
|
'error_name': 'BadRequest',
|
||||||
'message': 'Invalid input for query parameters '
|
'message': 'Invalid input for query parameters '
|
||||||
@ -164,6 +208,8 @@ class V1(base.Fixture):
|
|||||||
{
|
{
|
||||||
'id': self.hyper_id_1,
|
'id': self.hyper_id_1,
|
||||||
'hypervisor_hostname': 'hyper1',
|
'hypervisor_hostname': 'hyper1',
|
||||||
|
'state': 'up',
|
||||||
|
'status': 'enabled',
|
||||||
'servers': [
|
'servers': [
|
||||||
{'name': 'inst1', 'uuid': 'uuid1'},
|
{'name': 'inst1', 'uuid': 'uuid1'},
|
||||||
{'name': 'inst2', 'uuid': 'uuid2'}
|
{'name': 'inst2', 'uuid': 'uuid2'}
|
||||||
@ -172,6 +218,8 @@ class V1(base.Fixture):
|
|||||||
{
|
{
|
||||||
'id': self.hyper_id_2,
|
'id': self.hyper_id_2,
|
||||||
'hypervisor_hostname': 'hyper2',
|
'hypervisor_hostname': 'hyper2',
|
||||||
|
'state': 'up',
|
||||||
|
'status': 'enabled',
|
||||||
'servers': [
|
'servers': [
|
||||||
{'name': 'inst3', 'uuid': 'uuid3'},
|
{'name': 'inst3', 'uuid': 'uuid3'},
|
||||||
{'name': 'inst4', 'uuid': 'uuid4'}
|
{'name': 'inst4', 'uuid': 'uuid4'}
|
||||||
@ -180,7 +228,7 @@ class V1(base.Fixture):
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
if uuid_as_id:
|
if api_version >= api_versions.APIVersion('2.53'):
|
||||||
url = self.url(hypervisor_hostname_pattern='hyper',
|
url = self.url(hypervisor_hostname_pattern='hyper',
|
||||||
with_servers=True)
|
with_servers=True)
|
||||||
else:
|
else:
|
||||||
@ -207,10 +255,16 @@ class V1(base.Fixture):
|
|||||||
'current_workload': 2,
|
'current_workload': 2,
|
||||||
'running_vms': 2,
|
'running_vms': 2,
|
||||||
'cpu_info': 'cpu_info',
|
'cpu_info': 'cpu_info',
|
||||||
'disk_available_least': 100
|
'disk_available_least': 100,
|
||||||
|
'state': 'up',
|
||||||
|
'status': 'enabled',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if api_version >= api_versions.APIVersion('2.88'):
|
||||||
|
self._transform_hypervisor_details(
|
||||||
|
get_os_hypervisors_hyper1['hypervisor'])
|
||||||
|
|
||||||
self.requests_mock.get(self.url(self.hyper_id_1),
|
self.requests_mock.get(self.url(self.hyper_id_1),
|
||||||
json=get_os_hypervisors_hyper1,
|
json=get_os_hypervisors_hyper1,
|
||||||
headers=self.headers)
|
headers=self.headers)
|
||||||
@ -219,7 +273,9 @@ class V1(base.Fixture):
|
|||||||
'hypervisor': {
|
'hypervisor': {
|
||||||
'id': self.hyper_id_1,
|
'id': self.hyper_id_1,
|
||||||
'hypervisor_hostname': 'hyper1',
|
'hypervisor_hostname': 'hyper1',
|
||||||
'uptime': 'fake uptime'
|
'uptime': 'fake uptime',
|
||||||
|
'state': 'up',
|
||||||
|
'status': 'enabled',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,10 +284,15 @@ class V1(base.Fixture):
|
|||||||
headers=self.headers)
|
headers=self.headers)
|
||||||
|
|
||||||
|
|
||||||
class V2_53(V1):
|
class V253(V1):
|
||||||
"""Fixture data for the os-hypervisors 2.53 API."""
|
"""Fixture data for the os-hypervisors 2.53 API."""
|
||||||
api_version = '2.53'
|
api_version = '2.53'
|
||||||
hyper_id_1 = 'd480b1b6-2255-43c2-b2c2-d60d42c2c074'
|
hyper_id_1 = 'd480b1b6-2255-43c2-b2c2-d60d42c2c074'
|
||||||
hyper_id_2 = '43a8214d-f36a-4fc0-a25c-3cf35c17522d'
|
hyper_id_2 = '43a8214d-f36a-4fc0-a25c-3cf35c17522d'
|
||||||
service_id_1 = 'a87743ff-9c29-42ff-805d-2444659b5fc0'
|
service_id_1 = 'a87743ff-9c29-42ff-805d-2444659b5fc0'
|
||||||
service_id_2 = '0486ab8b-1cfc-4ccb-9d94-9f22ec8bbd6b'
|
service_id_2 = '0486ab8b-1cfc-4ccb-9d94-9f22ec8bbd6b'
|
||||||
|
|
||||||
|
|
||||||
|
class V288(V253):
|
||||||
|
"""Fixture data for the os-hypervisors 2.88 API."""
|
||||||
|
api_version = '2.88'
|
||||||
|
@ -63,7 +63,9 @@ class HypervisorsTest(utils.FixturedTestCase):
|
|||||||
current_workload=2,
|
current_workload=2,
|
||||||
running_vms=2,
|
running_vms=2,
|
||||||
cpu_info='cpu_info',
|
cpu_info='cpu_info',
|
||||||
disk_available_least=100),
|
disk_available_least=100,
|
||||||
|
state='up',
|
||||||
|
status='enabled'),
|
||||||
dict(id=self.data_fixture.hyper_id_2,
|
dict(id=self.data_fixture.hyper_id_2,
|
||||||
service=dict(id=self.data_fixture.service_id_2,
|
service=dict(id=self.data_fixture.service_id_2,
|
||||||
host="compute2"),
|
host="compute2"),
|
||||||
@ -81,7 +83,24 @@ class HypervisorsTest(utils.FixturedTestCase):
|
|||||||
current_workload=2,
|
current_workload=2,
|
||||||
running_vms=2,
|
running_vms=2,
|
||||||
cpu_info='cpu_info',
|
cpu_info='cpu_info',
|
||||||
disk_available_least=100)]
|
disk_available_least=100,
|
||||||
|
state='up',
|
||||||
|
status='enabled')]
|
||||||
|
|
||||||
|
if self.cs.api_version >= api_versions.APIVersion('2.88'):
|
||||||
|
for hypervisor in expected:
|
||||||
|
del hypervisor['current_workload']
|
||||||
|
del hypervisor['disk_available_least']
|
||||||
|
del hypervisor['free_ram_mb']
|
||||||
|
del hypervisor['free_disk_gb']
|
||||||
|
del hypervisor['local_gb']
|
||||||
|
del hypervisor['local_gb_used']
|
||||||
|
del hypervisor['memory_mb']
|
||||||
|
del hypervisor['memory_mb_used']
|
||||||
|
del hypervisor['running_vms']
|
||||||
|
del hypervisor['vcpus']
|
||||||
|
del hypervisor['vcpus_used']
|
||||||
|
hypervisor['uptime'] = 'fake uptime'
|
||||||
|
|
||||||
result = self.cs.hypervisors.list()
|
result = self.cs.hypervisors.list()
|
||||||
self.assert_request_id(result, fakes.FAKE_REQUEST_ID_LIST)
|
self.assert_request_id(result, fakes.FAKE_REQUEST_ID_LIST)
|
||||||
@ -93,9 +112,13 @@ class HypervisorsTest(utils.FixturedTestCase):
|
|||||||
def test_hypervisor_search(self):
|
def test_hypervisor_search(self):
|
||||||
expected = [
|
expected = [
|
||||||
dict(id=self.data_fixture.hyper_id_1,
|
dict(id=self.data_fixture.hyper_id_1,
|
||||||
hypervisor_hostname='hyper1'),
|
hypervisor_hostname='hyper1',
|
||||||
|
state='up',
|
||||||
|
status='enabled'),
|
||||||
dict(id=self.data_fixture.hyper_id_2,
|
dict(id=self.data_fixture.hyper_id_2,
|
||||||
hypervisor_hostname='hyper2')]
|
hypervisor_hostname='hyper2',
|
||||||
|
state='up',
|
||||||
|
status='enabled')]
|
||||||
|
|
||||||
result = self.cs.hypervisors.search('hyper')
|
result = self.cs.hypervisors.search('hyper')
|
||||||
self.assert_request_id(result, fakes.FAKE_REQUEST_ID_LIST)
|
self.assert_request_id(result, fakes.FAKE_REQUEST_ID_LIST)
|
||||||
@ -131,11 +154,15 @@ class HypervisorsTest(utils.FixturedTestCase):
|
|||||||
expected = [
|
expected = [
|
||||||
dict(id=self.data_fixture.hyper_id_1,
|
dict(id=self.data_fixture.hyper_id_1,
|
||||||
hypervisor_hostname='hyper1',
|
hypervisor_hostname='hyper1',
|
||||||
|
state='up',
|
||||||
|
status='enabled',
|
||||||
servers=[
|
servers=[
|
||||||
dict(name='inst1', uuid='uuid1'),
|
dict(name='inst1', uuid='uuid1'),
|
||||||
dict(name='inst2', uuid='uuid2')]),
|
dict(name='inst2', uuid='uuid2')]),
|
||||||
dict(id=self.data_fixture.hyper_id_2,
|
dict(id=self.data_fixture.hyper_id_2,
|
||||||
hypervisor_hostname='hyper2',
|
hypervisor_hostname='hyper2',
|
||||||
|
state='up',
|
||||||
|
status='enabled',
|
||||||
servers=[
|
servers=[
|
||||||
dict(name='inst3', uuid='uuid3'),
|
dict(name='inst3', uuid='uuid3'),
|
||||||
dict(name='inst4', uuid='uuid4')]),
|
dict(name='inst4', uuid='uuid4')]),
|
||||||
@ -171,7 +198,23 @@ class HypervisorsTest(utils.FixturedTestCase):
|
|||||||
current_workload=2,
|
current_workload=2,
|
||||||
running_vms=2,
|
running_vms=2,
|
||||||
cpu_info='cpu_info',
|
cpu_info='cpu_info',
|
||||||
disk_available_least=100)
|
disk_available_least=100,
|
||||||
|
state='up',
|
||||||
|
status='enabled')
|
||||||
|
|
||||||
|
if self.cs.api_version >= api_versions.APIVersion('2.88'):
|
||||||
|
del expected['current_workload']
|
||||||
|
del expected['disk_available_least']
|
||||||
|
del expected['free_ram_mb']
|
||||||
|
del expected['free_disk_gb']
|
||||||
|
del expected['local_gb']
|
||||||
|
del expected['local_gb_used']
|
||||||
|
del expected['memory_mb']
|
||||||
|
del expected['memory_mb_used']
|
||||||
|
del expected['running_vms']
|
||||||
|
del expected['vcpus']
|
||||||
|
del expected['vcpus_used']
|
||||||
|
expected['uptime'] = 'fake uptime'
|
||||||
|
|
||||||
result = self.cs.hypervisors.get(self.data_fixture.hyper_id_1)
|
result = self.cs.hypervisors.get(self.data_fixture.hyper_id_1)
|
||||||
self.assert_request_id(result, fakes.FAKE_REQUEST_ID_LIST)
|
self.assert_request_id(result, fakes.FAKE_REQUEST_ID_LIST)
|
||||||
@ -184,7 +227,9 @@ class HypervisorsTest(utils.FixturedTestCase):
|
|||||||
expected = dict(
|
expected = dict(
|
||||||
id=self.data_fixture.hyper_id_1,
|
id=self.data_fixture.hyper_id_1,
|
||||||
hypervisor_hostname="hyper1",
|
hypervisor_hostname="hyper1",
|
||||||
uptime="fake uptime")
|
uptime="fake uptime",
|
||||||
|
state='up',
|
||||||
|
status='enabled')
|
||||||
|
|
||||||
result = self.cs.hypervisors.uptime(self.data_fixture.hyper_id_1)
|
result = self.cs.hypervisors.uptime(self.data_fixture.hyper_id_1)
|
||||||
self.assert_request_id(result, fakes.FAKE_REQUEST_ID_LIST)
|
self.assert_request_id(result, fakes.FAKE_REQUEST_ID_LIST)
|
||||||
@ -215,11 +260,6 @@ class HypervisorsTest(utils.FixturedTestCase):
|
|||||||
|
|
||||||
self.compare_to_expected(expected, result)
|
self.compare_to_expected(expected, result)
|
||||||
|
|
||||||
def test_hypervisor_statistics_data_model(self):
|
|
||||||
result = self.cs.hypervisor_stats.statistics()
|
|
||||||
self.assert_request_id(result, fakes.FAKE_REQUEST_ID_LIST)
|
|
||||||
self.assert_called('GET', '/os-hypervisors/statistics')
|
|
||||||
|
|
||||||
# Test for Bug #1370415, the line below used to raise AttributeError
|
# Test for Bug #1370415, the line below used to raise AttributeError
|
||||||
self.assertEqual("<HypervisorStats: 2 Hypervisors>",
|
self.assertEqual("<HypervisorStats: 2 Hypervisors>",
|
||||||
result.__repr__())
|
result.__repr__())
|
||||||
@ -237,19 +277,23 @@ class HypervisorsV233Test(HypervisorsTest):
|
|||||||
self.assertEqual([v], self.requests_mock.last_request.qs[k])
|
self.assertEqual([v], self.requests_mock.last_request.qs[k])
|
||||||
|
|
||||||
|
|
||||||
class HypervisorsV2_53Test(HypervisorsV233Test):
|
class HypervisorsV253Test(HypervisorsV233Test):
|
||||||
"""Tests the os-hypervisors 2.53 API bindings."""
|
"""Tests the os-hypervisors 2.53 API bindings."""
|
||||||
data_fixture_class = data.V2_53
|
data_fixture_class = data.V253
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(HypervisorsV2_53Test, self).setUp()
|
super(HypervisorsV253Test, self).setUp()
|
||||||
self.cs.api_version = api_versions.APIVersion("2.53")
|
self.cs.api_version = api_versions.APIVersion("2.53")
|
||||||
|
|
||||||
def test_hypervisor_search_detailed(self):
|
def test_hypervisor_search_detailed(self):
|
||||||
expected = [
|
expected = [
|
||||||
dict(id=self.data_fixture.hyper_id_1,
|
dict(id=self.data_fixture.hyper_id_1,
|
||||||
|
state='up',
|
||||||
|
status='enabled',
|
||||||
hypervisor_hostname='hyper1'),
|
hypervisor_hostname='hyper1'),
|
||||||
dict(id=self.data_fixture.hyper_id_2,
|
dict(id=self.data_fixture.hyper_id_2,
|
||||||
|
state='up',
|
||||||
|
status='enabled',
|
||||||
hypervisor_hostname='hyper2')]
|
hypervisor_hostname='hyper2')]
|
||||||
result = self.cs.hypervisors.search('hyper', detailed=True)
|
result = self.cs.hypervisors.search('hyper', detailed=True)
|
||||||
self.assert_request_id(result, fakes.FAKE_REQUEST_ID_LIST)
|
self.assert_request_id(result, fakes.FAKE_REQUEST_ID_LIST)
|
||||||
@ -257,3 +301,35 @@ class HypervisorsV2_53Test(HypervisorsV233Test):
|
|||||||
'GET', '/os-hypervisors/detail?hypervisor_hostname_pattern=hyper')
|
'GET', '/os-hypervisors/detail?hypervisor_hostname_pattern=hyper')
|
||||||
for idx, hyper in enumerate(result):
|
for idx, hyper in enumerate(result):
|
||||||
self.compare_to_expected(expected[idx], hyper)
|
self.compare_to_expected(expected[idx], hyper)
|
||||||
|
|
||||||
|
|
||||||
|
class HypervisorsV288Test(HypervisorsV253Test):
|
||||||
|
data_fixture_class = data.V288
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super().setUp()
|
||||||
|
self.cs.api_version = api_versions.APIVersion('2.88')
|
||||||
|
|
||||||
|
def test_hypervisor_uptime(self):
|
||||||
|
expected = {
|
||||||
|
'id': self.data_fixture.hyper_id_1,
|
||||||
|
'hypervisor_hostname': 'hyper1',
|
||||||
|
'uptime': 'fake uptime',
|
||||||
|
'state': 'up',
|
||||||
|
'status': 'enabled',
|
||||||
|
}
|
||||||
|
|
||||||
|
result = self.cs.hypervisors.uptime(self.data_fixture.hyper_id_1)
|
||||||
|
self.assert_request_id(result, fakes.FAKE_REQUEST_ID_LIST)
|
||||||
|
self.assert_called(
|
||||||
|
'GET', '/os-hypervisors/%s' % self.data_fixture.hyper_id_1)
|
||||||
|
|
||||||
|
self.compare_to_expected(expected, result)
|
||||||
|
|
||||||
|
def test_hypervisor_statistics(self):
|
||||||
|
exc = self.assertRaises(
|
||||||
|
exceptions.UnsupportedVersion,
|
||||||
|
self.cs.hypervisor_stats.statistics)
|
||||||
|
self.assertIn(
|
||||||
|
"The 'statistics' API is removed in API version 2.88 or later.",
|
||||||
|
str(exc))
|
||||||
|
@ -3575,6 +3575,16 @@ class ShellTest(utils.TestCase):
|
|||||||
self.run_command('hypervisor-stats')
|
self.run_command('hypervisor-stats')
|
||||||
self.assert_called('GET', '/os-hypervisors/statistics')
|
self.assert_called('GET', '/os-hypervisors/statistics')
|
||||||
|
|
||||||
|
def test_hypervisor_stats_v2_88(self):
|
||||||
|
"""Tests nova hypervisor-stats at the 2.88 microversion."""
|
||||||
|
ex = self.assertRaises(
|
||||||
|
exceptions.CommandError, self.run_command,
|
||||||
|
'hypervisor-stats', api_version='2.88')
|
||||||
|
self.assertIn(
|
||||||
|
'The hypervisor-stats command is not supported in API version '
|
||||||
|
'2.88 or later.',
|
||||||
|
str(ex))
|
||||||
|
|
||||||
def test_quota_show(self):
|
def test_quota_show(self):
|
||||||
self.run_command(
|
self.run_command(
|
||||||
'quota-show --tenant '
|
'quota-show --tenant '
|
||||||
|
@ -123,8 +123,25 @@ class HypervisorManager(base.ManagerWithFind):
|
|||||||
:param hypervisor: Either a Hypervisor object or an ID. Starting with
|
:param hypervisor: Either a Hypervisor object or an ID. Starting with
|
||||||
microversion 2.53 the ID must be a UUID value.
|
microversion 2.53 the ID must be a UUID value.
|
||||||
"""
|
"""
|
||||||
return self._get("/os-hypervisors/%s/uptime" % base.getid(hypervisor),
|
# Starting with microversion 2.88, the '/os-hypervisors/{id}/uptime'
|
||||||
"hypervisor")
|
# route is removed in favour of returning 'uptime' in the response of
|
||||||
|
# the '/os-hypervisors/{id}' route. This behaves slightly differently,
|
||||||
|
# in that it won't error out if a virt driver doesn't support reporting
|
||||||
|
# uptime or if the hypervisor is down, but it's a good enough
|
||||||
|
# approximation
|
||||||
|
if self.api_version < api_versions.APIVersion("2.88"):
|
||||||
|
return self._get(
|
||||||
|
"/os-hypervisors/%s/uptime" % base.getid(hypervisor),
|
||||||
|
"hypervisor")
|
||||||
|
|
||||||
|
resp, body = self.api.client.get(
|
||||||
|
"/os-hypervisors/%s" % base.getid(hypervisor)
|
||||||
|
)
|
||||||
|
content = {
|
||||||
|
k: v for k, v in body['hypervisor'].items()
|
||||||
|
if k in ('id', 'hypervisor_hostname', 'state', 'status', 'uptime')
|
||||||
|
}
|
||||||
|
return self.resource_class(self, content, loaded=True, resp=resp)
|
||||||
|
|
||||||
def statistics(self):
|
def statistics(self):
|
||||||
"""
|
"""
|
||||||
@ -145,8 +162,15 @@ class HypervisorStats(base.Resource):
|
|||||||
class HypervisorStatsManager(base.Manager):
|
class HypervisorStatsManager(base.Manager):
|
||||||
resource_class = HypervisorStats
|
resource_class = HypervisorStats
|
||||||
|
|
||||||
|
@api_versions.wraps("2.0", "2.87")
|
||||||
def statistics(self):
|
def statistics(self):
|
||||||
"""
|
"""
|
||||||
Get hypervisor statistics over all compute nodes.
|
Get hypervisor statistics over all compute nodes.
|
||||||
"""
|
"""
|
||||||
return self._get("/os-hypervisors/statistics", "hypervisor_statistics")
|
return self._get("/os-hypervisors/statistics", "hypervisor_statistics")
|
||||||
|
|
||||||
|
@api_versions.wraps("2.88")
|
||||||
|
def statistics(self):
|
||||||
|
raise exceptions.UnsupportedVersion(
|
||||||
|
_("The 'statistics' API is removed in API version 2.88 or later.")
|
||||||
|
)
|
||||||
|
@ -4049,12 +4049,22 @@ def do_hypervisor_uptime(cs, args):
|
|||||||
utils.print_dict(hyper.to_dict())
|
utils.print_dict(hyper.to_dict())
|
||||||
|
|
||||||
|
|
||||||
|
@api_versions.wraps('2.0', '2.87')
|
||||||
def do_hypervisor_stats(cs, args):
|
def do_hypervisor_stats(cs, args):
|
||||||
"""Get hypervisor statistics over all compute nodes."""
|
"""Get hypervisor statistics over all compute nodes."""
|
||||||
stats = cs.hypervisor_stats.statistics()
|
stats = cs.hypervisor_stats.statistics()
|
||||||
utils.print_dict(stats.to_dict())
|
utils.print_dict(stats.to_dict())
|
||||||
|
|
||||||
|
|
||||||
|
@api_versions.wraps('2.88')
|
||||||
|
def do_hypervisor_stats(cs, args):
|
||||||
|
msg = _(
|
||||||
|
"The hypervisor-stats command is not supported in API version 2.88 "
|
||||||
|
"or later."
|
||||||
|
)
|
||||||
|
raise exceptions.CommandError(msg)
|
||||||
|
|
||||||
|
|
||||||
@utils.arg('server', metavar='<server>', help=_('Name or ID of server.'))
|
@utils.arg('server', metavar='<server>', help=_('Name or ID of server.'))
|
||||||
@utils.arg(
|
@utils.arg(
|
||||||
'--port',
|
'--port',
|
||||||
|
16
releasenotes/notes/microversion-v2_88-d91136020e3a3621.yaml
Normal file
16
releasenotes/notes/microversion-v2_88-d91136020e3a3621.yaml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Added support for `microversion 2.88`_. The
|
||||||
|
``novaclient.v2.hypervisors.HypervisorManager.uptime`` method will now
|
||||||
|
transparently switch between the ``/os-hypervisors/{id}/uptime`` API,
|
||||||
|
which is deprecated in 2.88, and the ``/os-hypervisors/{id}`` API, which
|
||||||
|
now includes uptime information, based on the microversion.
|
||||||
|
|
||||||
|
.. _microversion 2.88: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id80
|
||||||
|
deprecations:
|
||||||
|
- |
|
||||||
|
The ``nova hypervisor-stats`` command and underlying
|
||||||
|
``novaclient.v2.hypervisors.HypervisorStatsManager.statistics`` API are
|
||||||
|
deprecated starting in microversion 2.88 and will return an error starting
|
||||||
|
on this version.
|
Loading…
Reference in New Issue
Block a user