From f73e0c7a9942c2fe211a82dd19107e9fa351e0bd Mon Sep 17 00:00:00 2001 From: Oleg Gelbukh Date: Thu, 19 May 2016 16:54:02 +0300 Subject: [PATCH] Add enable-release command This command enables to deploy an older release of OpenStack with the upgraded Fuel Master node. Release to enable is identified by the ID. Administrator's password is required to access the Fuel API. Example: octane enable-release --id 1 --admin-password admin Partial-bug: 1567535 Change-Id: I625db20e570b177cb46143818ac65c5d78cda0e2 --- octane/commands/enable_release.py | 70 +++++++++++++++++++++++++++++ octane/magic_consts.py | 2 + octane/tests/test_enable_release.py | 68 ++++++++++++++++++++++++++++ setup.cfg | 1 + 4 files changed, 141 insertions(+) create mode 100644 octane/commands/enable_release.py create mode 100644 octane/tests/test_enable_release.py diff --git a/octane/commands/enable_release.py b/octane/commands/enable_release.py new file mode 100644 index 00000000..117044c8 --- /dev/null +++ b/octane/commands/enable_release.py @@ -0,0 +1,70 @@ +# 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 logging + +from cliff import command +from fuelclient.client import APIClient +from octane.handlers import backup_restore +from octane import magic_consts +from octane.util import fuel_client + +LOG = logging.getLogger(__name__) + + +def enable_release(release_id, context): + release_url = "/releases/{0}".format(release_id) + with fuel_client.set_auth_context(context): + data = APIClient.get_request(release_url) + state = data.get('state') + if state == magic_consts.RELEASE_STATUS_MANAGED: + data['state'] = magic_consts.RELEASE_STATUS_ENABLED + APIClient.put_request(release_url, data) + else: + exc_msg = ("Cannot enable release {0}: has status {1}, not {2}" + .format(release_id, + state, + magic_consts.RELEASE_STATUS_MANAGED)) + raise Exception(exc_msg) + + +class EnableReleaseCommand(command.Command): + + def get_parser(self, *args, **kwargs): + parser = super(EnableReleaseCommand, self).get_parser(*args, **kwargs) + parser.add_argument( + "--id", + type=str, + action="store", + dest="release_id", + required=True, + help="ID of the release to enable.") + parser.add_argument( + "--admin-password", + type=str, + action="store", + dest="admin_password", + required=True, + help="Fuel admin password") + return parser + + def get_context(self, parsed_args): + return backup_restore.NailgunCredentialsContext( + password=parsed_args.admin_password, + user="admin" + ) + + def take_action(self, parsed_args): + assert parsed_args.release_id + assert parsed_args.admin_password + enable_release(parsed_args.release_id, + self.get_context(parsed_args)) diff --git a/octane/magic_consts.py b/octane/magic_consts.py index 7f4b5c83..00c3c98f 100644 --- a/octane/magic_consts.py +++ b/octane/magic_consts.py @@ -80,3 +80,5 @@ OSD_REPOS_UPDATE = [ COBBLER_DROP_VERSION = "7.0" MIRRORS_EXTRA_DIRS = ["ubuntu-full", "mos-ubuntu"] +RELEASE_STATUS_ENABLED = "available" +RELEASE_STATUS_MANAGED = "manageonly" diff --git a/octane/tests/test_enable_release.py b/octane/tests/test_enable_release.py new file mode 100644 index 00000000..d6494cc0 --- /dev/null +++ b/octane/tests/test_enable_release.py @@ -0,0 +1,68 @@ +# 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 pytest + +from octane.commands.enable_release import enable_release +from octane import magic_consts + + +@pytest.mark.parametrize("release_id,password", + [('1', 'test_pass'), + ('1', ''), + ('', '')]) +def test_parser(mocker, octane_app, release_id, password): + command = "enable-release" + get_context_mock = mocker.patch( + "octane.commands.enable_release.EnableReleaseCommand.get_context") + context_mock = mocker.patch( + "octane.handlers.backup_restore.NailgunCredentialsContext") + get_context_mock.return_value = context_mock + enable_release_mock = mocker.patch( + "octane.commands.enable_release.enable_release") + params = [command, "--id", release_id, "--admin-password", password] + if release_id and password: + octane_app.run(params) + enable_release_mock.assert_called_once_with(release_id, + context_mock) + else: + with pytest.raises(AssertionError): + octane_app.run(params) + + +@pytest.mark.parametrize("release_id,data", [ + (1, {'state': 'manageonly', }), + (1, {'state': 'available', }), + (1, {'state': 'unavailable', }), + (1, {'nostate': '', }), +]) +def test_enable_release(mocker, release_id, data): + release_url = "/releases/{0}".format(release_id) + context_class_mock = mocker.patch( + "octane.handlers.backup_restore.NailgunCredentialsContext") + context_mock = context_class_mock() + set_auth_context_mock = mocker.patch( + "octane.util.fuel_client.set_auth_context") + get_request_mock = mocker.patch( + "fuelclient.client.APIClient.get_request") + put_request_mock = mocker.patch( + "fuelclient.client.APIClient.put_request") + get_request_mock.return_value = data + + if data.get("state") == magic_consts.RELEASE_STATUS_MANAGED: + enable_release(release_id, context_mock) + set_auth_context_mock.assert_called_once_with(context_mock) + expected_data = {'state': magic_consts.RELEASE_STATUS_ENABLED} + put_request_mock.assert_called_once_with(release_url, expected_data) + else: + with pytest.raises(Exception): + enable_release(release_id, context_mock) diff --git a/setup.cfg b/setup.cfg index 98a1dda4..dc84f7c5 100644 --- a/setup.cfg +++ b/setup.cfg @@ -40,6 +40,7 @@ octane = fuel-repo-backup = octane.commands.backup:BackupRepoCommand fuel-repo-restore = octane.commands.restore:RestoreRepoCommand update-bootstrap-centos = octane.commands.update_bootstrap:UpdateCentos + enable-release = octane.commands.enable_release:EnableReleaseCommand octane.handlers.upgrade = controller = octane.handlers.upgrade.controller:ControllerUpgrade compute = octane.handlers.upgrade.compute:ComputeUpgrade