diff --git a/controllerconfig/controllerconfig/upgrade-scripts/05-update-static-hieradata.py b/controllerconfig/controllerconfig/upgrade-scripts/05-update-static-hieradata.py new file mode 100755 index 0000000000..ff7605a3fe --- /dev/null +++ b/controllerconfig/controllerconfig/upgrade-scripts/05-update-static-hieradata.py @@ -0,0 +1,176 @@ +#!/usr/bin/env python +# Copyright (c) 2023 Wind River Systems, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# +import os +import shutil +import subprocess +import sys +import tempfile +import yaml + +from controllerconfig.common import log + + +LOG = log.get_logger(__name__) + + +def get_list_of_keys(from_release, to_release): + keys = {"static": [], "secure_static": []} + if from_release == "22.12": + keys["secure_static"] = ["usm::keystone::auth::password", + "usm::keystone::authtoken::password", + "usm::api::keystone_password"] + keys["static"] = ["usm::api::keystone_user"] + + return keys + + +def main(): + action = None + from_release = None + to_release = None + arg = 1 + + while arg < len(sys.argv): + if arg == 1: + from_release = sys.argv[arg] + elif arg == 2: + to_release = sys.argv[arg] + elif arg == 3: + action = sys.argv[arg] + elif arg == 4: + # optional port parameter for USM upgrade + # port = sys.argv[arg] + pass + else: + print("Invalid option %s." % sys.argv[arg]) + return 1 + arg += 1 + + log.configure() + LOG.info("%s invoked from_release = %s to_release = %s action = %s" + % (sys.argv[0], from_release, to_release, action)) + res = 0 + if action == "migrate": + try: + res = do_update(from_release, to_release) + except Exception: + LOG.exception("Updating static hieradata action failed") + res = 1 + + return res + + +def do_update(from_release, to_release): + with tempfile.TemporaryDirectory() as tempdir: + _do_update_under_temp(from_release, to_release, tempdir) + + +def _do_update_under_temp(from_release, to_release, tempdir): + SYSTEM_STATIC_FILE = "static.yaml" + SECURE_STATIC_FILE = "secure_static.yaml" + HIERADATA_PATH = "/opt/platform/puppet/%s/hieradata" + + # copy static hieradata yaml files to tempdir + system_static_file = \ + os.path.join(HIERADATA_PATH % to_release, SYSTEM_STATIC_FILE) + secure_static_file = \ + os.path.join(HIERADATA_PATH % to_release, SECURE_STATIC_FILE) + tmp_system_static_file = os.path.join(tempdir, SYSTEM_STATIC_FILE) + tmp_secure_static_file = os.path.join(tempdir, SECURE_STATIC_FILE) + files_to_copy = {system_static_file: tmp_system_static_file, + secure_static_file: tmp_secure_static_file} + + for src in files_to_copy: + dest = files_to_copy[src] + try: + shutil.copyfile(src, dest) + except IOError as e: + LOG.error("Failed copying file %s to %s. Error %s", src, dest, e) + raise + + # generate static config to /opt/platform/puppet//hieradata + cmd = ["sysinv-puppet", "create-static-config"] + process = subprocess.Popen( + cmd, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + universal_newlines=True) + + out, err = process.communicate() + if process.returncode != 0: + msg = "Failed to generate static config. Command output: \n%s" % err + LOG.error(msg) + raise Exception(msg) + + src_file_mapping = {"static": system_static_file, + "secure_static": secure_static_file} + + tmp_file_mapping = {"static": tmp_system_static_file, + "secure_static": tmp_secure_static_file} + list_of_keys = get_list_of_keys(from_release, to_release) + + # find the new generated static data and update the static hieradata + # from previous release + for tag in list_of_keys: + keys = list_of_keys[tag] + if len(keys) > 0: + tmp_file = tmp_file_mapping[tag] + src_file = src_file_mapping[tag] + # read the key/value from src_file + # (generated by sysinv-puppet create-static-config) + # at /opt/platform/puppet/hieradata/ + # write the key/value to tmp_file at temp directory + with open(src_file, "r") as src: + try: + src_data = yaml.load(src, Loader=yaml.Loader) + except Exception as e: + LOG.error("Failed to load %s. Error %s" % (src_file, e)) + raise + + with open(tmp_file, "r") as dest: + try: + dest_data = yaml.load(dest, Loader=yaml.Loader) + except Exception as e: + LOG.error("Failed to load %s. Error %s" % (tmp_file, e)) + raise + + for key in keys: + if key in src_data: + dest_data[key] = src_data[key] + else: + LOG.warn("Expect %s generated in %s, but is not found" % + (key, src_file)) + + with open(tmp_file, "w") as dest: + try: + yaml.dump(dest_data, dest, default_flow_style=False) + except Exception as e: + LOG.error("Failed to update %s. Error %s" % + (tmp_file, e)) + raise + + # copy the updated static hieradata yaml files to hieradata directory + # of to release + dest_system_static_file = \ + os.path.join(HIERADATA_PATH % to_release, SYSTEM_STATIC_FILE) + dest_secure_static_file = \ + os.path.join(HIERADATA_PATH % to_release, SECURE_STATIC_FILE) + dest_file_mapping = {"static": dest_system_static_file, + "secure_static": dest_secure_static_file} + for tag in ["static", "secure_static"]: + try: + shutil.copyfile(tmp_file_mapping[tag], dest_file_mapping[tag]) + except Exception as e: + msg = "Failed to copy file %s to %s. Error %s" % ( + tmp_file_mapping[tag], + dest_file_mapping[tag], + e) + LOG.error(msg) + raise Exception(msg) + + +if __name__ == "__main__": + sys.exit(main())