Skip to content

Commit aae95dc

Browse files
yongli-hemriedem
authored andcommitted
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
1 parent e43596c commit aae95dc

File tree

9 files changed

+153
-1
lines changed

9 files changed

+153
-1
lines changed

doc/source/cli/nova.rst

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,9 @@ nova usage
472472
'--os-compute-api-version' flag to show help
473473
message for proper version]
474474

475+
``server-topology``
476+
Retrieve NUMA topology of the given server.
477+
475478
``service-delete``
476479
Delete the service.
477480

@@ -3358,6 +3361,26 @@ version]
33583361
``<tags>``
33593362
Tag(s) to set.
33603363

3364+
.. _nova_server_topology:
3365+
3366+
nova server-topology
3367+
--------------------
3368+
3369+
.. code-block:: console
3370+
3371+
usage: nova server-topology <server>
3372+
3373+
Retrieve server NUMA topology information. Host specific fields are only
3374+
visible to users with the administrative role.
3375+
(Supported by API versions '2.78' - '2.latest')
3376+
3377+
.. versionadded:: 16.0.0
3378+
3379+
**Positional arguments:**
3380+
3381+
``<server>``
3382+
Name or ID of server.
3383+
33613384
.. _nova_service-delete:
33623385

33633386
nova service-delete

novaclient/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,4 @@
2525
# when client supported the max version, and bumped sequentially, otherwise
2626
# the client may break due to server side new version may include some
2727
# backward incompatible change.
28-
API_MAX_VERSION = api_versions.APIVersion("2.77")
28+
API_MAX_VERSION = api_versions.APIVersion("2.78")

novaclient/tests/unit/fixture_data/servers.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,10 @@ def setUp(self):
371371
self.requests_mock.delete(self.url('1234', 'os-interface', 'port-id'),
372372
headers=self.json_headers)
373373

374+
self.requests_mock.get(self.url('1234', 'topology'),
375+
json=v2_fakes.SERVER_TOPOLOGY,
376+
headers=self.json_headers)
377+
374378
# Testing with the following password and key
375379
#
376380
# Clear password: FooBar123

novaclient/tests/unit/v2/fakes.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,48 @@
5858
FAKE_SERVICE_UUID_1 = '75e9eabc-ed3b-4f11-8bba-add1e7e7e2de'
5959
FAKE_SERVICE_UUID_2 = '1f140183-c914-4ddf-8757-6df73028aa86'
6060

61+
SERVER_TOPOLOGY = {
62+
"nodes": [
63+
{
64+
"cpu_pinning": {
65+
"0": 0,
66+
"1": 5
67+
},
68+
"host_node": 0,
69+
"memory_mb": 1024,
70+
"siblings": [
71+
[
72+
0,
73+
1
74+
]
75+
],
76+
"vcpu_set": [
77+
0,
78+
1
79+
]
80+
},
81+
{
82+
"cpu_pinning": {
83+
"2": 1,
84+
"3": 8
85+
},
86+
"host_node": 1,
87+
"memory_mb": 2048,
88+
"siblings": [
89+
[
90+
2,
91+
3
92+
]
93+
],
94+
"vcpu_set": [
95+
2,
96+
3
97+
]
98+
}
99+
],
100+
"pagesize_kb": 4
101+
}
102+
61103

62104
class FakeClient(fakes.FakeClient, client.Client):
63105

@@ -738,6 +780,9 @@ def get_servers_1234_os_security_groups(self, **kw):
738780
'rules': []}]
739781
})
740782

783+
def get_servers_1234_topology(self, **kw):
784+
return 200, {}, SERVER_TOPOLOGY
785+
741786
#
742787
# Server password
743788
#

