From 57ed1b8872486dd00e47c336aaa7536deeb42d91 Mon Sep 17 00:00:00 2001 From: Jose Luis Franco Arza Date: Tue, 16 Jun 2020 22:36:23 +0200 Subject: [PATCH] Identify not allowed parameters in upgrades. This change allows us identifying a set of parameters which should not been passed in the upgrade prepare or upgrade converge steps. As it is now, it is mostly intended to block the converge step if the FFU parameters (Stein registry parameters) were left in the environment files before running the converge step, however it will allow blocking the upgrade prepare in the case that some deprecated or not recommended parameter is provided in the templates. The way how it works is by converting every single yaml passed in the environment files into a list of keys (only for the parameters_default so far), then it will try to intersect the list of forbidden parameters with the list of keys. If there is a match an exception will be raised showing those parameters: ERROR openstack [-] The following parameters should be removed from the environment files: ceph3_namespace name_suffix_stein tag_stein name_prefix_stein ceph3_image namespace_stein ceph3_tag Change-Id: I24715f5e55d4cd6cf9879345980d3a3c5ab8830c (cherry picked from commit fbc1eba88aa41d4a2ee73ebd4af3c212a4459829) (cherry picked from commit 3a86f9f7f54c68e1099b08d9a6b7ac1cc9eaaaa6) --- tripleoclient/constants.py | 8 +++ tripleoclient/exceptions.py | 4 ++ tripleoclient/v1/overcloud_upgrade.py | 10 ++++ tripleoclient/workflows/parameters.py | 82 +++++++++++++++++++++++++++ 4 files changed, 104 insertions(+) diff --git a/tripleoclient/constants.py b/tripleoclient/constants.py index f939650cc..3e98a16e3 100644 --- a/tripleoclient/constants.py +++ b/tripleoclient/constants.py @@ -78,6 +78,14 @@ UPDATE_PREPARE_ENV = "environments/lifecycle/update-prepare.yaml" UPDATE_CONVERGE_ENV = "environments/lifecycle/update-converge.yaml" UPGRADE_PREPARE_ENV = "environments/lifecycle/upgrade-prepare.yaml" UPGRADE_CONVERGE_ENV = "environments/lifecycle/upgrade-converge.yaml" +UPGRADE_CONVERGE_FORBIDDEN_PARAMS = ["ceph3_namespace", + "ceph3_tag", + "ceph3_image", + "name_prefix_stein", + "name_suffix_stein", + "namespace_stein", + "tag_stein", + ] FFWD_UPGRADE_PREPARE_ENV = "environments/lifecycle/ffwd-upgrade-prepare.yaml" FFWD_UPGRADE_CONVERGE_ENV = "environments/lifecycle/ffwd-upgrade-converge.yaml" FFWD_UPGRADE_PREPARE_SCRIPT = ("#!/bin/bash \n" diff --git a/tripleoclient/exceptions.py b/tripleoclient/exceptions.py index b738b462d..8f94dcb7d 100644 --- a/tripleoclient/exceptions.py +++ b/tripleoclient/exceptions.py @@ -135,3 +135,7 @@ class UndercloudUpgradeNotConfirmed(Base): class CellExportError(Base): """Cell export failed""" + + +class BannedParameters(Base): + """Some of the environment parameters provided should be removed""" diff --git a/tripleoclient/v1/overcloud_upgrade.py b/tripleoclient/v1/overcloud_upgrade.py index 02b655251..13eede967 100644 --- a/tripleoclient/v1/overcloud_upgrade.py +++ b/tripleoclient/v1/overcloud_upgrade.py @@ -25,6 +25,7 @@ from tripleoclient import utils as oooutils from tripleoclient.v1.overcloud_deploy import DeployOvercloud from tripleoclient.workflows import deployment from tripleoclient.workflows import package_update +from tripleoclient.workflows import parameters CONF = cfg.CONF logging.register_options(CONF) @@ -43,6 +44,8 @@ class UpgradePrepare(DeployOvercloud): template = constants.UPGRADE_PREPARE_ENV + forbidden_params = [] + log = logging.getLogger(__name__ + ".UpgradePrepare") def get_parser(self, prog_name): @@ -75,6 +78,11 @@ class UpgradePrepare(DeployOvercloud): parsed_args.environment_files = oooutils.prepend_environment( parsed_args.environment_files, templates_dir, self.template) + # Parse all environment files looking for undesired + # parameters + parameters.check_forbidden_params(self.log, + parsed_args.environment_files, + self.forbidden_params) super(UpgradePrepare, self).take_action(parsed_args) # Download stack_name-config as this is skiped in @@ -256,4 +264,6 @@ class UpgradeConvergeOvercloud(UpgradePrepare): template = constants.UPGRADE_CONVERGE_ENV + forbidden_params = constants.UPGRADE_CONVERGE_FORBIDDEN_PARAMS + log = logging.getLogger(__name__ + ".UpgradeConvergeOvercloud") diff --git a/tripleoclient/workflows/parameters.py b/tripleoclient/workflows/parameters.py index ea905737d..cc08ea7d1 100644 --- a/tripleoclient/workflows/parameters.py +++ b/tripleoclient/workflows/parameters.py @@ -10,6 +10,7 @@ # License for the specific language governing permissions and limitations # under the License. import logging +import os import re import yaml @@ -156,3 +157,84 @@ def generate_fencing_parameters(clients, **workflow_input): if ('fencing_parameters' in payload and (payload.get('status', 'FAILED') == "SUCCESS")): return payload['fencing_parameters'] + + +def check_forbidden_params(log, env_files, forbidden): + """Looks for undesired parameters in the environment files. + + Each of the environment files pass in env_files will be parsed + and if the parameters_default key is found, then all the keys + from the nested dictionary found under will be converted into + a list, for example: + + parameters_default: + key1: value1 + key2: value2 + key3: + - value3 + - key31: + key311: value311 + key312: value312 + key32: value32 + + Will be converted by get_all_keys into: + [key1, key2, key3, key31, key311, key312, key32] + + This list provides us with all the parameters used in the environment + file, without the values, in the format of a list. So we can use sets + to find occurrences of the forbbiden paramenters. + + The variable matched_params will get all the ocurrences of forbidden + parameters stored, so we can parse all the environment files and show + all the parameters which should get removed from the environment files + at once (saving the user to run the command, modify a template, run it + again, modify another, etc...). If matched_params list is not empty, + an exception will be raised, stopping the execution of the command and + displaying the commands which need to be removed. + + :param log: logging object passed from the calling method + :type log: Logging object + :param env_files: list of the environment files passed in the command + :type env_files: list of strings + :param forbidden: list of the undesired parameters + :type forbidden: list of strings + + :returns exception if some of the forbidden parameters are found in + the environment files. + """ + + # Iterates over a nested dict and returns all the + # keys from the dict in a list + # example: + # * input: {'a': '1', 'b': ['c': '2', 'd': {'e': '3'}]} + # * output: ['a', 'b', 'c', 'd', 'e'] + def get_all_keys(obj, keys_list): + if isinstance(obj, dict): + keys_list += obj.keys() + for value in obj.values(): + get_all_keys(value, keys_list) + elif isinstance(obj, list): + for value in obj: + get_all_keys(value, keys_list) + + matched_params = [] + + for file in env_files: + if os.path.exists(file): + with open(file, 'r') as env_file: + contents = yaml.safe_load(env_file) + pd = contents.get('parameter_defaults', {}) + if pd: + # Intersection of values and forbidden params + list_of_keys = [] + get_all_keys(pd, list_of_keys) + found_in_pd = list(set(list_of_keys) & set(forbidden)) + + # Combine them without duplicates + matched_params = list(set(matched_params + found_in_pd)) + + if matched_params: + raise exceptions.BannedParameters("The following parameters should be " + "removed from the environment files:" + "\n{}\n" + .format('\n'.join(matched_params)))