Remove upgrade scripts
With the release of stx11 some scripts were deprecated and will not be needed on future upgrades, for example, those who were needed only from stx10 to stx11 upgrade. PASS: Full major release deployment stx11 to stx12 in DX PASS: Check upgrade time didn't increased. Story: 2011357 Task: 53040 Change-Id: Ib33598355a1e98399786553b10b1da334aa56524 Signed-off-by: Luiz Eduardo Bonatti <LuizEduardo.Bonatti@windriver.com>
This commit is contained in:
committed by
Luis Eduardo Bonatti
parent
7850e395ff
commit
8277ce1e10
@@ -1,83 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# Copyright (c) 2025 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# This script uses sysinv-conductor API to pin kubernetes control plane containerd images
|
||||
# particularly kube-apiserver, kube-controller-manager, kube-scheduler on controller hosts.
|
||||
#
|
||||
# Note: This script is only required for 24.09 to 25.09 upgrade and should be removed afterwards.
|
||||
|
||||
import logging
|
||||
import sys
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_context import context as mycontext
|
||||
from six.moves import configparser
|
||||
from software.utilities.utils import configure_logging
|
||||
from sysinv.conductor import rpcapiproxy as conductor_rpcapi
|
||||
|
||||
LOG = logging.getLogger('main_logger')
|
||||
|
||||
CONF = cfg.CONF
|
||||
SYSINV_CONFIG_FILE = '/etc/sysinv/sysinv.conf'
|
||||
|
||||
# As this script is only required for 24.09 to 25.09 release, we do not need to use kubernetes APIs
|
||||
# to get current running version.
|
||||
KUBE_VERSION = "v1.29.2"
|
||||
|
||||
|
||||
def get_conductor_rpc_bind_ip():
|
||||
ini_str = '[DEFAULT]\n' + open(SYSINV_CONFIG_FILE, 'r').read()
|
||||
config_applied = configparser.RawConfigParser()
|
||||
config_applied.read_string(ini_str)
|
||||
|
||||
conductor_bind_ip = None
|
||||
if config_applied.has_option('DEFAULT', 'rpc_zeromq_conductor_bind_ip'):
|
||||
conductor_bind_ip = \
|
||||
config_applied.get('DEFAULT', 'rpc_zeromq_conductor_bind_ip')
|
||||
return conductor_bind_ip
|
||||
|
||||
|
||||
def pin_kubernetes_control_plane_images():
|
||||
CONF.rpc_zeromq_conductor_bind_ip = get_conductor_rpc_bind_ip()
|
||||
context = mycontext.get_admin_context()
|
||||
rpcapi = conductor_rpcapi.ConductorAPI(topic=conductor_rpcapi.MANAGER_TOPIC)
|
||||
rpcapi.pin_kubernetes_control_plane_images(context, KUBE_VERSION)
|
||||
|
||||
|
||||
def main():
|
||||
# Initialize variables
|
||||
action = None
|
||||
from_release = None
|
||||
to_release = None
|
||||
arg = 1
|
||||
|
||||
# Process command-line arguments
|
||||
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]
|
||||
arg += 1
|
||||
|
||||
configure_logging()
|
||||
LOG.info(
|
||||
"%s invoked from_release = %s invoked to_release = %s action = %s"
|
||||
% (sys.argv[0], from_release, to_release, action)
|
||||
)
|
||||
|
||||
try:
|
||||
if action == "activate" and from_release == "24.09":
|
||||
pin_kubernetes_control_plane_images()
|
||||
else:
|
||||
LOG.info("Nothing to do. Skipping pinning control plane images.")
|
||||
except Exception as ex:
|
||||
LOG.warning("Failed to pin kubernetes control-plane images. Ignoring... Error: [%s]" % (ex))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
sys.exit(0)
|
||||
@@ -1,123 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# Copyright (c) 2025 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# This script updates the out_of_tree_drivers service parameter
|
||||
# name to backup_oot_drivers_24.09 from sysinv DB during upgrade
|
||||
# from 24.09 to 25.09.
|
||||
#
|
||||
|
||||
|
||||
import logging
|
||||
import sys
|
||||
|
||||
from packaging import version
|
||||
import psycopg2
|
||||
|
||||
from software.utilities.utils import configure_logging
|
||||
|
||||
DEFAULT_POSTGRES_PORT = 5432
|
||||
LOG = logging.getLogger('main_logger')
|
||||
|
||||
PARAM_NAME = "out_of_tree_drivers"
|
||||
BACKUP_NAME = "backup_oot_drivers_24.09"
|
||||
PARAM_SERVICE = "platform"
|
||||
PARAM_SECTION = "kernel"
|
||||
|
||||
|
||||
def main():
|
||||
action = None
|
||||
from_release = None
|
||||
to_release = None
|
||||
postgres_port = DEFAULT_POSTGRES_PORT
|
||||
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]
|
||||
else:
|
||||
print("Invalid option %s." % sys.argv[arg])
|
||||
return 1
|
||||
arg += 1
|
||||
|
||||
configure_logging()
|
||||
LOG.info(
|
||||
"%s invoked from_release=%s to_release=%s action=%s",
|
||||
sys.argv[0], from_release, to_release, action
|
||||
)
|
||||
|
||||
res = 0
|
||||
to_release_version = version.Version(to_release)
|
||||
target_version = version.Version("25.09")
|
||||
|
||||
# Only remove service param on migrate to 25.09
|
||||
if action == 'migrate' and to_release_version == target_version:
|
||||
try:
|
||||
conn = psycopg2.connect(
|
||||
"dbname=sysinv user=postgres port=%s" % postgres_port
|
||||
)
|
||||
update_service_param(conn)
|
||||
conn.close()
|
||||
except Exception as e:
|
||||
LOG.exception("Error removing service parameter: %s", e)
|
||||
res = 1
|
||||
|
||||
return res
|
||||
|
||||
|
||||
def update_service_param(conn):
|
||||
"""Update out_of_tree_drivers service parameter to backup_oot_drivers
|
||||
and ensure any old backup is cleaned up first.
|
||||
"""
|
||||
# Delete any existing backup entry to avoid stale values
|
||||
cleanup_query = (
|
||||
"DELETE FROM service_parameter "
|
||||
"WHERE name='%s' AND service='%s' AND section='%s';"
|
||||
% (BACKUP_NAME, PARAM_SERVICE, PARAM_SECTION)
|
||||
)
|
||||
db_update(conn, cleanup_query)
|
||||
LOG.info("Cleaned up any existing '%s' backup entry.", BACKUP_NAME)
|
||||
|
||||
# Update the original parameter to backup_oot_drivers_24.09
|
||||
update_query = (
|
||||
"UPDATE service_parameter "
|
||||
"SET name='%s' "
|
||||
"WHERE name='%s' AND service='%s' AND section='%s';"
|
||||
% (BACKUP_NAME, PARAM_NAME, PARAM_SERVICE, PARAM_SECTION)
|
||||
)
|
||||
db_update(conn, update_query)
|
||||
LOG.info(
|
||||
"Updated service parameter '%s' to '%s' successfully.",
|
||||
PARAM_NAME, BACKUP_NAME
|
||||
)
|
||||
|
||||
|
||||
def db_query(conn, query):
|
||||
"""Execute a read-only query and return results."""
|
||||
result = []
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(query)
|
||||
for rec in cur:
|
||||
result.append(rec)
|
||||
return result
|
||||
|
||||
|
||||
def db_update(conn, query):
|
||||
"""Execute a write query and commit changes."""
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(query)
|
||||
conn.commit()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
sys.exit(main())
|
||||
except Exception as e:
|
||||
LOG.error("An error occurred: %s", e)
|
||||
raise
|
||||
@@ -1,174 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# Copyright (c) 2025 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# This script updates the node IP addresses in sysinv DB tables. Only network
|
||||
# entries with node addresses and only AIO-SX systems will be updated with the
|
||||
# following actions:
|
||||
# - address_pools: update controller0_address_id and controller1_address_id
|
||||
# to None
|
||||
# - addresses: update floating address IPv4 and IPv6 entries' interface_id
|
||||
# with controller-0's entries' interface_id
|
||||
# - addresses: delete IPv4 and IPv6 controller-0 and controller-1 entries'
|
||||
# interface_id
|
||||
#
|
||||
|
||||
import logging
|
||||
import sys
|
||||
|
||||
from packaging import version
|
||||
import psycopg2
|
||||
from six.moves import configparser
|
||||
|
||||
from software.utilities.utils import configure_logging
|
||||
|
||||
DEFAULT_POSTGRES_PORT = 5432
|
||||
LOG = logging.getLogger('main_logger')
|
||||
|
||||
|
||||
def main():
|
||||
action = None
|
||||
from_release = None
|
||||
to_release = None
|
||||
postgres_port = DEFAULT_POSTGRES_PORT
|
||||
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
|
||||
configure_logging()
|
||||
LOG.info(
|
||||
"%s invoked from_release = %s to_release = %s action = %s"
|
||||
% (sys.argv[0], from_release, to_release, action)
|
||||
)
|
||||
res = 0
|
||||
to_release_version = version.Version(to_release)
|
||||
target_version = version.Version("25.09")
|
||||
if get_system_mode() == "simplex":
|
||||
if action == 'migrate' and to_release_version == target_version:
|
||||
try:
|
||||
conn = psycopg2.connect("dbname=sysinv user=postgres port=%s"
|
||||
% postgres_port)
|
||||
del_node_addresses(conn)
|
||||
conn.close()
|
||||
except Exception as e:
|
||||
LOG.exception("Error: {}".format(e))
|
||||
res = 1
|
||||
return res
|
||||
|
||||
|
||||
def del_node_addresses(conn):
|
||||
net_types = (
|
||||
'mgmt',
|
||||
'admin',
|
||||
'cluster-host',
|
||||
'storage',
|
||||
'pxeboot',
|
||||
)
|
||||
|
||||
for net_type in net_types:
|
||||
del_node_addresses_from_db(conn, net_type)
|
||||
|
||||
|
||||
def del_node_addresses_from_db(conn, net_type):
|
||||
query = (
|
||||
"SELECT address_pools.id,controller0_address_id,controller1_address_id"
|
||||
",floating_address_id "
|
||||
"FROM address_pools "
|
||||
"JOIN network_addresspools ON address_pools.id "
|
||||
"= network_addresspools.address_pool_id "
|
||||
"JOIN networks ON network_addresspools.network_id = networks.id "
|
||||
f"WHERE networks.type = '{net_type}';"
|
||||
)
|
||||
res1 = db_query(conn, query)
|
||||
LOG.info("%s: Number of address_pools entries found: %s" % (net_type, len(res1)))
|
||||
|
||||
controller0_ids = ",".join([str(e[1]) for e in res1 if e[1]])
|
||||
if not controller0_ids:
|
||||
LOG.info("Nothing to change")
|
||||
return
|
||||
|
||||
query = (
|
||||
"SELECT interface_id "
|
||||
"FROM addresses "
|
||||
"WHERE id IN (%s);" % controller0_ids
|
||||
)
|
||||
res2 = db_query(conn, query)
|
||||
c0_interface_ids = tuple([e[0] for e in res2])
|
||||
LOG.info("%s: interface_id found in addresses: %s" % (net_type, (c0_interface_ids,)))
|
||||
|
||||
idx = 0
|
||||
for entry in res1:
|
||||
address_pools_id = entry[0]
|
||||
node_ids = entry[1:3]
|
||||
floating_id = entry[3]
|
||||
LOG.info("%s: Found controller-0 and controller-1 IDs = %s"
|
||||
% (net_type, (node_ids,)))
|
||||
query = (
|
||||
"UPDATE address_pools "
|
||||
"SET controller0_address_id = NULL, controller1_address_id = NULL "
|
||||
"WHERE id = %s;" % address_pools_id
|
||||
)
|
||||
db_update(conn, query)
|
||||
if c0_interface_ids[idx] is None:
|
||||
LOG.info("Skipping update with no c0_interface_id")
|
||||
else:
|
||||
query = (
|
||||
"UPDATE addresses "
|
||||
"SET interface_id = %s "
|
||||
"WHERE id = %s;" % (c0_interface_ids[idx], floating_id)
|
||||
)
|
||||
db_update(conn, query)
|
||||
query = (
|
||||
"DELETE FROM addresses "
|
||||
"WHERE id IN %s;" % (node_ids,)
|
||||
)
|
||||
db_update(conn, query)
|
||||
idx += 1
|
||||
|
||||
LOG.info("%s: node addresses deleted from address_pools and addresses tables "
|
||||
"with success" % net_type)
|
||||
|
||||
|
||||
def db_query(conn, query):
|
||||
result = []
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(query)
|
||||
for rec in cur:
|
||||
result.append(rec)
|
||||
return result
|
||||
|
||||
|
||||
def db_update(conn, query):
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(query)
|
||||
conn.commit()
|
||||
|
||||
|
||||
def get_system_mode():
|
||||
ini_str = '[DEFAULT]\n' + open('/etc/platform/platform.conf', 'r').read()
|
||||
|
||||
config_applied = configparser.RawConfigParser()
|
||||
config_applied.read_string(ini_str)
|
||||
|
||||
if config_applied.has_option('DEFAULT', 'system_mode'):
|
||||
system_mode = config_applied.get('DEFAULT', 'system_mode')
|
||||
else:
|
||||
system_mode = None
|
||||
|
||||
return system_mode
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@@ -1,90 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# Copyright (c) 2025 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# This script will remove load, host_upgrade and software_upgrade
|
||||
# database table
|
||||
#
|
||||
|
||||
import logging
|
||||
import sys
|
||||
|
||||
from packaging import version
|
||||
import psycopg2
|
||||
|
||||
from software.utilities.utils import configure_logging
|
||||
|
||||
DEFAULT_POSTGRES_PORT = 5432
|
||||
|
||||
LOG = logging.getLogger('main_logger')
|
||||
|
||||
|
||||
def main():
|
||||
action = None
|
||||
from_release = None
|
||||
to_release = None
|
||||
postgres_port = DEFAULT_POSTGRES_PORT
|
||||
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
|
||||
configure_logging()
|
||||
LOG.info(
|
||||
"%s invoked from_release = %s to_release = %s action = %s"
|
||||
% (sys.argv[0], from_release, to_release, action)
|
||||
)
|
||||
res = 0
|
||||
to_release_version = version.Version(to_release)
|
||||
minimum_version = version.Version("25.09")
|
||||
if action == 'migrate' and to_release_version == minimum_version:
|
||||
try:
|
||||
conn = psycopg2.connect("dbname=sysinv user=postgres port=%s"
|
||||
% postgres_port)
|
||||
delete_software_upgrade_database(conn)
|
||||
delete_host_upgrade_database(conn)
|
||||
delete_load_database(conn)
|
||||
conn.close()
|
||||
except Exception as e:
|
||||
LOG.exception("Error: {}".format(e))
|
||||
res = 1
|
||||
return res
|
||||
|
||||
|
||||
def delete_load_database(conn):
|
||||
delete_cmd = "drop table if exists loads;"
|
||||
db_update(conn, delete_cmd)
|
||||
LOG.info("Loads table removed with success")
|
||||
|
||||
|
||||
def delete_host_upgrade_database(conn):
|
||||
delete_cmd = "drop table if exists host_upgrade;"
|
||||
db_update(conn, delete_cmd)
|
||||
LOG.info("Host_upgrade table removed with success")
|
||||
|
||||
|
||||
def delete_software_upgrade_database(conn):
|
||||
delete_cmd = "drop table if exists software_upgrade;"
|
||||
db_update(conn, delete_cmd)
|
||||
LOG.info("Software_upgrade table removed with success")
|
||||
|
||||
|
||||
def db_update(conn, query):
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(query)
|
||||
conn.commit()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@@ -1,147 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# Copyright (c) 2025 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# This script deletes the backup_oot_drivers service parameter
|
||||
# from the sysinv DB when invoked with action=delete.
|
||||
#
|
||||
|
||||
import logging as LOG
|
||||
import sys
|
||||
import re
|
||||
import configparser
|
||||
import psycopg2
|
||||
|
||||
DEFAULT_POSTGRES_PORT = 5432
|
||||
DB_NAME = "sysinv"
|
||||
DB_HOST = "localhost"
|
||||
|
||||
BACKUP_NAME = "backup_oot_drivers_24.09"
|
||||
PARAM_SERVICE = "platform"
|
||||
PARAM_SECTION = "kernel"
|
||||
|
||||
LOG.basicConfig(
|
||||
filename="/var/log/software.log",
|
||||
format='%(asctime)s: [%(process)s]: %(filename)s(%(lineno)s): '
|
||||
'%(levelname)s: %(message)s',
|
||||
level=LOG.INFO,
|
||||
datefmt="%FT%T"
|
||||
)
|
||||
|
||||
|
||||
def get_db_credentials():
|
||||
"""Retrieve DB credentials from sysinv.conf"""
|
||||
try:
|
||||
config = configparser.ConfigParser()
|
||||
config.read("/etc/sysinv/sysinv.conf")
|
||||
|
||||
conn_string = config["database"]["connection"]
|
||||
match = re.match(r"postgresql\+psycopg2://([^:]+):([^@]+)@", conn_string)
|
||||
|
||||
if match:
|
||||
username = match.group(1)
|
||||
password = match.group(2)
|
||||
return username, password
|
||||
else:
|
||||
raise Exception("Failed to parse DB credentials from sysinv.conf")
|
||||
except Exception as e:
|
||||
LOG.error(f"Error getting DB credentials: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def connect_to_db(port):
|
||||
"""Establish DB connection"""
|
||||
username, password = get_db_credentials()
|
||||
try:
|
||||
conn = psycopg2.connect(
|
||||
dbname=DB_NAME,
|
||||
user=username,
|
||||
password=password,
|
||||
host=DB_HOST,
|
||||
port=port,
|
||||
)
|
||||
return conn
|
||||
except Exception as e:
|
||||
LOG.error(f"Database connection failed: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def db_query(conn, query, params=()):
|
||||
"""Execute SELECT query and return results"""
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(query, params)
|
||||
return cur.fetchall()
|
||||
|
||||
|
||||
def db_update(conn, query, params=(), autocommit=True):
|
||||
"""Execute UPDATE/DELETE query"""
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(query, params)
|
||||
if autocommit:
|
||||
conn.commit()
|
||||
|
||||
|
||||
def del_backup_param(conn):
|
||||
"""Delete backup_oot_drivers_24.09 service parameter from sysinv DB."""
|
||||
delete_query = (
|
||||
"DELETE FROM service_parameter "
|
||||
"WHERE name=%s AND service=%s AND section=%s;"
|
||||
)
|
||||
db_update(conn, delete_query, (BACKUP_NAME, PARAM_SERVICE, PARAM_SECTION))
|
||||
|
||||
rows = db_query(
|
||||
conn,
|
||||
"SELECT COUNT(*) FROM service_parameter "
|
||||
"WHERE name=%s AND service=%s AND section=%s;",
|
||||
(BACKUP_NAME, PARAM_SERVICE, PARAM_SECTION),
|
||||
)
|
||||
if rows and rows[0][0] > 0:
|
||||
LOG.info(
|
||||
"Deleted %d backup parameter(s) named '%s'.",
|
||||
rows[0][0], BACKUP_NAME
|
||||
)
|
||||
else:
|
||||
LOG.info("No backup parameter '%s' found to delete.", BACKUP_NAME)
|
||||
|
||||
|
||||
def main():
|
||||
action = None
|
||||
from_release = None
|
||||
to_release = None
|
||||
postgres_port = DEFAULT_POSTGRES_PORT
|
||||
|
||||
if len(sys.argv) < 4:
|
||||
print("Usage: %s from_release to_release action [postgres_port]" % sys.argv[0])
|
||||
return 1
|
||||
|
||||
from_release = sys.argv[1]
|
||||
to_release = sys.argv[2]
|
||||
action = sys.argv[3]
|
||||
if len(sys.argv) > 4:
|
||||
postgres_port = sys.argv[4]
|
||||
|
||||
LOG.info(
|
||||
"%s invoked from_release=%s to_release=%s action=%s",
|
||||
sys.argv[0],
|
||||
from_release,
|
||||
to_release,
|
||||
action,
|
||||
)
|
||||
|
||||
if action == "delete":
|
||||
try:
|
||||
conn = connect_to_db(postgres_port)
|
||||
del_backup_param(conn)
|
||||
conn.close()
|
||||
except Exception as e:
|
||||
LOG.exception("Error removing backup service parameter: %s", e)
|
||||
sys.exit(1)
|
||||
else:
|
||||
LOG.info("Nothing to do. Skipping")
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@@ -1,107 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
# Copyright (c) 2025 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# This script uses puppet to include the management IP on kube
|
||||
# apiserver certificate SANs on upgrades from stx10 to stx11.
|
||||
#
|
||||
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_context import context as mycontext
|
||||
from six.moves import configparser
|
||||
from software.utilities.utils import configure_logging
|
||||
from sysinv.conductor import rpcapiproxy as conductor_rpcapi
|
||||
|
||||
LOG = logging.getLogger('main_logger')
|
||||
|
||||
SUCCESS = 0
|
||||
ERROR = 1
|
||||
RETRIES = 3
|
||||
|
||||
CONF = cfg.CONF
|
||||
SYSINV_CONFIG_FILE = '/etc/sysinv/sysinv.conf'
|
||||
KUBE_CERT_SANS_UPDATE_FLAG = '/etc/platform/.upgrade_kube_apiserver_cert_sans_updated'
|
||||
|
||||
|
||||
def get_conductor_rpc_bind_ip():
|
||||
ini_str = '[DEFAULT]\n' + open(SYSINV_CONFIG_FILE, 'r').read()
|
||||
config_applied = configparser.RawConfigParser()
|
||||
config_applied.read_string(ini_str)
|
||||
|
||||
conductor_bind_ip = None
|
||||
if config_applied.has_option('DEFAULT', 'rpc_zeromq_conductor_bind_ip'):
|
||||
conductor_bind_ip = \
|
||||
config_applied.get('DEFAULT', 'rpc_zeromq_conductor_bind_ip')
|
||||
return conductor_bind_ip
|
||||
|
||||
|
||||
def update_kube_apiserver_cert_rpc():
|
||||
CONF.rpc_zeromq_conductor_bind_ip = get_conductor_rpc_bind_ip()
|
||||
context = mycontext.get_admin_context()
|
||||
rpcapi = conductor_rpcapi.ConductorAPI(topic=conductor_rpcapi.MANAGER_TOPIC)
|
||||
rpcapi.update_kube_apiserver_cert_sans(context)
|
||||
|
||||
|
||||
def check_kube_apiserver_cert_updated():
|
||||
return os.path.exists(KUBE_CERT_SANS_UPDATE_FLAG)
|
||||
|
||||
|
||||
def main():
|
||||
# Initialize variables
|
||||
action = None
|
||||
from_release = None
|
||||
to_release = None
|
||||
arg = 1
|
||||
|
||||
# Process command-line arguments
|
||||
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:
|
||||
# port = int(sys.argv[arg])
|
||||
pass
|
||||
else:
|
||||
print(f"Invalid option {sys.argv[arg]}.")
|
||||
return ERROR
|
||||
arg += 1
|
||||
|
||||
configure_logging()
|
||||
LOG.info(
|
||||
"%s invoked from_release = %s invoked to_release = %s action = %s"
|
||||
% (sys.argv[0], from_release, to_release, action)
|
||||
)
|
||||
|
||||
for retry in range(0, RETRIES):
|
||||
try:
|
||||
if action == "activate" and from_release == "24.09":
|
||||
if not check_kube_apiserver_cert_updated():
|
||||
update_kube_apiserver_cert_rpc()
|
||||
else:
|
||||
LOG.info("Nothing to do. "
|
||||
"Skipping kube-apiserver certificate update.")
|
||||
except Exception as ex:
|
||||
if retry == RETRIES - 1:
|
||||
LOG.error("Error in kube-apiserver certificate update. "
|
||||
"Please verify logs.")
|
||||
return ERROR
|
||||
else:
|
||||
LOG.exception(ex)
|
||||
LOG.error("Exception ocurred during script execution, "
|
||||
"retrying after 5 seconds.")
|
||||
time.sleep(5)
|
||||
else:
|
||||
return SUCCESS
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@@ -1,48 +0,0 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright (c) 2025 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# This script disables NFV-VIM Web Server. From version 25.x onwards,
|
||||
# the web server will stay disabled by default in order to optimize
|
||||
# memory and CPU consumption of the host.
|
||||
#
|
||||
# The user can manually reactivate it issuing the command:
|
||||
# "sm-provision service-group-member vim-services vim-webserver"
|
||||
#
|
||||
|
||||
# shellcheck disable=SC2206
|
||||
|
||||
# The script receives these parameters:
|
||||
FROM_RELEASE=$1
|
||||
TO_RELEASE=$2
|
||||
ACTION=$3
|
||||
|
||||
SOFTWARE_LOG_PATH="/var/log/software.log"
|
||||
FROM_RELEASE_ARR=(${FROM_RELEASE//./ })
|
||||
FROM_RELEASE_MAJOR=${FROM_RELEASE_ARR[0]}
|
||||
TO_RELEASE_ARR=(${TO_RELEASE//./ })
|
||||
TO_RELEASE_MAJOR=${TO_RELEASE_ARR[0]}
|
||||
|
||||
# Default logging method extracted from script #02
|
||||
function log {
|
||||
echo "$(date -Iseconds | cut -d'+' -f1): ${NAME}[$$]: INFO: $*" \
|
||||
>> "${SOFTWARE_LOG_PATH}" 2>&1
|
||||
}
|
||||
|
||||
if [[ "${ACTION}" == "migrate" ]] && \
|
||||
[ ${FROM_RELEASE_MAJOR} -lt 25 ] && \
|
||||
[ ${TO_RELEASE_MAJOR} -ge 25 ]; then
|
||||
|
||||
log Disabling the NFV-VIM Web Server...
|
||||
|
||||
sm-deprovision service-group-member vim-services vim-webserver
|
||||
ret_value=$?
|
||||
|
||||
[ $ret_value -eq 0 ] && log NFV-VIM Web Server successfully disabled
|
||||
exit $ret_value
|
||||
|
||||
else
|
||||
log No actions required from $FROM_RELEASE to $TO_RELEASE with action $ACTION
|
||||
fi
|
||||
@@ -1,242 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (c) 2025 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# This migration scripts is used to automaticaly upgrade the PTP
|
||||
# system configuration, according to changes on linuxptp library,
|
||||
# drivers, etc.
|
||||
|
||||
import logging as log
|
||||
import psycopg2 as db
|
||||
import sys
|
||||
import uuid
|
||||
|
||||
from datetime import datetime
|
||||
from datetime import timezone
|
||||
from software.utilities.utils import configure_logging
|
||||
|
||||
DEFAULT_POSTGRES_PORT = 5432
|
||||
DB_CONNECT_FORMAT = "dbname=sysinv user=postgres port=%s"
|
||||
|
||||
|
||||
def db_connect(port):
|
||||
try:
|
||||
conn = db.connect(DB_CONNECT_FORMAT % port)
|
||||
return conn
|
||||
except Exception as e:
|
||||
log.exception(f"Error: {e}")
|
||||
|
||||
|
||||
def db_close(conn):
|
||||
try:
|
||||
conn.close()
|
||||
except Exception as e:
|
||||
log.exception(f"Error: {e}")
|
||||
|
||||
|
||||
def db_query(conn, query):
|
||||
result = []
|
||||
try:
|
||||
with conn.cursor() as curs:
|
||||
curs.execute(query)
|
||||
result = curs.fetchall()
|
||||
except Exception as e:
|
||||
log.exception(f"Error: {e}")
|
||||
return result
|
||||
|
||||
|
||||
def db_execute(conn, query, params=None):
|
||||
try:
|
||||
with conn.cursor() as cursor:
|
||||
if params:
|
||||
cursor.execute(query, params)
|
||||
else:
|
||||
cursor.execute(query)
|
||||
conn.commit()
|
||||
except Exception as e:
|
||||
conn.rollback()
|
||||
log.exception(f"Error executing query: {e}")
|
||||
raise
|
||||
|
||||
|
||||
def get_instances(conn, service=None) -> list:
|
||||
""" get ts2phc instances from database """
|
||||
log.info("getting instances ...")
|
||||
|
||||
query = (
|
||||
"SELECT ptp_instances.id, ptp_instances.name, "
|
||||
"ptp_parameter_owners.uuid "
|
||||
"FROM ptp_instances "
|
||||
"INNER JOIN ptp_parameter_owners "
|
||||
"ON ptp_instances.id = ptp_parameter_owners.id"
|
||||
)
|
||||
# Filter by PTP service type
|
||||
if service:
|
||||
query += f" WHERE service = '{service}';"
|
||||
instances = db_query(conn, query)
|
||||
|
||||
instances_list = []
|
||||
for instance in instances:
|
||||
id = instance[0]
|
||||
name = instance[1]
|
||||
owner_id = instance[2]
|
||||
interfaces = get_interfaces(conn, id)
|
||||
for interface in interfaces:
|
||||
parameters = get_parameters(conn, interface['owner_id'])
|
||||
interface['parameters'] = parameters
|
||||
instances_list += [{
|
||||
'name': name,
|
||||
'id': id,
|
||||
'owner_id': owner_id,
|
||||
'interfaces': interfaces
|
||||
}]
|
||||
return instances_list
|
||||
|
||||
|
||||
def get_interfaces(conn, instance_id=None) -> list:
|
||||
""" get interfaces """
|
||||
log.info("getting interfaces ...")
|
||||
|
||||
query = (
|
||||
"SELECT ptp_interfaces.id, ptp_interfaces.name, "
|
||||
"ptp_parameter_owners.uuid "
|
||||
"FROM ptp_interfaces "
|
||||
"INNER JOIN ptp_parameter_owners "
|
||||
"ON ptp_interfaces.id = ptp_parameter_owners.id"
|
||||
)
|
||||
# Filter by PTP instance id
|
||||
if instance_id:
|
||||
query += f" WHERE ptp_interfaces.ptp_instance_id = '{instance_id}';"
|
||||
interfaces = db_query(conn, query)
|
||||
|
||||
interface_list = []
|
||||
for interface in interfaces:
|
||||
id = interface[0]
|
||||
name = interface[1]
|
||||
owner_id = interface[2]
|
||||
interface_list += [{'name': name, 'id': id, 'owner_id': owner_id}]
|
||||
return interface_list
|
||||
|
||||
|
||||
def get_parameters(conn, owner_id=None) -> list:
|
||||
""" get parameters """
|
||||
log.info("getting parameters ...")
|
||||
|
||||
query = (
|
||||
"SELECT ptp_parameters.id, ptp_parameters.name, "
|
||||
"ptp_parameters.value "
|
||||
"FROM ptp_parameters "
|
||||
"INNER JOIN ptp_parameter_ownerships "
|
||||
"ON ptp_parameters.uuid = ptp_parameter_ownerships.parameter_uuid"
|
||||
)
|
||||
# Filter by owner id
|
||||
if owner_id:
|
||||
query += f" WHERE ptp_parameter_ownerships.owner_uuid = '{owner_id}';"
|
||||
parameters = db_query(conn, query)
|
||||
|
||||
parameter_list = []
|
||||
for parameter in parameters:
|
||||
log.info(f"parameter: {parameter}")
|
||||
id = parameter[0]
|
||||
key = parameter[1]
|
||||
value = parameter[2]
|
||||
parameter_list += [{'id': id, 'key': key, 'value': value}]
|
||||
return parameter_list
|
||||
|
||||
|
||||
def insert_parameter(conn, key, value, owner_uuid):
|
||||
""" insert ptp parameter """
|
||||
log.info("inserting parameter ...")
|
||||
|
||||
parameter_uuid = str(uuid.uuid4())
|
||||
created_at = datetime.now(timezone.utc)
|
||||
|
||||
query = (
|
||||
"INSERT INTO ptp_parameters "
|
||||
"(uuid, name, value, created_at) "
|
||||
"VALUES (%s, %s, %s, %s);"
|
||||
)
|
||||
values = (parameter_uuid, key, value, created_at)
|
||||
db_execute(conn, query, values)
|
||||
|
||||
ownership_uuid = str(uuid.uuid4())
|
||||
query = (
|
||||
"INSERT INTO ptp_parameter_ownerships "
|
||||
"(uuid, parameter_uuid, owner_uuid, created_at) "
|
||||
"VALUES (%s, %s, %s, %s)"
|
||||
)
|
||||
values = (ownership_uuid, parameter_uuid, owner_uuid, created_at)
|
||||
db_execute(conn, query, values)
|
||||
|
||||
|
||||
def migrate_ts2phc_database(conn):
|
||||
""" migrate ts2phc database """
|
||||
log.info("migrating ts2phc database ...")
|
||||
|
||||
# Get list of ts2phc instances, interfaces and parameters.
|
||||
# If any interface hasn't the ts2phc.pin_index or the
|
||||
# ts2phc.channel parameter, add them as they're required.
|
||||
instances = get_instances(conn, 'ts2phc')
|
||||
for instance in instances:
|
||||
log.info(f"instance {instance}")
|
||||
for interface in instance['interfaces']:
|
||||
if not any(parameter['key'] == 'ts2phc.pin_index'
|
||||
for parameter in interface['parameters']):
|
||||
log.info(f"ts2phc instance {instance['name']} "
|
||||
f"interface {interface['name']} "
|
||||
"'ts2phc.pin_index' parameter not found.")
|
||||
insert_parameter(conn, 'ts2phc.pin_index', '1',
|
||||
interface['owner_id'])
|
||||
if not any(parameter['key'] == 'ts2phc.channel'
|
||||
for parameter in interface['parameters']):
|
||||
log.info(f"ts2phc instance {instance['name']} "
|
||||
f"interface {interface['name']} "
|
||||
"'ts2phc.channel' parameter not found.")
|
||||
insert_parameter(conn, 'ts2phc.channel', '1',
|
||||
interface['owner_id'])
|
||||
|
||||
|
||||
def main():
|
||||
"""" main - parsing args and call migration functions """
|
||||
# migration arguments
|
||||
action = None
|
||||
from_release = None
|
||||
to_release = None
|
||||
db_port = DEFAULT_POSTGRES_PORT
|
||||
arg = 1
|
||||
|
||||
while arg < len(sys.argv):
|
||||
if arg == 1:
|
||||
from_release = sys.argv[arg]
|
||||
elif arg == 2:
|
||||
to_release = sys.argv[arg]
|
||||
elif arg == 3:
|
||||
action = sys.argv[arg]
|
||||
elif arg == 4:
|
||||
# optional port parameter for USM upgrade
|
||||
db_port = sys.argv[arg]
|
||||
else:
|
||||
print("Invalid option %s." % sys.argv[arg])
|
||||
return 1
|
||||
arg += 1
|
||||
|
||||
configure_logging()
|
||||
log.info("%s invoked from_release = %s to_release = %s action = %s"
|
||||
% (sys.argv[0], from_release, to_release, action))
|
||||
|
||||
if action == 'migrate' and from_release == "24.09":
|
||||
conn = db_connect(db_port)
|
||||
if conn:
|
||||
migrate_ts2phc_database(conn)
|
||||
db_close(conn)
|
||||
else:
|
||||
log.error("%s failed to connect to database." %
|
||||
sys.argv[0])
|
||||
else:
|
||||
log.info("nothing to do")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@@ -1,315 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
# Copyright (c) 2025 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import logging
|
||||
import os
|
||||
import psycopg2
|
||||
import subprocess
|
||||
import sys
|
||||
import uuid
|
||||
from cgtsclient import client as cgts_client
|
||||
from netaddr import valid_ipv4
|
||||
from netaddr import valid_ipv6
|
||||
from software.utilities.utils import configure_logging
|
||||
from sysinv.common import constants as sysinv_constants
|
||||
from wsme import types as wtypes
|
||||
|
||||
|
||||
DEFAULT_POSTGRES_PORT = 5432
|
||||
LOG_FILE = "/var/log/software.log"
|
||||
LOG = logging.getLogger('main_logger')
|
||||
|
||||
|
||||
# CgtsClient class to handle API interactions
|
||||
class CgtsClient(object):
|
||||
SYSINV_API_VERSION = 1
|
||||
|
||||
def __init__(self):
|
||||
self.conf = {}
|
||||
self._sysinv = None
|
||||
|
||||
# Loading credentials and configurations from environment variables
|
||||
# typically set in OpenStack
|
||||
source_command = 'source /etc/platform/openrc && env'
|
||||
|
||||
with open(os.devnull, "w") as fnull:
|
||||
proc = subprocess.Popen(
|
||||
['bash', '-c', source_command],
|
||||
stdout=subprocess.PIPE, stderr=fnull,
|
||||
universal_newlines=True)
|
||||
|
||||
# Strip the configurations starts with 'OS_' and change
|
||||
# the value to lower
|
||||
for line in proc.stdout:
|
||||
key, _, value = line.partition("=")
|
||||
if key.startswith('OS_'):
|
||||
self.conf[key[3:].lower()] = value.strip()
|
||||
|
||||
proc.communicate()
|
||||
|
||||
@property
|
||||
def sysinv(self):
|
||||
if not self._sysinv:
|
||||
self._sysinv = cgts_client.get_client(
|
||||
self.SYSINV_API_VERSION,
|
||||
os_username=self.conf['username'],
|
||||
os_password=self.conf['password'],
|
||||
os_auth_url=self.conf['auth_url'],
|
||||
os_project_name=self.conf['project_name'],
|
||||
os_project_domain_name=self.conf['project_domain_name'],
|
||||
os_user_domain_name=self.conf['user_domain_name'],
|
||||
os_region_name=self.conf['region_name'],
|
||||
os_service_type='platform',
|
||||
os_endpoint_type='internal')
|
||||
return self._sysinv
|
||||
|
||||
|
||||
def main():
|
||||
action = None
|
||||
from_release = None
|
||||
to_release = None
|
||||
postgres_port = DEFAULT_POSTGRES_PORT
|
||||
arg = 1
|
||||
|
||||
while arg < len(sys.argv):
|
||||
if arg == 1:
|
||||
from_release = sys.argv[arg]
|
||||
elif arg == 2:
|
||||
to_release = sys.argv[arg]
|
||||
elif arg == 3:
|
||||
action = sys.argv[arg]
|
||||
elif arg == 4:
|
||||
# optional port parameter for USM upgrade
|
||||
postgres_port = sys.argv[arg]
|
||||
else:
|
||||
print("Invalid option %s." % sys.argv[arg])
|
||||
return 1
|
||||
arg += 1
|
||||
|
||||
configure_logging()
|
||||
|
||||
LOG.info("%s invoked from_release = %s to_release = %s action = %s"
|
||||
% (sys.argv[0], from_release, to_release, action))
|
||||
|
||||
if action == "migrate" and from_release == "24.09":
|
||||
LOG.info("Create service parameter dns host record for "
|
||||
"registry.central")
|
||||
|
||||
conn = None
|
||||
try:
|
||||
client = CgtsClient()
|
||||
virtual_system = check_virtual_system(client)
|
||||
|
||||
conn = psycopg2.connect(
|
||||
"dbname=sysinv user=postgres port=%s" % postgres_port)
|
||||
|
||||
floating_address_id = get_floating_sc_address_id(
|
||||
conn, virtual_system)
|
||||
if not floating_address_id:
|
||||
LOG.info("System controller address ID not found, exiting.")
|
||||
return 0
|
||||
|
||||
registry_central_ip = get_address_by_id(conn, floating_address_id)
|
||||
if not registry_central_ip:
|
||||
LOG.info("System controller address not found, exiting.")
|
||||
return 0
|
||||
|
||||
if virtual_system:
|
||||
registry_local_ip = get_controller_mgmt_address(conn)
|
||||
update_dns_registry(
|
||||
conn, registry_central_ip, registry_local_ip, to_release)
|
||||
else:
|
||||
update_dns_registry(conn, registry_central_ip, None,
|
||||
to_release)
|
||||
|
||||
if not check_dns_resolution(registry_central_ip):
|
||||
return 1
|
||||
|
||||
except Exception as ex:
|
||||
LOG.exception("Error: %s" % ex)
|
||||
print(ex)
|
||||
return 1
|
||||
|
||||
finally:
|
||||
if conn:
|
||||
conn.close()
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
def update_dns_registry(conn, registry_central_ip,
|
||||
registry_local_ip=None, to_release=None):
|
||||
try:
|
||||
delete_query = (
|
||||
"DELETE FROM service_parameter "
|
||||
"WHERE service='dns' AND section='host-record' "
|
||||
"AND name IN ('registry.central', 'registry.local');"
|
||||
)
|
||||
db_execute(conn, delete_query)
|
||||
|
||||
created_at = wtypes.datetime.datetime
|
||||
central_uuid = str(uuid.uuid4())
|
||||
|
||||
insert_central_query = (
|
||||
"INSERT INTO service_parameter "
|
||||
"(uuid, service, section, name, value, personality, "
|
||||
"resource, created_at) "
|
||||
"VALUES (%s, %s, %s, %s, %s, %s, %s, %s);"
|
||||
)
|
||||
central_values = (
|
||||
central_uuid, 'dns', 'host-record', 'registry.central',
|
||||
f"registry.central,{registry_central_ip}",
|
||||
None, None, created_at.utcnow()
|
||||
)
|
||||
db_execute(conn, insert_central_query, central_values)
|
||||
|
||||
if registry_local_ip:
|
||||
local_uuid = str(uuid.uuid4())
|
||||
insert_local_query = (
|
||||
"INSERT INTO service_parameter "
|
||||
"(uuid, service, section, name, value, personality, "
|
||||
"resource, created_at) "
|
||||
"VALUES (%s, %s, %s, %s, %s, %s, %s, %s);"
|
||||
)
|
||||
local_values = (
|
||||
local_uuid, 'dns', 'host-record', 'registry.local',
|
||||
f"registry.local,{registry_local_ip}",
|
||||
None, None, created_at.utcnow()
|
||||
)
|
||||
db_execute(conn, insert_local_query, local_values)
|
||||
|
||||
LOG.info("DNS host records for registry inserted successfully.")
|
||||
|
||||
config_dir = f"/opt/platform/config/{to_release}"
|
||||
config_file = os.path.join(config_dir, "dnsmasq.addn_conf")
|
||||
|
||||
os.makedirs(config_dir, exist_ok=True)
|
||||
LOG.info("Created config directory: %s" % config_dir)
|
||||
|
||||
existing_lines = []
|
||||
if os.path.exists(config_file):
|
||||
with open(config_file, "r") as f:
|
||||
existing_lines = f.readlines()
|
||||
|
||||
updated_lines = []
|
||||
for line in existing_lines:
|
||||
if not line.startswith("host-record=registry.central,") and \
|
||||
not line.startswith("host-record=registry.local,"):
|
||||
updated_lines.append(line.strip())
|
||||
|
||||
updated_lines.append(
|
||||
f"host-record=registry.central,{registry_central_ip}"
|
||||
)
|
||||
if registry_local_ip:
|
||||
updated_lines.append(
|
||||
f"host-record=registry.local,{registry_local_ip}"
|
||||
)
|
||||
|
||||
with open(config_file, "w") as f:
|
||||
for line in updated_lines:
|
||||
f.write(line + "\n")
|
||||
LOG.info("Updated entry in %s: %s" % (config_file, line))
|
||||
|
||||
except Exception as e:
|
||||
LOG.exception("Failed to update DNS records: %s" % e)
|
||||
raise
|
||||
|
||||
|
||||
def db_execute(conn, query, params=None):
|
||||
try:
|
||||
with conn.cursor() as cursor:
|
||||
if params:
|
||||
cursor.execute(query, params)
|
||||
else:
|
||||
cursor.execute(query)
|
||||
conn.commit()
|
||||
except Exception as e:
|
||||
conn.rollback()
|
||||
LOG.exception("Error executing query: %s" % e)
|
||||
raise
|
||||
|
||||
|
||||
def db_query(conn, query):
|
||||
try:
|
||||
with conn.cursor() as cursor:
|
||||
cursor.execute(query)
|
||||
result = cursor.fetchone()
|
||||
return result[0] if result else None
|
||||
except Exception as e:
|
||||
LOG.exception("Error executing query: %s" % e)
|
||||
raise
|
||||
|
||||
|
||||
def check_virtual_system(client):
|
||||
parameters = client.sysinv.service_parameter.list()
|
||||
|
||||
for parameter in parameters:
|
||||
if (parameter.name ==
|
||||
sysinv_constants.SERVICE_PARAM_NAME_PLAT_CONFIG_VIRTUAL):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def get_floating_sc_address_id(conn, virtual_system):
|
||||
if virtual_system:
|
||||
query = (
|
||||
"SELECT floating_address_id FROM address_pools "
|
||||
"WHERE name = 'system-controller-subnet';"
|
||||
)
|
||||
else:
|
||||
query = (
|
||||
"SELECT floating_address_id FROM address_pools "
|
||||
"WHERE name = 'system-controller-oam-subnet';"
|
||||
)
|
||||
|
||||
return db_query(conn, query)
|
||||
|
||||
|
||||
def get_controller_mgmt_address(conn):
|
||||
query = "SELECT address FROM addresses WHERE name = 'controller-mgmt';"
|
||||
return db_query(conn, query)
|
||||
|
||||
|
||||
def get_address_by_id(conn, floating_address_id):
|
||||
query = (
|
||||
"SELECT address FROM addresses WHERE id = %s;"
|
||||
% floating_address_id
|
||||
)
|
||||
return db_query(conn, query)
|
||||
|
||||
|
||||
def check_dns_resolution(ip_address):
|
||||
if valid_ipv4(ip_address):
|
||||
record_type = "A"
|
||||
ip_type = "IPv4"
|
||||
elif valid_ipv6(ip_address):
|
||||
record_type = "AAAA"
|
||||
ip_type = "IPv6"
|
||||
else:
|
||||
LOG.error("Invalid IP address: %s" % ip_address)
|
||||
return False
|
||||
|
||||
LOG.info("Checking resolution to registry.central")
|
||||
|
||||
result = subprocess.run(
|
||||
["dig", "registry.central", record_type, "+short"],
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
||||
universal_newlines=True
|
||||
)
|
||||
|
||||
if result.returncode != 0 or not result.stdout.strip():
|
||||
LOG.error(
|
||||
"Failed to resolve %s address %s to a name associated with "
|
||||
"the domain (registry.central). No valid DNS record found." %
|
||||
(ip_type, ip_address)
|
||||
)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@@ -1,249 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
# Copyright (c) 2024-2025 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# This script perform the apply command for service-parameters for
|
||||
# kube-apiserver added/removed/modified in the scrips listed below
|
||||
# (which need to be executed before this one), and monitors the
|
||||
# kube-apiserver PID restart in the active controller.
|
||||
#
|
||||
# An update of kube-apiserver port (6443 -> 16443) relies on this
|
||||
# procedure to reconfigure the k8s control plane.
|
||||
#
|
||||
# Scripts that should be executed before this one:
|
||||
# - k8s-disable-sched-controllermanager-leader-election.sh
|
||||
#
|
||||
|
||||
import logging
|
||||
import subprocess
|
||||
import sys
|
||||
import os
|
||||
import time
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_context import context as mycontext
|
||||
from six.moves import configparser
|
||||
from software.utilities.utils import configure_logging
|
||||
from sysinv.common.kubernetes import k8s_wait_for_endpoints_health
|
||||
from sysinv.conductor import rpcapiproxy as conductor_rpcapi
|
||||
|
||||
LOG = logging.getLogger('main_logger')
|
||||
|
||||
SUCCESS = 0
|
||||
ERROR = 1
|
||||
RETRIES = 3
|
||||
|
||||
KUBE_PORT_UPDATED_FLAG = '/etc/platform/.upgrade_kube_apiserver_port_updated'
|
||||
|
||||
CONF = cfg.CONF
|
||||
SYSINV_CONFIG_FILE = '/etc/sysinv/sysinv.conf'
|
||||
|
||||
|
||||
class ServiceParametersApplier(object):
|
||||
"""
|
||||
The main purpose of this class is to safely apply service parameters
|
||||
previously configured in the system.
|
||||
|
||||
The command: "system service-parameters-apply kubernetes" will trigger
|
||||
many system events including the restart of kube-apiserver process.
|
||||
"""
|
||||
def __init__(self) -> None:
|
||||
self.SP_APPLY_CMD = 'system service-parameter-apply kubernetes'
|
||||
self.initial_kube_apiserver_pid = -1
|
||||
|
||||
def __system_cmd(self, command: str) -> str:
|
||||
sub = subprocess.Popen(["bash", "-c", command],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
stdout, stderr = sub.communicate()
|
||||
if sub.returncode != 0:
|
||||
raise Exception(stderr.decode('utf-8'))
|
||||
return stdout.decode('utf-8')
|
||||
|
||||
def __service_parameter_apply(self) -> None:
|
||||
command = self.SP_APPLY_CMD
|
||||
LOG.info('Applying service parameters...')
|
||||
self.__system_cmd(command)
|
||||
|
||||
def __get_kube_apiserver_pid(self) -> int:
|
||||
try:
|
||||
return subprocess.check_output(["pidof", "-s", "kube-apiserver"])
|
||||
except Exception:
|
||||
return -1
|
||||
|
||||
def __register_kube_apiserver_pid(self):
|
||||
self.initial_kube_apiserver_pid = self.__get_kube_apiserver_pid()
|
||||
|
||||
def __wait_kube_apiserver_pid_ready(self):
|
||||
LOG.info("Waiting kube-apiserver PID to restart")
|
||||
for _ in range(0, 300):
|
||||
if check_kube_apiserver_port_updated():
|
||||
current_pid = self.__get_kube_apiserver_pid()
|
||||
if (current_pid != self.initial_kube_apiserver_pid and
|
||||
current_pid != -1):
|
||||
LOG.info("kube-apiserver PID is restarted!")
|
||||
return
|
||||
time.sleep(2)
|
||||
else:
|
||||
LOG.error("Timeout restarting kube-apiserver.")
|
||||
sys.exit(ERROR)
|
||||
|
||||
def apply(self):
|
||||
# Perform service parameter apply and wait kube-apiserver restart
|
||||
self.__register_kube_apiserver_pid()
|
||||
self.__service_parameter_apply()
|
||||
self.__wait_kube_apiserver_pid_ready()
|
||||
|
||||
def rollback(self):
|
||||
# Perform service parameter apply and wait kube-apiserver restart
|
||||
self.__register_kube_apiserver_pid()
|
||||
self.__service_parameter_apply()
|
||||
self.__wait_kube_apiserver_pid_ready()
|
||||
|
||||
|
||||
def check_kube_apiserver_port_updated():
|
||||
return os.path.exists(KUBE_PORT_UPDATED_FLAG)
|
||||
|
||||
|
||||
def get_conductor_rpc_bind_ip():
|
||||
ini_str = '[DEFAULT]\n' + open(SYSINV_CONFIG_FILE, 'r').read()
|
||||
config_applied = configparser.RawConfigParser()
|
||||
config_applied.read_string(ini_str)
|
||||
|
||||
conductor_bind_ip = None
|
||||
if config_applied.has_option('DEFAULT', 'rpc_zeromq_conductor_bind_ip'):
|
||||
conductor_bind_ip = \
|
||||
config_applied.get('DEFAULT', 'rpc_zeromq_conductor_bind_ip')
|
||||
return conductor_bind_ip
|
||||
|
||||
|
||||
def create_kube_apiserver_port_rollback_flag_rpc():
|
||||
CONF.rpc_zeromq_conductor_bind_ip = get_conductor_rpc_bind_ip()
|
||||
context = mycontext.get_admin_context()
|
||||
rpcapi = conductor_rpcapi.ConductorAPI(topic=conductor_rpcapi.MANAGER_TOPIC)
|
||||
rpcapi.flag_k8s_port_update_rollback(context)
|
||||
|
||||
|
||||
def run_kubernetes_health_audit_rpc():
|
||||
CONF.rpc_zeromq_conductor_bind_ip = get_conductor_rpc_bind_ip()
|
||||
context = mycontext.get_admin_context()
|
||||
rpcapi = conductor_rpcapi.ConductorAPI(topic=conductor_rpcapi.MANAGER_TOPIC)
|
||||
rpcapi.run_kubernetes_health_audit(context)
|
||||
|
||||
|
||||
def wait_kube_apiserver_port_update(desired_status):
|
||||
LOG.info("Wait kube-apiserver port update finish.")
|
||||
retries = 60
|
||||
sleep = 3
|
||||
for _ in range(0, retries):
|
||||
if check_kube_apiserver_port_updated() == desired_status:
|
||||
LOG.info("kube-apiserver port update status: %s" %
|
||||
str(desired_status))
|
||||
return
|
||||
time.sleep(sleep)
|
||||
msg = "The port for kube-apiserver was not updated in the allotted time."
|
||||
raise Exception(msg)
|
||||
|
||||
|
||||
def check_conductor_restarted():
|
||||
output = subprocess.check_output('/usr/bin/sm-dump', shell=True)
|
||||
for line in output.splitlines():
|
||||
if 'sysinv-conductor' in line.decode('utf-8'):
|
||||
if line.decode('utf-8').count('enabled-active') == 2:
|
||||
return True
|
||||
break
|
||||
return False
|
||||
|
||||
|
||||
def wait_conductor_restarted():
|
||||
retries = 30
|
||||
sleep = 3
|
||||
for _ in range(0, retries):
|
||||
if check_conductor_restarted():
|
||||
LOG.info("Sysinv-conductor is enabled-active")
|
||||
return True
|
||||
time.sleep(sleep)
|
||||
LOG.error("Sysinv-conductor not restarted in expected time")
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
# Initialize variables
|
||||
action = None
|
||||
from_release = None
|
||||
to_release = None
|
||||
arg = 1
|
||||
|
||||
# Process command-line arguments
|
||||
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:
|
||||
# port = int(sys.argv[arg])
|
||||
pass
|
||||
else:
|
||||
print(f"Invalid option {sys.argv[arg]}.")
|
||||
return ERROR
|
||||
arg += 1
|
||||
|
||||
configure_logging()
|
||||
LOG.info(
|
||||
"%s invoked from_release = %s invoked to_release = %s action = %s"
|
||||
% (sys.argv[0], from_release, to_release, action)
|
||||
)
|
||||
|
||||
for retry in range(0, RETRIES):
|
||||
try:
|
||||
if action == "activate" and from_release == "24.09":
|
||||
if not check_kube_apiserver_port_updated():
|
||||
ServiceParametersApplier().apply()
|
||||
wait_kube_apiserver_port_update(True)
|
||||
if not wait_conductor_restarted():
|
||||
# No point in retrying without sysinv-conductor
|
||||
LOG.error("Conductor is unhealthy, check sysinv logs")
|
||||
return ERROR
|
||||
if not k8s_wait_for_endpoints_health():
|
||||
# k8s_wait_for_endpoints_health already has retries
|
||||
LOG.error("K8s is unhealthy, aborting. "
|
||||
"Please check logs.")
|
||||
return ERROR
|
||||
run_kubernetes_health_audit_rpc()
|
||||
elif action == "activate-rollback" and to_release == "24.09":
|
||||
if check_kube_apiserver_port_updated():
|
||||
create_kube_apiserver_port_rollback_flag_rpc()
|
||||
ServiceParametersApplier().rollback()
|
||||
wait_kube_apiserver_port_update(False)
|
||||
if not wait_conductor_restarted():
|
||||
# No point in retrying without sysinv-conductor
|
||||
LOG.error("Conductor is unhealthy, check sysinv logs")
|
||||
return ERROR
|
||||
if not k8s_wait_for_endpoints_health():
|
||||
# k8s_wait_for_endpoints_health already has retries
|
||||
LOG.error("K8s is unhealthy, aborting. "
|
||||
"Please check logs.")
|
||||
return ERROR
|
||||
run_kubernetes_health_audit_rpc()
|
||||
else:
|
||||
LOG.info("Nothing to do. "
|
||||
"Skipping K8s service parameter apply.")
|
||||
except Exception as ex:
|
||||
if retry == RETRIES - 1:
|
||||
LOG.error("Error applying K8s service parameters. "
|
||||
"Please verify logs.")
|
||||
return ERROR
|
||||
else:
|
||||
LOG.exception(ex)
|
||||
LOG.error("Exception ocurred during script execution, "
|
||||
"retrying after 5 seconds.")
|
||||
time.sleep(5)
|
||||
else:
|
||||
return SUCCESS
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@@ -1,91 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
# Copyright (c) 2025 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import logging
|
||||
import psycopg2
|
||||
import sys
|
||||
|
||||
from software.utilities.utils import configure_logging
|
||||
|
||||
DEFAULT_POSTGRES_PORT = 5432
|
||||
LOG_FILE = "/var/log/software.log"
|
||||
DB_NAME = "sysinv"
|
||||
DB_USER = "postgres"
|
||||
LOG = logging.getLogger('main_logger')
|
||||
|
||||
|
||||
def main():
|
||||
action = None
|
||||
from_release = None
|
||||
to_release = None
|
||||
postgres_port = DEFAULT_POSTGRES_PORT
|
||||
arg = 1
|
||||
|
||||
while arg < len(sys.argv):
|
||||
if arg == 1:
|
||||
from_release = sys.argv[arg]
|
||||
elif arg == 2:
|
||||
to_release = sys.argv[arg]
|
||||
elif arg == 3:
|
||||
action = sys.argv[arg]
|
||||
elif arg == 4:
|
||||
# optional port parameter for USM upgrade
|
||||
postgres_port = sys.argv[arg]
|
||||
pass
|
||||
else:
|
||||
print("Invalid option %s." % sys.argv[arg])
|
||||
return 1
|
||||
arg += 1
|
||||
|
||||
configure_logging()
|
||||
|
||||
res = 0
|
||||
LOG.info("%s invoked from_release = %s to_release = %s action = %s"
|
||||
% (sys.argv[0], from_release, to_release, action))
|
||||
|
||||
if action == "migrate" and from_release == "24.09":
|
||||
LOG.info("Updating addresses table entries.")
|
||||
|
||||
try:
|
||||
update_address_name_from_db(postgres_port)
|
||||
except Exception as ex:
|
||||
LOG.exception("Error: {}".format(ex))
|
||||
print(ex)
|
||||
res = 1
|
||||
|
||||
return res
|
||||
|
||||
|
||||
def update_address_name_from_db(postgres_port):
|
||||
query = """
|
||||
UPDATE addresses
|
||||
SET name = REGEXP_REPLACE(
|
||||
name, '^system-controller-gateway-ip-', 'controller-gateway-')
|
||||
WHERE name LIKE 'system-controller-gateway-ip-%';
|
||||
"""
|
||||
try:
|
||||
with psycopg2.connect(
|
||||
dbname=DB_NAME,
|
||||
user=DB_USER,
|
||||
port=postgres_port
|
||||
) as conn:
|
||||
with conn.cursor() as cursor:
|
||||
cursor.execute(query)
|
||||
rows_updated = cursor.rowcount
|
||||
conn.commit()
|
||||
|
||||
if rows_updated:
|
||||
LOG.info(
|
||||
"Updated %d entries in addresses table.", rows_updated)
|
||||
else:
|
||||
LOG.info("No entries updated in addresses table.")
|
||||
except Exception as e:
|
||||
LOG.error(f"Failed to update IP addresses in the "
|
||||
f"database: {e}")
|
||||
raise
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@@ -167,9 +167,9 @@ def main():
|
||||
|
||||
for retry in range(0, RETRIES):
|
||||
try:
|
||||
if action == "activate" and from_release == "24.09":
|
||||
if action == "activate":
|
||||
PortierisWebhookDisabler(from_release).apply()
|
||||
elif action == "activate-rollback" and to_release == "24.09":
|
||||
elif action == "activate-rollback":
|
||||
PortierisWebhookDisabler(to_release).rollback()
|
||||
else:
|
||||
LOG.info("Nothing to do. "
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# Copyright (c) 2025 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# This script reconfigure the keystone endpoints using the sysinv
|
||||
# version (not puppet).
|
||||
# Needs to run at the end of the upgrade activation, to reduce the
|
||||
# stabilization time after upgrade is concluded (less reconfigurations).
|
||||
|
||||
import logging
|
||||
import socket
|
||||
import sys
|
||||
from time import sleep
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_context import context as mycontext
|
||||
from six.moves import configparser
|
||||
from sysinv.conductor import rpcapiproxy as conductor_rpcapi
|
||||
|
||||
from software.utilities.utils import configure_logging
|
||||
|
||||
LOG = logging.getLogger('main_logger')
|
||||
CONF = cfg.CONF
|
||||
SYSINV_CONFIG_FILE = '/etc/sysinv/sysinv.conf'
|
||||
|
||||
|
||||
def get_conductor_rpc_bind_ip():
|
||||
ini_str = '[DEFAULT]\n' + open(SYSINV_CONFIG_FILE, 'r').read()
|
||||
config_applied = configparser.RawConfigParser()
|
||||
config_applied.read_string(ini_str)
|
||||
|
||||
conductor_bind_ip = None
|
||||
if config_applied.has_option('DEFAULT', 'rpc_zeromq_conductor_bind_ip'):
|
||||
conductor_bind_ip = \
|
||||
config_applied.get('DEFAULT', 'rpc_zeromq_conductor_bind_ip')
|
||||
return conductor_bind_ip
|
||||
|
||||
|
||||
def main():
|
||||
action = None
|
||||
from_release = None
|
||||
to_release = None
|
||||
arg = 1
|
||||
while arg < len(sys.argv):
|
||||
if arg == 1:
|
||||
from_release = sys.argv[arg]
|
||||
elif arg == 2:
|
||||
to_release = sys.argv[arg]
|
||||
elif arg == 3:
|
||||
action = sys.argv[arg]
|
||||
elif arg == 4:
|
||||
# optional port parameter for USM upgrade
|
||||
# port = sys.argv[arg]
|
||||
pass
|
||||
else:
|
||||
print("Invalid option %s." % sys.argv[arg])
|
||||
return 1
|
||||
arg += 1
|
||||
|
||||
configure_logging()
|
||||
|
||||
# Activate
|
||||
if action == 'activate':
|
||||
LOG.info("%s invoked with from_release = %s to_release = %s "
|
||||
"action = %s"
|
||||
% (sys.argv[0], from_release, to_release, action))
|
||||
|
||||
# Options of bind ip to the rpc call
|
||||
rpc_ip_options = [get_conductor_rpc_bind_ip(), 'controller.internal']
|
||||
while None in rpc_ip_options:
|
||||
rpc_ip_options.remove(None)
|
||||
|
||||
for index, ip in enumerate(rpc_ip_options):
|
||||
try:
|
||||
CONF.rpc_zeromq_conductor_bind_ip = ip
|
||||
context = mycontext.get_admin_context()
|
||||
rpcapi = conductor_rpcapi.ConductorAPI(
|
||||
topic=conductor_rpcapi.MANAGER_TOPIC)
|
||||
host = rpcapi.get_ihost_by_hostname(
|
||||
context, socket.gethostname())
|
||||
|
||||
LOG.info("Call Conductor to reconfigure keystone endpoints. "
|
||||
"Bind ip: %s." % CONF.rpc_zeromq_conductor_bind_ip)
|
||||
rpcapi.reconfigure_service_endpoints(context, host)
|
||||
except Exception as e:
|
||||
if index == (len(rpc_ip_options) - 1):
|
||||
LOG.error("Error configuring keystone endpoints. "
|
||||
"Please verify logs.")
|
||||
return 1
|
||||
else:
|
||||
LOG.exception(e)
|
||||
LOG.error("Exception ocurred during script execution, "
|
||||
"retrying after 5 seconds.")
|
||||
sleep(5)
|
||||
else:
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@@ -6,7 +6,6 @@
|
||||
# This script install fluxcd controllers in the flux-helm namespace
|
||||
# in kubernetes
|
||||
#
|
||||
# This script can be removed in the release that follows stx7
|
||||
|
||||
import logging
|
||||
import subprocess
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright (c) 2025 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# This migration script is used to create keystone roles
|
||||
# operator and configurator during upgrade, also deletes
|
||||
# roles when the rollback is executed
|
||||
#
|
||||
|
||||
# The migration scripts are passed these parameters:
|
||||
NAME=$(basename $0)
|
||||
FROM_RELEASE=$1
|
||||
TO_RELEASE=$2
|
||||
ACTION=$3
|
||||
ROLES=("operator" "configurator")
|
||||
|
||||
function log {
|
||||
echo "$(date -Iseconds | cut -d'+' -f1): ${NAME}[$$]: INFO: $*" >> "/var/log/software.log" 2>&1
|
||||
}
|
||||
|
||||
# Only run this script during upgrade-activate and from release 24.09
|
||||
if [[ "$ACTION" == "activate" && "$FROM_RELEASE" == "24.09" ]]; then
|
||||
log "creating keystone roles operator,configurator"
|
||||
for role in "${ROLES[@]}"; do
|
||||
openstack role show $role
|
||||
RC=$?
|
||||
if [ ${RC} == 1 ]; then
|
||||
openstack role create $role
|
||||
RC=$?
|
||||
if [ ${RC} == 0 ]; then
|
||||
log "Successfully added keystone role ${role}"
|
||||
else
|
||||
log "Failed to add keystone role ${role}"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
elif [[ "$ACTION" == "activate-rollback" && "$TO_RELEASE" == "24.09" ]]; then
|
||||
for role in "${ROLES[@]}"; do
|
||||
openstack role show $role
|
||||
RC=$?
|
||||
if [ ${RC} == 0 ]; then
|
||||
openstack role delete $role
|
||||
RC=$?
|
||||
if [ ${RC} == 0 ]; then
|
||||
log "Successfully deleted keystone role ${role}"
|
||||
else
|
||||
log "Failed to delete keystone role ${role}"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
@@ -1,329 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2025 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
|
||||
# This script performs database updation and rollback operations
|
||||
# for the `interfaces` table in the `sysinv` PostgreSQL database,
|
||||
# specifically targeting VF interfaces with PCI SR-IOV class.
|
||||
|
||||
|
||||
import sys
|
||||
import psycopg2
|
||||
import logging
|
||||
from psycopg2 import sql
|
||||
import json
|
||||
import re
|
||||
import configparser
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
from software.utilities.utils import configure_logging
|
||||
|
||||
DB_NAME = "sysinv"
|
||||
DB_HOST = "localhost"
|
||||
TABLE_NAME = "interfaces"
|
||||
MAX_TX_RATE = "max_tx_rate"
|
||||
MAX_RX_RATE = "max_rx_rate"
|
||||
IFCAPABILITIES = "ifcapabilities"
|
||||
VF_TYPE = "vf"
|
||||
PCI_CLASS = "pci-sriov"
|
||||
DEFAULT_POSTGRES_PORT = "5432"
|
||||
LOG = logging.getLogger('main_logger')
|
||||
|
||||
configure_logging()
|
||||
|
||||
|
||||
def get_db_credentials():
|
||||
""" Retrieve DB credentials from sysinv.conf """
|
||||
try:
|
||||
config = configparser.ConfigParser()
|
||||
config.read('/etc/sysinv/sysinv.conf')
|
||||
|
||||
conn_string = config['database']['connection']
|
||||
match = re.match(r'postgresql\+psycopg2://([^:]+):([^@]+)@',
|
||||
conn_string)
|
||||
|
||||
if match:
|
||||
username = match.group(1)
|
||||
password = match.group(2)
|
||||
return username, password
|
||||
else:
|
||||
raise Exception("Failed to parse DB credentials from sysinv.conf")
|
||||
except Exception as e:
|
||||
LOG.error(f"Error getting DB credentials: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def connect_to_db(port):
|
||||
""" Establish DB connection """
|
||||
username, password = get_db_credentials()
|
||||
|
||||
try:
|
||||
conn = psycopg2.connect(
|
||||
dbname=DB_NAME,
|
||||
user=username,
|
||||
password=password,
|
||||
host=DB_HOST,
|
||||
port=port
|
||||
)
|
||||
return conn
|
||||
except Exception as e:
|
||||
LOG.error(f"Database connection failed: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def db_query(conn, query, params=()):
|
||||
""" Execute SELECT query and return results """
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(query, params)
|
||||
return cur.fetchall()
|
||||
|
||||
|
||||
def db_update(conn, query, params=(), autocommit=True):
|
||||
""" Execute UPDATE query """
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(query, params)
|
||||
if autocommit:
|
||||
conn.commit()
|
||||
|
||||
|
||||
def columns_exist(conn):
|
||||
""" Verify required columns exist in the table """
|
||||
query = f"""
|
||||
SELECT column_name
|
||||
FROM information_schema.columns
|
||||
WHERE table_name = '{TABLE_NAME}'
|
||||
AND column_name IN ('{MAX_TX_RATE}', '{MAX_RX_RATE}',
|
||||
'{IFCAPABILITIES}');
|
||||
"""
|
||||
|
||||
cols = db_query(conn, query)
|
||||
existing_cols = {col[0] for col in cols}
|
||||
|
||||
if {MAX_TX_RATE, MAX_RX_RATE, IFCAPABILITIES}.issubset(existing_cols):
|
||||
return True
|
||||
else:
|
||||
missing_cols = (
|
||||
{MAX_TX_RATE, MAX_RX_RATE, IFCAPABILITIES} - existing_cols
|
||||
)
|
||||
LOG.error(f"Missing columns: {', '.join(missing_cols)}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def update_data(conn):
|
||||
LOG.info("Starting data updation...")
|
||||
|
||||
select_query = sql.SQL(f"""
|
||||
SELECT id, uuid, {IFCAPABILITIES}
|
||||
FROM {TABLE_NAME}
|
||||
WHERE iftype = %s AND ifclass = %s;
|
||||
""")
|
||||
|
||||
vf_interfaces = []
|
||||
|
||||
vf_interfaces = db_query(
|
||||
conn, select_query, (VF_TYPE, PCI_CLASS)
|
||||
)
|
||||
LOG.info(f"Found {len(vf_interfaces)} VF interfaces to update.")
|
||||
if len(vf_interfaces) == 0:
|
||||
LOG.info("No VF interfaces found to update. No changes required")
|
||||
return
|
||||
|
||||
updated = False
|
||||
|
||||
for iface_id, iface_uuid, ifcapabilities in vf_interfaces:
|
||||
if ifcapabilities:
|
||||
try:
|
||||
capabilities_dict = json.loads(ifcapabilities)
|
||||
except (json.JSONDecodeError, TypeError) as e:
|
||||
raise ValueError(
|
||||
f"Malformed ifcapabilities for UUID {iface_uuid}: {e}"
|
||||
)
|
||||
|
||||
tx_rate = capabilities_dict.get("max_tx_rate", None)
|
||||
|
||||
if "max_tx_rate" in capabilities_dict:
|
||||
del capabilities_dict["max_tx_rate"]
|
||||
|
||||
cleaned_ifcapabilities = json.dumps(capabilities_dict) if \
|
||||
capabilities_dict else None
|
||||
|
||||
# Only update the database if either tx_rate or
|
||||
# cleaned_ifcapabilities has a value
|
||||
if tx_rate is not None or cleaned_ifcapabilities is not None:
|
||||
update_query = sql.SQL(f"""
|
||||
UPDATE {TABLE_NAME}
|
||||
SET {MAX_TX_RATE} = %s, {IFCAPABILITIES} = %s
|
||||
WHERE id = %s;
|
||||
""")
|
||||
|
||||
db_update(
|
||||
conn,
|
||||
update_query,
|
||||
(tx_rate, cleaned_ifcapabilities, iface_id),
|
||||
autocommit=False
|
||||
)
|
||||
updated = True
|
||||
|
||||
LOG.info(f"Updated {TABLE_NAME} for UUID: {iface_uuid} "
|
||||
f"with max_tx_rate: {tx_rate}")
|
||||
|
||||
if updated:
|
||||
conn.commit()
|
||||
LOG.info("All applicable records updated successfully.")
|
||||
else:
|
||||
LOG.info("No changes were made to the database.")
|
||||
|
||||
|
||||
def rollback_data(conn):
|
||||
"""Rollback migration by moving data back to ifcapabilities"""
|
||||
LOG.info("Starting data rollback...")
|
||||
|
||||
select_query = sql.SQL(f"""
|
||||
SELECT id, uuid, {MAX_TX_RATE}, {IFCAPABILITIES}
|
||||
FROM {TABLE_NAME}
|
||||
WHERE iftype = %s AND ifclass = %s;
|
||||
""")
|
||||
|
||||
vf_interfaces = []
|
||||
|
||||
vf_interfaces = db_query(
|
||||
conn, select_query, (VF_TYPE, PCI_CLASS)
|
||||
)
|
||||
LOG.info(f"Found {len(vf_interfaces)} VF interfaces to rollback.")
|
||||
if len(vf_interfaces) == 0:
|
||||
LOG.info("No VF interfaces found to rollback. No changes required")
|
||||
return
|
||||
|
||||
updated = False
|
||||
|
||||
for iface_id, iface_uuid, max_tx_rate, ifcapabilities in vf_interfaces:
|
||||
capabilities = {}
|
||||
|
||||
if max_tx_rate is not None:
|
||||
capabilities["max_tx_rate"] = max_tx_rate
|
||||
|
||||
if ifcapabilities:
|
||||
try:
|
||||
existing = json.loads(ifcapabilities)
|
||||
capabilities.update(existing)
|
||||
except (json.JSONDecodeError, TypeError) as e:
|
||||
raise ValueError(
|
||||
f"Malformed ifcapabilities for UUID {iface_uuid}: {e}"
|
||||
)
|
||||
|
||||
if not capabilities:
|
||||
continue
|
||||
|
||||
new_ifcap = json.dumps(capabilities) if capabilities else None
|
||||
|
||||
if new_ifcap or max_tx_rate is not None:
|
||||
update_query = sql.SQL(f"""
|
||||
UPDATE {TABLE_NAME}
|
||||
SET {IFCAPABILITIES} = %s, {MAX_TX_RATE} = NULL
|
||||
WHERE id = %s;
|
||||
""")
|
||||
|
||||
db_update(
|
||||
conn, update_query, (new_ifcap, iface_id), autocommit=False
|
||||
)
|
||||
updated = True
|
||||
|
||||
LOG.info(
|
||||
f"Rolled back {TABLE_NAME} for UUID: {iface_uuid} "
|
||||
f"with ifcapabilities: {new_ifcap}"
|
||||
)
|
||||
|
||||
if updated:
|
||||
conn.commit()
|
||||
LOG.info("All applicable records rolled back successfully.")
|
||||
else:
|
||||
LOG.info("No changes were made to the database.")
|
||||
|
||||
|
||||
def patch_felix_configuration():
|
||||
"""Ensure FelixConfiguration chainInsertMode is set to Append."""
|
||||
LOG.info("Patching FelixConfiguration to Append...")
|
||||
|
||||
cmd = [
|
||||
"kubectl", "--kubeconfig=/etc/kubernetes/admin.conf",
|
||||
"patch", "felixconfiguration", "default", "--type=merge",
|
||||
"-p", '{"spec":{"chainInsertMode":"Append"}}'
|
||||
]
|
||||
|
||||
retries, delay = 3, 5
|
||||
timeout = 15
|
||||
|
||||
for attempt in range(retries):
|
||||
try:
|
||||
result = subprocess.run(
|
||||
cmd,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=True,
|
||||
timeout=timeout
|
||||
)
|
||||
LOG.info(f"Patch applied successfully: {result.stdout}")
|
||||
return
|
||||
except subprocess.TimeoutExpired:
|
||||
LOG.warning(f"Attempt {attempt + 1} timed out after {timeout}s.")
|
||||
except subprocess.CalledProcessError as e:
|
||||
LOG.warning(f"Attempt {attempt + 1} failed: {e.stderr}")
|
||||
|
||||
if attempt < retries - 1:
|
||||
time.sleep(delay)
|
||||
else:
|
||||
LOG.error("FelixConfiguration patch failed after retries.")
|
||||
|
||||
|
||||
def main():
|
||||
action = None
|
||||
from_release = None
|
||||
to_release = None
|
||||
postgres_port = DEFAULT_POSTGRES_PORT
|
||||
|
||||
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]
|
||||
else:
|
||||
LOG.error(f"Invalid option {sys.argv[arg]}.")
|
||||
return 1
|
||||
arg += 1
|
||||
|
||||
if action not in ["activate", "activate-rollback"]:
|
||||
LOG.warning(f"Action '{action}' is not valid. Skipping...")
|
||||
return 0
|
||||
|
||||
try:
|
||||
conn = connect_to_db(postgres_port)
|
||||
|
||||
columns_exist(conn)
|
||||
|
||||
if to_release == "25.09" and action == "activate":
|
||||
update_data(conn)
|
||||
patch_felix_configuration()
|
||||
elif from_release == "25.09" and action == "activate-rollback":
|
||||
rollback_data(conn)
|
||||
else:
|
||||
LOG.error(f"Unknown action: {action}")
|
||||
return 1
|
||||
|
||||
except Exception as e:
|
||||
LOG.error(f"Exception during {action}: {e}", exc_info=True)
|
||||
return 1
|
||||
finally:
|
||||
if 'conn' in locals():
|
||||
conn.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -6,7 +6,6 @@
|
||||
# This script will remove the etcd folder of upgrade.
|
||||
#
|
||||
#
|
||||
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
@@ -20,8 +19,6 @@ from software.utilities.utils import configure_logging
|
||||
|
||||
LOG = logging.getLogger('main_logger')
|
||||
ETCD_DIR_NAME = 'db'
|
||||
UPGRADE_FLAG_NAME = '.upgrade'
|
||||
ROLLBACK_FLAG_NAME = '.rollback'
|
||||
|
||||
|
||||
def main():
|
||||
@@ -56,11 +53,10 @@ def main():
|
||||
else:
|
||||
major_release = from_major_release
|
||||
# Check delete action, upgrade and rollback scenario.
|
||||
if action == 'delete' and (to_major_release == '25.09' or (from_major_release == '25.09'
|
||||
and to_major_release == '24.09')):
|
||||
if action == 'delete':
|
||||
try:
|
||||
clean_up_deployment_data(major_release)
|
||||
create_etcd_flag(from_major_release)
|
||||
restart_etcd_service()
|
||||
except Exception as e:
|
||||
LOG.exception("Error: {}".format(e))
|
||||
res = 1
|
||||
@@ -95,20 +91,5 @@ def restart_etcd_service():
|
||||
LOG.error("Error restarting etcd: %s", str(e))
|
||||
|
||||
|
||||
def create_etcd_flag(from_release):
|
||||
"""
|
||||
Creates the right flag accordingly to upgrade or rollback
|
||||
"""
|
||||
if utils.compare_release_version(SW_VERSION, from_release) and from_release == '24.09':
|
||||
etcd_upgrade_flag_path = os.path.join(constants.ETCD_PATH, UPGRADE_FLAG_NAME)
|
||||
subprocess.run(["touch", etcd_upgrade_flag_path], check=True)
|
||||
LOG.info("Flag %s created.", etcd_upgrade_flag_path)
|
||||
else:
|
||||
etcd_rollback_flag_path = os.path.join(constants.ETCD_PATH, ROLLBACK_FLAG_NAME)
|
||||
subprocess.run(["touch", etcd_rollback_flag_path], check=True)
|
||||
LOG.info("Flag %s created.", etcd_rollback_flag_path)
|
||||
restart_etcd_service()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
|
||||
@@ -1,117 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2025 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# This script is responsible to update swanctl configuration
|
||||
# file in multinodes systems.
|
||||
|
||||
import logging
|
||||
import sys
|
||||
import time
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_context import context as mycontext
|
||||
from six.moves import configparser
|
||||
from software.utilities.utils import configure_logging
|
||||
from sysinv.conductor import rpcapiproxy as conductor_rpcapi
|
||||
|
||||
# Constants
|
||||
CONF = cfg.CONF
|
||||
LOG = logging.getLogger('main_logger')
|
||||
SYSINV_CONFIG_FILE = '/etc/sysinv/sysinv.conf'
|
||||
PLATFORM_CONFIG_FILE = '/etc/platform/platform.conf'
|
||||
ACTION_ACTIVATE = 'activate'
|
||||
ACTION_ACTIVATE_ROLLBACK = 'activate-rollback'
|
||||
|
||||
|
||||
def main():
|
||||
action = None
|
||||
from_release = None
|
||||
to_release = None
|
||||
arg = 1
|
||||
while arg < len(sys.argv):
|
||||
if arg == 1:
|
||||
from_release = sys.argv[arg]
|
||||
elif arg == 2:
|
||||
to_release = sys.argv[arg]
|
||||
elif arg == 3:
|
||||
action = sys.argv[arg]
|
||||
elif arg == 4:
|
||||
# optional port parameter for USM upgrade
|
||||
# port = sys.argv[arg]
|
||||
pass
|
||||
else:
|
||||
print("Invalid option %s." % sys.argv[arg])
|
||||
return 1
|
||||
arg += 1
|
||||
configure_logging()
|
||||
LOG.info(
|
||||
"%s invoked from_release = %s to_release = %s action = %s"
|
||||
% (sys.argv[0], from_release, to_release, action)
|
||||
)
|
||||
|
||||
res = 0
|
||||
system_mode = get_system_mode()
|
||||
if system_mode != "simplex" and action in [ACTION_ACTIVATE,
|
||||
ACTION_ACTIVATE_ROLLBACK]:
|
||||
# Options of bind ip to the rpc call
|
||||
rpc_ip_options = [get_conductor_rpc_bind_ip(), 'controller.internal']
|
||||
while None in rpc_ip_options:
|
||||
rpc_ip_options.remove(None)
|
||||
|
||||
for index, ip in enumerate(rpc_ip_options):
|
||||
try:
|
||||
CONF.rpc_zeromq_conductor_bind_ip = ip
|
||||
context = mycontext.get_admin_context()
|
||||
rpcapi = conductor_rpcapi.ConductorAPI(
|
||||
topic=conductor_rpcapi.MANAGER_TOPIC)
|
||||
|
||||
LOG.info("Call Conductor to reconfigure IPsec. "
|
||||
"Bind ip: %s." % CONF.rpc_zeromq_conductor_bind_ip)
|
||||
rpcapi.reconfigure_ipsec(context, action)
|
||||
except Exception as e:
|
||||
if index == (len(rpc_ip_options) - 1):
|
||||
LOG.error("Error configuring keystone endpoints. "
|
||||
"Please verify logs.")
|
||||
res = 1
|
||||
break
|
||||
else:
|
||||
LOG.exception(e)
|
||||
LOG.error("Exception ocurred during script execution, "
|
||||
"retrying after 5 seconds.")
|
||||
time.sleep(5)
|
||||
else:
|
||||
LOG.info(f"Nothing to do for action {action} in {system_mode} environment.")
|
||||
LOG.info("%s completed execution." % (sys.argv[0]))
|
||||
return res
|
||||
|
||||
|
||||
def get_system_mode():
|
||||
ini_str = '[DEFAULT]\n' + open(PLATFORM_CONFIG_FILE, 'r').read()
|
||||
|
||||
config_applied = configparser.RawConfigParser()
|
||||
config_applied.read_string(ini_str)
|
||||
|
||||
if config_applied.has_option('DEFAULT', 'system_mode'):
|
||||
system_mode = config_applied.get('DEFAULT', 'system_mode')
|
||||
else:
|
||||
system_mode = None
|
||||
|
||||
return system_mode
|
||||
|
||||
|
||||
def get_conductor_rpc_bind_ip():
|
||||
ini_str = '[DEFAULT]\n' + open(SYSINV_CONFIG_FILE, 'r').read()
|
||||
config_applied = configparser.RawConfigParser()
|
||||
config_applied.read_string(ini_str)
|
||||
|
||||
conductor_bind_ip = None
|
||||
if config_applied.has_option('DEFAULT', 'rpc_zeromq_conductor_bind_ip'):
|
||||
conductor_bind_ip = \
|
||||
config_applied.get('DEFAULT', 'rpc_zeromq_conductor_bind_ip')
|
||||
return conductor_bind_ip
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@@ -1,178 +0,0 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright (c) 2025 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
#####################################################################
|
||||
#
|
||||
# This script sets the Maintenance Heartbeat period service parameter
|
||||
# according to the release upgrade or rollback activate actions:
|
||||
#
|
||||
# Upgrade - To Release - 25.09 release - heartbeat_period=1000
|
||||
# Rollback - To Release - 24.09 release - heartbeat_period=100
|
||||
#
|
||||
# Performance Features to improve exeution time.
|
||||
#
|
||||
# 1. Only source openrc if its needed
|
||||
# 2. If a service parameter apply change is required,
|
||||
# it is launched in the background asynchronously.
|
||||
# The script does not wait around.
|
||||
#
|
||||
# These features are seen to reduce execution time
|
||||
# down to 4-5 seconds from 20-23 seconds.
|
||||
#
|
||||
# Assumptions: platform.conf and openrc are already part of the
|
||||
# environment passed to this script.
|
||||
#
|
||||
####################################################################
|
||||
NAME=$(basename "$0")
|
||||
|
||||
# The script can be called with the start,
|
||||
# migration, activation and delete actions
|
||||
# with these parameters:
|
||||
FROM_RELEASE=$1
|
||||
TO_RELEASE=$2
|
||||
ACTION=$3
|
||||
|
||||
# List of supported actions
|
||||
MY_SUPPORTED_ACTIONS=("activate" "activate-rollback")
|
||||
|
||||
# Safe valid action checker
|
||||
is_valid_action=false
|
||||
for action in "${MY_SUPPORTED_ACTIONS[@]}"; do
|
||||
if [[ "${ACTION}" == "${action}" ]]; then
|
||||
is_valid_action=true
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
# Exit silently on unsupported actions
|
||||
! ${is_valid_action} && exit 0
|
||||
|
||||
start_time=${SECONDS}
|
||||
|
||||
# The file to log to
|
||||
SOFTWARE_LOG_PATH="/var/log/software.log"
|
||||
PLATFORM_CONF_FILE="/etc/platform/platform.conf"
|
||||
OPENRC_FILE="/etc/platform/openrc"
|
||||
|
||||
# Make this script's logging consistent
|
||||
LOG_PREFIX="Maintenance Heartbeat Period"
|
||||
|
||||
# The desired heartbeat period in these releases
|
||||
HEARTBEAT_PERIOD_24_09=100
|
||||
HEARTBEAT_PERIOD_25_09=1000
|
||||
|
||||
function log {
|
||||
echo "$(date -Iseconds | cut -d'+' -f1): ${NAME}[$$]: INFO: $*" >> "${SOFTWARE_LOG_PATH}" 2>&1
|
||||
}
|
||||
|
||||
if [ $# -lt 3 ]; then
|
||||
error_str="Error: ${LOG_PREFIX} update script requires at least 3 arguments"
|
||||
echo "${error_str}"
|
||||
log "${error_str}"
|
||||
usage_str="Usage: $0 'FROM_RELEASE' 'TO_RELEASE' 'ACTION'"
|
||||
echo "${usage_str}"
|
||||
log "${usage_str}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
function script_exit {
|
||||
delta=$((SECONDS-start_time))
|
||||
log "${LOG_PREFIX} service parameter update for ${ACTION} from ${FROM_RELEASE} to ${TO_RELEASE} - Completed in ${delta} secs"
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Backup plan if called without nodetype being set
|
||||
if [ -z "${nodetype}" ]; then
|
||||
log "${LOG_PREFIX} need to source ${PLATFORM_CONF_FILE}"
|
||||
# shellcheck disable=SC1090
|
||||
source "${PLATFORM_CONF_FILE}"
|
||||
fi
|
||||
|
||||
# Backup plan if called without required environment credentials
|
||||
# Check to see if we need to source openrc
|
||||
if [ -z "${OS_USERNAME+x}" ] || [ -z "${OS_PASSWORD+x}" ]; then
|
||||
if [ -e ${OPENRC_FILE} ]; then
|
||||
log "${LOG_PREFIX} need to source ${OPENRC_FILE}"
|
||||
# shellcheck disable=SC1090
|
||||
source "${OPENRC_FILE}" >/dev/null 2>&1
|
||||
rc=$?
|
||||
if [ "${rc}" -ne 0 ]; then
|
||||
log "No actions required for inactive controller"
|
||||
script_exit
|
||||
fi
|
||||
else
|
||||
log "${LOG_PREFIX} missing ${OPENRC_FILE} ... exiting"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
log "${LOG_PREFIX} ${ACTION} from ${FROM_RELEASE} to ${TO_RELEASE} - Start"
|
||||
|
||||
# shellcheck disable=SC2154
|
||||
if [ "${nodetype}" = "controller" ]; then
|
||||
|
||||
# Query the heartbeat period
|
||||
period=$(system service-parameter-list --service platform \
|
||||
--section maintenance \
|
||||
--name heartbeat_period \
|
||||
--format value | \
|
||||
awk '/heartbeat_period/ {print $5}')
|
||||
|
||||
if ! [[ "${period}" =~ ^[0-9]+$ ]]; then
|
||||
log "Invalid heartbeat period: '${period}'"
|
||||
script_exit
|
||||
fi
|
||||
|
||||
log "${LOG_PREFIX} current value is ${period}"
|
||||
|
||||
if [ "${period}" -lt 100 ] || [ "${period}" -gt 1000 ]; then
|
||||
log "No actions required for invalid heartbeat period of '${period}'"
|
||||
script_exit
|
||||
fi
|
||||
|
||||
# Case: Upgrade to 25.09
|
||||
if [[ "${ACTION}" == "activate" && "${TO_RELEASE}" == "25.09" ]]; then
|
||||
if [ "${period}" -ne "${HEARTBEAT_PERIOD_25_09}" ]; then
|
||||
system "service-parameter-modify" "platform" "maintenance" "heartbeat_period=${HEARTBEAT_PERIOD_25_09}" >/dev/null 2>&1
|
||||
rc=$?
|
||||
# shellcheck disable=SC2181
|
||||
if [ "${rc}" -eq 0 ]; then
|
||||
# Note: The service parameter apply operation is seen to take upwards
|
||||
# of 10 seconds or more.
|
||||
#
|
||||
# For this reason and that it is the last operation in the script
|
||||
# a choice was made to post the apply in the background rather
|
||||
# than wait around for inline completion before continuing.
|
||||
#
|
||||
# The disown option was used in the background launch so that the
|
||||
# apply continues even if this script exits (which it will).
|
||||
system service-parameter-apply platform >/dev/null 2>&1 & disown
|
||||
log "${LOG_PREFIX} service parameter apply change, from ${period} to ${HEARTBEAT_PERIOD_25_09}, posted to sysinv"
|
||||
fi
|
||||
else
|
||||
log "${LOG_PREFIX} no change required"
|
||||
fi
|
||||
elif [[ "${ACTION}" == "activate-rollback" && "${TO_RELEASE}" == "24.09" ]]; then
|
||||
|
||||
if [ "${period}" -ne "${HEARTBEAT_PERIOD_24_09}" ]; then
|
||||
system "service-parameter-modify" "platform" "maintenance" "heartbeat_period=${HEARTBEAT_PERIOD_24_09}" >/dev/null 2>&1
|
||||
rc=$?
|
||||
# shellcheck disable=SC2181
|
||||
if [ "${rc}" -eq 0 ]; then
|
||||
# Posting ther apply operation. See Note above.
|
||||
system "service-parameter-apply" "platform" >/dev/null 2>&1 & disown
|
||||
log "${LOG_PREFIX} service parameter apply change, from ${period} to ${HEARTBEAT_PERIOD_24_09}, posted to sysinv"
|
||||
fi
|
||||
else
|
||||
log "${LOG_PREFIX} no change required"
|
||||
fi
|
||||
else
|
||||
log "No actions for ${ACTION} for ${FROM_RELEASE} to ${TO_RELEASE} transition"
|
||||
fi
|
||||
else
|
||||
log "No actions required for ${nodetype}"
|
||||
fi
|
||||
script_exit
|
||||
Reference in New Issue
Block a user