novaclient/tests/unit/v2/test_servers.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1875,3 +1875,27 @@ def test_unshelve_server_pre_277_fails_with_specified_az(self):
18751875
s, availability_zone='foo-az')
18761876
self.assertIn("unexpected keyword argument 'availability_zone'",
18771877
six.text_type(ex))
1878+
1879+
1880+
class ServersV278Test(ServersV273Test):
1881+
1882+
api_version = "2.78"
1883+
1884+
def test_get_server_topology(self):
1885+
s = self.cs.servers.get(1234)
1886+
topology = s.topology()
1887+
self.assert_request_id(topology, fakes.FAKE_REQUEST_ID_LIST)
1888+
self.assertIsNotNone(topology)
1889+
self.assert_called('GET', '/servers/1234/topology')
1890+
1891+
topology_from_manager = self.cs.servers.topology(1234)
1892+
self.assert_request_id(topology, fakes.FAKE_REQUEST_ID_LIST)
1893+
self.assertIsNotNone(topology_from_manager)
1894+
self.assert_called('GET', '/servers/1234/topology')
1895+
1896+
self.assertEqual(topology, topology_from_manager)
1897+
1898+
def test_get_server_topology_pre278(self):
1899+
self.cs.api_version = api_versions.APIVersion('2.77')
1900+
s = self.cs.servers.get(1234)
1901+
self.assertRaises(exceptions.VersionNotFoundForAPIMethod, s.topology)

novaclient/tests/unit/v2/test_shell.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2463,6 +2463,19 @@ def test_diagnostics(self):
24632463
self.run_command('diagnostics sample-server')
24642464
self.assert_called('GET', '/servers/1234/diagnostics')
24652465

2466+
def test_server_topology(self):
2467+
self.run_command('server-topology 1234', api_version='2.78')
2468+
self.assert_called('GET', '/servers/1234/topology')
2469+
self.run_command('server-topology sample-server', api_version='2.78')
2470+
self.assert_called('GET', '/servers/1234/topology')
2471+
2472+
def test_server_topology_pre278(self):
2473+
exp = self.assertRaises(SystemExit,
2474+
self.run_command,
2475+
'server-topology 1234',
2476+
api_version='2.77')
2477+
self.assertIn('2', six.text_type(exp))
2478+
24662479
def test_refresh_network(self):
24672480
self.run_command('refresh-network 1234')
24682481
self.assert_called('POST', '/os-server-external-events',

novaclient/v2/servers.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,11 @@ def diagnostics(self):
316316
"""Diagnostics -- Retrieve server diagnostics."""
317317
return self.manager.diagnostics(self)
318318

319+
@api_versions.wraps("2.78")
320+
def topology(self):
321+
"""Retrieve server topology."""
322+
return self.manager.topology(self)
323+
319324
@api_versions.wraps("2.0", "2.55")
320325
def migrate(self):
321326
"""
@@ -1286,6 +1291,19 @@ def diagnostics(self, server):
12861291
base.getid(server))
12871292
return base.TupleWithMeta((resp, body), resp)
12881293

1294+
@api_versions.wraps("2.78")
1295+
def topology(self, server):
1296+
"""
1297+
Retrieve server topology.
1298+
1299+
:param server: The :class:`Server` (or its ID) for which
1300+
topology to be returned
1301+
:returns: An instance of novaclient.base.DictWithMeta
1302+
"""
1303+
resp, body = self.api.client.get("/servers/%s/topology" %
1304+
base.getid(server))
1305+
return base.DictWithMeta(body, resp)
1306+
12891307
def _validate_create_nics(self, nics):
12901308
# nics are required with microversion 2.37+ and can be a string or list
12911309
if self.api_version > api_versions.APIVersion('2.36'):

novaclient/v2/shell.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2313,6 +2313,17 @@ def do_diagnostics(cs, args):
23132313
utils.print_dict(cs.servers.diagnostics(server)[1], wrap=80)
23142314

23152315

2316+
@api_versions.wraps("2.78")
2317+
@utils.arg('server', metavar='<server>', help=_('Name or ID of server.'))
2318+
def do_server_topology(cs, args):
2319+
"""Retrieve server topology."""
2320+
server = _find_server(cs, args.server)
2321+
# This prints a dict with only two properties: nodes and pagesize_kb
2322+
# nodes is a list of dicts so it does not print very well, it's just a
2323+
# json blob in the output.
2324+
utils.print_dict(cs.servers.topology(server), wrap=80)
2325+
2326+
23162327
@utils.arg(
23172328
'server', metavar='<server>',
23182329
help=_('Name or ID of a server for which the network cache should '
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
features:
3+
- |
4+
Added support for `microversion 2.78`_ which outputs the server NUMA
5+
topology information in the following command:
6+
7+
* ``nova server-topology``
8+
9+
And associated python API bindings:
10+
11+
* ``novaclient.v2.servers.Server.topology``
12+
* ``novaclient.v2.servers.ServerManager.topology``
13+
14+
.. _microversion 2.78: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id70

0 commit comments

Comments
 (0)