Accepting request 835192 from home:favogt:combustion

- Overhaul configuration fetching:
  * Add udev rules to wait for either ignition, combustion or
    fw_cfg drives
  * Allow combustion.firstboot in addition to ignition.firstboot
  M combustion
  A combustion-prepare.service
  M combustion.service
  M module-setup.sh
- Bump version to 0.2

OBS-URL: https://build.opensuse.org/request/show/835192
OBS-URL: https://build.opensuse.org/package/show/devel:kubic:ignition/combustion?expand=0&rev=7
This commit is contained in:
Ignaz Forster 2020-09-18 07:12:39 +00:00 committed by Git OBS Bridge
parent a22939cb1d
commit 651ee08f24
8 changed files with 99 additions and 22 deletions

23
README
View File

@ -13,12 +13,17 @@ snapshot, so that no reboot is needed.
How to use it How to use it
------------- -------------
To be compatible and co-installable with ignition The configuration files are copied from a filesystem with the LABEL
(https://github.com/coreos/ignition), the configuration files are copied from "combustion", but to be compatible and co-installable with ignition
a filesystem with the LABEL "ignition". (https://github.com/coreos/ignition), the LABEL "ignition" is used as fallback.
It expects a directory "combustion" at the root level of the filesystem and It expects a directory "combustion" at the root level of the filesystem and
a file "script" inside, which is executed inside a transactional-update shell. a file "script" inside, which is executed inside a transactional-update shell.
If a QEMU fw_cfg blob with the name "opt/org.opensuse.combustion/script" is
found, it is preferred and the content of that is used as script.
Example parameter for QEMU:
-fw_cfg name=opt/org.opensuse.combustion/script,file=/var/combustion-script
Example for formatting a USB drive and adding a config, which installs the Example for formatting a USB drive and adding a config, which installs the
"vim-small" package and creates a /root/welcome file: "vim-small" package and creates a /root/welcome file:
@ -54,12 +59,12 @@ kernel commandline.
If this option is found on the kernel cmdline, combustion.service's If this option is found on the kernel cmdline, combustion.service's
ConditionKernelCommandLine is fulfilled and it'll be required by initrd.target. ConditionKernelCommandLine is fulfilled and it'll be required by initrd.target.
This pulls in combustion-prepare.service, which runs after the config drive This pulls in combustion-prepare.service, which runs after the config drive or
with LABEL=ignition appears. It is mounted and if the "network" flag comment is QEMU fw_cfg blob appears (see combustion.rules for details). It is read and if
present, enables networking for later. After /sysroot is mounted and network is the "network" flag comment is present, enables networking for later.
up (if enabled), combustion.service runs, which tries to activate all After /sysroot is mounted and network is up (if enabled), combustion.service
mountpoints in the system's /etc/fstab and then calls transactional-update runs, which tries to activate all mountpoints in the system's /etc/fstab and
in a chroot. then calls transactional-update in a chroot.
In this transactional-update session the script is started and the exit code In this transactional-update session the script is started and the exit code
recorded. If the script failed, transactional-update rollback is called and recorded. If the script failed, transactional-update rollback is called and

View File

@ -9,14 +9,37 @@ if [ "${1-}" = "--prepare" ]; then
# Mount config drive # Mount config drive
mkdir -p "${config_mount}" mkdir -p "${config_mount}"
if ! [ -e /dev/disk/by-label/ignition ]; then config_drive_found=0
echo "No config drive found"
exit 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 fi
if ! mount -o ro /dev/disk/by-label/ignition "${config_mount}"; then # Try disks next
echo "Failed to mount config drive!" for label in combustion ignition; do
exit 1 [ "${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 fi
# Check for the magic flag "# combustion: network" in the script # Check for the magic flag "# combustion: network" in the script
@ -44,6 +67,8 @@ cleanup() {
if findmnt "${config_mount}" >/dev/null; then if findmnt "${config_mount}" >/dev/null; then
umount "${config_mount}" || true umount "${config_mount}" || true
rmdir "${config_mount}" || true rmdir "${config_mount}" || true
else
rm -rf "${config_mount}" || true
fi fi
rm -rf "${exchangedir}" || true rm -rf "${exchangedir}" || true

View File

@ -2,11 +2,14 @@
Description=Combustion (preparations) Description=Combustion (preparations)
DefaultDependencies=false DefaultDependencies=false
ConditionKernelCommandLine=ignition.firstboot # Systemd evaluates Requires/After before conditions, so this unit is pulled in
# even when combustion.service won't run.
ConditionKernelCommandLine=|ignition.firstboot
ConditionKernelCommandLine=|combustion.firstboot
# Config drive has to be available # Config drive has to be available
Wants=dev-disk-by\x2dlabel-ignition.device Wants=dev-combustion-config.device
After=dev-disk-by\x2dlabel-ignition.device After=dev-combustion-config.device
# If both Ignition and Combustion are active make sure to run their # If both Ignition and Combustion are active make sure to run their
# configuration scripts sequentially, as both try to mount the configuration # configuration scripts sequentially, as both try to mount the configuration

View File

@ -1,3 +1,16 @@
-------------------------------------------------------------------
Thu Sep 17 10:56:44 UTC 2020 - Fabian Vogt <fvogt@suse.com>
- Overhaul configuration fetching:
* Add udev rules to wait for either ignition, combustion or
fw_cfg drives
* Allow combustion.firstboot in addition to ignition.firstboot
M combustion
A combustion-prepare.service
M combustion.service
M module-setup.sh
- Bump version to 0.2
------------------------------------------------------------------- -------------------------------------------------------------------
Mon Sep 14 09:20:49 UTC 2020 - Ignaz Forster <iforster@suse.com> Mon Sep 14 09:20:49 UTC 2020 - Ignaz Forster <iforster@suse.com>

27
combustion.rules Normal file
View File

@ -0,0 +1,27 @@
# SPDX-FileCopyrightText: 2020 SUSE LLC
# SPDX-License-Identifier: GPL-2.0-only
# These rules are needed to work around two systemd limitations:
# - It's not possible to wait for one of multiple devices to appear
# - ConditionKernelCommandLine is evaluated after Wants/After,
# so it waits for the devices unnecessarily
# Introduce a dev-combustion-config.device unit as alias to the actual device(s).
# This is only used for the .service dependencies.
# Filesystems with either combustion or ignition as label
ACTION=="add", SUBSYSTEM=="block", ENV{ID_FS_LABEL}=="combustion", ENV{SYSTEMD_ALIAS}+="/dev/combustion/config"
ACTION=="add", SUBSYSTEM=="block", ENV{ID_FS_LABEL}=="ignition", ENV{SYSTEMD_ALIAS}+="/dev/combustion/config"
# QEMU fw_cfg blob with key opt/org.opensuse.combustion
ACTION=="add", SUBSYSTEM=="opt", ENV{DEVPATH}=="/firmware/qemu_fw_cfg/by_name/opt/org.opensuse.combustion", ENV{SYSTEMD_ALIAS}+="/dev/combustion/config", TAG+="systemd"
# If combustion won't run, alias it to /dev/null to avoid waiting
ACTION=="add", SUBSYSTEM=="mem", ENV{DEVPATH}=="/devices/virtual/mem/null", GOTO="combustion_dev_null"
GOTO="combustion_end"
LABEL="combustion_dev_null"
# IMPORT has to be on its own as it returns success or not, even with "="...
IMPORT{cmdline}="ignition.firstboot"
IMPORT{cmdline}="combustion.firstboot"
ENV{ignition.firstboot}!="1", ENV{combustion.firstboot}!="1", ENV{SYSTEMD_ALIAS}+="/dev/combustion/config", TAG+="systemd"
LABEL="combustion_end"

View File

@ -2,7 +2,8 @@
Description=Combustion Description=Combustion
DefaultDependencies=false DefaultDependencies=false
ConditionKernelCommandLine=ignition.firstboot ConditionKernelCommandLine=|ignition.firstboot
ConditionKernelCommandLine=|combustion.firstboot
Requires=sysroot.mount Requires=sysroot.mount
After=sysroot.mount After=sysroot.mount

View File

@ -17,7 +17,7 @@
Name: combustion Name: combustion
Version: 0.1 Version: 0.2
Release: 0 Release: 0
Summary: System for initial configuration of appliances Summary: System for initial configuration of appliances
License: GPL-2.0-only License: GPL-2.0-only
@ -29,6 +29,7 @@ Source3: module-setup.sh
Source4: combustion.service Source4: combustion.service
Source5: combustion-prepare.service Source5: combustion-prepare.service
Source6: combustion Source6: combustion
Source7: combustion.rules
Requires: ignition-dracut-grub2 Requires: ignition-dracut-grub2
BuildArch: noarch BuildArch: noarch
@ -54,6 +55,7 @@ install -m0644 %{SOURCE3} module-setup.sh
install -m0644 %{SOURCE4} combustion.service install -m0644 %{SOURCE4} combustion.service
install -m0644 %{SOURCE5} combustion-prepare.service install -m0644 %{SOURCE5} combustion-prepare.service
install -m0755 %{SOURCE6} combustion install -m0755 %{SOURCE6} combustion
install -m0644 %{SOURCE7} combustion.rules
%post %post
%{?regenerate_initrd_post} %{?regenerate_initrd_post}

View File

@ -5,6 +5,7 @@ depends() {
install() { install() {
inst_simple "${moddir}/combustion.service" "${systemdsystemunitdir}/combustion.service" inst_simple "${moddir}/combustion.service" "${systemdsystemunitdir}/combustion.service"
inst_simple "${moddir}/combustion-prepare.service" "${systemdsystemunitdir}/combustion-prepare.service" inst_simple "${moddir}/combustion-prepare.service" "${systemdsystemunitdir}/combustion-prepare.service"
inst_simple "${moddir}/combustion.rules" "/etc/udev/rules.d/70-combustion.rules"
mkdir -p "${initdir}/${systemdsystemunitdir}/initrd.target.requires/" mkdir -p "${initdir}/${systemdsystemunitdir}/initrd.target.requires/"
ln_r "../combustion.service" "${systemdsystemunitdir}/initrd.target.requires/combustion.service" ln_r "../combustion.service" "${systemdsystemunitdir}/initrd.target.requires/combustion.service"
inst_multiple awk chroot findmnt inst_multiple awk chroot findmnt
@ -13,6 +14,6 @@ install() {
# Wait up to 10s (30s on aarch64) for the config drive # Wait up to 10s (30s on aarch64) for the config drive
devtimeout=10 devtimeout=10
[ "$(uname -m)" = "aarch64" ] && devtimeout=30 [ "$(uname -m)" = "aarch64" ] && devtimeout=30
mkdir -p "${initdir}/${systemdsystemunitdir}/dev-disk-by\x2dlabel-ignition.device.d/" mkdir -p "${initdir}/${systemdsystemunitdir}/dev-combustion-config.device.d/"
echo -e "[Unit]\nJobTimeoutSec=${devtimeout}" > "${initdir}/${systemdsystemunitdir}/dev-disk-by\x2dlabel-ignition.device.d/timeout.conf" echo -e "[Unit]\nJobTimeoutSec=${devtimeout}" > "${initdir}/${systemdsystemunitdir}/dev-combustion-config.device.d/timeout.conf"
} }