From dd727fe1e7d5789527d6073671fc8281f7a016b4 Mon Sep 17 00:00:00 2001 From: emacdona Date: Thu, 3 Mar 2022 21:07:38 +0000 Subject: [PATCH] debian: Add Debian packaging for platform-kickstarts Add Debian packaging infrastructure for platform-kickstarts Test Plan: PASS: Verify CentOS package build and iso create PASS: Verify Debian package build and iso create PASS: Verify PXE Boot install with kickstart (single disk) PASS: Verify kickstart xxxPLATFORM_RELEASExxx variable replacement PASS: Verify platform backup partition creation and persistence PASS: Verify single disk vg and lv setup ; log and scratch PASS: Verify install traits=controller,worker boot paramter handling PASS: Verify disk boot kernel parameter cmdline update (aio) PASS: Verify platform.conf setup PASS: Verify INSTALL_UUID setup PASS: Verify boot interface setup, dhcp and login support PASS: Verify install script and logs preserved over an install PASS: Verify instdev with by-path notation PASS: Verify ostree repo pull to feed dir Limitations: - Single Disk install - Currently investigating lv leaking to other disks - Do not specify lowlatency trait without low latency kernel - USB install does not use this kickstart yet ; its not in the iso Story: 2009101 Task: 44658 Depends-On: https://review.opendev.org/c/starlingx/tools/+/834375 Co-authored-by: Eric MacDonald Co-authored-by: Leonardo Fagundes Luz Serrano Signed-off-by: emacdona Change-Id: I50bb797bedd9fb7f7ab1bbdae6e6f22b1023f1fb --- debian_pkg_dirs | 1 + kickstart/debian/deb_folder/changelog | 5 + kickstart/debian/deb_folder/control | 15 + kickstart/debian/deb_folder/copyright | 43 + .../deb_folder/platform-kickstarts.install | 1 + kickstart/debian/deb_folder/rules | 17 + kickstart/debian/meta_data.yaml | 7 + kickstart/files/kickstart.cfg | 1990 +++++++++++++++++ 8 files changed, 2079 insertions(+) create mode 100644 kickstart/debian/deb_folder/changelog create mode 100644 kickstart/debian/deb_folder/control create mode 100644 kickstart/debian/deb_folder/copyright create mode 100644 kickstart/debian/deb_folder/platform-kickstarts.install create mode 100644 kickstart/debian/deb_folder/rules create mode 100644 kickstart/debian/meta_data.yaml create mode 100644 kickstart/files/kickstart.cfg diff --git a/debian_pkg_dirs b/debian_pkg_dirs index 360db24a..b8d6cd07 100644 --- a/debian_pkg_dirs +++ b/debian_pkg_dirs @@ -1,4 +1,5 @@ installer/pxe-network-installer +kickstart mtce mtce-common mtce-compute diff --git a/kickstart/debian/deb_folder/changelog b/kickstart/debian/deb_folder/changelog new file mode 100644 index 00000000..73ebd076 --- /dev/null +++ b/kickstart/debian/deb_folder/changelog @@ -0,0 +1,5 @@ +platform-kickstarts (2.0-1) unstable; urgency=medium + + * Initial release. + + -- Eric MacDonald Wed, 02 Mar 2022 21:26:55 +0000 diff --git a/kickstart/debian/deb_folder/control b/kickstart/debian/deb_folder/control new file mode 100644 index 00000000..36d4bf2f --- /dev/null +++ b/kickstart/debian/deb_folder/control @@ -0,0 +1,15 @@ +Source: platform-kickstarts +Section: admin +Priority: optional +Maintainer: StarlingX Developers +Homepage: https://www.starlingx.io +Standards-Version: 4.5.1 +Build-Depends: debhelper-compat (= 13), + build-info-dev + +Package: platform-kickstarts +Architecture: all +Depends: ${misc:Depends} +Description: Platform kickstarts + Platform kickstart files used to configure nodes + based on install arguement personality traits. diff --git a/kickstart/debian/deb_folder/copyright b/kickstart/debian/deb_folder/copyright new file mode 100644 index 00000000..c1fd1399 --- /dev/null +++ b/kickstart/debian/deb_folder/copyright @@ -0,0 +1,43 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Contact: StarlingX Developers +Upstream-Name: platform-kickstarts +Source: https://opendev.org/starlingx/metal + +Files: * +Copyright: (c) 2013-2022 Wind River Systems, Inc + (c) Others (See individual files for more details) +License: Apache-2 + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + . + https://www.apache.org/licenses/LICENSE-2.0 + . + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + . + On Debian-based systems the full text of the Apache version 2.0 license + can be found in `/usr/share/common-licenses/Apache-2.0'. + +# If you want to use GPL v2 or later for the /debian/* files use +# the following clauses, or change it to suit. Delete these two lines +Files: debian/* +Copyright: 2021 Wind River Systems, Inc +License: Apache-2 + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + . + https://www.apache.org/licenses/LICENSE-2.0 + . + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + . + On Debian-based systems the full text of the Apache version 2.0 license + can be found in `/usr/share/common-licenses/Apache-2.0'. diff --git a/kickstart/debian/deb_folder/platform-kickstarts.install b/kickstart/debian/deb_folder/platform-kickstarts.install new file mode 100644 index 00000000..2282e249 --- /dev/null +++ b/kickstart/debian/deb_folder/platform-kickstarts.install @@ -0,0 +1 @@ +var/www/pages/feed/* diff --git a/kickstart/debian/deb_folder/rules b/kickstart/debian/deb_folder/rules new file mode 100644 index 00000000..29b5b4c0 --- /dev/null +++ b/kickstart/debian/deb_folder/rules @@ -0,0 +1,17 @@ +#!/usr/bin/make -f + +# export DH_VERBOSE = 1 +export ROOT=$(CURDIR)/debian/tmp +export platform_release="$(shell grep SW_VERSION /usr/include/build_info.h | cut -d ' ' -f 3)" + +%: + dh $@ + +override_dh_auto_configure: + sed -i s/xxxPLATFORM_RELEASExxx/$(platform_release)/g kickstart.cfg + dh_auto_configure + +override_dh_install: + install -d -m 755 $(ROOT)/var/www/pages/feed/rel-${platform_release} + install -p -D -m 700 kickstart.cfg $(ROOT)/var/www/pages/feed/rel-${platform_release} + dh_install diff --git a/kickstart/debian/meta_data.yaml b/kickstart/debian/meta_data.yaml new file mode 100644 index 00000000..da30b203 --- /dev/null +++ b/kickstart/debian/meta_data.yaml @@ -0,0 +1,7 @@ +--- +debname: platform-kickstarts +debver: 2.0-1 +src_path: files +revision: + dist: $STX_DIST + PKG_GITREVCOUNT: true diff --git a/kickstart/files/kickstart.cfg b/kickstart/files/kickstart.cfg new file mode 100644 index 00000000..c0adfcdb --- /dev/null +++ b/kickstart/files/kickstart.cfg @@ -0,0 +1,1990 @@ +# +# Copyright (c) 2022 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 +# miniboot ... redfish subcloud install 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 +# +# Pre Partition - Common Functions Script +# Pre Partition - Volume Remove & Wipe Disk +# Partition - Partition Disks & Create Volumes +# Mkfs - Create Volume Groups & Logical Volumes +# Post - Logical Volume Config +# Post - Traits & Platform Config File update +# Post - Set Kernel Args +# Post - Interface Setup +# Post - Kickstart Finalize Install UUID +# Post - Log Filesystem Setup +# Post Nochroot - Save Install scripts and Logs +# +############################################################################ +# +# LAT disk install override debug tool interface. +# +# lat-disk --install-device=${instdev} \ +# --fat-size=${FSZ} \ +# --boot-size=${BSZ} \ +# --root-size=${RSZ} \ +# --var-size=${VSZ} \ +# --inst-flux=0 +# +# Notes: exported environment variables changed in 'post' sections +# do not change the original value. +# +########################################################################### +# +# The first kickstart script creates '/tmp/lat/functions' common functions +# file that can be loaded from any of the other hook sections. +# +########################################################################### +# Pre Partition - Common Functions Script +%pre-part --interpreter=/bin/bash + +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: \$1" >>\${LOGFILE} +} + +function ilog() +{ + [ -z "$stdout" ] && stdout=1 + local dt="$(date "+%Y-%m-%d %H:%M:%S.%3N")" + echo "\$dt kickstart \${HOOK_LABEL} info: \$1" >&\${stdout} + echo "\$dt kickstart \${HOOK_LABEL} info: \$1" >>\${LOGFILE} +} + +function dlog() +{ + if [ "\${debug}" ] ; then + [ -z "\$stdout" ] && stdout=1 + local dt="\$(date "+%Y-%m-%d %H:%M:%S.%3N")" + echo "\$dt kickstart \${HOOK_LABEL} debug: \$1" >&\${stdout} + echo "\$dt kickstart \${HOOK_LABEL} debug: \$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: \$1" >&\${stdout} + echo "\$dt kickstart \${HOOK_LABEL} warn: \$1" >>\${LOGFILE} +} + +function elog() +{ + [ -z "\$stdout" ] && stdout=1 + local dt="\$(date "+%Y-%m-%d %H:%M:%S.%3N")" + echo "\$dt kickstart \${HOOK_LABEL} error: \$1" >&\${stdout} + echo "\$dt kickstart \${HOOK_LABEL} error: \$1" >>\${LOGFILE} +} + +function report_failure_with_msg() +{ + local msg=\${1} + echo -e '\n\nInstallation failed.\n' + wlog "Installation Failed: ERROR: \${msg}" + shell_start + exit 1 +} + +######################################################################## +# Name : get_disk +# Parameters: \$1 - ?????? +# Returns : No return but common disk name is echo's to stdio +######################################################################### +function get_disk() +{ + echo "\$(cd /dev ; readlink -f \$1)" +} + +######################################################################### +# Name : get_by_path +# Parameters: \$1 - device name i.e. /dev/sda +# Returns : echo of device name by-path +# example: /dev/disk/by-path/pci-0000:03:00.0-scsi-0:2:0:0 +######################################################################### +function get_by_path() +{ + # log "Function: get_by_path '\${1}'" + local disk=\$(cd /dev ; readlink -f \$1) + for p in /dev/disk/by-path/*; do + if [ "\$disk" = "\$(readlink -f \$p)" ]; then + echo "\$p" + return + fi + done +} + +######################################################################### +# Name : get_disk_dev +# Purpose : get the disk name +# Returns : echo of the first disk name found ; base on coded priority +######################################################################### +function get_disk_dev() +{ + local disk + # Detect HDD + 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 + echo "\$disk" + return + fi + fi + done + 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 +} + +######################################################################### +# 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 : 1 if yes 'pxecontroller' is in $insturl boot arg ; else 0 +######################################################################### +function is_system_node_install() +{ + if [[ "\$insturl" == *"pxecontroller"* ]] ; 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 \${PLATFORM_CONF} : \${1}" + echo "\${1}" >> \${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} + + # convert to predictive name + altname=\$(udevadm info --export --query=property --path=/sys/class/net/\${iface} | grep ID_NET_NAME_ONBOARD) + altname=\${altname#ID_NET_NAME_ONBOARD=} + + # 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 () +{ + 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} +} + +display_mount_info() +{ + if [ \${debug} -ne 0 ] ; then + echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + lsblk -o name,mountpoint,label,size,uuid + echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + fi +} + +function log_lvm_conf () +{ + lvm_global_filter=\$(cat /etc/lvm/lvm.conf | grep "global_filter =") + ilog "LVM 'global_filter' Config: \${lvm_global_filter}" + lvm_preferred_names=\$(cat /etc/lvm/lvm.conf | grep "preferred_names =") + ilog "LVM 'lvm_preferred_names' Config: \${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}" +} + +########################################################################## +# Global Kickstart Constants # +########################################################################## +# +# NOTE: exported Variables from other segments are NOT visible from functions +# + +BACKUP_PART_LABEL="Platform Backup" +BACKUP_PART_NO=6 +BACKUP_PART=\${instdev}\${BACKUP_PART_NO} + +DEFAULT_PERSISTENT_SIZE=30000 + +# 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" + +# 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}" +SUBFUNCTION__AIO_LOWLATENCY="\${TRAIT__CONTROLLER},\${TRAIT__WORKER},\${TRAIT__LOWLATENCY}" +VOLUME_GROUPS="cgts-vg" + +ROOTFS_SIZE=\${RSZ} # 20000 +BOOT_SIZE=\${BSZ} # 500 +EFI_SIZE=300 +LOG_VOL_SIZE=8000 +SCRATCH_VOL_SIZE=16000 +EOF + +chmod 755 /tmp/lat/ks_functions.sh +HOOK_LABEL="pre-part" +. /tmp/lat/ks_functions.sh + +########################################################################## +# Global Kickstart variables # +########################################################################## + +export debug=0 + +export PLATFORM_BACKUP_SIZE=${DEFAULT_PERSISTENT_SIZE} + +# Assume there is no Platform Backup (persistent) Partition +export BACKUP_CREATED=0 +export BACKUP_PERSISTED=0 + +# Platform Backup Partition Info +export BACKUP_PART_GUID=0 +export BACKUP_PART_FIRST=0 +export BACKUP_PART_END=0 +export BACKUP_PART_SIZE=0 +export BACKUP_PART_FLAGS=0 +export BACKUP_PART_NAME="" + +export STOR_DEV_FDS="" + +########################################################################## + +ilog "***********************************************" +ilog "** Pre Partition - Volume Remove & Wipe Disk **" +ilog "***********************************************" + +# Default traits to AIO if missing +if [ -z "${traits}" ] ; then + traits="controller,worker" + wlog "traits option missing ; defaulting to \${traits}" +fi + +export controller=false +export storage=false +export worker=false +export lowlatency=false +export miniboot=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 ;; + "miniboot") miniboot=true ;; + *) wlog "unknown trait '${trait}'" ;; + esac +done + +[ "${controller}" = true -a "${worker}" = true ] && aio=true + +grep -q 'debug_kickstart' /proc/cmdline +if [ $? -eq 0 ]; then + debug=1 +fi + +ilog "LAT size parameters: FSZ=${FSZ} BSZ=${BSZ} RSZ=${RSZ} VSZ=${VSZ}" + +# 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" +[ "${miniboot}" = true ] && ilog "Zero Touch Install Function" + +# Log System Type +if [ ${aio} = true ] ; then + ilog "${SYSTEM_TYPE__AIO} 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'" + +##################################################### +# From pre_disk_setup_common.cfg +##################################################### + +if [ -n "$instdev" ] ; then + instdev_by_path=$(get_by_path $instdev) + if [ -z ${instdev_by_path} ] ; then + report_failure_with_msg "invalid install device ${instdev}" + else + ilog "Install device: ${instdev} : ${instdev_by_path}" + 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:" +STOR_DEVS="" +for f in /dev/disk/by-path/*; do + dev=$(readlink -f $f) + # dlog "found device ${f}" + exec_retry 2 0.5 "lsblk --nodeps --pairs $dev" | grep -q 'TYPE="disk"' + if [ $? -eq 0 ] ; then + # ISSUE: Do /dev/sda only otherwise with sda,sdb,sdc the LAT boot + # partitions show up on /dev/sdc even if instdev = /dev/sda + # This issue is being investigated, Jira pending + if [ "${dev}" = "/dev/sda" ] ; then + STOR_DEVS="$STOR_DEVS $dev" + ilog "Adding ${f} -> ${dev} to managed device list" + fi + 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. +#STOR_DEV_FDS="$stdout" +#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" + +# Deactivate existing volume groups to avoid Anaconda issues with pre-existing groups +# TODO: May not need this Anaconda specific behavior work around +vgs=$(exec_no_fds "$STOR_DEV_FDS" "vgs --noheadings -o vg_name 2>/dev/null") +for vg in $vgs; do + wlog "Disabling $vg" + exec_no_fds "$STOR_DEV_FDS" "vgchange -an $vg 2>/dev/null" 5 0.5 + [ $? -ne 0 ] && report_failure_with_msg "Failed to disable $vg." +done + +# Remove the volume groups that have physical volumes on the root disk +for vg in $(exec_no_fds "$STOR_DEV_FDS" "vgs --noheadings -o vg_name 2>/dev/null"); do + exec_no_fds "$STOR_DEV_FDS" "pvs --select \"vg_name=$vg\" --noheadings -o pv_name 2>/dev/null" | grep -q "${instdev}" + rc=$? + if [ $rc -ne 0 ]; then + wlog "Found $vg with no PV on rootfs, ignoring ; rc=${rc}" + # continue + fi + +# wlog "Removing LVs on $vg." +# exec_no_fds "$STOR_DEV_FDS" "lvremove --force $vg 2>/dev/null" 5 0.5 || wlog "WARNING: Failed to remove lvs on $vg." +# pvs=$(exec_no_fds "$STOR_DEV_FDS" "pvs --select \"vg_name=$vg\" --noheadings -o pv_name 2>/dev/null") +# wlog "VG $vg has PVs: $(echo $pvs), removing them." +# for pv in $pvs; do +# wlog "Removing PV $pv." +# 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 + + # Just delete the Volume Group , the logical volumes will be deleted under the covers + vg_check=$(exec_no_fds "$STOR_DEV_FDS" "vgs --select \"vg_name=$vg\" --noheadings -o vg_name 2>/dev/null") + if [ -n "$vg_check" ]; then + wlog "Removing volume group $vg" + exec_no_fds "$STOR_DEV_FDS" "vgremove --force $vg 2>/dev/null" 5 0.5 + [ $? -ne 0 ] && report_failure_with_msg "Failed to remove VG." + fi +done + + +# Log info about system state after partitioning removal operation. +for dev in $STOR_DEVS; do + log "After partition removal for $dev is:" + parted -s $dev unit mib print >> ${LOGFILE} +done + +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" + +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_JOURNAL_GUID="45B0969E-9B03-4F30-B4C6-B4B80CEFF106" + + # Check if we wipe OSDs + if [ "$(curl -sf http://pxecontroller:6385/v1/ihosts/wipe_osds 2>/dev/null)" = "true" ]; then + wlog "Wipe OSD data" + WIPE_CEPH_OSDS="true" + else + wlog "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" + + pvs | grep -q "$dev *ceph" + if [ $? -eq 0 ]; then + wlog "skip rook provisoned disk $dev" + continue + fi + + part_numbers=( `parted -s $dev print | awk '$1 == "Number" {i=1; next}; i {print $1}'` ) + # Scanning the partitions looking for CEPH OSDs and + # skipping any disk found with such partitions + for part_number in "${part_numbers[@]}"; do + sgdisk_part_info=$(sgdisk -i $part_number $dev) + part_type_guid=$(echo "$sgdisk_part_info" | grep "$part_type_guid_str" | awk '{print $4;}') + if [ "$part_type_guid" == $CEPH_OSD_GUID ]; then + wlog "OSD found on $dev, skipping wipe" + wipe_dev="false" + break + fi + + pvs | grep -q -e "${dev}${part_number} *ceph" -e "${dev}p${part_number} *ceph" + if [ $? -eq 0 ]; then + wlog "Rook OSD found on $dev$part_number, skip wipe" + wipe_dev="false" + break + fi + done + + if [ "$wipe_dev" == "false" ]; then + ilog "Bypassing Wipe of ${dev}${part_number} ; reason: wipe_dev=false" + continue + else + ilog "Allowing Wipe of ${dev}${part_number} ; reason: wipe_dev=true" + 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 wipped" + 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 "***************************************************" +by_dev=${instdev} +# TODO: Avoid this loop if the instdev does not have by-path in its name +for f in /dev/disk/by-path/*; do + if [ "${f}" == "${instdev}" ] ; then + by_dev=$(get_disk "${instdev}") + break + fi +done +for dev in ${WIPE_HDD//,/ } +do + ilog "Wiping $dev" + + # Clear previous GPT tables or LVM data on each disk. + # + # Rule: Exclude the persistent 'Platform backup' partition. + # Note: Delete the first few bytes at the start and end of the partition. + # This is required with GPT partitions because they save partition + # info at both the start and the end of the block. + + # Get a list of partitions for this disk + part_numbers=( $(parted -s $dev print | awk '$1 == "Number" {i=1; next}; i {print $1}') ) + + # For each '/dev/${dev}${part_number} 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 '${instdev}' + if [ "${dev}" == "${by_dev}" ] ; then + + # Skip over the bios, efi and boot partitions that got us here. + # LAT handles these partitions + case ${part_name} in + "'bios'") + ilog "skipping ${part_name} on ${dev}${part_number}" + continue + ;; + "'otaefi'") + ilog "skipping ${part_name} on ${dev}${part_number}" + continue + ;; + "'otaboot'") + ilog "skipping ${part_name} on ${dev}${part_number}" + continue + ;; + "'otaboot_b'") + ilog "skipping ${part_name} on ${dev}${part_number}" + continue + ;; + "'otaroot'") + ilog "skipping ${part_name} on ${dev}${part_number}" + continue + ;; + "'fluxdata'") + ilog "skipping ${part_name} on ${dev}${part_number}" + continue + ;; + *) + dlog "wipe candidate ${part_name} on ${dev}${part_number}" + ;; + esac + fi + + # Deal with ssd's which have different partition labelling convention + part=$dev$part_number + case $part in + *"nvme"*) + part=${dev}p${part_number} + ;; + esac + + # ISSUE: ERIK: These are never the same when the by-path instdev is used. + # dev = /dev/sda instdev = by path string + ilog "Checking platform-backup partition ... $dev : ${instdev} ${by_dev}" + sgdisk_part_info=$(sgdisk -i $part_number $dev) + part_type_guid=$(echo "$sgdisk_part_info" | grep "$part_type_guid_str" | awk '{print $4;}') + BACKUP_PART_GUID=${part_type_guid} + if [ "$dev" == "${by_dev}" -a "$part_type_guid" == $BACKUP_PART_GUID ] ; then + BACKUP_PART_GUID=${part_type_guid} + + 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} + + # dlog "Platform Backup: ${BACKUP_PART_NAME}:${BACKUP_PART_FIRST}:${BACKUP_PART_END}:${BACKUP_PART_SIZE}:${BACKUP_PART_GUID}" + + part_fstype=$(exec_retry 5 0.5 "blkid -s TYPE -o value $part") + if [ "${part_fstype}" == "ext4" ]; then + ilog "Skipping wipe of persistent partition $part" + BACKUP_CREATED=1 + continue + else + ilog "Wipe Partition: part:${part} dev:${dev} pn:${part_number}" + # dlog ".... guid:$part_type_guid:$BACKUP_PART_GUID - fs:${part_fstype}" + fi + fi + + if [ $WIPE_CEPH_OSDS == "true" -a "$part_type_guid" == $CEPH_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 "STUBBED 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_CREATED} -eq 0 -o "${dev}" != "${by_dev}" ]; then + ilog "Creating disk label for $dev" + parted -s $dev mktable gpt + ilog "... done" + fi +done + +# Zap all disks except for the install disk +for dev in $STOR_DEVS; do + if [ ${dev} != "${by_dev}" ] ; then + ilog "Zapping ${dev}" + sgdisk -Z ${dev} + fi +done + +wlog "Destroy otaroot partitions on root disk" +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 -Z ${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 +true +%end + +########################################################################### + +%part --interpreter=/bin/bash +HOOK_LABEL=" part" +. /tmp/lat/ks_functions.sh +ilog "****************************************************" +ilog "*** Partition - Partition Disks & Create Volumes ***" +ilog "****************************************************" + +ilog "Allocate host partitions (MB) first:$first" + +## NOTE: updates to partition sizes need to be also reflected in +## _controller_filesystem_limits() in sysinv/api/controllers/v1/istorconfig.py + +ROOTFS_PART_PREFIX=${instdev} +#check if disk is nvme +case $instdev in + *"nvme"*) + ROOTFS_PART_PREFIX=${instdev}p + ;; +esac + +########################################################### +# From pre_disk_controller.cfg +########################################################### + +# Only controllers have a persistent partition +if [ "${controller}" = true ] ; then + + PLATFORM_BACKUP_SIZE=${DEFAULT_PERSISTENT_SIZE} + + if [ -z "$persistent_size" ]; then + # Default backup partition size in MiB + ilog "Platform Backup persistent size not on command line ; defaulting to ${DEFAULT_PERSISTENT_SIZE}" + persistent_size=${DEFAULT_PERSISTENT_SIZE} + fi + + if [ ${persistent_size} -lt ${DEFAULT_PERSISTENT_SIZE} ] ; then + wlog "Cannot set persistent_size smaller than default size of ${DEFAULT_PERSISTENT_SIZE} KB" + else + PLATFORM_BACKUP_SIZE=${persistent_size} + fi + ilog "Platform Backup partition size: ${PLATFORM_BACKUP_SIZE}" + + if [ -d /sys/firmware/efi ] ; then + ilog "UEFI Firmware" + else + ilog "BIOS Firmware" + fi + if [ ${BACKUP_CREATED} -eq 0 ] ; then + ilog "Platform Backup partition CREATED" + else + BACKUP_PERSISTED=1 + ilog "Platform Backup Partition PERSISTED" + fi + grub_pt_update + end=$(($first+($PLATFORM_BACKUP_SIZE*1024*1024/$lsz)-1)) + a="$a -n $p:$first:$end -c $p:platform_backup" +fi + +# Auto expand +grub_pt_update +end=$last +a="$a -n $p:$first:$end -c $p:plat_pv -t $p:8E00" + +dlog "Partition Table: ${a}" + +STOR_DEVS=$(echo "$STOR_DEVS" | xargs -n 1 | sort -u | xargs) +[ -z "$STOR_DEVS" ] && report_failure_with_msg "No storage devices available." +STOR_DEV_FDS="$stdout" +for dev in $STOR_DEVS; do + exec {fd}>$dev || report_failure_with_msg "Error creating file descriptor for $dev." + STOR_DEV_FDS="$STOR_DEV_FDS $fd" +done +ilog "STOR_DEV_FDS Updated ; $STOR_DEV_FDS" +##################################################################### +# From pre_disk_setup_tail.cfg +##################################################################### + +# Log info about system state at end of partitioning operation. +# From pre_disk_setup_tail.cfg +for dev in $STOR_DEVS; do + log "Partition table at end of script for $dev is:" + parted -s $dev unit mib print >> ${LOGFILE} +done + +# Close all FDs and wait for udev to reshuffle all partitions. +# wlog "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 + +true +%end + +########################################################################### + +%mkfs --interpreter=/bin/bash +HOOK_LABEL="mkfs" +. /tmp/lat/ks_functions.sh +ilog "****************************************************" +ilog "** Mkfs - Create Volume Groups & Logical Volumes **" +ilog "****************************************************" + +####################################################### +# From pre_disk_aio +###################################################### + +# TODO: Remove this duplicate for next update +BACKUP_PART_GUID="BA5EBA11-0000-1111-2222-000000000002" + +# TODO: This causes a kernel panic +# Action: Reverify +# let -i gb=1024*1024*1024 +gb=1073741824 + +ilog "LAT size parameters: FSZ=${FSZ} BSZ=${BSZ} RSZ=${RSZ} VSZ=${VSZ} gb:${gb}" + +if [ "${controller}" = true ] ; then + LOG_VOL_SIZE=8000 + SCRATCH_VOL_SIZE=16000 + + if [ ! -z "$persistent_size" ]; then + # Default backup partition size in MiB + persistent_size=${DEFAULT_PERSISTENT_SIZE} + fi + # PLATFORM_BACKUP_SIZE=${persistent_size} + ilog "Persistent Size: $persistent_size ${PLATFORM_BACKUP_SIZE}" +fi + +if [ "${aio}" = true ] ; then + ## + ## 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 + ## LOG_VOL_SIZE = 8GiB + ## SCRATCH_VOL_SIZE = 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) + ## + ## CGCS_PV_SIZE = (10 + 2*10 + 25 + 8 + 16 + 2 + 1 + 30 + 16 + 5 + 20 + 10 + 15)GiB + 16MiB/1024 = 178.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 + ## + ## LOG_VOL_SIZE = 8GiB + ## SCRATCH_VOL_SIZE = 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) + ## + ## CGCS_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 + ## + ## LOG_VOL_SIZE = 3GiB + ## SCRATCH_VOL_SIZE = 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 + ## + ## CGCS_PV_SIZE = (1 + 2*1 + 1 + 3 + 2 + 2 + 1 + 20 + 8 + 1 + 2)GiB = 43GiB + ## + ## MINIMUM_TINY_DISK_SIZE = CGCS_PV_SIZE + ROOTFS_SIZE + EFI_SIZE + BOOT_SIZE + PLATFORM_BACKUP_SIZE + ## = 43 + 15 + 0.3 + 0.5 + 1 = 60GiB + + # 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 size:$sz gb:$gb" + + # Round CGCS_PV_SIZE to the closest upper value that can be divided by 1024. + if [ $sz -gt $(($default_small_disk_size*$gb)) ] ; then + ilog "Large disk: CGCS_PV_SIZE=179GiB*1024=183296" + CGCS_PV_SIZE=183296 + + elif [ $sz -ge $(($minimum_small_disk_size*$gb)) ] ; then + ilog "Small disk: CGCS_PV_SIZE=164GiB*1024=167936" + CGCS_PV_SIZE=167936 + + else + ilog "Tiny disk: CGCS_PV_SIZE=43GiB*1024=44032" + # Using a disk with a size under 60GiB will fail. + CGCS_PV_SIZE=44032 + LOG_VOL_SIZE=3000 + SCRATCH_VOL_SIZE=2000 + PLATFORM_BACKUP_SIZE=1000 + fi + +elif [ "${controller}" = true ] ; then + LOG_VOL_SIZE=8000 + SCRATCH_VOL_SIZE=16000 +fi + +ilog "CGCS_PV_SIZE : ${CGCS_PV_SIZE}" +ilog "SCRATCH_VOL_SIZE : ${SCRATCH_VOL_SIZE}" +ilog "ROOTFS_SIZE : ${ROOTFS_SIZE}" +ilog "LOG_VOL_SIZE : ${LOG_VOL_SIZE}" +ilog "PLATFORM_BACKUP_SIZE : ${PLATFORM_BACKUP_SIZE}" + +ilog "BACKUP_PART : ${BACKUP_PART}" +ilog "BACKUP_PART_NO : ${BACKUP_PART_NO}" +ilog "BACKUP_PART_LABEL : ${BACKUP_PART_LABEL}" +ilog "BACKUP_PART_GUID : ${BACKUP_PART_GUID}" + +if [ "${controller}" = true ] ; then + ilog "Backup Partition : ${BACKUP_PART}" + if [ ${BACKUP_PERSISTED} -eq 0 ] ; then + # TODO: Was hanging when the flock preceeded the sgdisk. + # Action: Reverify + # flock ${instdev} sgdisk --change-name=${BACKUP_PART_NO}:"${BACKUP_PART_LABEL}" --typecode=${BACKUP_PART_NO}:"${BACKUP_PART_GUID}" ${instdev} || exit 1 + cat</tmp/backup-guid-change.sh + ilog "Updating backup partition GUID" +sgdisk --change-name=${BACKUP_PART_NO}:"${BACKUP_PART_LABEL}" --typecode=${BACKUP_PART_NO}:"${BACKUP_PART_GUID}" ${instdev} || exit 1 +EOF + fi +fi + +ilog "cgts--vg-log--lv size: ${LOG_VOL_SIZE} MB" +ilog "cgts--vg-scratch--lv : ${SCRATCH_VOL_SIZE} MB" +ilog "Install disk: ${instdev} ; current partition index:$pi" + +vg="volume group" +lv="logical volume" +dev=$(get_disk "${instdev}") + +# Only init Platform Backup partition filesystem if the partition was just created +pi=$((pi+1)) +if [ ${BACKUP_PERSISTED} -eq 0 ] ; then + ilog "Platform Backup filesystem init ${dev}${pi}" + mkfs.ext4 -F -L platform_backup ${dev}${pi} + [ ${?} -ne 0 ] && report_failure_with_msg "Failed Platform Backup partition filesystem init ${dev}${pi}" +fi + +# Create Volume Group +pi=$((pi+1)) + +# Log important LVM config settings +log_lvm_conf + +ilog "Create ${vg} 'cgts-vg' ${dev}${pi} ; $STOR_DEV_FDS" +exec_no_fds "$STOR_DEV_FDS" "vgcreate -y --force cgts-vg ${dev}${pi} 2>/dev/null" 5 0.5 +[ ${?} -ne 0 ] && report_failure_with_msg "Failed to create ${vg} 'cgts-vg' ${dev}${pi}" + +# Create and Init the '/var/log' logical volume +ilog "Create ${lv} 'log-lv' ; $STOR_DEV_FDS" +exec_no_fds "$STOR_DEV_FDS" "lvcreate -y -n log-lv -L ${LOG_VOL_SIZE}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 -n scratch-lv -L ${SCRATCH_VOL_SIZE}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 +LV_ROOTDISK=$(pvdisplay --select 'vg_name=cgts-vg' -C -o pv_name --noheadings) +[ -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 + +true +%end + +########################################################################### + +%post --interpreter=/bin/bash +HOOK_LABEL="post" +. /tmp/lat/ks_functions.sh +ilog "****************************************************" +ilog "**** Post - Traits & Platform Config File update **" +ilog "****************************************************" + +set -- `env` +dlog "env: $*" + +if false ; then +# TODO: Why does LAT break into prompt when I do this +for e in $*; do + case "$e" in + *=*) + eval $e 2>/dev/null + log "env : $e" + ;; + esac +done +fi + +ilog "Install traits: $traits" + +# 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} + ilog "Controller Function" +elif [ "${storage}" = true ] ; then + nodetype=${TRAIT__STORAGE} + ilog "Storage Function" +elif [ "${worker}" = true ] ; then + nodetype=${TRAIT__WORKER} +else + elog "No personality traits specified ; defaulting to All-In-One" + controller=true + worker=true + nodetype=${TRAIT__CONTROLLER} +fi +ilog "nodetype=${nodetype}" + +# Set system type and subfunction +subfunction="" +system_type="" +system_mode="simplex" +[ "${controller}" = true -a "${worker}" = true ] && aio=true +if [ "${aio}" = true ] ; then + ilog "${SYSTEM_TYPE__AIO} System" + system_type="${SYSTEM_TYPE__AIO}" + if [ "${rt}" = true ] ; then + subfunction="${SUBFUNCTION__AIO_LOWLATENCY}" + else + subfunction="${SUBFUNCTION__AIO}" + fi +else + ilog "${SYSTEM_TYPE__STANDARD} System" + system_type="${SYSTEM_TYPE__STANDARD}" + if [ "${worker}" = true ] ; then + subfunction=${SUBFUNCTION__WORKER} + elif [ "${storage}" = true ] ; then + subfunction=${SUBFUNCTION__STORAGE} + else + subfunction=${SUBFUNCTION__CONTROLLER} + fi +fi +ilog "subfunction=${subfunction}" +ilog "system_type=${system_type}" +ilog "system_mode=${system_mode}" + +# Create and Update /etc/platform/platform.conf +# --------------------------------------------- + +if [ -e "${PLATFORM_CONF}" ] ; then + wlog "removing temp platform.conf" +fi + +################################################################# +# 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 < ${PLATFORM_CONF} +nodetype=${nodetype} +subfunction=${subfunction} +system_type=${system_type} +system_mode=${system_mode} +EOF + +# Set http port +# Persist the default http port number to platform configuration. +# This will get overwritten when by manifest during sw configuration phase. +http_port=$(echo $(cat /proc/cmdline |xargs -n1 echo |grep '^insturl=' | sed -r 's#^[^/]*://[^/]*:([0-9]*)/.*#\1#')) +update_platform_conf "http_port=${http_port}" + +# TODO: Set sw release +update_platform_conf "sw_release=xxxPLATFORM_RELEASExxx" + +############################################################# +# From post_common.cfg (all hosts) +############################################################# + +# Should handle controller-0 install from external server and USB +is_system_node_install +if [ ${?} -ne 0 ] ; then + # Unset the hostname + rm /etc/hostname + if [ "${controller}" = true ] ; then + echo "controller-0" > /etc/hostname + fi +fi + +# 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 + +if [ "${controller}" = true ] ; then + # Add the WRCP GUID to the Platform backup partition. + BACKUP_PART_CHANGE_FILE="/tmp/backup-guid-change.sh" + if [ -f "${BACKUP_PART_CHANGE_FILE}" ] ; then + ilog "Found ${BACKUP_PART_CHANGE_FILE} ; running to set Platform backup to persist" + chmod 744 ${BACKUP_PART_CHANGE_FILE} + # ISSUE: This hangs LAT with 'flock /dev/sda' + # TODO : Discuss with Architects + # + # flock /dev/sda sgdisk --change-name=6:"Platform Backup" --typecode=6:"BA5EBA11-0000-1111-2222-000000000002" /dev/sda + . ${BACKUP_PART_CHANGE_FILE} 2>/dev/null + sleep 2 + parted -l 2>/dev/null + fi +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 +# ---------------------------------------- +export KERN_OPTS="" +ilog "Building 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 + +# TODO: Remove as it turns out that this is not added by kickstarts. +# Remove all reference to 'security_feature' above as well. +# +# add security_feature to platform.conf ; be sure not to add as empty. +# [ -z "${security_feature}" ] && security_feature=none +# update_platform_conf "security_feature=${security_feature}" + +[ "${KERN_OPTS}" != "" ] && ilog "Learned kernel params: ${KERN_OPTS}" + +if [ "${aio}" = true ] ; then + + ilog "Adding ${SYSTEM_TYPE__AIO} kernel options" + 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 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 + + # 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 + + # k8s updates: + #KERN_OPTS="${KERN_OPTS} cgroup_disable=memory" + add_kernel_option "user_namespace.enable=1" + + # 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 an selinux is disabled + add_kernel_option "selinux=0 enforcing=0" + + # Add kernel options to ensure NMI watchdog is enabled, if supported + add_kernel_option "nmi_watchdog=panic,1 softlockup_panic=1" + + # Add kernel option to panic on a softdog timeout + add_kernel_option "softdog.soft_panic=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 + [ $? -ne 0 ] && add_kernel_option "biosdevname=0" + + # k8s updates + add_kernel_option "user_namespace.enable=1" +else + wlog "TODO: system node install type kernel parameters, worker and storage" +fi + +# TODO: Is this needed ? Certainlty not the Centos part +# perl -pi -e 's/(GRUB_CMDLINE_LINUX=.*)\"/\1'"$KERN_OPTS"'\"/g' /etc/default/grub + +# if [ -d /sys/firmware/efi ] ; then +# grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg +# else +# grub2-mkconfig -o /boot/grub2/grub.cfg +# fi +# The uncommented code below updates the disk boot command for LAT + +ilog "Adding these kernel params to disk boot: ${KERN_OPTS}" +if [ -n "${KERN_OPTS}" ] ; then + # Add 'set kernel_params="${kernel_params} ${KERN_OPTS}"' to disk + # boot command line by /boot/efi/EFI/BOOT/grub.cfg update + grep -q "set kernel_params=.*${KERN_OPTS}" /boot/efi/EFI/BOOT/grub.cfg + if [ ${?} -ne 0 ]; then + sed -i "/set kernel_params=.*/a set kernel_params=\"\${kernel_params} ${KERN_OPTS}\"" /boot/efi/EFI/BOOT/grub.cfg + fi +else + wlog "no kernel options added" +fi + +###################################################################### +# From post_system_aio +###################################################################### +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 + + ilog "${SYSTEM_TYPE__AIO} Reserved Memory: ${RESERVEDMEM}" + sed -i -e "s#\(WORKER_BASE_RESERVED\)=.*#\1=(\"node0:${RESERVEDMEM}MB:1\" \"node1:2000MB:0\" \"node2:2000MB:0\" \"node3:2000MB:0\")#g" /etc/platform/worker_reserved.conf + worker_reserved=$(grep WORKER_BASE_RESERVED /etc/platform/worker_reserved.conf) + 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))\"/" /etc/platform/worker_reserved.conf + + worker_cpu_list=$(grep WORKER_CPU_LIST /etc/platform/worker_reserved.conf) + ilog "${SYSTEM_TYPE__AIO} '${worker_cpu_list}'" +fi + +true +%end + +########################################################################### + +%post --interpreter=/bin/bash +HOOK_LABEL="post" +. /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=} +mgmt_dev=lo +mgmt_vlan=0 +if [ -n "$BOOTIF" ] ; then + BOOTIF=$(echo $BOOTIF | sed -r -e 's/.*(..-..-..-..-..-..)$/\1/' -e 's/-/:/g') + ndev=`ip link show |grep -B 1 $BOOTIF |head -1 |awk '{print $2}' |sed -e 's/://'` + if [ -n "$ndev" ] ; then + # convert to predictive name + mgmt_dev=$(get_iface_from_ethname $ndev) + if [ "${mgmt_dev}" == "" ] ; then + elog "failed to get predictive altname from ${ndev}" + mgmt_dev=${ndev} + + # get vlan info for system node installs + system_node=$(is_system_node_install) + if [ "${system_node}" = true ] ; 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` + if [ ${?} -ne 0 ] ; then + # TODO: uncomment to force install failure for product + # report_failure_with_msg "Unable to communicate with System Inventory REST API. Aborting installation." + wlog "ERROR: Unable to communicate with System Inventory REST API." + fi + fi + else + ilog "Management Interface: ${ndev} -> ${mgmt_dev}" + fi + else + elog "ERROR:POST: Unable to determine mgmt interface from BOOTIF=$BOOTIF." + # TODO: MAKE Default - Should not get here without BOOTIF set ; LAT guarantees that. + # report_failure_with_msg "Unable to determine mgmt interface from BOOTIF=$BOOTIF." + fi +else + elog "ERROR:POST: BOOTIF is not set. Unable to determine mgmt interface." + # TODO: MAKE Default - Should not get here without BOOTIF set ; LAT guarantees that. +fi + +if [ ! -e "/etc/network/interfaces" ] ; then +cat << EOF >> /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 /etc/network/interfaces.d/* +EOF +fi + +if [ ! -d "/etc/network/interfaces.d" ] ; then + mkdir -p -m 0775 /etc/network/interfaces.d +fi + +# Build networking scripts, starting with the localhost interface +cat << EOF >> /etc/network/interfaces + +# The loopback network interface +auto lo +iface lo inet loopback +EOF + +cat << EOF >> /etc/network/interfaces + +# management network interface +allow-hotplug $mgmt_dev +auto $mgmt_dev +iface $mgmt_dev inet dhcp + +EOF + +ilog "Setup network scripts" + +if [ $mgmt_vlan -eq 0 ] ; then + + # 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=$mgmt_dev" + + # Build networking scripts + cat << EOF > /etc/network/interfaces.d/ifcfg-lo +auto lo +iface lo inet static +address 127.0.0.1 +netmask 255.0.0.0 + post-up echo 0 > /proc/sys/net/ipv6/conf/lo/autoconf; echo 0 > /proc/sys/net/ipv6/conf/lo/accept_ra; echo 0 > /proc/sys/net/ipv6/conf/lo/accept_redirects +EOF + + + cat << EOF > /etc/network/interfaces.d/ifcfg-$mgmt_dev +auto $mgmt_dev +iface $mgmt_dev inet manual + pre-up sleep 20 + post-up echo 0 > /proc/sys/net/ipv6/conf/lo/autoconf; echo 0 > /proc/sys/net/ipv6/conf/lo/accept_ra; echo 0 > /proc/sys/net/ipv6/conf/lo/accept_redirects +EOF + +else + + # Check whether to use inet or inet6 + ipv6_addr=$(dig +short AAAA controller) + if [[ -n "$ipv6_addr" ]] + then + mgmt_address_family=inet6 + ipv6init=yes + dhcpv6c=yes + dhclientargs=-1 + else + mgmt_address_family=inet + ipv6init=no + dhcpv6c=no + dhclientargs= + 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 > /etc/network/interfaces.d/ifcfg-lo +auto lo +iface lo $mgmt_address_family static +address 127.0.0.1 +netmask 255.0.0.0 + post-up echo 0 > /proc/sys/net/ipv6/conf/lo/autoconf; echo 0 > /proc/sys/net/ipv6/conf/lo/accept_ra; echo 0 > /proc/sys/net/ipv6/conf/lo/accept_redirects +EOF + + cat << EOF > /etc/network/interfaces.d/ifcfg-$mgmt_dev +auto $mgmt_dev +iface $mgmt_dev $mgmt_address_family manual + pre-up sleep 20 + post-up echo 0 > /proc/sys/net/ipv6/conf/lo/autoconf; echo 0 > /proc/sys/net/ipv6/conf/lo/accept_ra; echo 0 > /proc/sys/net/ipv6/conf/lo/accept_redirects +EOF + + cat << EOF > /etc/network/interfaces.d/ifcfg-vlan$mgmt_vlan +auto vlan$mgmt_vlan +iface vlan$mgmt_vlan $mgmt_address_family dhcp + vlan-raw-device $mgmt_dev + pre-up sleep 20 + post-up echo 0 > /proc/sys/net/ipv6/conf/lo/autoconf; echo 0 > /proc/sys/net/ipv6/conf/lo/accept_ra; echo 0 > /proc/sys/net/ipv6/conf/lo/accept_redirects +EOF +fi + +true + +%end + +########################################################################## + +%post --interpreter=/bin/bash +HOOK_LABEL="post" +. /tmp/lat/ks_functions.sh +ilog "****************************************************" +ilog "*** Post - Kickstart Finalize Install UUID ***" +ilog "****************************************************" + +# Create a uuid specific to this installation +ilog "Add install uuid to feed and platform.conf" + +INSTALL_UUID=`uuidgen` + +[ ! -d "/var/www/pages/feed/rel-xxxPLATFORM_RELEASExxx" ] && mkdir -p -m 0755 /var/www/pages/feed/rel-xxxPLATFORM_RELEASExxx +echo ${INSTALL_UUID} > /var/www/pages/feed/rel-xxxPLATFORM_RELEASExxx/install_uuid +update_platform_conf "INSTALL_UUID=${INSTALL_UUID}" + +# Create first_boot flag +touch /etc/platform/.first_boot + +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 - Save Install Scripts and Logs **" +ilog "****************************************************" +ilog "IMAGE_ROOTFS=${IMAGE_ROOTFS}" + +get_variable "ostree_repo_fetched" +OSTREE_REPO_FETCHED=$? + +# Fetch ostree +if [ "${controller}" = true -a ${OSTREE_REPO_FETCHED} -eq 0 ] ; then + $(is_system_node_install) + if [ $? -ne 0 ] ; then + sw_release="xxxPLATFORM_RELEASExxx" + pxeurl=$(echo $insturl | sed -e s/ostree_repo//) + + # -1 is all commits, positive number is that number of last commits + commits="--depth=-1" + pull_options="${commits} --mirror" + feed="${IMAGE_ROOTFS}/var/www/pages/feed/rel-${sw_release}" + repo="${feed}/ostree_repo" + mkdir -p "${repo}" + + ilog "Pull ostree_repo to ${repo}" + ostree --repo=${repo} init --mode=archive + ostree --repo=${repo} remote add ${instbr} ${insturl} + ostree --repo=${repo} pull ${pull_options} ${instbr}:${instbr} + + # TODO: Figure out a way on the second run /sysroot/ostree/2 + # to avoid this error string + # + # error: Remote configuration for "starlingx" already exists: (in config) + + # Check for noverifyssl + if grep -q noverifyssl /proc/cmdline; then + NOVERIFYSSL_WGET_OPT="--no-check-certificate" + else + NOVERIFYSSL_WGET_OPT="" + fi + + pushd ${feed} + + # TODO: Remove ; This is temporary until the kernel and initrd are fetched from ostree_repo + wget ${NOVERIFYSSL_WGET_OPT} --spider --quiet ${pxeurl}/bzImage + [ $? -ne 0 ] && report_failure_with_msg "Failed to find bzImage on pxeboot server ; ${sw_release} ${pxeurl}" + wget ${NOVERIFYSSL_WGET_OPT} --reject 'index.html*' --quiet ${pxeurl}/bzImage + [ $? -ne 0 ] && report_failure_with_msg "Failed to get bzImage from pxeboot server ; ${sw_release} ${pxeurl}" + + wget ${NOVERIFYSSL_WGET_OPT} --spider --quiet ${pxeurl}/initrd + [ $? -ne 0 ] && report_failure_with_msg "Failed to find initrd on pxeboot server ; ${sw_release} ${pxeurl}" + wget ${NOVERIFYSSL_WGET_OPT} --reject 'index.html*' --quiet ${pxeurl}/initrd + [ $? -ne 0 ] && report_failure_with_msg "Failed to get initrd from pxeboot server ; ${sw_release} ${pxeurl}" + + # TODO: Not neeed once the kickstart is in the iso + # Save the kickstart + cp /${LAT_DIR}/lat-installer.ks ${feed}/kickstart.cfg + + # This fetch is only needed once because the repo is stored in /var + set_variable "ostree_repo_fetched" + + popd + 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 + ilog "Saving installer data to /${LOG_DIR}" + cp -a /${LAT_DIR} ${IMAGE_ROOTFS}/${LOG_DIR} + cp /install ${IMAGE_ROOTFS}/${LOG_DIR}/lat + else + wlog "Could not save installer data" + fi + umount "${IMAGE_ROOTFS}/${LOG_DIR}" +fi + +# 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' ${IMAGE_ROOTFS}/etc/lvm/lvm.conf +#perl -0777 -i -pe 's:(# Example\n)\t# preferred_names:$1 preferred_names:m' ${IMAGE_ROOTFS}/etc/lvm/lvm.conf +#sed -i "s#^\( *\)global_filter = \[.*#\1global_filter = [ \"a|${LV_ROOTDISK}|\", \"r|.*|\" ]#" ${IMAGE_ROOTFS}/etc/lvm/lvm.conf + +true +%end