From 7d341604b7bf522660230b1260e77791ad60f6c1 Mon Sep 17 00:00:00 2001 From: Douglas Henrique Koerich Date: Thu, 24 Feb 2022 15:51:22 -0300 Subject: [PATCH] [PTP dual NIC config] Avoid late old-PTP update With the previous logic, the legacy PTP instances could get created much after update/upgrade procedure ran if the host was configured with clock_synchronization=ntp during those procedures, but then changed to ptp later on. This change introduces a flag in the file system telling the update/upgrade procedure actually ran and shouldn't run a second time even the legacy instances were not created and host changed to be ptp-synced. Test Plan: PASS: Upgrade from r/stx6.0 to r/stx7.0 (master), w/o configured PTP; PASS: Upgrade from r/stx6.0 to r/stx7.0 (master), w/ configured PTP; PASS: Patch apply then removal on r/stx6.0, w/o configured PTP; PASS: Patch apply then removal on r/stx6.0, w/ configured PTP; PASS: Upgrade from PATCHED r/stx6.0 to r/stx7.0 (master). Task: 44606 Story: 2009248 Signed-off-by: Douglas Henrique Koerich Change-Id: I04c9cf69a61cdfe21619f419a6d2be7d17467359 --- .../upgrade-scripts/61-move-ptp-parameters.py | 86 ++++++++++++------- .../sysinv/sysinv/sysinv/conductor/manager.py | 52 ++++++----- tsconfig/tsconfig/tsconfig/tsconfig.py | 5 ++ 3 files changed, 88 insertions(+), 55 deletions(-) diff --git a/controllerconfig/controllerconfig/upgrade-scripts/61-move-ptp-parameters.py b/controllerconfig/controllerconfig/upgrade-scripts/61-move-ptp-parameters.py index 2300e1c152..ec93fe0854 100755 --- a/controllerconfig/controllerconfig/upgrade-scripts/61-move-ptp-parameters.py +++ b/controllerconfig/controllerconfig/upgrade-scripts/61-move-ptp-parameters.py @@ -18,6 +18,7 @@ # 'ptp4l' entry in 'ptp_instances' and inserts the corresponding entry # in 'ptp_parameters'. +import os import sys import psycopg2 from controllerconfig.common import log @@ -28,6 +29,11 @@ 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' @@ -88,42 +94,52 @@ def main(): 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'): - conn = psycopg2.connect("dbname=sysinv user=postgres") - try: - if _legacy_ptp4l_not_found(conn): - _move_ptp_parameters(conn) - res = 0 - except psycopg2.Error as ex: - LOG.exception(ex) - res = 1 - except Exception as ex: - LOG.exception(ex) - res = 1 - finally: - conn.close() - return res + # 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: + conn.close() + + return res -def _legacy_ptp4l_not_found(connection): +def _legacy_instances_not_found(connection): with connection.cursor(cursor_factory=DictCursor) as cur: - # Look for legacy ptp4l instance already in database, which is an - # indication this migration was performed before (probably when - # applying an update/patch) - cur.execute("SELECT id FROM ptp_instances WHERE name = %s;", - (PTP_INSTANCE_LEGACY_PTP4L,)) - ptp4l_instance = cur.fetchone() - if ptp4l_instance is not None: - LOG.info("Legacy ptp4l instance found with id = %s" % - ptp4l_instance['id']) + 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("Legacy instance found with id = %s" % instance['id']) return False - LOG.info("No legacy ptp4l instance found") - return True + LOG.info("No legacy instances found") + return True -def _insert_ptp_parameter_owner(connection, type, capabilities=None): +def _insert_ptp_parameter_owner(connection, owner_type, capabilities=None): owner_uuid = uuidutils.generate_uuid() with connection.cursor(cursor_factory=DictCursor) as cur: @@ -131,7 +147,7 @@ def _insert_ptp_parameter_owner(connection, type, capabilities=None): cur.execute("INSERT INTO ptp_parameter_owners " "(created_at, uuid, type, capabilities)" "VALUES (%s, %s, %s, %s);", - (datetime.now(), owner_uuid, type, capabilities)) + (datetime.now(), owner_uuid, owner_type, capabilities)) cur.execute("SELECT id FROM ptp_parameter_owners WHERE uuid = %s;", (owner_uuid,)) row = cur.fetchone() @@ -233,12 +249,12 @@ def _move_ptp_parameters(connection): return with connection.cursor(cursor_factory=DictCursor) as cur: - # List all the interfaces with ptp_role=slave + # List all the interfaces with ptp_role!=none cur.execute("SELECT id FROM interfaces WHERE ptp_role <> %s;", (INTERFACE_PTP_ROLE_NONE,)) - slave_ifaces = cur.fetchall() + ptp_ifaces = cur.fetchall() LOG.debug("There are %d interfaces with ptp_role != none" % - len(slave_ifaces)) + len(ptp_ifaces)) LOG.info("Creating PTP instances for legacy parameters") @@ -297,8 +313,8 @@ def _move_ptp_parameters(connection): _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=slave - for iface in slave_ifaces: + # 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']) @@ -386,6 +402,10 @@ def _move_ptp_parameters(connection): connection, PTP_PARAMETER_BC_JBOD, PTP_BOUNDARY_CLOCK_JBOD_1) _add_parameter_to_instance(connection, ptp4l_uuid, bc_clock_jbod_uuid) + # Committing all changes + LOG.info("Committing PTP legacy configuration into database") + connection.commit() + if __name__ == "__main__": sys.exit(main()) diff --git a/sysinv/sysinv/sysinv/sysinv/conductor/manager.py b/sysinv/sysinv/sysinv/sysinv/conductor/manager.py index 98fcb34048..5df3fc7ba2 100644 --- a/sysinv/sysinv/sysinv/sysinv/conductor/manager.py +++ b/sysinv/sysinv/sysinv/sysinv/conductor/manager.py @@ -7174,11 +7174,6 @@ class ConductorManager(service.PeriodicService): (ptp_interface_id, interface_id)) def _update_ptp_parameters(self): - # TODO: this method is supposed to be called in the context of the same - # patch that is deprecating the former PTP APIs. Thus, in a future - # release (probably the next one) it can be removed - LOG.info("Checking for pending update of PTP parameters") - """This function moves PTP legacy configuration from other tables. Once it is done, the subsequent calls will find the generated PTP instance at database and will return quickly. @@ -7197,18 +7192,32 @@ class ConductorManager(service.PeriodicService): 'ptp4l' entry in 'ptp_instances' and inserts the corresponding entry in 'ptp_parameters'. """ + # TODO: this method is supposed to be called in the context of the same + # patch that is deprecating the former PTP APIs. Thus, in a future + # release (probably the next one) it can be removed + check_file = tsc.PTP_UPDATE_PARAMETERS_FLAG + if os.path.isfile(check_file): + LOG.debug("Already done with legacy PTP configuration") + return + + # Add check file to avoid re-running this method (with late creation of + # legacy instances) + open(check_file, 'w').close() + try: - # Look for legacy ptp4l instance already in database, which is an - # indication this migration was performed before (probably when - # upgrading the release) - try: - ptp_instance = self.dbapi.ptp_instance_get_by_name( - constants.PTP_INSTANCE_LEGACY_PTP4L) - LOG.debug("Legacy ptp4l instance found with id = %s" % - ptp_instance['id']) - return - except exception.NotFound: - LOG.debug("No legacy ptp4l instance found") + # This additional check ensures that patch re-apply won't fail + # because legacy entries weren't removed together with the check + # file and the patch itself, when it got removed earlier + legacy_names = [constants.PTP_INSTANCE_LEGACY_PTP4L, + constants.PTP_INSTANCE_LEGACY_PHC2SYS] + for name in legacy_names: + try: + ptp_instance = self.dbapi.ptp_instance_get_by_name(name) + LOG.info("Legacy PTP instance %s found with id = %s, " + "skipping update" % (name, ptp_instance['id'])) + return + except exception.NotFound: + LOG.debug("Legacy PTP instance %s not found" % name) # List all the hosts with clock_synchronization=ptp hosts_list = self.dbapi.ihost_get_list() @@ -7230,14 +7239,14 @@ class ConductorManager(service.PeriodicService): # No need for upgrade return - # List all the interfaces with ptp_role=slave + # List all the interfaces with ptp_role!=none ifaces_list = self.dbapi.iinterface_get_list() - slave_ifaces_list = [ + ptp_ifaces_list = [ iface for iface in ifaces_list if iface['ptp_role'] != constants.INTERFACE_PTP_ROLE_NONE] LOG.debug("There are %d interfaces with ptp_role != none" % - len(slave_ifaces_list)) + len(ptp_ifaces_list)) LOG.info("Creating PTP instances for legacy parameters") @@ -7281,9 +7290,8 @@ class ConductorManager(service.PeriodicService): self._update_ptp_assign_instance_to_host(ptp4l_id, host['id']) self._update_ptp_assign_instance_to_host(phc2sys_id, host['id']) - # Assign legacy PTP interfaces to all interfaces with - # ptp_role=slave - for iface in slave_ifaces_list: + # Assign legacy PTP interfaces to all interfaces with ptp_role!=none + for iface in ptp_ifaces_list: self._update_ptp_assign_ptp_to_interface(ptp4lif_id, iface['id']) self._update_ptp_assign_ptp_to_interface(phc2sysif_id, diff --git a/tsconfig/tsconfig/tsconfig/tsconfig.py b/tsconfig/tsconfig/tsconfig/tsconfig.py index ecb1c08b5d..5fb0eba487 100644 --- a/tsconfig/tsconfig/tsconfig/tsconfig.py +++ b/tsconfig/tsconfig/tsconfig/tsconfig.py @@ -241,6 +241,11 @@ UPGRADE_ROLLBACK_FLAG = os.path.join( UPGRADE_ABORT_FILE = '.upgrade_abort' UPGRADE_ABORT_FLAG = os.path.join( CONFIG_PATH, UPGRADE_ABORT_FILE) +# Update/upgrade from legacy PTP configuration has been already run +# TODO(douglashenrique.koerich): remove it in a later release # pylint: disable=fixme +PTP_UPDATE_PARAMETERS_DONE = '.update_ptp_parameters_done' +PTP_UPDATE_PARAMETERS_FLAG = os.path.join(CONFIG_PATH, + PTP_UPDATE_PARAMETERS_DONE) # Set on controller-0 (by controller-1) to indicate that data migration has # started