From 68f6439499fe11fa43e2a4dbf94a76e2bd5ba829 Mon Sep 17 00:00:00 2001 From: Nikita Dubrovskii Date: Thu, 30 Sep 2021 10:44:30 +0200 Subject: [PATCH] overlay.d: create udev rule for `stable-root` disk Issue: https://github.com/coreos/fedora-coreos-tracker/issues/759 Signed-off-by: Nikita Dubrovskii --- .../coreos-root-symlink.service | 23 ++++++++++++ .../coreos-teardown-initramfs.sh | 4 +++ .../35coreos-ignition/create-root-symlink.sh | 35 +++++++++++++++++++ .../35coreos-ignition/module-setup.sh | 9 +++++ tests/kola/ignition/stable-root/config.bu | 10 ++++++ tests/kola/ignition/stable-root/test.sh | 31 ++++++++++++++++ 6 files changed, 112 insertions(+) create mode 100644 overlay.d/05core/usr/lib/dracut/modules.d/35coreos-ignition/coreos-root-symlink.service create mode 100755 overlay.d/05core/usr/lib/dracut/modules.d/35coreos-ignition/create-root-symlink.sh create mode 100644 tests/kola/ignition/stable-root/config.bu create mode 100755 tests/kola/ignition/stable-root/test.sh diff --git a/overlay.d/05core/usr/lib/dracut/modules.d/35coreos-ignition/coreos-root-symlink.service b/overlay.d/05core/usr/lib/dracut/modules.d/35coreos-ignition/coreos-root-symlink.service new file mode 100644 index 0000000000..8dd41c7c2e --- /dev/null +++ b/overlay.d/05core/usr/lib/dracut/modules.d/35coreos-ignition/coreos-root-symlink.service @@ -0,0 +1,23 @@ +[Unit] +Description=Create symlink to boot disk +ConditionPathExists=/etc/initrd-release +DefaultDependencies=no +Wants=systemd-udevd.service +After=systemd-udevd.service + +Requires=dev-disk-by\x2dlabel-root.device +After=dev-disk-by\x2dlabel-root.device +# And since the boot device may be on multipath; optionally wait for it to +# appear via the dynamic target. +After=coreos-multipath-wait.target +After=coreos-gpt-setup.service +Before=ignition-disks.service + +OnFailure=emergency.target +OnFailureJobMode=isolate + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/usr/sbin/create-root-symlink + diff --git a/overlay.d/05core/usr/lib/dracut/modules.d/35coreos-ignition/coreos-teardown-initramfs.sh b/overlay.d/05core/usr/lib/dracut/modules.d/35coreos-ignition/coreos-teardown-initramfs.sh index 7f8135ace7..b07b23d452 100755 --- a/overlay.d/05core/usr/lib/dracut/modules.d/35coreos-ignition/coreos-teardown-initramfs.sh +++ b/overlay.d/05core/usr/lib/dracut/modules.d/35coreos-ignition/coreos-teardown-initramfs.sh @@ -211,6 +211,10 @@ main() { # clean it up so that no information from outside of the # real root is passed on to NetworkManager in the real root rm -rf /run/NetworkManager/ + + # Remove udev rule for symlink to disk holding 'root' partition + rm -f /run/udev/rules.d/99-stable-root.rules + rm -f /dev/disk/by-id/coreos-root-disk } main diff --git a/overlay.d/05core/usr/lib/dracut/modules.d/35coreos-ignition/create-root-symlink.sh b/overlay.d/05core/usr/lib/dracut/modules.d/35coreos-ignition/create-root-symlink.sh new file mode 100755 index 0000000000..d8cc7ed635 --- /dev/null +++ b/overlay.d/05core/usr/lib/dracut/modules.d/35coreos-ignition/create-root-symlink.sh @@ -0,0 +1,35 @@ +#!/bin/bash +# Creates a stable device path for the `boot` disk when there's exactly one such +# disk, and creates nothing in other cases (e.g. rootfs RAID). Symlink is not +# propogated to the real root and gets removed in `coreos-teardown-initramfs` + +set -euo pipefail + +udev_trigger() { + udevadm trigger "$1" + udevadm settle +} + +# We should treat all paths (which have same WWN) to multipath disk as a single +# disk, but `WWN` could be empty in `lsblk` output, so we call `partx` to force +# kernel updating info about disks. Originally this issue was observed on s390x +for dev in $(lsblk -o NAME --noheadings --nodeps --list --paths); do + partx -u ${dev} || true +done +udev_trigger --subsystem-match=block + +LINK=disk/by-id/coreos-root-disk +PARTITIONS=() + +# Unique sorting all disks labeled `root` keeping one path to each mpath disk +mapfile -t PARTITIONS < <(lsblk -o WWN,LABEL,NAME,PKNAME --pairs --noheadings | grep 'LABEL="root"' | sed 's/WWN=\"\" //' | sort -u -k1,2) + +LENGTH=${#PARTITIONS[@]} +if [[ ${LENGTH} -eq 1 ]]; then + eval ${PARTITIONS[0]} + echo "Creating symlink '${LINK}' to '${PKNAME}' (contains 'root' partition '${NAME}')" + mkdir -p /run/udev/rules.d/ + echo "KERNEL==\"${PKNAME}\", SUBSYSTEM==\"block\", SYMLINK+=\"${LINK}\"" > /run/udev/rules.d/99-stable-root.rules + udevadm control --reload-rules + udev_trigger /dev/${PKNAME} +fi diff --git a/overlay.d/05core/usr/lib/dracut/modules.d/35coreos-ignition/module-setup.sh b/overlay.d/05core/usr/lib/dracut/modules.d/35coreos-ignition/module-setup.sh index a42bcc3724..d44212d691 100755 --- a/overlay.d/05core/usr/lib/dracut/modules.d/35coreos-ignition/module-setup.sh +++ b/overlay.d/05core/usr/lib/dracut/modules.d/35coreos-ignition/module-setup.sh @@ -22,6 +22,9 @@ install() { diff \ lsblk \ sed \ + sort \ + grep \ + partx \ sgdisk inst_simple "$moddir/coreos-diskful-generator" \ @@ -30,6 +33,9 @@ install() { inst_script "$moddir/coreos-gpt-setup.sh" \ "/usr/sbin/coreos-gpt-setup" + inst_script "$moddir/create-root-symlink.sh" \ + "/usr/sbin/create-root-symlink" + inst_script "$moddir/coreos-ignition-setup-user.sh" \ "/usr/sbin/coreos-ignition-setup-user" @@ -56,4 +62,7 @@ install() { "ignition-diskful.target" install_ignition_unit coreos-ignition-setup-user.service + + install_ignition_unit coreos-root-symlink.service \ + ignition-diskful.target } diff --git a/tests/kola/ignition/stable-root/config.bu b/tests/kola/ignition/stable-root/config.bu new file mode 100644 index 0000000000..073be8fc98 --- /dev/null +++ b/tests/kola/ignition/stable-root/config.bu @@ -0,0 +1,10 @@ +variant: fcos +version: 1.3.0 +storage: + disks: + - device: /dev/disk/by-id/coreos-root-disk + wipe_table: false + partitions: + - number: 5 + size_mib: 1024 + label: toor diff --git a/tests/kola/ignition/stable-root/test.sh b/tests/kola/ignition/stable-root/test.sh new file mode 100755 index 0000000000..d00e9ed5b2 --- /dev/null +++ b/tests/kola/ignition/stable-root/test.sh @@ -0,0 +1,31 @@ +#!/bin/bash +set -xeuo pipefail + +# This test makes sure that ignition is able to use symlink to the disk with `root` fs + +# We don't need to test this on every platform. If it passes in +# one place it will pass everywhere. +# kola: { "platforms": "qemu-unpriv" } + +ok() { + echo "ok" "$@" +} + +fatal() { + echo "$@" >&2 + exit 1 +} + +unit="coreos-root-symlink.service" +link="/dev/disk/by-id/coreos-root-disk" + +eval $(journalctl -o export MESSAGE_ID=39f53479d3a045ac8e11786248231fbf -u ${unit} | grep JOB_RESULT) +if [[ "${JOB_RESULT}" != "done" ]]; then + fatal "${unit} failed" +fi + +if [[ -h ${link} ]]; then + fatal "${unit} failed: ${link} still exists" +fi + +ok "${unit} is ok"