Add 'Host Status' to 'server list --long' with >= v2.16
Currently, the 'Host Status' field is shown only for 'server show' but not for 'server list'. The host_status can be helpful for users who are having issues with servers that show a status of ACTIVE, as it can show a hint about the compute host status when nova policy is configured to allow it. Story: 2009689 Task: 44003 Change-Id: I6209cf52044218b7b32ab2fa5712574f12ba2f5f
This commit is contained in:
parent
9fc9e8d9d7
commit
93578ef85b
openstackclient
releasenotes/notes
@ -2569,6 +2569,21 @@ class ListServer(command.Lister):
|
|||||||
else:
|
else:
|
||||||
s.security_groups_name = []
|
s.security_groups_name = []
|
||||||
|
|
||||||
|
# The host_status field contains the status of the compute host the
|
||||||
|
# server is on. It is only returned by the API when the nova-api
|
||||||
|
# policy allows. Users can look at the host_status field when, for
|
||||||
|
# example, their server has status ACTIVE but is unresponsive. The
|
||||||
|
# host_status field can indicate a possible problem on the host
|
||||||
|
# it's on, providing useful information to a user in this
|
||||||
|
# situation.
|
||||||
|
if (
|
||||||
|
compute_client.api_version >= api_versions.APIVersion('2.16') and
|
||||||
|
parsed_args.long
|
||||||
|
):
|
||||||
|
if any([hasattr(s, 'host_status') for s in data]):
|
||||||
|
columns += ('Host Status',)
|
||||||
|
column_headers += ('Host Status',)
|
||||||
|
|
||||||
table = (
|
table = (
|
||||||
column_headers,
|
column_headers,
|
||||||
(
|
(
|
||||||
|
@ -4885,6 +4885,99 @@ class TestServerList(_TestServerList):
|
|||||||
self.assertEqual(self.columns, columns)
|
self.assertEqual(self.columns, columns)
|
||||||
self.assertEqual(tuple(self.data), tuple(data))
|
self.assertEqual(tuple(self.data), tuple(data))
|
||||||
|
|
||||||
|
def test_server_list_long_with_host_status_v216(self):
|
||||||
|
self.app.client_manager.compute.api_version = \
|
||||||
|
api_versions.APIVersion('2.16')
|
||||||
|
|
||||||
|
self.data1 = tuple(
|
||||||
|
(
|
||||||
|
s.id,
|
||||||
|
s.name,
|
||||||
|
s.status,
|
||||||
|
getattr(s, 'OS-EXT-STS:task_state'),
|
||||||
|
server.PowerStateColumn(
|
||||||
|
getattr(s, 'OS-EXT-STS:power_state')
|
||||||
|
),
|
||||||
|
format_columns.DictListColumn(s.networks),
|
||||||
|
# Image will be an empty string if boot-from-volume
|
||||||
|
self.image.name if s.image else server.IMAGE_STRING_FOR_BFV,
|
||||||
|
s.image['id'] if s.image else server.IMAGE_STRING_FOR_BFV,
|
||||||
|
self.flavor.name,
|
||||||
|
s.flavor['id'],
|
||||||
|
getattr(s, 'OS-EXT-AZ:availability_zone'),
|
||||||
|
getattr(s, 'OS-EXT-SRV-ATTR:host'),
|
||||||
|
s.Metadata,
|
||||||
|
) for s in self.servers)
|
||||||
|
|
||||||
|
arglist = [
|
||||||
|
'--long'
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('long', True),
|
||||||
|
]
|
||||||
|
|
||||||
|
# First test without host_status in the data -- the column should not
|
||||||
|
# be present in this case.
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
self.servers_mock.list.assert_called_with(**self.kwargs)
|
||||||
|
|
||||||
|
self.assertEqual(self.columns_long, columns)
|
||||||
|
self.assertEqual(tuple(self.data1), tuple(data))
|
||||||
|
|
||||||
|
# Next test with host_status in the data -- the column should be
|
||||||
|
# present in this case.
|
||||||
|
self.servers_mock.reset_mock()
|
||||||
|
|
||||||
|
self.attrs['host_status'] = 'UP'
|
||||||
|
servers = self.setup_servers_mock(3)
|
||||||
|
self.servers_mock.list.return_value = servers
|
||||||
|
|
||||||
|
# Make sure the returned image and flavor IDs match the servers.
|
||||||
|
Image = collections.namedtuple('Image', 'id name')
|
||||||
|
self.images_mock.return_value = [
|
||||||
|
Image(id=s.image['id'], name=self.image.name)
|
||||||
|
# Image will be an empty string if boot-from-volume
|
||||||
|
for s in servers if s.image
|
||||||
|
]
|
||||||
|
|
||||||
|
Flavor = collections.namedtuple('Flavor', 'id name')
|
||||||
|
self.flavors_mock.list.return_value = [
|
||||||
|
Flavor(id=s.flavor['id'], name=self.flavor.name)
|
||||||
|
for s in servers
|
||||||
|
]
|
||||||
|
|
||||||
|
# Add the expected host_status column and data.
|
||||||
|
columns_long = self.columns_long + ('Host Status',)
|
||||||
|
self.data2 = tuple(
|
||||||
|
(
|
||||||
|
s.id,
|
||||||
|
s.name,
|
||||||
|
s.status,
|
||||||
|
getattr(s, 'OS-EXT-STS:task_state'),
|
||||||
|
server.PowerStateColumn(
|
||||||
|
getattr(s, 'OS-EXT-STS:power_state')
|
||||||
|
),
|
||||||
|
format_columns.DictListColumn(s.networks),
|
||||||
|
# Image will be an empty string if boot-from-volume
|
||||||
|
self.image.name if s.image else server.IMAGE_STRING_FOR_BFV,
|
||||||
|
s.image['id'] if s.image else server.IMAGE_STRING_FOR_BFV,
|
||||||
|
self.flavor.name,
|
||||||
|
s.flavor['id'],
|
||||||
|
getattr(s, 'OS-EXT-AZ:availability_zone'),
|
||||||
|
getattr(s, 'OS-EXT-SRV-ATTR:host'),
|
||||||
|
s.Metadata,
|
||||||
|
s.host_status,
|
||||||
|
) for s in servers)
|
||||||
|
|
||||||
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
self.servers_mock.list.assert_called_with(**self.kwargs)
|
||||||
|
|
||||||
|
self.assertEqual(columns_long, columns)
|
||||||
|
self.assertEqual(tuple(self.data2), tuple(data))
|
||||||
|
|
||||||
|
|
||||||
class TestServerListV273(_TestServerList):
|
class TestServerListV273(_TestServerList):
|
||||||
|
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
The ``server list`` command will now display ``Host Status`` when the
|
||||||
|
``--long`` option is specified and the compute API microversion is 2.16 or
|
||||||
|
greater.
|
Loading…
x
Reference in New Issue
Block a user