metal/kickstart/files/kickstart.cfg

3366 lines
129 KiB
INI

#
# Copyright (c) 2022-2023 Wind River Systems, Inc.
# SPDX-License-Identifier: Apache-2.0
#
############################################################################
#
# StarlingX Debian Unified System Node Install Kickstart
#
############################################################################
#
# This is the unified kickstart for Debian installation of system nodes.
#
# The Linux Assembly Tool (LAT) performs a unified install for all system
# nodes and exposes boot loader environment variables to this kickstart.
#
# This kickstart must be called with the 'traits=' boot parameter.
# Valid traits are:
#
# controller ... the controller function
# storage ... the storage function
# worker ... the worker function
# lowlatency ... the low latency function
#
# Valid node personality trait groupings ... set configuration function
#
# traits=controller ... Controller
# traits=controller,worker ... All-in-one
# traits=controller,worker,lowlatency ... All-in-one Low Latency
# traits=storage ... Storage
# traits=worker ... Worker
# traits=worker,lowlatency ... Worker Low Latency
#
# Kickstart Stages
#
# Kickstart Early - Common Functions Script
# Pre Partition - Pre Disk Setup Common Script
# Partition - Partition Disks
# Mkfs - Format Partitions & LVM Volumes
# Post - Traits & Platform Config File update
# Post - Set Kernel Args
# Post - Interface Setup
# Post - Kickstart Finalize Install UUID
# Post - Upgrade Support
# Post Nochroot - Restage OSTree repo
# - Save Install Scripts and Logs
# Post - Log Filesystem Setup
# Post Nochroot - Save Install scripts and Logs
# Post Nochroot - Workarounds for enabling integration
# Post Nochroot - Set up filesystems access
# Post Nochroot - Set up package links per node type
#
###########################################################################
#
# The first kickstart script creates '/tmp/lat/functions' common functions
# file that can be loaded from any of the other hook sections.
#
###########################################################################
# Kickstart Early - Common Functions Script
%ks-early --interpreter=/bin/bash
# Define a hook to report error log if install failed
cat << EOF > /tmp/lat/report_error_log.sh
#!/bin/bash
_dev=\$(blkid --label fluxdata -o device)
if [ "\$_dev" != "" ] ; then
mkdir -p /t
mount -o rw,noatime \$_dev /t
echo "Save install-fail.log to partition fluxdata /var (\$_dev)"
sleep 2
cp /install.log /t/install-fail.log
umount /t
fi
EOF
chmod 755 /tmp/lat/report_error_log.sh
cat << EOF >> /tmp/lat/ks_functions.sh
[ "\${HOOK_LABEL}" = "" ] && HOOK_LABEL="unknown"
export LOG_DIR="var/log"
export LAT_DIR="tmp/lat"
export LOGFILE="/\${LAT_DIR}/kickstart.log"
############################################################################
# log utils
############################################################################
function log()
{
local dt="\$(date "+%Y-%m-%d %H:%M:%S.%3N")"
echo "\$dt kickstart \${HOOK_LABEL} info: \${prefix} \$1" >>\${LOGFILE}
}
function ilog()
{
[ -z "\${stdout}" ] && stdout=1
local dt="\$(date "+%Y-%m-%d %H:%M:%S.%3N")"
echo "\$dt kickstart \${HOOK_LABEL} info: \${prefix} \$1" >&\${stdout}
echo "\$dt kickstart \${HOOK_LABEL} info: \${prefix} \$1" >>\${LOGFILE}
}
function dlog()
{
if [ \${debug} -ne 0 ] ; then
[ -z "\$stdout" ] && stdout=1
local dt="\$(date "+%Y-%m-%d %H:%M:%S.%3N")"
echo "\$dt kickstart \${HOOK_LABEL} debug: \${prefix} \$1" >&\${stdout}
echo "\$dt kickstart \${HOOK_LABEL} debug: \${prefix} \$1" >>\${LOGFILE}
fi
}
function wlog()
{
[ -z "\$stdout" ] && stdout=1
local dt="\$(date "+%Y-%m-%d %H:%M:%S.%3N")"
echo "\$dt kickstart \${HOOK_LABEL} warn: \${prefix} \$1" >&\${stdout}
echo "\$dt kickstart \${HOOK_LABEL} warn: \${prefix} \$1" >>\${LOGFILE}
}
function elog()
{
[ -z "\$stdout" ] && stdout=1
local dt="\$(date "+%Y-%m-%d %H:%M:%S.%3N")"
echo "\$dt kickstart \${HOOK_LABEL} error: \${prefix} \$1" >&\${stdout}
echo "\$dt kickstart \${HOOK_LABEL} error: \${prefix} \$1" >>\${LOGFILE}
}
########################################################################
# Name : report_failure_with_msg
# Purpose : Report installation error, offer a console and
# reboot on exit.
# Parameters: \$1 is the failure message string
# Return : Does not return
########################################################################
function report_failure_with_msg()
{
local msg=\${1}
echo -e '\n\nInstallation failed.\n'
wlog "Installation Failed: ERROR: \${msg}"
echo "... dropping to shell ; exit to reboot ..."
sleep 1
bash
reboot -f
}
########################################################################
# Name : get_disk
# Parameters: \$1 - any disk path
# Returns : echo of the canonicalized version of the disk path
#
# Example : /dev/sda -> /dev/sda
# : /dev/nvme1n1 -> /dev/nvme1n1
# : /dev/disk/by-path/pci-0000:02:00.0-scsi-0:1:0:0 -> /dev/sda
# : /dev/disk/by-id/wwn-0x50014ee6ae58b07f -> /dev/sdc
# : /dev/disk/by-id/wwn-0x600508b1001c2a30 -> /dev/dm-0
#########################################################################
function get_disk()
{
echo "\$(cd /dev ; readlink -f \$1)"
}
#########################################################################
# Name : get_persistent_disk
# Parameters: \$1 - device name i.e. /dev/sda
# Returns : echo of device name by-path or by-id
# example: /dev/disk/by-path/pci-0000:03:00.0-scsi-0:2:0:0 or
# /dev/disk/by-id/wwn-0x50014ee6ae58b07f
#
# Notes: During kickstarts there are 2 links to a generic /dev/sd<X>.
# Example: pci-0000:00:1f.2-ata-1 and pci-0000:00:1f.2-ata-1.0.
# After reboot only the longer 'ata-1.0' exists.
# Reverse the parsing so we return the longer path.
#########################################################################
function get_persistent_disk()
{
local dev=\$(cd /dev ; readlink -f \$1)
case \$dev in
*"dm-"*)
for p in /dev/disk/by-id/wwn-*; do
if [ "\$(basename \$dev)" = "\$(basename \$(readlink -f \$p))" ]; then
echo "\$p"
return
fi
done
;;
*)
reverse_list=""
for p in /dev/disk/by-path/*; do
reverse_list="\${p} \${reverse_list}"
done
for p in \${reverse_list}; do
if [ "\$(basename \$dev)" = "\$(basename \$(readlink -f \$p))" ]; then
echo "\$p"
return
fi
done
;;
esac
}
#########################################################################
# Name : get_part_prefix
# Parameters: \$1 - device name i.e. /dev/sda, /dev/nvme0n1, /dev/dm-0
# Returns : echo of acceptable partition prefix
# example: /dev/sda
# /dev/nvme0n1p
# /dev/disk/by-id/wwn-0x50014ee6ae58b07f-part
#########################################################################
function get_part_prefix()
{
# ensure that we have a canonicalized device
local dev=\$(cd /dev ; readlink -f \$1)
case \$dev in
*"nvme"*)
echo "\${dev}p"
;;
*"dm-"*)
for p in /dev/disk/by-id/wwn-*; do
if [ "\$dev" = "\$(readlink -f \${p})" ]; then
echo "\${p}-part"
return
fi
done
;;
*)
echo "\${dev}"
;;
esac
}
#########################################################################
# Name : get_default_install_disk
# Purpose : Called when no install disk is provided. Will "discover" an
# install disk. Limited to "a" and "b" devices so that if the
# "a" device is a USB device it can be skipped.
# Returns : echo of the first disk name found ; base on coded priority
#
# Rules : Look for a HDD/SSD device, an NVMe device, and finally a
# multipath device
#########################################################################
function get_default_install_disk()
{
local disk
# Detect a HDD first and make sure it is not part of a mulitpath device
for blk_dev in vda vdb sda sdb dda ddb hda hdb; do
if [ -d /sys/block/\$blk_dev ]; then
disk=\$(ls -l /sys/block/\$blk_dev | grep -v usb | head -n1 | sed 's/^.*\([vsdh]d[a-z]\+\).*\$/\1/');
if [ -n "\$disk" ]; then
# Skip if this device is part of a multipath device
multipath -c /dev/\$disk > /dev/null && continue
echo "\$disk"
return
fi
fi
done
# An acceptable HDD/SSD has not been found, look for an NVMe disk
for blk_dev in nvme0n1 nvme1n1; do
if [ -d /sys/block/\$blk_dev ]; then
disk=\$(ls -l /sys/block/\$blk_dev | grep -v usb | head -n1 | sed 's/^.*\(nvme[01]n1\).*\$/\1/');
if [ -n "\$disk" ]; then
echo "\$disk"
return
fi
fi
done
# An acceptable NVMe disk has not been found, look for a multipath disk
for mpath_dev in mpatha mpathb; do
if [ -e /dev/mapper/\$mpath_dev ]; then
echo "/dev/mapper/\$mpath_dev"
return
fi
done
}
#########################################################################
# Name : exec_retry
# Purpose : Retry operations up to a caller specified ...
# Parameters: $1 - retries - up to number of retries before giving up
# $2 - time in seconds between each retry
# $3 - the command string to execute
# Returns : exit code from last command operation
#########################################################################
function exec_retry()
{
local retries=\${1}
local interval=\${2}
local command=\${3}
# local variables
retry_count=1
local ret_code=0
local ret_stdout=""
command="\${command}" # 2>&\${stdout}"
while [ \${retry_count} -le \${retries} ]; do
# dlog "Running command: '\${command}'."
ret_stdout=\$(eval \${command})
ret_code=\${?}
[ \${ret_code} -eq 0 ] && break
wlog "Error running command '\${command}'. Try \${retry_count} of \${retries} retry in \${interval}s."
wlog "ret_code: \${ret_code}, stdout: '\${ret_stdout}'."
sleep \${interval}
retry_count=\$((retry_count+1))
done
echo "\${ret_stdout}"
return \${ret_code}
}
#########################################################################
# Name : exec_no_fds
# Purpose : Execute command (with retries) after closing fds
# Parameters: $1 - List of volume file descriptors
# $2 - the command string to execute
# $3 - up to number of retries before giving up
# $4 - time in seconds between each retry
# Returns : exit code from last command operation
#########################################################################
function exec_no_fds()
{
# Close open FDs when executing commands that complain about leaked FDs.
local fds=\${1}
local cmd=\${2}
local retries=\${3}
local interval=\${4}
local ret_code=0
local ret_stdout=""
for fd in \${fds}
do
local cmd="\${cmd} \$fd>&-"
done
if [ -z "\${retries}" ]; then
#wlog "Running command: '\${cmd}'."
eval "\${cmd}"
else
ret_stdout=\$(exec_retry "\${retries}" "\${interval}" "\${cmd}")
ret_code=\${?}
echo "\${ret_stdout}"
return \${ret_code}
fi
}
#########################################################################
# Name : is_system_node_install
# Returns : true : 0 if 'pxecontroller' is in $insturl boot arg
# false: 1
#########################################################################
function is_system_node_install()
{
if [[ "\${insturl}" == *"pxecontroller"* ]] ; then
return 0
else
return 1
fi
}
#########################################################################
# Name : is_usb_install
# Returns : true :0
# false:1
#########################################################################
function is_usb_install()
{
pxeurl=\$(echo \${insturl} | sed -e s/ostree_repo//)
if [ "\${pxeurl}" = "file://NOT_SET" ] ; then
return 0
else
return 1
fi
}
#########################################################################
# Name : check_prestage
# Returns : true :0
# false:1
#########################################################################
function check_prestage()
{
set -- `cat /proc/cmdline`
for value in "\$@"; do
if [ "\${value}" = "prestage" ]; then
touch /tmp/lat/.prestage
return 0
fi
done
return 1
}
#########################################################################
# Name : is_prestage
# Returns : true :0
# false:1
#########################################################################
function is_prestage()
{
if [ -e /tmp/lat/.prestage ] ; then
return 0
else
return 1
fi
}
#########################################################################
# Name : update_platform_conf
# Purpose : Update the platform.conf file with logging
#########################################################################
PLATFORM_CONF="/etc/platform/platform.conf"
function update_platform_conf()
{
ilog "update \${IMAGE_ROOTFS}\${PLATFORM_CONF} : \${1}"
echo "\${1}" >> \${IMAGE_ROOTFS}\${PLATFORM_CONF}
}
#########################################################################
# Name : get_iface_from_ethname
# Purpose : Translate eth# interface to the alternate predicitive
# interface name'altname'.
# Parameter: eth# name interface string to translate
# Return : echo's of altname interface string
#########################################################################
# TODO: Move to where its used if there is only one section caller
function get_iface_from_ethname()
{
iface=\${1}
# log the interface info for post issue debug
udevadm info --export --query=property --path=/sys/class/net/\${iface} >> \${LOGFILE}
# convert to predictive name: ONBOARD > SLOT > PATH
# https://wiki.debian.org/NetworkInterfaceNames
altname=\$(udevadm info --export --query=property --path=/sys/class/net/\${iface} | grep ID_NET_NAME_ONBOARD)
altname=\${altname#ID_NET_NAME_ONBOARD=}
if [ -z "\${altname}" ] ; then
# try searching for ID_NET_NAME_SLOT
log "... retrying to translate \${iface} to predictive name with ID_NET_NAME_SLOT filter label "
altname=\$(udevadm info --export --query=property --path=/sys/class/net/\${iface} | grep ID_NET_NAME_SLOT)
altname=\${altname#ID_NET_NAME_SLOT=}
fi
if [ -z "\${altname}" ] ; then
# try searching for ID_NET_NAME_PATH
log "... retrying to translate \${iface} to predictive name with ID_NET_NAME_PATH filter label "
altname=\$(udevadm info --export --query=property --path=/sys/class/net/\${iface} | grep ID_NET_NAME_PATH)
altname=\${altname#ID_NET_NAME_PATH=}
fi
# The altname is seen enveloped with tick's ; 'eno1'
# Handle with and without tick's just in case
if [ -z "\${altname}" ] ; then
log "Failed to translate \${iface} to predictive name"
elif [ "\${altname::1}" = "'" ] ; then
echo "\${altname:1:-1}"
else
echo "\${altname}"
fi
}
function display_volume_info ()
{
if [ \${debug} -ne 0 ] ; then
ilog "Volume Info:\${1}"
pvscan 2>/dev/null
pvscan 2>/dev/null >> \${LOGFILE}
lvscan 2>/dev/null
lvscan 2>/dev/null >> \${LOGFILE}
pvdisplay 2>/dev/null
pvdisplay 2>/dev/null >> \${LOGFILE}
lvdisplay 2>/dev/null
lvdisplay 2>/dev/null >> \${LOGFILE}
fi
}
display_mount_info()
{
if [ \${debug} -ne 0 ] ; then
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
lsblk -o name,mountpoint,label,size,uuid
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
fi
}
function log_lvm_conf ()
{
local msg=\${1}
local conf=\${2}
lvm_global_filter=\$(cat \${conf} | grep "global_filter =")
lvm_preferred_names=\$(cat \${conf} | grep "preferred_names =")
ilog "\${msg}: \${conf}: \${lvm_global_filter}"
ilog "\${msg}: \${conf}: \${lvm_preferred_names}"
}
function breakpoint()
{
echo "*** BREAKPOINT ***: \${1} ; type exit to continue"
bash
echo "continuing from breakpoint: \${1}"
}
function set_variable()
{
touch "/\${LAT_DIR}/\${1}"
}
function get_variable()
{
[ -e "/\${LAT_DIR}/\${1}" ] && return 1
return 0
}
function clr_variable()
{
rm -f "/\${LAT_DIR}/\${1}"
}
#########################################################################
# Name : get_aio_controller_provisioning_sizes
# Purpose : Provide partition, physical volume, and logical volume sizes
# Parameter: None
# Return : Nothing, but exports key values
#########################################################################
function get_aio_controller_provisioning_sizes()
{
gib=\$((1024*1024*1024))
# Partitions
export PART_SZ_EFI=300
export PART_SZ_BOOT=2048
export PART_SZ_ROOT=0
# Logical volumes
export LV_SZ_LOG=8000
export LV_SZ_ROOT=20480
export LV_SZ_SCRATCH=16000
export LV_SZ_VAR=20480
##
## NOTE: updates to partition sizes need to be also reflected in
## - config/.../sysinv/conductor/manager.py:create_controller_filesystems()
## - config/.../sysinv/common/constants.py
##
## NOTE: When adding partitions, we currently have a max of 4 primary partitions.
## If more than 4 partitions are required, we can use a max of 3 --asprimary,
## to allow 1 primary logical partition with extended partitions
##
## NOTE: Max default PV size must align with the default controllerfs sizes
##
##
## NOTE TO REVIEWERS:
## This section was talen from CentOS and needs to be updated for Debian.
##
##***********************************************************************
## Large disk install (for disks over 240GB)
## - DB size is doubled to allow for upgrades
##
## BACKUP_OVERHEAD = 5GiB
## DEFAULT_PLATFORM_STOR_SIZE = 10GiB
## DEFAULT_DATABASE_STOR_SIZE = 10GiB
## BACKUP = DEFAULT_DATABASE_STOR_SIZE +
## DEFAULT_PLATFORM_STOR_SIZE +
## BACKUP_OVERHEAD = 25GiB
## LV_SZ_LOG = 8GiB
## LV_SZ_ROOT = 20 GiB
## LV_SZ_SCRATCH = 16GiB
## LV_SZ_VAR = 20 GiB
## RABBIT_LV = 2GiB
## DEFAULT_EXTENSION_STOR_SIZE = 1GiB
## KUBERNETES_DOCKER_STOR_SIZE = 30GiB
## DOCKER_DISTRIBUTION_STOR_SIZE = 16GiB
## ETCD_STOR_SIZE = 5GiB
## CEPH_MON_SIZE = 20GiB
## KUBELET_STOR_SIZE = 10GiB
## DC_VAULT_SIZE = 15GiB
## RESERVED_PE = 16MiB (based on pesize=32768)
##
## MINIMUM_PLATFORM_PV_SIZE = (10 + 2*10 + 25 + 8 + 20 + 16 + 20 + 2 + 1 + 30 + 16 + 5 + 20 + 10 + 15)GiB + 16MiB/1024 = 218.02GiB
##
##***********************************************************************
## Small disk install - (for disks below 240GB)
## - DB size is doubled to allow for upgrades
##
## DEFAULT_PLATFORM_STOR_SIZE = 10GiB
## DEFAULT_SMALL_DATABASE_STOR_SIZE = 5GiB
## DEFAULT_SMALL_BACKUP_STOR_SIZE = 20GiB
##
## LV_SZ_LOG = 8GiB
## LV_SZ_SCRATCH = 16GiB
## RABBIT_LV = 2GiB
## DEFAULT_EXTENSION_STOR_SIZE = 1GiB
## KUBERNETES_DOCKER_STOR_SIZE = 30GiB
## DOCKER_DISTRIBUTION_STOR_SIZE = 16GiB
## ETCD_STOR_SIZE = 5GiB
## CEPH_MON_SIZE = 20GiB
## KUBELET_STOR_SIZE = 10GiB
## DC_VAULT_SIZE = 15GiB
## RESERVED_PE = 16MiB (based on pesize=32768)
##
## MINIMUM_PLATFORM_PV_SIZE = (10 + 2*5 + 20 + 8 + 16 + 2 + 1 + 30 + 16 + 5 + 20 + 10 + 15)GiB + 16MiB/1024 = 163.02GiB
##
##***********************************************************************
## Tiny disk install - (for disks below 154GB)
##
## NOTE: Tiny disk setup is mainly for StarlingX running in QEMU/KVM VM.
##
## DEFAULT_TINY_PLATFORM_STOR_SIZE = 1GiB
## DEFAULT_TINY_DATABASE_STOR_SIZE = 1GiB
## DEFAULT_TINY_BACKUP_STOR_SIZE = 1GiB
##
## LV_SZ_LOG = 3GiB
## LV_SZ_SCRATCH = 2GiB
## RABBIT_LV = 2GiB
## DEFAULT_EXTENSION_STOR_SIZE = 1GiB
## TINY_KUBERNETES_DOCKER_STOR_SIZE = 20GiB
## TINY_DOCKER_DISTRIBUTION_STOR_SIZE = 8GiB
## TINY_ETCD_STOR_SIZE = 1GiB
## TINY_KUBELET_STOR_SIZE = 2GiB
##
## MINIMUM_PLATFORM_PV_SIZE = (1 + 2*1 + 1 + 3 + 2 + 2 + 1 + 20 + 8 + 1 + 2)GiB = 43GiB
##
## MINIMUM_TINY_DISK_SIZE = MINIMUM_PLATFORM_PV_SIZE + PART_SZ_ROOT + PART_SZ_EFI + PART_SZ_BOOT + FLUXDATA + BACKUP_SIZE
## = 43 + 20 + 0.03 + 0.5 + 20 + 1 = 85GiB
# TODO: create a log representing 'free space" on self expand partition.
# TODO: Do the math for this new environment
# The default disk size thresholds must align with the ones in
# config/.../sysinv/common/constants.py
# which are DEFAULT_SMALL_DISK_SIZE
# MINIMUM_SMALL_DISK_SIZE
default_small_disk_size=240
minimum_small_disk_size=196
sz=\$(blockdev --getsize64 \${INSTDEV})
ilog "Install disk \${INSTDEV} has size:\${sz}B, \$((\${sz}/\$gib))GiB"
# Round MINIMUM_PLATFORM_PV_SIZE to the closest upper value that can be divided by 1024.
if [ \${sz} -gt \$((\${default_small_disk_size}*\${gib})) ] ; then
ilog "Large disk: MINIMUM_PLATFORM_PV_SIZE=219GiB*1024=224256 MiB"
export BACKUP_DEFAULT_PERSISTENT_SIZE=30000
elif [ \${sz} -ge \$((\${minimum_small_disk_size}*\${gib})) ] ; then
ilog "Small disk: MINIMUM_PLATFORM_PV_SIZE=164GiB*1024=167936 MiB"
export BACKUP_DEFAULT_PERSISTENT_SIZE=30000
else
ilog "Tiny disk: MINIMUM_PLATFORM_PV_SIZE=43GiB*1024=44032 MiB"
# Using a disk with a size under 85GiB will fail.
export LV_SZ_LOG=3000
export LV_SZ_SCRATCH=2000
export BACKUP_DEFAULT_PERSISTENT_SIZE=1000
fi
}
#########################################################################
# Name : get_std_controller_provisioning_sizes
# Purpose : Provide partition, physical volume, and logical volume sizes
# Parameter: None
# Return : Nothing, but exports key values
#########################################################################
function get_std_controller_provisioning_sizes()
{
## NOTE: updates to partition sizes need to be also reflected in
## _controller_filesystem_limits() in sysinv/api/controllers/v1/istorconfig.py
# Partitions
export PART_SZ_EFI=300
export PART_SZ_BOOT=2048
export PART_SZ_ROOT=0
export BACKUP_DEFAULT_PERSISTENT_SIZE=30000
# Logical volumes
export LV_SZ_LOG=8000
export LV_SZ_ROOT=20480
export LV_SZ_SCRATCH=16000
export LV_SZ_VAR=20480
}
#########################################################################
# Name : get_worker_provisioning_sizes
# Purpose : Provide partition, physical volume, and logical volume sizes
# Parameter: None
# Return : Nothing, but exports key values
#########################################################################
function get_worker_provisioning_sizes()
{
gib=\$((1024*1024*1024))
# Partitions
export PART_SZ_EFI=300
export PART_SZ_BOOT=2048
export PART_SZ_ROOT=0
# Logical volumes
export LV_SZ_LOG=4096
export LV_SZ_SCRATCH=4096
# Physical volumes
## LV_SZ_LOG = 4096
## LV_SZ_SCRATCH = 4096
## LV_SZ_VAR=20480
##
## DOCKER = 30720
## CEPH_MON = 20480
## KUBELET_VOL_SIZE = 10240
## RESERVED_PE = 16 (based on pesize=32768)
##
## CGTS_PV_SIZE = 4096 + 4096 + 30720 + 20480 + 10240 + 16 = 69648
##
## Round CGTS_PV_SIZE to the closest upper value that can be divided by 1024.
## 69648/1024=68.01. CGTS_PV_SIZE=69*1024=70656.
sz=\$(blockdev --getsize64 \${INSTDEV})
if [ \$sz -le \$((120*\$gib)) ] ; then
export LV_SZ_ROOT=10240
export LV_SZ_VAR=10240
else
export LV_SZ_ROOT=20480
export LV_SZ_VAR=20480
fi
ilog "Install disk \${INSTDEV} has size:\${sz}B, \$((\${sz}/\$gib))GiB"
}
#########################################################################
# Name : get_storage_provisioning_sizes
# Purpose : Provide partition, physical volume, and logical volume sizes
# Parameter: None
# Return : Nothing, but exports key values
#########################################################################
function get_storage_provisioning_sizes()
{
gib=\$((1024*1024*1024))
# Partitions
export PART_SZ_EFI=300
export PART_SZ_BOOT=2048
export PART_SZ_ROOT=0
# Logical volumes
sz=\$(blockdev --getsize64 \${INSTDEV})
if [ \$sz -le \$((120*\$gib)) ] ; then
export LV_SZ_LOG=4000
export LV_SZ_ROOT=10240
export LV_SZ_SCRATCH=4000
export LV_SZ_VAR=10240
else
export LV_SZ_LOG=8000
export LV_SZ_ROOT=20480
export LV_SZ_SCRATCH=8000
export LV_SZ_VAR=20480
fi
ilog "Install disk \${INSTDEV} has size:\${sz}B, \$((\${sz}/\$gib))GiB"
}
#########################################################################
# Name : parse_miniboot_network_params
# Purpose : Setup IP addressing for two cases:
# 1) initial boot and 2) persistent across reboot
# Parameter: operation: one of 'initial' or 'persistent'
# Return : Nothing
#########################################################################
function parse_miniboot_network_params()
{
# Unused: only here for simpler diff with miniboot
elog "Unused: parse_miniboot_network_params"
}
##########################################################################
# Global Kickstart Constants #
##########################################################################
#
# NOTE: exported Variables from other segments are NOT visible from functions
#
# Log the server firmware type
if [ -d /sys/firmware/efi ] ; then
ilog "UEFI Firmware execution"
USE_UEFI_PARTITIONS=1
else
ilog "BIOS Firmware execution"
USE_UEFI_PARTITIONS=0
fi
if [ "\${controller}" = true ] ; then
# Legacy locations of the backup partition
BACKUP_PART_UEFI=1
BACKUP_PART_BIOS=2
# Set the expected locations of the backup partition
if [ "\$USE_UEFI_PARTITIONS" = 0 ] ; then
BACKUP_PART_NO=\${BACKUP_PART_BIOS}
else
BACKUP_PART_NO=\${BACKUP_PART_UEFI}
fi
BACKUP_PART_LABEL="platform_backup"
# Note that the BA5EBA11-0000-1111-2222- is the prefix used by STX and it's
# defined in sysinv constants.py. Since the 000000000001 suffix is used by
# custom stx LVM partitions, the next suffix is used for the persistent backup
# partition (000000000002)
BACKUP_PART_GUID="BA5EBA11-0000-1111-2222-000000000002"
fi
# Node Personality Trait
TRAIT__CONTROLLER="controller"
TRAIT__STORAGE="storage"
TRAIT__WORKER="worker"
TRAIT__LOWLATENCY="lowlatency"
# System Types
SYSTEM_TYPE__AIO="All-in-one"
SYSTEM_TYPE__STANDARD="Standard"
# Node Subfunctions
SUBFUNCTION__CONTROLLER="\${TRAIT__CONTROLLER}"
SUBFUNCTION__STORAGE="\${TRAIT__STORAGE}"
SUBFUNCTION__WORKER="\${TRAIT__WORKER}"
SUBFUNCTION__AIO="\${TRAIT__CONTROLLER},\${TRAIT__WORKER}"
VOLUME_GROUPS="cgts-vg"
EOF
###############################
# END of Common Functions Block
###############################
chmod 755 /tmp/lat/ks_functions.sh
HOOK_LABEL="ks-early"
. /tmp/lat/ks_functions.sh
##########################################################################
# Global Kickstart variables #
##########################################################################
export debug=0
export prefix=""
# Assume there is no Platform Backup (persistent) Partition
export BACKUP_PART_FOUND=0
export STOR_DEV_FDS=""
export PROC_SELF_FDS="$(ls -1 /proc/$$/fd | egrep -v "^(0|1|2|255)$" | xargs)"
for fd in ${PROC_SELF_FDS}; do
export realpath=$(readlink -f /proc/$$/fd/"${fd}")
if [ -e "${realpath}" ]; then
STOR_DEV_FDS="${STOR_DEV_FDS} ${fd}"
fi
done
##########################################################################
# Local Kickstart variables #
##########################################################################
BACKUP_PART_FIRST=0
BACKUP_PART_END=0
BACKUP_PART_SIZE=0
BACKUP_PART_FLAGS=0
BACKUP_PART_NAME=""
##########################################################################
ilog "*****************************************************"
ilog "*** Pre Partition - Volume Remove & Wipe Disk ***"
ilog "*****************************************************"
if [ -z "${traits}" ] ; then
report_failure_with_msg "No install traits specified ; need boot arg traits=<controller|worker|storage|lowlatency>"
fi
ilog "Waiting for disks to be available"
udevadm settle --timeout=300 || report_failure_with_msg "udevadm settle failed"
ilog "Disks became available"
export controller=false
export storage=false
export worker=false
export lowlatency=false
export aio=false
for trait in ${traits//,/ }; do
# dlog "trait:${trait}"
case ${trait} in
"controller") controller=true ;;
"storage") storage=true ;;
"worker") worker=true ;;
"lowlatency") lowlatency=true ;;
*) wlog "unknown trait '${trait}'" ;;
esac
done
# Force enable 'lowlatency' trait if the realtime kernel is detected ; PREEMPT_RT
uname=$(uname -a)
if [[ "${uname}" == *"PREEMPT_RT"* ]] ; then
if [ "${lowlatency}" = false ] ; then
wlog "forcing lowlatency trait after discovering the RT kernel"
lowlatency=true
fi
fi
# Handle trait conbination errors
#
# Handle no valid nodetypes specified
if [ "${controller}" = false -a "${storage}" = false -a "${worker}" = false ] ; then
report_failure_with_msg "No valid install traits specified ; ${traits} ; need boot arg traits=<controller|worker|storage>"
# Storage and controller don't go together
elif [ "${storage}" = true -a "${controller}" = true ] ; then
report_failure_with_msg "Cannot combine storage and controller traits"
# Storage and lowlatency don't go together
elif [ "${storage}" = true -a "${lowlatency}" = true ] ; then
report_failure_with_msg "Cannot combine storage and lowlatency traits"
# Storage and worker don't go together
elif [ "${storage}" = true -a "${worker}" = true ] ; then
report_failure_with_msg "Cannot combine storage and worker traits"
else
ilog "Install traits: $traits"
fi
# setup the install type for the log prefix
if [ "${controller}" = true -a "${worker}" = true ] ; then
aio=true
prefix="${SYSTEM_TYPE__AIO}"
elif [ "${controller}" = true ] ; then
prefix="${TRAIT__CONTROLLER}"
elif [ "${worker}" = true ] ; then
prefix="${TRAIT__WORKER}"
elif [ "${storage}" = true ] ; then
prefix="${TRAIT__STORAGE}"
fi
if [ "${lowlatency}" = true ] ; then
prefix="${prefix}-${TRAIT__LOWLATENCY}"
fi
grep -q 'debug_kickstart' /proc/cmdline
if [ $? -eq 0 ]; then
debug=1
fi
# First, parse /proc/cmdline to find the boot args
set -- `cat /proc/cmdline`
ilog "/proc/cmdline:$*"
# for I in $*; do case "$I" in *=*) eval $I 2>/dev/null;; esac; done
for arg in $*; do
case "$arg" in
*=*)
eval $arg 2>/dev/null
log "arg : $arg"
;;
esac
done
# Note: This is equivalent to pre_disk_setup_common.cfg
# Name : check_execs
# Purpose: Confirm all the executables required by the kickstart are present
# Returns: 1 of one or more executable are missing
REQUIRED_EXECS="bc blkid dd lvcreate mkfs.ext4 partprobe pvremove pvs sgdisk vgcreate wipefs"
function check_execs()
{
missing_exec=0
for x in ${REQUIRED_EXECS} ; do
which ${x} > /dev/null 2>&1
if [ ${?} -ne 0 ] ; then
elog "dependency check failed ; required '${x}' exec is missing"
missing_exec=1
fi
done
return ${missing_exec}
}
# Log Traits
[ "${controller}" = true ] && ilog "Controller Function"
[ "${storage}" = true ] && ilog "Storage Function"
[ "${worker}" = true ] && ilog "Worker Function"
[ "${lowlatency}" = true ] && ilog "Low Latency Function"
# Log System Type
if [ ${aio} = true ] ; then
ilog "system"
else
ilog "${SYSTEM_TYPE__STANDARD} system"
fi
# Verify that all the required executables are presenty
check_execs
[ $? -ne 0 ] && report_failure_with_msg "Required executables are missing"
####################################################
# pre_common_head (obsolete with lat)
####################################################
# TODO: The installer does not have 'timezone'
# Does LAT handle this ?
wlog "timezone not set ; 'timezone --nontp --utc UTC'"
true
%end
####################################################
# prestaging: local installation
####################################################
#
# This code is only executed if "prestage" is set in the command line
# to the kernel.
%ks-early --interpreter=/bin/bash
HOOK_LABEL="ks-early"
. /tmp/lat/ks_functions.sh
# First, parse /proc/cmdline to find the boot args
# Check for prestaging
#
if check_prestage -eq 0 ; then
ilog "Prestaging for Local Install"
# The iso label is instboot. To mount the iso, we use
# /dev/disk/by-label/instboot.
ISO_DEV=/dev/disk/by-label/instboot
ISODIR=/run/install/repo
mkdir -p ${ISODIR}
# Mount the isofile
mount "${ISO_DEV}" "${ISODIR}"
rc=$?
if [ "${rc}" -ne 0 ]; then
report_failure_with_msg "Unable to mount ${ISO_DEV} Error rc=${rc}"
fi
local_repo_check_fail=
# Calculate local checksum and compare
checksum_file=${ISODIR}/.ostree_repo_checksum
if [ -f "${checksum_file}" ]; then
checksum_from_file=$(cat "${checksum_file}")
ilog "Verifying checksum for prestaged ${ISODIR}/ostree_repo"
pushd "${ISODIR}" > /dev/null
checksum=$(find ostree_repo -type f -exec md5sum {} + | LC_ALL=C sort | md5sum | awk '{ print $1; }')
popd > /dev/null
if [ "${checksum}" = "${checksum_from_file}" ]; then
ilog "Verified ostree checksum: ${checksum}"
else
elog "ostree checksum failed on ${ISODIR}/ostree_repo"
elog "Calculated checksum: ${checksum}"
elog "File checksum: ${checksum_from_file}"
local_repo_check_fail=true
fi
else
# No prestage checksum file is available. Use ostree fsck instead.
# The only problem with this is the length of time required for fsck to complete.
wlog "No ostree checksum file at ${checksum_file}. Performing ostree fsck instead."
if ! ostree --repo="${ISODIR}/ostree_repo" fsck; then
elog "ostree fsck failed on prestaged ${ISODIR}/ostree_repo: reverting to remote pull"
local_repo_check_fail=true
fi
fi
if [ -n "${local_repo_check_fail}" ]; then
report_failure_with_msg "ostree integrity check failed on ISO ${ISODIR}/ostree_repo"
fi
if [ -e "${ISODIR}/ks-setup.cfg" ]; then
source "${ISODIR}/ks-setup.cfg"
fi
umount ${ISODIR}
# override the INSTDEV based on the information from ks-setup.cfg
export INSTDEV="${rootfs_device}"
export instdev="${rootfs_device}"
ilog "rootfs device is ${INSTDEV}"
# Check if force_install is not set. If it is set, then install anyway.
set -- `cat /proc/cmdline`
for value in "$@"; do case "$value" in force_install) force_install=${value};; esac; done
if [ -z "${force_install}" ]; then
if [ -z "${rootfs_device}" ]; then
rootfs_device=$(get_default_install_disk)
fi
desired_rootfs_device=$rootfs_device
persistent_rootfs_device=$(get_persistent_disk ${desired_rootfs_device})
if [ -z "${persistent_rootfs_device}" ]; then
report_failure_with_msg "Device not found: ${desired_rootfs_device}"
fi
rootfs_device=$(get_disk ${persistent_rootfs_device})
ilog "Desired root disk $desired_rootfs_device evaluates to: $persistent_rootfs_device->$rootfs_device."
part_numbers=( $(parted -s ${rootfs_device} print | awk '$1 == "Number" {i=1; next}; i {print $1}') )
# Get the correct rootfs prefix
rootfs_part_prefix=$(get_part_prefix ${rootfs_device})
# temporary mount directory
temp_mount=/mnt/temp_mount
mkdir -p ${temp_mount}
ilog "Searching for existing installation..."
# Build up device_list to search for existing installation.
# We will look for the install_uuid file on each of the devices in the list.
# First, if volume groups have been enabled, we can mount /dev/cgts-vg/var-lv
device_list=("/dev/cgts-vg/var-lv")
# Now add the rest of the rootfs partitions to device_list
for part in "${part_numbers[@]}"; do
device_list+=("${rootfs_part_prefix}${part}")
done
ilog "Checking device_list: ${device_list[*]}"
for device in "${device_list[@]}"; do
# mount this part at a temporary mount point
ilog "Checking device: ${device}"
mount "${device}" "${temp_mount}"
rc=$?
if [ "${rc}" -ne 0 ]; then
wlog "Unable to mount ${device}, rc=${rc}"
continue
fi
# Check for the presence of install_uuid in one of the partitions on the device_list
if [ -e "${temp_mount}/www/pages/feed/rel-xxxPLATFORM_RELEASExxx/install_uuid" ]; then
wlog "Found valid installation on ${device}"
umount ${temp_mount}
# Do not modify the system in any way
report_failure_with_msg "Prestage rejected. Existing installation detected. Please eject the media before rebooting."
fi
umount ${temp_mount}
done
rm -rf ${temp_mount}
ilog "Installing Prestaged content. No existing installation found."
else
# force install in spite of existing installation
wlog "Prestage: Force Installing Prestaged content. All existing installations will be lost."
fi
# If the size of the Platform Backup partition is greater than 30GB, parted will fail when
# it tries to reconfigure the partition in a later step. We delete the partition now so that
# parted succeeds in the later step.
partition_id=$(parted -s ${rootfs_device} print | awk '/platform_backup/ { print $1; }')
ilog "Partition id = ${partition_id}"
# If the partition id is not empty or zero, then the partition actually exists.
# Delete the partition.
if [[ "${partition_id}" -ne '' && "${partition_id}" -ne "0" ]]; then
wlog "Deleting platform backup at partition ${partition_id} on ${rootfs_device}"
# Delete the platform backup partition
parted -s ${rootfs_device} rm ${partition_id}
rc=$?
if [ "${rc}" -ne 0 ]; then
report_failure_with_msg "Unable to delete platform backup at partition ${partition_id} on ${rootfs_device}: [exit code ${rc}]"
else
ilog "Deleted partition ${partition_id} on ${rootfs_device}"
fi
fi
fi
true
%end
# Pre Partition - Pre Disk Setup Common Script
%pre-part --interpreter=/bin/bash
HOOK_LABEL="pre-part"
. /tmp/lat/ks_functions.sh
#####################################################
# From pre_net_common.cfg for system node installs
#####################################################
if is_system_node_install -eq 0 ; then
# Setup ntp.conf and sync time
cat <<EOF >/etc/ntp_kickstart.conf
server pxecontroller
EOF
if [ -e /usr/sbin/ntpd ] ; then
/usr/sbin/ntpd -g -q -n -c /etc/ntp_kickstart.conf
rc=$?
if [ ${rc} -eq 0 ] ; then
if [ -e /sbin/hwclock ] ; then
/sbin/hwclock --systohc --utc
if [ $? -ne 0 ] ; then
wlog "failed hwclock command ; /sbin/hwclock --systohc --utc"
else
ilog "ntpd and hwclock set ok"
fi
else
wlog "lat initrd is missing /sbin/hwclock"
fi
else
wlog "ntpd setup failed rc:$rc ; /usr/sbin/ntpd -g -q -n -c /etc/ntp_kickstart.conf"
fi
else
wlog "lat initrd is missing /usr/sbin/ntpd"
fi
fi
#####################################################
# From pre_disk_setup_common.cfg
#####################################################
if [ -n "${INSTDEV}" ] ; then
persistent_instdev=$(get_persistent_disk "${INSTDEV}")
if [ -z ${persistent_instdev} ] ; then
report_failure_with_msg "invalid install device ${INSTDEV}"
else
ilog "Install device: ${INSTDEV} : ${persistent_instdev}"
fi
fi
# Get all block devices of type disk in the system.
# This includes solid state devices.
# Note: /dev/* are managed by kernel tmpdevfs while links in
# /dev/disk/by-path/ are managed by udev which updates them
# asynchronously so avoid using them while performing partition
# operations.
ilog "Detected storage devices:"
case ${persistent_instdev} in
*"by-id"*)
disk_regex='/dev/disk/by-id/wwn-*'
;;
*)
disk_regex='/dev/disk/by-path/*'
;;
esac
STOR_DEVS=""
for f in ${disk_regex} ; do
dev=$(readlink -f $f)
# dlog "found device ${f}"
exec_retry 2 0.5 "lsblk --nodeps --pairs $dev" | grep -q -e 'TYPE="disk"' -e 'TYPE="mpath"'
if [ $? -eq 0 ] ; then
# Filter out ISO disk from storage devices
check_valid_dev $dev || continue
STOR_DEVS="$STOR_DEVS $dev"
ilog "Adding ${f} -> ${dev} to managed device list"
fi
done
# Filter STOR_DEVS variable for any duplicates as on some systems udev
# creates multiple links to the same device. This causes issues due to
# attempting to acquire a flock on the same device multiple times.
STOR_DEVS=$(echo "$STOR_DEVS" | xargs -n 1 | sort -u | xargs)
ilog "Unique storage devices: $STOR_DEVS"
if [ -z "$STOR_DEVS" ] ; then
report_failure_with_msg "No storage devices available."
fi
# Lock all devices so that udev doesn't trigger a kernel partition table
# rescan that removes and recreates all /dev nodes for partitions on those
# devices. Since udev events are asynchronous this could lead to a case
# where /dev/ links for existing partitions are briefly missing.
# Missing /dev links leads to command execution failures.
for dev in $STOR_DEVS ; do
exec {fd}>$dev || report_failure_with_msg "Error creating file descriptor for $dev."
flock -n "$fd" || report_failure_with_msg "Can't get a lock on fd $fd of device $dev."
STOR_DEV_FDS="$STOR_DEV_FDS $fd"
ilog "Locked ${dev} fd:${fd}"
done
# Log info about system state at beginning of partitioning operation
for dev in $STOR_DEVS ; do
ilog "Initial partition table for $dev is:"
# log "Initial partition table for $dev is:"
parted -s $dev unit mib print
# parted -s $dev unit mib print >> ${LOGFILE}
done
display_volume_info "before"
display_mount_info
# Consider removing since LAT already handles this failure mode
# Ensure specified device is not a USB drive
udevadm info --query=property --name="${INSTDEV}" | grep -q '^ID_BUS=usb'
if [ $? -eq 0 ] ; then
report_failure_with_msg "Specified installation (${INSTDEV}) device is a USB drive."
fi
# Log the disk setup
ilog "Volume Groups : ${VOLUME_GROUPS} ; $STOR_DEV_FDS"
# update lvm.conf to prevent udev delays for locked devices
sed -i "s#obtain_device_list_from_udev = 1#obtain_device_list_from_udev = 0#" /etc/lvm/lvm.conf
# Deactivate existing volume groups to avoid Anaconda issues with pre-existing groups
vgs=( $(exec_no_fds "$STOR_DEV_FDS" "vgdisplay -C --noheadings -o vg_uuid 2>/dev/null") )
if [ ${#vgs[@]} -eq 0 ] ; then
ilog "No volume groups found"
else
for vg in ${vgs[@]} ; do
lvs=( $(exec_no_fds "$STOR_DEV_FDS" "lvs --select vg_uuid=${vg} --noheadings -o lv_name 2>/dev/null") )
vg_name=$(exec_no_fds "$STOR_DEV_FDS" "vgdisplay -C --noheadings --select vg_uuid=${vg} -o vg_name 2>/dev/null" | xargs)
ilog "Wipe any previous signatures from ${vg_name} volume group"
for lv in ${lvs[@]} ; do
ilog "Wipe any previous signatures from ${lv} logical volume"
exec_no_fds "$STOR_DEV_FDS" "wipefs -a /dev/${vg_name}/${lv} 2>/dev/null" 5 0.5 || wlog "Failed to wipe signatures from ${lv}"
done
ilog "Disable volume group ${vg}"
exec_no_fds "$STOR_DEV_FDS" "vgchange -an --select vg_uuid=${vg} 2>/dev/null" 5 0.5
[ $? -ne 0 ] && report_failure_with_msg "Failed to disable ${vg}."
done
for vg in ${vgs[@]} ; do
vg_name=$(exec_no_fds "$STOR_DEV_FDS" "vgdisplay -C --noheadings --select vg_uuid=${vg} -o vg_name 2>/dev/null" | xargs)
pvs=( $(exec_no_fds "$STOR_DEV_FDS" "pvs --select vg_uuid=${vg} --noheadings -o pv_name 2>/dev/null" | grep -v unknown) )
if [ ${#pvs[@]} -ne 0 ] ; then
ilog "Remove logical volumes from ${vg_name} (${vg})"
exec_no_fds "$STOR_DEV_FDS" "lvremove --force --select vg_uuid=${vg} 2>/dev/null" 5 0.5 || wlog "WARNING: Failed to remove lvs on ${vg_name} (${vg})."
for pv in ${pvs[@]} ; do
ilog "Remove physical volume ${pv} from ${vg_name} (${vg})"
exec_no_fds "$STOR_DEV_FDS" "pvremove --force --force --yes ${pv} 2>/dev/null" 5 0.5
[ $? -ne 0 ] && report_failure_with_msg "Failed to remove ${pv}."
done
fi
ilog "Force remove volume group ${vg_name} (${vg})"
exec_no_fds "$STOR_DEV_FDS" "vgremove --force --select vg_uuid=${vg} 2>/dev/null" 5 0.5
[ $? -ne 0 ] && report_failure_with_msg "Failed to remove ${vg_name} (${vg})."
done
fi
display_volume_info "after"
display_mount_info
ONLYUSE_HDD=""
part_type_guid_str="Partition GUID code"
part_type_name_str="Partition name"
part_type_size_str="Partition size"
part_type_first_str="First sector"
part_type_end_str="Last sector"
part_type_flags_str="Attribute flags"
# The /v1/upgrade/${hostname}/in_upgrade endpoint accepts any textual data
# as hostname and returns system-wide upgrade state
hostname="hostname"
if [ "$(curl -sf http://pxecontroller:6385/v1/upgrade/${hostname}/in_upgrade 2>/dev/null)" = "true" ] ; then
# In an upgrade, only wipe the disk with the rootfs and boot partition
wlog "In upgrade, wiping only ${INSTDEV}"
WIPE_HDD=${INSTDEV}
ONLYUSE_HDD="$(basename ${INSTDEV})"
else
# Make a list of all the hard drives that are to be wiped.
# Never put the LAT install disk '${INSTDEV}' in that list.
WIPE_HDD=""
# Partition type OSD has a unique globally identifier
CEPH_OSD_GUID="4FBD7E29-9D25-41B8-AFD0-062C0CEFF05D"
CEPH_OSD_MPATH_GUID="4FBD7E29-8AE0-4982-BF9D-5A8D867AF560"
CEPH_JOURNAL_GUID="45B0969E-9B03-4F30-B4C6-B4B80CEFF106"
CEPH_JOURNAL_MPATH_GUID="45B0969E-8AE0-4982-BF9D-5A8D867AF560"
# Check if we wipe OSDs
if [ "$(curl -sf http://pxecontroller:6385/v1/ihosts/wipe_osds 2>/dev/null)" = "true" ] ; then
ilog "Wipe OSD data"
WIPE_CEPH_OSDS="true"
else
ilog "Skip Ceph OSD data wipe."
WIPE_CEPH_OSDS="false"
fi
for dev in $STOR_DEVS ; do
# TODO: Allowing the install dev 'in' results in a failure mode where
# every second install fails with the following error string
# and unrecoverable mount failure.
#
# Logs:
#
# Warning: The kernel is still using the old partition table.
# The new table will be used at the next reboot or after you
# run partprobe(8) or kpartx(8)
# and then
#
# Failure:
#
# mount: /sysroot: can't find LABEL=otaroot.
#
# Action: Find correct place to put partprobe
#
# Avoid wiping the install root disk
# [ ${dev} == ${INSTDEV} ] && continue
# Avoid wiping USB drives
udevadm info --query=property --name=$dev |grep -q '^ID_BUS=usb' && continue
# Avoid wiping ceph osds if sysinv tells us so
if [ ${WIPE_CEPH_OSDS} == "false" ] ; then
wipe_dev="true"
exec_no_fds "$STOR_DEV_FDS" "pvs" | grep -q "$dev *ceph"
if [ $? -eq 0 ] ; then
wlog "skip rook provisoned disk $dev"
continue
fi
part_numbers=( `parted -s $dev print | awk '$1 == "Number" {i=1; next}; i {print $1}'` )
# Scanning the partitions looking for CEPH OSDs and
# skipping any disk found with such partitions
for part_number in "${part_numbers[@]}" ; do
sgdisk_part_info=$(sgdisk -i $part_number $dev)
part_type_guid=$(echo "$sgdisk_part_info" | grep "$part_type_guid_str" | awk '{print $4;}')
if [ "$part_type_guid" == $CEPH_OSD_GUID -o "$part_type_guid" == $CEPH_OSD_MPATH_GUID ]; then
wlog "OSD found on $dev, skipping wipe"
wipe_dev="false"
break
fi
dev_part_prefix=$(get_part_prefix "${dev}")
exec_no_fds "$STOR_DEV_FDS" "pvs" | grep -q -e "${dev_part_prefix}${part_number} *ceph" -e "${dev_part_prefix}p${part_number} *ceph"
if [ $? -eq 0 ]; then
wlog "Rook OSD found on $dev_part_prefix$part_number, skip wipe"
wipe_dev="false"
break
fi
done
if [ "$wipe_dev" == "false" ] ; then
continue
fi
fi
# Add device to the wipe list
devname=$(basename $dev)
if [ -e $dev -a "$ISO_DEV" != "../../$devname" -a "$USB_DEV" != "../../$devname" ] ; then
ilog "Adding ${dev} to list of disks to be wiped"
if [ -n "$WIPE_HDD" ] ; then
ilog "WIPE_HDD=$WIPE_HDD,$dev"
WIPE_HDD=$WIPE_HDD,$dev
else
ilog "WIPE_HDD=$dev"
WIPE_HDD=$dev
fi
fi
done
ilog "Not in upgrade"
fi
ilog "==========="
ilog "WIPE DISKs: ${WIPE_HDD}"
ilog "==========="
inst_dev=$(get_disk "${INSTDEV}")
for dev in ${WIPE_HDD//,/ } ; do
ilog "Wiping $dev"
# Clear previous GPT tables or LVM data on each disk.
#
# Rule: Exclude the persistent 'Platform backup' partition.
# Note: Delete the first few bytes at the start and end of the partition.
# This is required with GPT partitions because they save partition
# info at both the start and the end of the block.
# Get a list of partitions for this disk
part_numbers=( $(parted -s $dev print | awk '$1 == "Number" {i=1; next}; i {print $1}') )
# For each device partition apply wipe rules
for part_number in "${part_numbers[@]}"; do
sgdisk_part_info=$(sgdisk -i $part_number $dev)
part_name=$(echo "$sgdisk_part_info" | grep "$part_type_name_str" | awk '{print $3;}')
# special handling for the install device
if [ "${dev}" == "${inst_dev}" ] ; then
# Skip over the bios, efi and boot partitions that got us here.
# LAT handles these partitions
case ${part_name} in
"'bios'" | "'otaefi'" | "'otaboot'" | "'otaboot_b'")
ilog "skipping ${part_name} on partition ${part_number} of device ${dev}"
continue
;;
*)
dlog "wipe candidate ${part_name} on partition ${part_number} of device ${dev}"
;;
esac
fi
part=$(get_part_prefix "${dev}")$part_number
if [ "${controller}" = true ] ; then
# Skip if we already found a valid partition, look otherwise
[ ${BACKUP_PART_FOUND} -eq 1 ] && continue
ilog "Looking for platform-backup partition on $part from ... instdev=${INSTDEV} device=${inst_dev} persistent_device=${persistent_instdev}"
sgdisk_part_info=$(sgdisk -i $part_number $dev)
part_type_guid=$(echo "$sgdisk_part_info" | grep "$part_type_guid_str" | awk '{print $4;}')
if [ "$dev" == "${inst_dev}" -a "$part_type_guid" == $BACKUP_PART_GUID ] ; then
part_type_name=$(echo "$sgdisk_part_info" | grep "$part_type_name_str" | awk '{print $3,$4;}')
BACKUP_PART_NAME=${part_type_name:1:-1}
part_type_first=$(echo "$sgdisk_part_info" | grep "$part_type_first_str" | awk '{print $3;}')
BACKUP_PART_FIRST=${part_type_first}
part_type_end=$(echo "$sgdisk_part_info" | grep "$part_type_end_str" | awk '{print $3;}')
BACKUP_PART_END=${part_type_end}
part_type_size=$(echo "$sgdisk_part_info" | grep "$part_type_size_str" | awk '{print $3;}')
BACKUP_PART_SIZE=${part_type_size}
part_type_flags=$(echo "$sgdisk_part_info" | grep "$part_type_flags_str" | awk '{print $3;}')
BACKUP_PART_FLAGS=${part_type_flags}
ilog "Discovered persistent backup partition: ${part} [${BACKUP_PART_NAME}:${BACKUP_PART_FIRST}:${BACKUP_PART_END}:${BACKUP_PART_SIZE}:${part_type_guid}]"
# Only keep a backup partition that is in the expected location
# and contains a proper filesystem
if [ "${part_number}" == "${BACKUP_PART_NO}" ] ; then
part_fstype=$(exec_retry 5 0.5 "blkid -s TYPE -o value $part")
if [ "${part_fstype}" == "ext4" ] ; then
ilog "Discovered persistent backup partition, ${part}, is in the expected location and is formatted correctly. Maintaining..."
BACKUP_PART_FOUND=1
continue
else
ilog "Discovered persistent backup partition, ${part}, has a missing 'ext4' filesystem . Recreating..."
fi
else
# Make sure we only recreate the backup partition on systems that are
# known to be invalid. Detect a potential switch in BIOS vs. UEFI and
# exit with an appropriate message.
ilog "Discovered persistent backup partition, ${part}, is in an unexpected location. Expected on partition ${BACKUP_PART_NO}."
if [ "$USE_UEFI_PARTITIONS" = 0 ] ; then
# BIOS boot...
if [ "${part_number}" == "${BACKUP_PART_UEFI}" ] ; then
# Found a UEFI location for platform backup
report_failure_with_msg "BIOS booted system has a persistent backup partition in a UEFI expected location. Wipe disks or boot system in UEFI mode."
else
ilog "BIOS booted system has an invalid installation. Recreating "
fi
else
# UEFI boot...
if [ "${part_number}" == "${BACKUP_PART_BIOS}" ] ; then
# Found a BIOS location for platform backup
report_failure_with_msg "UEFI booted system has a persistent backup partition in a BIOS expected location. Wipe disks or boot system in BIOS mode."
else
ilog "UEFI booted system has an invalid installation. Recreating "
fi
fi
fi
fi
fi
if [ "${WIPE_CEPH_OSDS}" = "true" ] && ([ "${part_type_guid}" = "${CEPH_JOURNAL_GUID}" ] || [ "${part_type_guid}" = "${CEPH_MPATH_JOURNAL_GUID}" ]); then
# Journal partitions require additional wiping. Based on the ceph-manage-journal.py
# script in the integ repo (at the ceph/ceph/files/ceph-manage-journal.py location)
# wiping 100MB of data at the beginning of the partition should be enough. We also
# wipe 100MB at the end, just to be safe.
ilog "Wiping Ceph ${part_name} on ${part} start and end with dd"
dd if=/dev/zero of=$part bs=1M count=100 2>/dev/null
dd if=/dev/zero of=$part bs=1M count=100 seek=$(( `blockdev --getsz $part` / (1024 * 2) - 100 )) 2>/dev/null
else
ilog "Wiping ${part_name} on ${part} start and end with dd"
dd if=/dev/zero of=$part bs=512 count=34 2>/dev/null
dd if=/dev/zero of=$part bs=512 count=34 seek=$((`blockdev --getsz $part` - 34)) 2>/dev/null
fi
done
if [ ${BACKUP_PART_FOUND} -eq 0 -o "${dev}" != "${inst_dev}" ] ; then
ilog "Creating disk label for $dev"
parted -s $dev mktable gpt
ilog "... done"
fi
done
ilog "Ensure any LAT installer root/boot partitions are zapped/wiped"
for oldrootlabel in otaroot otaroot_1 otaroot_b otaroot_b_1 ; do
oldrootpart=$(blkid --label $oldrootlabel)
[ -z "$oldrootpart" ] && continue
oldinstdev=/dev/$(lsblk $oldrootpart -n -o pkname)
ilog "... destroying ${oldrootpart} on ${oldinstdev}"
# sgdisk - Command-line GUID partition table (GPT) manipulator
# Zap the entire partition
ilog "... zapping ${oldinstdev}"
sgdisk -Zo ${oldinstdev}
# partprobe - inform the OS of partition table changes
# root@(none):/# partprobe /dev/sda -s
# /dev/sda: gpt partitions 1 2 3 4 5 6
ilog "... probing ${oldinstdev}"
partprobe ${oldinstdev}
# wipefs - wipe a signature from a device
ilog "... wiping ${oldinstdev}"
wipefs --all --backup ${oldinstdev}
done
# Override installer variable to not prompt for erasing the disk
export INSTW=0
true
%end
###########################################################################
%part --interpreter=/bin/bash
HOOK_LABEL="part"
. /tmp/lat/ks_functions.sh
ilog "*****************************************"
ilog "*** Partition - Partition Disks ***"
ilog "*****************************************"
inst_dev=$(get_disk "${INSTDEV}")
###########################################################
# From pre_disk_controller.cfg
###########################################################
function check_partitioning_status() {
start_sec=$(($end_sec+1))
part_no=$((part_no+1))
if [ $start_sec -gt $last ] ; then
report_failure_with_msg "Disk is not big enough for requested layout (start_sec: $start_sec, last: $last)"
fi
}
if [ "$BIOSPLUSEFI" = 1 ] ; then
ilog "BIOSPLUSEFI=1 configuration is requested"
if [ "${controller}" = true -a "$USE_UEFI_PARTITIONS" = 1 ] ; then
ilog "WARNING: UEFI booted and installed controllers will NOT have a BIOS MBR partition due to partitioning patterns established in previous releases."
fi
fi
MIB_BYTES=$((1024*1024))
# Start common partitioning regardless of personality
sgdisk_parts=""
# Get the logical sector size used for determining partition boundaries
LOGICAL_SECTOR_SZ=`lsblk -n ${inst_dev} -o LOG-SEC -d`
# Zap the GPT/MBR information
sgdisk -Z ${inst_dev}
# Get the first aligned sector
first=`sgdisk -F ${inst_dev} | grep -v Creating`
# Get the last aligned sector
export last=$(sgdisk -E ${inst_dev} 2>/dev/null |grep -v Creating)
ilog "Allocate host partitions on ${inst_dev} with first sector: $first and last sector: $last"
# Maintain BIOS partition mappings from previous releases
start_sec=$first
part_no=1
if [ "$USE_UEFI_PARTITIONS" = 0 -o "${controller}" = false ] ; then
# 1MB size for BIOS boot partition
BIOSSZ=1
end_sec=$(($start_sec+(${BIOSSZ}*${MIB_BYTES}/${LOGICAL_SECTOR_SZ})-1))
sgdisk_parts="$sgdisk_parts -n $part_no:$start_sec:$end_sec -c $part_no:bios -t $part_no:EF02"
check_partitioning_status
fi
if [ "${controller}" = true ] ; then
if [ "${aio}" = true ] ; then
get_aio_controller_provisioning_sizes
ilog "AIO Controller: MINIMIZING root disk space allocation"
else
get_std_controller_provisioning_sizes
ilog "STD Controller: MAXIMIZING root disk space allocation"
fi
# Only controllers have a persistent backup partition
export BACKUP_SIZE=${BACKUP_DEFAULT_PERSISTENT_SIZE}
# Check for a bootline override and allocate platform backup partition
if [ -z "$persistent_size" ]; then
# Default backup partition size in MiB
ilog "Platform Backup persistent size not on command line ; defaulting to ${BACKUP_SIZE}"
else
if [ ${persistent_size} -lt ${BACKUP_SIZE} ] ; then
wlog "Cannot set persistent_size smaller than default size of ${BACKUP_SIZE} KB"
else
export BACKUP_SIZE=${persistent_size}
fi
fi
ilog "Platform Backup partition size: ${BACKUP_SIZE}"
if [ ${BACKUP_PART_FOUND} -eq 0 ] ; then
ilog "Platform Backup partition not detected: CREATING"
else
ilog "Platform Backup Partition was detected: PERSISTING"
fi
end_sec=$(($start_sec+(${BACKUP_SIZE}*${MIB_BYTES}/${LOGICAL_SECTOR_SZ})-1))
sgdisk_parts="$sgdisk_parts -n $part_no:$start_sec:$end_sec -c $part_no:${BACKUP_PART_LABEL} -t $part_no:${BACKUP_PART_GUID}"
check_partitioning_status
elif [ "${worker}" = true ] ; then
ilog "Setting up platform_pv partition sizes for worker node"
get_worker_provisioning_sizes
elif [ "${storage}" = true ] ; then
ilog "Setting up platform_pv partition sizes for storage node"
get_storage_provisioning_sizes
fi
ilog "PART_SZ_EFI : ${PART_SZ_EFI}"
ilog "PART_SZ_BOOT : ${PART_SZ_BOOT}"
ilog "PART_SZ_ROOT : ${PART_SZ_ROOT}"
# 300 MiB size for EFI boot partition to align with previous releases
end_sec=$(($start_sec+(${PART_SZ_EFI}*${MIB_BYTES}/${LOGICAL_SECTOR_SZ})-1))
sgdisk_parts="$sgdisk_parts -n $part_no:$start_sec:$end_sec -c $part_no:otaefi -t $part_no:EF00"
check_partitioning_status
# Boot/Root OSTree Partition A (Note: OSTree Partition B not used)
if [ "${PART_SZ_BOOT}" != 0 ] ; then
end_sec=$(($start_sec+(${PART_SZ_BOOT}*${MIB_BYTES}/${LOGICAL_SECTOR_SZ})-1))
sgdisk_parts="$sgdisk_parts -n $part_no:$start_sec:$end_sec -c $part_no:otaboot"
check_partitioning_status
fi
if [ "${PART_SZ_ROOT}" != 0 ] ; then
if [ "$INSTAB" = 0 -a "${INSTFLUX}" = 0 ] ; then
if [ "$VSZ" = 0 ] ; then
report_failure_with_msg "Installation with VSZ=0 is not supported."
else
end_sec=$(($start_sec+(${PART_SZ_ROOT}*${MIB_BYTES}/${LOGICAL_SECTOR_SZ})-1))
fi
sgdisk_parts="$sgdisk_parts -n $part_no:$start_sec:$end_sec -c $part_no:otaroot"
else
end_sec=$(($start_sec+(${PART_SZ_ROOT}*${MIB_BYTES}/${LOGICAL_SECTOR_SZ})-1))
sgdisk_parts="$sgdisk_parts -n $part_no:$start_sec:$end_sec -c $part_no:otaroot"
fi
check_partitioning_status
fi
# Flux Partition
if [ "${LV_SZ_VAR}" = 0 -a "${INSTFLUX}" = 1 ] ; then
if [ "$VSZ" = 0 ] ; then
report_failure_with_msg "Installation with VSZ=0 is not supported."
else
end_sec=$(($start_sec+(${VSZ}*${MIB_BYTES}/${LOGICAL_SECTOR_SZ})-1))
fi
sgdisk_parts="$sgdisk_parts -n $part_no:$start_sec:$end_sec -c $part_no:fluxdata"
check_partitioning_status
fi
# Allocate platform pv
ilog "platform_pv partition - using all remaining disk space"
end_sec=$last
sgdisk_parts="$sgdisk_parts -n $part_no:$start_sec:$end_sec -c $part_no:platform_pv -t $part_no:8E00"
STOR_DEVS=$(echo "$STOR_DEVS" | xargs -n 1 | sort -u | xargs)
[ -z "$STOR_DEVS" ] && report_failure_with_msg "No storage devices available."
ilog "STOR_DEV_FDS Updated ; $STOR_DEV_FDS"
dlog "Requesting ${inst_dev} Partition Table: ${a}"
sgdisk $sgdisk_parts -p ${inst_dev}
[ $? -ne 0 ] && report_failure_with_msg "sgdisk failed to create partitions: ${a}"
true
%end
###########################################################################
%mkfs --interpreter=/bin/bash
HOOK_LABEL="mkfs"
. /tmp/lat/ks_functions.sh
ilog "***************************************************"
ilog "*** Mkfs - Format Partitions & LVM Volumes ***"
ilog "***************************************************"
#######################################################
# From pre_disk_aio
######################################################
vg="volume group"
lv="logical volume"
dev=$(get_disk "${INSTDEV}")
dev_part_prefix=$(get_part_prefix "${dev}")
if [ "${controller}" = true ] ; then
if [ "${aio}" = true ] ; then
get_aio_controller_provisioning_sizes
else
get_std_controller_provisioning_sizes
fi
elif [ "${worker}" = true ] ; then
get_worker_provisioning_sizes
elif [ "${storage}" = true ] ; then
get_storage_provisioning_sizes
fi
# Maintain BIOS partition mappings from previous releases
part_no=1
if [ "$USE_UEFI_PARTITIONS" = 0 -o "${controller}" = false ] ; then
# No formating for the BIOS boot partition
part_no=$((part_no+1))
fi
if [ "${controller}" = true ] ; then
ilog "BACKUP_SIZE : ${BACKUP_SIZE}"
ilog "BACKUP_PART_NO : ${BACKUP_PART_NO}"
ilog "BACKUP_PART_LABEL : ${BACKUP_PART_LABEL}"
ilog "BACKUP_PART_GUID : ${BACKUP_PART_GUID}"
ilog "BACKUP_PART : ${dev_part_prefix}${BACKUP_PART_NO}"
# Only init Platform Backup partition filesystem if the partition was just created
if [ ${BACKUP_PART_FOUND} -eq 0 ] ; then
ilog "Platform Backup Partition was CREATED. Initialize filesystem on ${dev_part_prefix}${BACKUP_PART_NO}"
mkfs.ext4 -F -L ${BACKUP_PART_LABEL} ${dev_part_prefix}${BACKUP_PART_NO}
[ ${?} -ne 0 ] && report_failure_with_msg "Failed Platform Backup partition filesystem init ${dev_part_prefix}${BACKUP_PART_NO}"
else
# Preserving the contents of the backup partition, but make sure it's labeled correctly
e2label ${dev_part_prefix}${BACKUP_PART_NO} ${BACKUP_PART_LABEL}
fi
part_no=$((part_no+1))
fi
# Maintain UEFI partition mappings from previous releases
mkfs.vfat -n otaefi ${dev_part_prefix}${part_no}
[ ${?} -ne 0 ] && report_failure_with_msg "Failed UEFI filesystem init: ${dev_part_prefix}${part_no}, rc=${?}"
part_no=$((part_no+1))
# Boot/Root OSTree Partition A (Note: OSTree Partition B not used)
if [ "${PART_SZ_BOOT}" != 0 ] ; then
mkfs.ext4 -F -L otaboot ${dev_part_prefix}${part_no}
[ ${?} -ne 0 ] && report_failure_with_msg "Failed Boot filesystem init: ${dev_part_prefix}${part_no}, rc=${?}"
part_no=$((part_no+1))
fi
if [ "${PART_SZ_ROOT}" != 0 ] ; then
mkfs.ext4 -F -L otaroot ${dev_part_prefix}${part_no}
[ ${?} -ne 0 ] && report_failure_with_msg "Failed Root filesystem init: ${dev_part_prefix}${part_no}, rc=${?}"
part_no=$((part_no+1))
fi
# Flux Partition
if [ "${LV_SZ_VAR}" = 0 -a "${INSTFLUX}" = 1 ] ; then
mkfs.ext4 -F -L fluxdata ${dev_part_prefix}${part_no}
[ ${?} -ne 0 ] && report_failure_with_msg "Failed Fluxdata (/var) filesystem init: ${dev_part_prefix}${part_no}, rc=${?}"
part_no=$((part_no+1))
fi
# Log important LVM config settings
log_lvm_conf "Installer Initial" /etc/lvm/lvm.conf
# Create Volume Group
pv_part=${dev_part_prefix}${part_no}
ilog "Install disk: ${INSTDEV}"
ilog "Current disk: ${dev} ; current partition index: $part_no"
ilog "LV_SZ_LOG (cgts--vg-log--lv size): ${LV_SZ_LOG} MB"
ilog "LV_SZ_ROOT (cgts--vg-root--lv) : ${LV_SZ_ROOT} MB"
ilog "LV_SZ_SCRATCH (cgts--vg-scratch--lv) : ${LV_SZ_SCRATCH} MB"
ilog "LV_SZ_VAR (cgts--vg-var--lv) : ${LV_SZ_VAR} MB"
ilog "Wipe any previous signatures from the platform physical volume ${pv_part}"
wipefs -a ${pv_part}
[ ${?} -ne 0 ] && report_failure_with_msg "Failed to wipe signatures from ${pv_part}, rc=${?}"
ilog "Create ${vg} 'cgts-vg' ${pv_part} ; $STOR_DEV_FDS"
exec_no_fds "$STOR_DEV_FDS" "vgcreate -y --force cgts-vg ${pv_part} 2>/dev/null" 5 0.5
[ ${?} -ne 0 ] && report_failure_with_msg "Failed to create ${vg} 'cgts-vg' ${pv_part}"
if [ "${LV_SZ_ROOT}" != 0 ] ; then
# Create and Init the '/' logical volume
ilog "Create ${lv} 'root-lv' ; $STOR_DEV_FDS"
exec_no_fds "$STOR_DEV_FDS" "lvcreate -y -Wy -Zy -n root-lv --size ${LV_SZ_ROOT}MB cgts-vg 2>/dev/null" 5 0.5
[ ${?} -ne 0 ] && report_failure_with_msg "Failed to create ${lv} 'root-lv'"
ilog "InitFs ${lv} 'root-lv'"
mkfs.ext4 -F /dev/cgts-vg/root-lv
[ ${?} -ne 0 ] && report_failure_with_msg "Failed to init ${lv} 'root-lv'"
fi
if [ "${LV_SZ_VAR}" != 0 ] ; then
# Create and Init the '/' logical volume
ilog "Create ${lv} 'var-lv' ; $STOR_DEV_FDS"
exec_no_fds "$STOR_DEV_FDS" "lvcreate -y -Wy -Zy -n var-lv --size ${LV_SZ_ROOT}MB cgts-vg 2>/dev/null" 5 0.5
[ ${?} -ne 0 ] && report_failure_with_msg "Failed to create ${lv} 'root-lv'"
ilog "InitFs ${lv} 'var-lv'"
mkfs.ext4 -F /dev/cgts-vg/var-lv
[ ${?} -ne 0 ] && report_failure_with_msg "Failed to init ${lv} 'root-lv'"
fi
# Create and Init the '/var/log' logical volume
ilog "Create ${lv} 'log-lv' ; $STOR_DEV_FDS"
exec_no_fds "$STOR_DEV_FDS" "lvcreate -y -Wy -Zy -n log-lv --size ${LV_SZ_LOG}MB cgts-vg 2>/dev/null" 5 0.5
[ ${?} -ne 0 ] && report_failure_with_msg "Failed to create ${lv} 'log-lv'"
ilog "InitFs ${lv} 'log-lv'"
mkfs.ext4 -F /dev/cgts-vg/log-lv
[ ${?} -ne 0 ] && report_failure_with_msg "Failed to init ${lv} 'log-lv'"
# Create and init the '/scratch' logical volume
ilog "Create ${lv} 'scratch-lv' ; $STOR_DEV_FDS"
exec_no_fds "$STOR_DEV_FDS" "lvcreate -y -Wy -Zy -n scratch-lv --size ${LV_SZ_SCRATCH}MB cgts-vg 2>/dev/null" 5 0.5
[ ${?} -ne 0 ] && report_failure_with_msg "Failed to create ${lv} 'scratch-lv'"
ilog "InitFs ${lv} 'scratch-lv'"
mkfs.ext4 -F /dev/cgts-vg/scratch-lv
[ ${?} -ne 0 ] && report_failure_with_msg "Failed to init ${lv} 'scratch-lv'"
#######################################################################
# From post_lvm_on_rootfs.cfg (all hosts)
#######################################################################
# uncomment the global_filter line in lvm.conf
perl -0777 -i.bak -pe 's:(# This configuration option has an automatic default value\.\n)\t# global_filter:$1 global_filter:m' /etc/lvm/lvm.conf
perl -0777 -i -pe 's:(# Example\n)\t# preferred_names:$1 preferred_names:m' /etc/lvm/lvm.conf
# Get the LVM disk partition and add it to the lvm.conf file
export LV_ROOTDISK=$(exec_no_fds "$STOR_DEV_FDS" "pvdisplay --select 'vg_name=cgts-vg' -C -o pv_name --noheadings" | xargs)
[ -z ${LV_ROOTDISK} ] && report_failure_with_msg "Failed to identify logical volume rootdisk via pvdisplay"
# Edit the LVM config so LVM only looks for LVs on ${LV_ROOTDISK}
ilog "Edit the LVM config so LVM only looks for LVs on the root disk"
sed -i "s#^\( *\)global_filter = \[.*#\1global_filter = [ \"a|${LV_ROOTDISK}|\", \"r|.*|\" ]#" /etc/lvm/lvm.conf
# Log important LVM config settings
log_lvm_conf "Installer Updated" /etc/lvm/lvm.conf
#####################################################################
# From pre_disk_setup_tail.cfg
#####################################################################
# Close all FDs and wait for udev to reshuffle all partitions.
ilog "Releasing storage device locks and FDs."
for fd in $STOR_DEV_FDS
do
flock -u "$fd"
exec {fd}>&-
done
sleep 2
udevadm settle --timeout=300 || report_failure_with_msg "udevadm settle failed"
#lsblk -o name,mountpoint,label,size,uuid
# Rescan LVM cache to avoid warnings for VGs that were recreated.
pvscan --cache 2>/dev/null
# Stage the ostree_repo in /sysroot for network installations
# of controller nodes. Doing so avoids a double ostree pull of
# the huge ostree_repo over the network.
if is_usb_install -eq 0 ; then
ilog "USB Install"
else
ilog "Network Install"
##################################################################
#
# System node installs of worker and storage nodes are installed
# over the network rather than from a staged archive.
# This is because these node types do not have/need a local feed.
#
##################################################################
if [ "${controller}" = true ] ; then
ilog "Controller Install"
##############################################################
#
# Controller node network installs pull the ostree_repo from
# the pxeboot server's feed directory in 'archive' mode into
# /sysroot as a local staging location. In this case LAT's
# INSTL (install) variable is updated to install from that
# local stage.
#
# This is done to avoid a second (double) ostree_repo pull
# over the network that would otherwise be needed to populate
# the controller's feed directory.
#
# This staged ostree_repo archive is later moved to the
# controller's feed directory to be used for future installs
# of other system nodes from this controller.
#
##############################################################
ilog "OSTREE_ROOT_DEVICE: ${OSTREE_ROOT_DEVICE}"
ilog "OSTREE_VAR_DEVICE : ${OSTREE_VAR_DEVICE}"
PHYS_SYSROOT="/sysroot"
mkdir -p ${PHYS_SYSROOT}
mount -o rw,noatime "${OSTREE_ROOT_DEVICE}" "${PHYS_SYSROOT}" || elog "Error mounting ${OSTREE_ROOT_DEVICE}"
repo="${PHYS_SYSROOT}/var/www/pages/feed/rel-xxxPLATFORM_RELEASExxx/ostree_repo"
mkdir -p "${repo}"
# Tell LAT to install from this local stage
# i.e. override where LAT installs from.
export instl=${repo}
export INSTL=${instl}
ostree --repo=${repo} init --mode=archive
if [ "${insturl}" = "file://NOT_SET" ] ; then
ilog "ostree_repo archive pull from file:///instboot/ostree_repo"
ostree --repo=${repo} remote add ${instbr} file:///instboot/ostree_repo
else
ilog "ostree_repo archive pull from ${insturl}"
ostree --repo=${repo} remote add ${instbr} ${insturl}
fi
ilog "Executing: ostree --repo=${repo} pull --depth=-1 --mirror ${instbr}:${instbr}"
ostree --repo=${repo} pull --depth=-1 --mirror ${instbr}:${instbr}
rc=$?
if [ $rc -ne 0 ]; then
report_failure_with_msg "ostree pull failed, rc=$rc"
fi
umount ${PHYS_SYSROOT}
fi
fi
# Important: To align with installer expectations of where otaefi will reside,
# reset the value of p1
if [ "${controller}" = true ] ; then
if [ "$USE_UEFI_PARTITIONS" = 0 ] ; then
# BIOS firmware execution
# Number Start (sector) End (sector) Size Code Name
# 1 2048 4095 1024.0 KiB EF02 bios
# 2 4096 61444095 29.3 GiB FFFF platform_backup
# 3 61444096 62058495 300.0 MiB EF00 otaefi
#
p1=3
else
# UEFI firmware execution
# Number Start (sector) End (sector) Size Code Name
# 1 2048 61442047 29.3 GiB FFFF platform_backup
# 2 61442048 62056447 300.0 MiB EF00 otaefi
p1=2
# LAT installer will attempt to write the legacy BIOS grub information
# after exiting from this hook. Skip it, in this case, as we don't have
# a BIOS boot partition
export BIOSPLUSEFI=0
fi
elif [ "${worker}" = true -o "${storage}" = true ] ; then
# UEFI and BIOS firmware execution
# Number Start (sector) End (sector) Size Code Name
# 1 2048 4095 1024.0 KiB EF02 bios
# 2 4096 618495 300.0 MiB EF00 otaefi
p1=2
fi
# Important: Set fs_dev needed by the installer for mounting/updating the efi
# partition
fs_dev=${dev_part_prefix}
true
%end
###########################################################################
%post --interpreter=/bin/bash
HOOK_LABEL="post"
. /tmp/lat/ks_functions.sh
ilog "*********************************************************"
ilog "**** Post - Add user/groups **"
ilog "*********************************************************"
# Set password for root to 'root'
# usermod -p '$6$hEv/K.fPeg/$ezIWhJPrMG3WtdEwqQRdyBwdYmPZkqW2PONFAcDd6TqWliYc9dHAwW4MFTlLanVH3/clE0/34FheDMpbAqZVG.' root
# To enable root password
# 1. Uncomment set root password command above
# 2. Comment out 'passwd -l root' command below
# Lock the root password
passwd -l root
# Remove admin user whether it exists or not
deluser admin || true
# Create the sysadmin user
useradd sysadmin -m --shell /bin/bash -G sudo --password 4SuW8cnXFyxsk
chage -d 0 sysadmin
# add 'nobody' group
groupadd nobody
# Reload /etc/group- to make systemd-sysusers.service happy
/usr/sbin/grpconv || report_failure_with_msg "Failed to convert from shadow passwords and groups"
%end
%post --interpreter=/bin/bash
HOOK_LABEL="post"
. /tmp/lat/ks_functions.sh
ilog "*********************************************************"
ilog "*** Post - Traits & Platform Config File update ***"
ilog "*********************************************************"
# Set node traits' state
[ "${controller}" = true ] && ilog "Controller Function"
[ "${storage}" = true ] && ilog "Storage Function"
[ "${worker}" = true ] && ilog "Worker Function"
[ "${lowlatency}" = true ] && ilog "Low Latency Function"
[ "${controller}" = true -a ${worker} = true ] && aio=true
# Parse traits to nodetype, subfunction and system_type
# -----------------------------------------------------
# Set nodetype from traits
if [ "${controller}" = true ] ; then
nodetype=${TRAIT__CONTROLLER}
elif [ "${storage}" = true ] ; then
nodetype=${TRAIT__STORAGE}
elif [ "${worker}" = true ] ; then
nodetype=${TRAIT__WORKER}
fi
ilog "nodetype=${nodetype}"
# Set system type and subfunction
subfunction=""
system_type=""
[ "${controller}" = true -a "${worker}" = true ] && aio=true
if [ "${aio}" = true ] ; then
ilog "${SYSTEM_TYPE__AIO} System"
system_type="${SYSTEM_TYPE__AIO}"
subfunction="${SUBFUNCTION__AIO}"
if [ "${lowlatency}" = true ] ; then
ilog "Setting aio lowlatency"
ln -s /usr/share/systemd-presets/lowlatency.preset /etc/systemd/system-preset/10-aio.preset
else
ln -s /usr/share/systemd-presets/aio.preset /etc/systemd/system-preset/10-aio.preset
fi
else
ilog "${SYSTEM_TYPE__STANDARD} System"
system_type="${SYSTEM_TYPE__STANDARD}"
if [ "${worker}" = true ] ; then
subfunction=${SUBFUNCTION__WORKER}
if [ "${lowlatency}" = true ] ; then
ilog "Setting ${SUBFUNCTION__WORKER} lowlatency"
ln -s /usr/share/systemd-presets/worker-lowlatency.preset /etc/systemd/system-preset/10-${SUBFUNCTION__WORKER}.preset
else
ln -s /usr/share/systemd-presets/worker.preset /etc/systemd/system-preset/10-${SUBFUNCTION__WORKER}.preset
fi
elif [ "${storage}" = true ] ; then
subfunction=${SUBFUNCTION__STORAGE}
ilog "Setting ${SUBFUNCTION__STORAGE} preset"
ln -s /usr/share/systemd-presets/storage.preset /etc/systemd/system-preset/10-${SUBFUNCTION__STORAGE}.preset
else
subfunction=${SUBFUNCTION__CONTROLLER}
ilog "Setting ${SUBFUNCTION__CONTROLLER} preset"
ln -s /usr/share/systemd-presets/controller.preset /etc/systemd/system-preset/10-${SUBFUNCTION__CONTROLLER}.preset
fi
fi
if [ "${lowlatency}" = true ] ; then
subfunction="${subfunction},${TRAIT__LOWLATENCY}"
fi
ilog "subfunction=${subfunction}"
ilog "system_type=${system_type}"
#################################################################
# From post_platform_conf_controller.cfg
# From post_platform_conf_aio.cfg
# From post_platform_conf_aio_lowlatency.cfg
#################################################################
ilog "create platform.conf and set personality traits"
[ ! -d "/etc/platform" ] && mkdir -p -m 0775 /etc/platform
cat <<EOF > ${PLATFORM_CONF}
nodetype=${nodetype}
subfunction=${subfunction}
system_type=${system_type}
EOF
ilog "Create systemd presets and set personality traits"
systemctl daemon-reload
systemctl --preset-mode=full preset-all
##############################################################
# From post_pxeboot_controller
# From post_net_common.cfg
# ############################################################
# Set http port
# Persist the default http port number to platform configuration.
# This will get overwritten when by manifest during sw configuration phase.
if [[ "${insturl}" == *"pxecontroller"* && "${insturl}" == *"http"* ]] ; then
http_port=$(echo $(cat /proc/cmdline |xargs -n1 echo |grep '^insturl=' | sed -r 's#^[^/]*://[^/]*:([0-9]*)/.*#\1#'))
else
http_port=8080
fi
update_platform_conf "http_port=${http_port}"
#############################################################
# From post_common.cfg (all hosts)
#############################################################
rm /etc/hostname
# TODO: is this needed with LAT ??
# If using a serial install make sure to add a getty on the tty1
conarg=`cat /proc/cmdline |xargs -n1 echo |grep console= |grep ttyS`
if [ -n "$conarg" ] ; then
echo "1:2345:respawn:/sbin/mingetty tty1" >> /etc/inittab
fi
blkid >> ${LOGFILE}
# TODO: See if other post_common.cfg content is needed
true
%end
###########################################################################
%post --interpreter=/bin/bash
HOOK_LABEL="post"
. /tmp/lat/ks_functions.sh
ilog "*************************************"
ilog "*** Post - Set Kernel Args ***"
ilog "*************************************"
###########################################################
# From post_kernel_controller.cfg
# From post_kernel_aio_worker.cfg
###########################################################
. /etc/platform/platform.conf
# Prepare the disk boot kernel comand line
# ----------------------------------------
KERN_OPTS="${KERNEL_PARAMS}"
ilog "Building up KERN_OPTS: ${KERN_OPTS}"
function add_kernel_option()
{
option="${1}"
ilog "... adding: ${option}"
# avoid adding leading space on first option
if [ "${KERN_OPTS}" = "" ] ; then
KERN_OPTS="${option}"
else
KERN_OPTS="${KERN_OPTS} ${option}"
fi
}
# If the installer asked us to use security related kernel params, use
# them in the grub line as well (until they can be configured via puppet)
security_feature=""
# Handle security options
# TODO: Create a list and loop over it
security_options="nopti nospectre_v2 nospectre_v1"
for o in ${security_options}
do
grep -q ${o} /proc/cmdline
if [ $? -eq 0 ]; then
add_kernel_option "${o}"
if [ "${security_feature}" = "" ] ; then
security_feature="${o}"
else
security_feature="${security_feature} ${o}"
fi
fi
done
[ "${KERN_OPTS}" != "" ] && ilog "Learned kernel params: ${KERN_OPTS}"
ilog "Adding kernel options"
if [ "${aio}" = true -o "${worker}" = true ] ; then
if [ -e /etc/init.d/cpumap_functions.sh ] ; then
# Update grub with custom kernel bootargs
source /etc/init.d/cpumap_functions.sh
n_cpus=$(cat /proc/cpuinfo 2>/dev/null | \
awk '/^[pP]rocessor/ { n +=1 } END { print (n>0) ? n : 1}')
ilog "cpumap: n_cpus:${n_cpus}"
n_numa=$(ls -d /sys/devices/system/node/node* 2>/dev/null | wc -l)
ilog "cpumap: n_numa:${n_numa}"
KERN_OPTS="${KERN_OPTS} iommu=pt"
KERN_OPTS="${KERN_OPTS} hugepagesz=2M hugepages=0 default_hugepagesz=2M"
# If this is an all-in-one system, we need at least 4 CPUs
if [ "${aio}" = true -a ${n_cpus} -lt 4 ]; then
report_failure_with_msg "At least 4 CPUs are required for ${SYSTEM_TYPE__AIO} node."
fi
# Add kernel options for cpu isolation / affinity
if [ ${n_cpus} -gt 1 ] ; then
base_cpulist=$(platform_expanded_cpu_list)
ilog "cpumap: base_cpulist: ${base_cpulist}"
base_cpumap=$(cpulist_to_cpumap ${base_cpulist} ${n_cpus})
ilog "cpumap: base_cpumap: ${base_cpumap}"
avp_cpulist=$(vswitch_expanded_cpu_list)
ilog "cpumap: avp_cpulist:${avp_cpulist}"
if [ -e /etc/vswitch/vswitch.conf ] ; then
# Update vswitch.conf
sed -i "s/^VSWITCH_CPU_LIST=.*/VSWITCH_CPU_LIST=\"${avp_cpulist}\"/" /etc/vswitch/vswitch.conf
else
wlog "Missing /etc/vswitch/vswitch.conf ; update bypassed"
fi
norcu_cpumap=$(invert_cpumap ${base_cpumap} ${n_cpus})
ilog "cpumap: norcu_cpumap:${norcu_cpumap}"
norcu_cpulist=$(cpumap_to_cpulist ${norcu_cpumap} ${n_cpus})
ilog "cpumap: norcu_cpulist:${norcu_cpulist}"
if [ "${lowlatency}" = true ]; then
KERN_OPTS="${KERN_OPTS} nohz_full=${norcu_cpulist}"
fi
KERN_OPTS="${KERN_OPTS} rcu_nocbs=${norcu_cpulist}"
KERN_OPTS="${KERN_OPTS} kthread_cpus=${base_cpulist}"
KERN_OPTS="${KERN_OPTS} irqaffinity=${norcu_cpulist}"
fi
else
wlog "Missing /etc/init.d/cpumap_functions.sh ; cpumap setup bypassed"
fi
# Add kernel options to set NMI watchdog
if [ "${lowlatency}" = true ] ; then
add_kernel_option "nmi_watchdog=0 softlockup_panic=0"
else
add_kernel_option "nmi_watchdog=panic,1 softlockup_panic=1"
fi
if [[ "$(dmidecode -s system-product-name)" =~ ^ProLiant.*Gen8$ ]]; then
add_kernel_option "intel_iommu=on,eth_no_rmrr"
else
add_kernel_option "intel_iommu=on"
fi
# Add kernel options to disable kvm-intel.eptad on Broadwell
# Broadwell: Model: 79, Model name: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz
if grep -q -E "^model\s+:\s+79$" /proc/cpuinfo
then
add_kernel_option "kvm-intel.eptad=0"
fi
# Add kernel option to avoid jiffies_lock contention on real-time kernel
if [ "${lowlatency}" = true ] ; then
add_kernel_option "skew_tick=1"
fi
elif [ "${controller}" = true ] ; then
ilog "Adding ${TRAIT__CONTROLLER} function kernel options"
## Custom kernel options
add_kernel_option "intel_iommu=off usbcore.autosuspend=-1"
## Setup the loop module to support up to 15 partitions so that we
## can enable the customer to manually resize images if needed.
##
add_kernel_option "loop.max_part=15"
# Add kernel options to ensure NMI watchdog is enabled, if supported
add_kernel_option "nmi_watchdog=panic,1 softlockup_panic=1"
elif [ "${storage}" = true ] ; then
ilog "Adding ${TRAIT__STORAGE} function kernel options"
## Custom kernel options
add_kernel_option "intel_iommu=off usbcore.autosuspend=-1"
# Add kernel options to ensure NMI watchdog is enabled, if supported
add_kernel_option "nmi_watchdog=panic,1 softlockup_panic=1"
fi
#########################################################################################
# From post_kernel_aio_and_worker.cfg
# From post_kernel_controller.cfg
# From post_kernel_storage.cfg
#########################################################################################
# Add kernel options to ensure an selinux is disabled for all node types
add_kernel_option "selinux=0 enforcing=0"
# Add kernel option to panic on a softdog timeout
add_kernel_option "softdog.soft_panic=1"
# Make sure that we are using cgroups v1
add_kernel_option "systemd.unified_cgroup_hierarchy=0"
# k8s updates
add_kernel_option "user_namespace.enable=1"
# Add kernel option to disable biosdevname if enabled
# As this may already be in GRUB_CMDLINE_LINUX, only add if it is not already present
grep -q '^GRUB_CMDLINE_LINUX=.*biosdevname=0' /etc/default/grub
if [ $? -ne 0 ]; then
add_kernel_option "biosdevname=0"
fi
if [ ! -z "${insthwsettle}" ]; then
if [[ ${insthwsettle} =~ ^[0-9]+$ ]]; then
add_kernel_option "hwsettle=${insthwsettle}"
fi
fi
# Search the install kernel command line for the multi-drivers-switch=
# option and if present propagate that to the disk boot kernel options.
CMDLINE=`cat /proc/cmdline`
param="multi-drivers-switch"
for option in ${CMDLINE} ; do
opt=${option%%=*}
if [ "${param}" = "${opt}" ]; then
add_kernel_option "${option}"
break
fi
done
########################################################################################
ilog "Adding these kernel params to disk boot: ${KERN_OPTS}"
if [ -n "${KERN_OPTS}" ] ; then
grep -q "^kernel_params=" /boot/efi/EFI/BOOT/boot.env
if [ ${?} -ne 0 ]; then
# Add line
sed -i "1 a kernel_params=${KERN_OPTS}" /boot/efi/EFI/BOOT/boot.env
else
# Update existing
sed -i "s/^kernel_params=.*/kernel_params=${KERN_OPTS}/" /boot/efi/EFI/BOOT/boot.env
fi
else
wlog "no kernel options added"
fi
ilog "Override LAT grub file"
GRUB_PATH_N_FILE="/boot/efi/EFI/BOOT/grub.cfg"
if [ ! -e ${GRUB_PATH_N_FILE}.lat ] ; then
mv ${GRUB_PATH_N_FILE} ${GRUB_PATH_N_FILE}.lat
cp /var/pxeboot/pxelinux.cfg.files/grub.cfg.stx ${GRUB_PATH_N_FILE}
fi
######################################################################
# From post_system_aio
######################################################################
TEMPLATE_FILE="/usr/share/worker-utils/config/worker_reserved.conf"
TARGET_FILE="/etc/platform/worker_reserved.conf"
if [ "${aio}" = true ] ; then
## Reserve more memory for base processes since the controller has higher
## memory requirements but cap it to better handle systems with large
## amounts of memory
TOTALMEM=$(grep MemTotal /proc/meminfo | awk '{print int($2/1024)}')
ilog "${SYSTEM_TYPE__AIO} MemTotal:${TOTALMEM}"
if [ -e /sys/devices/system/node/node0 ]; then
RESERVEDMEM=$(grep MemTotal /sys/devices/system/node/node0/meminfo | awk '{printf "%d\n", $4/1024}')
else
RESERVEDMEM=$(grep MemTotal /proc/meminfo | awk '{print int($2/1024/4)}')
fi
if [ ${RESERVEDMEM} -lt 6144 ]; then
RESERVEDMEM=6144
elif [ ${RESERVEDMEM} -gt 14500 ]; then
RESERVEDMEM=14500
elif [ ${RESERVEDMEM} -gt 8192 ]; then
RESERVEDMEM=8192
fi
# Normally we would set personality based files later
# But we need to copy worker_reserved.conf now since it needs to be modified for AIO
ilog "${SYSTEM_TYPE__AIO} Reserved Memory: ${RESERVEDMEM}"
if [ ! -e "${TEMPLATE_FILE}" ] ; then
report_failure_with_msg "Cannot configure worker cpu/memory ; missing ${TEMPLATE_FILE}"
fi
cp "${TEMPLATE_FILE}" "${TARGET_FILE}"
if [ ! -e "${TARGET_FILE}" ] ; then
report_failure_with_msg "Cannot configure worker cpu/memory ; missing ${TARGET_FILE}"
fi
sed -i -e "s#\(WORKER_BASE_RESERVED\)=.*#\1=(\"node0:${RESERVEDMEM}MB:1\" \"node1:2000MB:0\" \"node2:2000MB:0\" \"node3:2000MB:0\")#g" "${TARGET_FILE}"
if [ $? -ne 0 ] ; then
report_failure_with_msg "Cannot configure worker cpu/memory ; previous sed search and replace request failed"
fi
worker_reserved=$(grep WORKER_BASE_RESERVED "${TARGET_FILE}")
ilog "${SYSTEM_TYPE__AIO} '${worker_reserved}'"
# Update WORKER_CPU_LIST
N_CPUS=$(cat /proc/cpuinfo 2>/dev/null | awk '/^[pP]rocessor/ { n +=1 } END { print (n>0) ? n : 1}')
sed -i "s/^WORKER_CPU_LIST=.*/WORKER_CPU_LIST=\"0-$((N_CPUS-1))\"/" "${TARGET_FILE}"
worker_cpu_list=$(grep WORKER_CPU_LIST "${TARGET_FILE}")
ilog "${SYSTEM_TYPE__AIO} '${worker_cpu_list}'"
elif [ "${worker}" = true ] ; then
# Keep logic contained and copy worker_reserved.conf now since we need
# to do the copy for AIO above
ilog "Enable ${TARGET_FILE} for ${TRAIT__WORKER}"
if [ ! -e "${TEMPLATE_FILE}" ] ; then
report_failure_with_msg "Cannot configure worker cpu/memory ; missing ${TEMPLATE_FILE}"
fi
cp "${TEMPLATE_FILE}" "${TARGET_FILE}"
if [ ! -e "${TARGET_FILE}" ] ; then
report_failure_with_msg "Cannot configure worker cpu/memory ; missing ${TARGET_FILE}"
fi
fi
true
%end
###########################################################################
%post --interpreter=/bin/bash --nochroot
HOOK_LABEL="post_nochroot"
. /tmp/lat/ks_functions.sh
ilog "************************************"
ilog "*** Post - Interface Setup ***"
ilog "************************************"
###########################################################
# From post_pxeboot_controller
# From post_net_common.cfg
###########################################################
# TODO: Not needed on a USB install.
# TODO: Need to adjust fault handling or condition on USB install.
# Obtain the boot interface from the PXE boot
BOOTIF=$(cat /proc/cmdline |xargs -n1 echo |grep BOOTIF=)
BOOTIF=${BOOTIF#BOOTIF=}
boot_dev=lo
mgmt_vlan=0
# host_info is fetched from system inventory by curl using
# the sysinv public api with the boot interface mac address.
# curl -sf http://pxecontroller:6385/v1/ihosts/<mac>/mgmt_ip
#
# System inventory returns the following quoted string containing
# the hostname, management ip and netmask (prefix) that matches the
# supplied mac address.
#
# "<hostname> <mgmt ip>/<netmask>"
#
# This information is used to create a management network interface
# setup file for /etc/network/interfaces.d/ifcfg_<mgmt> so that IPSec
# can be configured early in the first reboot following the install.
# Specifically before config / puppet manifests are run.
host_info=""
# The management ip and netmask are extracted from ${host_info}
mgmt_ip=""
mgmt_nm=0
mgmt_gw=0
if [ -n "${BOOTIF}" ] ; then
# convert xx-xx-xx-xx-xx-xx to xx:xx:xx:xx:xx:xx
BOOTIF=$(echo ${BOOTIF} | sed -r -e 's/.*(..-..-..-..-..-..)$/\1/' -e 's/-/:/g')
if is_system_node_install -eq 0 ; then
get_mgmt_ip_cmd="curl -sf http://pxecontroller:6385/v1/ihosts/${BOOTIF}/mgmt_ip"
host_info=`${get_mgmt_ip_cmd}`
rc=$?
if [ ${rc} -ne 0 ] ; then
elog "Failed command: ${get_mgmt_ip_cmd}"
report_failure_with_msg "Unable to fetch management network IP from System Inventory REST API. Aborting installation. rc:${rc}"
elif [[ ${#host_info} -lt 8 ]] ; then
report_failure_with_msg "Host Info fetched from System Inventory REST API is invalid : [${host_info}]. Aborting installation."
else
# remove unwanted string quotes
ilog "Host Info: ${host_info}"
mgmt_nm=$(echo "${host_info}" | grep -o '"netmask": "[^"]*' | cut -d'"' -f4)
mgmt_ip=$(echo "${host_info}" | grep -o '"address": "[^"]*' | cut -d'"' -f4)
ilog "... mgmt_ip=${mgmt_ip} and mgmt_nm=${mgmt_nm}"
if [ -z "${mgmt_ip}" -o "${mgmt_ip}" == "None" -o -z "${mgmt_nm}" -o "${mgmt_nm}" = "None" ] ; then
report_failure_with_msg "Unable to parse management ip and netmask from sysinv queried mgmt_ip info : value:${host_info}. Aborting Installation."
else
mgmt_gw=$(echo "${mgmt_ip}" | awk -F'.' -v OFS='.' '{$NF=1}1')
ilog "... mgmt_gw=${mgmt_gw}"
fi
hostname=$(echo "${host_info}" | grep -o '"hostname": "[^"]*' | cut -d'"' -f4)
if [ -z "${hostname}" -o "${hostname}" == "None" ] ; then
report_failure_with_msg "Unable to parse hostname from sysinv queried mgmt_ip info: value:${host_info}. Aborting Installation."
else
ilog "adding ${hostname} to ${IMAGE_ROOTFS}/etc/hostname"
echo "${hostname}" > ${IMAGE_ROOTFS}/etc/hostname
fi
floating=$(echo "${host_info}" | grep -o '"floating": "[^"]*' | cut -d'"' -f4)
if [ -z "${floating}" -o "${floating}" == "None" ] ; then
report_failure_with_msg "Unable to parse floating ip from sysinv queried mgmt_ip info: value:${host_info}. Aborting Installation."
else
ilog "adding nameserver ${floating} to ${IMAGE_ROOTFS}/etc/resolv.conf"
echo "nameserver ${floating}" >> ${IMAGE_ROOTFS}/etc/resolv.conf
fi
fi
fi
ndev=`ip link show |grep -B 1 ${BOOTIF} |head -1 |awk '{print $2}' |sed -e 's/://'`
if [ -n "${ndev}" ] ; then
# convert to predictive name
boot_dev=$(get_iface_from_ethname ${ndev})
if [ "${boot_dev}" == "" ] ; then
report_failure_with_msg "failed to get predictive altname from ${ndev}"
fi
# get vlan info for system node installs
if is_system_node_install -eq 0 ; then
# Retrieve the management VLAN from sysinv if it exists
ilog "Querying system inventory for management vlan id"
mgmt_vlan=`curl -sf http://pxecontroller:6385/v1/isystems/mgmtvlan`
rc=$?
if [ ${rc} -ne 0 ] ; then
report_failure_with_msg "Unable to communicate with System Inventory REST API. Aborting installation. rc:${rc}"
fi
ilog "Pxeboot Interface: ${ndev} -> ${boot_dev} -> vlan${mgmt_vlan}"
else
ilog "Pxeboot Interface: ${ndev} -> ${boot_dev}"
fi
else
report_failure_with_msg "Unable to determine boot interface from BOOTIF=$BOOTIF."
fi
else
wlog "BOOTIF is not set. Unable to determine boot interface."
fi
ilog "boot_dev : ${boot_dev}"
ilog "mgmt_vlan: ${mgmt_vlan}"
if [ ! -e "${IMAGE_ROOTFS}/etc/network/interfaces" ] ; then
cat << EOF >> ${IMAGE_ROOTFS}/etc/network/interfaces
# This file describes the network interfaces available on the system
# and how to activate them. For more information , see interfaces(5)
source ${IMAGE_ROOTFS}/etc/network/interfaces.d/*
EOF
fi
if [ ! -d "${IMAGE_ROOTFS}/etc/network/interfaces.d" ] ; then
mkdir -p -m 0775 ${IMAGE_ROOTFS}/etc/network/interfaces.d
fi
ilog "Setup network scripts"
# Create the default ipv4 pxeboot network interface setup file
if [[ ${boot_dev} != "lo" && is_system_node_install -eq 0 ]] ; then
# create a pxeboot network setup script based on the pxeboot assigned ip
pxeboot_ip=$(ip -o -4 addr show ${boot_dev} | awk '{print $4}' | cut -d/ -f1)
ifcfg_file="${IMAGE_ROOTFS}/etc/network/interfaces.d/ifcfg-pxeboot"
ilog "dhcp leased pxeboot_ip is ${pxeboot_ip}"
ilog "Creating dhcp pxeboot ${ifcfg_file}"
cat << EOF > ${ifcfg_file}
auto ${boot_dev}:2
iface ${boot_dev}:2 inet dhcp
post-up echo 0 > /proc/sys/net/ipv6/conf/${boot_dev}/autoconf; echo 0 > /proc/sys/net/ipv6/conf/${boot_dev}/accept_ra; echo 0 > /proc/sys/net/ipv6/conf/${boot_dev}/accept_redirects
EOF
# add the pxecontroller ip address to /etc/resolv.conf
output=$(nslookup pxecontroller | grep "Name:" -C 1 | grep Address)
if [ -z "${output}" ] ; then
wlog "nslookup pxecontroller did not yield an ip address"
else
pxeboot_gw=$(echo "${output}" | awk '{print $2}')
ilog "adding nameserver ${pxeboot_gw} to ${IMAGE_ROOTFS}/etc/resolv.conf"
echo "nameserver ${pxeboot_gw}" >> ${IMAGE_ROOTFS}/etc/resolv.conf
fi
fi
# Check if this is a vlan setup
if [ ${mgmt_vlan} -eq 0 ] ; then
# Not vlan path
# Persist the boot device to the platform configuration. This will get
# overwritten later if the management_interface is on a bonded interface.
update_platform_conf "management_interface=${boot_dev}"
# Build networking scripts
cat << EOF > ${IMAGE_ROOTFS}/etc/network/interfaces.d/ifcfg-lo
auto lo
iface lo inet loopback
EOF
if [[ ${boot_dev} != "lo" && is_system_node_install -eq 0 ]] ; then
# setup the management interface with the sysinv supplied static address
if [ -n "${host_info}" ] ; then
ifcfg_file="${IMAGE_ROOTFS}/etc/network/interfaces.d/ifcfg-${boot_dev}"
ilog "Creating static mgmt ${ifcfg_file}"
cat << EOF > ${ifcfg_file}
auto ${boot_dev}
iface ${boot_dev} inet static
address ${mgmt_ip}
netmask ${mgmt_nm}
gateway ${mgmt_gw}
post-up echo 0 > /proc/sys/net/ipv6/conf/${boot_dev}/autoconf; echo 0 > /proc/sys/net/ipv6/conf/${boot_dev}/accept_ra; echo 0 > /proc/sys/net/ipv6/conf/${boot_dev}/accept_redirects
EOF
fi
else
# Is a pxeboot but not a system node install - likely controller-0
# Setup boot interface with DHCP so we can log into the server following the install.
# This will get changed during ansible bootstrap
ifcfg_file=${IMAGE_ROOTFS}/etc/network/interfaces.d/ifcfg-${boot_dev}
ilog "Creating dhcp mgmt ${ifcfg_file}"
cat << EOF > ${ifcfg_file}
auto ${boot_dev}
iface ${boot_dev} inet dhcp
post-up echo 0 > /proc/sys/net/ipv6/conf/${boot_dev}/autoconf; echo 0 > /proc/sys/net/ipv6/conf/${boot_dev}/accept_ra; echo 0 > /proc/sys/net/ipv6/conf/${boot_dev}/accept_redirects
EOF
fi
else # vlan
ilog "Configuring vlan: boot_iface=vlan${mgmt_vlan}"
# Check whether to use inet or inet6
ipv6_addr=$(dig +short AAAA controller.internal)
if [[ -z "${ipv6_addr}" ]]
then
# during an upgrade the controller.internal may not be defined
# but the scenario could be IPv6. So try to resolve the controller
ipv6_addr=$(dig +short AAAA controller)
fi
if [[ -n "${ipv6_addr}" ]]
then
boot_address_family=inet6
ipv6init=yes
dhcpv6c=yes
else
boot_address_family=inet
ipv6init=no
dhcpv6c=no
fi
# Persist the boot device to the platform configuration. This will get
# overwritten later if the management_interface is on a bonded interface.
update_platform_conf "management_interface=vlan${mgmt_vlan}"
# Build networking scripts
cat << EOF > ${IMAGE_ROOTFS}/etc/network/interfaces.d/ifcfg-lo
auto lo
iface lo ${boot_address_family} loopback
EOF
ifcfg_file="${IMAGE_ROOTFS}/etc/network/interfaces.d/ifcfg-${boot_dev}"
ilog "Creating manual mgmt ${ifcfg_file}"
cat << EOF > ${ifcfg_file}
auto ${boot_dev}
iface ${boot_dev} ${boot_address_family} manual
address ${mgmt_ip}
netmask ${mgmt_nm}
gateway ${mgmt_gw}
post-up echo 0 > /proc/sys/net/ipv6/conf/${boot_dev}/autoconf; echo 0 > /proc/sys/net/ipv6/conf/${boot_dev}/accept_ra; echo 0 > /proc/sys/net/ipv6/conf/${boot_dev}/accept_redirects
EOF
ifcfg_file="${IMAGE_ROOTFS}/etc/network/interfaces.d/ifcfg-vlan${mgmt_vlan}"
ilog "Creating static mgmt vlan ${ifcfg_file}"
cat << EOF > ${ifcfg_file}
auto vlan${mgmt_vlan}
iface vlan${mgmt_vlan} ${boot_address_family} static
address ${mgmt_ip}
netmask ${mgmt_nm}
gateway ${mgmt_gw}
vlan-raw-device ${boot_dev}
post-up echo 0 > /proc/sys/net/ipv6/conf/vlan${mgmt_vlan}/autoconf; echo 0 > /proc/sys/net/ipv6/conf/vlan${mgmt_vlan}/accept_ra; echo 0 > /proc/sys/net/ipv6/conf/vlan${mgmt_vlan}/accept_redirects
EOF
# Reject DHCPOFFER from DHCP server that doesn't send
# wrs-install-uuid option
echo "require wrs-install-uuid;" >>/etc/dhcp/dhclient.conf
echo "require dhcp6.wrs-install-uuid;" >>/etc/dhcp/dhclient.conf
# set the same DUID-LL IDs (see RFC 8415) that will be used during regular operations
echo "send dhcp6.client-id = concat(00:03:00, hardware);" >>/etc/dhcp/dhclient.conf
echo "send dhcp-client-identifier = concat(00:03:00, hardware);" >>/etc/dhcp/dhclient.conf
# Bring up the boot vlan so that a dhcp lease is acquired and an address is
# setup prior to the post-install reboot. This is so that the timing of the IP
# address allocation is similar to how normal/non-pxe installation works.
boot_iface=vlan${mgmt_vlan}
ilog "boot_iface=vlan${mgmt_vlan}"
ilog "boot_address_family: ${boot_address_family}"
dhclient_family=$([[ ${boot_address_family} == "inet" ]] && echo -4 || echo -6)
ilog "dhclient_family: ${dhclient_family}"
ilog "ip link add link ${boot_dev} name ${boot_iface} type vlan id ${mgmt_vlan}"
ip link add link ${boot_dev} name ${boot_iface} type vlan id ${mgmt_vlan}
ilog "ip link set up dev ${boot_iface}"
ip link set up dev ${boot_iface}
timeout_value=60
dhclient_request="/usr/sbin/dhclient $dhclient_family $boot_iface"
ilog "timeout ${timeout_value} ${dhclient_request}"
timeout ${timeout_value} ${dhclient_request}
rc=${?}
if [ ${rc} -ne 0 ] ; then
wlog "timeout ${timeout_value} ${dhclient_request} failed ; rc:${rc}"
else
ilog "${dhclient_request} complete"
fi
fi
# Clean machine-id file, it needs to be generated after install.
# It must be unique per installation because it is used to generate
# random MACs for SR-IOV VFs, among other resources.
find / -name machine-id | xargs rm -fv
true
%end
##########################################################################
%post --interpreter=/bin/bash --nochroot
HOOK_LABEL="post_nochroot"
. /tmp/lat/ks_functions.sh
ilog "*********************************************************"
ilog "*** Post Nochroot - Kickstart Finalize Install UUID ***"
ilog "*********************************************************"
# Create a uuid specific to this installation
# install_uuid under /var needs to match what is written to /etc/platform/platform.conf
# When instflux=0 (/var not on a dedicated fluxdata partition)
# When instflux=1 (/var is part of the two different sysroot deployments).
# Therefore check if the file has been written and use that, otherwise generate it
feed="${IMAGE_ROOTFS}/var/www/pages/feed/rel-xxxPLATFORM_RELEASExxx"
[ ! -d "${feed}" ] && mkdir -p -m 0755 ${feed}
$(is_system_node_install)
if [ $? -ne 0 ] ; then
if [ -e "${LAT_DIR}/INSTALL_UUID" ]; then
INSTALL_UUID=$(< "${LAT_DIR}/INSTALL_UUID")
ilog "Using saved install uuid ${INSTALL_UUID}"
else
INSTALL_UUID=`uuidgen`
ilog "Generated install uuid ${INSTALL_UUID}"
echo "${INSTALL_UUID}" > ${LAT_DIR}/INSTALL_UUID
fi
ilog "... adding to ${feed}"
echo ${INSTALL_UUID} > ${feed}/install_uuid
ilog "... adding to ${PLATFORM_CONF}"
update_platform_conf "INSTALL_UUID=${INSTALL_UUID}"
else
pxeurl=$(echo $insturl | sed -e s/ostree_repo//)
# Check for noverifyssl
if grep -q noverifyssl /proc/cmdline; then
NOVERIFYSSL_WGET_OPT="--no-check-certificate"
else
NOVERIFYSSL_WGET_OPT=""
fi
ilog "Fetching install uuid from ${pxeurl}"
if [ "${controller}" = true ] ; then
ilog "... adding to ${feed}"
pushd ${feed} > /dev/null
else
# must be a worker or storage node install
pushd /tmp > /dev/null
# There is no feed function on non-controller nodes
# TODO: Prevent feed dir packaging on non-controller nodes
rm -rf ${IMAGE_ROOTFS}/var/www/pages/feed
fi
if [ ! -e ./install_uuid ] ; then
wget ${NOVERIFYSSL_WGET_OPT} ${pxeurl}/install_uuid -o /${LAT_DIR}/wget_install_uuid.log
[ $? -ne 0 ] && report_failure_with_msg "Failed to fetch install_uuid from pxeboot server"
fi
if [ -e ./install_uuid ] ; then
INSTALL_UUID=$(cat install_uuid)
else
report_failure_with_msg "Failed to find fetched install_uuid file"
fi
popd > /dev/null
ilog "... adding to ${PLATFORM_CONF}"
update_platform_conf "INSTALL_UUID=${INSTALL_UUID}"
fi
true
%end
##########################################################################
%post --interpreter=/bin/bash --nochroot
HOOK_LABEL="post_nochroot"
. /tmp/lat/ks_functions.sh
ilog "****************************************************"
ilog "*** Post - Upgrade Support ***"
ilog "****************************************************"
# INSTALL_UUID was written into platform.conf in the Post - Kickstart Finalize Install UUID section
if [[ "${insturl}" == *"pxecontroller"* && "${insturl}" == *"http"* ]] ; then
http_port=$(echo $(cat /proc/cmdline |xargs -n1 echo |grep '^insturl=' | sed -r 's#^[^/]*://[^/]*:([0-9]*)/.*#\1#'))
else
http_port=8080
fi
cd ${IMAGE_ROOTFS}/var/www/pages
# Sync software repository
feed_url=http://pxecontroller:${http_port}/feed/
sw_release="xxxPLATFORM_RELEASExxx"
hostname="hostname"
if [ "$(curl -sf http://pxecontroller:6385/v1/upgrade/${hostname}/upgrade_in_progress 2>/dev/null)" = "true" ]; then
ilog "System upgrade in progress"
ilog "Mirroring software repository (may take several minutes)..."
wget --recursive --no-parent --no-host-directories --no-clobber --reject 'index.html*' --reject '*.log' \
-o /${LAT_DIR}/wget_sw_repo.log --exclude-directories=/feed/rel-${sw_release} ${feed_url} \
|| report_failure_with_msg "Mirroring software repository failed"
# Check whether a second release is installed
CURRENT_REL_DIR=rel-${sw_release}
OTHER_REL_DIR=$(find ${IMAGE_ROOTFS}/var/www/pages/feed/* -maxdepth 0 -type d ! -name *${sw_release}*)
OTHER_REL_VERSION=$(basename "${OTHER_REL_DIR}")
ilog "Installing pxeboot files for release ${OTHER_REL_DIR}"
mkdir -p ${IMAGE_ROOTFS}/var/pxeboot/${OTHER_REL_VERSION} \
|| report_failure_with_msg "Failed to create /var/pxeboot/${OTHER_REL_VERSION}"
cp -rp ${OTHER_REL_DIR}/kickstart/kickstart.cfg ${OTHER_REL_DIR}/ \
|| report_failure_with_msg "Failed to copy kickstart.cfg for to ${OTHER_REL_DIR}"
cp -rp ${OTHER_REL_DIR}/pxeboot/bzImage* ${IMAGE_ROOTFS}/var/pxeboot/${OTHER_REL_VERSION} \
|| report_failure_with_msg "Failed to copy pxeboot bzImage files for to /var/pxeboot/${OTHER_REL_VERSION}"
cp -rp ${OTHER_REL_DIR}/pxeboot/initrd* ${IMAGE_ROOTFS}/var/pxeboot/${OTHER_REL_VERSION} \
|| report_failure_with_msg "Failed to copy pxeboot initrd files for to /var/pxeboot/${OTHER_REL_VERSION}"
cp -rp ${OTHER_REL_DIR}/pxeboot/pxelinux.cfg.files/* ${IMAGE_ROOTFS}/var/pxeboot/pxelinux.cfg.files/ \
|| report_failure_with_msg "Failed to copy pxeboot pxelinux.cfg files for to /var/pxeboot/${OTHER_REL_VERSION}"
cp -rp ${OTHER_REL_DIR}/upgrades/pxeboot-update-${OTHER_REL_VERSION:4}.sh ${IMAGE_ROOTFS}/etc/ \
|| report_failure_with_msg "Failed to copy pxeboot-update-${OTHER_REL_VERSION:4}.sh to /etc/"
chmod 755 ${IMAGE_ROOTFS}/etc/pxeboot-update-${OTHER_REL_VERSION:4}.sh \
|| report_failure_with_msg "Failed to chmod 755 /etc/pxeboot-update-${OTHER_REL_VERSION:4}.sh"
fi
true
%end
##########################################################################
%post --interpreter=/bin/bash
HOOK_LABEL="post"
. /tmp/lat/ks_functions.sh
ilog "****************************************"
ilog "*** Post - Log Filesystem Setup ***"
ilog "****************************************"
display_volume_info "final"
true
%end
##########################################################################
%post --interpreter=/bin/bash --nochroot
HOOK_LABEL="post_nochroot"
. /tmp/lat/ks_functions.sh
ilog "***********************************************************"
ilog "*** Post Nochroot - Restage OSTree repo ***"
ilog "*** - Save Install Scripts and Logs ***"
ilog "***********************************************************"
ilog "IMAGE_ROOTFS=${IMAGE_ROOTFS}"
get_variable "ostree_repo_fetched"
OSTREE_REPO_FETCHED=$?
# Check for noverifyssl
if grep -q noverifyssl /proc/cmdline; then
NOVERIFYSSL_WGET_OPT="--no-check-certificate"
else
NOVERIFYSSL_WGET_OPT=""
fi
# Fetch ostree
sw_release="xxxPLATFORM_RELEASExxx" # updated by the build
if [ "${controller}" = true ] ; then
# -1 is all commits, positive number is that number of last commits
commits="--depth=-1"
pull_options="${commits} --mirror"
pxeboot="${IMAGE_ROOTFS}/var/pxeboot"
feed="${IMAGE_ROOTFS}/var/www/pages/feed/rel-${sw_release}"
repo="${feed}/ostree_repo"
mkdir -p "${repo}"
mkdir -p "${feed}"
if [ ${OSTREE_REPO_FETCHED} -eq 0 ] ; then
if is_usb_install -eq 0 ; then
ilog "Stage ostree_repo from USB device to ${repo}"
ostree --repo=${repo} init --mode=archive
ostree --repo=${repo} remote add ${instbr} file:///instboot/ostree_repo
ostree --repo=${repo} pull ${pull_options} ${instbr}:${instbr}
# Check if this is a prestage iso.If yes, then
# copy the ostree_repo to the backup directory.
if is_prestage -eq 0 ; then
ilog "Prestage operation: copying repo to /opt/platform-backup/${sw_release}"
backup_device=/dev/disk/by-partlabel/platform_backup
backup_mount=/tmp/platform-backup
backup_mount_release="${backup_mount}/${sw_release}"
ilog "Temporary backup mount: ${backup_mount}, release: ${backup_mount_release}"
mkdir -p "${backup_mount}"
mount "${backup_device}" "${backup_mount}"
rc=$?
if [ ${rc} -ne 0 ]; then
report_failure_with_msg "Unable to mount ${backup_device} on ${backup_mount} [rc=${rc}]"
fi
ilog "Copying repo to ${backup_mount_release}"
mkdir "${backup_mount_release}"
rc=$?
if [ ${rc} -ne 0 ]; then
report_failure_with_msg "Unable to create ${backup_mount_release} directory [rc=${rc}]"
fi
cp -a "${repo}" "${backup_mount_release}"
rc=$?
if [ ${rc} -ne 0 ]; then
report_failure_with_msg "Unable to copy repo to /opt/platform-backup/${sw_release} [rc=${rc}]"
fi
# The summary file is not transferred on an ostree pull, so we need to
# regenerate the checksum here based on the new local repo contents
ilog "Calculating new checksum for prestaged ${backup_mount_release}/ostree_repo"
pushd "${backup_mount_release}" > /dev/null
find ostree_repo -type f -exec md5sum {} + | LC_ALL=C sort | md5sum | awk '{ print $1; }' > .ostree_repo_checksum
ilog "Calculated checksum: $(cat .ostree_repo_checksum)"
popd > /dev/null
if [ -e "/instboot/opt/platform-backup/${sw_release}" ]; then
ilog "Copying images and patches to ${backup_mount_release}"
rsync -a /instboot/opt/platform-backup/${sw_release}/ ${backup_mount_release}
rc=$?
if [ ${rc} -ne 0 ]; then
report_failure_with_msg "Unable to copy images from /instboot to /opt/platform-backup/${sw_release} [rc=${rc}]"
fi
fi
umount "${backup_mount}"
fi
else
ilog "Stage ostree_repo from previous /sysroot pull to ${repo}"
mv -f /sysroot/var/www/pages/feed/rel-${sw_release}/ostree_repo ${IMAGE_ROOTFS}/var/www/pages/feed/rel-${sw_release}/
fi
# This is used by patching.
# Set ostree remote to the local install feed
file_feed="file:///var/www/pages/feed/rel-${sw_release}/ostree_repo/"
feed_branch="starlingx"
ilog "Replacing ostree sysroot remote with: ${file_feed} ${feed_branch}"
ostree --repo=/sysroot/ostree/repo remote delete ${instname}
ostree --repo=/sysroot/ostree/repo remote add ${instname} ${file_feed} ${feed_branch}
# Set feed ostree remote "starlingx" to point to active controller's feed ostree repo
feed_remote_name="starlingx"
feed_remote_url="http://controller:8080/feed/rel-${sw_release}/ostree_repo/"
ilog "Replacing ostree feed remote with: ${feed_remote_url} ${feed_remote_name}"
ostree --repo=${repo} remote delete ${feed_remote_name}
ostree --repo=${repo} remote add ${feed_remote_name} ${feed_remote_url} ${feed_branch}
# This fetch is only needed once because the repo is stored in /var
set_variable "ostree_repo_fetched"
####################################################################
# Fetch and add efi.img to /var/pxeboot
#####################################################################
mkdir -p "${pxeboot}/EFI/BOOT"
# handle USB install
if is_usb_install -eq 0 ; then
cp -a /instboot/efi.img ${pxeboot}
# handle pxeboot install
else
pxeurl=$(echo $insturl | sed -e s/ostree_repo//)
# Fetch and stage the efi.img
ilog "Fetch efi.img from ${pxeurl} to ${pxeboot}"
pushd ${pxeboot} > /dev/null
for f in efi.img ; do
ilog "... fetching ${f} to ${pxeboot}"
wget ${NOVERIFYSSL_WGET_OPT} ${pxeurl}/${f} -o /${LAT_DIR}/wget.tmp
[ $? -ne 0 ] && report_failure_with_msg "Failed to get ${pxeurl}/${f}"
cat /${LAT_DIR}/wget.tmp >> /${LAT_DIR}/wget_pxeboot_setup.log
# also copy to the feeds
ilog "... copying ${f} to ${feed}"
cp -a ${f} ${feed}
done
popd > /dev/null
[ -e /${LAT_DIR}/wget.tmp ] && rm -f /${LAT_DIR}/wget.tmp
fi
# Save and override the LAT grub menu by creating a link to the default
# provisioning mac based grub menu.
pushd ${pxeboot}/EFI/BOOT > /dev/null
if [ ! -L grub.cfg ] ; then
if [ -e grub.cfg ] ; then
mv grub.cfg grub.cfg.lat
fi
ln -s ../../pxelinux.cfg/grub.cfg
fi
popd > /dev/null
fi
else
# This is used by patching.
# For non-controller system node installs (worker/storage) we need to
# update the ostree remote to be the url to the pxecontroller's ostree_repo
# and set the remote debian branches to starlingx.
feed_branch="starlingx"
feed_remote_url="http://controller:8080/feed/rel-${sw_release}/ostree_repo/"
ilog "Replacing ostree sysroot remote with: ${feed_branch}"
ostree --repo=/sysroot/ostree/repo remote delete ${instname}
ostree --repo=/sysroot/ostree/repo remote add ${instname} ${feed_remote_url} ${feed_branch}
fi
# Verify Patched iso
if [ -d "/instboot/patches" ]; then
ilog "Prepatched iso"
ilog "Creating USM metadata directories"
mkdir -p ${IMAGE_ROOTFS}/var/rootdirs/opt/software/metadata/{committed,available,deployed}
cp -a /instboot/patches/* ${IMAGE_ROOTFS}/var/rootdirs/opt/software/metadata/deployed/
else
# Prepatch iso pxeboot
patches_url="${insturl/ostree_repo/patches}"
wget ${NOVERIFYSSL_WGET_OPT} -q --spider ${patches_url}/
if [ $? -eq 0 ]; then
ilog "Prepatched iso from pxeboot"
ilog "Creating USM metadata directories"
mkdir -p ${IMAGE_ROOTFS}/var/rootdirs/opt/software/metadata/{committed,available,deployed}
cd ${IMAGE_ROOTFS}/var/rootdirs/opt/software/metadata/deployed
wget ${NOVERIFYSSL_WGET_OPT} --recursive --no-parent --no-host-directories --no-clobber \
--accept='*.xml' -o /${LAT_DIR}/wget_prepatch_metadata.log -nd ${patches_url}/
ilog "Metadata files copied"
fi
fi
# Copy current release scripts to software directory
highest_patch_version="0"
for metadata_file in /instboot/patches/*; do
patch_version=$(grep "sw_version" $metadata_file | cut -d"." -f3 | cut -d'<' -f1)
if [ $patch_version -gt $highest_patch_version ]; then
highest_patch_version=$patch_version;
fi;
done;
versioned_dir="/opt/software/rel-${sw_release}.${highest_patch_version}/bin"
ilog "Creating versioned USM scripts directory $versioned_dir for current release"
mkdir -p "${IMAGE_ROOTFS}/var/rootdirs/${versioned_dir}"
cp -r /instboot/upgrades/software-deploy/* ${IMAGE_ROOTFS}/var/rootdirs/${versioned_dir}
# Save the install scripts and kickstart logs
mount /dev/mapper/cgts--vg-log--lv "${IMAGE_ROOTFS}/${LOG_DIR}"
if [ ${?} -ne 0 ] ; then
elog "Failed to mount /dev/mapper/cgts--vg-log--lv"
else
if [ -e "${IMAGE_ROOTFS}/${LOG_DIR}" ]; then
cp -a /${LAT_DIR} ${IMAGE_ROOTFS}/${LOG_DIR}
cp /install ${IMAGE_ROOTFS}/${LOG_DIR}/lat
cp /lat-installer* ${IMAGE_ROOTFS}/${LOG_DIR}/lat
ilog "Saved installer data to ${IMAGE_ROOTFS}/${LOG_DIR}"
else
wlog "Could not save installer data"
fi
umount "${IMAGE_ROOTFS}/${LOG_DIR}"
fi
true
%end
##########################################################################
%post --interpreter=/bin/bash --nochroot
HOOK_LABEL="post_nochroot"
. /tmp/lat/ks_functions.sh
# This section needs to be removed when solutions are implemented
ilog "******************************************************************"
ilog "*** Post Nochroot - Workarounds for enabling integration ***"
ilog "******************************************************************"
# Workaround for enabling swacts on AIO-DX
# Workaround for enabling compute unlocks
# Launchpad: #1983580
[ -f ${IMAGE_ROOTFS}/var/lib/dpkg/triggers/Unincorp ] && rm ${IMAGE_ROOTFS}/var/lib/dpkg/triggers/Unincorp
true
%end
##########################################################################
%post --interpreter=/bin/bash --nochroot
HOOK_LABEL="post_nochroot"
. /tmp/lat/ks_functions.sh
# This needs to update all available ostree based rootfs
ilog "******************************************************"
ilog "*** Post Nochroot - Set up filesystem access ***"
ilog "******************************************************"
if [ "${controller}" = true ] ; then
mkdir -p ${IMAGE_ROOTFS}/var/rootdirs/opt/platform-backup
echo -e "LABEL=platform_backup\t/var/rootdirs/opt/platform-backup\text4\tdefaults\t1 2" >> ${IMAGE_ROOTFS}/etc/fstab
elif [ "${worker}" = true ] ; then
mkdir -p ${IMAGE_ROOTFS}/var/rootdirs/opt/platform
echo -e "controller-platform-nfs:/opt/platform\t/opt/platform\tnfs\ttimeo=30,udp,rsize=1024,wsize=1024,_netdev 0 0" >> ${IMAGE_ROOTFS}/etc/fstab
fi
mkdir -p ${IMAGE_ROOTFS}/var/rootdirs/scratch
echo -e "/dev/mapper/cgts--vg-scratch--lv\t/var/rootdirs/scratch\text4\tdefaults\t1 2" >> ${IMAGE_ROOTFS}/etc/fstab
mkdir -p ${IMAGE_ROOTFS}/var/log
echo -e "/dev/mapper/cgts--vg-log--lv\t/var/log\text4\tdefaults\t1 2" >> ${IMAGE_ROOTFS}/etc/fstab
# Report and update the lvm config for the sysroot. Remove preceeding tab and
# convert to spaces to align with puppet expectations
LV_PERSISTENT_ROOTDISK=$(get_persistent_disk ${LV_ROOTDISK})
log_lvm_conf "SysRoot Initial" ${IMAGE_ROOTFS}/etc/lvm/lvm.conf
ilog ""
ilog "Update the LVM global filter to enable the initial physical volume only: ${LV_PERSISTENT_ROOTDISK}"
ilog ""
sed -i "s@^\(\s*\)# global_filter = \[.*@ global_filter = [ \"a|${LV_PERSISTENT_ROOTDISK}|\", \"r|.*|\" ]@" ${IMAGE_ROOTFS}/etc/lvm/lvm.conf
log_lvm_conf "SysRoot Updated" ${IMAGE_ROOTFS}/etc/lvm/lvm.conf
# Create first_boot flag
touch ${IMAGE_ROOTFS}/etc/platform/.first_boot
# Create first controller flag
$(is_system_node_install)
if [ $? -ne 0 ] ; then
touch ${IMAGE_ROOTFS}/etc/platform/.first_controller
fi
true
%end
##########################################################################
%post --interpreter=/bin/bash --nochroot
HOOK_LABEL="post_nochroot"
. /tmp/lat/ks_functions.sh
# This needs to update all available ostree based rootfs
ilog "****************************************************************"
ilog "*** Post Nochroot - Set up package links per node type ***"
ilog "****************************************************************"
ilog "IMAGE_ROOTFS=${IMAGE_ROOTFS}"
if [ ! "${controller}" = true -a "${worker}" = true ] ; then
ilog "Setting up ${TRAIT__WORKER} package file links"
ln -s /etc/goenabled.d/config_goenabled_check.sh.worker ${IMAGE_ROOTFS}/etc/goenabled.d/config_goenabled_check.sh
ln -s /dev/null ${IMAGE_ROOTFS}/etc/systemd/system/controllerconfig.service
ln -s /dev/null ${IMAGE_ROOTFS}/etc/systemd/system/storageconfig.service
elif [ "${storage}" = true ] ; then
ilog "Setting up ${TRAIT__STORAGE} package file links"
ln -s /etc/goenabled.d/config_goenabled_check.sh.storage ${IMAGE_ROOTFS}/etc/goenabled.d/config_goenabled_check.sh
ln -s /dev/null ${IMAGE_ROOTFS}/etc/systemd/system/controllerconfig.service
ln -s /dev/null ${IMAGE_ROOTFS}/etc/systemd/system/workerconfig.service
elif [ "${controller}" = true ] ; then
ilog "Setting up ${TRAIT__CONTROLLER} package file links"
ln -s /etc/goenabled.d/config_goenabled_check.sh.controller ${IMAGE_ROOTFS}/etc/goenabled.d/config_goenabled_check.sh
ln -s /dev/null ${IMAGE_ROOTFS}/etc/systemd/system/workerconfig.service
ln -s /dev/null ${IMAGE_ROOTFS}/etc/systemd/system/storageconfig.service
fi
chmod 700 ${IMAGE_ROOTFS}/etc/goenabled.d/config_goenabled_check.sh
if [[ ! -d "${IMAGE_ROOTFS}/etc/pmon.d" ]]; then
wlog "Directory ${IMAGE_ROOTFS}/etc/pmon.d/ is missing, creating it now"
mkdir ${IMAGE_ROOTFS}/etc/pmon.d
fi
if [ "${controller}" = true ] ; then
ilog "Setting up pmon files for ${TRAIT__CONTROLLER} and/or ${TRAIT__CONTROLLER} side of ${SYSTEM_TYPE__AIO}"
ln -s /usr/share/starlingx/pmon.d/acpid.conf ${IMAGE_ROOTFS}/etc/pmon.d/acpid.conf
ln -s /usr/share/starlingx/pmon.d/containerd.conf ${IMAGE_ROOTFS}/etc/pmon.d/containerd.conf
ln -s /usr/share/starlingx/pmon.d/docker.conf ${IMAGE_ROOTFS}/etc/pmon.d/docker.conf
ln -s /usr/share/starlingx/pmon.d/fm-api.conf ${IMAGE_ROOTFS}/etc/pmon.d/fm-api.conf
ln -s /usr/share/starlingx/pmon.d/fsmon.conf ${IMAGE_ROOTFS}/etc/pmon.d/fsmon.conf
ln -s /usr/share/starlingx/pmon.d/hbsAgent.conf ${IMAGE_ROOTFS}/etc/pmon.d/hbsAgent.conf
ln -s /usr/share/starlingx/pmon.d/hbsClient.conf ${IMAGE_ROOTFS}/etc/pmon.d/hbsClient.conf
ln -s /usr/share/starlingx/pmon.d/lmon.conf ${IMAGE_ROOTFS}/etc/pmon.d/lmon.conf
ln -s /usr/share/starlingx/pmon.d/logmgmt ${IMAGE_ROOTFS}/etc/pmon.d/logmgmt
ln -s /usr/share/starlingx/pmon.d/mtcClient.conf ${IMAGE_ROOTFS}/etc/pmon.d/mtcClient.conf
ln -s /usr/share/starlingx/pmon.d/mtcalarm.conf ${IMAGE_ROOTFS}/etc/pmon.d/mtcalarm.conf
ln -s /usr/share/starlingx/pmon.d/mtclogd.conf ${IMAGE_ROOTFS}/etc/pmon.d/mtclogd.conf
ln -s /usr/share/starlingx/pmon.d/sm-api.conf ${IMAGE_ROOTFS}/etc/pmon.d/sm-api.conf
ln -s /usr/share/starlingx/pmon.d/sm-eru.conf ${IMAGE_ROOTFS}/etc/pmon.d/sm-eru.conf
ln -s /usr/share/starlingx/pmon.d/sm.conf ${IMAGE_ROOTFS}/etc/pmon.d/sm.conf
ln -s /usr/share/starlingx/pmon.d/sshd.conf ${IMAGE_ROOTFS}/etc/pmon.d/sshd.conf
ln -s /usr/share/starlingx/pmon.d/sssd.conf ${IMAGE_ROOTFS}/etc/pmon.d/sssd.conf
ln -s /usr/share/starlingx/pmon.d/sw-patch-agent.conf ${IMAGE_ROOTFS}/etc/pmon.d/sw-patch-agent.conf
ln -s /usr/share/starlingx/pmon.d/sw-patch-controller-daemon.conf ${IMAGE_ROOTFS}/etc/pmon.d/sw-patch-controller-daemon.conf
ln -s /usr/share/starlingx/pmon.d/sysinv-agent.conf ${IMAGE_ROOTFS}/etc/pmon.d/sysinv-agent.conf
ln -s /usr/share/starlingx/pmon.d/syslog-ng.conf ${IMAGE_ROOTFS}/etc/pmon.d/syslog-ng.conf
ln -s /usr/share/starlingx/pmon.d/luks.conf ${IMAGE_ROOTFS}/etc/pmon.d/luks.conf
ln -s /usr/share/starlingx/pmon.d/ipsec-server.conf ${IMAGE_ROOTFS}/etc/pmon.d/ipsec-server.conf
fi
if [ "${worker}" = true ] ; then
ilog "Setting up pmon files for ${TRAIT__WORKER} and/or ${TRAIT__WORKER} side of ${SYSTEM_TYPE__AIO}"
ln -s /usr/share/starlingx/pmon.d/acpid.conf ${IMAGE_ROOTFS}/etc/pmon.d/acpid.conf
ln -s /usr/share/starlingx/pmon.d/containerd.conf ${IMAGE_ROOTFS}/etc/pmon.d/containerd.conf
ln -s /usr/share/starlingx/pmon.d/docker.conf ${IMAGE_ROOTFS}/etc/pmon.d/docker.conf
ln -s /usr/share/starlingx/pmon.d/fsmon.conf ${IMAGE_ROOTFS}/etc/pmon.d/fsmon.conf
ln -s /usr/share/starlingx/pmon.d/hbsClient.conf ${IMAGE_ROOTFS}/etc/pmon.d/hbsClient.conf
ln -s /usr/share/starlingx/pmon.d/isolcpu_plugin.conf ${IMAGE_ROOTFS}/etc/pmon.d/isolcpu_plugin.conf
ln -s /usr/share/starlingx/pmon.d/lmon.conf ${IMAGE_ROOTFS}/etc/pmon.d/lmon.conf
ln -s /usr/share/starlingx/pmon.d/logmgmt ${IMAGE_ROOTFS}/etc/pmon.d/logmgmt
ln -s /usr/share/starlingx/pmon.d/mtcClient.conf ${IMAGE_ROOTFS}/etc/pmon.d/mtcClient.conf
ln -s /usr/share/starlingx/pmon.d/mtcalarm.conf ${IMAGE_ROOTFS}/etc/pmon.d/mtcalarm.conf
ln -s /usr/share/starlingx/pmon.d/mtclogd.conf ${IMAGE_ROOTFS}/etc/pmon.d/mtclogd.conf
ln -s /usr/share/starlingx/pmon.d/sm-eru.conf ${IMAGE_ROOTFS}/etc/pmon.d/sm-eru.conf
ln -s /usr/share/starlingx/pmon.d/sshd.conf ${IMAGE_ROOTFS}/etc/pmon.d/sshd.conf
ln -s /usr/share/starlingx/pmon.d/sssd.conf ${IMAGE_ROOTFS}/etc/pmon.d/sssd.conf
ln -s /usr/share/starlingx/pmon.d/sw-patch-agent.conf ${IMAGE_ROOTFS}/etc/pmon.d/sw-patch-agent.conf
ln -s /usr/share/starlingx/pmon.d/sysinv-agent.conf ${IMAGE_ROOTFS}/etc/pmon.d/sysinv-agent.conf
ln -s /usr/share/starlingx/pmon.d/syslog-ng.conf ${IMAGE_ROOTFS}/etc/pmon.d/syslog-ng.conf
fi
if [ "${storage}" = true ] ; then
ilog "Setting up pmon files for ${TRAIT__STORAGE} and/or ${TRAIT__STORAGE} side of ${SYSTEM_TYPE__AIO}"
ln -s /usr/share/starlingx/pmon.d/acpid.conf ${IMAGE_ROOTFS}/etc/pmon.d/acpid.conf
ln -s /usr/share/starlingx/pmon.d/containerd.conf ${IMAGE_ROOTFS}/etc/pmon.d/containerd.conf
ln -s /usr/share/starlingx/pmon.d/docker.conf ${IMAGE_ROOTFS}/etc/pmon.d/docker.conf
ln -s /usr/share/starlingx/pmon.d/fsmon.conf ${IMAGE_ROOTFS}/etc/pmon.d/fsmon.conf
ln -s /usr/share/starlingx/pmon.d/hbsClient.conf ${IMAGE_ROOTFS}/etc/pmon.d/hbsClient.conf
ln -s /usr/share/starlingx/pmon.d/lmon.conf ${IMAGE_ROOTFS}/etc/pmon.d/lmon.conf
ln -s /usr/share/starlingx/pmon.d/logmgmt ${IMAGE_ROOTFS}/etc/pmon.d/logmgmt
ln -s /usr/share/starlingx/pmon.d/mtcClient.conf ${IMAGE_ROOTFS}/etc/pmon.d/mtcClient.conf
ln -s /usr/share/starlingx/pmon.d/mtcalarm.conf ${IMAGE_ROOTFS}/etc/pmon.d/mtcalarm.conf
ln -s /usr/share/starlingx/pmon.d/mtclogd.conf ${IMAGE_ROOTFS}/etc/pmon.d/mtclogd.conf
ln -s /usr/share/starlingx/pmon.d/sm-eru.conf ${IMAGE_ROOTFS}/etc/pmon.d/sm-eru.conf
ln -s /usr/share/starlingx/pmon.d/sshd.conf ${IMAGE_ROOTFS}/etc/pmon.d/sshd.conf
ln -s /usr/share/starlingx/pmon.d/sssd.conf ${IMAGE_ROOTFS}/etc/pmon.d/sssd.conf
ln -s /usr/share/starlingx/pmon.d/sw-patch-agent.conf ${IMAGE_ROOTFS}/etc/pmon.d/sw-patch-agent.conf
ln -s /usr/share/starlingx/pmon.d/sysinv-agent.conf ${IMAGE_ROOTFS}/etc/pmon.d/sysinv-agent.conf
ln -s /usr/share/starlingx/pmon.d/syslog-ng.conf ${IMAGE_ROOTFS}/etc/pmon.d/syslog-ng.conf
fi
if [ -e "/instboot/ks-addon.cfg" ]; then
ilog "Running kickstart addon script"
source /instboot/ks-addon.cfg
rc=$?
if [ "${rc}" -ne 0 ]; then
ilog "Addon script ks-addon.cfg exited with [rc=${rc}]"
fi
fi
true
%end