709 lines
28 KiB
Python
709 lines
28 KiB
Python
#!/usr/bin/env python
|
|
# Copyright (c) 2017-2018 Wind River Systems, Inc.
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
#
|
|
# This script will update the partition schema for controller-1.
|
|
|
|
import collections
|
|
import json
|
|
import math
|
|
import psycopg2
|
|
import re
|
|
import sys
|
|
import subprocess
|
|
import parted
|
|
from sysinv.openstack.common import uuidutils
|
|
|
|
from sysinv.common import constants
|
|
from psycopg2.extras import RealDictCursor
|
|
from controllerconfig.common import log
|
|
from controllerconfig import utils
|
|
|
|
from tsconfig.tsconfig import system_mode
|
|
|
|
LOG = log.get_logger(__name__)
|
|
|
|
Partition_Tuple = collections.namedtuple(
|
|
'partition', 'uuid idisk_id idisk_uuid size_mib device_node device_path '
|
|
'status type_guid forihostid foripvid start_mib end_mib')
|
|
uefi_cgts_pv_1_partition_number = 4
|
|
bios_cgts_pv_1_partition_number = 5
|
|
|
|
|
|
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 == "17.06" and action == "migrate":
|
|
try:
|
|
create_user_partitions()
|
|
except Exception as ex:
|
|
LOG.exception(ex)
|
|
return 1
|
|
|
|
|
|
def get_partitions(device_path):
|
|
"""Obtain existing partitions from a disk."""
|
|
try:
|
|
device = parted.getDevice(device_path)
|
|
disk = parted.newDisk(device)
|
|
except Exception as e:
|
|
LOG.info("No partition info for disk %s - %s" % (device_path, e))
|
|
return None
|
|
|
|
ipartitions = []
|
|
|
|
partitions = disk.partitions
|
|
|
|
for partition in partitions:
|
|
part_size_mib = partition.getSize()
|
|
part_device_node = partition.path
|
|
part_device_path = '{}-part{}'.format(device_path,
|
|
partition.number)
|
|
start_mib = math.ceil(float(partition.geometry.start) / 2048)
|
|
end_mib = math.ceil(float(partition.geometry.end) / 2048)
|
|
|
|
part_attrs = {
|
|
'size_mib': part_size_mib,
|
|
'device_node': part_device_node,
|
|
'device_path': part_device_path,
|
|
'start_mib': start_mib,
|
|
'end_mib': end_mib
|
|
}
|
|
ipartitions.append(part_attrs)
|
|
|
|
return ipartitions
|
|
|
|
|
|
def get_disk_available_mib(device_node):
|
|
# Get sector size command.
|
|
sector_size_bytes_cmd = '{} {}'.format('blockdev --getss', device_node)
|
|
|
|
# Get total free space in sectors command.
|
|
avail_space_sectors_cmd = '{} {} {}'.format(
|
|
'sgdisk -p', device_node, "| grep \"Total free space\"")
|
|
|
|
# Get the sector size.
|
|
sector_size_bytes_process = subprocess.Popen(
|
|
sector_size_bytes_cmd, stdout=subprocess.PIPE, shell=True)
|
|
sector_size_bytes = sector_size_bytes_process.stdout.read().rstrip()
|
|
|
|
# Get the free space.
|
|
avail_space_sectors_process = subprocess.Popen(
|
|
avail_space_sectors_cmd, stdout=subprocess.PIPE, shell=True)
|
|
avail_space_sectors_output = avail_space_sectors_process.stdout.read()
|
|
avail_space_sectors = re.findall('\d+',
|
|
avail_space_sectors_output)[0].rstrip()
|
|
|
|
# Free space in MiB.
|
|
avail_space_mib = (int(sector_size_bytes) * int(avail_space_sectors) /
|
|
(1024 ** 2))
|
|
|
|
# Keep 2 MiB for partition table.
|
|
if avail_space_mib >= 2:
|
|
avail_space_mib = avail_space_mib - 2
|
|
|
|
return avail_space_mib
|
|
|
|
|
|
def build_partition_device_node(disk_device_node, partition_number):
|
|
if constants.DEVICE_NAME_NVME in disk_device_node:
|
|
partition_device_node = '{}p{}'.format(
|
|
disk_device_node, partition_number)
|
|
else:
|
|
partition_device_node = '{}{}'.format(
|
|
disk_device_node, partition_number)
|
|
|
|
LOG.info("partition_device_node: %s" % partition_device_node)
|
|
|
|
return partition_device_node
|
|
|
|
|
|
def update_db_pv(cur, part_device_path, part_device_node, part_uuid,
|
|
lvm_pv_name, pv_id):
|
|
cur.execute("update i_pv set disk_or_part_device_path=%s,"
|
|
"disk_or_part_device_node=%s, disk_or_part_uuid=%s,"
|
|
"lvm_pv_name=%s where id=%s",
|
|
(part_device_path, part_device_node, part_uuid,
|
|
lvm_pv_name, pv_id))
|
|
|
|
|
|
def create_partition(cur, partition):
|
|
cur.execute(
|
|
"insert into partition(uuid, idisk_id, idisk_uuid, size_mib,"
|
|
"device_node, device_path, status, type_guid, "
|
|
"forihostid, foripvid, start_mib, end_mib) "
|
|
"values(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)",
|
|
partition)
|
|
|
|
|
|
def get_storage_backend(cur):
|
|
cur.execute("select storage_backend.id, storage_backend.backend, "
|
|
"storage_backend.state, "
|
|
"storage_backend.forisystemid, storage_backend.services, "
|
|
"storage_backend.capabilities from storage_backend")
|
|
storage_backend = cur.fetchone()
|
|
if not storage_backend:
|
|
LOG.exception("No storage backend present, exiting.")
|
|
raise
|
|
|
|
backend = storage_backend['backend']
|
|
LOG.info("storage_backend: %s" % str(storage_backend))
|
|
|
|
return backend
|
|
|
|
|
|
def cgts_vg_extend(cur, disk, partition4, pv_cgts_vg, partition_number,
|
|
part_size_mib):
|
|
part_device_node = '{}{}'.format(disk.get('device_node'),
|
|
partition_number)
|
|
part_device_path = '{}-part{}'.format(disk.get('device_path'),
|
|
partition_number)
|
|
|
|
LOG.info("Extra cgts-vg partition size: %s device node: %s "
|
|
"device path: %s" %
|
|
(part_size_mib, part_device_node, part_device_path))
|
|
|
|
part_uuid = uuidutils.generate_uuid()
|
|
|
|
new_partition = Partition_Tuple(
|
|
uuid=part_uuid, idisk_id=disk.get('id'),
|
|
idisk_uuid=disk.get('uuid'), size_mib=part_size_mib,
|
|
device_node=part_device_node, device_path=part_device_path,
|
|
status=constants.PARTITION_CREATE_ON_UNLOCK_STATUS,
|
|
type_guid=constants.USER_PARTITION_PHYSICAL_VOLUME,
|
|
forihostid=disk['forihostid'], foripvid=None,
|
|
start_mib=None, end_mib=None)
|
|
|
|
create_partition(cur, new_partition)
|
|
|
|
pv_uuid = uuidutils.generate_uuid()
|
|
cur.execute(
|
|
"insert into i_pv(uuid, pv_state, pv_type, disk_or_part_uuid, "
|
|
"disk_or_part_device_node, disk_or_part_device_path, lvm_pv_name, "
|
|
"lvm_vg_name, forihostid, forilvgid) "
|
|
"values(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)",
|
|
(pv_uuid, constants.PV_ADD, constants.PV_TYPE_PARTITION, part_uuid,
|
|
part_device_node, part_device_path, part_device_node,
|
|
constants.LVG_CGTS_VG, disk.get('forihostid'),
|
|
pv_cgts_vg.get('forilvgid')))
|
|
|
|
# Get the PV.
|
|
cur.execute("select i_pv.id from i_pv where uuid=%s",
|
|
(pv_uuid,))
|
|
pv = cur.fetchone()
|
|
|
|
# Update partition.
|
|
cur.execute(
|
|
"update partition set foripvid=%s where uuid=%s",
|
|
(pv.get('id'), part_uuid))
|
|
|
|
|
|
def update_ctrl0_cinder_partition_pv(cur):
|
|
# Get controller-0 id.
|
|
hostname = constants.CONTROLLER_0_HOSTNAME
|
|
cur.execute("select i_host.id, i_host.rootfs_device from i_host "
|
|
"where hostname=%s;", (hostname,))
|
|
row = cur.fetchone()
|
|
if row is None:
|
|
LOG.exception("Failed to fetch %s host_id" % hostname)
|
|
raise
|
|
ctrl0_id = row['id']
|
|
|
|
# Controller-0 has only one partition added, the cinder partition.
|
|
cur.execute("select partition.id, partition.uuid, "
|
|
"partition.status, partition.device_node, "
|
|
"partition.device_path, partition.size_mib,"
|
|
"partition.idisk_uuid, partition.foripvid "
|
|
"from partition where forihostid = %s",
|
|
(ctrl0_id,))
|
|
ctrl0_cinder_partition = cur.fetchone()
|
|
if not ctrl0_cinder_partition:
|
|
LOG.exception("Failed to get ctrl0 cinder volumes partition")
|
|
raise
|
|
|
|
# Obtain the cinder PV for controller-0.
|
|
cur.execute("select i_pv.id, i_pv.disk_or_part_uuid, "
|
|
"i_pv.disk_or_part_device_node, "
|
|
"i_pv.disk_or_part_device_path, i_pv.lvm_pv_size,"
|
|
"i_pv.lvm_pv_name, i_pv.lvm_vg_name, i_pv.forilvgid,"
|
|
"i_pv.pv_type from i_pv where forihostid=%s and "
|
|
"lvm_vg_name=%s",
|
|
(ctrl0_id, constants.LVG_CINDER_VOLUMES))
|
|
ctrl0_cinder_pv = cur.fetchone()
|
|
if not ctrl0_cinder_pv:
|
|
LOG.exception("Failed to get ctrl0 cinder physical volume")
|
|
raise
|
|
|
|
# Update the cinder PV with the partition info.
|
|
update_db_pv(cur, ctrl0_cinder_partition['device_path'],
|
|
ctrl0_cinder_partition['device_node'],
|
|
ctrl0_cinder_partition['uuid'],
|
|
ctrl0_cinder_partition['device_node'],
|
|
ctrl0_cinder_pv['id'])
|
|
|
|
# Mark the cinder partition in use.
|
|
cur.execute("update partition set foripvid=%s, status=%s "
|
|
"where id=%s",
|
|
(ctrl0_cinder_pv['id'], constants.PARTITION_IN_USE_STATUS,
|
|
ctrl0_cinder_partition['id']))
|
|
|
|
|
|
def update_partition_pv(cur, pvs, partitions, disks):
|
|
backend = get_storage_backend(cur)
|
|
if system_mode != constants.SYSTEM_MODE_SIMPLEX and backend != "ceph":
|
|
update_ctrl0_cinder_partition_pv(cur)
|
|
|
|
for pv in pvs:
|
|
if (pv['pv_type'] == constants.PV_TYPE_PARTITION and
|
|
'-part' not in pv['disk_or_part_device_path']):
|
|
if "drbd" in pv['lvm_pv_name']:
|
|
partition_number = '1'
|
|
else:
|
|
partition_number = (
|
|
re.match('.*?([0-9]+)$', pv['lvm_pv_name']).group(1))
|
|
# Update disk foripvid to null.
|
|
disk = next((
|
|
d for d in disks
|
|
if d['device_path'] == pv['disk_or_part_device_path']), None)
|
|
if disk:
|
|
LOG.info("Set foripvid to null for disk %s" % disk['id'])
|
|
cur.execute(
|
|
"update i_idisk set foripvid=null where id=%s",
|
|
(disk['id'],))
|
|
|
|
# Update partition device path and device path for the current PV.
|
|
part_device_path = "{}{}{}".format(
|
|
pv['disk_or_part_device_path'],
|
|
'-part',
|
|
partition_number)
|
|
|
|
if constants.DEVICE_NAME_NVME in pv['disk_or_part_device_node']:
|
|
part_device_node = "{}p{}".format(
|
|
pv['disk_or_part_device_node'],
|
|
partition_number)
|
|
else:
|
|
part_device_node = "{}{}".format(
|
|
pv['disk_or_part_device_node'],
|
|
partition_number)
|
|
|
|
LOG.info("Old PV device path: %s New PV device path: %s" %
|
|
(pv['disk_or_part_device_path'], part_device_path))
|
|
LOG.info("Old PV device node: %s New PV device node: %s" %
|
|
(pv['disk_or_part_device_node'], part_device_node))
|
|
|
|
lvm_pv_name = part_device_node
|
|
# Do not use constant here yet since this may change due to
|
|
# cinder removal from cfg ctrl US.
|
|
if "drbd" in pv['lvm_pv_name']:
|
|
lvm_pv_name = pv['lvm_pv_name']
|
|
|
|
part = next((
|
|
p for p in partitions
|
|
if p['device_path'] == part_device_path), None)
|
|
|
|
if not part:
|
|
LOG.info("No %s partition, returning" % part_device_path)
|
|
continue
|
|
|
|
# Update the PV DB entry.
|
|
update_db_pv(cur, part_device_path, part_device_node,
|
|
part['uuid'], lvm_pv_name, pv['id'])
|
|
|
|
# Update the PV DB entry.
|
|
cur.execute(
|
|
"update partition set foripvid=%s, status=%s "
|
|
"where id=%s",
|
|
(pv['id'], constants.PARTITION_IN_USE_STATUS,
|
|
part['id']))
|
|
|
|
|
|
def create_ctrl0_cinder_partition(cur, stors, part_size):
|
|
hostname = constants.CONTROLLER_0_HOSTNAME
|
|
cur.execute("select i_host.id, i_host.rootfs_device from i_host "
|
|
"where hostname=%s;", (hostname,))
|
|
row = cur.fetchone()
|
|
if row is None:
|
|
LOG.exception("Failed to fetch %s host_id" % hostname)
|
|
raise
|
|
|
|
controller_id = row['id']
|
|
|
|
# Get the disks for controller-0.
|
|
cur.execute("select i_idisk.forihostid, i_idisk.uuid, "
|
|
"i_idisk.device_node, i_idisk.device_path, "
|
|
"i_idisk.id, i_idisk.size_mib from i_idisk where "
|
|
"forihostid = %s", (controller_id,))
|
|
|
|
disks_ctrl0 = cur.fetchall()
|
|
|
|
# Obtain the cinder disk for controller-0.
|
|
cinder_disk_ctrl0 = next((
|
|
d for d in disks_ctrl0
|
|
if d['uuid'] in [s['idisk_uuid'] for s in stors]), None)
|
|
LOG.info("cinder_disk_ctrl0: %s" % str(cinder_disk_ctrl0))
|
|
if not cinder_disk_ctrl0:
|
|
LOG.exception("Failed to get cinder disk for host %s" %
|
|
controller_id)
|
|
raise
|
|
|
|
# Fill in partition info.
|
|
new_part_size = part_size
|
|
new_part_device_node = "%s1" % cinder_disk_ctrl0['device_node']
|
|
new_part_device_path = ('%s-part1' %
|
|
cinder_disk_ctrl0['device_path'])
|
|
LOG.info("New partition: %s - %s" %
|
|
(new_part_device_node, new_part_device_path))
|
|
new_part_uuid = uuidutils.generate_uuid()
|
|
|
|
new_partition = Partition_Tuple(
|
|
uuid=new_part_uuid,
|
|
idisk_id=cinder_disk_ctrl0.get('id'),
|
|
idisk_uuid=cinder_disk_ctrl0.get('uuid'),
|
|
size_mib=new_part_size,
|
|
device_node=new_part_device_node,
|
|
device_path=new_part_device_path,
|
|
status=constants.PARTITION_IN_USE_STATUS,
|
|
type_guid=constants.USER_PARTITION_PHYSICAL_VOLUME,
|
|
forihostid=controller_id,
|
|
foripvid=None,
|
|
start_mib=None,
|
|
end_mib=None)
|
|
|
|
create_partition(cur, new_partition)
|
|
|
|
|
|
def create_db_partition_entries(cur, disks):
|
|
# Get the stors with the cinder function.
|
|
cur.execute("select i_istor.id, i_istor.idisk_uuid, "
|
|
"i_istor.function, i_istor.forihostid "
|
|
"from i_istor where function = %s",
|
|
(constants.STOR_FUNCTION_CINDER,))
|
|
stors = cur.fetchall()
|
|
|
|
cinder_partition = False
|
|
for disk in disks:
|
|
partitions = get_partitions(disk['device_path'])
|
|
|
|
LOG.info("partitions: %s" % str(partitions))
|
|
# Create the DB entries for all disk partitions on controller-1.
|
|
# For controller-0 we will only create the cinder partition, as the
|
|
# rest will be reported by sysinv-agent once the host is upgraded.
|
|
if not partitions:
|
|
continue
|
|
|
|
for part in partitions:
|
|
part_disk = next((
|
|
d for d in disks if d['device_path'] in part['device_path']
|
|
))
|
|
|
|
crt_stor = next((s for s in stors
|
|
if s['idisk_uuid'] == part_disk['uuid']), None)
|
|
|
|
part_type_guid = constants.LINUX_LVM_PARTITION
|
|
if crt_stor:
|
|
part_type_guid = constants.USER_PARTITION_PHYSICAL_VOLUME
|
|
|
|
part_size = part['size_mib']
|
|
part_device_node = part['device_node']
|
|
part_device_path = part['device_path']
|
|
|
|
LOG.info("New partition size: %s part device node: %s "
|
|
"part device path: %s" %
|
|
(part_size, part_device_node, part_device_path))
|
|
|
|
part_uuid = uuidutils.generate_uuid()
|
|
new_partition = Partition_Tuple(
|
|
uuid=part_uuid, idisk_id=part_disk.get('id'),
|
|
idisk_uuid=part_disk.get('uuid'), size_mib=part_size,
|
|
device_node=part_device_node, device_path=part_device_path,
|
|
status=constants.PARTITION_IN_USE_STATUS,
|
|
type_guid=part_type_guid,
|
|
forihostid=disk['forihostid'], foripvid=None,
|
|
start_mib=part['start_mib'], end_mib=part['end_mib'])
|
|
|
|
create_partition(cur, new_partition)
|
|
|
|
# If this is the cinder disk, also create partition for the other
|
|
# controller.
|
|
if not crt_stor:
|
|
LOG.info("Disk %s is not a cinder disk for host %s" %
|
|
(part_disk['device_path'], part_disk['forihostid']))
|
|
continue
|
|
|
|
if system_mode == constants.SYSTEM_MODE_SIMPLEX:
|
|
cinder_partition = True
|
|
continue
|
|
|
|
# Also create the cinder partition for controller-0.
|
|
create_ctrl0_cinder_partition(cur, stors, part_size)
|
|
cinder_partition = True
|
|
|
|
# If somehow the cinder disk was also wiped and the partition was lost,
|
|
# we need to retrieve it in another way.
|
|
if not cinder_partition:
|
|
LOG.info("Cinder partition was wiped so we need to create it")
|
|
for disk in disks:
|
|
d_json_dict = json.loads(disk['capabilities'])
|
|
if (constants.IDISK_DEV_FUNCTION in d_json_dict and
|
|
d_json_dict['device_function'] == 'cinder_device'):
|
|
if 'cinder_gib' in d_json_dict:
|
|
LOG.info("cinder_gib: %s" % d_json_dict['cinder_gib'])
|
|
|
|
# Partition size calculated from the size of cinder_gib.
|
|
part_size = int(d_json_dict['cinder_gib'])
|
|
|
|
# Actual disk size in MiB.
|
|
device = parted.getDevice(disk['device_path'])
|
|
disk_size = device.length * device.sectorSize / (1024 ** 2)
|
|
|
|
part_size = min(part_size, disk_size - 2)
|
|
|
|
if constants.DEVICE_NAME_NVME in disk['device_node']:
|
|
part_device_node = "%sp1" % disk['device_node']
|
|
else:
|
|
part_device_node = "%s1" % disk['device_node']
|
|
part_device_path = "%s-part1" % disk['device_path']
|
|
part_start_mib = 2
|
|
part_end_mib = 2 + part_size
|
|
|
|
LOG.info("New partition size: %s part device node: %s "
|
|
"part device path: %s part_end_mib: %s" %
|
|
(part_size, part_device_node, part_device_path,
|
|
part_end_mib))
|
|
|
|
part_uuid = uuidutils.generate_uuid()
|
|
new_partition = Partition_Tuple(
|
|
uuid=part_uuid,
|
|
idisk_id=disk.get('id'),
|
|
idisk_uuid=disk.get('uuid'), size_mib=part_size,
|
|
device_node=part_device_node,
|
|
device_path=part_device_path,
|
|
status=constants.PARTITION_IN_USE_STATUS,
|
|
type_guid=constants.USER_PARTITION_PHYSICAL_VOLUME,
|
|
forihostid=disk['forihostid'], foripvid=None,
|
|
start_mib=part_start_mib, end_mib=part_end_mib)
|
|
create_partition(cur, new_partition)
|
|
if system_mode != constants.SYSTEM_MODE_SIMPLEX:
|
|
create_ctrl0_cinder_partition(cur, stors, part_size)
|
|
break
|
|
|
|
|
|
def create_user_partitions():
|
|
conn = psycopg2.connect("dbname=sysinv user=postgres")
|
|
with conn:
|
|
with conn.cursor(cursor_factory=RealDictCursor) as cur:
|
|
hostname = constants.CONTROLLER_1_HOSTNAME
|
|
if system_mode == constants.SYSTEM_MODE_SIMPLEX:
|
|
hostname = constants.CONTROLLER_0_HOSTNAME
|
|
|
|
cur.execute("select i_host.id, i_host.rootfs_device from i_host "
|
|
"where hostname=%s;", (hostname,))
|
|
row = cur.fetchone()
|
|
if row is None:
|
|
LOG.exception("Failed to fetch %s host_id" % hostname)
|
|
raise
|
|
|
|
controller_id = row['id']
|
|
controller_rootfs = row['rootfs_device']
|
|
|
|
# Get the disks for the controller.
|
|
cur.execute("select i_idisk.forihostid, i_idisk.uuid, "
|
|
"i_idisk.device_node, i_idisk.device_path, "
|
|
"i_idisk.capabilities, "
|
|
"i_idisk.id, i_idisk.size_mib from i_idisk where "
|
|
"forihostid = %s", (controller_id,))
|
|
|
|
disks = cur.fetchall()
|
|
|
|
# Get the PVs for the controller.
|
|
cur.execute(
|
|
"select i_pv.id, i_pv.disk_or_part_uuid, "
|
|
"i_pv.disk_or_part_device_node, "
|
|
"i_pv.disk_or_part_device_path, i_pv.lvm_pv_size,"
|
|
"i_pv.lvm_pv_name, i_pv.lvm_vg_name, i_pv.forilvgid,"
|
|
"i_pv.pv_type from i_pv where forihostid = %s",
|
|
(controller_id,))
|
|
pvs = cur.fetchall()
|
|
|
|
# Obtain the rootfs disk. This is for handling the case when
|
|
# rootfs is not on /dev/sda.
|
|
controller_rootfs_disk = next((
|
|
d for d in disks
|
|
if (d.get('device_path') == controller_rootfs or
|
|
controller_rootfs in d.get('device_node'))), None)
|
|
LOG.info("controller_rootfs_disk: %s" % controller_rootfs_disk)
|
|
|
|
create_db_partition_entries(cur, disks)
|
|
|
|
# Get the PVs for the controller.
|
|
cur.execute(
|
|
"select partition.id, partition.uuid, "
|
|
"partition.status, partition.device_node, "
|
|
"partition.device_path, partition.size_mib,"
|
|
"partition.idisk_uuid, partition.foripvid "
|
|
"from partition where forihostid = %s",
|
|
(controller_id,))
|
|
partitions = cur.fetchall()
|
|
|
|
update_partition_pv(cur, pvs, partitions, disks)
|
|
|
|
# If this is not an AIO setup, we must return, as we already have
|
|
# all the needed information.
|
|
if utils.get_system_type() != constants.TIS_AIO_BUILD:
|
|
LOG.info("This is not an AIO setup, nothing to do here.")
|
|
return
|
|
|
|
# Get the PVs for cgts-vg from the root fs disk, present in the DB.
|
|
# This list can have max 2 elements.
|
|
cgts_vg_pvs = [pv for pv in pvs
|
|
if pv['lvm_vg_name'] == constants.LVG_CGTS_VG and
|
|
(controller_rootfs_disk['device_path'] in
|
|
pv['disk_or_part_device_path'])]
|
|
|
|
LOG.info("cgts-vg pvs: %s" % str(cgts_vg_pvs))
|
|
|
|
# Build the PV name of the initial PV for cgts-vg.
|
|
R5_cgts_pv_1_name = build_partition_device_node(
|
|
controller_rootfs_disk['device_node'],
|
|
uefi_cgts_pv_1_partition_number)
|
|
|
|
# Get the initial PV of cgts-vg. If it's not present with the
|
|
# provided name, then we're probably on a BIOS setup.
|
|
R5_cgts_pv_1 = next((
|
|
pv for pv in cgts_vg_pvs
|
|
if pv['lvm_pv_name'] == R5_cgts_pv_1_name), None)
|
|
|
|
# Get the device used by R5_cgts_pv_1.
|
|
R5_cgts_pv_1_part = next((
|
|
p for p in partitions
|
|
if p['device_node'] == R5_cgts_pv_1_name),
|
|
None)
|
|
|
|
# On an R4 AIO installed with BIOS, we won't have 6 partitions
|
|
# right after install, but only 4.
|
|
# R4 PV /dev/sda5 thus should become PV /dev/sda4 in R5.
|
|
if not R5_cgts_pv_1:
|
|
LOG.info("Probably bios here, we need to update the DB for "
|
|
"cgts-vg partitions and pv")
|
|
R4_cgts_pv_1_name = build_partition_device_node(
|
|
controller_rootfs_disk['device_node'],
|
|
bios_cgts_pv_1_partition_number)
|
|
R5_cgts_pv_1 = next((
|
|
pv for pv in pvs
|
|
if pv['lvm_pv_name'] == R4_cgts_pv_1_name),
|
|
None)
|
|
|
|
cur.execute(
|
|
"update partition set foripvid=%s, status=%s "
|
|
"where device_path=%s and forihostid=%s",
|
|
(R5_cgts_pv_1.get('id'), constants.PARTITION_IN_USE_STATUS,
|
|
R5_cgts_pv_1_part['device_path'], controller_id))
|
|
|
|
update_db_pv(cur, R5_cgts_pv_1_part['device_path'],
|
|
R5_cgts_pv_1_part['device_node'],
|
|
R5_cgts_pv_1_part['uuid'],
|
|
R5_cgts_pv_1_part['device_node'],
|
|
R5_cgts_pv_1.get('id'))
|
|
|
|
cgts_vg_pvs.remove(R5_cgts_pv_1)
|
|
|
|
# There is a high chance that the current R5 /dev/sda4 partition is
|
|
# too small for the R4 cgts-vg. In this case, we need to create
|
|
# an extra partition & PV for cgts-vg.
|
|
part_number = 5
|
|
|
|
extra_cgts_part_size = math.ceil(
|
|
float(R5_cgts_pv_1.get('lvm_pv_size')) / (1024 ** 2) -
|
|
R5_cgts_pv_1_part.get('size_mib'))
|
|
if extra_cgts_part_size > 0:
|
|
LOG.info("/dev/sda4 is not enough for R4 cgts-vg")
|
|
cgts_vg_extend(cur, controller_rootfs_disk, R5_cgts_pv_1_part,
|
|
R5_cgts_pv_1,
|
|
part_number, extra_cgts_part_size)
|
|
part_number = part_number + 1
|
|
else:
|
|
extra_cgts_part_size = 0
|
|
|
|
# If the remaining space was used by either nova-local or cgts-vg,
|
|
# then the R4 partition must be specifically created.
|
|
if cgts_vg_pvs:
|
|
last_rootfs_pv = cgts_vg_pvs[0]
|
|
LOG.info("Extra rootfs disk space used by cgts-vg")
|
|
else:
|
|
# Get the nova-local PV from the rootfs disk.
|
|
last_rootfs_pv = next((
|
|
pv for pv in pvs
|
|
if (pv['lvm_vg_name'] == constants.LVG_NOVA_LOCAL and
|
|
controller_rootfs_disk['device_node'] in
|
|
pv['lvm_pv_name'])),
|
|
None)
|
|
|
|
if last_rootfs_pv:
|
|
LOG.info("Extra rootfs disk space used by nova-local")
|
|
|
|
# If the remaining space is not used, return.
|
|
if not last_rootfs_pv:
|
|
LOG.info("Extra rootfs disk space not used, return")
|
|
return
|
|
|
|
# Create the partition DB entry and update the associated
|
|
# physical volume.
|
|
disk_available_mib = get_disk_available_mib(
|
|
controller_rootfs_disk['device_node']) - extra_cgts_part_size
|
|
LOG.info("Available mib: %s" % disk_available_mib)
|
|
|
|
part_size = disk_available_mib
|
|
part_device_node = '{}{}'.format(
|
|
controller_rootfs_disk.get('device_node'),
|
|
part_number)
|
|
part_device_path = '{}-part{}'.format(
|
|
controller_rootfs_disk.get('device_path'),
|
|
part_number)
|
|
|
|
LOG.info("Partition size: %s part device node: %s "
|
|
"part device path: %s" %
|
|
(part_size, part_device_node, part_device_path))
|
|
|
|
part_uuid = uuidutils.generate_uuid()
|
|
|
|
new_partition = Partition_Tuple(
|
|
uuid=part_uuid,
|
|
idisk_id=controller_rootfs_disk.get('id'),
|
|
idisk_uuid=controller_rootfs_disk.get('uuid'),
|
|
size_mib=part_size,
|
|
device_node=part_device_node,
|
|
device_path=part_device_path,
|
|
status=constants.PARTITION_CREATE_ON_UNLOCK_STATUS,
|
|
type_guid=constants.USER_PARTITION_PHYSICAL_VOLUME,
|
|
forihostid=controller_id,
|
|
foripvid=last_rootfs_pv.get('id'),
|
|
start_mib=None,
|
|
end_mib=None)
|
|
|
|
create_partition(cur, new_partition)
|
|
|
|
update_db_pv(cur, part_device_path, part_device_node,
|
|
part_uuid, part_device_node, last_rootfs_pv.get('id'))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|