diff --git a/openstackclient/compute/v2/hypervisor.py b/openstackclient/compute/v2/hypervisor.py index 7f110028b6..8fdb66983c 100644 --- a/openstackclient/compute/v2/hypervisor.py +++ b/openstackclient/compute/v2/hypervisor.py @@ -15,9 +15,12 @@ """Hypervisor action implementations""" +import json import re +from novaclient import api_versions from novaclient import exceptions as nova_exceptions +from osc_lib.cli import format_columns from osc_lib.command import command from osc_lib import utils @@ -86,8 +89,8 @@ class ShowHypervisor(command.ShowOne): if aggregates: # Hypervisors in nova cells are prefixed by "@" if "@" in hypervisor['service']['host']: - cell, service_host = hypervisor['service']['host'].split('@', - 1) + cell, service_host = hypervisor['service']['host'].split( + '@', 1) else: cell = None service_host = hypervisor['service']['host'] @@ -125,4 +128,19 @@ class ShowHypervisor(command.ShowOne): hypervisor["service_host"] = hypervisor["service"]["host"] del hypervisor["service"] - return zip(*sorted(hypervisor.items())) + if compute_client.api_version < api_versions.APIVersion('2.28'): + # microversion 2.28 transformed this to a JSON blob rather than a + # string; on earlier fields, do this manually + if hypervisor['cpu_info']: + hypervisor['cpu_info'] = json.loads(hypervisor['cpu_info']) + else: + hypervisor['cpu_info'] = {} + + columns = tuple(sorted(hypervisor)) + data = utils.get_dict_properties( + hypervisor, columns, + formatters={ + 'cpu_info': format_columns.DictColumn, + }) + + return (columns, data) diff --git a/openstackclient/tests/unit/compute/v2/test_hypervisor.py b/openstackclient/tests/unit/compute/v2/test_hypervisor.py index 7200d04ed8..518109c6b0 100644 --- a/openstackclient/tests/unit/compute/v2/test_hypervisor.py +++ b/openstackclient/tests/unit/compute/v2/test_hypervisor.py @@ -14,8 +14,11 @@ # import copy +import json +from novaclient import api_versions from novaclient import exceptions as nova_exceptions +from osc_lib.cli import format_columns from osc_lib import exceptions from openstackclient.compute.v2 import hypervisor @@ -247,7 +250,7 @@ class TestHypervisorShow(TestHypervisor): ) self.data = ( [], - {'aaa': 'aaa'}, + format_columns.DictColumn({'aaa': 'aaa'}), 0, 50, 50, @@ -278,6 +281,9 @@ class TestHypervisorShow(TestHypervisor): self.cmd = hypervisor.ShowHypervisor(self.app, None) def test_hypervisor_show(self): + self.app.client_manager.compute.api_version = \ + api_versions.APIVersion('2.28') + arglist = [ self.hypervisor.hypervisor_hostname, ] @@ -292,9 +298,38 @@ class TestHypervisorShow(TestHypervisor): columns, data = self.cmd.take_action(parsed_args) self.assertEqual(self.columns, columns) - self.assertEqual(self.data, data) + self.assertItemsEqual(self.data, data) + + def test_hypervisor_show_pre_v228(self): + self.app.client_manager.compute.api_version = \ + api_versions.APIVersion('2.27') + + # before microversion 2.28, nova returned a stringified version of this + # field + self.hypervisor._info['cpu_info'] = json.dumps( + self.hypervisor._info['cpu_info']) + self.hypervisors_mock.get.return_value = self.hypervisor + + arglist = [ + self.hypervisor.hypervisor_hostname, + ] + verifylist = [ + ('hypervisor', self.hypervisor.hypervisor_hostname), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # In base command class ShowOne in cliff, abstract method take_action() + # returns a two-part tuple with a tuple of column names and a tuple of + # data to be shown. + columns, data = self.cmd.take_action(parsed_args) + + self.assertEqual(self.columns, columns) + self.assertItemsEqual(self.data, data) + + def test_hypervisor_show_uptime_not_implemented(self): + self.app.client_manager.compute.api_version = \ + api_versions.APIVersion('2.28') - def test_hyprvisor_show_uptime_not_implemented(self): arglist = [ self.hypervisor.hypervisor_hostname, ] @@ -337,7 +372,7 @@ class TestHypervisorShow(TestHypervisor): ) expected_data = ( [], - {'aaa': 'aaa'}, + format_columns.DictColumn({'aaa': 'aaa'}), 0, 50, 50, @@ -361,4 +396,4 @@ class TestHypervisorShow(TestHypervisor): ) self.assertEqual(expected_columns, columns) - self.assertEqual(expected_data, data) + self.assertItemsEqual(expected_data, data) diff --git a/releasenotes/notes/improved-server-output-6965b664f6abda8d.yaml b/releasenotes/notes/improved-server-output-6965b664f6abda8d.yaml index 5dc2980c77..305e915e61 100644 --- a/releasenotes/notes/improved-server-output-6965b664f6abda8d.yaml +++ b/releasenotes/notes/improved-server-output-6965b664f6abda8d.yaml @@ -18,3 +18,6 @@ fixes: The ``policies`` (or ``policy``, on newer microversions) and ``members`` fields of the ``server group list`` and ``server group show`` commands will now be rendered correctly as lists. + - | + The ``cpu_info`` field of the ``hypervisor show`` output is now + correctly decoded and output as an object.