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 fbc1eba88a)
(cherry picked from commit 3a86f9f7f5)
This commit is contained in:
Jose Luis Franco Arza 2020-06-16 22:36:23 +02:00
parent f0c2113cbb
commit 57ed1b8872
4 changed files with 104 additions and 0 deletions

View File

@ -78,6 +78,14 @@ UPDATE_PREPARE_ENV = "environments/lifecycle/update-prepare.yaml"
UPDATE_CONVERGE_ENV = "environments/lifecycle/update-converge.yaml" UPDATE_CONVERGE_ENV = "environments/lifecycle/update-converge.yaml"
UPGRADE_PREPARE_ENV = "environments/lifecycle/upgrade-prepare.yaml" UPGRADE_PREPARE_ENV = "environments/lifecycle/upgrade-prepare.yaml"
UPGRADE_CONVERGE_ENV = "environments/lifecycle/upgrade-converge.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_PREPARE_ENV = "environments/lifecycle/ffwd-upgrade-prepare.yaml"
FFWD_UPGRADE_CONVERGE_ENV = "environments/lifecycle/ffwd-upgrade-converge.yaml" FFWD_UPGRADE_CONVERGE_ENV = "environments/lifecycle/ffwd-upgrade-converge.yaml"
FFWD_UPGRADE_PREPARE_SCRIPT = ("#!/bin/bash \n" FFWD_UPGRADE_PREPARE_SCRIPT = ("#!/bin/bash \n"

View File

@ -135,3 +135,7 @@ class UndercloudUpgradeNotConfirmed(Base):
class CellExportError(Base): class CellExportError(Base):
"""Cell export failed""" """Cell export failed"""
class BannedParameters(Base):
"""Some of the environment parameters provided should be removed"""

View File

@ -25,6 +25,7 @@ from tripleoclient import utils as oooutils
from tripleoclient.v1.overcloud_deploy import DeployOvercloud from tripleoclient.v1.overcloud_deploy import DeployOvercloud
from tripleoclient.workflows import deployment from tripleoclient.workflows import deployment
from tripleoclient.workflows import package_update from tripleoclient.workflows import package_update
from tripleoclient.workflows import parameters
CONF = cfg.CONF CONF = cfg.CONF
logging.register_options(CONF) logging.register_options(CONF)
@ -43,6 +44,8 @@ class UpgradePrepare(DeployOvercloud):
template = constants.UPGRADE_PREPARE_ENV template = constants.UPGRADE_PREPARE_ENV
forbidden_params = []
log = logging.getLogger(__name__ + ".UpgradePrepare") log = logging.getLogger(__name__ + ".UpgradePrepare")
def get_parser(self, prog_name): def get_parser(self, prog_name):
@ -75,6 +78,11 @@ class UpgradePrepare(DeployOvercloud):
parsed_args.environment_files = oooutils.prepend_environment( parsed_args.environment_files = oooutils.prepend_environment(
parsed_args.environment_files, templates_dir, parsed_args.environment_files, templates_dir,
self.template) 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) super(UpgradePrepare, self).take_action(parsed_args)
# Download stack_name-config as this is skiped in # Download stack_name-config as this is skiped in
@ -256,4 +264,6 @@ class UpgradeConvergeOvercloud(UpgradePrepare):
template = constants.UPGRADE_CONVERGE_ENV template = constants.UPGRADE_CONVERGE_ENV
forbidden_params = constants.UPGRADE_CONVERGE_FORBIDDEN_PARAMS
log = logging.getLogger(__name__ + ".UpgradeConvergeOvercloud") log = logging.getLogger(__name__ + ".UpgradeConvergeOvercloud")

View File

@ -10,6 +10,7 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import logging import logging
import os
import re import re
import yaml import yaml
@ -156,3 +157,84 @@ def generate_fencing_parameters(clients, **workflow_input):
if ('fencing_parameters' in payload and if ('fencing_parameters' in payload and
(payload.get('status', 'FAILED') == "SUCCESS")): (payload.get('status', 'FAILED') == "SUCCESS")):
return payload['fencing_parameters'] 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)))