Microversion 2.78 - show server topology
Add support microversion 2.78 which adds server topology information in the output of the following new command: nova server-topology Depends-on: https://review.opendev.org/#/c/621476/ Change-Id: I6467d52d2528a37348458baf4842b571a97f3ed2 Implements: blueprint show-server-numa-topology
This commit is contained in:
parent
e43596ca5c
commit
aae95dcc7a
@ -472,6 +472,9 @@ nova usage
|
||||
'--os-compute-api-version' flag to show help
|
||||
message for proper version]
|
||||
|
||||
``server-topology``
|
||||
Retrieve NUMA topology of the given server.
|
||||
|
||||
``service-delete``
|
||||
Delete the service.
|
||||
|
||||
@ -3358,6 +3361,26 @@ version]
|
||||
``<tags>``
|
||||
Tag(s) to set.
|
||||
|
||||
.. _nova_server_topology:
|
||||
|
||||
nova server-topology
|
||||
--------------------
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
usage: nova server-topology <server>
|
||||
|
||||
Retrieve server NUMA topology information. Host specific fields are only
|
||||
visible to users with the administrative role.
|
||||
(Supported by API versions '2.78' - '2.latest')
|
||||
|
||||
.. versionadded:: 16.0.0
|
||||
|
||||
**Positional arguments:**
|
||||
|
||||
``<server>``
|
||||
Name or ID of server.
|
||||
|
||||
.. _nova_service-delete:
|
||||
|
||||
nova service-delete
|
||||
|
@ -25,4 +25,4 @@ API_MIN_VERSION = api_versions.APIVersion("2.1")
|
||||
# when client supported the max version, and bumped sequentially, otherwise
|
||||
# the client may break due to server side new version may include some
|
||||
# backward incompatible change.
|
||||
API_MAX_VERSION = api_versions.APIVersion("2.77")
|
||||
API_MAX_VERSION = api_versions.APIVersion("2.78")
|
||||
|
@ -371,6 +371,10 @@ class V1(Base):
|
||||
self.requests_mock.delete(self.url('1234', 'os-interface', 'port-id'),
|
||||
headers=self.json_headers)
|
||||
|
||||
self.requests_mock.get(self.url('1234', 'topology'),
|
||||
json=v2_fakes.SERVER_TOPOLOGY,
|
||||
headers=self.json_headers)
|
||||
|
||||
# Testing with the following password and key
|
||||
#
|
||||
# Clear password: FooBar123
|
||||
|
@ -58,6 +58,48 @@ FAKE_RESPONSE_HEADERS = {'x-openstack-request-id': FAKE_REQUEST_ID}
|
||||
FAKE_SERVICE_UUID_1 = '75e9eabc-ed3b-4f11-8bba-add1e7e7e2de'
|
||||
FAKE_SERVICE_UUID_2 = '1f140183-c914-4ddf-8757-6df73028aa86'
|
||||
|
||||
SERVER_TOPOLOGY = {
|
||||
"nodes": [
|
||||
{
|
||||
"cpu_pinning": {
|
||||
"0": 0,
|
||||
"1": 5
|
||||
},
|
||||
"host_node": 0,
|
||||
"memory_mb": 1024,
|
||||
"siblings": [
|
||||
[
|
||||
0,
|
||||
1
|
||||
]
|
||||
],
|
||||
"vcpu_set": [
|
||||
0,
|
||||
1
|
||||
]
|
||||
},
|
||||
{
|
||||
"cpu_pinning": {
|
||||
"2": 1,
|
||||
"3": 8
|
||||
},
|
||||
"host_node": 1,
|
||||
"memory_mb": 2048,
|
||||
"siblings": [
|
||||
[
|
||||
2,
|
||||
3
|
||||
]
|
||||
],
|
||||
"vcpu_set": [
|
||||
2,
|
||||
3
|
||||
]
|
||||
}
|
||||
],
|
||||
"pagesize_kb": 4
|
||||
}
|
||||
|
||||
|
||||
class FakeClient(fakes.FakeClient, client.Client):
|
||||
|
||||
@ -738,6 +780,9 @@ class FakeSessionClient(base_client.SessionClient):
|
||||
'rules': []}]
|
||||
})
|
||||
|
||||
def get_servers_1234_topology(self, **kw):
|
||||
return 200, {}, SERVER_TOPOLOGY
|
||||
|
||||
#
|
||||
# Server password
|
||||
#
|
||||
|
@ -1875,3 +1875,27 @@ class ServersV277Test(ServersV274Test):
|
||||
s, availability_zone='foo-az')
|
||||
self.assertIn("unexpected keyword argument 'availability_zone'",
|
||||
six.text_type(ex))
|
||||
|
||||
|
||||
class ServersV278Test(ServersV273Test):
|
||||
|
||||
api_version = "2.78"
|
||||
|
||||
def test_get_server_topology(self):
|
||||
s = self.cs.servers.get(1234)
|
||||
topology = s.topology()
|
||||
self.assert_request_id(topology, fakes.FAKE_REQUEST_ID_LIST)
|
||||
self.assertIsNotNone(topology)
|
||||
self.assert_called('GET', '/servers/1234/topology')
|
||||
|
||||
topology_from_manager = self.cs.servers.topology(1234)
|
||||
self.assert_request_id(topology, fakes.FAKE_REQUEST_ID_LIST)
|
||||
self.assertIsNotNone(topology_from_manager)
|
||||
self.assert_called('GET', '/servers/1234/topology')
|
||||
|
||||
self.assertEqual(topology, topology_from_manager)
|
||||
|
||||
def test_get_server_topology_pre278(self):
|
||||
self.cs.api_version = api_versions.APIVersion('2.77')
|
||||
s = self.cs.servers.get(1234)
|
||||
self.assertRaises(exceptions.VersionNotFoundForAPIMethod, s.topology)
|
||||
|
@ -2463,6 +2463,19 @@ class ShellTest(utils.TestCase):
|
||||
self.run_command('diagnostics sample-server')
|
||||
self.assert_called('GET', '/servers/1234/diagnostics')
|
||||
|
||||
def test_server_topology(self):
|
||||
self.run_command('server-topology 1234', api_version='2.78')
|
||||
self.assert_called('GET', '/servers/1234/topology')
|
||||
self.run_command('server-topology sample-server', api_version='2.78')
|
||||
self.assert_called('GET', '/servers/1234/topology')
|
||||
|
||||
def test_server_topology_pre278(self):
|
||||
exp = self.assertRaises(SystemExit,
|
||||
self.run_command,
|
||||
'server-topology 1234',
|
||||
api_version='2.77')
|
||||
self.assertIn('2', six.text_type(exp))
|
||||
|
||||
def test_refresh_network(self):
|
||||
self.run_command('refresh-network 1234')
|
||||
self.assert_called('POST', '/os-server-external-events',
|
||||
|
@ -316,6 +316,11 @@ class Server(base.Resource):
|
||||
"""Diagnostics -- Retrieve server diagnostics."""
|
||||
return self.manager.diagnostics(self)
|
||||
|
||||
@api_versions.wraps("2.78")
|
||||
def topology(self):
|
||||
"""Retrieve server topology."""
|
||||
return self.manager.topology(self)
|
||||
|
||||
@api_versions.wraps("2.0", "2.55")
|
||||
def migrate(self):
|
||||
"""
|
||||
@ -1286,6 +1291,19 @@ class ServerManager(base.BootingManagerWithFind):
|
||||
base.getid(server))
|
||||
return base.TupleWithMeta((resp, body), resp)
|
||||
|
||||
@api_versions.wraps("2.78")
|
||||
def topology(self, server):
|
||||
"""
|
||||
Retrieve server topology.
|
||||
|
||||
:param server: The :class:`Server` (or its ID) for which
|
||||
topology to be returned
|
||||
:returns: An instance of novaclient.base.DictWithMeta
|
||||
"""
|
||||
resp, body = self.api.client.get("/servers/%s/topology" %
|
||||
base.getid(server))
|
||||
return base.DictWithMeta(body, resp)
|
||||
|
||||
def _validate_create_nics(self, nics):
|
||||
# nics are required with microversion 2.37+ and can be a string or list
|
||||
if self.api_version > api_versions.APIVersion('2.36'):
|
||||
|
@ -2313,6 +2313,17 @@ def do_diagnostics(cs, args):
|
||||
utils.print_dict(cs.servers.diagnostics(server)[1], wrap=80)
|
||||
|
||||
|
||||
@api_versions.wraps("2.78")
|
||||
@utils.arg('server', metavar='<server>', help=_('Name or ID of server.'))
|
||||
def do_server_topology(cs, args):
|
||||
"""Retrieve server topology."""
|
||||
server = _find_server(cs, args.server)
|
||||
# This prints a dict with only two properties: nodes and pagesize_kb
|
||||
# nodes is a list of dicts so it does not print very well, it's just a
|
||||
# json blob in the output.
|
||||
utils.print_dict(cs.servers.topology(server), wrap=80)
|
||||
|
||||
|
||||
@utils.arg(
|
||||
'server', metavar='<server>',
|
||||
help=_('Name or ID of a server for which the network cache should '
|
||||
|
14
releasenotes/notes/microversion-v2_78-77a12630e668c2ae.yaml
Normal file
14
releasenotes/notes/microversion-v2_78-77a12630e668c2ae.yaml
Normal file
@ -0,0 +1,14 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Added support for `microversion 2.78`_ which outputs the server NUMA
|
||||
topology information in the following command:
|
||||
|
||||
* ``nova server-topology``
|
||||
|
||||
And associated python API bindings:
|
||||
|
||||
* ``novaclient.v2.servers.Server.topology``
|
||||
* ``novaclient.v2.servers.ServerManager.topology``
|
||||
|
||||
.. _microversion 2.78: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id70
|
Loading…
Reference in New Issue
Block a user