umorpha-boxes/bin/umorpha-update

121 lines
3.4 KiB
Bash
Executable File

#!/usr/bin/env bash
# Copyright (C) 2023 Umorpha Systems
# SPDX-License-Identifier: AGPL-3.0-or-later
set -euE -o pipefail
v() {
printf >&2 ' $ %s\n' "${*@Q}"
"$@"
}
main() {
local rootfs size
case "$1" in
*rootfs*)
rootfs="$1"
size=$(stat --format='%s' -- "$rootfs")
;;
--stdin=*)
rootfs=/dev/stdin
size=${1#--stdin=}
;;
*)
echo >&2 "!! Filename '${1}' does not look like a rootfs filename"
return 2
;;
esac
########################################################################
cleanup=()
_do_cleanup() {
if [[ $? == 0 ]]; then
echo ":: Cleaning up..."
else
echo >&2 "!! ERROR! Cleaning up..."
fi
for (( i=${#cleanup[@]}-1; i >= 0; i-- )); do
eval "${cleanup[$i]}"
done
}
trap '_do_cleanup' EXIT
########################################################################
local booted other
booted=$(awk '$2 == "/run/umorpha-root/root"{print $1}' </proc/mounts)
booted=${booted##*_}
if [[ $booted == a ]]; then
other=b
else
other=a
fi
echo ":: Installing '${rootfs}' to slot '$other'"
v rm -f -- "/boot/grub/grub_$other.cfg"
if [[ -e /dev/mapper/vg_umorpha-lv_root_$other ]]; then
# Ugg, lvresize exits with non-zero for no-ops, which we can't
# even really do a pre-flight check for since it might round a
# size up.
v lvresize --size="${size}b" "/dev/mapper/vg_umorpha-lv_root_$other" || true
else
v lvcreate --zero=y --wipesignatures=y --yes --name="lv_root_$other" \
--size="${size}b" vg_umorpha
fi
if [[ "$rootfs" == /dev/stdin ]]; then
v pv --size="${size}" >"/dev/mapper/vg_umorpha-lv_root_$other"
else
v pv -- "$rootfs" >"/dev/mapper/vg_umorpha-lv_root_$other"
fi
########################################################################
local tmpdir
tmpdir="$(mktemp -dt "${0##*/}.XXXXXXXXXX")"
cleanup+="rmdir -- ${tmpdir@Q}"
########################################################################
echo ":: Configuring boot"
local selector_boot selector_root selector_overlay
selector_root="$( blkid --output=export "/dev/mapper/vg_umorpha-lv_root_$other" | grep ^UUID=)"
selector_boot="$( xargs -a /proc/cmdline printf '%s\n' | sed -n 's/^boot=//p')"
selector_overlay="$(xargs -a /proc/cmdline printf '%s\n' | sed -n 's/^overlay_root=//p')"
v declare -p selector_boot selector_root selector_overlay
mkdir "$tmpdir/mnt"
cleanup+=("rmdir -- ${tmpdir@Q}/mnt")
v mount -o ro -- "/dev/mapper/vg_umorpha-lv_root_$other" "$tmpdir/mnt"
cleanup+=("v umount ${tmpdir@Q}/mnt")
v mount -o bind -- /etc/mkinitcpio.d "${tmpdir}/mnt/etc/mkinitcpio.d"
cleanup+=("v umount ${tmpdir@Q}/mnt/etc/mkinitcpio.d")
v mount -o bind -- /boot "${tmpdir}/mnt/boot"
cleanup+=("v umount ${tmpdir@Q}/mnt/boot")
{
for krnl in "$tmpdir/mnt"/usr/lib/modules/*/vmlinuz; do
pkgbase=$(cat -- ${krnl%vmlinuz}pkgbase)
cat <<-EOF
menuentry 'Parabola GNU/Linux-libre, slot ${other}, ${pkgbase} kernel'
set search --no-floppy --fs-uuid --set=root ${selector_boot#UUID=}
echo 'Loading ${pkgbase} kernel...'
linux /vmlinuz-${pkgbase} root=$selector_root overlay_root=$selector_overlay boot=$selector_boot rw
echo 'Loading initial ramdisk...'
initrd /initramfs-${pkgbase}.img
echo 'Booting...'
boot
EOF
done
} | install -Dm600 /dev/stdin "/boot/grub/grub_$other.cfg"
v arch-chroot -- "$tmpdir/mnt" sh -c "printf '%s\n' usr/lib/modules/*/vmlinuz | /usr/share/libalpm/scripts/mkinitcpio install"
}
main "$@"