From 8bb7d9c4af1c7298d04c32ca6ed1258b29d3c367 Mon Sep 17 00:00:00 2001 From: Kai Lueke Date: Tue, 25 Jul 2023 16:20:18 +0200 Subject: [PATCH 1/8] initrd-setup-root: Add comments for future improvements --- dracut/99setup-root/initrd-setup-root-after-ignition | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dracut/99setup-root/initrd-setup-root-after-ignition b/dracut/99setup-root/initrd-setup-root-after-ignition index 4be1c31..5355bed 100755 --- a/dracut/99setup-root/initrd-setup-root-after-ignition +++ b/dracut/99setup-root/initrd-setup-root-after-ignition @@ -15,6 +15,7 @@ function download_and_verify() { # Downloads release artifact to /sysroot/$name and verifies $name.sig with gpg # Expects the env vars: FLATCAR_BOARD, VERSION local name="$1" + # TODO: We should use update.release.flatcar-linux.net and then decode the payload local channel="" case $(echo "${VERSION}" | cut -d . -f 2) in 0) channel="alpha" ;; @@ -121,6 +122,8 @@ if [ "${OEMID}" != "" ] && [ -e "/sysroot/oem/sysext/active-oem-${OEMID}" ]; the echo "Did not find ${SYSEXT_OEM_PART} nor ${SYSEXT_ROOT_PART}, downloading" >&2 systemctl start --quiet systemd-networkd systemd-resolved download_and_verify "oem-${OEMID}.raw" + # TODO: This can be removed once we download the update payload from update.release.flatcar-linux.net + # because it won't be the "initial" MVP sysext mkdir -p /run/_oem mount "/sysroot/oem-${OEMID}.raw" /run/_oem/ if grep -q SYSEXT_LEVEL=1.0 "/run/_oem/usr/lib/extension-release.d/extension-release.oem-${OEMID}" ; then From 31616d686c5ac3e0baed3c1605d1705112fdc0ae Mon Sep 17 00:00:00 2001 From: Kai Lueke Date: Tue, 25 Jul 2023 16:21:01 +0200 Subject: [PATCH 2/8] initrd-setup-root: Use the right filename for sysext image The filename should have a version suffix but didn't in the fallback download case when it's not the "initial" MVP sysext. Reuse the path we have prepared for the symlink target when moving to ensure that the file has the version suffix. --- dracut/99setup-root/initrd-setup-root-after-ignition | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dracut/99setup-root/initrd-setup-root-after-ignition b/dracut/99setup-root/initrd-setup-root-after-ignition index 5355bed..956bd7c 100755 --- a/dracut/99setup-root/initrd-setup-root-after-ignition +++ b/dracut/99setup-root/initrd-setup-root-after-ignition @@ -133,15 +133,15 @@ if [ "${OEMID}" != "" ] && [ -e "/sysroot/oem/sysext/active-oem-${OEMID}" ]; the umount "/sysroot/oem-${OEMID}.raw" mkdir -p /sysroot/oem/sysext/ if [ "${ACTIVE_OEM}" != "" ]; then - mv "/sysroot/oem-${OEMID}.raw" "/sysroot/${ACTIVE_OEM}" + mv "/sysroot/oem-${OEMID}.raw" "/sysroot${ACTIVE_OEM}" else echo "Trying to place /sysroot/oem-${OEMID}.raw on OEM partition" >&2 - if mv "/sysroot/oem-${OEMID}.raw" /sysroot/oem/sysext/; then + if mv "/sysroot/oem-${OEMID}.raw" "/sysroot${SYSEXT_OEM_PART}"; then ACTIVE_OEM="${SYSEXT_OEM_PART}" else echo "That failed, moving it to right location on root partition" >&2 mkdir -p /sysroot/etc/flatcar/oem-sysext/ - mv "/sysroot/oem-${OEMID}.raw" /sysroot/etc/flatcar/oem-sysext/ + mv "/sysroot/oem-${OEMID}.raw" "/sysroot${SYSEXT_ROOT_PART}" ACTIVE_OEM="${SYSEXT_ROOT_PART}" fi fi From dd61fd9e5ec394998da758e50c3a62c3a7617ab7 Mon Sep 17 00:00:00 2001 From: Kai Lueke Date: Tue, 25 Jul 2023 16:29:18 +0200 Subject: [PATCH 3/8] initrd-setup-root: Make retry logic more explicit The retry logic in the loop relied on the if statement after it. Move the failure into the retry loop. --- dracut/99setup-root/initrd-setup-root-after-ignition | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/dracut/99setup-root/initrd-setup-root-after-ignition b/dracut/99setup-root/initrd-setup-root-after-ignition index 956bd7c..654aaf4 100755 --- a/dracut/99setup-root/initrd-setup-root-after-ignition +++ b/dracut/99setup-root/initrd-setup-root-after-ignition @@ -31,7 +31,11 @@ function download_and_verify() { URLS+=("https://bincache.flatcar-linux.net/images/${FLATCAR_BOARD/-usr}/${VERSION}/${name}") local COUNT="" local URL="" - for URL in "${URLS[@]}"; do + for URL in "${URLS[@]}" LAST; do + if [ "${URL}" = LAST ]; then + echo "Failed to download required sysext image ${name}" >&2 + exit 1 # Fail the boot + fi # Workaround: Once curl starts and fails to resolve a DNS name (due to a race or temporary failure), # it sticks to it for each retry, making the retry pointless. Therefore, we first have to # add a curl waiter that does the DNS retry and won't be stuck (nor waste 30*60 seconds). @@ -41,15 +45,10 @@ function download_and_verify() { fi sleep 1 done - # If the loop terminated without the break, rely on the command below to fail usrcurl -o "/sysroot/${name}" "${URL}" || { rm -f "/sysroot/${name}" ; continue ; } usrcurl -o "/sysroot/${name}.sig" "${URL}.sig" || { rm -f "/sysroot/${name}.sig" ; continue ; } break done - if [ ! -e "/sysroot/${name}" ] || [ ! -e "/sysroot/${name}.sig" ]; then - echo "Failed to download required sysext image ${name}" >&2 - exit 1 # Fail the boot - fi local GPG_KEY="" local GPG_LONG_ID="" # Extract public key from flatcar-install From 0ed8da3f9e8d87632c6024999fbb5df21edc3221 Mon Sep 17 00:00:00 2001 From: Kai Lueke Date: Tue, 25 Jul 2023 20:00:19 +0200 Subject: [PATCH 4/8] initrd-setup-root: Allow to delete folders in migration action The list of old OEM files to clean up when migrating to an OEM sysext can have many files which might have changing names but since they are part of a common subfolder, can be removed easily through removing the whole folder. Support deleting folders in the migration logic. --- dracut/99setup-root/initrd-setup-root-after-ignition | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dracut/99setup-root/initrd-setup-root-after-ignition b/dracut/99setup-root/initrd-setup-root-after-ignition index 654aaf4..77185ba 100755 --- a/dracut/99setup-root/initrd-setup-root-after-ignition +++ b/dracut/99setup-root/initrd-setup-root-after-ignition @@ -158,7 +158,7 @@ if [ "${OEMID}" != "" ] && [ -e "/sysroot/oem/sysext/active-oem-${OEMID}" ]; the # For each OEMID, delete known old files under /oem/ and /etc/ based on the contents of the flag file # (The list is maintained in the update-engine post-inst action) while IFS="" read -r entry; do - rm -f "${entry}" || true + rm -rf "${entry}" || true done < "/sysroot/oem/sysext/migrate-oem-${OEMID}" rm -f "/sysroot/oem/sysext/migrate-oem-${OEMID}" fi From 5aa8aa2c82a30008fb4e34554330a96cf022a214 Mon Sep 17 00:00:00 2001 From: Kai Lueke Date: Tue, 25 Jul 2023 21:00:05 +0200 Subject: [PATCH 5/8] initrd-setup-root: Migrate cloud-init enablement symlink The old OEM setup was creating and enabling a cloud-init service unit from the default.ign file on the rootfs. When deleting this, we need to ensure that cloud-init is still enabled by enabling the inbuilt service unit from the base image. Special-case the removal of the cloud-init enablement symlink to create it again with the new target. --- dracut/99setup-root/initrd-setup-root-after-ignition | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/dracut/99setup-root/initrd-setup-root-after-ignition b/dracut/99setup-root/initrd-setup-root-after-ignition index 77185ba..60314b2 100755 --- a/dracut/99setup-root/initrd-setup-root-after-ignition +++ b/dracut/99setup-root/initrd-setup-root-after-ignition @@ -158,7 +158,11 @@ if [ "${OEMID}" != "" ] && [ -e "/sysroot/oem/sysext/active-oem-${OEMID}" ]; the # For each OEMID, delete known old files under /oem/ and /etc/ based on the contents of the flag file # (The list is maintained in the update-engine post-inst action) while IFS="" read -r entry; do - rm -rf "${entry}" || true + if [ "${entry}" = "/sysroot/etc/systemd/system/multi-user.target.wants/oem-cloudinit.service" ] && [ -L "/sysroot/etc/systemd/system/multi-user.target.wants/oem-cloudinit.service" ]; then + ln -fs /usr/lib/systemd/system/oem-cloudinit.service /sysroot/etc/systemd/system/multi-user.target.wants/oem-cloudinit.service || true + else + rm -rf "${entry}" || true + fi done < "/sysroot/oem/sysext/migrate-oem-${OEMID}" rm -f "/sysroot/oem/sysext/migrate-oem-${OEMID}" fi From 5497a192fa0e6fbc65a9043142f133f39d861afc Mon Sep 17 00:00:00 2001 From: Kai Lueke Date: Tue, 25 Jul 2023 22:27:43 +0200 Subject: [PATCH 6/8] initrd-setup-root: Expect regular paths for the migration action First the plan was to request that the migration list should use /sysroot/ as prefix but if someone forgets that and writes regular paths it would remove things in the initrd instead (or nothing). Simplify the interface by expecting regular paths and prepending /sysroot on removal. --- dracut/99setup-root/initrd-setup-root-after-ignition | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dracut/99setup-root/initrd-setup-root-after-ignition b/dracut/99setup-root/initrd-setup-root-after-ignition index 60314b2..c9bcfc6 100755 --- a/dracut/99setup-root/initrd-setup-root-after-ignition +++ b/dracut/99setup-root/initrd-setup-root-after-ignition @@ -158,10 +158,10 @@ if [ "${OEMID}" != "" ] && [ -e "/sysroot/oem/sysext/active-oem-${OEMID}" ]; the # For each OEMID, delete known old files under /oem/ and /etc/ based on the contents of the flag file # (The list is maintained in the update-engine post-inst action) while IFS="" read -r entry; do - if [ "${entry}" = "/sysroot/etc/systemd/system/multi-user.target.wants/oem-cloudinit.service" ] && [ -L "/sysroot/etc/systemd/system/multi-user.target.wants/oem-cloudinit.service" ]; then + if [ "${entry}" = "/etc/systemd/system/multi-user.target.wants/oem-cloudinit.service" ] && [ -L "/sysroot/etc/systemd/system/multi-user.target.wants/oem-cloudinit.service" ]; then ln -fs /usr/lib/systemd/system/oem-cloudinit.service /sysroot/etc/systemd/system/multi-user.target.wants/oem-cloudinit.service || true - else - rm -rf "${entry}" || true + elif [ "${entry}" != "" ]; then + rm -rf "/sysroot${entry}" || true fi done < "/sysroot/oem/sysext/migrate-oem-${OEMID}" rm -f "/sysroot/oem/sysext/migrate-oem-${OEMID}" From 9aa0a0d2e4c763b3ab9fbbff13ad4229746e6697 Mon Sep 17 00:00:00 2001 From: Kai Lueke Date: Wed, 26 Jul 2023 11:15:02 +0200 Subject: [PATCH 7/8] initrd-setup-root: Improve Flatcar extension config format A simple list of extensions to enable is not enough in case we want to move parts of the base image to an extension because then we would have to enable it by default. This requires an option for the user to explicity disable it. Add support for reading the OS default extensions from /usr and allow that the user disables extensions through writing "-NAME" in the extension config file in /etc. --- dracut/99setup-root/initrd-setup-root-after-ignition | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/dracut/99setup-root/initrd-setup-root-after-ignition b/dracut/99setup-root/initrd-setup-root-after-ignition index c9bcfc6..d5c3a9d 100755 --- a/dracut/99setup-root/initrd-setup-root-after-ignition +++ b/dracut/99setup-root/initrd-setup-root-after-ignition @@ -171,9 +171,12 @@ fi # Manage optional Flatcar extensions that are coupled to the OS version. # They are only stored on the root partition but not directly in /etc/extensions/ because there # can only be one file for the extension name (this could be covered by the ".v directory" proposal). -# The enabled-sysext.conf file contains the names per line and supports comments, -# update-engine uses this file to know which extensions to download. -for NAME in $(grep -o '^[^#]*' /sysroot/etc/flatcar/enabled-sysext.conf || true); do +# The enabled-sysext.conf file is read from /etc and /usr and contains one name per line, +# and when the name is prefixed with a "-" it means that the extension should be disabled if enabled by default in the file from /usr. +# It may contain comments starting with "#" at the beginning of a line or after a name. +# The file is also used in update-engine to know which extensions to download. +# Note that we don't need "{ grep || true ; }" to suppress the match return code because in for _ in $(grep...) return codes are ignored +for NAME in $(grep -h -o '^[^#]*' /sysroot/etc/flatcar/enabled-sysext.conf /sysroot/usr/share/flatcar/enabled-sysext.conf | grep -v -x -f <(grep '^-' /sysroot/etc/flatcar/enabled-sysext.conf | cut -d - -f 2-) | grep -v -P '^(-).*'); do ACTIVE_EXT="/etc/flatcar/sysext/flatcar-${NAME}-${VERSION}.raw" if [ ! -e "/sysroot/${ACTIVE_EXT}" ]; then echo "Did not find ${ACTIVE_EXT}" >&2 From 9392dd21a832bfecfa015165845bf2b2075c46b3 Mon Sep 17 00:00:00 2001 From: Kai Lueke Date: Wed, 30 Aug 2023 17:31:31 +0200 Subject: [PATCH 8/8] initrd-setup-root: Get list of old OEM files from /usr To have one place where the list of old OEM files to clean up is specified it is now read from /usr. --- dracut/99setup-root/initrd-setup-root-after-ignition | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dracut/99setup-root/initrd-setup-root-after-ignition b/dracut/99setup-root/initrd-setup-root-after-ignition index d5c3a9d..8415b98 100755 --- a/dracut/99setup-root/initrd-setup-root-after-ignition +++ b/dracut/99setup-root/initrd-setup-root-after-ignition @@ -156,14 +156,14 @@ if [ "${OEMID}" != "" ] && [ -e "/sysroot/oem/sysext/active-oem-${OEMID}" ]; the if [ -e "/sysroot/oem/sysext/migrate-oem-${OEMID}" ]; then echo "Found migration flag, deleting known old OEM partition files" >&2 # For each OEMID, delete known old files under /oem/ and /etc/ based on the contents of the flag file - # (The list is maintained in the update-engine post-inst action) + # (The list is maintained in the coreos-base/misc-files package) while IFS="" read -r entry; do if [ "${entry}" = "/etc/systemd/system/multi-user.target.wants/oem-cloudinit.service" ] && [ -L "/sysroot/etc/systemd/system/multi-user.target.wants/oem-cloudinit.service" ]; then ln -fs /usr/lib/systemd/system/oem-cloudinit.service /sysroot/etc/systemd/system/multi-user.target.wants/oem-cloudinit.service || true elif [ "${entry}" != "" ]; then rm -rf "/sysroot${entry}" || true fi - done < "/sysroot/oem/sysext/migrate-oem-${OEMID}" + done < "/sysroot/usr/share/flatcar/oems/${OEMID}" rm -f "/sysroot/oem/sysext/migrate-oem-${OEMID}" fi fi