echo ""
echo "Automatically selected kernels:"
echo "$boot_kernels"
+
+ pinned_kernel="$(get_first_line "$PINNED_KERNEL_CONF")"
+ if [ -n "$pinned_kernel" ]; then
+ echo ""
+ echo "Pinned kernel:"
+ echo "${pinned_kernel}"
+ fi
}
usage() {
warn " $0 clean [--dry-run]"
warn " $0 refresh [--hook <name>]"
warn " $0 kernel <add|remove> <kernel-version>"
+ warn " $0 kernel pin <kernel-version>"
+ warn " $0 kernel unpin"
warn " $0 kernel list"
warn " $0 status [--quiet]"
warn " $0 help"
echo " add/remove pve-kernel with ABI <kernel-version> to list of synced kernels, in addition to automatically selected ones."
echo " NOTE: you need to manually run 'refresh' once you're finished with adding/removing kernels from the list"
echo ""
+ echo "USAGE: $0 kernel pin <kernel-version>"
+ echo ""
+ echo " pin pve-kernel with ABI <kernel-version> as the default entry to be booted."
+ echo " NOTE: you need to manually run 'refresh' once you're finished with pinning kernels"
+ echo ""
+ echo "USAGE: $0 kernel unpin"
+ echo ""
+ echo " unpin sets the latest kernel as the default entry (undoes a previous pin)"
+ echo ""
echo "USAGE: $0 kernel list"
echo ""
echo " list kernel versions currently selected for inclusion on ESPs."
fi
}
+pin_kernel() {
+ ver="$1"
+
+ if [ -z "$ver" ]; then
+ warn "E: <kernel-version> is mandatory"
+ warn ""
+ exit 1
+ fi
+
+ if [ ! -e "/boot/vmlinuz-$ver" ]; then
+ warn "E: no kernel image found in /boot for '$ver', not setting default."
+ exit 1
+ fi
+ echo "$ver" > "$PINNED_KERNEL_CONF"
+ echo "Set kernel '$ver' $PINNED_KERNEL_CONF. Use the 'refresh' command to update the ESPs."
+}
+
+unpin_kernel() {
+ rm -f "$PINNED_KERNEL_CONF"
+ echo "Removed $PINNED_KERNEL_CONF. Use the 'refresh' command to update the ESPs."
+}
+
if [ -z "$1" ]; then
usage
exit 0
list_kernels
exit 0
;;
+ 'pin')
+ pin_kernel "$2"
+ exit 0
+ ;;
+ 'unpin')
+ unpin_kernel "$2"
+ exit 0
+ ;;
*)
warn "E: invalid 'kernel' subcommand '$cmd'."
warn ""
ESPTYPE='c12a7328-f81f-11d2-ba4b-00a0c93ec93b'
MANUAL_KERNEL_LIST="/etc/kernel/pve-efiboot-manual-kernels"
+PINNED_KERNEL_CONF="/etc/kernel/proxmox-boot-pin"
MOUNTROOT="${TMPDIR:-/var/tmp}/espmounts"
# relative to the ESP mountpoint
PMX_ESP_DIR="EFI/proxmox"
PMX_LOADER_CONF="loader/loader.conf"
+GRUB_PIN_SNIPPET="/etc/default/grub.d/proxmox-kernel-pin.cfg"
# adapted from /etc/kernel/postinst.d/apt-auto-removal as present in
# debian's apt package:
# - the second-latest kernel version
# - the latest kernel version of each series (e.g. 4.13, 4.15, 5.0) by
# marking the meta-packages
+# - the currently pinned kernel if any
kernel_keep_versions() {
eval "$(apt-config shell DPKG Dir::bin::dpkg/f)"
manual_kernels="$(cat "$MANUAL_KERNEL_LIST")"
fi
+ pinned_kernel="$(get_first_line "$PINNED_KERNEL_CONF")"
+
kernels="$(cat <<-EOF
$running_version
$install_version
$latest_2_versions
$series_metapackages
$oldseries_latest_kernel
+ $pinned_kernel
EOF
)"
done < "${file}"
echo "$line"
}
+
+set_grub_default() {
+ kver="$1"
+
+ if [ -z "${kver}" ]; then
+ rm -f "${GRUB_PIN_SNIPPET}"
+ else
+ # grub menu entry ids contain the internal root-device id (e.g. for zfs the GUID of
+ # the pool printed in hex) as this is independent of the ESP (or grub location)
+ # take it from /boot/grub/grub.cfg
+ root_devid=$(sed -rn "s/.*gnulinux-advanced-(.+)['] \{$/\1/p" \
+ /boot/grub/grub.cfg)
+ entry="gnulinux-advanced-${root_devid}>gnulinux-${kver}-advanced-${root_devid}"
+ echo "GRUB_DEFAULT=\"${entry}\"" > "${GRUB_PIN_SNIPPET}"
+ fi
+}
+
+set_systemd_boot_default() {
+ mountpoint="$1"
+ kver="$2"
+ if [ -z "${kver}" ]; then
+ entry="proxmox-*"
+ else
+ entry="proxmox-${kver}.conf"
+ fi
+
+ # replaces the current default entry, if one exists else append it at the end of the file
+ sed -ri "/^default /{h;s/ .*\$/ ${entry}/};\${x;/^$/{s//default ${entry}/;H};x}" \
+ "${mountpoint}/$PMX_LOADER_CONF"
+
+}
fi
warn "Copying and configuring kernels on ${path}"
copy_and_config_kernels "${mountpoint}"
+
+ pinned_kernel=$(get_first_line "${PINNED_KERNEL_CONF}")
+
if [ -d /sys/firmware/efi ]; then
+ set_systemd_boot_default "${mountpoint}" "${pinned_kernel}"
remove_old_kernels_efi "${mountpoint}"
else
+ set_grub_default "${pinned_kernel}"
remove_old_kernels_legacy "${mountpoint}"
mount --bind "${mountpoint}" "/boot"
update-grub