
On Debian, during the "migrate" phase, the following changes are required: 1. CentOS and Debian differ on the pattern used for multipath disks on rootfs and boot device paths. CentOS uses UUID and Debian WWN: CentOS: "/dev/disk/by-id/uuid-mpath-*" Debian: "/dev/disk/by-id/wwn-0x*" Therefore, the sysinv database shall be migrate properly to address this difference: i_idisks partitions i_pv i_host PASS: AIO-SX Upgrade: Verify after upgrade all device paths are updated. PASS: AIO-DX Upgrade: Verify all device paths in controller-01 are updated. 2. Due to a limitation on the kernel installer on Debian, the parameter hw_settle have been introduced to the host. This parameter is passed in the kernel command line upon host installation and is used by the kickstart processing to add a delay to allow the multipath disks to be properly discovered. If the system is installed on a multipath disk this shall be set to 30 by default on the i_host table. The parameter is isnthwsettle on the kernel line. Test Plan: PASS: AIO-DX Upgrade: Verify on controller-1, after host-upgrade, hw_settle is set to 30 PASS: AIO-DX Upgrade: Verify on controller-0, after host-upgrade, hw_settle is set to 30 Story: 2010608 Task: 47491 Change-Id: I36ecfddfc39607ef6c291f4e109d9642c754470f Signed-off-by: Lucas Borges <lucas.borges@windriver.com>
224 lines
6.0 KiB
Python
Executable File
224 lines
6.0 KiB
Python
Executable File
#!/usr/bin/env python
|
|
# Copyright (c) 2023 Wind River Systems, Inc.
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
#
|
|
import psycopg2
|
|
import re
|
|
import sys
|
|
from controllerconfig.common import log
|
|
from psycopg2.extras import RealDictCursor
|
|
from sysinv.agent import disk
|
|
from sysinv.common import constants
|
|
|
|
|
|
LOG = log.get_logger(__name__)
|
|
|
|
|
|
def main():
|
|
action = None
|
|
from_release = None
|
|
to_release = None
|
|
arg = 1
|
|
while arg < len(sys.argv):
|
|
if arg == 1:
|
|
from_release = sys.argv[arg]
|
|
elif arg == 2:
|
|
to_release = sys.argv[arg]
|
|
elif arg == 3:
|
|
action = sys.argv[arg]
|
|
else:
|
|
print("Invalid option %s." % sys.argv[arg])
|
|
return 1
|
|
arg += 1
|
|
log.configure()
|
|
LOG.info(
|
|
"%s invoked from_release = %s to_release = %s action = %s"
|
|
% (sys.argv[0], from_release, to_release, action)
|
|
)
|
|
res = 0
|
|
if action == "migrate" and (
|
|
from_release == "21.12"
|
|
and to_release == "22.12"
|
|
):
|
|
if not is_multipath():
|
|
LOG.info("Multipath not detected, nothing to do")
|
|
return 0
|
|
|
|
try:
|
|
conn = psycopg2.connect("dbname=sysinv user=postgres")
|
|
do_update_i_host(conn)
|
|
do_update_i_idisks(conn)
|
|
do_update_partitions(conn)
|
|
do_update_i_pv(conn)
|
|
except Exception as e:
|
|
LOG.exception("Error: {}".format(e))
|
|
res = 1
|
|
return res
|
|
|
|
|
|
def do_update_partitions(conn):
|
|
partitions_db = get_partitions(conn)
|
|
|
|
for partition_db in partitions_db:
|
|
new_path_device_node = transform_device_node_path(
|
|
partition_db["device_node"]
|
|
)
|
|
new_part_path_device_path = transform_part_device_path(
|
|
partition_db["device_path"])
|
|
|
|
query = (
|
|
"UPDATE partition SET device_path='{}', "
|
|
"device_node='{}' WHERE id={};".format(
|
|
new_part_path_device_path,
|
|
new_path_device_node,
|
|
partition_db["id"],
|
|
)
|
|
)
|
|
LOG.info(
|
|
"Update partition id={} query={}".format(
|
|
partition_db["id"], query)
|
|
)
|
|
do_update_query(conn, query)
|
|
|
|
|
|
def do_update_i_pv(conn):
|
|
i_pvs = get_i_pvs(conn)
|
|
|
|
for i_pv in i_pvs:
|
|
new_path_device_node = transform_device_node_path(
|
|
i_pv["disk_or_part_device_node"]
|
|
)
|
|
|
|
new_disk_or_part_device_path = transform_part_device_path(
|
|
i_pv["disk_or_part_device_path"]
|
|
)
|
|
|
|
query = (
|
|
"UPDATE i_pv SET disk_or_part_device_node='{}', "
|
|
"lvm_pv_name='{}', disk_or_part_device_path='{}' "
|
|
"WHERE id={}").format(
|
|
new_path_device_node,
|
|
new_path_device_node,
|
|
new_disk_or_part_device_path,
|
|
i_pv["id"])
|
|
LOG.info("Update i_pv id={} query= {}".format(
|
|
i_pv["id"], query))
|
|
|
|
do_update_query(
|
|
conn,
|
|
query
|
|
)
|
|
|
|
|
|
def do_update_i_idisks(conn):
|
|
i_disks_db = get_idisks(conn)
|
|
|
|
for i_disk_db in i_disks_db:
|
|
new_device_path = transform_device_path(i_disk_db["device_path"])
|
|
query = "UPDATE i_idisk SET device_path='{}' "\
|
|
"WHERE id={};".format(
|
|
new_device_path, i_disk_db["id"])
|
|
LOG.info(
|
|
"Update disk id={} device_path={} "
|
|
"to {}".format(
|
|
i_disk_db["id"],
|
|
i_disk_db["device_path"],
|
|
new_device_path))
|
|
do_update_query(conn, query)
|
|
|
|
|
|
def do_update_i_host(conn):
|
|
i_hosts = get_i_hosts(conn)
|
|
|
|
for i_host in i_hosts:
|
|
query = (
|
|
"UPDATE i_host SET boot_device='/dev/mapper/mpatha', "
|
|
"rootfs_device='/dev/mapper/mpatha', hw_settle='30' "
|
|
"WHERE id={};".format(
|
|
i_host["id"]
|
|
)
|
|
)
|
|
LOG.info("Update i_hosts id={} query= {}".format(
|
|
i_host["id"], query))
|
|
|
|
do_update_query(conn, query)
|
|
|
|
|
|
def get_idisks(conn):
|
|
query = "SELECT id, device_node, serial_id, device_id, device_path "\
|
|
"FROM i_idisk;"
|
|
with conn.cursor(cursor_factory=RealDictCursor) as cur:
|
|
cur.execute(query)
|
|
i_disks = cur.fetchall()
|
|
return i_disks
|
|
|
|
|
|
def get_partitions(conn):
|
|
query = "SELECT id, device_node, device_path FROM partition;"
|
|
with conn.cursor(cursor_factory=RealDictCursor) as cur:
|
|
cur.execute(query)
|
|
partitions = cur.fetchall()
|
|
return partitions
|
|
|
|
|
|
def get_i_pvs(conn):
|
|
query = (
|
|
"SELECT id, disk_or_part_device_node, lvm_pv_name, "
|
|
"disk_or_part_device_path FROM i_pv;"
|
|
)
|
|
with conn.cursor(cursor_factory=RealDictCursor) as cur:
|
|
cur.execute(query)
|
|
pvs = cur.fetchall()
|
|
return pvs
|
|
|
|
|
|
def get_i_hosts(conn):
|
|
query = "SELECT id, boot_device, rootfs_device "\
|
|
"FROM i_host WHERE personality='controller';"
|
|
with conn.cursor(cursor_factory=RealDictCursor) as cur:
|
|
cur.execute(query)
|
|
ihosts = cur.fetchall()
|
|
return ihosts
|
|
|
|
|
|
def do_update_query(conn, query):
|
|
with conn.cursor() as cur:
|
|
cur.execute(query)
|
|
conn.commit()
|
|
|
|
|
|
def is_multipath():
|
|
disk_operator = disk.DiskOperator()
|
|
system_disk = disk_operator.idisk_get()[0]
|
|
if constants.DEVICE_NAME_MPATH in system_disk["device_node"]:
|
|
return True
|
|
return False
|
|
|
|
|
|
def transform_device_node_path(path):
|
|
regex = r"(\/dev\/mapper\/mpath)([a-zA-Z])(\d)"
|
|
result = re.match(regex, path)
|
|
if result:
|
|
return "{}{}-part{}".format(result[1], result[2], result[3])
|
|
return path
|
|
|
|
|
|
def transform_device_path(path):
|
|
regex = r"(\/dev\/disk\/by-id\/)dm-uuid-mpath-3(.*)"
|
|
result = re.match(regex, path)
|
|
if result:
|
|
return "{}wwn-0x{}".format(result[1], result[2])
|
|
return path
|
|
|
|
|
|
def transform_part_device_path(path):
|
|
regex = r"(\/dev\/disk\/by-id\/)dm-uuid-(.*)-mpath-3(.*)"
|
|
result = re.match(regex, path)
|
|
if result:
|
|
return "{}wwn-0x{}-{}".format(result[1], result[3], result[2])
|
|
return path
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|