Skip to content

Commit bf834f6

Browse files
committed
compute: Fix 'hypervisor show -f yaml' output
The 'cpu_info' field returned by the 'os-hypervisors' API is an object and should be formatted as such. However, this is complicated by the fact that the object in this field is stringified until microversion 2.28 and is only returned as an actual object on later microversions. Handle the conversion from the string for older microversions and display things correctly for all releases. Change-Id: Ide31466cbb9e89c96d6bd542fe039ab5ed1fac1f Signed-off-by: Stephen Finucane <sfinucan@redhat.com>
1 parent e2a9a96 commit bf834f6

3 files changed

Lines changed: 64 additions & 8 deletions

File tree

openstackclient/compute/v2/hypervisor.py

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,12 @@
1515

1616
"""Hypervisor action implementations"""
1717

18+
import json
1819
import re
1920

21+
from novaclient import api_versions
2022
from novaclient import exceptions as nova_exceptions
23+
from osc_lib.cli import format_columns
2124
from osc_lib.command import command
2225
from osc_lib import utils
2326

@@ -86,8 +89,8 @@ def take_action(self, parsed_args):
8689
if aggregates:
8790
# Hypervisors in nova cells are prefixed by "<cell>@"
8891
if "@" in hypervisor['service']['host']:
89-
cell, service_host = hypervisor['service']['host'].split('@',
90-
1)
92+
cell, service_host = hypervisor['service']['host'].split(
93+
'@', 1)
9194
else:
9295
cell = None
9396
service_host = hypervisor['service']['host']
@@ -125,4 +128,19 @@ def take_action(self, parsed_args):
125128
hypervisor["service_host"] = hypervisor["service"]["host"]
126129
del hypervisor["service"]
127130

128-
return zip(*sorted(hypervisor.items()))
131+
if compute_client.api_version < api_versions.APIVersion('2.28'):
132+
# microversion 2.28 transformed this to a JSON blob rather than a
133+
# string; on earlier fields, do this manually
134+
if hypervisor['cpu_info']:
135+
hypervisor['cpu_info'] = json.loads(hypervisor['cpu_info'])
136+
else:
137+
hypervisor['cpu_info'] = {}
138+
139+
columns = tuple(sorted(hypervisor))
140+
data = utils.get_dict_properties(
141+
hypervisor, columns,
142+
formatters={
143+
'cpu_info': format_columns.DictColumn,
144+
})
145+
146+
return (columns, data)

openstackclient/tests/unit/compute/v2/test_hypervisor.py

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,11 @@
1414
#
1515

1616
import copy
17+
import json
1718

19+
from novaclient import api_versions
1820
from novaclient import exceptions as nova_exceptions
21+
from osc_lib.cli import format_columns
1922
from osc_lib import exceptions
2023

2124
from openstackclient.compute.v2 import hypervisor
@@ -247,7 +250,7 @@ def setUp(self):
247250
)
248251
self.data = (
249252
[],
250-
{'aaa': 'aaa'},
253+
format_columns.DictColumn({'aaa': 'aaa'}),
251254
0,
252255
50,
253256
50,
@@ -278,6 +281,35 @@ def setUp(self):
278281
self.cmd = hypervisor.ShowHypervisor(self.app, None)
279282

280283
def test_hypervisor_show(self):
284+
self.app.client_manager.compute.api_version = \
285+
api_versions.APIVersion('2.28')
286+
287+
arglist = [
288+
self.hypervisor.hypervisor_hostname,
289+
]
290+
verifylist = [
291+
('hypervisor', self.hypervisor.hypervisor_hostname),
292+
]
293+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
294+
295+
# In base command class ShowOne in cliff, abstract method take_action()
296+
# returns a two-part tuple with a tuple of column names and a tuple of
297+
# data to be shown.
298+
columns, data = self.cmd.take_action(parsed_args)
299+
300+
self.assertEqual(self.columns, columns)
301+
self.assertItemsEqual(self.data, data)
302+
303+
def test_hypervisor_show_pre_v228(self):
304+
self.app.client_manager.compute.api_version = \
305+
api_versions.APIVersion('2.27')
306+
307+
# before microversion 2.28, nova returned a stringified version of this
308+
# field
309+
self.hypervisor._info['cpu_info'] = json.dumps(
310+
self.hypervisor._info['cpu_info'])
311+
self.hypervisors_mock.get.return_value = self.hypervisor
312+
281313
arglist = [
282314
self.hypervisor.hypervisor_hostname,
283315
]
@@ -292,9 +324,12 @@ def test_hypervisor_show(self):
292324
columns, data = self.cmd.take_action(parsed_args)
293325

294326
self.assertEqual(self.columns, columns)
295-
self.assertEqual(self.data, data)
327+
self.assertItemsEqual(self.data, data)
328+
329+
def test_hypervisor_show_uptime_not_implemented(self):
330+
self.app.client_manager.compute.api_version = \
331+
api_versions.APIVersion('2.28')
296332

297-
def test_hyprvisor_show_uptime_not_implemented(self):
298333
arglist = [
299334
self.hypervisor.hypervisor_hostname,
300335
]
@@ -337,7 +372,7 @@ def test_hyprvisor_show_uptime_not_implemented(self):
337372
)
338373
expected_data = (
339374
[],
340-
{'aaa': 'aaa'},
375+
format_columns.DictColumn({'aaa': 'aaa'}),
341376
0,
342377
50,
343378
50,
@@ -361,4 +396,4 @@ def test_hyprvisor_show_uptime_not_implemented(self):
361396
)
362397

363398
self.assertEqual(expected_columns, columns)
364-
self.assertEqual(expected_data, data)
399+
self.assertItemsEqual(expected_data, data)

releasenotes/notes/improved-server-output-6965b664f6abda8d.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,6 @@ fixes:
1818
The ``policies`` (or ``policy``, on newer microversions) and ``members``
1919
fields of the ``server group list`` and ``server group show`` commands
2020
will now be rendered correctly as lists.
21+
- |
22+
The ``cpu_info`` field of the ``hypervisor show`` output is now
23+
correctly decoded and output as an object.

0 commit comments

Comments
 (0)