Upgrade adjustments for multipath on Debian

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>
This commit is contained in:
Lucas Borges 2023-02-23 15:29:01 -03:00
parent 703d5ac3da
commit ab11a1380c

View File

@ -0,0 +1,223 @@
#!/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())