Microversion 2.77: Support Specifying AZ to unshelve

This patch adds a new parameter ``--availability-zone`` to ``nova
unshelve`` command. This can help users to specify an ``availability_zone``
to unshelve a shelve offloaded server from 2.77 microversion.

Depends-On: https://review.opendev.org/#/c/663851/
Implements: blueprint support-specifying-az-when-restore-shelved-server

Change-Id: I8bce8f430bc54f03bacc105e37fc8b3bbf2432c2
This commit is contained in:
zhangbailin 2019-06-13 21:22:28 +08:00 committed by Matt Riedemann
parent a3e44e8b39
commit ecfa521b21
9 changed files with 133 additions and 4 deletions

View File

@ -3698,7 +3698,7 @@ nova unshelve
.. code-block:: console
usage: nova unshelve <server>
usage: nova unshelve [--availability-zone <availability_zone>] <server>
Unshelve a server.
@ -3707,6 +3707,12 @@ Unshelve a server.
``<server>``
Name or ID of server.
**Optional arguments:**
``--availability-zone <availability_zone>``
Name of the availability zone in which to unshelve a ``SHELVED_OFFLOADED``
server. (Supported by API versions '2.77' - '2.latest')
.. _nova_update:
nova update

View File

@ -25,4 +25,4 @@ API_MIN_VERSION = api_versions.APIVersion("2.1")
# when client supported the max version, and bumped sequentially, otherwise
# the client may break due to server side new version may include some
# backward incompatible change.
API_MAX_VERSION = api_versions.APIVersion("2.76")
API_MAX_VERSION = api_versions.APIVersion("2.77")

View File

@ -456,6 +456,8 @@ class V1(Base):
return None
elif action == 'lock':
return None
elif action == 'unshelve':
return None
elif action == 'rebuild':
body = body[action]
adminPass = body.get('adminPass', 'randompassword')

View File

@ -775,7 +775,7 @@ class FakeSessionClient(base_client.SessionClient):
none_actions = ['revertResize', 'os-stop', 'os-start',
'forceDelete', 'restore', 'pause', 'unpause', 'unlock',
'unrescue', 'resume', 'suspend', 'shelve',
'shelveOffload', 'unshelve', 'resetNetwork']
'shelveOffload', 'resetNetwork']
type_actions = ['os-getVNCConsole', 'os-getSPICEConsole',
'os-getRDPConsole']
@ -852,6 +852,16 @@ class FakeSessionClient(base_client.SessionClient):
assert set(body[action].keys()) == expected
else:
assert body[action] is None
elif action == 'unshelve':
if self.api_version < api_versions.APIVersion("2.77"):
assert body[action] is None
else:
# In 2.77 and above, we allow body to be one of these:
# {'unshelve': None}
# {'unshelve': {'availability_zone': 'foo-az'}}
if body[action] is not None:
assert set(body[action].keys()) == set(
['availability_zone'])
elif action == 'rebuild':
body = body[action]
adminPass = body.get('adminPass', 'randompassword')

View File

@ -1839,3 +1839,39 @@ class ServersV274Test(ServersV273Test):
hypervisor_hostname="new-host")
self.assertIn("'host' argument is only allowed since microversion "
"2.74", six.text_type(ex))
class ServersV277Test(ServersV274Test):
api_version = "2.77"
def test_unshelve_with_az(self):
s = self.cs.servers.get(1234)
# Test going through the Server object.
ret = s.unshelve(availability_zone='foo-az')
self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST)
self.assert_called('POST', '/servers/1234/action',
{'unshelve': {
'availability_zone': 'foo-az'}})
# Test going through the ServerManager directly.
ret = self.cs.servers.unshelve(s, availability_zone='foo-az')
self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST)
self.assert_called('POST', '/servers/1234/action',
{'unshelve': {
'availability_zone': 'foo-az'}})
def test_unshelve_server_pre_277_fails_with_specified_az(self):
self.cs.api_version = api_versions.APIVersion('2.76')
s = self.cs.servers.get(1234)
# Test going through the Server object.
ex = self.assertRaises(TypeError,
s.unshelve,
availability_zone='foo-az')
self.assertIn("unexpected keyword argument 'availability_zone'",
six.text_type(ex))
# Test going through the ServerManager directly.
ex = self.assertRaises(TypeError,
self.cs.servers.unshelve,
s, availability_zone='foo-az')
self.assertIn("unexpected keyword argument 'availability_zone'",
six.text_type(ex))

