-
Notifications
You must be signed in to change notification settings - Fork 0
/
ubuntukernel-load.sh
executable file
·160 lines (134 loc) · 5.02 KB
/
ubuntukernel-load.sh
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#!/bin/bash
#
# Rewrite Scaleway initrd and kexec into Ubuntu kernel
#
# Author: stuffo (https://github.com/stuffo/)
# Location: https://github.com/stuffo/scaleway-ubuntukernel
#
# kernel modules to add to the Scaleway initrd to enable Arch kernel network
# and to mount nbd devices. If module is missing, we skip it as it may be a
# kernel that does not require it. Path prefix is /lib/modules/<kernel version>
REQUIRED_MODULES="net/phy/phylink net/virtio_net block/virtio_blk block/nbd dca/dca i2c/algos/i2c-algo-bit pps/pps_core ptp/ptp net/ethernet/intel/igb/igb"
# current Scaleway IPXE boot script
SCW_IPXE_SCRIPT="http://169.254.42.42/ipxe"
# where to account current Ubuntu kernel version
UBUNTU_KERNEL_STAMP="/boot/.ubuntukernel-version"
# default value initialization
INITRD_KERNEL_VERSION="none"
UBUNTU_KERNEL_VERSION="wedontknowyet"
set -eu
set -o pipefail
shopt -s nullglob
shopt -s dotglob
umask 022
export LC_ALL=C
export LANG=C
unset LANGUAGE
log() {
echo "$@" >&2
}
fatal() {
log "$@"
log "Exiting."
exit 1
}
rebuild_initrd() {
local workdir=$(mktemp -d)
# get original initrd url from IPXE
local orig_initrd=$(curl -s $SCW_IPXE_SCRIPT | grep ^initrd | grep -P -o 'http://\S+')
log "Scaleway initrd: $orig_initrd"
log "+ get scaleway initrd"
curl -s -o $workdir/uInitrd.orig.gz $orig_initrd
log "+ extract scaleway initrd"
local initrd_dir=$(mktemp -d initrd.XXXXXX)
( cd $initrd_dir && gunzip < $workdir/uInitrd.orig.gz | cpio -i --quiet > /dev/null )
rm -f $workdir/uInitrd.orig.gz
# copy kernel modules
local insmod_command=
local modname mod
local initrd_mod_dir="$initrd_dir/lib/modules/$UBUNTU_KERNEL_VERSION"
mkdir -p $initrd_mod_dir
for mod in $REQUIRED_MODULES ; do
if [ -e /lib/modules/$UBUNTU_KERNEL_VERSION/kernel/drivers/$mod.ko.gz ] ; then
log "+ add module $mod to initrd"
modname=$(basename $mod).ko
cp /lib/modules/$UBUNTU_KERNEL_VERSION/kernel/drivers/$mod.ko $initrd_mod_dir/$modname
insmod_command=$insmod_command"insmod /lib/modules/$UBUNTU_KERNEL_VERSION/$modname\n"
else
log "+ skipping module $mod for initrd. not found."
fi
done
log "+ prepend loading modules before entering scaleway initrd"
mv $initrd_dir/init $initrd_dir/init.scw
cat > $initrd_dir/init <<-EOF
#!/bin/sh
# this was added by ubuntukernel-load.sh to load Ubuntu kernel modules
# before executing the Scaleway init script. Please do not remove.
/bin/busybox mkdir -p /bin /sbin /etc /proc /sys /newroot /usr/bin /usr/sbin
/bin/busybox --install -s
EOF
echo -e $insmod_command >> $initrd_dir/init
echo '. init.scw' >> $initrd_dir/init
chmod 755 $initrd_dir/init
log "+ rebuild initrd archive"
( cd $initrd_dir && find . -print0 | cpio --quiet --null -o --format=newc | gzip -9 > /boot/uInitrd-$UBUNTU_KERNEL_VERSION.gz )
# record kernel version we just integrated into intird for later
echo $UBUNTU_KERNEL_VERSION > $UBUNTU_KERNEL_STAMP
rm -fr $initrd_dir $workdir
}
shutdown_initrd_kexec_check() {
# compat for old initrds which don't know how to kexec
if ! grep -q 'kexec -e' /run/initramfs/shutdown ; then
log "current initrd won't kexec automatically. patching it."
fixup_shutdown_initrd
fi
}
fixup_shutdown_initrd() {
mv /run/initramfs/shutdown /tmp/oldshutdown
{
head -n -1 /tmp/oldshutdown
echo "kexec -e"
} > /run/initramfs/shutdown && chmod 755 /run/initramfs/shutdown
rm -f /tmp/oldshutdown
}
get_kernel_version() {
# i guess /vmlinuz always points to the current kernel
UBUNTU_KERNEL_VERSION=$(readlink /vmlinuz | cut -f2- -d-)
if [ -r $UBUNTU_KERNEL_STAMP ] ; then
INITRD_KERNEL_VERSION=$(cat $UBUNTU_KERNEL_STAMP)
fi
log "Ubuntu kernel version: $UBUNTU_KERNEL_VERSION"
log "Initrd kernel version: $INITRD_KERNEL_VERSION"
}
sanity_checks() {
[ ${EUID} -eq 0 ] || fatal "Script must be run as root."
[ ${UID} -eq 0 ] || fatal "Script must be run as root."
if [ ! -r /proc/sys/kernel/kexec_load_disabled ] ; then
fatal "kernel has no kexec support. please change bootscript."
fi
if [ ! -x /run/initramfs/sbin/kexec ] ; then
fatal "current initrd has no kexec binary. kexec will fail."
fi
exit_if_disabled
}
# kill switch
exit_if_disabled() {
if scw-metadata |grep -q "TAGS_[[:digit:]]=ubuntukernel_disabled" ; then
fatal "ubuntukernel load disabled via server tag."
fi
}
#
# main
#
sanity_checks
shutdown_initrd_kexec_check
get_kernel_version
if [ "$UBUNTU_KERNEL_VERSION" != "$INITRD_KERNEL_VERSION" ] ; then
rebuild_initrd
fi
# we disable some features of the Scaleway initrd as they are superfluous
# for a kexeced environment
log "Kexec engaged. Make it So!"
kexec -l /boot/vmlinuz-$UBUNTU_KERNEL_VERSION \
--initrd=/boot/uInitrd-$UBUNTU_KERNEL_VERSION.gz \
--command-line="$(cat /proc/cmdline) is_in_kexec=yes NO_SIGNAL_STATE=1 DONT_FETCH_KERNEL_MODULES=1 NO_NTPDATE=1 ubuntukernel" && systemctl kexec