metal/kickstart/files/kickstart.cfg
Eric MacDonald 5db11d9fe6 Disable Route Advertisement during install
Route Advertisement, also known as 'ra', needs to be disabled during
node installation or ostree pull failures, although rare, can happen.

This update ensures that IPV6 autoconf, accept_ra and accept_redirect
settings are disabled on all interfaces during install.

Test Plan:

PASS: Verify build and install ISO
PASS: Verify controller-0 usb install
PASS: Verify controller-0 network install
PASS: Verify system node network install
PASS: Verify redfish subcloud install
PASS: In all cases above verify update logging
      ... /var/log/lat/kickstart.log
      ... /var/log/lat/miniboot.log

Closes-Bug: 2089298
Change-Id: Ia9978d3df5a4c96d9615fe57701e78721e0c62c5
Signed-off-by: Eric MacDonald <eric.macdonald@windriver.com>
2024-11-22 14:09:02 +00:00

3486 lines
134 KiB
INI

#
# Copyright (c) 2022-2024 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 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.
#
############################################################################
#
# Developer Note:
#
# The Linux Assembly Tool parses this kickstart file which contains
# various hook segments that are syntactically delineated with
# statements that start with '%'.
# The example below shows the start and end syntax of a hook block.
#
# %post --interpreter=/bin/bash --nochroot
#
# <kickstart bash code goes here>
#
# %end
#
# Warning: If LAT detects a hook block syntax error it fails the
# install and renders it as a Permission error console output like this.
#
# ./lat-installer.sh: line 539:
# /tmp/lat/lat_post_nochroot_script/10_script: Permission denied
#
# This may occur if for example %end is miss spelled as %en or missing
# or if the last %end is not terminated with a Line Feed.
#
###########################################################################
# 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 : check_rc_with_msg
# Purpose : Check given return code, reporting failure if non-zero
# Parameters: \$1 is the exit code to check
# \$2 is the failure message string
# Return : Does not return if exit code is non-zero
########################################################################
function check_rc_with_msg {
local rc=\${1}
local msg=\${2}
if [ \${rc} -ne 0 ]; then
report_failure_with_msg "\${msg} [rc=\${rc}]"
fi
}
########################################################################
# 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 : enable_cloudinit
# Returns : true :0
# false:1
#########################################################################
function enable_cloudinit()
{
if grep -q 'cloud-init=enabled' /proc/cmdline; 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"
# Check if the disk is Rook Ceph OSD
fs_type=$(blkid -o value -s TYPE "${dev}")
if [ "${fs_type}" == "ceph_bluestore" ]; then
wlog "BlueStore OSD found on $dev, skipping wipe"
wipe_dev="false"
else
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
done
fi
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"
# Check if the disk is Rook Ceph OSD
# see https://github.com/rook/rook/blob/master/Documentation/Storage-Configuration/ceph-teardown.md#zapping-devices
fs_type=$(blkid -o value -s TYPE "${dev}")
if [ "${fs_type}" == "ceph_bluestore" ]; then
sgdisk --zap-all "${dev}"
wipefs -a "${dev}"
continue
fi
# 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
# Unverified GPG with kernel parameter instgpg!=1
# Verified GPG with kernel parameter instgpg=1
if grep -q 'instgpg=1' /proc/cmdline 2>/dev/null; then
gpg_option=""
else
# Tell LAT to enable --no-gpg-verify
export INSTGPG=0
gpg_option="--no-gpg-verify"
ilog "Enable LAT ${gpg_option} option to configure ostree for unverified GPG (gpg-verify=false)"
fi
#
# Disable IPV6 Route Advertisement during install if enabled
#
_autoconf=$(cat /proc/sys/net/ipv6/conf/all/autoconf)
_accept_ra=$(cat /proc/sys/net/ipv6/conf/all/accept_ra)
_accept_redirects=$(cat /proc/sys/net/ipv6/conf/all/accept_redirects)
ilog "IPV6 Route Advertisement settings : autoconf=${_autoconf}, accept_ra=${_accept_ra}, accept_redirects=${_accept_redirects} (all interfaces)"
change=false
if [ ${_autoconf} -ne 0 ] ; then
echo 0 > /proc/sys/net/ipv6/conf/all/autoconf
_autoconf=$(cat /proc/sys/net/ipv6/conf/all/autoconf)
change=true
fi
if [ ${_accept_ra} -ne 0 ] ; then
echo 0 > /proc/sys/net/ipv6/conf/all/accept_ra
_accept_ra=$(cat /proc/sys/net/ipv6/conf/all/accept_ra)
change=true
fi
if [ ${_accept_redirects} -ne 0 ] ; then
echo 0 > /proc/sys/net/ipv6/conf/all/accept_redirects
_accept_redirects=$(cat /proc/sys/net/ipv6/conf/all/accept_redirects)
change=true
fi
if [ "${change}" = true ] ; then
ilog "IPV6 Route Advertisement disabled : autoconf=${_autoconf}, accept_ra=${_accept_ra}, accept_redirects=${_accept_redirects}"
else
ilog "... no changes required"
fi
# 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"
config_file="${repo}/config"
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
echo "min-free-space-percent=0" >> "${config_file}"
if [ "${insturl}" = "file://NOT_SET" ] ; then
ilog "ostree_repo archive pull from file:///instboot/ostree_repo ${gpg_option}"
ostree --repo=${repo} remote add ${gpg_option} ${instbr} file:///instboot/ostree_repo
else
ilog "ostree_repo archive pull from ${insturl} ${gpg_option}"
ostree --repo=${repo} remote add ${gpg_option} ${instbr} ${insturl}
fi
ilog "Executing: ostree --repo=${repo} pull --depth=-1 --mirror ${instbr}:${instbr} ${gpg_option}"
MAX_TRIES=3
RETRY_WAIT=10
for try in 1 2 3
do
ostree --repo=${repo} pull --depth=-1 --mirror ${instbr}:${instbr}
rc=$?
if [ ${rc} -ne 0 ]; then
if [ ${try} -lt ${MAX_TRIES} ] ; then
wlog "ostree pull failed on try ${try} of ${MAX_TRIES}, rc=${rc} ; retry in ${RETRY_WAIT} seconds ..."
sleep ${RETRY_WAIT}
else
report_failure_with_msg "ostree pull failed, rc=${rc} ; max tries ${try} of ${MAX_TRIES}"
fi
else
break
fi
done
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 out-of-tree-drivers=
# option and if present propagate that to the disk boot kernel options.
CMDLINE=`cat /proc/cmdline`
param="out-of-tree-drivers"
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
# the mgmt floating address is running on the active controller, so it is our gateway
mgmt_gw=$(echo "${host_info}" | grep -o '"floating": "[^"]*' | cut -d'"' -f4)
if [ -z "${mgmt_gw}" -o "${mgmt_gw}" == "None" ] ; then
ilog "invalid mgmt_gw=${mgmt_gw}, extrapolate gateway from ${mgmt_ip}"
# this step is done only to have a valid address value for mgmt_gw, to not create
# parsing errors for ifupdown, no need to interrupt installation, as all traffic
# post install will run locally on the management network until puppet executes
# the manifest and with it the definitive network configuration is applied.
if [[ ${mgmt_ip} =~ ^([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}$ ]]; then
# IPv6
mgmt_gw=$(echo "${mgmt_ip}" | awk -F':' -v OFS=':' '{$NF=1}1')
else
# IPv4
mgmt_gw=$(echo "${mgmt_ip}" | awk -F'.' -v OFS='.' '{$NF=1}1')
fi
fi
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)
# due to the alias in the /etc/dnsmasq.conf:
# cname=controller,controller.internal
# An IPv4 scenario may answer "controller.internal." even for an IPv6 DIG
# for this reason, remove the "controller.internal." from the result
fqdn_pattern="controller.internal."
ipv6_addr=${ipv6_addr/${fqdn_pattern}/}
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
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"
config_file="${repo}/config"
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
echo "min-free-space-percent=0" >> "${config_file}"
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"
# All patch metadata xml files were presumably copied to /opt/software/metadata/deployed/ by the code above
# The assumption allows us not retrieve the xml files from the source again
for metadata_file in ${IMAGE_ROOTFS}/var/rootdirs/opt/software/metadata/deployed/*; 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}"
ilog "Creating USM upgrades directory in ${feed}"
mkdir -p "${feed}/upgrades"
if is_usb_install -eq 0 ; then
ilog "Copying USM software deploy scripts to ${IMAGE_ROOTFS}/var/rootdirs/${versioned_dir}"
cp -r /instboot/upgrades/software-deploy/* ${IMAGE_ROOTFS}/var/rootdirs/${versioned_dir}
ilog "Copying USM upgrades directory to ${feed}"
cp -r /instboot/upgrades/* ${feed}/upgrades
else
upgrade_url=$(echo ${insturl} | sed -e 's/ostree_repo/upgrades/g')
ilog "Getting USM upgrades directory from ${upgrade_url}"
wget ${NOVERIFYSSL_WGET_OPT} -q --spider ${upgrade_url}/
if [ $? -eq 0 ]; then
ilog "Downloading USM upgrades directory from ${upgrade_url}"
cd ${feed}/upgrades
wget ${NOVERIFYSSL_WGET_OPT} -r -np -nH --cut-dirs=3 -R "index.html*" \
${upgrade_url}/ -o /${LAT_DIR}/wget_usm_upgrades.log
ilog "USM upgrades directory download complete"
chmod 755 ./software-deploy/*
ilog "The file permissions in the ${feed}/upgrades/software-deploy/ directory are configured to 755."
ilog "Copy software-deploy directory to ${IMAGE_ROOTFS}/var/rootdirs/${versioned_dir}"
cp -r ${feed}/upgrades/software-deploy/* ${IMAGE_ROOTFS}/var/rootdirs/${versioned_dir}
ilog "Copy software-deploy directory complete"
fi
fi
# 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
ln -s /usr/share/starlingx/pmon.d/software-controller-daemon.conf ${IMAGE_ROOTFS}/etc/pmon.d/software-controller-daemon.conf
ln -s /usr/share/starlingx/pmon.d/software-agent.conf ${IMAGE_ROOTFS}/etc/pmon.d/software-agent.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
ln -s /usr/share/starlingx/pmon.d/software-agent.conf ${IMAGE_ROOTFS}/etc/pmon.d/software-agent.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
ln -s /usr/share/starlingx/pmon.d/software-agent.conf ${IMAGE_ROOTFS}/etc/pmon.d/software-agent.conf
fi
if enable_cloudinit; then
ilog "Enabling cloud-init services"
mkdir -p "${IMAGE_ROOTFS}"/etc/systemd/system/cloud-init.target.wants
check_rc_with_msg $? "mkdir failed (cloud-init.target.wants)"
ln -s /usr/lib/systemd/system/cloud-config.service "${IMAGE_ROOTFS}"/etc/systemd/system/cloud-init.target.wants/cloud-config.service && \
ln -s /usr/lib/systemd/system/cloud-init-local.service "${IMAGE_ROOTFS}"/etc/systemd/system/cloud-init.target.wants/cloud-init-local.service && \
ln -s /usr/lib/systemd/system/cloud-init.service "${IMAGE_ROOTFS}"/etc/systemd/system/cloud-init.target.wants/cloud-init.service && \
ln -s /usr/lib/systemd/system/cloud-final.service "${IMAGE_ROOTFS}"/etc/systemd/system/cloud-init.target.wants/cloud-final.service
check_rc_with_msg $? "Failed to setup cloud-init services"
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
# Warning: Do not remove the line feed from the end of this file
# or the install will fail with a permission denied error.
%end