From f200799848831a00f350c324bb77c00efa50da1c Mon Sep 17 00:00:00 2001 From: Yongli He <yongli.he@intel.com> Date: Mon, 9 Sep 2019 13:56:30 +0800 Subject: [PATCH] compute: Add 'server show --topology' option Add support for compute microversion 2.78 by adding a '--topology' option to 'openstack server show' command that retrieves server NUMA information. Change-Id: Ie22979df2ea9082ca64a4d43b571bd4025684825 --- doc/source/cli/data/nova.csv | 1 + openstackclient/compute/v2/server.py | 46 +++++++++++++---- .../tests/unit/compute/v2/test_server.py | 49 +++++++++++++++++++ ...y-microversion-v2_78-3891fc67f767177e.yaml | 5 ++ 4 files changed, 92 insertions(+), 9 deletions(-) create mode 100644 releasenotes/notes/show-server-topology-microversion-v2_78-3891fc67f767177e.yaml diff --git a/doc/source/cli/data/nova.csv b/doc/source/cli/data/nova.csv index 872d6e09b2..2004007f8d 100644 --- a/doc/source/cli/data/nova.csv +++ b/doc/source/cli/data/nova.csv @@ -121,6 +121,7 @@ start,server start,Start the server(s). stop,server stop,Stop the server(s). suspend,server suspend,Suspend a server. trigger-crash-dump,server dump create,Trigger crash dump in an instance. +topology,openstack server show --topology,Retrieve server NUMA topology. unlock,server unlock,Unlock a server. unpause,server unpause,Unpause a server. unrescue,server unrescue,Restart the server from normal boot disk again. diff --git a/openstackclient/compute/v2/server.py b/openstackclient/compute/v2/server.py index ba0243ef3e..c1716e5be1 100644 --- a/openstackclient/compute/v2/server.py +++ b/openstackclient/compute/v2/server.py @@ -3383,7 +3383,8 @@ class ShelveServer(command.Command): class ShowServer(command.ShowOne): _description = _( "Show server details. Specify ``--os-compute-api-version 2.47`` " - "or higher to see the embedded flavor information for the server.") + "or higher to see the embedded flavor information for the server." + ) def get_parser(self, prog_name): parser = super(ShowServer, self).get_parser(prog_name) @@ -3392,18 +3393,29 @@ class ShowServer(command.ShowOne): metavar='<server>', help=_('Server (name or ID)'), ) - parser.add_argument( + # TODO(stephenfin): This should be a separate command, not a flag + diagnostics_group = parser.add_mutually_exclusive_group() + diagnostics_group.add_argument( '--diagnostics', action='store_true', default=False, help=_('Display server diagnostics information'), ) + diagnostics_group.add_argument( + '--topology', + action='store_true', + default=False, + help=_( + 'Include topology information in the output ' + '(supported by --os-compute-api-version 2.78 or above)' + ), + ) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute - server = utils.find_resource(compute_client.servers, - parsed_args.server) + server = utils.find_resource( + compute_client.servers, parsed_args.server) if parsed_args.diagnostics: (resp, data) = server.diagnostics() @@ -3412,10 +3424,26 @@ class ShowServer(command.ShowOne): "Error retrieving diagnostics data\n" )) return ({}, {}) - else: - data = _prep_server_detail(compute_client, - self.app.client_manager.image, server, - refresh=False) + return zip(*sorted(data.items())) + + topology = None + if parsed_args.topology: + if compute_client.api_version < api_versions.APIVersion('2.78'): + msg = _( + '--os-compute-api-version 2.78 or greater is required to ' + 'support the --topology option' + ) + raise exceptions.CommandError(msg) + + topology = server.topology() + + data = _prep_server_detail( + compute_client, self.app.client_manager.image, server, + refresh=False) + + if topology: + data['topology'] = format_columns.DictColumn(topology) + return zip(*sorted(data.items())) @@ -3731,7 +3759,7 @@ class UnsetServer(command.Command): help=_( 'Tag to remove from the server. ' 'Specify multiple times to remove multiple tags. ' - '(supported by --os-compute-api-version 2.26 or later' + '(supported by --os-compute-api-version 2.26 or above)' ), ) return parser diff --git a/openstackclient/tests/unit/compute/v2/test_server.py b/openstackclient/tests/unit/compute/v2/test_server.py index efc105e565..8c3bf317e0 100644 --- a/openstackclient/tests/unit/compute/v2/test_server.py +++ b/openstackclient/tests/unit/compute/v2/test_server.py @@ -6285,6 +6285,10 @@ class TestServerShow(TestServer): self.image = image_fakes.FakeImage.create_one_image() self.flavor = compute_fakes.FakeFlavor.create_one_flavor() + self.topology = { + 'nodes': [{'vcpu_set': [0, 1]}, {'vcpu_set': [2, 3]}], + 'pagesize_kb': None, + } server_info = { 'image': {'id': self.image.id}, 'flavor': {'id': self.flavor.id}, @@ -6298,6 +6302,7 @@ class TestServerShow(TestServer): resp.status_code = 200 server_method = { 'diagnostics': (resp, {'test': 'test'}), + 'topology': self.topology, } self.server = compute_fakes.FakeServer.create_one_server( attrs=server_info, methods=server_method) @@ -6348,6 +6353,7 @@ class TestServerShow(TestServer): ] verifylist = [ ('diagnostics', False), + ('topology', False), ('server', self.server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -6365,6 +6371,7 @@ class TestServerShow(TestServer): ] verifylist = [ ('diagnostics', False), + ('topology', False), ('server', self.server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -6391,6 +6398,7 @@ class TestServerShow(TestServer): ] verifylist = [ ('diagnostics', True), + ('topology', False), ('server', self.server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -6400,6 +6408,47 @@ class TestServerShow(TestServer): self.assertEqual(('test',), columns) self.assertEqual(('test',), data) + def test_show_topology(self): + self.app.client_manager.compute.api_version = \ + api_versions.APIVersion('2.78') + + arglist = [ + '--topology', + self.server.name, + ] + verifylist = [ + ('diagnostics', False), + ('topology', True), + ('server', self.server.name), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + self.columns += ('topology',) + self.data += (format_columns.DictColumn(self.topology),) + + columns, data = self.cmd.take_action(parsed_args) + + self.assertCountEqual(self.columns, columns) + self.assertCountEqual(self.data, data) + + def test_show_topology_pre_v278(self): + self.app.client_manager.compute.api_version = \ + api_versions.APIVersion('2.77') + + arglist = [ + '--topology', + self.server.name, + ] + verifylist = [ + ('diagnostics', False), + ('topology', True), + ('server', self.server.name), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + self.assertRaises( + exceptions.CommandError, self.cmd.take_action, parsed_args) + class TestServerStart(TestServer): diff --git a/releasenotes/notes/show-server-topology-microversion-v2_78-3891fc67f767177e.yaml b/releasenotes/notes/show-server-topology-microversion-v2_78-3891fc67f767177e.yaml new file mode 100644 index 0000000000..0b48ed009c --- /dev/null +++ b/releasenotes/notes/show-server-topology-microversion-v2_78-3891fc67f767177e.yaml @@ -0,0 +1,5 @@ +--- +features: + - | + Add support for ``openstack server show --topology`` flag, which will + include NUMA topology information in the output.