Fix 'server event list|show' for deleted servers

As of compute microversion >= 2.21, support for list and show of server
events for deleted servers was added. This however wasn't working using
the openstackclient because the compute GET /servers/{server_id} will
not return a deleted server, so osc_lib.utils.find_resource() fails to
find the server and the command bails early.

This adds a check for a uuid-like <server> arg and uses it directly if
the <server> cannot be found via find_resource().

A note is also added to the command help to indicate that list and show
for deleted servers will only work if a server ID is passed (name will
not work).

Story: 2009841
Task: 44443

Change-Id: Icd33b3b9a3a1855d7893dd111bbb2aca059f45fd
This commit is contained in:
melanie witt 2022-02-09 19:48:42 +00:00
parent 27843fc232
commit 72a2477ec0
2 changed files with 64 additions and 9 deletions

View File

@ -19,6 +19,7 @@ import logging
import iso8601
from novaclient import api_versions
import openstack.cloud._utils
from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
@ -33,7 +34,7 @@ class ListServerEvent(command.Lister):
"""List recent events of a server.
Specify ``--os-compute-api-version 2.21`` or higher to show events for a
deleted server.
deleted server, specified by ID only.
"""
def get_parser(self, prog_name):
@ -143,9 +144,18 @@ class ListServerEvent(command.Lister):
kwargs['changes_before'] = parsed_args.changes_before
server_id = utils.find_resource(
compute_client.servers, parsed_args.server,
).id
try:
server_id = utils.find_resource(
compute_client.servers, parsed_args.server,
).id
except exceptions.CommandError:
# If we fail to find the resource, it is possible the server is
# deleted. Try once more using the <server> arg directly if it is a
# UUID.
if openstack.cloud._utils._is_uuid_like(parsed_args.server):
server_id = parsed_args.server
else:
raise
data = compute_client.instance_action.list(server_id, **kwargs)
@ -184,8 +194,9 @@ class ShowServerEvent(command.ShowOne):
"""Show server event details.
Specify ``--os-compute-api-version 2.21`` or higher to show event details
for a deleted server. Specify ``--os-compute-api-version 2.51`` or higher
to show event details for non-admin users.
for a deleted server, specified by ID only. Specify
``--os-compute-api-version 2.51`` or higher to show event details for
non-admin users.
"""
def get_parser(self, prog_name):
@ -205,9 +216,18 @@ class ShowServerEvent(command.ShowOne):
def take_action(self, parsed_args):
compute_client = self.app.client_manager.compute
server_id = utils.find_resource(
compute_client.servers, parsed_args.server,
).id
try:
server_id = utils.find_resource(
compute_client.servers, parsed_args.server,
).id
except exceptions.CommandError:
# If we fail to find the resource, it is possible the server is
# deleted. Try once more using the <server> arg directly if it is a
# UUID.
if openstack.cloud._utils._is_uuid_like(parsed_args.server):
server_id = parsed_args.server
else:
raise
action_detail = compute_client.instance_action.get(
server_id, parsed_args.request_id

View File

@ -82,3 +82,38 @@ class ServerEventTests(common.ComputeTestCase):
self.assertEqual('reboot', cmd_output.get('action'))
self.assertIsNotNone(cmd_output.get('events'))
self.assertIsInstance(cmd_output.get('events'), list)
def test_server_event_list_and_show_deleted_server(self):
# Need to create a new server that will not attempt cleanup because we
# are going to delete it during the test and cleanup would fail with
# 404.
cmd_output = self.server_create(cleanup=False)
server_id = cmd_output['id']
# Delete the server
self.openstack('server delete --wait ' + server_id)
# And verify we can get the event list after it's deleted
# Test 'server event list' for deleting
cmd_output = json.loads(self.openstack(
'--os-compute-api-version 2.21 '
'server event list -f json ' + server_id
))
request_id = None
for each_event in cmd_output:
self.assertNotIn('Message', each_event)
self.assertNotIn('Project ID', each_event)
self.assertNotIn('User ID', each_event)
if each_event.get('Action') == 'delete':
self.assertEqual(server_id, each_event.get('Server ID'))
request_id = each_event.get('Request ID')
break
self.assertIsNotNone(request_id)
# Test 'server event show' for deleting
cmd_output = json.loads(self.openstack(
'--os-compute-api-version 2.21 '
'server event show -f json ' + server_id + ' ' + request_id
))
self.assertEqual(server_id, cmd_output.get('instance_uuid'))
self.assertEqual(request_id, cmd_output.get('request_id'))
self.assertEqual('delete', cmd_output.get('action'))
self.assertIsNotNone(cmd_output.get('events'))
self.assertIsInstance(cmd_output.get('events'), list)