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 <jack.ding@windriver.com>
This commit is contained in:
Joseph Richard 2018-04-11 15:51:56 -04:00 committed by Jack Ding
parent 97c0576e96
commit cc4983c0f1
1 changed files with 133 additions and 0 deletions

View File

@ -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())