summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYongli He <yongli.he@intel.com>2019-07-15 16:36:09 +0800
committerMatt Riedemann <mriedem.os@gmail.com>2019-09-06 17:24:17 -0400
commitaae95dcc7a79be019fc304ced76a351c16382ede (patch)
treebb2fa94b9ff6dab6da11c762060a515e8c8d45ce
parente43596ca5ce076ecbb53a6788349b46f2b3f5c39 (diff)
downloadpython-novaclient-aae95dcc7a79be019fc304ced76a351c16382ede.tar.gz
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
-rw-r--r--doc/source/cli/nova.rst23
-rw-r--r--novaclient/__init__.py2
-rw-r--r--novaclient/tests/unit/fixture_data/servers.py4
-rw-r--r--novaclient/tests/unit/v2/fakes.py45
-rw-r--r--novaclient/tests/unit/v2/test_servers.py24
-rw-r--r--novaclient/tests/unit/v2/test_shell.py13
-rw-r--r--novaclient/v2/servers.py18
-rw-r--r--novaclient/v2/shell.py11
-rw-r--r--releasenotes/notes/microversion-v2_78-77a12630e668c2ae.yaml14
9 files changed, 153 insertions, 1 deletions
diff --git a/doc/source/cli/nova.rst b/doc/source/cli/nova.rst
index dcd24be9..ab310758 100644
--- a/doc/source/cli/nova.rst
+++ b/doc/source/cli/nova.rst
@@ -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
diff --git a/novaclient/__init__.py b/novaclient/__init__.py
index 00e0b3e4..3e5daf21 100644
--- a/novaclient/__init__.py
+++ b/novaclient/__init__.py
@@ -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")
diff --git a/novaclient/tests/unit/fixture_data/servers.py b/novaclient/tests/unit/fixture_data/servers.py
index 9962842a..7e4ee64a 100644
--- a/novaclient/tests/unit/fixture_data/servers.py
+++ b/novaclient/tests/unit/fixture_data/servers.py
@@ -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
diff --git a/novaclient/tests/unit/v2/fakes.py b/novaclient/tests/unit/v2/fakes.py
index faf5f6f4..d6fbf129 100644
--- a/novaclient/tests/unit/v2/fakes.py
+++ b/novaclient/tests/unit/v2/fakes.py
@@ -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
#
diff --git a/novaclient/tests/unit/v2/test_servers.py b/novaclient/tests/unit/v2/test_servers.py
index 5ef987fa..c255cbd7 100644
--- a/novaclient/tests/unit/v2/test_servers.py
+++ b/novaclient/tests/unit/v2/test_servers.py
@@ -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)
diff --git a/novaclient/tests/unit/v2/test_shell.py b/novaclient/tests/unit/v2/test_shell.py
index 2dc8a38a..928a9de4 100644
--- a/novaclient/tests/unit/v2/test_shell.py
+++ b/novaclient/tests/unit/v2/test_shell.py
@@ -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',
diff --git a/novaclient/v2/servers.py b/novaclient/v2/servers.py
index acef7856..9870be0b 100644
--- a/novaclient/v2/servers.py
+++ b/novaclient/v2/servers.py
@@ -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'):
diff --git a/novaclient/v2/shell.py b/novaclient/v2/shell.py
index a08c8674..acaf1783 100644
--- a/novaclient/v2/shell.py
+++ b/novaclient/v2/shell.py
@@ -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 '
diff --git a/releasenotes/notes/microversion-v2_78-77a12630e668c2ae.yaml b/releasenotes/notes/microversion-v2_78-77a12630e668c2ae.yaml
new file mode 100644
index 00000000..17e6289e
--- /dev/null
+++ b/releasenotes/notes/microversion-v2_78-77a12630e668c2ae.yaml
@@ -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