From bef67651042a3ce123222079a41461677f3f9df0 Mon Sep 17 00:00:00 2001 From: Takashi NATSUME Date: Tue, 14 Nov 2017 15:06:56 +0900 Subject: [PATCH] Microversion 2.54 - Enable reset keypair while rebuild Adds support for microversion 2.54 which adds resetting keypair and unsetting keypair in rebuild operation. Adds optional ``--key-name`` and ``--key-unset`` options in the ``nova rebuild`` command. The ``--key-name`` and ``--key-unset`` cannot be specified at the same time. Change-Id: Ie2a39bb29dd59c070adc94e79ea0f6473227a427 Implements: blueprint rebuild-keypair-reset --- novaclient/__init__.py | 2 +- novaclient/tests/unit/v2/test_servers.py | 31 +++++++++++++++++ novaclient/tests/unit/v2/test_shell.py | 33 +++++++++++++++++++ novaclient/v2/servers.py | 11 +++++++ novaclient/v2/shell.py | 24 ++++++++++++++ .../microversion-v2_54-6c7ccb61eff6cb6d.yaml | 7 ++++ 6 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 releasenotes/notes/microversion-v2_54-6c7ccb61eff6cb6d.yaml diff --git a/novaclient/__init__.py b/novaclient/__init__.py index 3fe7488d0..d84695cec 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.53") +API_MAX_VERSION = api_versions.APIVersion("2.54") diff --git a/novaclient/tests/unit/v2/test_servers.py b/novaclient/tests/unit/v2/test_servers.py index 0766f1cd6..396e3b763 100644 --- a/novaclient/tests/unit/v2/test_servers.py +++ b/novaclient/tests/unit/v2/test_servers.py @@ -1550,3 +1550,34 @@ class ServersV252Test(ServersV249Test): key_name="fakekey", nics=self._get_server_create_default_nics(), tags=['tag1', 'tag2']) + + +class ServersV254Test(ServersV252Test): + + api_version = "2.54" + + def test_rebuild_with_key_name(self): + s = self.cs.servers.get(1234) + ret = s.rebuild(image="1", key_name="test_keypair") + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) + self.assert_called('POST', '/servers/1234/action', + {'rebuild': { + 'imageRef': '1', + 'key_name': 'test_keypair'}}) + + def test_rebuild_with_key_name_none(self): + s = self.cs.servers.get(1234) + ret = s.rebuild(image="1", key_name=None) + self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) + self.assert_called('POST', '/servers/1234/action', + {'rebuild': { + 'key_name': None, + 'imageRef': '1'}}) + + def test_rebuild_with_key_name_pre_254_fails(self): + self.cs.api_version = api_versions.APIVersion('2.53') + ex = self.assertRaises(exceptions.UnsupportedAttribute, + self.cs.servers.rebuild, + '1234', fakes.FAKE_IMAGE_UUID_1, + key_name='test_keypair') + self.assertIn('key_name', six.text_type(ex.message)) diff --git a/novaclient/tests/unit/v2/test_shell.py b/novaclient/tests/unit/v2/test_shell.py index a4580b088..341f5e51f 100644 --- a/novaclient/tests/unit/v2/test_shell.py +++ b/novaclient/tests/unit/v2/test_shell.py @@ -1494,6 +1494,38 @@ class ShellTest(utils.TestCase): self.assert_called('GET', '/flavors/1', pos=4) self.assert_called('GET', '/v2/images/%s' % FAKE_UUID_2, pos=5) + def test_rebuild_reset_keypair(self): + self.run_command('rebuild sample-server %s --key-name test_keypair' % + FAKE_UUID_1, api_version='2.54') + self.assert_called('GET', '/servers?name=sample-server', pos=0) + self.assert_called('GET', '/servers/1234', pos=1) + self.assert_called('GET', '/v2/images/%s' % FAKE_UUID_1, pos=2) + self.assert_called('POST', '/servers/1234/action', + {'rebuild': {'imageRef': FAKE_UUID_1, + 'key_name': 'test_keypair', + 'description': None}}, pos=3) + self.assert_called('GET', '/v2/images/%s' % FAKE_UUID_2, pos=4) + + def test_rebuild_unset_keypair(self): + self.run_command('rebuild sample-server %s --key-unset' % + FAKE_UUID_1, api_version='2.54') + self.assert_called('GET', '/servers?name=sample-server', pos=0) + self.assert_called('GET', '/servers/1234', pos=1) + self.assert_called('GET', '/v2/images/%s' % FAKE_UUID_1, pos=2) + self.assert_called('POST', '/servers/1234/action', + {'rebuild': {'imageRef': FAKE_UUID_1, + 'key_name': None, + 'description': None}}, pos=3) + self.assert_called('GET', '/v2/images/%s' % FAKE_UUID_2, pos=4) + + def test_rebuild_unset_keypair_with_key_name(self): + ex = self.assertRaises( + exceptions.CommandError, self.run_command, + 'rebuild sample-server %s --key-unset --key-name test_keypair' % + FAKE_UUID_1, api_version='2.54') + self.assertIn("Cannot specify '--key-unset' with '--key-name'.", + six.text_type(ex)) + def test_rebuild_with_incorrect_metadata(self): cmd = 'rebuild sample-server %s --name asdf --meta foo' % FAKE_UUID_1 result = self.assertRaises(argparse.ArgumentTypeError, @@ -3126,6 +3158,7 @@ class ShellTest(utils.TestCase): 48, # There are no version-wrapped shell method changes for this. 51, # There are no version-wrapped shell method changes for this. 52, # There are no version-wrapped shell method changes for this. + 54, # 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 2801e2a36..ed8e2b55f 100644 --- a/novaclient/v2/servers.py +++ b/novaclient/v2/servers.py @@ -1496,12 +1496,21 @@ class ServerManager(base.BootingManagerWithFind): and each file must be 10k or less. :param description: optional description of the server (allowed since microversion 2.19) + :param key_name: optional key pair name for rebuild operation; passing + None will unset the key for the server instance + (starting from microversion 2.54) :returns: :class:`Server` """ descr_microversion = api_versions.APIVersion("2.19") if "description" in kwargs and self.api_version < descr_microversion: raise exceptions.UnsupportedAttribute("description", "2.19") + # Starting from microversion 2.54, + # the optional 'key_name' parameter has been added. + if ('key_name' in kwargs and + self.api_version < api_versions.APIVersion('2.54')): + raise exceptions.UnsupportedAttribute('key_name', '2.54') + body = {'imageRef': base.getid(image)} if password is not None: body['adminPass'] = password @@ -1513,6 +1522,8 @@ class ServerManager(base.BootingManagerWithFind): body['name'] = name if "description" in kwargs: body["description"] = kwargs["description"] + if 'key_name' in kwargs: + body['key_name'] = kwargs['key_name'] if meta: body['metadata'] = meta if files: diff --git a/novaclient/v2/shell.py b/novaclient/v2/shell.py index ea68e1a40..837526c41 100644 --- a/novaclient/v2/shell.py +++ b/novaclient/v2/shell.py @@ -1786,6 +1786,20 @@ def do_reboot(cs, args): default=[], help=_("Store arbitrary files from locally to " "on the new server. You may store up to 5 files.")) +@utils.arg( + '--key-name', + metavar='', + default=None, + help=_("Keypair name to set in the server. " + "Cannot be specified with the '--key-unset' option."), + start_version='2.54') +@utils.arg( + '--key-unset', + action='store_true', + default=False, + help=_("Unset keypair in the server. " + "Cannot be specified with the '--key-name' option."), + start_version='2.54') def do_rebuild(cs, args): """Shutdown, re-image, and re-boot a server.""" server = _find_server(cs, args.server) @@ -1819,6 +1833,16 @@ def do_rebuild(cs, args): "form '--file " "'") % f) kwargs['files'] = files + + if cs.api_version >= api_versions.APIVersion('2.54'): + if args.key_unset: + kwargs['key_name'] = None + if args.key_name: + raise exceptions.CommandError( + _("Cannot specify '--key-unset' with '--key-name'.")) + elif args.key_name: + kwargs['key_name'] = args.key_name + server = server.rebuild(image, _password, **kwargs) _print_server(cs, args, server) diff --git a/releasenotes/notes/microversion-v2_54-6c7ccb61eff6cb6d.yaml b/releasenotes/notes/microversion-v2_54-6c7ccb61eff6cb6d.yaml new file mode 100644 index 000000000..5321c486f --- /dev/null +++ b/releasenotes/notes/microversion-v2_54-6c7ccb61eff6cb6d.yaml @@ -0,0 +1,7 @@ +--- +features: + - | + Adds support for microversion 2.54 which adds resetting keypair and + unsetting keypair in rebuild operation. + Adds optional ``--key-name`` and ``--key-unset`` options + in the ``nova rebuild`` command.