View File

@ -2258,6 +2258,27 @@ class ShellTest(utils.TestCase):
self.run_command('unshelve sample-server')
self.assert_called('POST', '/servers/1234/action', {'unshelve': None})
def test_unshelve_pre_v277_with_az_fails(self):
"""Tests that trying to unshelve with an --availability-zone before
2.77 is an error.
"""
self.assertRaises(SystemExit,
self.run_command,
'unshelve --availability-zone foo-az sample-server',
api_version='2.76')
def test_unshelve_v277(self):
# Test backward compat without an AZ specified.
self.run_command('unshelve sample-server',
api_version='2.77')
self.assert_called('POST', '/servers/1234/action',
{'unshelve': None})
# Test with specifying an AZ.
self.run_command('unshelve --availability-zone foo-az sample-server',
api_version='2.77')
self.assert_called('POST', '/servers/1234/action',
{'unshelve': {'availability_zone': 'foo-az'}})
def test_migrate(self):
self.run_command('migrate sample-server')
self.assert_called('POST', '/servers/1234/action', {'migrate': None})
@ -4277,6 +4298,7 @@ class ShellTest(utils.TestCase):
74, # There are no version-wrapped shell method changes for this.
75, # There are no version-wrapped shell method changes for this.
76, # doesn't require any changes in novaclient.
77, # There are no version-wrapped shell method changes for this.
])
versions_supported = set(range(0,
novaclient.API_MAX_VERSION.ver_minor + 1))

View File

@ -291,6 +291,7 @@ class Server(base.Resource):
"""
return self.manager.shelve_offload(self)
@api_versions.wraps("2.0", "2.76")
def unshelve(self):
"""
Unshelve -- Unshelve the server.
@ -299,6 +300,18 @@ class Server(base.Resource):
"""
return self.manager.unshelve(self)
@api_versions.wraps("2.77")
def unshelve(self, availability_zone=None):
"""
Unshelve -- Unshelve the server.
:param availability_zone: The specified availability zone name
(Optional)
:returns: An instance of novaclient.base.TupleWithMeta
"""
return self.manager.unshelve(self,
availability_zone=availability_zone)
def diagnostics(self):
"""Diagnostics -- Retrieve server diagnostics."""
return self.manager.diagnostics(self)
@ -1222,6 +1235,7 @@ class ServerManager(base.BootingManagerWithFind):
"""
return self._action('shelveOffload', server, None)
@api_versions.wraps("2.0", "2.76")
def unshelve(self, server):
"""
Unshelve the server.
@ -1231,6 +1245,21 @@ class ServerManager(base.BootingManagerWithFind):
"""
return self._action('unshelve', server, None)
@api_versions.wraps("2.77")
def unshelve(self, server, availability_zone=None):
"""
Unshelve the server.
:param server: The :class:`Server` (or its ID) to unshelve
:param availability_zone: The specified availability zone name
(Optional)
:returns: An instance of novaclient.base.TupleWithMeta
"""
info = None
if availability_zone:
info = {'availability_zone': availability_zone}
return self._action('unshelve', server, info)
def ips(self, server):
"""
Return IP Addresses associated with the server.

View File

@ -2285,9 +2285,25 @@ def do_shelve_offload(cs, args):
@utils.arg('server', metavar='<server>', help=_('Name or ID of server.'))
@utils.arg(
'--availability-zone',
metavar='<availability-zone>',
default=None,
dest='availability_zone',
help=_('Name of the availability zone in which to unshelve a '
'SHELVED_OFFLOADED server.'),
start_version='2.77')
def do_unshelve(cs, args):
"""Unshelve a server."""
_find_server(cs, args.server).unshelve()
update_kwargs = {}
# Microversion >= 2.77 will support user to specify an
# availability_zone to unshelve a shelve offloaded server.
if cs.api_version >= api_versions.APIVersion('2.77'):
if 'availability_zone' in args and args.availability_zone is not None:
update_kwargs['availability_zone'] = args.availability_zone
server = _find_server(cs, args.server)
server.unshelve(**update_kwargs)
@utils.arg('server', metavar='<server>', help=_('Name or ID of server.'))

View File

@ -0,0 +1,8 @@
---
features:
- |
Support has been added for `microversion 2.77`_. This microversion
allows specifying an availability zone to unshelve a shelve
offloaded server.
.. _microversion 2.77: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id69