Migrate script to update static hieradata

This change adds a new migration script to update static
hieradata for new release deployment.

The new static hieradata values will be generated by command
  sysinv-puppet create-static-config
and selected key/value pairs will update to static hieradata
files from current running system.

In particular this change includes new USM static hieradata
migration to 23.09.

TCs:
   passed migrating new USM key pairs from 22.12 -> 23.09

Story: 2010676
Task: 48909

Change-Id: I3560233876e6f0592933656b11a45c20ba1408e8
Signed-off-by: Bin Qian <bin.qian@windriver.com>
This commit is contained in:
Bin Qian 2023-10-06 16:23:04 +00:00
parent 81dedc557c
commit 9f9e66f0fe
1 changed files with 176 additions and 0 deletions

View File

@ -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/<ver>/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/<to_release>
# 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())