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
-------------
To be compatible and co-installable with ignition
(https://github.com/coreos/ignition), the configuration files are copied from
a filesystem with the LABEL "ignition".
The configuration files are copied from a filesystem with the LABEL
"combustion", but to be compatible and co-installable with 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
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
"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
ConditionKernelCommandLine is fulfilled and it'll be required by initrd.target.
This pulls in combustion-prepare.service, which runs after the config drive
with LABEL=ignition appears. It is mounted and if the "network" flag comment is
present, enables networking for later. After /sysroot is mounted and network is
up (if enabled), combustion.service runs, which tries to activate all
mountpoints in the system's /etc/fstab and then calls transactional-update
in a chroot.
This pulls in combustion-prepare.service, which runs after the config drive or
QEMU fw_cfg blob appears (see combustion.rules for details). It is read and if
the "network" flag comment is present, enables networking for later.
After /sysroot is mounted and network is up (if enabled), combustion.service
runs, which tries to activate all mountpoints in the system's /etc/fstab and
then calls transactional-update in a chroot.
In this transactional-update session the script is started and the exit code
recorded. If the script failed, transactional-update rollback is called and

View File

@ -9,14 +9,37 @@ if [ "${1-}" = "--prepare" ]; then
# Mount config drive
mkdir -p "${config_mount}"
if ! [ -e /dev/disk/by-label/ignition ]; then
echo "No config drive found"
exit 0
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
if ! mount -o ro /dev/disk/by-label/ignition "${config_mount}"; then
echo "Failed to mount config drive!"
exit 1
# Try disks next
for label in combustion 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
@ -44,6 +67,8 @@ 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

View File

@ -2,11 +2,14 @@
Description=Combustion (preparations)
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
Wants=dev-disk-by\x2dlabel-ignition.device
After=dev-disk-by\x2dlabel-ignition.device
Wants=dev-combustion-config.device
After=dev-combustion-config.device
# If both Ignition and Combustion are active make sure to run their
# 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>

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
DefaultDependencies=false
ConditionKernelCommandLine=ignition.firstboot
ConditionKernelCommandLine=|ignition.firstboot
ConditionKernelCommandLine=|combustion.firstboot
Requires=sysroot.mount
After=sysroot.mount

View File

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

View File

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