[microversions] Enable 2.21
2.21 - The os-instance-actions API now returns information from deleted instances. Change-Id: Iff514e4fa9135207c6f8e32e444d45b1b61d8c7c
This commit is contained in:
parent
ca5b06f6ae
commit
cd88097ff5
@ -25,4 +25,4 @@ API_MIN_VERSION = api_versions.APIVersion("2.1")
|
|||||||
# when client supported the max version, and bumped sequentially, otherwise
|
# when client supported the max version, and bumped sequentially, otherwise
|
||||||
# the client may break due to server side new version may include some
|
# the client may break due to server side new version may include some
|
||||||
# backward incompatible change.
|
# backward incompatible change.
|
||||||
API_MAX_VERSION = api_versions.APIVersion("2.20")
|
API_MAX_VERSION = api_versions.APIVersion("2.21")
|
||||||
|
@ -308,7 +308,8 @@ class ClientTestBase(testtools.TestCase):
|
|||||||
|
|
||||||
raise ValueError("Unable to find value for column '%s'.")
|
raise ValueError("Unable to find value for column '%s'.")
|
||||||
|
|
||||||
def _create_server(self, name=None, with_network=True, **kwargs):
|
def _create_server(self, name=None, with_network=True, add_cleanup=True,
|
||||||
|
**kwargs):
|
||||||
name = name or self.name_generate(prefix='server')
|
name = name or self.name_generate(prefix='server')
|
||||||
if with_network:
|
if with_network:
|
||||||
nics = [{"net-id": self.network.id}]
|
nics = [{"net-id": self.network.id}]
|
||||||
@ -316,7 +317,8 @@ class ClientTestBase(testtools.TestCase):
|
|||||||
nics = None
|
nics = None
|
||||||
server = self.client.servers.create(name, self.image, self.flavor,
|
server = self.client.servers.create(name, self.image, self.flavor,
|
||||||
nics=nics, **kwargs)
|
nics=nics, **kwargs)
|
||||||
self.addCleanup(server.delete)
|
if add_cleanup:
|
||||||
|
self.addCleanup(server.delete)
|
||||||
novaclient.v2.shell._poll_for_status(
|
novaclient.v2.shell._poll_for_status(
|
||||||
self.client.servers.get, server.id,
|
self.client.servers.get, server.id,
|
||||||
'building', ['active'])
|
'building', ['active'])
|
||||||
|
60
novaclient/tests/functional/v2/test_instance_action.py
Normal file
60
novaclient/tests/functional/v2/test_instance_action.py
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
import six
|
||||||
|
from tempest_lib import exceptions
|
||||||
|
|
||||||
|
from novaclient.tests.functional import base
|
||||||
|
|
||||||
|
|
||||||
|
class TestInstanceActionCLI(base.ClientTestBase):
|
||||||
|
|
||||||
|
COMPUTE_API_VERSION = "2.21"
|
||||||
|
|
||||||
|
def _test_cmd_with_not_existing_instance(self, cmd, args):
|
||||||
|
try:
|
||||||
|
self.nova("%s %s" % (cmd, args))
|
||||||
|
except exceptions.CommandFailed as e:
|
||||||
|
self.assertIn("ERROR (NotFound):", six.text_type(e))
|
||||||
|
else:
|
||||||
|
self.fail("%s is not failed on non existing instance." % cmd)
|
||||||
|
|
||||||
|
def test_show_action_with_not_existing_instance(self):
|
||||||
|
name_or_uuid = str(uuid.uuid4())
|
||||||
|
request_id = str(uuid.uuid4())
|
||||||
|
self._test_cmd_with_not_existing_instance(
|
||||||
|
"instance-action", "%s %s" % (name_or_uuid, request_id))
|
||||||
|
|
||||||
|
def test_list_actions_with_not_existing_instance(self):
|
||||||
|
name_or_uuid = str(uuid.uuid4())
|
||||||
|
self._test_cmd_with_not_existing_instance("instance-action-list",
|
||||||
|
name_or_uuid)
|
||||||
|
|
||||||
|
def test_show_and_list_actions_on_deleted_instance(self):
|
||||||
|
server = self._create_server(add_cleanup=False)
|
||||||
|
server.delete()
|
||||||
|
self.wait_for_resource_delete(server, self.client.servers)
|
||||||
|
|
||||||
|
output = self.nova("instance-action-list %s" % server.id)
|
||||||
|
# NOTE(andreykurilin): output is not a single row table, so we can
|
||||||
|
# obtain just "create" action. It should be enough for testing
|
||||||
|
# "nova instance-action <server> <request-id>" command
|
||||||
|
request_id = self._get_column_value_from_single_row_table(
|
||||||
|
output, "Request_ID")
|
||||||
|
|
||||||
|
output = self.nova("instance-action %s %s" % (server.id, request_id))
|
||||||
|
|
||||||
|
# ensure that obtained action is "create".
|
||||||
|
self.assertEqual("create",
|
||||||
|
self._get_value_from_the_table(output, "action"))
|
@ -158,6 +158,15 @@ class FindResourceTestCase(test_utils.TestCase):
|
|||||||
output = utils.find_resource(alphanum_manager, '01234')
|
output = utils.find_resource(alphanum_manager, '01234')
|
||||||
self.assertEqual(output, alphanum_manager.get('01234'))
|
self.assertEqual(output, alphanum_manager.get('01234'))
|
||||||
|
|
||||||
|
def test_find_without_wrapping_exception(self):
|
||||||
|
alphanum_manager = FakeManager(True)
|
||||||
|
self.assertRaises(exceptions.NotFound, utils.find_resource,
|
||||||
|
alphanum_manager, 'not_exist', wrap_exception=False)
|
||||||
|
res = alphanum_manager.resources[0]
|
||||||
|
alphanum_manager.resources.append(res)
|
||||||
|
self.assertRaises(exceptions.NoUniqueMatch, utils.find_resource,
|
||||||
|
alphanum_manager, res.name, wrap_exception=False)
|
||||||
|
|
||||||
|
|
||||||
class _FakeResult(object):
|
class _FakeResult(object):
|
||||||
def __init__(self, name, value):
|
def __init__(self, name, value):
|
||||||
|
@ -273,7 +273,7 @@ def print_dict(d, dict_property="Property", dict_value="Value", wrap=0):
|
|||||||
print(result)
|
print(result)
|
||||||
|
|
||||||
|
|
||||||
def find_resource(manager, name_or_id, **find_args):
|
def find_resource(manager, name_or_id, wrap_exception=True, **find_args):
|
||||||
"""Helper for the _find_* methods."""
|
"""Helper for the _find_* methods."""
|
||||||
# for str id which is not uuid (for Flavor, Keypair and hypervsior in cells
|
# for str id which is not uuid (for Flavor, Keypair and hypervsior in cells
|
||||||
# environments search currently)
|
# environments search currently)
|
||||||
@ -316,7 +316,9 @@ def find_resource(manager, name_or_id, **find_args):
|
|||||||
"to be more specific.") %
|
"to be more specific.") %
|
||||||
{'class': manager.resource_class.__name__.lower(),
|
{'class': manager.resource_class.__name__.lower(),
|
||||||
'name': name_or_id})
|
'name': name_or_id})
|
||||||
raise exceptions.CommandError(msg)
|
if wrap_exception:
|
||||||
|
raise exceptions.CommandError(msg)
|
||||||
|
raise exceptions.NoUniqueMatch(msg)
|
||||||
|
|
||||||
# finally try to get entity as integer id
|
# finally try to get entity as integer id
|
||||||
try:
|
try:
|
||||||
@ -325,7 +327,9 @@ def find_resource(manager, name_or_id, **find_args):
|
|||||||
msg = (_("No %(class)s with a name or ID of '%(name)s' exists.") %
|
msg = (_("No %(class)s with a name or ID of '%(name)s' exists.") %
|
||||||
{'class': manager.resource_class.__name__.lower(),
|
{'class': manager.resource_class.__name__.lower(),
|
||||||
'name': name_or_id})
|
'name': name_or_id})
|
||||||
raise exceptions.CommandError(msg)
|
if wrap_exception:
|
||||||
|
raise exceptions.CommandError(msg)
|
||||||
|
raise exceptions.NotFound(404, msg)
|
||||||
|
|
||||||
|
|
||||||
def _format_servers_list_networks(server):
|
def _format_servers_list_networks(server):
|
||||||
|
@ -15,7 +15,11 @@
|
|||||||
|
|
||||||
import pprint
|
import pprint
|
||||||
|
|
||||||
|
import six
|
||||||
|
|
||||||
|
from novaclient import api_versions
|
||||||
from novaclient import base
|
from novaclient import base
|
||||||
|
from novaclient import exceptions
|
||||||
from novaclient.i18n import _
|
from novaclient.i18n import _
|
||||||
from novaclient.openstack.common import cliutils
|
from novaclient.openstack.common import cliutils
|
||||||
from novaclient import utils
|
from novaclient import utils
|
||||||
@ -41,17 +45,41 @@ class InstanceActionManager(base.ManagerWithFind):
|
|||||||
base.getid(server), 'instanceActions')
|
base.getid(server), 'instanceActions')
|
||||||
|
|
||||||
|
|
||||||
|
@api_versions.wraps("2.0", "2.20")
|
||||||
|
def _find_server(cs, args):
|
||||||
|
return utils.find_resource(cs.servers, args.server)
|
||||||
|
|
||||||
|
|
||||||
|
@api_versions.wraps("2.21")
|
||||||
|
def _find_server(cs, args):
|
||||||
|
try:
|
||||||
|
return utils.find_resource(cs.servers, args.server,
|
||||||
|
wrap_exception=False)
|
||||||
|
except exceptions.NoUniqueMatch as e:
|
||||||
|
raise exceptions.CommandError(six.text_type(e))
|
||||||
|
except exceptions.NotFound:
|
||||||
|
# The server can be deleted
|
||||||
|
return args.server
|
||||||
|
|
||||||
|
|
||||||
@cliutils.arg(
|
@cliutils.arg(
|
||||||
'server',
|
'server',
|
||||||
metavar='<server>',
|
metavar='<server>',
|
||||||
help=_('Name or UUID of the server to show an action for.'))
|
help=_('Name or UUID of the server to show actions for.'),
|
||||||
|
start_version="2.0", end_version="2.20")
|
||||||
|
@cliutils.arg(
|
||||||
|
'server',
|
||||||
|
metavar='<server>',
|
||||||
|
help=_('Name or UUID of the server to show actions for. Only UUID can be '
|
||||||
|
'used to show actions for a deleted server.'),
|
||||||
|
start_version="2.21")
|
||||||
@cliutils.arg(
|
@cliutils.arg(
|
||||||
'request_id',
|
'request_id',
|
||||||
metavar='<request_id>',
|
metavar='<request_id>',
|
||||||
help=_('Request ID of the action to get.'))
|
help=_('Request ID of the action to get.'))
|
||||||
def do_instance_action(cs, args):
|
def do_instance_action(cs, args):
|
||||||
"""Show an action."""
|
"""Show an action."""
|
||||||
server = utils.find_resource(cs.servers, args.server)
|
server = _find_server(cs, args)
|
||||||
action_resource = cs.instance_action.get(server, args.request_id)
|
action_resource = cs.instance_action.get(server, args.request_id)
|
||||||
action = action_resource._info
|
action = action_resource._info
|
||||||
if 'events' in action:
|
if 'events' in action:
|
||||||
@ -62,10 +90,17 @@ def do_instance_action(cs, args):
|
|||||||
@cliutils.arg(
|
@cliutils.arg(
|
||||||
'server',
|
'server',
|
||||||
metavar='<server>',
|
metavar='<server>',
|
||||||
help=_('Name or UUID of the server to list actions for.'))
|
help=_('Name or UUID of the server to list actions for.'),
|
||||||
|
start_version="2.0", end_version="2.20")
|
||||||
|
@cliutils.arg(
|
||||||
|
'server',
|
||||||
|
metavar='<server>',
|
||||||
|
help=_('Name or UUID of the server to list actions for. Only UUID can be '
|
||||||
|
'used to list actions on a deleted server.'),
|
||||||
|
start_version="2.21")
|
||||||
def do_instance_action_list(cs, args):
|
def do_instance_action_list(cs, args):
|
||||||
"""List actions on a server."""
|
"""List actions on a server."""
|
||||||
server = utils.find_resource(cs.servers, args.server)
|
server = _find_server(cs, args)
|
||||||
actions = cs.instance_action.list(server)
|
actions = cs.instance_action.list(server)
|
||||||
utils.print_list(actions,
|
utils.print_list(actions,
|
||||||
['Action', 'Request_ID', 'Message', 'Start_Time'],
|
['Action', 'Request_ID', 'Message', 'Start_Time'],
|
||||||
|
Loading…
Reference in New Issue
Block a user