From cc4983c0f1a57c2e97605b6ef85abe55522f294d Mon Sep 17 00:00:00 2001 From: Joseph Richard Date: Wed, 11 Apr 2018 15:51:56 -0400 Subject: [PATCH] Move bindings away from controller-1 during upgrade After the upgrade is started, controller-1 is locked, which causes routers and DHCP from being migrated away from controller-1. Because the database is mirrored before this point, any changes to these bindings are lost after swacting to newer load. This results in a loss of connectivity over an AIO upgrade. As a long-term solution, all these changes to the neutron DB should be kept over the upgrade. As an interim solution, this commit adds a migration script to manually move the bindings off of controller-1. Note, this script will have no effect unless compute services ar running on controller-1. Change-Id: I5a42a1f1f20b52665805ce73b56c383a4497b58e Story: 2002886 Task: 22847 Signed-off-by: Jack Ding --- ...-neutron-move-bindings-off-controller-1.py | 133 ++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100755 controllerconfig/controllerconfig/upgrade-scripts/16-neutron-move-bindings-off-controller-1.py diff --git a/controllerconfig/controllerconfig/upgrade-scripts/16-neutron-move-bindings-off-controller-1.py b/controllerconfig/controllerconfig/upgrade-scripts/16-neutron-move-bindings-off-controller-1.py new file mode 100755 index 0000000000..e2bb78d356 --- /dev/null +++ b/controllerconfig/controllerconfig/upgrade-scripts/16-neutron-move-bindings-off-controller-1.py @@ -0,0 +1,133 @@ +#!/usr/bin/env python +# +# Copyright (c) 2018 Wind River Systems, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# +# This script will remove all neutron bindings from controller-1. +# This is necessary to match the behaviour on controller-1 after +# the host is locked. +# This should be removed once we support data migration upon a +# swact to controller-1 during an upgrade. +import psycopg2 + +import sys + +from psycopg2.extras import RealDictCursor +from controllerconfig.common import log + +LOG = log.get_logger(__name__) + + +def main(): + action = None + from_release = None + to_release = None # noqa + arg = 1 + while arg < len(sys.argv): + if arg == 1: + from_release = sys.argv[arg] + elif arg == 2: + to_release = sys.argv[arg] # noqa + elif arg == 3: + action = sys.argv[arg] + else: + print ("Invalid option %s." % sys.argv[arg]) + return 1 + arg += 1 + + log.configure() + + if from_release == "18.03" and action == "migrate": + try: + move_routers_off_controller_1() + move_networks_off_controller_1() + move_port_bindings_off_controller_1() + move_dhcp_port_device_id_off_controller_1() + move_distributed_port_bindings_off_controller_1() + except Exception as ex: + LOG.exception(ex) + print ex + return 1 + + +def run_cmd_postgres(cmd): + """ + This executes the given command as user postgres. This is necessary when + this script is run as root, which is the case on an upgrade activation. + """ + neutron_conn = psycopg2.connect("dbname=neutron user=postgres") + with neutron_conn: + with neutron_conn.cursor(cursor_factory=RealDictCursor) as cur: + cur.execute(cmd) + LOG.info("Executing '%s'" % cmd) + + +def move_routers_off_controller_1(): + """ + This function moves all routers hosted on controller-1 to controller-0. + This is required to match the DB state after controller-1 is locked as + part of the upgrade, at which point they will be automatically reschduled. + """ + cmd = ("UPDATE routerl3agentbindings SET l3_agent_id=" + "(SELECT id FROM agents WHERE agent_type='L3 agent'" + " AND host='controller-0') WHERE l3_agent_id IN" + " (SELECT id FROM agents WHERE agent_type='L3 agent'" + " AND host='controller-1') AND (SELECT count(id)" + " FROM agents WHERE agent_type='L3 agent'" + " AND host='controller-0')=1;") + run_cmd_postgres(cmd) + + +def move_networks_off_controller_1(): + """ + This function moves all dhcp bindings from controller-1 to controller-0. + This is required to match the DB state after controller-1 is locked as + part of the upgrade, at which point they will be automatically reschduled. + """ + cmd = ("UPDATE networkdhcpagentbindings SET dhcp_agent_id=" + "(SELECT id FROM agents WHERE agent_type='DHCP agent'" + " AND host='controller-0') WHERE dhcp_agent_id IN" + " (SELECT id FROM agents WHERE agent_type='DHCP agent'" + " AND host='controller-1') AND (SELECT count(id)" + " FROM agents WHERE agent_type='DHCP agent'" + " AND host='controller-0')=1;") + run_cmd_postgres(cmd) + + +def move_dhcp_port_device_id_off_controller_1(): + """ + This function updates all dhcp ports' device IDs bound to controller-0 + over to controller-1. Note that because the prefix is based on hostname, + this prefix is constant for both controllers. + controller-0: "dhcpaebe17f8-776d-5ab6-9a5f-e9bdeeaca66f" + controller-1: "dhcpf42f2830-b2ec-5a2c-93f3-e3e3328e20a3" + """ + cmd = ("UPDATE ports SET device_id =" + " REPLACE(device_id," + " 'dhcpf42f2830-b2ec-5a2c-93f3-e3e3328e20a3'," + " 'dhcpaebe17f8-776d-5ab6-9a5f-e9bdeeaca66f')" + " WHERE device_owner = 'network:dhcp';") + run_cmd_postgres(cmd) + + +def move_port_bindings_off_controller_1(): + """ + This function moves all port bindings from controller-1 to controller-0. + """ + cmd = ("UPDATE ml2_port_bindings SET host='controller-0'" + " WHERE host='controller-1';") + run_cmd_postgres(cmd) + + +def move_distributed_port_bindings_off_controller_1(): + """ + This function deletes all ml2_distributed_port_bindings on contorller-1. + """ + cmd = ("DELETE FROM ml2_distributed_port_bindings" + " WHERE host='controller-1';") + run_cmd_postgres(cmd) + + +if __name__ == "__main__": + sys.exit(main())