From de52667d406458bc4f5a21daa22c5176bfe15345 Mon Sep 17 00:00:00 2001 From: Jonathan Lebon Date: Mon, 5 Feb 2024 22:43:44 -0500 Subject: [PATCH] 40ignition-ostree: add ignition-ostree-mount-state-overlays.service The new experimental `opt-usrlocal-overlays` treefile knob[1] allows users to overlay packages with `/opt`/`/usr/local` content (and eventually, rebase to container images with content in those places). However, booting a base compose with this knob will break Ignition configs that currently write data in e.g. `/opt` since that now points to `/usr/lib/opt`, which is of course read-only. We need to assemble the state overlays from the initramfs so that those configs keep working seamlessly. This is a no-op if state overlays are off (status quo), but it'll make it easier for people and CI to test the feature. This is a tiny part of the required bits if we want to eventually turn this on in FCOS/RHCOS. The other major part is migrating existing systems. [1] https://github.com/coreos/rpm-ostree/pull/4728 --- ...nition-ostree-mount-state-overlays.service | 19 +++++++ .../ignition-ostree-mount-state-overlays.sh | 50 +++++++++++++++++++ .../40ignition-ostree/module-setup.sh | 4 ++ 3 files changed, 73 insertions(+) create mode 100644 overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-mount-state-overlays.service create mode 100755 overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-mount-state-overlays.sh diff --git a/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-mount-state-overlays.service b/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-mount-state-overlays.service new file mode 100644 index 0000000000..59fac81264 --- /dev/null +++ b/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-mount-state-overlays.service @@ -0,0 +1,19 @@ +[Unit] +Description=Ignition OSTree Mount State Overlays +DefaultDependencies=false +ConditionKernelCommandLine=|ostree +ConditionPathExists=|/run/ostree-live + +# Need to do this with all mount points active +After=ignition-mount.service +# Not strictly required, but both do /var things +After=ignition-ostree-populate-var.service + +# But *before* we start dumping files in there +Before=ignition-files.service + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/usr/libexec/ignition-ostree-mount-state-overlays mount +ExecStop=/usr/libexec/ignition-ostree-mount-state-overlays umount diff --git a/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-mount-state-overlays.sh b/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-mount-state-overlays.sh new file mode 100755 index 0000000000..84a987b6b7 --- /dev/null +++ b/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-mount-state-overlays.sh @@ -0,0 +1,50 @@ +#!/bin/bash +set -euo pipefail + +fatal() { + echo "$@" >&2 + exit 1 +} + +if [ $# -ne 1 ] || { [[ $1 != mount ]] && [[ $1 != umount ]]; }; then + fatal "Usage: $0 " +fi + +# if state overlays are not enabled, there's nothing to do +if ! ls /sysroot/usr/lib/systemd/system/local-fs.target.requires/ostree-state-overlay@*.service 2>/dev/null; then + exit 0 +fi + +do_mount() { + # be nice to persistent /var; if the top-level state overlay dir exists, + # then assume it's properly labeled + relabel=1 + state_overlays_dir=/sysroot/var/ostree/state-overlays + if [ -d ${state_overlays_dir} ]; then + relabel=0 + fi + for overlay in /usr/lib/opt /usr/local; do + escaped=$(systemd-escape --path "${overlay}") + overlay_dirs=${state_overlays_dir}/${escaped} + mkdir -p "${overlay_dirs}"/{upper,work} + # ideally we'd use `ostree admin state-overlay`, but that'd require + # pulling in bwrap and chroot which isn't yet in the FCOS initrd + mount -t overlay overlay /sysroot/${overlay} -o "lowerdir=/sysroot/${overlay},upperdir=${overlay_dirs}/upper,workdir=${overlay_dirs}/work" + done + if [ $relabel = 1 ]; then + coreos-relabel /var/ostree + # the above relabel will have relabeled the upperdir too; relabel that + # from the perspective of the mount point so it's not var_t + for overlay in /usr/lib/opt /usr/local; do + coreos-relabel ${overlay} + done + fi +} + +do_umount() { + for overlay in /usr/lib/opt /usr/local; do + umount /sysroot/${overlay} + done +} + +"do_$1" diff --git a/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/module-setup.sh b/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/module-setup.sh index 81ab59896b..d7fd9b650d 100755 --- a/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/module-setup.sh +++ b/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/module-setup.sh @@ -102,5 +102,9 @@ install() { inst_script "$moddir/coreos-check-rootfs-size" \ /usr/libexec/coreos-check-rootfs-size + install_ignition_unit ignition-ostree-mount-state-overlays.service + inst_script "$moddir/ignition-ostree-mount-state-overlays.sh" \ + /usr/libexec/ignition-ostree-mount-state-overlays + inst_script "$moddir/coreos-relabel" /usr/bin/coreos-relabel }