summaryrefslogtreecommitdiffstats
path: root/core/modules/kexec-reboot
diff options
context:
space:
mode:
authorSimon Rettberg2020-07-08 16:12:32 +0200
committerSimon Rettberg2020-07-08 16:12:32 +0200
commitc1d6cad0e7653fcad04f27a7827a439827470092 (patch)
tree32578b2e35511271a913ac01bfb9a6b30166e0fd /core/modules/kexec-reboot
parent[remote-access] Tweak screen splitting (diff)
downloadmltk-c1d6cad0e7653fcad04f27a7827a439827470092.tar.gz
mltk-c1d6cad0e7653fcad04f27a7827a439827470092.tar.xz
mltk-c1d6cad0e7653fcad04f27a7827a439827470092.zip
[init/kexec/] More advanced network setup via KCL, could skip DHCP
If enough information if provided via KCL, we can skip the initial DHCP request in stage 3.1. Currently we require IP address, subnet mask and DNS server to skip DHCP. If we extend the boot server to supply a fallback/default DNS server, we could even do without DNS which would work in almost all cases. kexec-reboot has been extended to make use of this feature, but can be extended even more to provide up to date values from the current system configuration. Currently, some of the values it provides to the new kernel will be cached values from stage 3.1. kexec-reboot also honors the ipxe menu id from the KCL if given, to properly download the matching menu entry, which will take updates to the entry into account (e.g. changed URLs to kernel/init).
Diffstat (limited to 'core/modules/kexec-reboot')
-rwxr-xr-xcore/modules/kexec-reboot/data/opt/openslx/scripts/systemd-kexec_load95
1 files changed, 83 insertions, 12 deletions
diff --git a/core/modules/kexec-reboot/data/opt/openslx/scripts/systemd-kexec_load b/core/modules/kexec-reboot/data/opt/openslx/scripts/systemd-kexec_load
index 5907bc0b..0b73824f 100755
--- a/core/modules/kexec-reboot/data/opt/openslx/scripts/systemd-kexec_load
+++ b/core/modules/kexec-reboot/data/opt/openslx/scripts/systemd-kexec_load
@@ -1,4 +1,4 @@
-#!/bin/ash
+#!/bin/bash
kexec=$(which kexec 2>/dev/null)
if [ -z "$kexec" ]; then
@@ -8,22 +8,93 @@ fi
. /opt/openslx/bin/slx-tools
+perror() {
+ echo "$*" >&2
+ exit 1
+}
+
+# Download <base> <relative_or_absolute>
+dl_prefix() {
+ local url
+ if regex_imatch "$2" 'https?:'; then
+ url="$2"
+ else
+ url="$1/${2#/}"
+ fi
+ download_retry "$url"
+}
+
kexec_load() {
. /opt/openslx/config
- local DIR="$(mktemp -d)"
+ 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
- for FILE in kernel initramfs-stage31; do
- if ! download_retry "http://${SLX_KCL_SERVERS}/${SLX_BASE_PATH}/${FILE}" > "${DIR}/${FILE}" ; then
- echo "Failed to download ${FILE}."
- exit 1
+ if [ -n "$ipxeId" ]; then
+ local ok=
+ if ! download_retry "${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 br0 | awk '{ if ($1 == "inet") { print $2; exit 0 }}' )"
+ local gateway="$( ip route show dev br0 | 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 br0 | 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
- done
- if download_retry "http://${SLX_KCL_SERVERS}/tftp/bwlp.cpio" > "${DIR}/bwlp.cpio"; then
- cat "${DIR}/initramfs-stage31" "${DIR}/bwlp.cpio" > "${DIR}/initramfs-tmp"
- mv -f -- "${DIR}/initramfs-tmp" "${DIR}/initramfs-stage31"
+ [ -z "$ok" ] && ipxeId=
fi
- if ! kexec -l "${DIR}/kernel" --initrd "${DIR}/initramfs-stage31" --reuse-cmdline; then
- echo "Failed to load kernel/initrd from ${DIR}"
+ if [ -z "$ipxeId" ]; then
+ echo "No iPXE menu id, guessing file names..."
+ download_retry "${base}/${SLX_BASE_PATH}/kernel" > "$newKernel" \
+ || perror "Failed to download new kernel."
+ download_retry "${base}/${SLX_BASE_PATH}/initramfs-stage31" > "$newInitRd" \
+ || perror "Failed to download new initramfs."
+ # Logo is not critical
+ download_retry "${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 ! kexec -l "${newKernel}" --initrd "${newInitRd}" --command-line="${newKcl}"; then
+ echo "Failed to load kernel/initrd from ${tempdir}"
exit 1
fi
}