summaryrefslogtreecommitdiffstats
path: root/core/modules/kexec-reboot/data/opt/openslx/scripts/systemd-kexec_load
blob: 27be324a43251f568536cf8211751fe281ccf418 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#!/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 <base> <relative_or_absolute>
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