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