From 3dbd0d6941dcab9cc9c1ff22ee8417946d41b04d Mon Sep 17 00:00:00 2001 From: Heitor Matsui Date: Mon, 11 Dec 2023 17:05:07 -0300 Subject: [PATCH] Cleanup obsolete upgrade scripts With the release of stx8 some scripts were deprecated and will not be needed on future upgrades, for example, those who were needed only for CentOS (stx6 or stx7) -> Debian (stx8) upgrade. This commit removes the deprecated scripts. Note: The USM "software deploy activate" command will be tested in the scope of another commit, since it is not yet implemented. Test Plan: PASS: legacy upgrade stx8 -> stx9 "migrate" and "activate" steps executed successfully PASS: USM "software deploy start" command executed successfully Story: 2010676 Task: 49196 Change-Id: Iee96afa1eca5d9d9751168a53635e5995c47aff4 Signed-off-by: Heitor Matsui --- ...9-adjust-debian-multipath-disks-support.py | 235 ------- .../10-update-centos-partition-to-debian.py | 613 ------------------ .../50-validate-oidc-auth-apps.py | 496 -------------- .../upgrade-scripts/61-move-ptp-parameters.py | 434 ------------- .../64-upgrade-cert-manager.sh | 268 -------- ...od-security-admission-controller-labels.py | 88 --- .../69-update-nfs-ip-address-alias.py | 125 ---- .../70-upgrade-oidc-auth-apps.sh | 224 ------- .../upgrade-scripts/72-remove-etcd-rbac.sh | 75 --- .../90-reset-k8s-key-file-permissions.sh | 42 -- .../98-sysinv-k8s-apiserver-param-upgrade.py | 227 ------- 11 files changed, 2827 deletions(-) delete mode 100755 controllerconfig/controllerconfig/upgrade-scripts/09-adjust-debian-multipath-disks-support.py delete mode 100755 controllerconfig/controllerconfig/upgrade-scripts/10-update-centos-partition-to-debian.py delete mode 100755 controllerconfig/controllerconfig/upgrade-scripts/50-validate-oidc-auth-apps.py delete mode 100755 controllerconfig/controllerconfig/upgrade-scripts/61-move-ptp-parameters.py delete mode 100644 controllerconfig/controllerconfig/upgrade-scripts/64-upgrade-cert-manager.sh delete mode 100644 controllerconfig/controllerconfig/upgrade-scripts/68-pod-security-admission-controller-labels.py delete mode 100644 controllerconfig/controllerconfig/upgrade-scripts/69-update-nfs-ip-address-alias.py delete mode 100755 controllerconfig/controllerconfig/upgrade-scripts/70-upgrade-oidc-auth-apps.sh delete mode 100755 controllerconfig/controllerconfig/upgrade-scripts/72-remove-etcd-rbac.sh delete mode 100644 controllerconfig/controllerconfig/upgrade-scripts/90-reset-k8s-key-file-permissions.sh delete mode 100644 controllerconfig/controllerconfig/upgrade-scripts/98-sysinv-k8s-apiserver-param-upgrade.py diff --git a/controllerconfig/controllerconfig/upgrade-scripts/09-adjust-debian-multipath-disks-support.py b/controllerconfig/controllerconfig/upgrade-scripts/09-adjust-debian-multipath-disks-support.py deleted file mode 100755 index 7c698cac5c..0000000000 --- a/controllerconfig/controllerconfig/upgrade-scripts/09-adjust-debian-multipath-disks-support.py +++ /dev/null @@ -1,235 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2023 Wind River Systems, Inc. -# -# SPDX-License-Identifier: Apache-2.0 -# -import psycopg2 -import re -import sys -from controllerconfig.common import log -from psycopg2.extras import RealDictCursor -from sysinv.agent import disk -from sysinv.common import constants - - -LOG = log.get_logger(__name__) - - -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] - 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" and ( - from_release == "21.12" and - to_release == "22.12" - ): - if not is_multipath(): - LOG.info("Multipath not detected, nothing to do") - return 0 - - try: - conn = psycopg2.connect("dbname=sysinv user=postgres") - do_update_i_host(conn) - do_update_i_idisks(conn) - do_update_partitions(conn) - do_update_i_pv(conn) - do_update_hw_settle(conn) - except Exception as e: - LOG.exception("Error: {}".format(e)) - res = 1 - return res - - -def do_update_partitions(conn): - partitions_db = get_partitions(conn) - - for partition_db in partitions_db: - new_path_device_node = transform_device_node_path( - partition_db["device_node"] - ) - new_part_path_device_path = transform_part_device_path( - partition_db["device_path"]) - - query = ( - "UPDATE partition SET device_path='{}', " - "device_node='{}' WHERE id={};".format( - new_part_path_device_path, - new_path_device_node, - partition_db["id"], - ) - ) - LOG.info( - "Update partition id={} query={}".format( - partition_db["id"], query) - ) - do_update_query(conn, query) - - -def do_update_i_pv(conn): - i_pvs = get_i_pvs(conn) - - for i_pv in i_pvs: - new_path_device_node = transform_device_node_path( - i_pv["disk_or_part_device_node"] - ) - - new_disk_or_part_device_path = transform_part_device_path( - i_pv["disk_or_part_device_path"] - ) - - query = ( - "UPDATE i_pv SET disk_or_part_device_node='{}', " - "lvm_pv_name='{}', disk_or_part_device_path='{}' " - "WHERE id={}").format( - new_path_device_node, - new_path_device_node, - new_disk_or_part_device_path, - i_pv["id"]) - LOG.info("Update i_pv id={} query= {}".format( - i_pv["id"], query)) - - do_update_query( - conn, - query - ) - - -def do_update_i_idisks(conn): - i_disks_db = get_idisks(conn) - - for i_disk_db in i_disks_db: - new_device_path = transform_device_path(i_disk_db["device_path"]) - query = "UPDATE i_idisk SET device_path='{}' "\ - "WHERE id={};".format( - new_device_path, i_disk_db["id"]) - LOG.info( - "Update disk id={} device_path={} " - "to {}".format( - i_disk_db["id"], - i_disk_db["device_path"], - new_device_path)) - do_update_query(conn, query) - - -def do_update_i_host(conn): - i_hosts = get_i_hosts(conn) - - for i_host in i_hosts: - query = ( - "UPDATE i_host SET boot_device='/dev/mapper/mpatha', " - "rootfs_device='/dev/mapper/mpatha' " - "WHERE id={};".format( - i_host["id"] - ) - ) - LOG.info("Update i_hosts id={} query= {}".format( - i_host["id"], query)) - - do_update_query(conn, query) - - -def get_idisks(conn): - query = "SELECT id, device_node, serial_id, device_id, device_path "\ - "FROM i_idisk;" - with conn.cursor(cursor_factory=RealDictCursor) as cur: - cur.execute(query) - i_disks = cur.fetchall() - return i_disks - - -def get_partitions(conn): - query = "SELECT id, device_node, device_path FROM partition;" - with conn.cursor(cursor_factory=RealDictCursor) as cur: - cur.execute(query) - partitions = cur.fetchall() - return partitions - - -def get_i_pvs(conn): - query = ( - "SELECT id, disk_or_part_device_node, lvm_pv_name, " - "disk_or_part_device_path FROM i_pv;" - ) - with conn.cursor(cursor_factory=RealDictCursor) as cur: - cur.execute(query) - pvs = cur.fetchall() - return pvs - - -def get_i_hosts(conn): - query = "SELECT id, boot_device, rootfs_device "\ - "FROM i_host WHERE personality='controller';" - with conn.cursor(cursor_factory=RealDictCursor) as cur: - cur.execute(query) - ihosts = cur.fetchall() - return ihosts - - -def do_update_query(conn, query): - with conn.cursor() as cur: - cur.execute(query) - conn.commit() - - -def do_update_hw_settle(conn): - query = "UPDATE i_host SET hw_settle='30'; " - LOG.info("Update hw_settle query= {}".format(query)) - do_update_query(conn, query) - - -def is_multipath(): - disk_operator = disk.DiskOperator() - system_disk = disk_operator.idisk_get()[0] - if constants.DEVICE_NAME_MPATH in system_disk["device_node"]: - return True - return False - - -def transform_device_node_path(path): - regex = r"(\/dev\/mapper\/mpath)([a-zA-Z])(\d)" - result = re.match(regex, path) - if result: - return "{}{}-part{}".format(result[1], result[2], result[3]) - return path - - -def transform_device_path(path): - # This regex is used to support QEMU virtualization devices, - # while all other real iSCSI devices start with 0 - regex = r"(\/dev\/disk\/by-id\/)dm-uuid-mpath-[0-9](.*)" - result = re.match(regex, path) - if result: - return "{}wwn-0x{}".format(result[1], result[2]) - return path - - -def transform_part_device_path(path): - # This regex is used to support QEMU virtualization devices, - # while all other real iSCSI devices start with 0 - regex = r"(\/dev\/disk\/by-id\/)dm-uuid-(.*)-mpath-[0-9](.*)" - result = re.match(regex, path) - if result: - return "{}wwn-0x{}-{}".format(result[1], result[3], result[2]) - return path - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/controllerconfig/controllerconfig/upgrade-scripts/10-update-centos-partition-to-debian.py b/controllerconfig/controllerconfig/upgrade-scripts/10-update-centos-partition-to-debian.py deleted file mode 100755 index 726c0467c4..0000000000 --- a/controllerconfig/controllerconfig/upgrade-scripts/10-update-centos-partition-to-debian.py +++ /dev/null @@ -1,613 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2022 Wind River Systems, Inc. -# -# SPDX-License-Identifier: Apache-2.0 -# -# This is a data migration script to pickup the partition changes during -# upgrade to Debian OS. -# The migration refreshes the partition, i_pv and i_lvg tables -# with the new partition configuration on filessytem of Debian StarlingX -# after controller-1 is upgraded. -# -import copy -import sys -import psycopg2 -from controllerconfig.common import log -from datetime import datetime -import operator -from psycopg2.extras import DictCursor -import uuid - -from sysinv.common import constants -from sysinv.common import utils as cutils -from sysinv.agent import partition as Partition - -LOG = log.get_logger(__name__) - -# set partition end_mib to END_OF_DISK_MIB to indicate -# that the partition will take all the remaining disk spaces -END_OF_DISK_MIB = "-1" -ONE_GIB = 1024 * 1024 * 1024 - - -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] - 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" and (from_release in ['22.06', '21.12'] and - to_release == '22.12'): - try: - res = do_update() - except Exception: - LOG.exception("Remapping partition action failed") - res = 1 - - return res - - -IPARTITION_COLUMNS = 'created_at', 'updated_at', 'deleted_at', 'uuid', \ - 'start_mib', 'end_mib', 'size_mib', 'device_path', \ - 'type_guid', 'type_name', 'idisk_id', 'idisk_uuid', \ - 'capabilities', 'status', 'foripvid', 'forihostid', \ - 'device_node' - -# worker node partition template -WORKER_PARTITION_LIST = [ - {'start_mib': '1', 'end_mib': '2', 'size_mib': '1', - 'type_guid': '21686148-6449-6e6f-744e-656564454649', - 'type_name': 'BIOS boot partition'}, - {'start_mib': '2', 'end_mib': '302', 'size_mib': '300', - 'type_guid': 'c12a7328-f81f-11d2-ba4b-00a0c93ec93b', - 'type_name': 'EFI system partition'}, - {'start_mib': '302', 'end_mib': '2350', 'size_mib': '2048', - 'type_guid': '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'type_name': 'Linux filesystem'}, - {'start_mib': '2350', 'end_mib': END_OF_DISK_MIB, 'size_mib': '0', - 'type_guid': 'e6d6d379-f507-44c2-a23c-238f2a3df928', - 'type_name': 'Linux LVM'}] - - -def get_disk_uuid_mapping(conn, forihostid): - # return map of idisk uuid indexed by device_node - with conn.cursor(cursor_factory=DictCursor) as cur: - sql = "SELECT uuid, device_node FROM i_idisk WHERE forihostid = %s;" - cur.execute(sql, (forihostid, )) - vals = cur.fetchall() - mappings = {} - for val in vals: - pair = {val["device_node"]: val["uuid"]} - mappings.update(pair) - return mappings - - -def get_idisks(conn, forihostid): - # do not consider disk change (replace, remove, or add new disk) - # during upgrade - sql = "SELECT * FROM i_idisk WHERE forihostid = %s;" - with conn.cursor(cursor_factory=DictCursor) as cur: - cur.execute(sql, (forihostid, )) - idisks = cur.fetchall() - return idisks - - -def get_cur_host(conn): - with conn.cursor(cursor_factory=DictCursor) as cur: - cur.execute("SELECT system_mode FROM i_system;") - system = cur.fetchone() - upgrade_controller = "controller-1" - if system["system_mode"] == "simplex": - upgrade_controller = "controller-0" - - cur.execute("SELECT id, boot_device FROM i_host WHERE hostname = %s;", - (upgrade_controller,)) - instance = cur.fetchone() - if instance is None: - raise Exception("Failed to retrieve host id for %s" % - upgrade_controller) - return instance - - -def get_disk_by_device_node(disks, device_path): - for disk in disks: - if disk["device_path"] in device_path: - return disk - elif constants.DEVICE_NAME_MPATH in disk["device_node"]: - path_split = disk["device_node"].split(constants.DEVICE_NAME_MPATH) - if path_split[0] in device_path and path_split[1] in device_path: - return disk - - raise Exception("Cannot locate the disk for %s" % device_path) - - -def get_rootdisk_partitions(conn, forihostid): - # get partitions on root disk of N release configuration - # the corresponding vg name is ammended to the end of each partition. - col_fmt = "p." + ", p.".join(IPARTITION_COLUMNS) - sql_fmt = "select %s, pv.lvm_vg_name " \ - "from partition as p left join i_pv pv on pv.id = foripvid " \ - "where idisk_uuid in" \ - " (select d.uuid from i_host join i_idisk d on" \ - " d.device_node = boot_device or" \ - " d.device_path = boot_device" \ - " where d.forihostid = %%s and i_host.id = %%s) " \ - "order by start_mib;" % col_fmt - sql = sql_fmt % (forihostid, forihostid) - partitions = [] - with conn.cursor(cursor_factory=DictCursor) as cur: - cur.execute(sql, (forihostid, forihostid)) - partitions = cur.fetchall() - return partitions - - -def get_controller_partition_template(rootdisk): - # return list of partitions created on rootdisk, sorted by physical - # order (start_mib) - - root_device_path = rootdisk["device_path"] - root_device_node = rootdisk["device_node"] - po = Partition.PartitionOperator() - partitions = po.ipartition_get(skip_gpt_check=True) - - # sort by start_mib - now = datetime.now() - - partition_additions = { - "created_at": now, - "updated_at": now, - "deleted_at": None, - # foripvid will be populated when updating i_pv table - "foripvid": None, - # TODO: check to load capabilities - "capabilities": None, - # These are the partitions that have already created - "status": 1 - } - - bootdisk_partitions = [] - for partition in partitions: - partition.update(partition_additions) - part_device_path = partition["device_path"] - if is_device_path_on_disk(part_device_path, root_device_path, - root_device_node): - partition["device_path"] = None - partition["device_node"] = None - bootdisk_partitions.append(partition) - sorted_list = sorted(bootdisk_partitions, - key=operator.itemgetter('start_mib')) - - # the last partition takes all the rest of disk spaces - sorted_list[-1]["end_mib"] = END_OF_DISK_MIB - return sorted_list - - -def get_node_partition_template(part_list): - # create a partition template from a list of partitions - template = copy.deepcopy(part_list) - - now = datetime.now() - partition_additions = { - "created_at": now, - "updated_at": now, - "deleted_at": None, - # foripvid will be populated when updating i_pv table - "foripvid": None, - # TODO: check to load capabilities - "capabilities": None, - # These are the partitions that have already created - "status": 1, - "device_path": None, - "device_node": None - } - - for partition in template: - partition.update(partition_additions) - - return template - - -def get_ipartitions(forihostid, template, rootdisk): - # localize default partitions on rootdisk - partitions = copy.deepcopy(template) - - rootdisk_device_node = rootdisk["device_node"] - rootdisk_device_path = rootdisk["device_path"] - idx = 1 - for partition in partitions: - # regenerate uuid - partition["uuid"] = "%s" % uuid.uuid4() - partition["idisk_id"] = rootdisk["id"] - partition["idisk_uuid"] = rootdisk["uuid"] - partition["forihostid"] = forihostid - device_node, device_path = \ - build_device_node_path(rootdisk_device_node, rootdisk_device_path, - idx) - partition["device_node"] = device_node - partition["device_path"] = device_path - if partition["end_mib"] == END_OF_DISK_MIB: - # get all the rest of disk spaces - end_mib = int(rootdisk["size_mib"]) + 1 - partition["end_mib"] = str(end_mib) - partition["size_mib"] = str(end_mib - int(partition["start_mib"])) - idx += 1 - - return partitions - - -def build_device_node_path(disk_device_node, disk_device_path, device_idx): - """Builds the partition device path and device node based on last - partition number and assigned disk. - """ - if constants.DEVICE_NAME_NVME in disk_device_node: - device_node = "%sp%s" % (disk_device_node, device_idx) - else: - device_node = "%s%s" % (disk_device_node, device_idx) - device_path = cutils.get_part_device_path(disk_device_path, - str(device_idx)) - return device_node, device_path - - -def is_device_path_on_disk(device_path, disk_device_path, disk_device_node): - if disk_device_path in device_path: - return True - elif constants.DEVICE_NAME_MPATH in disk_device_node: - split_path = device_path.split("-part") - if split_path[0] in disk_device_path: - return True - return False - - -def append_additional_partitions(conn, new_rootdisk_partitions, - host, rootdisk): - # append user created partitions on rootdisk from the N release - # new_rootdisk_partitions is new default partitions on root disk - # will append additional user partitions on root disk to the list - # to form the entier partition list on root disk - - forihostid = host["id"] - # get partitions on rootdisk from N db - rootdisk_partitions = get_rootdisk_partitions(conn, forihostid) - - rootdisk_device_node = rootdisk["device_node"] - LOG.info("Previous release ipartitions on root disk %s \n%s" % - (rootdisk_device_node, rootdisk_partitions)) - - # find the last default partition in ordered list. All default - # partitions will be replaced with new default partitions. - for partition in rootdisk_partitions: - if partition["lvm_vg_name"] == "cgts-vg": - # found the 1st cgts-vg. - # cgts-vg in new load will replace the existing cgts-vg partition - # on the node as PV of cgts-vg - new_rootdisk_partitions[-1]["foripvid"] = partition["foripvid"] - break - else: - # a cgts-vg is not found on root disk... game over - raise Exception("cgts-vg partition is not found on rootdisk") - - ipartitions = [] - for partition in new_rootdisk_partitions: - ipartition = [partition[key] for key in IPARTITION_COLUMNS] - ipartitions.append(ipartition) - return ipartitions - - -def update_partition(conn, ipartitions, forihostid, rootdisk): - dp_idx = IPARTITION_COLUMNS.index("device_path") - partition_disk_uuid_idx = IPARTITION_COLUMNS.index("idisk_uuid") - rootdisk_uuid = rootdisk["uuid"] - - with conn.cursor(cursor_factory=DictCursor) as cur: - # 1. delete all partitions on rootdisk - sql = "DELETE FROM partition where idisk_uuid = %s;" - LOG.info("Delete partition records on root disk: uuid(%s)" % - rootdisk_uuid) - cur.execute(sql, (rootdisk_uuid, )) - count = cur.rowcount - LOG.info("%s partition records are deleted" % count) - - # 2. recreate records for the partitions on created root disk - LOG.info("recreate partition record on root disk %s" % rootdisk_uuid) - for ipartition in ipartitions: - if ipartition[partition_disk_uuid_idx] != rootdisk_uuid: - # skip non-rootdisk partitions - continue - - device_path = ipartition[dp_idx] - col_fmt = ", ".join(["%s"] * len(IPARTITION_COLUMNS)) - values_fmt = ", ".join(["%%s"] * len(IPARTITION_COLUMNS)) - sql_fmt = "INSERT INTO partition (%s) VALUES(%s)" % \ - (col_fmt, values_fmt) - sql = sql_fmt % IPARTITION_COLUMNS - cur.execute(sql, ipartition) - if cur.rowcount == 1: - LOG.info("Create new partition %s, %s" % - (device_path, ipartition[partition_disk_uuid_idx])) - - LOG.info("Done recreate partitions on root disk") - - sql = "SELECT id, uuid, device_node, device_path, foripvid " \ - "FROM partition WHERE forihostid = %s" - cur.execute(sql, (forihostid, )) - partitions = [{"id": d[0], "uuid": d[1], "device_node": d[2], - "device_path": d[3], "foripvid": d[4], - "type": "partition"} - for d in cur.fetchall()] - return partitions - - -def update_pvs(conn, forihostid): - with conn.cursor(cursor_factory=DictCursor) as cur: - # partition records are pointing to i_pv, but the i_pv reference - # to partition uuid (disk_or_part_uuid) and device_node - # (disk_or_part_device_node) needs to relink. - # this is a double link - - # update primary cgts-vg pv, this pv and partition have been - # provisioned - sql = "UPDATE i_pv " \ - "SET disk_or_part_uuid = p.uuid, " \ - "disk_or_part_device_node = p.device_node, " \ - "disk_or_part_device_path = p.device_path, " \ - "lvm_pv_name = p.device_node " \ - "FROM i_pv AS v JOIN partition AS p ON p.foripvid = v.id " \ - "WHERE v.forihostid = %s AND p.forihostid = %s AND" \ - " i_pv.id = v.id AND p.status <> %s" - cur.execute(sql, (forihostid, forihostid, - constants.PARTITION_CREATE_ON_UNLOCK_STATUS)) - LOG.info("Updated %s PVs" % cur.rowcount) - - # Delete the PVs that link to user partition on boot disk. - # As the user partitions on boot disk are deleted during - # update_partition, the orphan partition PVs are to be deleted. - sql = "DELETE FROM i_pv " \ - "WHERE pv_type = 'partition' AND forihostid = %s AND id NOT IN" \ - " (SELECT foripvid FROM partition WHERE forihostid = %s AND " \ - "foripvid IS NOT Null)" - cur.execute(sql, (forihostid, forihostid)) - count = cur.rowcount - if count > 0: - LOG.info("Deleted %s PVs on user partition" % cur.rowcount) - - sql = "SELECT id, uuid, lvm_pv_name, pv_type, pv_state, " \ - "disk_or_part_uuid " \ - "FROM i_pv WHERE forihostid = %s" - cur.execute(sql, (forihostid, )) - pvs = [{"id": d[0], "uuid": d[1], "lvm_pv_name": d[2], "pv_type": - d[3], "pv_state": d[4], "disk_or_part_uuid": d[5]} - for d in cur.fetchall()] - return pvs - - -def update_lvgs(conn, forihostid): - with conn.cursor(cursor_factory=DictCursor) as cur: - # delete the lvgs that don't have any PVs. - # PVs can be deleted in update_pvs when associated partition is - # deleted as root disk space is reallocated to cgts-vg. - # nova-local can be deleted if all nova-local PVs are partitions - # on root disk. In this case all partitions and PVs are deleted - # in update_partition and update_pvs. - sql = "DELETE FROM i_lvg " \ - "WHERE forihostid = %s AND id NOT IN " \ - "(SELECT forilvgid FROM i_pv WHERE forihostid = %s AND " \ - "forilvgid IS NOT Null);" - cur.execute(sql, (forihostid, forihostid)) - count = cur.rowcount - if count > 0: - LOG.info("Deleted %s unused lvg" % count) - - # mark lvgs to be recreated during host unlock - sql = "UPDATE i_lvg SET vg_state = %s " \ - "WHERE lvm_vg_name <> 'cgts-vg' AND forihostid = %s;" - cur.execute(sql, (constants.LVG_ADD, forihostid)) - count = cur.rowcount - if count > 0: - LOG.info("%s lvg will be recreated" % count) - - sql = "SELECT id, uuid, lvm_vg_name FROM i_lvg WHERE forihostid = %s" - cur.execute(sql, (forihostid, )) - lvgs = [{"id": d[0], "uuid": d[1], "lvm_vg_name": d[2]} - for d in cur.fetchall()] - return lvgs - - -def get_disk_or_partition(conn, hostid): - sql = "SELECT uuid, device_node, device_path, foripvid, 'disk' as type " \ - "FROM i_idisk WHERE forihostid = %s UNION " \ - "SELECT uuid, device_node, device_path, foripvid, " \ - "'partition' as type FROM partition WHERE forihostid = %s;" - with conn.cursor(cursor_factory=DictCursor) as cur: - cur.execute(sql, (hostid, hostid)) - dops = [{"uuid": d[0], "device_node": d[1], "device_path": d[2], - "foripvid": d[3], "type": d[4]} - for d in cur.fetchall()] - return dops - - -def get_rootdisk(conn, hostid, boot_device): - # return device_node and device_path of rootdisk - sql = "SELECT id, uuid, device_node, device_path, size_mib " \ - "FROM i_idisk " \ - "WHERE (device_node = %s OR device_path = %s) AND forihostid = %s" - with conn.cursor(cursor_factory=DictCursor) as cur: - cur.execute(sql, (boot_device, boot_device, hostid)) - rootdisk = cur.fetchone() - return rootdisk - - -def get_hosts(conn): - with conn.cursor(cursor_factory=DictCursor) as cur: - cur.execute("SELECT id, hostname, personality, boot_device, " - "subfunctions " - "FROM i_host WHERE personality " - "IN ('controller', 'worker');") - nodes = cur.fetchall() - return nodes - - -def update_host(conn, host, partition_template): - hostid = host["id"] - hostname = host["hostname"] - - rootdisk = get_rootdisk(conn, hostid, host["boot_device"]) - ipartitions = get_ipartitions(hostid, - partition_template, rootdisk) - - ipartitions = append_additional_partitions(conn, ipartitions, - host, rootdisk) - ipartitions = update_partition(conn, ipartitions, hostid, rootdisk) - - pvs = update_pvs(conn, hostid) - lvgs = update_lvgs(conn, hostid) - - LOG.info("partition migration summary %s:" % hostname) - LOG.info("=" * 60) - LOG.info("new list of lvgs:") - for lvg in lvgs: - LOG.info("%s" % lvg) - - LOG.info("new list of pvs:") - for pv in pvs: - LOG.info("%s" % pv) - - LOG.info("new list of partitions:") - for ip in ipartitions: - LOG.info(ip) - LOG.info("=" * 60) - - -def get_nova_local_pvs(conn, hostid): - sql = "SELECT pv_type, lvm_vg_name, lvm_pv_size, disk_or_part_uuid " \ - "FROM i_pv WHERE forihostid = %s AND lvm_vg_name='nova-local';" - with conn.cursor(cursor_factory=DictCursor) as cur: - cur.execute(sql, (hostid,)) - pvs = cur.fetchall() - return pvs - - -def create_instances_lv(conn, host, rootdisk_nova_local_size): - # size_gib is rounded up to nearest Gib - sql = "INSERT INTO host_fs" \ - "(created_at, uuid, name, size, logical_volume, forihostid) " \ - "VALUES(%s, %s, %s, %s, %s, %s);" - - created_at = datetime.now() - fs_uuid = "%s" % uuid.uuid4() - name = constants.FILESYSTEM_NAME_INSTANCES - # round up - size_gib = int((rootdisk_nova_local_size + ONE_GIB - 1) / ONE_GIB) - lv_name = constants.FILESYSTEM_LV_DICT[name] - forihostid = host["id"] - - with conn.cursor(cursor_factory=DictCursor) as cur: - cur.execute(sql, (created_at, fs_uuid, name, size_gib, - lv_name, forihostid)) - if cur.rowcount == 1: - LOG.info("%s: created cgts-vg:%s %sGib" % - (host["hostname"], lv_name, size_gib)) - - -def migrate_nova_local(conn, host, rootdisk): - # Migrate nova-local on boot disk - # This only needs to do on nodes with worker subfunction - # The migration rules: - # 1. if nova-local only exists on boot disk as a partition, - # the nova-local partition will be dropped, replaced with - # same size will be allocated to cgts-vg:instances-lv, - # 2. if nova-local only exists on separated disk, then no - # migration operation is needed - # 3. if nova-local exists on both boot disk partition and - # separated disk, nova-local partition on boot disk will - # be dropped, and with no other compensation. This will - # result total nova-local space reduced. - pvs = get_nova_local_pvs(conn, host["id"]) - if len(pvs) > 0: - LOG.info("Found nova-local pvs on rootdisk: %s", pvs) - - rootdisk_partitions = get_rootdisk_partitions(conn, host["id"]) - rootdisk_part_uuids = [p["uuid"] for p in rootdisk_partitions] - - rootdisk_nova_local_size = 0 - pv_on_other_disk = False - for pv in pvs: - pv_type = pv["pv_type"] - dop_uuid = pv["disk_or_part_uuid"] - if (pv_type == "partition" and dop_uuid in rootdisk_part_uuids): - rootdisk_nova_local_size += int(pv["lvm_pv_size"]) - else: - pv_on_other_disk = True - - if rootdisk_nova_local_size > 0: - if not pv_on_other_disk: - create_instances_lv(conn, host, rootdisk_nova_local_size) - else: - msg = "Total nova-local is reduced by %s bytes" - LOG.info(msg % rootdisk_nova_local_size) - - -def do_update(): - res = 0 - conn = psycopg2.connect("dbname=sysinv user=postgres") - - try: - cur_host = get_cur_host(conn) - rootdisk = get_rootdisk(conn, cur_host["id"], cur_host["boot_device"]) - controller_partitions = get_controller_partition_template(rootdisk) - worker_partitions = get_node_partition_template(WORKER_PARTITION_LIST) - - # migrate hosts with the partition template - hosts = get_hosts(conn) - for host in hosts: - personality = host["personality"] - - if personality == constants.WORKER: - partition_template = worker_partitions - elif personality == constants.CONTROLLER: - partition_template = controller_partitions - else: - # nothing to migrate on storage node, as no user partitions - # are allowed on root disk - continue - - if "worker" in host["subfunctions"]: - migrate_nova_local(conn, host, rootdisk) - update_host(conn, host, partition_template) - - except psycopg2.Error as ex: - conn.rollback() - LOG.exception(ex) - LOG.warning("Rollback changes") - res = 1 - except Exception as ex: - conn.rollback() - LOG.exception(ex) - LOG.warning("Rollback changes") - res = 1 - else: - LOG.info("All good, committing all changes into database") - conn.commit() - finally: - conn.close() - - return res - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/controllerconfig/controllerconfig/upgrade-scripts/50-validate-oidc-auth-apps.py b/controllerconfig/controllerconfig/upgrade-scripts/50-validate-oidc-auth-apps.py deleted file mode 100755 index 842316bd6b..0000000000 --- a/controllerconfig/controllerconfig/upgrade-scripts/50-validate-oidc-auth-apps.py +++ /dev/null @@ -1,496 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2022 Wind River Systems, Inc. -# -# SPDX-License-Identifier: Apache-2.0 - -# Conversion of oidc-auth-apps configuration -# -# Verify the supported configuration during health-query-upgrade. -# Backup overrides at upgrade start. -# Convert the configuration during upgrade activate. - -from controllerconfig.common import log -import copy -import os -import psycopg2 -from psycopg2.extras import RealDictCursor -import sys -import yaml - -LOG = log.get_logger(__name__) -log.configure() - -# This script is only valid for to/from releases: -ACCEPTED_FROM = ['21.12'] -ACCEPTED_TO = ['22.12'] -ACCEPTED_ACTIONS = ['health-check', 'start', 'migrate'] - -# this path should have been created by stx-oidc-auth-helm package -# with ownership assigned to postgres:postgres -BACKUP_PATH = '/var/opt/oidc-auth-apps' - -# list of charts in oidc-auth-apps; for sanity check only -oidc_charts = ['dex', 'oidc-client', 'secret-observer'] - -# Hard-coded chart values; matching the fluxcd manifest defaults -DEFAULT_HTTPSTLS_MOUNT = '/etc/dex/tls' -DEFAULT_HTTPSTLS_MODE = 420 -DEFAULT_HTTPSTLS_SECRET = 'local-dex.tls' - -# A dictionary of values selected from the overrides yaml during -# validate_overrides(). The selected values are used to convert -# the yaml from old dex to new dex -DEFINES = {} - -# validate yaml, instructions for what configurations accepted -validation_yaml = """ -name: "supported" -validation: "children" -optional: False -accepted: ["extraVolumeMounts", "extraVolumes", "config", "certs"] -children: -- name: "extraVolumeMounts" - validation: "any" - optional: True - define: "volumeMounts" -- name: "extraVolumes" - validation: "any" - optional: True - define: "volumes" -- name: "config" - validation: "children" - optional: False - define: "dex_config" - children: - - name: "web" - validation: "children" - optional: True - children: - - name: "tlsCert" - validation: "exact" - optional: True - define: "dex_https_tlsCert" - - name: "tlsKey" - validation: "exact" - optional: True - define: "dex_https_tlsKey" -- name: "certs" - validation: "children" - optional: True - accepted: ["grpc", "web"] - children: - - name: "grpc" - validation: "children" - optional: True - accepted: ["secret"] - children: - - name: "secret" - validation: "children" - optional: False - accepted: ["caName", "clientTlsName", "serverTlsName"] - children: - - name: "caName" - validation: "exact" - optional: False - define: "tls_secret" - - name: "clientTlsName" - validation: "exact" - optional: False - define: "tls_secret" - - name: "serverTlsName" - validation: "exact" - optional: False - define: "tls_secret" - - name: "web" - validation: "children" - optional: False - accepted: ["secret"] - children: - - name: "secret" - validation: "children" - optional: False - accepted: ["caName", "tlsName"] - children: - - name: "caName" - validation: "exact" - optional: False - define: "tls_secret" - - name: "tlsName" - validation: "exact" - optional: False - define: "tls_secret" - -""" - -# sql to fetch the user_overrides from DB for oidc-auth-apps -sql_overrides = ("SELECT helm_overrides.name, user_overrides" - " FROM helm_overrides" - " LEFT OUTER JOIN kube_app" - " ON helm_overrides.app_id = kube_app.id" - " WHERE kube_app.name = 'oidc-auth-apps'") - -sql_update = ("UPDATE helm_overrides" - " SET user_overrides = '%s'" - " FROM kube_app" - " WHERE helm_overrides.app_id = kube_app.id" - " AND kube_app.name = 'oidc-auth-apps'" - " AND helm_overrides.name = 'dex'") - - -def get_overrides(conn): - """Fetch helm overrides from DB""" - with conn.cursor(cursor_factory=RealDictCursor) as cur: - cur.execute(sql_overrides) - return cur.fetchall() - - -def backup_overrides(overrides, action='debug'): - """Dump helm overrides from DB to files in BACKUP_PATH""" - backup_path = os.path.join(BACKUP_PATH, action) - if not os.path.exists(backup_path): - os.makedirs(backup_path) - field = 'user_overrides' - for chart in overrides: - name = chart['name'] - if name not in oidc_charts: - LOG.warning("oidc-auth-apps: mismatch chart name '%s'", name) - if chart[field]: - document = yaml.safe_load(chart[field]) - if not document: - LOG.debug("oidc-auth-apps: %s empty document", name) - continue - backup_f = '_'.join([name, field]) - backup_f = '.'.join([backup_f, 'yaml']) - backup_f = os.path.join(backup_path, backup_f) - try: - with open(backup_f, 'w') as file: - yaml.dump(document, file, default_flow_style=False) - except IOError as e: - LOG.error("oidc-auth-apps: IOError: %s; file: %s", e, backup_f) - return 1 - LOG.info("oidc-auth-apps: user_overrides backed up to %s", backup_path) - return 0 - - -def validate_value(instruction, value): - """Verify a value""" - if instruction['validation'] == 'exact': - if type(value) not in [str, bool, int, float]: - LOG.error("oidc-auth-apps: value type %s not supported", - type(value)) - return False - if 'define' in instruction: - if instruction['define'] in DEFINES: - if DEFINES[instruction['define']] != value: - LOG.error("oidc-auth-apps: defined value is" - " mismatched '%s': '%s' != '%s'", - instruction['define'], - DEFINES[instruction['define']], - value) - LOG.error("oidc-auth-apps: instruction: %s", instruction) - return False - else: - DEFINES[instruction['define']] = value - LOG.debug("oidc-auth-apps: define: '%s' == '%s'", - instruction['define'], value) - if 'values' in instruction: - LOG.error("oidc-auth-apps: validation exact values" - " not implemented") - return False - else: - LOG.error("oidc-auth-apps: validation %s not supported", - instruction['validation']) - return False - LOG.debug("oidc-auth-apps: accept %s: %s: %s", - instruction['validation'], instruction, value) - return True - - -def printable_item(item): - """remove children from item to make it printable""" - printable = {} - printable['validation'] = item['validation'] - printable['name'] = item['name'] - printable['optional'] = item['optional'] - if 'define' in item: - printable['define'] = item['define'] - return printable - - -def define_complex_value(item, yaml_doc): - """Subroutine to fill DEFINES for complex values""" - if 'define' in item and item['validation'] != 'exact': - # Handle saving of complex values - if item['define'] in DEFINES: - LOG.error("oidc-auth-apps: complex values comparison" - " is not supported: %s", printable_item(item)) - return False - else: - DEFINES[item['define']] = copy.deepcopy(yaml_doc[item['name']]) - LOG.debug("oidc-auth-apps: define: '%s'", - item['define']) - return True - - -def validate_item(item, yaml_doc): - """Handle one list item from instruction""" - print_item = printable_item(item) - # If neither present nor optional: fail - # If not present, but optional: pass - optional = True - if 'optional' in item: - optional = item['optional'] - present = item['name'] in yaml_doc - if not (present or optional): - LOG.error("oidc-auth-apps: overrides omit required value:" - " %s", print_item) - return False - elif not present: - # pass - return True - if not define_complex_value(item, yaml_doc): - return False - - if item['validation'] == 'any': - # pass - LOG.debug("oidc-auth-apps: accept instruction: %s", print_item) - elif item['validation'] == 'exact': - if not validate_value(item, yaml_doc[item['name']]): - return False - elif item['validation'] == 'children': - accepted_keys = ['*'] - if 'accepted' in item: - if not validate_accepted(item['accepted'], yaml_doc[item['name']]): - return False - else: - accepted_keys = [x for x in yaml_doc[item['name']]] - if not recurse_validate_document(item['children'], - yaml_doc[item['name']]): - LOG.error("oidc-auth-apps: instruction: %s", print_item) - return False - else: - LOG.debug("oidc-auth-apps: accept instruction: %s: %s", - print_item, accepted_keys) - else: - LOG.error("oidc-auth-apps: instruction %s not implemented", - item['validation']) - return False - return True - - -def validate_accepted(accepted, yaml_doc): - """Check that each item in yaml is expected""" - if type(yaml_doc) is not dict: - LOG.error("oidc-auth-apps: accepting from list not implemented") - return False - error = False - for key in yaml_doc: - if key not in accepted: - error = True - LOG.error("oidc-auth-apps: key is not accepted: %s", key) - return not error - - -def recurse_validate_document(instruction, yaml_doc): - """Recursively verify the document against validation yaml""" - if type(instruction) is not list: - LOG.error("oidc-auth-apps: non-list instruction not implemented") - return False - for item in instruction: - if type(item) is not dict: - LOG.error("oidc-auth-apps: non-dict instruction item" - " not implemented") - return False - elif 'validation' not in item: - LOG.error("oidc-auth-apps: instruction missing validation") - return False - elif 'name' not in item: - LOG.error("oidc-auth-apps: instruction missing name") - return False - elif not validate_item(item, yaml_doc): - return False - return True - - -def validate_document(validation, document): - """Top level, verify the document against validation yaml""" - LOG.info("oidc-auth-apps: validating %s", validation['name']) - if validation['validation'] != 'children': - LOG.warning("oidc-auth-apps: root validation should be" - " children not %s", validation['validation']) - result = recurse_validate_document(validation['children'], document) - if 'accepted' in validation: - if not validate_accepted(validation['accepted'], document): - return False - if validation['optional']: - LOG.warning("oidc-auth-apps: root validation is optional") - return True - return result - - -def get_chart_override(overrides, chart): - """Get a specific set of overrides from the db value""" - chart_ov = None - for chart_ov in overrides: - if 'name' in chart_ov and chart_ov['name'] == chart: - break - else: - chart_ov = None - if not (chart_ov and 'user_overrides' in chart_ov): - return None - if not chart_ov['user_overrides']: - # A sanity check. Really shouldn't see this if oidc-auth-apps - # does not have dex overrides - either because the app is not - # applied, or because it failed to apply without overrides - return None - # convert the string to python structures - return yaml.safe_load(chart_ov['user_overrides']) - - -def validate_overrides(overrides): - """Check if the user_overrides are supported""" - DEFINES.clear() - if not overrides: - # dex without overrides isn't configured correctly - LOG.error("oidc-auth-apps: no overrides to validate") - return False - elif type(overrides) is not list: - # this shouldn't happen - LOG.error("oidc-auth-apps: overrides not list type") - return False - # Find dex; only dex helm needs conversion - document = get_chart_override(overrides, 'dex') - if not document: - LOG.error("oidc-auth-apps: no dex user_overrides to validate") - return False - validate = yaml.safe_load(validation_yaml) - return validate_document(validate, document) - - -def get_httpstls_mount(): - """Use the default unless the end-user had overridden it""" - if 'dex_https_tlsCert' in DEFINES: - return os.path.dirname(DEFINES['dex_https_tlsCert']) - # The default matches oic-auth-apps flucd manifest defaults - return DEFAULT_HTTPSTLS_MOUNT - - -def get_httpstls_secret(): - """Use the default unless the end-user had overridden it""" - if 'tls_secret' in DEFINES: - return DEFINES['tls_secret'] - # The default matches oic-auth-apps flucd manifest defaults - return DEFAULT_HTTPSTLS_SECRET - - -def merge_new_overrides(): - """Read DEFINES and prepare new overrides yaml""" - # Take the dex config as is: - new_doc = {'config': copy.deepcopy(DEFINES['dex_config'])} - # Convert old dex certs.web.secret to https-tls volume/volumeMounts - mount = {'mountPath': get_httpstls_mount(), 'name': 'https-tls'} - vol = {'secret': {'secretName': get_httpstls_secret(), - 'defaultMode': DEFAULT_HTTPSTLS_MODE}, - 'name': 'https-tls'} - # Take 'extra' volumes and mounts that may exist in old dex - # This is expected to be the WAD certificate - volumes = [] - volumeMounts = [] - if 'volumes' in DEFINES: - volumes = copy.deepcopy(DEFINES['volumes']) - if 'volumeMounts' in DEFINES: - volumeMounts = copy.deepcopy(DEFINES['volumeMounts']) - - # only add volumes/mounts if 'extra' was specified, or - # if there was non-default mount - if volumes or 'tls_secret' in DEFINES: - volumes.append(vol) - if volumeMounts or 'dex_https_tlsCert' in DEFINES: - volumeMounts.append(mount) - if volumes: - new_doc['volumes'] = volumes - if volumeMounts: - new_doc['volumeMounts'] = volumeMounts - return new_doc - - -def convert_overrides(overrides, conn): - """Convert the user_overrides from old dex to new""" - LOG.info("oidc-auth-apps: converting dex overrides") - if not validate_overrides(overrides): - return 1 - new_doc = merge_new_overrides() - res = backup_overrides(overrides, action='migrate') - if res != 0: - return res - # replace the dex user overrides - new_str = yaml.dump(new_doc, default_flow_style=False) - for override in overrides: - if override['name'] == 'dex': - override['user_overrides'] = new_str - res = backup_overrides(overrides, action='converted') - return res - - -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] - else: - print("Invalid option %s." % sys.argv[arg]) - return 1 - arg += 1 - if action not in ACCEPTED_ACTIONS: - LOG.debug("oidc-auth-apps: omit %s, %s, %s", - from_release, to_release, action) - return 0 - elif from_release not in ACCEPTED_FROM: - LOG.warning("oidc-auth-apps: not valid from release %s", - from_release) - return 0 - elif to_release not in ACCEPTED_TO: - LOG.warning("oidc-auth-apps: not valid to release %s", - to_release) - return 0 - - try: - conn = psycopg2.connect("dbname=sysinv user=postgres") - overrides = get_overrides(conn) - except Exception as ex: - LOG.exception("oidc-auth-apps: %s", ex) - return 1 - if not overrides: - LOG.error("oidc-auth-apps: failed to fetch overrides") - return 1 - elif not get_chart_override(overrides, 'dex'): - LOG.info("oidc-auth-apps: no dex overrides to convert") - return 0 - - if action == 'health-check': - if validate_overrides(overrides): - LOG.info("oidc-auth-apps: upgrade script health-check: success") - return 0 - return 1 - elif action == 'start': - return backup_overrides(overrides, action='start') - elif action == 'migrate': - convert_overrides(overrides, conn) - # A failure of oidc-auth-apps overrides conversion is unhandled. - # A patch for 21.12 release is needed to pre-test the - # compatibility of user overrides with expected configurations. - # 22.06 version of oidc-auth-apps will fail to apply if overrides - # are not converted. - return 0 - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/controllerconfig/controllerconfig/upgrade-scripts/61-move-ptp-parameters.py b/controllerconfig/controllerconfig/upgrade-scripts/61-move-ptp-parameters.py deleted file mode 100755 index bae6114267..0000000000 --- a/controllerconfig/controllerconfig/upgrade-scripts/61-move-ptp-parameters.py +++ /dev/null @@ -1,434 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2022 Wind River Systems, Inc. -# -# SPDX-License-Identifier: Apache-2.0 -# -# This script moves legacy PTP configuration (contents) from other tables: -# - Global (system-wide) ptp4l configuration in 'ptp' table, by creating -# a "legacy" 'ptp4l' entry in 'ptp_instances' table and inserting the -# corresponding entries in 'ptp_parameters'; -# - If advanced (specialized) ptp4l configuration is found in -# 'service_parameter' table, it inserts the corresponding entry(ies) in -# 'ptp_parameters' and refers to the "legacy" 'ptp4l' instance created -# for global (system-wide) configuration; -# - If phc2sys configuration is found in 'service_parameter' table, it -# inserts a 'phc2sys' entry in 'ptp_instances' table and inserts the -# corresponding entry(ies) in 'ptp_parameters'; -# - If any interface has 'ptp_role' not equal to 'none', it inserts a -# 'ptp4l' entry in 'ptp_instances' and inserts the corresponding entry -# in 'ptp_parameters'. - -import os -import sys -import psycopg2 -from controllerconfig.common import log -from datetime import datetime -from oslo_utils import uuidutils -from psycopg2.extras import DictCursor - -LOG = log.get_logger(__name__) - -INTERFACE_PTP_ROLE_NONE = 'none' -PLATFORM_PATH = '/opt/platform' # following tsconfig - -# Hidden file indicating the update/upgrade from legacy configuration -# has been already run -PTP_UPDATE_PARAMETERS_DONE = '.update_ptp_parameters_done' - -# PTP instance types -PTP_INSTANCE_TYPE_PTP4L = 'ptp4l' -PTP_INSTANCE_TYPE_PHC2SYS = 'phc2sys' - -# PTP instances created during migration -PTP_INSTANCE_LEGACY_PTP4L = 'ptp4l-legacy' -PTP_INSTANCE_LEGACY_PHC2SYS = 'phc2sys-legacy' - -# PTP interfaces created during migration -PTP_INTERFACE_LEGACY_PTP4L = 'ptp4lif-legacy' -PTP_INTERFACE_LEGACY_PHC2SYS = 'phc2sysif-legacy' - -# PTP parameter: owner types -PTP_PARAMETER_OWNER_INSTANCE = 'ptp-instance' -PTP_PARAMETER_OWNER_INTERFACE = 'ptp-interface' - -# Global PTP configuration migrated to legacy instance -PTP_PARAMETER_DELAY_MECHANISM = 'delay_mechanism' -PTP_PARAMETER_TIME_STAMPING = 'time_stamping' -PTP_PARAMETER_NETWORK_TRANSPORT = 'network_transport' - -# PTP service parameter sections -SERVICE_PARAM_SECTION_PTP_GLOBAL = 'global' -SERVICE_PARAM_SECTION_PTP_PHC2SYS = 'phc2sys' - -# Special PTP service parameters migrated from legacy configuration -PTP_PARAMETER_UDS_ADDRESS = 'uds_address' -PTP_PARAMETER_DOMAIN_NUMBER = 'domainNumber' -PTP_PARAMETER_DEFAULT_DOMAIN = '0' -PTP_PARAMETER_BC_JBOD = 'boundary_clock_jbod' -PTP_BOUNDARY_CLOCK_JBOD_1 = '1' - -# PTP service parameters NOT migrated from legacy configuration -PTP_PARAMETER_UPDATE_RATE = 'update-rate' -PTP_PARAMETER_SUMMARY_UPDATES = 'summary-updates' - - -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] - 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" and ( - from_release == '21.05' or from_release == '21.12'): - # Avoid attempt of updating PTP configuration after this upgrade - TO_CONFIG_PATH = PLATFORM_PATH + '/config/' + to_release + '/' - to_file = os.path.join(TO_CONFIG_PATH, PTP_UPDATE_PARAMETERS_DONE) - open(to_file, 'w').close() - - # First check on filesystem to detect if some update from old PTP - # configuration has been already done (before upgrading) - FROM_CONFIG_PATH = PLATFORM_PATH + '/config/' + from_release + '/' - from_file = os.path.join(FROM_CONFIG_PATH, PTP_UPDATE_PARAMETERS_DONE) - if not os.path.isfile(from_file): - conn = psycopg2.connect("dbname=sysinv user=postgres") - try: - # Second check, using the restored database contents - if _legacy_instances_not_found(conn): - _move_ptp_parameters(conn) - except psycopg2.Error as ex: - LOG.exception(ex) - res = 1 - except Exception as ex: - LOG.exception(ex) - res = 1 - finally: - if to_release.startswith('22'): - _cleanup_ptp_service_parameters(conn) - - # Committing all changes - LOG.info("Committing all PTP-related changes into database") - conn.commit() - conn.close() - - return res - - -def _legacy_instances_not_found(connection): - with connection.cursor(cursor_factory=DictCursor) as cur: - cur.execute("SELECT id FROM ptp_instances WHERE " - "name = %s OR name = %s;", - (PTP_INSTANCE_LEGACY_PTP4L, - PTP_INSTANCE_LEGACY_PHC2SYS)) - instance = cur.fetchone() - if instance is not None: - LOG.info("PTP legacy instance found with id = %s" % instance['id']) - return False - - LOG.info("No PTP legacy instances found") - - # If no legacy instances are present BUT any other instance is found, - # it would mean that instance must have been created after patching the - # current release making the new API fully functional, while legacy API was - # deprecated since then. - # In such case, legacy instances shouldn't be created automatically, even - # even based on the still existing (but now legacy and potentially - # untouched) 'ptp' table, because that would be an undesired behavior - with connection.cursor(cursor_factory=DictCursor) as cur: - cur.execute("SELECT id FROM ptp_instances;") - instance = cur.fetchone() - if instance is not None: - LOG.info("PTP legacy instances dismissed") - return False - - return True - - -def _insert_ptp_parameter_owner(connection, owner_type, capabilities=None): - owner_uuid = uuidutils.generate_uuid() - - with connection.cursor(cursor_factory=DictCursor) as cur: - LOG.debug("Creating PTP parameter owner %s" % owner_uuid) - cur.execute("INSERT INTO ptp_parameter_owners " - "(created_at, uuid, type, capabilities)" - "VALUES (%s, %s, %s, %s);", - (datetime.now(), owner_uuid, owner_type, capabilities)) - cur.execute("SELECT id FROM ptp_parameter_owners WHERE uuid = %s;", - (owner_uuid,)) - row = cur.fetchone() - owner_id = row['id'] - - return (owner_id, owner_uuid) - - -def _insert_ptp_instance(connection, - id, - name, - service, - extra_info=None): - with connection.cursor(cursor_factory=DictCursor) as cur: - LOG.debug("Creating PTP instance %s id %d" % (name, id)) - cur.execute("INSERT INTO ptp_instances " - "(id, name, service, extra_info) " - "VALUES (%s, %s, %s, %s);", - (id, name, service, extra_info)) - - -def _insert_ptp_interface(connection, - id, - name, - instance_id, - extra_info=None): - with connection.cursor(cursor_factory=DictCursor) as cur: - LOG.debug("Creating PTP interface %s id %d" % (name, id)) - cur.execute("INSERT INTO ptp_interfaces " - "(id, name, ptp_instance_id, extra_info) " - "VALUES (%s, %s, %s, %s);", - (id, name, instance_id, extra_info)) - - -def _insert_ptp_parameter(connection, name, value): - param_uuid = uuidutils.generate_uuid() - - with connection.cursor(cursor_factory=DictCursor) as cur: - LOG.debug("Creating PTP parameter %s=%s" % (name, value)) - cur.execute("INSERT INTO ptp_parameters " - "(created_at, uuid, name, value) " - "VALUES (%s, %s, %s, %s);", - (datetime.now(), param_uuid, name, value)) - - return param_uuid - - -def _add_parameter_to_instance(connection, owner_uuid, param_uuid): - with connection.cursor(cursor_factory=DictCursor) as cur: - LOG.debug("Adding PTP parameter %s to %s" % (param_uuid, owner_uuid)) - cur.execute("INSERT INTO ptp_parameter_ownerships " - "(created_at, uuid, parameter_uuid, owner_uuid) " - "VALUES (%s, %s, %s, %s);", - (datetime.now(), uuidutils.generate_uuid(), param_uuid, - owner_uuid)) - - -def _assign_instance_to_host(connection, instance_id, host_id): - with connection.cursor(cursor_factory=DictCursor) as cur: - LOG.debug("Assigning PTP instance %d to host %d" % - (instance_id, host_id)) - cur.execute("INSERT INTO ptp_instance_maps " - "(created_at, uuid, host_id, ptp_instance_id) " - "VALUES (%s, %s, %s, %s);", - (datetime.now(), uuidutils.generate_uuid(), host_id, - instance_id)) - - -def _assign_ptp_to_interface(connection, ptp_interface_id, interface_id): - with connection.cursor(cursor_factory=DictCursor) as cur: - LOG.debug("Assigning PTP interface %d to interface %d" % - (ptp_interface_id, interface_id)) - cur.execute("INSERT INTO ptp_interface_maps " - "(created_at, uuid, interface_id, ptp_interface_id) " - "VALUES (%s, %s, %s, %s);", - (datetime.now(), uuidutils.generate_uuid(), interface_id, - ptp_interface_id)) - - -def _cleanup_ptp_service_parameters(connection): - with connection.cursor(cursor_factory=DictCursor) as cur: - LOG.info("Removing PTP configuration from 'service_parameter' table") - cur.execute("DELETE FROM service_parameter WHERE service = 'ptp';") - - -def _move_ptp_parameters(connection): - with connection.cursor(cursor_factory=DictCursor) as cur: - # List all the hosts with clock_synchronization=ptp - cur.execute("SELECT id FROM i_host " - "WHERE clock_synchronization = 'ptp';") - ptp_hosts = cur.fetchall() - LOG.debug("There are %d hosts with clock_synchronization=ptp" % - len(ptp_hosts)) - - with connection.cursor(cursor_factory=DictCursor) as cur: - # List all PTP parameters in service-parameters table - cur.execute("SELECT section, name, value FROM service_parameter " - "WHERE service = 'ptp';") - param_entries = cur.fetchall() - LOG.debug("There are %d PTP rows in 'service_parameter' table" % - len(param_entries)) - - if len(ptp_hosts) == 0 and len(param_entries) == 0: - # No need for upgrade - return - - with connection.cursor(cursor_factory=DictCursor) as cur: - # List all the interfaces with ptp_role!=none - cur.execute("SELECT id FROM interfaces WHERE ptp_role <> %s;", - (INTERFACE_PTP_ROLE_NONE,)) - ptp_ifaces = cur.fetchall() - LOG.debug("There are %d interfaces with ptp_role != none" % - len(ptp_ifaces)) - - LOG.info("Creating PTP instances for legacy parameters") - - # Take system-wide parameters from legacy configuration - with connection.cursor(cursor_factory=DictCursor) as cur: - cur.execute("SELECT mechanism, mode, transport FROM ptp;") - ptp_config = cur.fetchone() - - delay_mechanism = str(ptp_config['mechanism']).upper() - time_stamping = str(ptp_config['mode']).lower() - network_transport = str(ptp_config['transport']).upper() - - # Legacy instance for system-wide parameters and those of - # section "global" in service-parameters table - (ptp4l_id, ptp4l_uuid) = _insert_ptp_parameter_owner( - connection, PTP_PARAMETER_OWNER_INSTANCE) - _insert_ptp_instance(connection, - ptp4l_id, - PTP_INSTANCE_LEGACY_PTP4L, - PTP_INSTANCE_TYPE_PTP4L) - - # Legacy PTP interface associated to legacy ptp4l instance - (ptp4lif_id, ptp4lif_uuid) = _insert_ptp_parameter_owner( - connection, PTP_PARAMETER_OWNER_INTERFACE) - _insert_ptp_interface(connection, - ptp4lif_id, - PTP_INTERFACE_LEGACY_PTP4L, - ptp4l_id) - - # Legacy instance for parameters of section "phc2sys" - (phc2sys_id, phc2sys_uuid) = _insert_ptp_parameter_owner( - connection, PTP_PARAMETER_OWNER_INSTANCE) - _insert_ptp_instance(connection, - phc2sys_id, - PTP_INSTANCE_LEGACY_PHC2SYS, - PTP_INSTANCE_TYPE_PHC2SYS) - - # Legacy PTP interface associated to legacy phc2sys instance - (phc2sysif_id, phc2sysif_uuid) = _insert_ptp_parameter_owner( - connection, PTP_PARAMETER_OWNER_INTERFACE) - _insert_ptp_interface(connection, - phc2sysif_id, - PTP_INTERFACE_LEGACY_PHC2SYS, - phc2sys_id) - - # Add 'uds_address' parameter to phy2sys instance for linkage - # with ptp4l instance - uds_address_path = '/var/run/ptp4l-%s' % PTP_INSTANCE_LEGACY_PTP4L - uds_address_uuid = _insert_ptp_parameter(connection, - PTP_PARAMETER_UDS_ADDRESS, - uds_address_path) - _add_parameter_to_instance(connection, phc2sys_uuid, uds_address_uuid) - - # Assign legacy instances to all hosts with clock_synchronization=ptp - for host in ptp_hosts: - _assign_instance_to_host(connection, ptp4l_id, host['id']) - _assign_instance_to_host(connection, phc2sys_id, host['id']) - - # Assign legacy PTP interfaces to all interfaces with ptp_role!=none - for iface in ptp_ifaces: - _assign_ptp_to_interface(connection, ptp4lif_id, iface['id']) - _assign_ptp_to_interface(connection, phc2sysif_id, iface['id']) - - # Copy service-parameter PTP entries, if any - domain_number = PTP_PARAMETER_DEFAULT_DOMAIN - for param in param_entries: - - if (param['name'] == PTP_PARAMETER_UPDATE_RATE or - param['name'] == PTP_PARAMETER_SUMMARY_UPDATES): - LOG.info("Found %s parameter, ignored" % param['name']) - continue - - if param['name'] == PTP_PARAMETER_DOMAIN_NUMBER: - domain_number = param['value'] # overwrite default - continue # skip it for below - - if param['name'] == PTP_PARAMETER_DELAY_MECHANISM: - delay_mechanism = str(param['value']).upper() # overwrite global - continue # skip it for below - - if param['name'] == PTP_PARAMETER_TIME_STAMPING: - time_stamping = str(param['value']).lower() # overwrite global - continue # skip it for below - - if param['name'] == PTP_PARAMETER_NETWORK_TRANSPORT: - network_transport = str(param['value']).upper() # overwrite global - continue # skip it for below - - if param['section'] == SERVICE_PARAM_SECTION_PTP_GLOBAL: - owner_uuid = ptp4l_uuid - elif param['section'] == SERVICE_PARAM_SECTION_PTP_PHC2SYS: - owner_uuid = phc2sys_uuid - else: - raise Exception("Unexpected PTP section in " - "'service-parameter' table") - - param_uuid = _insert_ptp_parameter(connection, - param['name'], - param['value']) - _add_parameter_to_instance(connection, owner_uuid, param_uuid) - - # Whatever 'global' parameter has been found, it must be - # added also to phc2sys instance, since now this has own - # configuration file - if param['section'] == SERVICE_PARAM_SECTION_PTP_GLOBAL: - _add_parameter_to_instance(connection, - phc2sys_uuid, - param_uuid) - - domain_number_uuid = _insert_ptp_parameter( - connection, PTP_PARAMETER_DOMAIN_NUMBER, domain_number) - _add_parameter_to_instance(connection, ptp4l_uuid, domain_number_uuid) - _add_parameter_to_instance(connection, - phc2sys_uuid, - domain_number_uuid) - ptp_delay_mechanism_uuid = _insert_ptp_parameter( - connection, PTP_PARAMETER_DELAY_MECHANISM, delay_mechanism) - _add_parameter_to_instance(connection, - ptp4l_uuid, - ptp_delay_mechanism_uuid) - _add_parameter_to_instance(connection, - phc2sys_uuid, - ptp_delay_mechanism_uuid) - ptp_time_stamping_uuid = _insert_ptp_parameter( - connection, PTP_PARAMETER_TIME_STAMPING, time_stamping) - _add_parameter_to_instance(connection, - ptp4l_uuid, - ptp_time_stamping_uuid) - _add_parameter_to_instance(connection, - phc2sys_uuid, - ptp_time_stamping_uuid) - ptp_network_transport_uuid = _insert_ptp_parameter( - connection, PTP_PARAMETER_NETWORK_TRANSPORT, network_transport) - _add_parameter_to_instance(connection, - ptp4l_uuid, - ptp_network_transport_uuid) - _add_parameter_to_instance(connection, - phc2sys_uuid, - ptp_network_transport_uuid) - - # Add 'boundary_clock_jbod' parameter to ptp4l instance if mode is - # "hardware" - if time_stamping == 'hardware': - bc_clock_jbod_uuid = _insert_ptp_parameter( - connection, PTP_PARAMETER_BC_JBOD, PTP_BOUNDARY_CLOCK_JBOD_1) - _add_parameter_to_instance(connection, ptp4l_uuid, bc_clock_jbod_uuid) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/controllerconfig/controllerconfig/upgrade-scripts/64-upgrade-cert-manager.sh b/controllerconfig/controllerconfig/upgrade-scripts/64-upgrade-cert-manager.sh deleted file mode 100644 index cd92fe0fe4..0000000000 --- a/controllerconfig/controllerconfig/upgrade-scripts/64-upgrade-cert-manager.sh +++ /dev/null @@ -1,268 +0,0 @@ -#!/bin/bash -# -# Copyright (c) 2022 Wind River Systems, Inc. -# -# SPDX-License-Identifier: Apache-2.0 -# -# -# This migration script is used for upgrading cert manager during the -# activate stage of a platform upgrade. It will: -# - dump existing certificates and issuers -# - convert the dump from deprecated v1alpha2 and v1alpha3 to v1 -# - remove the old armada version of cert manager -# - apply the new fluxcd version of cert manager -# -# A lot of the logic for determining application versions is copied -# from the generic application upgrade script in order to keep things -# consistent. -# -# This script should only be needed in the upgrade from the armada -# version of cert manager to the fluxcd version of cert manager. -# The cert manager version difference between the armada and fluxcd -# tarball is too great, and require additional steps for data migration. - -# The migration scripts are passed these parameters: -NAME=$(basename $0) -FROM_RELEASE=$1 -TO_RELEASE=$2 -ACTION=$3 - -# This will log to /var/log/platform.log -function log { - logger -p local1.info $1 -} - -# only run this script during upgrade-activate -if [ "$ACTION" != "activate" ]; then - exit 0 -fi - -# TODO: double check the inclusive condition. -if [[ "$TO_RELEASE" == "22.12" && "$FROM_RELEASE" == "22.06" ]]; then - log "upgrade to 22.12, skip" - exit 0 -fi - -PLATFORM_APPLICATION_PATH='/usr/local/share/applications/helm' -CONFIG_PERMDIR="/opt/platform/config/${TO_RELEASE}" -PATH=$PATH:/usr/local/sbin - -DELETE_RESULT_SLEEP=10 -DELETE_RESULT_ATTEMPTS=6 # ~1 min to delete app -UPLOAD_RESULT_SLEEP=10 -UPLOAD_RESULT_ATTEMPTS=24 # ~4 min to upload app -APPLY_RESULT_SLEEP=30 -APPLY_RESULT_ATTEMPTS=30 # ~15 min to update app -REMOVE_RESULT_SLEEP=10 -REMOVE_RESULT_ATTEMPTS=48 # ~8 min to remove app - -source /etc/platform/openrc -source /etc/platform/platform.conf - -EXISTING_APP_NAME='cert-manager' -EXISTING_APP_INFO=$(system application-show $EXISTING_APP_NAME --column app_version --column status --format yaml) -EXISTING_APP_VERSION=$(echo ${EXISTING_APP_INFO} | sed 's/.*app_version:[[:space:]]\(\S*\).*/\1/') -EXISTING_APP_STATUS=$(echo ${EXISTING_APP_INFO} | sed 's/.*status:[[:space:]]\(\S*\).*/\1/') - -# Extract the app name and version from the tarball name: app_name-version.tgz -UPGRADE_CERT_MANAGER_TARBALL=$(find $PLATFORM_APPLICATION_PATH -name "cert-manager*") -re='^(.*)-([0-9]+\.[0-9]+-[0-9]+).tgz' -[[ "$(basename $UPGRADE_CERT_MANAGER_TARBALL)" =~ $re ]] -UPGRADE_APP_NAME=${BASH_REMATCH[1]} -UPGRADE_APP_VERSION=${BASH_REMATCH[2]} - -# cert manager is a required application -# if it is not in the applied state, something is very wrong -if [ $EXISTING_APP_STATUS != "applied" ]; then - log "$NAME: ${UPGRADE_APP_NAME}, version ${EXISTING_APP_VERSION}, in bad state ${EXISTING_APP_STATUS}. Exiting for manual intervention..." - exit 1 -fi - -# assuming application is in applied state, but log it anyways -log "$NAME: cert-manager, version $EXISTING_APP_VERSION, is currently in the state: $EXISTING_APP_STATUS" - -# only upgrade the application if the versions dont match -# in case the upgrade activate failed due to other reasons, and this -# is not the first time this script is run -if [ "x${UPGRADE_APP_VERSION}" != "x${EXISTING_APP_VERSION}" ]; then - - # dump existing cert manager CRDs - # only dump once, to prevent overwriting existing dumps - # if the script is run more than once due to other failures - if [ ! -f "$CONFIG_PERMDIR/.cm_upgrade_dump" ]; then - log "$NAME: creating cert manager resources backup" - EXISTING_CM_RESOURCES=$(kubectl --kubeconfig=/etc/kubernetes/admin.conf \ - get issuer,clusterissuer,certificates,certificaterequests \ - --all-namespaces 2>&1 > /dev/null) - - if [ "${EXISTING_CM_RESOURCES}" == 'No resources found' ]; then - log "$NAME: no existing cert manager resources detected." - touch "$CONFIG_PERMDIR/.cm_upgrade_no_existing_resources" - else - kubectl get -o yaml \ - --kubeconfig=/etc/kubernetes/admin.conf \ - --all-namespaces \ - issuer,clusterissuer,certificates,certificaterequests \ - > $CONFIG_PERMDIR/cert-manager-backup.yaml - - if [ $? != 0 ]; then - log "$NAME: Failed to dump existing cert manager resources. Exiting for manual intervention..." - exit 1 - fi - - # remove the 'resourceVersion' of all cm resources in backup file - # to avoid version related errors while updating the resource - sed -i '/resourceVersion:/d' $CONFIG_PERMDIR/cert-manager-backup.yaml - if [ $? != 0 ]; then - log "$NAME: Failed to delete resourceVersion in cert-manager-backup.yaml. Exiting for manual intervention..." - exit 1 - fi - fi - - touch "$CONFIG_PERMDIR/.cm_upgrade_dump" - fi - - # convert dump using kubectl cert-manager kubernetes plugin - # .cm_upgrade_no_existing_resources check is to not convert an empty dump - # the dump can be empty if the system does not have any cert manager resources. - # this fails the kubectl plugin and the subsequent kubectl apply to restore the backup. - if [ ! -f "$CONFIG_PERMDIR/.cm_upgrade_convert" ] && \ - [ ! -f "$CONFIG_PERMDIR/.cm_upgrade_no_existing_resources" ]; then - log "$NAME: converting cert manager resources backup" - kubectl cert-manager convert \ - --output-version cert-manager.io/v1 \ - -f $CONFIG_PERMDIR/cert-manager-backup.yaml \ - > $CONFIG_PERMDIR/cert-manager-v1.yaml - - if [ $? != 0 ]; then - log "$NAME: Failed to convert cert manager resources. Exiting for manual intervention..." - exit 1 - fi - - touch "$CONFIG_PERMDIR/.cm_upgrade_convert" - fi - - # remove extra args overrides. - # we need to do this because our configuration of cert manager deletes secrets tied to - # cert manager certificates when the certificates are deleted. - # this means when we delete the certificates as part of data migration, the secrets are deleted. - # when the certificates are restored, the underlying secrets will be missing. - # this triggers a refresh on all cert manager certificates, which could mess up - # trust chains if the certificates are being used for a rootca, like in DC deployments - log "$NAME: removing extra args overrides from ${EXISTING_APP_NAME}" - system helm-override-update ${EXISTING_APP_NAME} cert-manager cert-manager --set extraArgs="" - - # apply old cert manager - log "$NAME: Applying ${EXISTING_APP_NAME}, version ${EXISTING_APP_VERSION}" - system application-apply ${EXISTING_APP_NAME} - - # Wait on the apply - for tries in $(seq 1 $APPLY_RESULT_ATTEMPTS); do - EXISTING_APP_STATUS=$(system application-show $EXISTING_APP_NAME --column status --format value) - if [ "${EXISTING_APP_STATUS}" == 'applied' ]; then - log "$NAME: ${EXISTING_APP_NAME} has been applied." - break - fi - sleep $APPLY_RESULT_SLEEP - done - - if [ $tries == $APPLY_RESULT_ATTEMPTS ]; then - log "$NAME: ${EXISTING_APP_NAME}, version ${EXISTING_APP_VERSION}, was not applied in the allocated time. Exiting for manual intervention..." - exit 1 - fi - - # remove old cert manager - log "$NAME: Removing ${EXISTING_APP_NAME}, version ${EXISTING_APP_VERSION}" - system application-remove -f ${EXISTING_APP_NAME} - - # Wait on the remove, should be somewhat quick - for tries in $(seq 1 $REMOVE_RESULT_ATTEMPTS); do - EXISTING_APP_STATUS=$(system application-show $EXISTING_APP_NAME --column status --format value) - if [ "${EXISTING_APP_STATUS}" == 'uploaded' ]; then - log "$NAME: ${EXISTING_APP_NAME} has been removed." - break - fi - sleep $REMOVE_RESULT_SLEEP - done - - if [ $tries == $REMOVE_RESULT_ATTEMPTS ]; then - log "$NAME: ${EXISTING_APP_NAME}, version ${EXISTING_APP_VERSION}, was not removed in the allocated time. Exiting for manual intervention..." - exit 1 - fi - - - # delete old cert manager - log "$NAME: Deleting ${EXISTING_APP_NAME}, version ${EXISTING_APP_VERSION}" - system application-delete -f ${EXISTING_APP_NAME} - - # Wait on the delete, should be quick - for tries in $(seq 1 $DELETE_RESULT_ATTEMPTS); do - EXISTING_APP_STATUS=$(system application-show $EXISTING_APP_NAME --column status --format value) - if [ -z "${EXISTING_APP_STATUS}" ]; then - log "$NAME: ${EXISTING_APP_NAME} has been deleted." - break - fi - sleep $DELETE_RESULT_SLEEP - done - - if [ $tries == $DELETE_RESULT_ATTEMPTS ]; then - log "$NAME: ${EXISTING_APP_NAME}, version ${EXISTING_APP_VERSION}, was not deleted in the allocated time. Exiting for manual intervention..." - exit 1 - fi - - - # upload new cert manager - log "$NAME: Uploading ${UPGRADE_APP_NAME}, version ${UPGRADE_APP_VERSION} from $UPGRADE_CERT_MANAGER_TARBALL" - system application-upload $UPGRADE_CERT_MANAGER_TARBALL - # Wait on the upload, should be quick - for tries in $(seq 1 $UPLOAD_RESULT_ATTEMPTS); do - UPGRADE_APP_STATUS=$(system application-show $UPGRADE_APP_NAME --column status --format value) - if [ "${UPGRADE_APP_STATUS}" == 'uploaded' ]; then - log "$NAME: ${UPGRADE_APP_NAME} has been uploaded." - break - fi - sleep $UPLOAD_RESULT_SLEEP - done - - if [ $tries == $UPLOAD_RESULT_ATTEMPTS ]; then - log "$NAME: ${UPGRADE_APP_NAME}, version ${UPGRADE_APP_VERSION}, was not uploaded in the allocated time. Exiting for manual intervention..." - exit 1 - fi - - - # apply new cert manager - log "$NAME: Applying ${UPGRADE_APP_NAME}, version ${UPGRADE_APP_VERSION}" - system application-apply ${UPGRADE_APP_NAME} - - # Wait on the apply - for tries in $(seq 1 $APPLY_RESULT_ATTEMPTS); do - UPGRADE_APP_STATUS=$(system application-show $UPGRADE_APP_NAME --column status --format value) - if [ "${UPGRADE_APP_STATUS}" == 'applied' ]; then - log "$NAME: ${UPGRADE_APP_NAME} has been applied." - break - fi - sleep $APPLY_RESULT_SLEEP - done - - if [ $tries == $APPLY_RESULT_ATTEMPTS ]; then - log "$NAME: ${UPGRADE_APP_NAME}, version ${UPGRADE_APP_VERSION}, was not applied in the allocated time. Exiting for manual intervention..." - exit 1 - fi - - # apply converted cert manager resources to the new cert manager application - # -f check is required because the cert manager backup could be empty - # if the system had no cert manager resources before the upgrade - if [ ! -f "$CONFIG_PERMDIR/.cm_upgrade_no_existing_resources" ]; then - log "$NAME: Restoring cert manager resource backup" - kubectl --kubeconfig=/etc/kubernetes/admin.conf apply -f $CONFIG_PERMDIR/cert-manager-v1.yaml - - if [ $? != 0 ]; then - log "$NAME: Failed to apply cert manager resources on the fluxcd version of cert manager. Exiting for manual intervention..." - exit 1 - fi - fi - - -fi - -exit 0 diff --git a/controllerconfig/controllerconfig/upgrade-scripts/68-pod-security-admission-controller-labels.py b/controllerconfig/controllerconfig/upgrade-scripts/68-pod-security-admission-controller-labels.py deleted file mode 100644 index 65293a8140..0000000000 --- a/controllerconfig/controllerconfig/upgrade-scripts/68-pod-security-admission-controller-labels.py +++ /dev/null @@ -1,88 +0,0 @@ -#!/usr/bin/python -# Copyright (c) 2022 Wind River Systems, Inc. -# -# SPDX-License-Identifier: Apache-2.0 -# -# This script adds pod security admission controller labels to a system -# after upgrades. These are applied by ansible and sysinv when a new -# namespace is created during application deployment. Upgrades needs -# to apply these labels to existing namespaces - -import subprocess -import sys -from controllerconfig.common import log -from sysinv.helm import common -LOG = log.get_logger(__name__) - - -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: - # postgres_port = sys.argv[arg] - pass - else: - print("Invalid option %s." % sys.argv[arg]) - return 1 - arg += 1 - log.configure() - if from_release == '21.12' and action == 'activate': - LOG.info("%s invoked from_release = %s to_release = %s action = %s" - % (sys.argv[0], from_release, to_release, action)) - add_pod_security_admission_controller_labels() - - -def add_pod_security_admission_controller_labels(): - try: - cmd = ["kubectl", "--kubeconfig=/etc/kubernetes/admin.conf", - "get", "namespaces", "-o=name"] - - namespaces_output = subprocess.check_output(cmd).decode("utf-8") - - except Exception: - LOG.error('Command failed:\n %s' % (cmd)) - raise Exception('Cannot get namespaces for pod security labels') - - for line in namespaces_output.splitlines(): - # we add pod security admission controller labels to namespaces that - # we create - namespace = line.replace("namespace/", "") - if namespace not in common.PRIVILEGED_NS: - continue - - security_version = 'latest' - if namespace in common.PRIVILEGED_NS: - security_level = 'privileged' - - try: - cmd = ["kubectl", "--kubeconfig=/etc/kubernetes/admin.conf", - "label", "--overwrite", "namespaces", namespace, - "pod-security.kubernetes.io/enforce=%s" - % (security_level), - "pod-security.kubernetes.io/warn=%s" - % (security_level), - "pod-security.kubernetes.io/audit=%s" - % (security_level), - "pod-security.kubernetes.io/enforce-version=%s" - % (security_version), - "pod-security.kubernetes.io/warn-version=%s" - % (security_version), - "pod-security.kubernetes.io/audit-version=%s" - % (security_version)] - subprocess.call(cmd) - except Exception as exc: - LOG.error('Command failed:\n %s\n%s' % (cmd, exc)) - raise Exception('Cannot assign pod security label') - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/controllerconfig/controllerconfig/upgrade-scripts/69-update-nfs-ip-address-alias.py b/controllerconfig/controllerconfig/upgrade-scripts/69-update-nfs-ip-address-alias.py deleted file mode 100644 index bd6d1cd3f3..0000000000 --- a/controllerconfig/controllerconfig/upgrade-scripts/69-update-nfs-ip-address-alias.py +++ /dev/null @@ -1,125 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2022 Wind River Systems, Inc. -# -# SPDX-License-Identifier: Apache-2.0 -# -# This migration script is used for update controller-platform-nfs -# during migrate stage of platform upgrade. It will: -# - create controller-platform-nfs alias for controller mgmt IP in -# /opt/platform/config//hosts file -# - remove the controller-platform-nfs-mgmt IP address from address DB - - -import sys - -import psycopg2 -from psycopg2.extras import DictCursor -import subprocess -import os.path - -from controllerconfig.common import log - -LOG = log.get_logger(__name__) - - -def _add_nfs_alias_to_hosts_file(connection, to_release): - with connection.cursor(cursor_factory=DictCursor) as cur: - - # during the upgrade-start the hosts file is copied from: - # /opt/platform/config// - # to - # /opt/platform/config// - # and /opt/platform/config//host is used to upgrade - # other controller/storage/worker nodes - # the host files from this path must be updated - CONFIG_PERMDIR = "/opt/platform/config/{}".format(to_release) - host_file = "{}/hosts".format(CONFIG_PERMDIR) - LOG.info("updating hosts in {}".format(CONFIG_PERMDIR)) - if (not os.path.exists(host_file)): - LOG.info("Skipping update of {}. File does not exists" - .format(host_file)) - return None - - LOG.info("Get controller-mgmt floating ip from 'addresses' table") - cur.execute("SELECT address FROM addresses WHERE " - "name='controller-mgmt';") - ctrl_mgmt_ip = cur.fetchone() - - # remove the controller-platform-nfs line from ${host_file} - sed_cmd = "sed -i '/controller\-platform\-nfs/d' {}".format(host_file) - - # Find the controller mgmt floating IP - # copy entire line and put in ctrl_float - grep_cmd = "grep -w '{}' {} | xargs -I ctrl_float" \ - .format(ctrl_mgmt_ip['address'], host_file) - - # Add the alias controller-platform-nfs to controller IP - # replacing the ${ctrl_float} by - # "${ctrl_float} controller-platform-nfs" - sed_concat = "sed -i -e " \ - "'s|ctrl_float|ctrl_float controller-platform-nfs|' {}" \ - .format(host_file) - - command = "{} && {} {}".format(sed_cmd, grep_cmd, sed_concat) - - sub = subprocess.Popen(command, shell=True, - stdout=subprocess.PIPE, stderr=subprocess.PIPE) - stdout, stderr = sub.communicate() - - if sub.returncode != 0: - LOG.error('Cmd Failed:\n%s\n.%s\n%s' % (command, stdout, stderr)) - raise Exception('Error controller-platform-nfs IP: {} ' - 'in etc/hosts'.format(ctrl_mgmt_ip['address'])) - LOG.info('alias controller-platform-nfs added for IP: {} ' - 'in {}'.format(ctrl_mgmt_ip['address'], host_file)) - - -def main(): - action = None - from_release = None - to_release = None - arg = 1 - res = 0 - - log.configure() - - 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] - else: - LOG.error("Invalid option %s." % sys.argv[arg]) - return 1 - arg += 1 - - LOG.info("%s invoked with from_release = %s to_release = %s action = %s" - % (sys.argv[0], from_release, to_release, action)) - - if action == "migrate" and from_release in ['21.12', '22.06']: - - conn = psycopg2.connect("dbname=sysinv user=postgres") - try: - _add_nfs_alias_to_hosts_file(conn, to_release) - - except psycopg2.Error as ex: - LOG.exception(ex) - LOG.warning("DB Connection error") - res = 1 - except Exception as ex: - LOG.exception(ex) - LOG.warning("Exception") - res = 1 - else: - LOG.info("controller-platform-nfs alias updated") - finally: - LOG.info("Closing DB connection") - conn.close() - - return res - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/controllerconfig/controllerconfig/upgrade-scripts/70-upgrade-oidc-auth-apps.sh b/controllerconfig/controllerconfig/upgrade-scripts/70-upgrade-oidc-auth-apps.sh deleted file mode 100755 index 0f2331fd1f..0000000000 --- a/controllerconfig/controllerconfig/upgrade-scripts/70-upgrade-oidc-auth-apps.sh +++ /dev/null @@ -1,224 +0,0 @@ -#!/bin/bash -# -# Copyright (c) 2022-2023 Wind River Systems, Inc. -# -# SPDX-License-Identifier: Apache-2.0 -# -# This migration script is used for replacing an app during the -# activate stage of a platform upgrade. The app is not otherwise -# handled by 65-k8s-app-upgrade.sh. The code will: -# - remove the old app version -# - run app specific code with is inserted into the script -# - apply the new app version -# -# The script is based on 64-upgrade-cert-manager.sh. Logic for -# determining application versions is copied from 65-k8s-app-upgrade.sh -# application upgrade script in order to keep things consistent. -# -# This script is intended initially as a generic template. -# -# The current copy is writen for oidc-auth-apps - -# The migration scripts are passed these parameters: -NAME=$(basename $0) -FROM_RELEASE=$1 -TO_RELEASE=$2 -ACTION=$3 - -# only run this script during upgrade-activate -if [ "$ACTION" != "activate" ]; then - exit 0 -fi - -# only run if from 21.12 release -if [ "$FROM_RELEASE" != "21.12" ]; then - exit 0 -fi - -# only run if to 22.12 release -if [ "$TO_RELEASE" != "22.12" ]; then - exit 0 -fi - -PLATFORM_APPLICATION_PATH='/usr/local/share/applications/helm' -UPGRADE_IN_PROGRESS_APPS_FILE='/etc/platform/.upgrade_in_progress_apps' -PATH=$PATH:/usr/local/sbin - -# conversion script; this script will convert the helm overrides -# reading from postgres and putting overrides into /var/opt/oidc-auth-apps -CONV_SCRIPT='/etc/upgrade.d/50-validate-oidc-auth-apps.py' -CONV_PARAMS="$FROM_RELEASE $TO_RELEASE migrate" - -DELETE_RESULT_SLEEP=10 -DELETE_RESULT_ATTEMPTS=6 # ~1 min to delete app -UPLOAD_RESULT_SLEEP=10 -UPLOAD_RESULT_ATTEMPTS=24 # ~4 min to upload app -APPLY_RESULT_SLEEP=30 -APPLY_RESULT_ATTEMPTS=30 # ~15 min to update app -REMOVE_RESULT_SLEEP=10 -REMOVE_RESULT_ATTEMPTS=48 # ~8 min to remove app - -source /etc/platform/openrc -source /etc/platform/platform.conf - -# This will log to /var/log/platform.log -function log { - logger -p local1.info $1 -} - -EXISTING_APP_NAME='oidc-auth-apps' -EXISTING_APP_INFO=$(system application-show $EXISTING_APP_NAME --column app_version --column status --format yaml) -EXISTING_APP_VERSION=$(echo ${EXISTING_APP_INFO} | sed 's/.*app_version:[[:space:]]\(\S*\).*/\1/') -EXISTING_APP_STATUS=$(echo ${EXISTING_APP_INFO} | sed 's/.*status:[[:space:]]\(\S*\).*/\1/') -ORIGINAL_APP_STATUS=$EXISTING_APP_STATUS - -# oidc-auth-apps has user overrides converted and saved for -# re-apply at this time -OIDC_OVERRIDES="/var/opt/oidc-auth-apps/converted" -OIDC_CHARTS="dex oidc-client secret-observer" -function oidc_specific_handling { - for chart in $OIDC_CHARTS; do - chart_f="${OIDC_OVERRIDES}/${chart}_user_overrides.yaml" - if [ ! -f "$chart_f" ]; then - continue - fi - system helm-override-update oidc-auth-apps "${chart}" kube-system \ - --values="${chart_f}" \ - || return 1 - done -} - -# Extract the app name and version from the tarball name: app_name-version.tgz -UPGRADE_TARBALL="$(find $PLATFORM_APPLICATION_PATH -name "${EXISTING_APP_NAME}*.tgz")" -filecount="$( echo "$UPGRADE_TARBALL" | wc -w )" -if [ -z "$UPGRADE_TARBALL" -o "$filecount" -ne 1 ]; then - log "$NAME: ${EXISTING_APP_NAME}, version ${EXISTING_APP_VERSION}, upgrade tarball not found (${filecount}). Exiting for manual intervention..." - exit 1 -fi - -re='^('${EXISTING_APP_NAME}')-([0-9]+\.[0-9]+-[0-9]+).tgz' -[[ "$(basename $UPGRADE_TARBALL)" =~ $re ]] -UPGRADE_APP_NAME=${BASH_REMATCH[1]} -UPGRADE_APP_VERSION=${BASH_REMATCH[2]} - -# Accept the application in the following states -ACCEPTED_STATES="applied uploaded" -if [[ " $ACCEPTED_STATES " != *" $EXISTING_APP_STATUS "* ]]; then - log "$NAME: ${UPGRADE_APP_NAME}, version ${EXISTING_APP_VERSION}, in bad state ${EXISTING_APP_STATUS}. Exiting for manual intervention..." - exit 1 -fi - -# assuming application is in applied state, but log it anyways -log "$NAME: $EXISTING_APP_NAME, version $EXISTING_APP_VERSION, is currently in the state: $EXISTING_APP_STATUS" - -# only upgrade the application if the versions dont match -# in case the upgrade activate failed due to other reasons, and this -# is not the first time this script is run -if [ "x${UPGRADE_APP_VERSION}" == "x${EXISTING_APP_VERSION}" ]; then - log "$NAME: $UPGRADE_APP_NAME, version $UPGRADE_APP_VERSION, is the same." - exit 0 -else - # Include app in upgrade in progress file - if ! grep -q "${EXISTING_APP_NAME},${EXISTING_APP_VERSION},${UPGRADE_APP_VERSION}" $UPGRADE_IN_PROGRESS_APPS_FILE; then - echo "${EXISTING_APP_NAME},${EXISTING_APP_VERSION},${UPGRADE_APP_VERSION}" >> $UPGRADE_IN_PROGRESS_APPS_FILE - fi - - # The 50-validate-oidc-auth-apps.py is used to convert helm - # overrides. Run it here on the active controller during - # uprade-activate - su postgres -c "$CONV_SCRIPT $CONV_PARAMS" - - if [ "$ORIGINAL_APP_STATUS" != "uploaded" ]; then - # remove old app version - log "$NAME: Removing ${EXISTING_APP_NAME}, version ${EXISTING_APP_VERSION}" - system application-remove -f ${EXISTING_APP_NAME} - - # Wait on the remove, should be somewhat quick - for tries in $(seq 1 $REMOVE_RESULT_ATTEMPTS); do - EXISTING_APP_STATUS=$(system application-show $EXISTING_APP_NAME --column status --format value) - if [ "${EXISTING_APP_STATUS}" == 'uploaded' ]; then - log "$NAME: ${EXISTING_APP_NAME} has been removed." - break - fi - sleep $REMOVE_RESULT_SLEEP - done - - if [ $tries == $REMOVE_RESULT_ATTEMPTS ]; then - log "$NAME: ${EXISTING_APP_NAME}, version ${EXISTING_APP_VERSION}, was not removed in the allocated time. Exiting for manual intervention..." - exit 1 - fi - fi - - # delete old app - log "$NAME: Deleting ${EXISTING_APP_NAME}, version ${EXISTING_APP_VERSION}" - system application-delete -f ${EXISTING_APP_NAME} - - # Wait on the delete, should be quick - for tries in $(seq 1 $DELETE_RESULT_ATTEMPTS); do - EXISTING_APP_STATUS=$(system application-show $EXISTING_APP_NAME --column status --format value) - if [ -z "${EXISTING_APP_STATUS}" ]; then - log "$NAME: ${EXISTING_APP_NAME} has been deleted." - break - fi - sleep $DELETE_RESULT_SLEEP - done - - if [ $tries == $DELETE_RESULT_ATTEMPTS ]; then - log "$NAME: ${EXISTING_APP_NAME}, version ${EXISTING_APP_VERSION}, was not deleted in the allocated time. Exiting for manual intervention..." - exit 1 - fi - - # upload new app version - log "$NAME: Uploading ${UPGRADE_APP_NAME}, version ${UPGRADE_APP_VERSION} from $UPGRADE_TARBALL" - system application-upload $UPGRADE_TARBALL - # Wait on the upload, should be quick - for tries in $(seq 1 $UPLOAD_RESULT_ATTEMPTS); do - UPGRADE_APP_STATUS=$(system application-show $UPGRADE_APP_NAME --column status --format value) - if [ "${UPGRADE_APP_STATUS}" == 'uploaded' ]; then - log "$NAME: ${UPGRADE_APP_NAME} has been uploaded." - break - fi - sleep $UPLOAD_RESULT_SLEEP - done - - if [ $tries == $UPLOAD_RESULT_ATTEMPTS ]; then - log "$NAME: ${UPGRADE_APP_NAME}, version ${UPGRADE_APP_VERSION}, was not uploaded in the allocated time. Exiting for manual intervention..." - exit 1 - fi - - if [ ! -d "$OIDC_OVERRIDES" ]; then - # this is a soft error, the upgrades procedure should not - # be affected by the absence of helm-overrides. Either the - # application is not configured, or the conversion of overrides - # was not possible - log "$NAME: ${UPGRADE_APP_NAME}, version ${UPGRADE_APP_VERSION}, no helm overrides to set. Upgrade of ${UPGRADE_APP_NAME} complete." - exit 0 - fi - oidc_specific_handling - if [ $? -ne 0 ]; then - log "$NAME: ${UPGRADE_APP_NAME}, version ${UPGRADE_APP_VERSION}, Helm overrides not set. Exiting for manual intervention..." - if [ "$ORIGINAL_APP_STATUS" == "uploaded" ]; then - # the application that is not applied does not interfere - exit 0 - else - exit 1 - fi - fi - - if [ "$ORIGINAL_APP_STATUS" == "uploaded" ]; then - log "$NAME: ${UPGRADE_APP_NAME}, version ${UPGRADE_APP_VERSION}: upload complete" - exit 0 - fi - - # dex won't apply without overrides, do not try - if [ ! -f "${OIDC_OVERRIDES}/dex_user_overrides.yaml" ]; then - log "$NAME: ${UPGRADE_APP_NAME}, version ${UPGRADE_APP_VERSION}: dex does not have overrides" - exit 0 - fi - - # apply new app version - log "$NAME: Applying ${UPGRADE_APP_NAME}, version ${UPGRADE_APP_VERSION}" - system application-apply ${UPGRADE_APP_NAME} -fi - -exit 0 diff --git a/controllerconfig/controllerconfig/upgrade-scripts/72-remove-etcd-rbac.sh b/controllerconfig/controllerconfig/upgrade-scripts/72-remove-etcd-rbac.sh deleted file mode 100755 index 5a52b3dd12..0000000000 --- a/controllerconfig/controllerconfig/upgrade-scripts/72-remove-etcd-rbac.sh +++ /dev/null @@ -1,75 +0,0 @@ -#!/bin/bash - -# Copyright (c) 2022 Wind River Systems, Inc. - -# SPDX-License-Identifier: Apache-2.0 - -# Remove Etcd RBAC against V2 backend -# -# Note: this can be removed in the release after STX7.0 - -. /etc/platform/platform.conf - -# This will log to /var/log/platform.log -function log { - logger -p local1.info $1 -} - -FROM_REL=$1 -TO_REL=$2 -ACTION=$3 - -ACCEPTED_REL="21.12" - -STATIC="/opt/platform/puppet/${sw_version}/hieradata/static.yaml" -NET_KEY="platform::etcd::params::bind_address" -NETVER_KEY="platform::etcd::params::bind_address_version" - -PORT="2379" -ETCD_CERT="/etc/etcd/etcd-client.crt" -ETCD_KEY="/etc/etcd/etcd-client.key" -ETCD_CA="/etc/etcd/ca.crt" -ETCD_CMDS="auth disable -user remove root -user remove apiserver-etcd-client" - -remove-etcd-rbac() -{ - local host_addr - local host_ver - local server_url - - if [[ ! -f "${STATIC}" ]]; then - log "Script $0 does not find static yaml file: $STATIC" - exit 1 - fi - - host_addr="$( grep "^${NET_KEY}:" "${STATIC}" | gawk '{print $NF}' )" - host_ver="$( grep "^${NETVER_KEY}:" "${STATIC}" | gawk '{print $NF}' )" - - if [ "$host_ver" == "6" ]; then - server_url="https://[${host_addr}]:${PORT},https://127.0.0.1:${PORT}" - else - server_url="https://${host_addr}:${PORT},https://127.0.0.1:${PORT}" - fi - - # Ignore the return code of etcdctl calls here because the - # configuration against v2 API does not persist BnR; it may be absent - while read -r cmd; do - etcdctl --cert-file="${ETCD_CERT}" \ - --key-file="${ETCD_KEY}" \ - --ca-file="${ETCD_CA}" \ - --endpoint="${server_url}" \ - $cmd - done <<<"$ETCD_CMDS" -} - -log "Script ${0} invoked with from_release = ${FROM_REL} to_release = ${TO_REL} action = ${ACTION}" - -if [ ${FROM_REL} == "$ACCEPTED_REL" -a ${ACTION} == "activate" ]; then - remove-etcd-rbac -else - log "Script $0: No actions required from release $FROM_REL to $TO_REL with action $ACTION" -fi - -exit 0 diff --git a/controllerconfig/controllerconfig/upgrade-scripts/90-reset-k8s-key-file-permissions.sh b/controllerconfig/controllerconfig/upgrade-scripts/90-reset-k8s-key-file-permissions.sh deleted file mode 100644 index 7dbd2ba21b..0000000000 --- a/controllerconfig/controllerconfig/upgrade-scripts/90-reset-k8s-key-file-permissions.sh +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/bash -# -# Copyright (c) 2022 Wind River Systems, Inc. -# -# SPDX-License-Identifier: Apache-2.0 -# -# This script resets permissions of some Kubernetes *.key files to 0600 on controller-0 only. - -FROM_RELEASE=$1 -TO_RELEASE=$2 -ACTION=$3 - -# This will log to /var/log/platform.log -function log { - logger -p local1.info $1 -} - -reset-k8s-key-file-permissions() -{ - APISERVER_KEY="/etc/kubernetes/pki/apiserver-etcd-client.key" - CA_KEY="/etc/kubernetes/pki/ca.key" - declare -a FILE_LIST=("$APISERVER_KEY" "$CA_KEY" ) - - for file in "${FILE_LIST[@]}"; do - if [ -f "$file" ]; then - log "Resetting permissions for file $file ..." - chmod 0600 $file - fi - done - - log "Kubernetes key files permissions successfully reset." -} - -log "Script $0 invoked with from_release = $FROM_RELEASE to_release = $TO_RELEASE action = $ACTION" - -if [ "$TO_RELEASE" == "22.12" ] && [ "$ACTION" == "activate" ]; then - reset-k8s-key-file-permissions -else - log "Script $0 execution skipped" -fi - -exit 0 diff --git a/controllerconfig/controllerconfig/upgrade-scripts/98-sysinv-k8s-apiserver-param-upgrade.py b/controllerconfig/controllerconfig/upgrade-scripts/98-sysinv-k8s-apiserver-param-upgrade.py deleted file mode 100644 index 0d6a30bf2d..0000000000 --- a/controllerconfig/controllerconfig/upgrade-scripts/98-sysinv-k8s-apiserver-param-upgrade.py +++ /dev/null @@ -1,227 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2022 Wind River Systems, Inc. -# -# SPDX-License-Identifier: Apache-2.0 -# -# This script will upgrade kubernetes service parameters -# from release 22.06 and 21.12 to 22.12 -# -# Note: this can be removed in the release after STX8.0 - -import datetime -import json -import sys -import ruamel.yaml as yaml - -from oslo_utils import uuidutils -import psycopg2 -from psycopg2.extras import RealDictCursor -from psycopg2.extras import DictCursor - -from controllerconfig.common import log - -LOG = log.get_logger(__name__) - -K8S_SERVICE = 'kubernetes' - -K8S_BOOTSTRAP_PARAMETERS =\ - "/opt/platform/config/22.12/last_kube_extra_config_bootstrap.yaml" - -SYSINV_K8S_SECTIONS = { - 'apiserver_extra_args': 'kube_apiserver', - 'controllermanager_extra_args': 'kube_controller_manager', - 'scheduler_extra_args': 'kube_scheduler', - 'apiserver_extra_volumes': 'kube_apiserver_volumes', - 'controllermanager_extra_volumes': 'kube_controller_manager_volumes', - 'scheduler_extra_volumes': 'kube_scheduler_volumes', - 'kubelet_configurations': 'kubelet'} - -default_extra_volumes = { - "encryption-config": { - 'name': "encryption-config", - 'hostPath': "/etc/kubernetes/encryption-provider.yaml", - 'mountPath': "/etc/kubernetes/encryption-provider.yaml", - 'readOnly': True, - 'pathType': 'File'}, - - "default-audit-policy-file": { - 'name': "default-audit-policy-file", - 'hostPath': "/etc/kubernetes/default-audit-policy.yaml", - 'mountPath': "/etc/kubernetes/default-audit-policy.yaml", - 'readOnly': True, - 'pathType': 'File'}, - "audit-log-dir": { - 'name': "audit-log-dir", - 'hostPath': "/var/log/kubernetes/audit/", - 'mountPath': "/var/log/kubernetes/audit/", - 'readOnly': False, - 'pathType': 'DirectoryOrCreate'} -} - - -def get_service_parameters(db_conn, K8S_SERVICE, K8S_SECTION): - with db_conn.cursor(cursor_factory=RealDictCursor) as cur: - cur.execute("select name, uuid, value, personality, resource from " - "service_parameter where service='{}' and " - "section='{}'".format(K8S_SERVICE, K8S_SECTION)) - return cur.fetchall() - - -def add_service_parameter(db_conn, name, value, service, section, - personality=None, resource=None): - with db_conn.cursor(cursor_factory=DictCursor) as cur: - cur.execute( - "INSERT INTO service_parameter " - "(created_at, uuid, name, value, service, " - "section, personality, resource) " - "VALUES (%s, %s, %s, %s, %s, %s, %s, %s);", - (datetime.datetime.now(), uuidutils.generate_uuid(), - name, value, service, section, personality, resource)) - LOG.info("Adding %s=%s to db [%s]." % (name, value, section)) - - -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] - else: - LOG.error("Invalid option %s." % sys.argv[arg]) - return 1 - arg += 1 - - log.configure() - - LOG.info("%s invoked with from_release = %s to_release = %s action = %s" - % (sys.argv[0], from_release, to_release, action)) - if action == "migrate" and from_release in ['22.06', '21.12']: - try: - db_conn = psycopg2.connect("dbname=sysinv user=postgres") - with db_conn: - migrate_k8s_control_plane_and_kubelet_parameters(db_conn) - return 0 - except Exception as ex: - LOG.exception(ex) - return 1 - - -def migrate_k8s_control_plane_and_kubelet_parameters(db_conn): - """This method will take each k8s cluster config and kubelet parameter - stored in backup data and will restore it into sysinv database - """ - try: - with open(K8S_BOOTSTRAP_PARAMETERS, 'r') as file: - cluster_cfg = yaml.load(file, Loader=yaml.RoundTripLoader) - except FileNotFoundError as e: - msg = str('Loading k8s bootstrap parameters from file. {}'.format(e)) - LOG.error(msg) - return 1 - - # ------------------------------------------------------------------------- - # Restoring params into sysinv db - # ------------------------------------------------------------------------- - for kubeadm_section in [ - 'apiserver_extra_args', 'controllermanager_extra_args', - 'scheduler_extra_args', 'apiserver_extra_volumes', - 'controllermanager_extra_volumes', 'scheduler_extra_volumes', - 'kubelet_configurations']: - - # current parameters stored into sysinv db - sysinv_section = SYSINV_K8S_SECTIONS.get(kubeadm_section) - sysinv_section_params = get_service_parameters( - db_conn, K8S_SERVICE, sysinv_section) - sysinv_section_params_names =\ - [param.get('name') for param in sysinv_section_params] - - # cases: apiserver, controller-manager and scheduler extra-args - # params loaded during latest bootstrap take precedence over 22.06 - if isinstance(cluster_cfg[kubeadm_section], ( - dict, yaml.comments.CommentedMap)): - for param_name, param_value in cluster_cfg[ - kubeadm_section].items(): - if param_name not in sysinv_section_params_names: - try: - if isinstance(param_value, ( - dict, yaml.comments.CommentedMap)): - param_value = str(dict(param_value)) - - # add new parameter to sysinv - add_service_parameter( - db_conn, param_name, param_value, - K8S_SERVICE, sysinv_section) - - except Exception as e: - LOG.error("[%s] Adding %s=%s to db [Detail: %s]." % ( - sysinv_section, param_name, param_value, e)) - else: - LOG.info("Skipping %s pre existent param." % (param_name)) - - # cases: apiserver, controller-manager and scheduler extra-volumes - elif isinstance(cluster_cfg[kubeadm_section], ( - list, yaml.comments.CommentedSeq)): - for parameter in cluster_cfg[kubeadm_section]: - if not isinstance(parameter, yaml.comments.CommentedMap): - continue - # each parameter is a dictionary containing the fields needed - # to create an extra-volume service-parameter entry and the - # associated k8s configmap. - param_dict = dict(parameter) - param_name = param_dict['name'] - if 'content' in param_dict: - param_dict.pop('content') - param_value = json.dumps(param_dict) - - if param_name not in sysinv_section_params_names: - try: - # add new extra-volume parameter to sysinv - add_service_parameter( - db_conn, param_name, param_value, - K8S_SERVICE, sysinv_section) - except Exception as e: - LOG.error("[%s] Adding %s=%s to db [Detail: %s]." % ( - sysinv_section, param_name, param_value, e)) - continue - else: - LOG.info("Skipping %s pre existent param." % (param_name)) - - # ------------------------------------------------------------------------- - # Restoring params into sysinv db - # ------------------------------------------------------------------------- - # The default extra_volumes in 22.06 or earlier versions are hardcoded - # in the kubeadmin configuration file. This function adds the corresponding - # service parameter entries in the sysinv database - # (service: kubernetes, section: kube_apiserver_volumes). - - # current parameters stored into sysinv db - sysinv_section = 'kube_apiserver_volumes' - sysinv_section_params = get_service_parameters( - db_conn, K8S_SERVICE, sysinv_section) - sysinv_section_params_names =\ - [param.get('name') for param in sysinv_section_params] - - for param_name, volume_dict in default_extra_volumes.items(): - if param_name not in sysinv_section_params_names: - param_value = json.dumps(volume_dict) - try: - add_service_parameter( - db_conn, param_name, param_value, - K8S_SERVICE, sysinv_section) - except Exception as e: - LOG.error("[%s] Adding %s=%s to db [Detail: %s]." % ( - sysinv_section, param_name, param_value, e)) - raise - - LOG.info("k8s service-parameters upgrade completed") - return 0 - - -if __name__ == "__main__": - sys.exit(main())