From ecfa521b2126e2f0cee25969a7d2c4c8637abba2 Mon Sep 17 00:00:00 2001 From: zhangbailin Date: Thu, 13 Jun 2019 21:22:28 +0800 Subject: [PATCH] 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 --- doc/source/cli/nova.rst | 8 ++++- novaclient/__init__.py | 2 +- novaclient/tests/unit/fixture_data/servers.py | 2 ++ novaclient/tests/unit/v2/fakes.py | 12 ++++++- novaclient/tests/unit/v2/test_servers.py | 36 +++++++++++++++++++ novaclient/tests/unit/v2/test_shell.py | 22 ++++++++++++ novaclient/v2/servers.py | 29 +++++++++++++++ novaclient/v2/shell.py | 18 +++++++++- .../microversion-v2_77-ffee30c180aa4dbe.yaml | 8 +++++ 9 files changed, 133 insertions(+), 4 deletions(-) create mode 100644 releasenotes/notes/microversion-v2_77-ffee30c180aa4dbe.yaml diff --git a/doc/source/cli/nova.rst b/doc/source/cli/nova.rst index 1a0081eb2..b9e3fffc1 100644 --- a/doc/source/cli/nova.rst +++ b/doc/source/cli/nova.rst @@ -3698,7 +3698,7 @@ nova unshelve .. code-block:: console - usage: nova unshelve + usage: nova unshelve [--availability-zone ] Unshelve a server. @@ -3707,6 +3707,12 @@ Unshelve a server. ```` Name or ID of server. +**Optional arguments:** + +``--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 diff --git a/novaclient/__init__.py b/novaclient/__init__.py index eaf452773..00e0b3e4d 100644 --- a/novaclient/__init__.py +++ b/novaclient/__init__.py @@ -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") diff --git a/novaclient/tests/unit/fixture_data/servers.py b/novaclient/tests/unit/fixture_data/servers.py index d3354469a..9962842a8 100644 --- a/novaclient/tests/unit/fixture_data/servers.py +++ b/novaclient/tests/unit/fixture_data/servers.py @@ -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') diff --git a/novaclient/tests/unit/v2/fakes.py b/novaclient/tests/unit/v2/fakes.py index 29ec88877..faf5f6f49 100644 --- a/novaclient/tests/unit/v2/fakes.py +++ b/novaclient/tests/unit/v2/fakes.py @@ -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') diff --git a/novaclient/tests/unit/v2/test_servers.py b/novaclient/tests/unit/v2/test_servers.py index 62c8d8d43..5ef987faa 100644 --- a/novaclient/tests/unit/v2/test_servers.py +++ b/novaclient/tests/unit/v2/test_servers.py @@ -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)) diff --git a/novaclient/tests/unit/v2/test_shell.py b/novaclient/tests/unit/v2/test_shell.py index 7eb86d7a9..2dc8a38a5 100644 --- a/novaclient/tests/unit/v2/test_shell.py +++ b/novaclient/tests/unit/v2/test_shell.py @@ -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)) diff --git a/novaclient/v2/servers.py b/novaclient/v2/servers.py index 43ed34f22..acef78568 100644 --- a/novaclient/v2/servers.py +++ b/novaclient/v2/servers.py @@ -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. diff --git a/novaclient/v2/shell.py b/novaclient/v2/shell.py index 7b9c02061..3eb68bc28 100644 --- a/novaclient/v2/shell.py +++ b/novaclient/v2/shell.py @@ -2285,9 +2285,25 @@ def do_shelve_offload(cs, args): @utils.arg('server', metavar='', help=_('Name or ID of server.')) +@utils.arg( + '--availability-zone', + metavar='', + 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='', help=_('Name or ID of server.')) diff --git a/releasenotes/notes/microversion-v2_77-ffee30c180aa4dbe.yaml b/releasenotes/notes/microversion-v2_77-ffee30c180aa4dbe.yaml new file mode 100644 index 000000000..6262f2207 --- /dev/null +++ b/releasenotes/notes/microversion-v2_77-ffee30c180aa4dbe.yaml @@ -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