combustion/combustion
Fabian Vogt ec1e979ea6 Accepting request 929857 from home:mitko_zahariev:branches:devel:kubic:ignition
Changed the "Try disks next" section to check for both lower and upper case volume names. This is necessary for FAT/FAT32 volumes created under Windows.

OBS-URL: https://build.opensuse.org/request/show/929857
OBS-URL: https://build.opensuse.org/package/show/devel:kubic:ignition/combustion?expand=0&rev=22
2021-11-24 13:08:55 +00:00

184 lines
5.5 KiB
Bash

#!/bin/bash
# SPDX-FileCopyrightText: 2020 SUSE LLC
# SPDX-License-Identifier: GPL-2.0-or-later
set -euo pipefail
config_mount="/run/combustion/mount"
if [ "${1-}" = "--prepare" ]; then
# Mount config drive
mkdir -p "${config_mount}"
config_drive_found=0
# Try fw_cfg first
if [ -e "/sys/firmware/qemu_fw_cfg/by_name/opt/org.opensuse.combustion" ]; then
mkdir -p "${config_mount}/combustion"
if ! cp /sys/firmware/qemu_fw_cfg/by_name/opt/org.opensuse.combustion/script/raw \
"${config_mount}/combustion/script"; then
echo "Failed to copy script from fw_cfg!"
exit 1
fi
# TODO: Support other files, e.g. with a tarball or fs image?
config_drive_found=1
fi
# Try disks next - both lower and upper case
for label in combustion COMBUSTION ignition IGNITION; do
[ "${config_drive_found}" = "1" ] && break
[ -e "/dev/disk/by-label/${label}" ] || continue
if ! mount -o ro /dev/disk/by-label/${label} "${config_mount}"; then
echo "Failed to mount config drive!"
exit 1
fi
config_drive_found=1
done
if [ "${config_drive_found}" = "0" ]; then
echo "No config drive found"
exit 0
fi
# Check for the magic flag "# combustion: network" in the script
if [ -e "${config_mount}/combustion/script" ] \
&& grep -qE '^# combustion:(.*)\<network\>' "${config_mount}/combustion/script"; then
sh -s <<EOF
. /lib/dracut-lib.sh
getargbool 0 'rd.neednet' && exit 0
echo rd.neednet=1 > /etc/cmdline.d/40-combustion-neednet.conf
# Re-trigger generation of network rules and apply them
. /lib/dracut/hooks/pre-udev/60-net-genrules.sh
udevadm control --reload
udevadm trigger --subsystem-match net --action add
EOF
fi
exit 0
fi
# Use /dev/shm for data exchange
exchangedir="/dev/shm/combustion/"
delete_resolv_conf=0
cleanup() {
if findmnt "${config_mount}" >/dev/null; then
umount "${config_mount}" || true
rmdir "${config_mount}" || true
else
rm -rf "${config_mount}" || true
fi
rm -rf "${exchangedir}" || true
if [ "${delete_resolv_conf}" -eq 1 ]; then
rm -f /sysroot/etc/resolv.conf || true
fi
# umount and remount so that the new default subvol is used
umount -R /sysroot
# Manual umount confuses systemd sometimes because it's async and the
# .mount unit might still be active when the "start" is queued, making
# it a noop, which ultimately leaves /sysroot unmounted
# (https://github.com/systemd/systemd/issues/20329). To avoid that,
# wait until systemd processed the umount events. In a chroot (or with
# SYSTEMD_OFFLINE=1) systemctl always succeeds, so avoid an infinite loop.
if ! systemctl is-active does-not-exist.mount; then
while systemctl is-active sysroot.mount; do sleep 0.5; done
fi
systemctl start sysroot.mount
}
trap cleanup EXIT
# ignition-mount.service mounts stuff below /sysroot in ExecStart and umounts
# it on ExecStop, failing if umounting fails. This conflicts with the
# mounts/umounts done by combustion. Ignition is already done, so just stop it.
if systemctl --quiet is-active ignition-mount.service; then
systemctl stop ignition-mount.service
fi
if ! [ -d "${config_mount}/combustion" ]; then
echo "No config found - doing nothing."
exit 0
fi
# Make sure /sysroot is mounted
systemctl start sysroot.mount
# Copy config
mkdir "${exchangedir}"
config_dir="${exchangedir}/config"
cp -R "${config_mount}/combustion" "${config_dir}"
if ! [ -e "${config_dir}/script" ]; then
echo "No config script found."
exit 1
fi
# Have to take care of x-initrd.mount first and from the outside
awk '$4 ~ /x-initrd.mount/ { system("findmnt /sysroot" $2 " >/dev/null || mount -t " $3 " -o " $4 " " $1 " /sysroot" $2) }' /sysroot/etc/fstab
# Make sure the old snapshot is relabeled too, otherwise syncing its /etc fails.
if [ -e /sysroot/etc/selinux/.autorelabel ]; then
NEWROOT=/sysroot bash -c '. /lib/dracut-lib.sh; . /lib/dracut/hooks/pre-pivot/50-selinux-microos-relabel.sh'
fi
# Prepare chroot
for i in proc sys dev; do
mount --rbind /$i /sysroot/$i
done
mount --make-rslave /sysroot
# Mount everything we can, errors deliberately ignored
chroot /sysroot mount -a || true
# t-u needs writable /var/run and /tmp
findmnt /sysroot/run >/dev/null || mount -t tmpfs tmpfs /sysroot/run
findmnt /sysroot/tmp >/dev/null || mount -t tmpfs tmpfs /sysroot/tmp
# Fake a netconfig setup
if [ -r /etc/resolv.conf ]; then
mkdir -p /sysroot/run/netconfig/
cp /etc/resolv.conf /sysroot/run/netconfig/resolv.conf
if ! [ -e /sysroot/etc/resolv.conf ]; then
if ln -sf /run/netconfig/resolv.conf /sysroot/etc/resolv.conf; then
delete_resolv_conf=1
fi
fi
fi
if [ -x /sysroot/usr/sbin/transactional-update ]; then
# t-u doesn't allow running arbitrary commands and
# also ignores the shell's exit code, so DIY.
if ! chroot /sysroot transactional-update shell <<EOF; then
cd "${config_dir}"
chmod a+x script
./script
echo \$? > "${exchangedir}/retval"
EOF
echo "transactional-update failed"
exit 1
fi
if ! [ -e "${exchangedir}/retval" ] || [ "$(cat "${exchangedir}/retval")" -ne 0 ]; then
echo "Command failed, rolling back"
chroot /sysroot transactional-update --no-selfupdate rollback
exit 1
fi
# Snapshot got touched while the policy isn't active, needs relabeling again.
[ -e /sysroot/etc/selinux/.relabelled ] && >> /sysroot/etc/selinux/.autorelabel
else
mount -o remount,rw /sysroot
if ! chroot /sysroot sh -e -c "cd '${config_dir}'; chmod a+x script; ./script"; then
echo "Command failed"
exit 1
fi
chroot /sysroot snapper --no-dbus create -d "After combustion configuration" || :
fi
exit 0