#!/bin/bash kexec=$(which kexec 2>/dev/null) if [ -z "$kexec" ]; then echo "Failed to find kexec binary in PATH. Exiting." exit 1 fi . /opt/openslx/bin/slx-tools perror() { echo "$*" >&2 exit 1 } dl_long() { download_retry --max-time 30 "$@" } # Download dl_prefix() { local url if regex_imatch "$2" 'https?:'; then url="$2" else url="$1/${2#/}" fi dl_long "$url" } kexec_load() { . /opt/openslx/config local serverip="${SLX_KCL_SERVERS%% *}" local base="http://${serverip}" local tempdir oldKcl ipxeId local newKernel newInitRd newKcl tempdir="$(mktemp -d)" newKernel="${tempdir}/kernel" newInitRd="${tempdir}/initrd" read -r oldKcl < /proc/cmdline newKcl="$oldKcl" # Fallback ipxeId= for opts in ${oldKcl}; do case "${opts}" in slx.ipxe.id=*) ipxeId="${opts#slx.ipxe.id=}" ;; esac done if [ -n "$ipxeId" ]; then local ok= if ! dl_long "${base}/boot/ipxe?type=bash&entryid=$ipxeId&uuid=$(cat /etc/system-uuid)" > "${tempdir}/bootentry"; then echo "Could not download iPXE menu entry, falling back..." else local ip="$( ip addr show dev $SLX_PXE_NETIF | awk '{ if ($1 == "inet") { print $2; exit 0 }}' )" local gateway="$( ip route show dev $SLX_PXE_NETIF | awk '{ if ($1 == "default") {print $3; exit 0 }}' )" local dns="${SLX_DNS// /,}" local hostname="${SLX_HOSTNAME}" local domain="${SLX_NET_DOMAIN}" local dnssl="${SLX_NET_SEARCH// /,}" local mac="${SLX_PXE_MAC}" local ntpsrv="${SLX_NTP_SERVER// /,}" [ -z "$mac" ] && mac="$( ip addr show dev $SLX_PXE_NETIF | awk '{ if ($1 == "link/ether") { print $2; exit 0 }}' )" . "${tempdir}/bootentry" if [ -z "$kernel" ]; then echo "iPXE boot entry is missing kernel, falling back..." elif [ -z "$initrd" ]; then echo "iPXE boot entry is missing initRd, falling back..." else # OK-ish, download files dl_prefix "${base}" "${kernel}" > "$newKernel" \ || perror "Error downloading new kernel $kernel" for file in "${initrd[@]}"; do dl_prefix "${base}" "${file}" >> "$newInitRd" \ || perror "Could not download initrd $file" done if [ -n "$kcl" ]; then newKcl="${kcl} slx.ipxe.id=$ipxeId" echo "New KCL is $newKcl" fi ok=true fi fi [ -z "$ok" ] && ipxeId= fi if [ -z "$ipxeId" ]; then echo "No iPXE menu id, guessing file names..." dl_long "${base}/${SLX_BASE_PATH}/kernel" > "$newKernel" \ || perror "Failed to download new kernel." dl_long "${base}/${SLX_BASE_PATH}/initramfs-stage31" > "$newInitRd" \ || perror "Failed to download new initramfs." # Logo is not critical dl_long "${base}/tftp/bwlp.cpio" > "$tempdir/logo" \ && cat "$tempdir/logo" >> "$newInitRd" newKcl="$( cat /proc/cmdline )" # TODO patch all the ipv4.* vars if they exist fi if grep -q '\bsplash\b' /proc/cmdline; then newKcl="$(printf "%s" "${newKcl}" | sed -r 's/\bvga=\S*//g') vga=current" else newKcl="$(printf "%s" "${newKcl}" | sed -r 's/\bvga=\S*//g')" fi if ! kexec -l "${newKernel}" --initrd "${newInitRd}" --command-line="${newKcl}"; then echo "Failed to load kernel/initrd from ${tempdir}" exit 1 fi } kexec_load