add in overlays

This commit is contained in:
Neil Hanlon 2022-10-18 11:48:48 -04:00
parent a1422529c0
commit e95986917e
Signed by: neil
GPG Key ID: 705BC21EC3C70F34
143 changed files with 4362 additions and 8 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
build/
.direnv/
.envrc
ass

View File

@ -0,0 +1,3 @@
# We don't ship cracklib dicts, so don't try to use them to validate
# password changes.
dictcheck = 0

View File

@ -0,0 +1,2 @@
# https://github.com/openshift/os/issues/96
%sudo ALL=(ALL) NOPASSWD: ALL

View File

@ -0,0 +1,7 @@
# Config file for overriding permission bits on overlay files/dirs
# Format: =<file mode in decimal> <absolute path to a file or directory>
# sudo prefers its config files to be mode 440, and some security scanners
# complain if /etc/sudoers.d files are world-readable.
# https://bugzilla.redhat.com/show_bug.cgi?id=1981979
=288 /etc/sudoers.d/coreos-sudo-group

View File

@ -0,0 +1,2 @@
[connection]
ipv4.dhcp-client-id=mac

View File

@ -0,0 +1,30 @@
# File intended to be sourced by shell script generators shipped with CoreOS systems
# Generators don't have logging right now
# https://github.com/systemd/systemd/issues/15638
exec 1>/dev/kmsg; exec 2>&1
UNIT_DIR="${1:-/tmp}"
have_karg() {
local arg="$1"
local cmdline=( $(</proc/cmdline) )
local i
for i in "${cmdline[@]}"; do
if [[ "$i" =~ "$arg=" ]]; then
return 0
fi
done
return 1
}
karg() {
local name="$1" value="${2:-}"
local cmdline=( $(</proc/cmdline) )
for arg in "${cmdline[@]}"; do
if [[ "${arg%%=*}" == "${name}" ]]; then
value="${arg#*=}"
fi
done
echo "${value}"
}

View File

@ -0,0 +1,2 @@
# Default rpm-ostree model is server-side generated initramfs
hostonly=no

View File

@ -0,0 +1,3 @@
# We don't ship `strip` or `eu-strip` today, and even if we did, it doesn't
# save much space. So let's disable it to avoid the error-looking message.
do_strip=no

View File

@ -0,0 +1,15 @@
# We don't support root on NFS, so we don't need it in the initramfs. It also
# conflicts with /var mount support in ignition because NFS tries to mount stuff
# in /var/ and then ignition can't cleanly unmount it. For example:
# https://github.com/dracutdevs/dracut/blob/1856ae95c873a6fe855b3dccd0144f1a96b9e71c/modules.d/95nfs/nfs-start-rpc.sh#L7
# See also discussion in https://github.com/coreos/fedora-coreos-config/pull/60
# Further, we currently do not use LVM, iSCSI or dmraid
omit_dracutmodules+=" nfs lvm iscsi dmraid "
# More storage modules we don't use
omit_dracutmodules+=" fcoe fcoe-uefi nbd "
# We use NetworkManager
omit_dracutmodules+=" systemd-networkd network-legacy network-wicked "
# We use systemd network naming
omit_dracutmodules+=" biosdevname "
# Random stuff we don't want
omit_dracutmodules+=" rngd busybox dbus-daemon memstrack pcsc bluetooth "

View File

@ -0,0 +1,13 @@
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# ex: ts=8 sw=4 sts=4 et filetype=sh
# 1) Fix for https://bugzilla.redhat.com/show_bug.cgi?id=1918244
# On s390x systems with IBM 2810XIV discs multipath couldn't be configured
# because SCSI_IDENT_* udev properties are not set at boot time
# 2-) Fix for https://bugzilla.redhat.com/show_bug.cgi?id=1990506
# Missing symlinks to disk install
install() {
inst_simple sg_inq
inst_rules 61-scsi-sg3_id.rules
inst_rules 63-scsi-sg3_symlink.rules
}

View File

@ -0,0 +1,23 @@
# For now we are using kmsg [1] for multiplexing output to
# multiple console devices during early boot. We need to also tell
# the kernel not to ratelimit kmsg during the initramfs.
#
# We do not want to use kmsg in the future as there may be sensitive
# ignition data that leaks to non-root users (by reading the kernel
# ring buffer using `dmesg`). In the future we will rely on kernel
# console multiplexing [2] for this and will not use kmsg.
#
# [1] https://github.com/coreos/ignition-dracut/blob/26f2396b116286dcb46644dc157e4211aea3aba5/dracut/99journald-conf/00-journal-log-forwarding.conf#L2
# [2] https://github.com/coreos/fedora-coreos-tracker/issues/136
# See also 10-coreos-ratelimit-kmsg.conf, which turns ratelimiting back *on*
# in the real root.
check() {
return 0
}
install() {
mkdir -p "$initdir/etc/sysctl.d"
echo "kernel.printk_devkmsg = on" > "$initdir/etc/sysctl.d/10-dont-ratelimit-kmsg.conf"
}

View File

@ -0,0 +1,70 @@
{
"ignition": {
"version": "3.2.0"
},
"storage": {
"disks": [
{
"device": "${BOOTDEV}",
"partitions": [
{
"label": "boot",
"number": 3
},
{
"label": "root",
"number": 4,
"resize": true,
"sizeMiB": 0
},
{
"number": 5,
"shouldExist": false,
"wipePartitionEntry": true
},
{
"number": 6,
"shouldExist": false,
"wipePartitionEntry": true
}
]
}
],
"luks": [
{
"device": "/dev/disk/by-partlabel/boot",
"label": "crypt_bootfs",
"name": "boot",
"options": [
"--integrity",
"hmac-sha256"
],
"wipeVolume": true
},
{
"device": "/dev/disk/by-partlabel/root",
"label": "crypt_rootfs",
"name": "root",
"options": [
"--integrity",
"hmac-sha256"
],
"wipeVolume": true
}
],
"filesystems": [
{
"device": "/dev/mapper/boot",
"format": "ext4",
"label": "boot",
"wipeFilesystem": true
},
{
"device": "/dev/mapper/root",
"format": "xfs",
"label": "root",
"wipeFilesystem": true
}
]
}
}

View File

@ -0,0 +1,10 @@
# CoreOS-specific symlink for boot disk
ACTION!="add|change", GOTO="stable_boot_end"
SUBSYSTEM!="block", GOTO="stable_boot_end"
ENV{DEVTYPE}=="disk" \
, PROGRAM=="coreos-disk-contains-fs $name boot" \
, SYMLINK+="disk/by-id/coreos-boot-disk"
LABEL="stable_boot_end"

View File

@ -0,0 +1,32 @@
# This unit will run late in the initrd process after Ignition is completed
# successfully and temporarily mount /boot read-write to make edits
# (e.g. removing firstboot networking configuration files if necessary).
[Unit]
Description=CoreOS Boot Edit
ConditionPathExists=/usr/lib/initrd-release
OnFailure=emergency.target
OnFailureJobMode=isolate
# Since we are mounting /boot, require the device first. This isn't strictly
# necessary since we run late, but on principle let's make clear the dependency.
Requires=dev-disk-by\x2dlabel-boot.device
After=dev-disk-by\x2dlabel-boot.device
# Start after Ignition has finished
After=ignition-files.service
# As above, this isn't strictly necessary, but on principle.
After=coreos-multipath-wait.target
# Finish before systemd starts tearing down services
Before=initrd.target
# initrd-parse-etc.service starts initrd-cleanup.service which will race
# with us completing before we get nuked. Need to get to the bottom of it,
# but for now we need this.
Before=initrd-parse-etc.service
[Service]
Type=oneshot
ExecStart=/usr/sbin/coreos-boot-edit
RemainAfterExit=yes
# MountFlags=slave is so the umount of /boot is guaranteed to happen.
# /boot will only be mounted for the lifetime of the unit.
MountFlags=slave

View File

@ -0,0 +1,45 @@
#!/bin/bash
set -euo pipefail
# For a description of how this is used, see `coreos-boot-edit.service`.
cmdline=( $(</proc/cmdline) )
karg() {
local name="$1" value="${2:-}"
for arg in "${cmdline[@]}"; do
if [[ "${arg%%=*}" == "${name}" ]]; then
value="${arg#*=}"
fi
done
echo "${value}"
}
# Mount /boot. Note that we mount /boot but we don't unmount it because we
# are run in a systemd unit with MountFlags=slave so it is unmounted for us.
bootmnt=/mnt/boot_partition
mkdir -p ${bootmnt}
bootdev=/dev/disk/by-label/boot
mount -o rw ${bootdev} ${bootmnt}
# Clean up firstboot networking config files if the user copied them into the
# installed system (most likely by using `coreos-installer install --copy-network`).
firstboot_network_dir_basename="coreos-firstboot-network"
initramfs_firstboot_network_dir="${bootmnt}/${firstboot_network_dir_basename}"
rm -vrf ${initramfs_firstboot_network_dir}
# If root is specified, assume rootmap is already configured. Otherwise,
# append rootmap kargs to the BLS configs.
root=$(karg root)
if [ -z "${root}" ]; then
rdcore rootmap /sysroot --boot-mount ${bootmnt}
fi
# This does a few things:
# 1. it puts the boot UUID in /run/coreos/bootfs_uuid which is used by the real
# root for mounting the bootfs in this boot
# 2. it adds a boot=UUID= karg which is used by the real root for mounting the
# bootfs in subsequent boots
# 3. it create a .root_uuid stamp file on the bootfs or fails if one exists
# 4. it adds GRUB bootuuid.cfg dropins so that GRUB selects the boot filesystem
# by UUID
rdcore bind-boot /sysroot ${bootmnt}

View File

@ -0,0 +1,20 @@
#!/bin/bash
# checks whether `disk` contains filesystem labeled `label`
set -euo pipefail
disk=$1
label=$2
# during execution of udev rules on disks 'lsblk' returns empty fields
for pt in /sys/block/$disk/*; do
name=$(basename $pt)
if [[ "$name" =~ ${disk}p?[[:digit:]] ]] && [[ -e "/sys/block/$disk/$name/start" ]];
then
eval $(udevadm info --query=property -n /dev/$name | grep -e ID_FS_LABEL -e PARTNAME)
if [[ "${ID_FS_LABEL:-}" == "$label" ]] || [[ "${PARTNAME:-}" == "$label" ]]; then
exit 0
fi
fi
done
exit 1

View File

@ -0,0 +1,77 @@
#!/bin/bash
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# ex: ts=8 sw=4 sts=4 et filetype=sh
# Originally this was known as 'ignition-generator' found in ignition-dracut.
# With Ignition v 2.5.0, ignition-dracut was merged into Ignition and the CoreOS
# specific bits were deposited here.
set -e
# Generators don't have logging right now
# https://github.com/systemd/systemd/issues/15638
exec 1>/dev/kmsg; exec 2>&1
UNIT_DIR="${1:-/tmp}"
cmdline=( $(</proc/cmdline) )
cmdline_arg() {
local name="$1" value="$2"
for arg in "${cmdline[@]}"; do
if [[ "${arg%%=*}" == "${name}" ]]; then
value="${arg#*=}"
fi
done
echo "${value}"
}
cmdline_bool() {
local value=$(cmdline_arg "$@")
case "$value" in
""|0|no|off) return 1;;
*) return 0;;
esac
}
add_requires() {
local name="$1"; shift
local target="$1"; shift
local requires_dir="${UNIT_DIR}/${target}.requires"
mkdir -p "${requires_dir}"
ln -sf "../${name}" "${requires_dir}/${name}"
}
if ! $(cmdline_bool 'ignition.firstboot' 0); then
exit 0
fi
if ! is-live-image; then
# coreos-ignition-setup-user.service should depend on the boot device node
# only on diskful boots
mkdir -p "${UNIT_DIR}/coreos-ignition-setup-user.service.d"
cat > "${UNIT_DIR}/coreos-ignition-setup-user.service.d/diskful.conf" <<EOF
[Unit]
Requires=dev-disk-by\x2dlabel-boot.device
After=dev-disk-by\x2dlabel-boot.device
Requires=coreos-gpt-setup.service
After=coreos-gpt-setup.service
EOF
# create symlink for udev rule
mkdir -p /run/udev/rules.d/
ln -sf /usr/lib/coreos/80-coreos-boot-disk.rules \
/run/udev/rules.d/80-coreos-boot-disk.rules
# IBM Secure Execution case
# During firstboot we have to reencrypt '/boot' and '/', to do that an Ignition config
# is injected. 'coreos-boot-disk' is required for this
secure_execution=0
if [[ $(uname -m) == s390x ]] && [[ -e /sys/firmware/uv/prot_virt_guest ]]; then
secure_execution=$(cat /sys/firmware/uv/prot_virt_guest)
fi
if [[ "${secure_execution}" = "1" ]]; then
mkdir -p /run/coreos/
touch /run/coreos/secure-execution
fi
fi

View File

@ -0,0 +1,36 @@
[Unit]
Description=Generate New UUID For Boot Disk GPT
ConditionPathExists=/etc/initrd-release
DefaultDependencies=no
Before=local-fs-pre.target systemd-fsck-root.service
Before=ignition-diskful.target
Wants=systemd-udevd.service
After=systemd-udevd.service
# This unit must be the first to run when the disk holding the root partition
# becomes available. To avoid relying on the name of the root partition which
# is different between RHCOS LUKS setup and current FCOS setup, we wait for the
# partition labeled 'boot' to become available. This is reliable as we don't
# have any plan to support re-provisioning/re-writing the /boot partition,
#
# This is the only unit where it is safe to wait only on a specific disk label
# as this will call udevadm settle after the GPT setup. Units that requires the
# boot and root partitions to be available should order themselves after this
# unit.
Requires=dev-disk-by\x2dlabel-boot.device
After=dev-disk-by\x2dlabel-boot.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
# Run before services that use device nodes, preventing them from racing
# with udev activity generated by sgdisk
Before=coreos-ignition-setup-user.service ignition-disks.service
OnFailure=emergency.target
OnFailureJobMode=isolate
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/sbin/coreos-gpt-setup /dev/disk/by-label/boot

View File

@ -0,0 +1,42 @@
#!/bin/bash
# randomizes the disk guid on the disk containing the partition specified by $1
# and moves the secondary gpt header/partition table to the end of the disk where it
# should be. If the disk guid is already randomized, it does nothing.
set -euo pipefail
UNINITIALIZED_GUID='00000000-0000-4000-a000-000000000001'
# If it's on multipath, get the parent device from udev properties.
DM_MPATH=$(eval $(udevadm info --query property --export "$1") && echo "${DM_MPATH:-}")
if [ -n "${DM_MPATH:-}" ]; then
PKNAME=/dev/mapper/$DM_MPATH
PTUUID=$(eval $(udevadm info --query property --export "$PKNAME") && echo "${ID_PART_TABLE_UUID:-}")
else
# On RHEL 8 the version of lsblk doesn't have PTUUID. Let's detect
# if lsblk supports it. In the future we can remove the 'if' and
# just use the 'else'.
if ! lsblk --help | grep -q PTUUID; then
# Get the PKNAME
eval $(lsblk --output PKNAME --pairs --paths --nodeps "$1")
# Get the PTUUID
eval $(blkid -o export $PKNAME)
else
# PTUUID is the disk guid, PKNAME is the parent kernel name
eval $(lsblk --output PTUUID,PKNAME --pairs --paths --nodeps "$1")
fi
fi
# Skip in the following two cases:
# - The PTUUID is != $UNINITIALIZED_GUID
# - The PTUUID is empty. This happens on s390x where DASD disks don't
# have PTUUID or any of the other traditional partition table
# attributes of GPT disks.
if [ "${PTUUID:-}" != "$UNINITIALIZED_GUID" ]; then
echo "Not randomizing disk GUID; found ${PTUUID:-none}"
exit 0
fi
echo "Randomizing disk GUID"
sgdisk --disk-guid=R --move-second-header "$PKNAME"
udevadm settle || :

View File

@ -0,0 +1,23 @@
[Unit]
Description=CoreOS Ignition User Config Setup
Documentation=https://github.com/coreos/ignition
ConditionPathExists=/etc/initrd-release
DefaultDependencies=false
# We run before config fetch because we may copy in new/different configs
# for Ignition to consume.
Before=ignition-fetch-offline.service
OnFailure=emergency.target
OnFailureJobMode=isolate
# On diskful boots, coreos-diskful-generator adds Requires/After on
# dev-disk-by\x2dlabel-boot.device and coreos-gpt-setup.service
[Service]
Type=oneshot
RemainAfterExit=yes
# The MountFlags=slave is so the umount of /boot is guaranteed to happen
# /boot will only be mounted for the lifetime of the unit.
MountFlags=slave
ExecStart=/usr/sbin/coreos-ignition-setup-user

View File

@ -0,0 +1,32 @@
#!/bin/bash
set -euo pipefail
copy_file_if_exists() {
src="${1}"; dst="${2}"
if [ -f "${src}" ]; then
echo "Copying ${src} to ${dst}"
cp "${src}" "${dst}"
else
echo "File ${src} does not exist.. Skipping copy"
fi
}
destination=/usr/lib/ignition
mkdir -p $destination
if is-live-image; then
# Live image. If the user has supplied a config.ign via an appended
# initrd, put it in the right place.
copy_file_if_exists "/config.ign" "${destination}/user.ign"
else
# We will support a user embedded config in the boot partition
# under $bootmnt/ignition/config.ign. Note that we mount /boot
# but we don't unmount boot because we are run in a systemd unit
# with MountFlags=slave so it is unmounted for us.
bootmnt=/mnt/boot_partition
mkdir -p $bootmnt
# mount as read-only since we don't strictly need write access and we may be
# running alongside other code that also has it mounted ro
mount -o ro /dev/disk/by-label/boot $bootmnt
copy_file_if_exists "${bootmnt}/ignition/config.ign" "${destination}/user.ign"
fi

View File

@ -0,0 +1,19 @@
[Unit]
Description=CoreOS Ensure Unique Boot Filesystem
ConditionPathExists=/etc/initrd-release
OnFailure=emergency.target
OnFailureJobMode=isolate
# That's a weak dependency, so service won't fail if boot dissaperears
Wants=dev-disk-by\x2dlabel-boot.device
After=dev-disk-by\x2dlabel-boot.device
# Start after ignition has finished with disks but before mounting them
After=ignition-disks.service
Before=ignition-mount.service
Before=ignition-ostree-uuid-root.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/rdcore verify-unique-fs-label --rereadpt boot

View File

@ -0,0 +1,23 @@
[Unit]
Description=CoreOS Kernel Arguments Reboot
ConditionPathExists=/etc/initrd-release
ConditionPathExists=/run/coreos-kargs-reboot
DefaultDependencies=false
Before=ignition-complete.target
# This runs after ignition-kargs & before ignition-disks so that it can optionally reboot
# if kargs were modified via Ignition. This is done in a two-stage fashion so that other
# mechanisms which may want to reboot (e.x. FIPS) can also hook in here and only reboot
# once from the initrd.
After=ignition-kargs.service
Before=ignition-disks.service
OnFailure=emergency.target
OnFailureJobMode=isolate
[Service]
Type=oneshot
RemainAfterExit=yes
# --force causes a rapid reboot. Without it, systemd continues running
# Ignition stages in parallel with shutting down.
ExecStart=/usr/bin/systemctl reboot --force

View File

@ -0,0 +1,12 @@
#!/bin/bash
set -euo pipefail
if is-live-image; then
/usr/bin/rdcore kargs --current --create-if-changed /run/coreos-kargs-changed "$@"
if [ -e /run/coreos-kargs-changed ]; then
echo "Need to modify kernel arguments, but cannot affect live system." >&2
exit 1
fi
else
/usr/bin/rdcore kargs --boot-device /dev/disk/by-label/boot --create-if-changed /run/coreos-kargs-reboot "$@"
fi

View File

@ -0,0 +1,17 @@
# This unit will run late in the initrd process after the Ignition files
# stage has completed successfully so that we may validate ignition changes
[Unit]
Description=CoreOS Post Ignition Checks
ConditionPathExists=/usr/lib/initrd-release
OnFailure=emergency.target
OnFailureJobMode=isolate
# Start after Ignition has finished creating files and before ignition umount
After=ignition-files.service
Before=ignition-complete.target
[Service]
Type=oneshot
ExecStart=/usr/sbin/coreos-post-ignition-checks
RemainAfterExit=yes

View File

@ -0,0 +1,18 @@
#!/bin/bash
# See coreos-post-ignition-checks.service for more information about this script
set -euo pipefail
# Verify that GRUB password directives are only used when GRUB is being used
arch=$(uname -p)
# Butane sugar will tell ignition to mount /boot to /sysroot/boot. We can simply check if
# the file exists to see whether the check needs to be performed.
# It is possible that the user creates a config, which will mount /boot at a different path
# but that case is not officially supported.
if [ -f /sysroot/boot/grub2/user.cfg ]; then
# s390x does not use GRUB, ppcle64 uses petitboot with a GRUB config parser which does not support passwords
# So in both these cases, GRUB password is not supported
if grep -q password_pbkdf2 /sysroot/boot/grub2/user.cfg && [[ "$arch" =~ ^(s390x|ppc64le)$ ]]; then
echo "Ignition config provisioned a GRUB password, which is not supported on $arch"
exit 1
fi
fi

View File

@ -0,0 +1,38 @@
# Clean up the initramfs networking on first boot
# so the real network is being brought up
# https://github.com/coreos/fedora-coreos-tracker/issues/394#issuecomment-599721763
[Unit]
Description=CoreOS Tear Down Initramfs
DefaultDependencies=false
# We want to run the teardown after all other Ignition stages
# have run because some platforms (like Packet) do remote status
# reporting for each Ignition stage. Since we are tearing down
# the networking using an ExecStop we need to make sure we run
# the ExecStop *after* any other ignition*.service unit's ExecStop.
# The only other one right now is ignition-mount that has an ExecStop
# for doing an unmount. Since the ordering for ExecStop is the
# opposite of ExecStart we need to use `Before=ignition-mount.service`.
# https://github.com/coreos/fedora-coreos-tracker/issues/440
Before=ignition-mount.service
Before=ignition-complete.target
# Make sure ExecStop= runs before we switch root
Conflicts=initrd-switch-root.target umount.target
Before=initrd-switch-root.target
OnFailure=emergency.target
OnFailureJobMode=isolate
# If we are already heading towards emergency.target
# then don't try to stop this unit because it will fail
# when trying to access files in /sysroot/etc/. The failure
# is mostly harmless but having the extra error messages
# leads us away from the original problem.
IgnoreOnIsolate=true
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStop=/usr/sbin/coreos-teardown-initramfs

View File

@ -0,0 +1,240 @@
#!/bin/bash
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# ex: ts=8 sw=4 sts=4 et filetype=sh
set -euo pipefail
# Load dracut libraries. Using getargbool() and getargs() from
# dracut-lib and ip_to_var() from net-lib
load_dracut_libs() {
# dracut is not friendly to set -eu
set +euo pipefail
type getargbool &>/dev/null || . /lib/dracut-lib.sh
type ip_to_var &>/dev/null || . /lib/net-lib.sh
set -euo pipefail
}
dracut_func() {
# dracut is not friendly to set -eu
set +euo pipefail
"$@"; local rc=$?
set -euo pipefail
return $rc
}
# Get the BOOTIF and rd.bootif kernel arguments from
# the kernel command line.
get_bootif_kargs() {
bootif_kargs=""
bootif_karg=$(dracut_func getarg BOOTIF)
if [ ! -z "$bootif_karg" ]; then
bootif_kargs+="BOOTIF=${bootif_karg}"
fi
rdbootif_karg=$(dracut_func getarg rd.bootif)
if [ ! -z "$rdbootif_karg" ]; then
bootif_kargs+=" rd.bootif=${rdbootif_karg}"
fi
echo $bootif_kargs
}
# Determine if the generated NM connection profiles match the default
# that would be given to us if the user had provided no additional
# configuration. i.e. did the user give us any network configuration
# other than the default? We determine this by comparing the generated
# output of nm-initrd-generator with a new run of nm-initrd-generator.
# If it matches then it was the default, if not then the user provided
# something extra.
are_default_NM_configs() {
# pick up our CoreOS default networking kargs from the afterburn dropin
DEFAULT_KARGS_FILE=/usr/lib/systemd/system/afterburn-network-kargs.service.d/50-afterburn-network-kargs-default.conf
source <(grep -o 'AFTERBURN_NETWORK_KARGS_DEFAULT=.*' $DEFAULT_KARGS_FILE)
# Also pick up BOOTIF/rd.bootif kargs and apply them here.
# See https://github.com/coreos/fedora-coreos-tracker/issues/1048
BOOTIF_KARGS=$(get_bootif_kargs)
# Make two dirs for storing files to use in the comparison
mkdir -p /run/coreos-teardown-initramfs/connections-compare-{1,2}
# Make another that's just a throwaway for the initrd-data-dir
mkdir -p /run/coreos-teardown-initramfs/initrd-data-dir
# Copy over the previously generated connection(s) profiles
cp /run/NetworkManager/system-connections/* \
/run/coreos-teardown-initramfs/connections-compare-1/
# Do a new run with the default input
/usr/libexec/nm-initrd-generator \
-c /run/coreos-teardown-initramfs/connections-compare-2 \
-i /run/coreos-teardown-initramfs/initrd-data-dir \
-- $AFTERBURN_NETWORK_KARGS_DEFAULT $BOOTIF_KARGS
# remove unique identifiers from the files (so our diff can work)
sed -i '/^uuid=/d' /run/coreos-teardown-initramfs/connections-compare-{1,2}/*
# currently the output will differ based on whether rd.neednet=1
# was part of the kargs. Let's ignore the single difference (wait-device-timeout)
sed -i '/^wait-device-timeout=/d' /run/coreos-teardown-initramfs/connections-compare-{1,2}/*
if diff -r -q /run/coreos-teardown-initramfs/connections-compare-{1,2}/; then
rc=0 # They are the default configs
else
rc=1 # They are not the defaults, user must have added configuration
fi
rm -rf /run/coreos-teardown-initramfs
return $rc
}
# Propagate initramfs networking if desired. The policy here is:
#
# - If a networking configuration was provided before this point
# (most likely via Ignition) and exists in the real root then
# we do nothing and don't propagate any initramfs networking.
# - If a user did not provide any networking configuration
# then we'll propagate the initramfs networking configuration
# into the real root, but only if it's different than the NM
# defaults (trying dhcp/dhcp6 on everything). If it's just the
# defaults then we want to avoid a slight behavior diff between
# propagating configs and just booting with no configuration. See
# https://github.com/coreos/fedora-coreos-tracker/issues/696
#
# See https://github.com/coreos/fedora-coreos-tracker/issues/394#issuecomment-599721173
propagate_initramfs_networking() {
# Check for any real root config in the two locations where a user could have
# provided network configuration. On FCOS we only support keyfiles, but on RHCOS
# we support keyfiles and ifcfg. We also need to ignore readme-ifcfg-rh.txt
# which is a cosmetic file added in
# https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/commit/96d7362
if [ -n "$(ls -A /sysroot/etc/NetworkManager/system-connections/)" -o \
-n "$(ls -A -I readme-ifcfg-rh.txt /sysroot/etc/sysconfig/network-scripts/)" ]; then
echo "info: networking config is defined in the real root"
realrootconfig=1
else
echo "info: no networking config is defined in the real root"
realrootconfig=0
fi
# Did the user tell us to force initramfs networking config
# propagation even if real root networking config exists?
# Hopefully we only need this in rare circumstances.
# https://github.com/coreos/fedora-coreos-tracker/issues/853
forcepropagate=0
if dracut_func getargbool 0 'coreos.force_persist_ip'; then
forcepropagate=1
echo "info: coreos.force_persist_ip detected: will force network config propagation"
fi
if [ $realrootconfig == 1 -a $forcepropagate == 0 ]; then
echo "info: will not attempt to propagate initramfs networking"
fi
if [ $realrootconfig == 0 -o $forcepropagate == 1 ]; then
if [ -n "$(ls -A /run/NetworkManager/system-connections/)" ]; then
if are_default_NM_configs; then
echo "info: skipping propagation of default networking configs"
else
echo "info: propagating initramfs networking config to the real root"
cp -v /run/NetworkManager/system-connections/* /sysroot/etc/NetworkManager/system-connections/
coreos-relabel /etc/NetworkManager/system-connections/
fi
else
echo "info: no initramfs networking information to propagate"
fi
fi
}
# Propagate the ip= karg hostname if desired. The policy here is:
#
# - IF a hostname was detected in ip= kargs by NetworkManager
# - AND no hostname was set via Ignition (realroot `/etc/hostname`)
# - THEN we make the hostname detected by NM apply permanently
# by writing it into `/etc/hostname`
#
propagate_initramfs_hostname() {
if [ -e '/sysroot/etc/hostname' ]; then
echo "info: hostname is defined in the real root"
echo "info: will not attempt to propagate initramfs hostname"
return 0
fi
# If any hostname was provided NetworkManager will write it out to
# /run/NetworkManager/initrd/hostname. See
# https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/481
if [ -s /run/NetworkManager/initrd/hostname ]; then
hostname=$(</run/NetworkManager/initrd/hostname)
echo "info: propagating initramfs hostname (${hostname}) to the real root"
echo $hostname > /sysroot/etc/hostname
coreos-relabel /etc/hostname
else
echo "info: no initramfs hostname information to propagate"
fi
}
down_interface() {
echo "info: taking down network device: $1"
# On recommendation from the NM team let's try to delete the device
# first and if that doesn't work then set it to down and flush any
# associated addresses. Deleting virtual devices (bonds, teams, bridges,
# ip-tunnels, etc) will clean up any associated kernel resources. A real
# device can't be deleted so that will fail and we'll fallback to setting
# it down and flushing addresses.
if ! ip link delete $1; then
ip link set $1 down
ip addr flush dev $1
fi
}
# Iterate through the interfaces in the machine and take them down.
# Note that in the futre we would like to possibly use `nmcli` networking off`
# for this. See the following two comments for details:
# https://github.com/coreos/fedora-coreos-tracker/issues/394#issuecomment-599721763
# https://github.com/coreos/fedora-coreos-tracker/issues/394#issuecomment-599746049
down_interfaces() {
if ! [ -z "$(ls /sys/class/net)" ]; then
for f in /sys/class/net/*; do
interface=$(basename "$f")
# The `bonding_masters` entry is not a true interface and thus
# cannot be taken down. Also skip local loopback
case "$interface" in
"lo" | "bonding_masters")
continue
;;
esac
# When we start taking down devices some other devices can
# start to disappear (for example vlan on top of interface).
# If the device we're about to take down has disappeared
# since the start of this loop then skip taking it down.
if [ ! -e "$f" ]; then
echo "info: skipping teardown of ${interface}; no longer exists."
continue
fi
down_interface $interface
done
fi
}
main() {
# Load libraries from dracut
load_dracut_libs
# Take down all interfaces set up in the initramfs
down_interfaces
# Clean up all routing
echo "info: flushing all routing"
ip route flush table main
ip route flush cache
# Hopefully our logic is sound enough that this is never needed, but
# user's can explicitly disable initramfs network/hostname propagation
# with the coreos.no_persist_ip karg.
if dracut_func getargbool 0 'coreos.no_persist_ip'; then
echo "info: coreos.no_persist_ip karg detected"
echo "info: skipping propagating initramfs settings"
else
propagate_initramfs_hostname
propagate_initramfs_networking
fi
# Now that the configuration has been propagated (or not)
# 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/
rm -f /run/udev/rules.d/80-coreos-boot-disk.rules
rm -f /dev/disk/by-id/coreos-boot-disk
}
main

View File

@ -0,0 +1,22 @@
[Unit]
Description=Ensure filesystem labeled `boot` is unique
ConditionPathExists=/etc/initrd-release
DefaultDependencies=no
Before=ignition-diskful.target
Wants=systemd-udevd.service
After=systemd-udevd.service
# And since the boot device may be on multipath; optionally wait for it to
# appear via the dynamic target.
After=coreos-multipath-wait.target
Requires=dev-disk-by\x2dlabel-boot.device
After=dev-disk-by\x2dlabel-boot.device
# Run before services that modify/use `boot` partition
Before=coreos-gpt-setup.service coreos-boot-edit.service
OnFailure=emergency.target
OnFailureJobMode=isolate
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/rdcore verify-unique-fs-label boot

View File

@ -0,0 +1,79 @@
#!/bin/bash
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# ex: ts=8 sw=4 sts=4 et filetype=sh
depends() {
echo systemd network ignition coreos-live
}
install_ignition_unit() {
local unit="$1"; shift
local target="${1:-ignition-complete.target}"; shift
local instantiated="${1:-$unit}"; shift
inst_simple "$moddir/$unit" "$systemdsystemunitdir/$unit"
# note we `|| exit 1` here so we error out if e.g. the units are missing
# see https://github.com/coreos/fedora-coreos-config/issues/799
systemctl -q --root="$initdir" add-requires "$target" "$instantiated" || exit 1
}
install() {
inst_multiple \
basename \
diff \
lsblk \
sed \
grep \
sgdisk \
uname
inst_simple "$moddir/coreos-diskful-generator" \
"$systemdutildir/system-generators/coreos-diskful-generator"
inst_script "$moddir/coreos-gpt-setup.sh" \
"/usr/sbin/coreos-gpt-setup"
# This has to work only on diskful systems during firstboot.
# coreos-diskful-generator will create a symlink
inst_simple "$moddir/80-coreos-boot-disk.rules" \
"/usr/lib/coreos/80-coreos-boot-disk.rules"
inst_script "$moddir/coreos-disk-contains-fs.sh" \
"/usr/lib/udev/coreos-disk-contains-fs"
inst_script "$moddir/coreos-ignition-setup-user.sh" \
"/usr/sbin/coreos-ignition-setup-user"
inst_script "$moddir/coreos-post-ignition-checks.sh" \
"/usr/sbin/coreos-post-ignition-checks"
install_ignition_unit coreos-post-ignition-checks.service
# For consistency tear down the network and persist multipath between the initramfs and
# real root. See https://github.com/coreos/fedora-coreos-tracker/issues/394#issuecomment-599721763
inst_script "$moddir/coreos-teardown-initramfs.sh" \
"/usr/sbin/coreos-teardown-initramfs"
install_ignition_unit coreos-teardown-initramfs.service
# units only started when we have a boot disk
# path generated by systemd-escape --path /dev/disk/by-label/root
install_ignition_unit coreos-gpt-setup.service ignition-diskful.target
# dracut inst_script doesn't allow overwrites and we are replacing
# the default script placed by Ignition
binpath="/usr/sbin/ignition-kargs-helper"
cp "$moddir/coreos-kargs.sh" "$initdir$binpath"
install_ignition_unit coreos-kargs-reboot.service
inst_script "$moddir/coreos-boot-edit.sh" \
"/usr/sbin/coreos-boot-edit"
# Only start when the system has disks since we are editing /boot.
install_ignition_unit "coreos-boot-edit.service" \
"ignition-diskful.target"
install_ignition_unit coreos-ignition-unique-boot.service ignition-diskful.target
install_ignition_unit coreos-unique-boot.service ignition-diskful.target
install_ignition_unit coreos-ignition-setup-user.service
# IBM Secure Execution. Ignition config for reencryption of / and /boot
inst_simple "$moddir/01-secex.ign" /usr/lib/coreos/01-secex.ign
}

View File

@ -0,0 +1,18 @@
# SSSD caches passwd data from /etc in /var. If we have a persistent /var
# but not a persistent /etc, ignition-files.service can think a user
# already exists when in fact it needs to be (re-)created. Clear the
# cache to avoid this.
[Unit]
Description=Clear SSSD NSS cache in persistent /var
DefaultDependencies=false
ConditionPathExists=/run/ostree-live
ConditionPathExists=/sysroot/var/lib/sss/mc
After=ignition-mount.service
Before=ignition-files.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/rm -r /sysroot/var/lib/sss/mc

View File

@ -0,0 +1,24 @@
# If the user specified a persistent /var, ideally it'd just be mounted
# overtop of our tmpfs /var and everything would be fine. That works
# fine in the initramfs, where ignition-mount handles the mounting.
# But in the real root, the user's mount unit is ignored by systemd,
# since there's already a filesystem mounted on /var. To fix this, we
# notice that the user wants to mount /var, and unmount our tmpfs /var
# before switching roots.
[Unit]
Description=Unmount live /var if persistent /var is configured
DefaultDependencies=false
ConditionPathExists=/run/ostree-live
ConditionPathExists=|/sysroot/etc/systemd/system/var.mount
ConditionPathExists=|/sysroot/etc/fstab
Before=initrd-switch-root.target
# Run after Ignition mounts are unmounted, since the Ignition config
# presumably mounted overtop /sysroot/var
After=ignition-mount.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/sbin/coreos-live-unmount-tmpfs-var

View File

@ -0,0 +1,33 @@
#!/bin/bash
# If the user specified a persistent /var, ideally it'd just be mounted
# overtop of our tmpfs /var and everything would be fine. That works
# fine in the initramfs, where ignition-mount handles the mounting.
# But in the real root, the user's mount unit is ignored by systemd,
# since there's already a filesystem mounted on /var. To fix this, we
# notice that the user wants to mount /var, and unmount our tmpfs /var
# before switching roots.
set -euo pipefail
should_unmount() {
# Did the user specify a mount unit for /var?
if [ -e /sysroot/etc/systemd/system/var.mount ]; then
return 0
fi
# Is there an fstab entry for /var?
if [ -e /sysroot/etc/fstab ]; then
# Uncommented entry with mountpoint on /var, without noauto in options
result=$(awk '(! /^\s*#/) && ($2 == "/var") && ($4 !~ /noauto/) {print "found"}' /sysroot/etc/fstab)
if [ -n "$result" ]; then
return 0
fi
fi
return 1
}
if should_unmount; then
echo "Unmounting /sysroot/var"
umount /sysroot/var
fi

View File

@ -0,0 +1,17 @@
[Unit]
Description=Persist osmet files (ISO)
DefaultDependencies=false
ConditionPathExists=/run/ostree-live
ConditionKernelCommandLine=coreos.liveiso
RequiresMountsFor=/run/media/iso
# on el8, the ISO is mounted by our own systemd unit
After=run-media-iso-mount.service
Before=initrd-switch-root.target
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/mkdir -p /run/coreos-installer/osmet
# bsdtar reads cpio archives, and unlike cpio(1L), knows how to seek over
# members it isn't reading
ExecStart=/usr/bin/bsdtar -x -C /run/coreos-installer/osmet -f /run/media/iso/images/pxeboot/rootfs.img *.osmet

View File

@ -0,0 +1,14 @@
[Unit]
Description=Persist osmet files (PXE)
DefaultDependencies=false
ConditionPathExists=/run/ostree-live
ConditionKernelCommandLine=!coreos.liveiso
# Downloads and unpacks the osmet files if not already appended
After=coreos-livepxe-rootfs.service
Before=initrd-switch-root.target
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/mkdir -p /run/coreos-installer/osmet
ExecStart=/usr/bin/sh -c "if ls /*.osmet &>/dev/null; then cp /*.osmet /run/coreos-installer/osmet; fi"

View File

@ -0,0 +1,21 @@
[Unit]
Description=Acquire live PXE rootfs image
DefaultDependencies=false
ConditionPathExists=/usr/lib/initrd-release
ConditionPathExists=/run/ostree-live
ConditionKernelCommandLine=!coreos.liveiso
After=basic.target
# Network is enabled here
After=nm-run.service
# compat: remove when everyone is on dracut 053+
After=dracut-initqueue.service
# If we fail, the boot will fail. Be explicit about it.
OnFailure=emergency.target
OnFailureJobMode=isolate
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/sbin/coreos-livepxe-rootfs

View File

@ -0,0 +1,70 @@
#!/bin/bash
# Ensure that a PXE-booted system has a valid rootfs.
set -euo pipefail
# Get rootfs_url karg
set +euo pipefail
. /usr/lib/dracut-lib.sh
rootfs_url=$(getarg coreos.live.rootfs_url=)
set -euo pipefail
if [[ -f /etc/coreos-live-rootfs ]]; then
# rootfs image was injected via PXE. Verify that the initramfs and
# rootfs versions match.
initramfs_ver=$(cat /etc/coreos-live-initramfs)
rootfs_ver=$(cat /etc/coreos-live-rootfs)
if [[ $initramfs_ver != $rootfs_ver ]]; then
echo "Found initramfs version $initramfs_ver but rootfs version $rootfs_ver." >&2
echo "Please fix your PXE configuration." >&2
exit 1
fi
elif [[ -n "${rootfs_url}" ]]; then
# rootfs URL was provided as karg. Fetch image, check its hash, and
# unpack it.
echo "Fetching rootfs image from ${rootfs_url}..."
if [[ ${rootfs_url} != http:* && ${rootfs_url} != https:* && ${rootfs_url} != tftp:* ]]; then
# Don't commit to supporting protocols we might not want to expose in
# the long term.
echo "Unsupported scheme for image specified by:" >&2
echo "coreos.live.rootfs_url=${rootfs_url}" >&2
echo "Only HTTP, HTTPS, and TFTP are supported. Please fix your PXE configuration." >&2
exit 1
fi
# First, reach out to the server to verify connectivity before
# trying to download and pipe content through other programs.
# Doing this allows us to retry all errors (including transient
# "no route to host" errors during startup). Note we can't use
# curl's --retry-all-errors here because it's not in el8's curl yet.
# We retry forever, matching Ignition's semantics.
curl_common_args="--silent --show-error --insecure --location"
while ! curl --head $curl_common_args "${rootfs_url}" >/dev/null; do
echo "Couldn't establish connectivity with the server specified by:" >&2
echo "coreos.live.rootfs_url=${rootfs_url}" >&2
echo "Retrying in 5s..." >&2
sleep 5
done
# We don't need to verify TLS certificates because we're checking the
# image hash.
# bsdtar can read cpio archives and we already depend on it for
# coreos-liveiso-persist-osmet.service, so use it instead of cpio.
# We shouldn't need a --retry here since we've just successfully HEADed the
# file, but let's add one just to be safe (e.g. if the connection just went
# online and flickers or something).
if ! curl $curl_common_args --retry 5 "${rootfs_url}" | \
rdcore stream-hash /etc/coreos-live-want-rootfs | \
bsdtar -xf - -C / ; then
echo "Couldn't fetch, verify, and unpack image specified by:" >&2
echo "coreos.live.rootfs_url=${rootfs_url}" >&2
echo "Check that the URL is correct and that the rootfs version matches the initramfs." >&2
exit 1
fi
else
# Nothing. Fail.
echo "No rootfs image found. Modify your PXE configuration to add the rootfs" >&2
echo "image as a second initrd, or use the coreos.live.rootfs_url kernel parameter" >&2
echo "to specify an HTTP or HTTPS URL to the rootfs." >&2
exit 1
fi

View File

@ -0,0 +1,6 @@
#!/bin/sh
# Script invoked by ignition-dracut generator to detect whether this is a
# live system without a root device. We can't test for /run/ostree-live
# because it's created by a generator.
# This file is created by coreos-assembler buildextend-live.
test -f /etc/coreos-live-initramfs

View File

@ -0,0 +1,271 @@
#!/bin/bash
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# ex: ts=8 sw=4 sts=4 et filetype=sh
# Generators don't have logging right now
# https://github.com/systemd/systemd/issues/15638
exec 1>/dev/kmsg; exec 2>&1
command -v getarg >/dev/null || . /usr/lib/dracut-lib.sh
set -e
UNIT_DIR="${1:-/tmp}"
add_requires() {
local name="$1"; shift
local target="$1"; shift
local requires_dir="${UNIT_DIR}/${target}.requires"
mkdir -p "${requires_dir}"
ln -sf "../${name}" "${requires_dir}/${name}"
}
if ! is-live-image; then
exit 0
fi
# Create stamp file that everything else should use to detect a live boot
> /run/ostree-live
add_requires sysroot.mount initrd-root-fs.target
add_requires sysroot-etc.mount initrd-root-fs.target
add_requires sysroot-var.mount initrd-root-fs.target
mkdir -p "${UNIT_DIR}/ostree-prepare-root.service.d"
cat > "${UNIT_DIR}/ostree-prepare-root.service.d/10-live.conf" <<EOF
# With live PXE there's no ostree= argument on the kernel command line, so
# we need to find the tree path and pass it to ostree-prepare-root. But
# ostree-prepare-root only knows how to read the path from
# /proc/cmdline, so we need to synthesize the proper karg and bind-mount
# it over /proc/cmdline.
# https://github.com/ostreedev/ostree/issues/1920
[Unit]
# The base unit conditions on the ostree karg, which won't exist until
# ExecStartPre runs
ConditionKernelCommandLine=
[Service]
ExecStartPre=/usr/sbin/ostree-cmdline start
ExecStartPost=/usr/sbin/ostree-cmdline stop
EOF
isoroot=$(getarg coreos.liveiso= ||:)
is_rhcos8() {
# Unfortunately we can't rely on /etc/os-release since el8 doesn't seem to
# have https://github.com/dracutdevs/dracut/pull/655.
[[ "${isoroot}" == rhcos-* ]] && [[ $(uname -r) == *.el8* ]]
}
if [ -z "${isoroot}" ]; then
# In this case, the rootfs is already unpacked into the initrd, or we need
# to retrieve it
cat >"${UNIT_DIR}/sysroot.mount" <<EOF
# Automatically generated by live-generator
[Unit]
DefaultDependencies=false
# Verifies that we have the right root.squashfs, or downloads it if needed
After=coreos-livepxe-rootfs.service
Before=initrd-root-fs.target
[Mount]
What=/root.squashfs
Where=/sysroot
Type=squashfs
Options=loop
EOF
else
# And in this case, it's on the ISO
mkdir -p /run/media/iso
isosrc=dev/disk/by-label/${isoroot}
isosrc_escaped=$(systemd-escape -p --suffix=device "${isosrc}")
initrd_rootdev_target_d="${UNIT_DIR}"/initrd-root-device.target.d
mkdir -p "${initrd_rootdev_target_d}"
cat > "${initrd_rootdev_target_d}/50-root-device.conf" <<EOF
[Unit]
After=${isosrc_escaped}
Requires=${isosrc_escaped}
EOF
# Temporary hack for rhel8, where our mount unit can race with udev's
# cdrom_id using open(O_EXCL). See:
# https://github.com/coreos/fedora-coreos-config/pull/1986#pullrequestreview-1120840529
# https://issues.redhat.com/browse/OCPBUGS-1505
if is_rhcos8; then
cat >"${UNIT_DIR}/run-media-iso-mount.service" <<EOF
# Automatically generated by live-generator
[Unit]
DefaultDependencies=false
# Note that bootup(7) implies that initrd-root-device is After=basic.target
# but that appears to not be the case. We explicitly order after sysinit.target
After=sysinit.target
After=initrd-root-device.target
Before=initrd-root-fs.target
[Service]
Type=oneshot
RemainAfterExit=yes
# See https://issues.redhat.com/browse/OCPBUGS-1505
# and https://github.com/coreos/fedora-coreos-config/pull/411
ExecStart=/bin/sh -c 'for x in {0..60}; do if mount -o ro -t iso9660 /${isosrc} /run/media/iso; then break; fi; sleep 1; done'
EOF
add_requires run-media-iso-mount.service initrd-root-fs.target
else
cat >"${UNIT_DIR}/run-media-iso.mount" <<EOF
# Automatically generated by live-generator
[Unit]
DefaultDependencies=false
# HACK for https://github.com/coreos/fedora-coreos-config/issues/437
Wants=systemd-udev-settle.service
# Note that bootup(7) implies that initrd-root-device is After=basic.target
# but that appears to not be the case. We explicitly order after sysinit.target
After=sysinit.target
After=initrd-root-device.target
Before=initrd-root-fs.target
[Mount]
What=/${isosrc}
Where=/run/media/iso
Options=ro
Type=iso9660
EOF
fi
cat >"${UNIT_DIR}/sysroot.mount" <<EOF
# Automatically generated by live-generator
[Unit]
DefaultDependencies=false
Before=initrd-root-fs.target
RequiresMountsFor=/run/media/iso
# on el8, the ISO is mounted by our own systemd unit
After=run-media-iso-mount.service
[Mount]
What=/run/media/iso/images/pxeboot/rootfs.img
Where=/sysroot
Type=squashfs
# Offset of the squashfs within the rootfs cpio. Assumes newc format
# and that a file named "root.squashfs" is the first member. This offset
# is checked by coreos-assembler cmd-buildextend-live at build time.
Options=loop,offset=124
EOF
# And one more unit to workaround what we think is a systemd bug.
# We've found the system can stall waiting for run-media-iso.mount
# and apparently any operation seems to be effective at reviving
# the system.
# https://github.com/coreos/fedora-coreos-tracker/issues/1233#issuecomment-1238814171
cat >"${UNIT_DIR}/workaround-stalled-media-iso-mount.service" <<EOF
[Service]
Type=simple
StandardOutput=journal
StandardError=journal
ExecStart=bash -c "sleep 10; echo 'warn: tracker issue workaround engaged for https://github.com/coreos/fedora-coreos-tracker/issues/1233'"
EOF
add_requires workaround-stalled-media-iso-mount.service basic.target
fi
# It turns out that `tmpfs` currently munches all SELinux labels
# we set before policy is loaded, so we make an XFS filesystem
# loopback mounted that's sized the same as /run.
# https://github.com/coreos/fedora-coreos-config/pull/499
cat >"${UNIT_DIR}/sysroot-xfs-ephemeral-mkfs.service" <<'EOF'
[Unit]
DefaultDependencies=false
# Let's be sure we have basic devices, but other than that we
# can run really early.
After=systemd-tmpfiles-setup-dev.service
ConditionPathExists=/usr/lib/initrd-release
# Something seems to be causing us to rerun?
ConditionPathExists=!/run/ephemeral
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/sh -c 'set -euo pipefail; mem=$$(($$(stat -f -c "%%b * %%s / 1024" /run))) && /bin/truncate -s $${mem}k /run/ephemeral.xfsloop'
ExecStart=/sbin/mkfs.xfs /run/ephemeral.xfsloop
ExecStart=/bin/mkdir /run/ephemeral
EOF
add_requires sysroot-xfs-ephemeral-mkfs.service initrd-root-fs.target
cat >>"${UNIT_DIR}/run-ephemeral.mount" <<EOF
[Unit]
DefaultDependencies=false
Requires=sysroot-xfs-ephemeral-mkfs.service
After=sysroot-xfs-ephemeral-mkfs.service
[Mount]
What=/run/ephemeral.xfsloop
Where=/run/ephemeral
Type=xfs
Options=loop,discard
EOF
cat >"${UNIT_DIR}/sysroot-xfs-ephemeral-setup.service" <<EOF
[Unit]
DefaultDependencies=false
RequiresMountsFor=/run/ephemeral
ConditionPathExists=/usr/lib/initrd-release
ConditionPathExists=!/run/ephemeral/var
# Make sure /sysroot is mounted first, since we're mounting under there
Requires=sysroot.mount
After=sysroot.mount
# And after OSTree has set up the chroot() equivalent
After=ostree-prepare-root.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/cp -a /sysroot/etc /run/ephemeral/etc
ExecStart=/bin/mkdir /run/ephemeral/var
EOF
common_etcvar_unit() {
cat << EOF
# Automatically generated by live-generator
[Unit]
DefaultDependencies=false
# Make sure our tmpfs is available
Requires=sysroot-xfs-ephemeral-setup.service
After=sysroot-xfs-ephemeral-setup.service
# We're part of assembling the root fs
Before=initrd-root-fs.target
EOF
}
common_etcvar_unit > "${UNIT_DIR}/sysroot-etc.mount"
cat >>"${UNIT_DIR}/sysroot-etc.mount" <<EOF
[Mount]
What=/run/ephemeral/etc
Where=/sysroot/etc
Type=none
Options=bind
EOF
add_requires sysroot-etc.mount initrd-root-fs.target
common_etcvar_unit >"${UNIT_DIR}/sysroot-var.mount"
cat >>"${UNIT_DIR}/sysroot-var.mount" <<EOF
[Mount]
What=/run/ephemeral/var
Where=/sysroot/var
Type=none
Options=bind
EOF
add_requires sysroot-var.mount initrd-root-fs.target
cat >>"${UNIT_DIR}/sysroot-relabel.service" <<EOF
[Unit]
DefaultDependencies=false
RequiresMountsFor=/sysroot/etc /sysroot/var
Before=initrd-root-fs.target
[Service]
Type=oneshot
RemainAfterExit=yes
# We don't need the full relabeling spam by default for these
StandardOutput=null
ExecStart=/bin/coreos-relabel /etc
ExecStart=/bin/coreos-relabel /var
EOF
add_requires sysroot-relabel.service initrd-root-fs.target

View File

@ -0,0 +1,55 @@
depends() {
# We need the rdcore binary
echo rdcore
}
install_and_enable_unit() {
unit="$1"; shift
target="$1"; shift
inst_simple "$moddir/$unit" "$systemdsystemunitdir/$unit"
# note we `|| exit 1` here so we error out if e.g. the units are missing
# see https://github.com/coreos/fedora-coreos-config/issues/799
systemctl -q --root="$initdir" add-requires "$target" "$unit" || exit 1
}
installkernel() {
# we do loopmounts
instmods -c loop
}
install() {
inst_multiple \
bsdtar \
curl \
truncate
inst_script "$moddir/is-live-image.sh" \
"/usr/bin/is-live-image"
inst_script "$moddir/ostree-cmdline.sh" \
"/usr/sbin/ostree-cmdline"
inst_simple "$moddir/live-generator" \
"$systemdutildir/system-generators/live-generator"
inst_simple "$moddir/coreos-live-unmount-tmpfs-var.sh" \
"/usr/sbin/coreos-live-unmount-tmpfs-var"
inst_simple "$moddir/coreos-livepxe-rootfs.sh" \
"/usr/sbin/coreos-livepxe-rootfs"
install_and_enable_unit "coreos-live-unmount-tmpfs-var.service" \
"initrd-switch-root.target"
install_and_enable_unit "coreos-livepxe-rootfs.service" \
"initrd-root-fs.target"
install_and_enable_unit "coreos-live-clear-sssd-cache.service" \
"ignition-complete.target"
install_and_enable_unit "coreos-liveiso-persist-osmet.service" \
"default.target"
install_and_enable_unit "coreos-livepxe-persist-osmet.service" \
"default.target"
}

View File

@ -0,0 +1,25 @@
#!/bin/bash
# With live PXE there's no ostree= argument on the kernel command line, so
# we need to find the tree path and pass it to ostree-prepare-root. But
# ostree-prepare-root only knows how to read the path from
# /proc/cmdline, so we need to synthesize the proper karg and bind-mount
# it over /proc/cmdline.
# https://github.com/ostreedev/ostree/issues/1920
set -euo pipefail
case "${1:-unset}" in
start)
treepath="$(echo /sysroot/ostree/boot.1/*/*/0)"
echo "$(cat /proc/cmdline) ostree=${treepath#/sysroot}" > /tmp/cmdline
mount --bind /tmp/cmdline /proc/cmdline
;;
stop)
umount /proc/cmdline
rm /tmp/cmdline
;;
*)
echo "Usage: $0 {start|stop}" >&2
exit 1
;;
esac

View File

@ -0,0 +1,30 @@
#!/bin/bash
# Generators don't have logging right now
# https://github.com/systemd/systemd/issues/15638
exec 1>/dev/kmsg; exec 2>&1
command -v getargbool >/dev/null || . /usr/lib/dracut-lib.sh
set -e
if is-live-image; then
exit 0
fi
UNIT_DIR="${1:-/tmp}"
add_requires() {
local name="$1"; shift
local target="$1"; shift
local requires_dir="${UNIT_DIR}/${target}.requires"
mkdir -p "${requires_dir}"
ln -sf "../${name}" "${requires_dir}/${name}"
}
if getargbool 0 rd.multipath; then
add_requires coreos-multipath-wait.target initrd.target
if ! getargbool 0 ignition.firstboot; then
add_requires coreos-multipath-trigger.service initrd.target
fi
fi

View File

@ -0,0 +1,19 @@
# This unit is needed in the LUKS-on-multipath case on subsequent boots. When
# multipathd takes ownership of the individual paths, the by-uuid/ symlink
# which systemd-cryptsetup@.service binds to gets lost. So we retrigger udev
# here to make sure it's re-added.
#
# This is tracked at:
# https://bugzilla.redhat.com/show_bug.cgi?id=1963242
[Unit]
Description=CoreOS Trigger Multipath
DefaultDependencies=false
Requires=coreos-multipath-wait.target
After=coreos-multipath-wait.target
Before=cryptsetup-pre.target
[Service]
Type=oneshot
ExecStart=/usr/sbin/udevadm trigger --settle --subsystem-match block
RemainAfterExit=yes

View File

@ -0,0 +1,17 @@
[Unit]
Description=CoreOS Wait For Multipathed Boot
DefaultDependencies=false
Before=dracut-initqueue.service
After=dracut-cmdline.service
Requires=dev-disk-by\x2dlabel-dm\x2dmpath\x2dboot.device
After=dev-disk-by\x2dlabel-dm\x2dmpath\x2dboot.device
Requires=multipathd.service
After=multipathd.service
# This is already enforced transitively by coreos-gpt-setup.service, but
# let's be more explicit and list it directly here too.
Before=coreos-ignition-setup-user.service
# This is already enforced by coreos-multipath-trigger.service, though ideally
# eventually we can get rid of that one and then we *would* need this.
Before=cryptsetup-pre.target

View File

@ -0,0 +1,24 @@
[Unit]
Description=CoreOS Propagate Multipath Configuration
Before=initrd.target
# we write to the rootfs, so run after it's ready
After=initrd-root-fs.target
# we only propagate if multipath wasn't configured via Ignition
After=ignition-files.service
# That service starts initrd-cleanup.service which will race with us completing
# before we get nuked. Need to get to the bottom of it, but for now we need
# this (XXX: add link to systemd issue here).
Before=initrd-parse-etc.service
ConditionKernelCommandLine=rd.multipath=default
OnFailure=emergency.target
OnFailureJobMode=isolate
[Service]
Type=oneshot
ExecStart=/usr/sbin/coreos-propagate-multipath-conf
RemainAfterExit=yes

View File

@ -0,0 +1,23 @@
#!/bin/bash
set -euo pipefail
# Persist automatic multipath configuration, if any.
# When booting with `rd.multipath=default`, the default multipath
# configuration is written. We need to ensure that the multipath configuration
# is persisted to the rootfs.
if [ ! -f /etc/multipath.conf ]; then
echo "info: initrd file /etc/multipath.conf does not exist"
echo "info: no initrd multipath configuration to propagate"
exit 0
fi
if [ -f /sysroot/etc/multipath.conf ]; then
echo "info: real root file /etc/multipath.conf exists"
echo "info: not propagating initrd multipath configuration"
exit 0
fi
echo "info: propagating initrd multipath configuration"
cp -v /etc/multipath.conf /sysroot/etc/
coreos-relabel /etc/multipath.conf

View File

@ -0,0 +1,28 @@
#!/bin/bash
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# ex: ts=8 sw=4 sts=4 et filetype=sh
install_unit() {
local unit=$1; shift
local target=${1:-initrd}
inst_simple "$moddir/$unit" "$systemdsystemunitdir/$unit"
# note we `|| exit 1` here so we error out if e.g. the units are missing
# see https://github.com/coreos/fedora-coreos-config/issues/799
systemctl -q --root="$initdir" add-requires "${target}.target" "$unit" || exit 1
}
install() {
inst_script "$moddir/coreos-propagate-multipath-conf.sh" \
"/usr/sbin/coreos-propagate-multipath-conf"
install_unit coreos-propagate-multipath-conf.service
inst_simple "$moddir/coreos-multipath-generator" \
"$systemdutildir/system-generators/coreos-multipath-generator"
# we don't enable these; they're enabled dynamically via the generator
inst_simple "$moddir/coreos-multipath-wait.target" \
"$systemdsystemunitdir/coreos-multipath-wait.target"
inst_simple "$moddir/coreos-multipath-trigger.service" \
"$systemdsystemunitdir/coreos-multipath-trigger.service"
}

View File

@ -0,0 +1,7 @@
# This contains the default kargs for firstboot network configuration.
# Default values can be dynamically overridden by platform-specific
# logic (e.g. injected via a back-channel).
# https://github.com/coreos/fedora-coreos-tracker/issues/460
[Service]
Environment=AFTERBURN_NETWORK_KARGS_DEFAULT='ip=auto'

View File

@ -0,0 +1,65 @@
# This unit will run early in boot and detect if:
# - In the diskful case, the user copied in firstboot networking config files
# into `/boot` (most likely by using `coreos-installer install
# --copy-network`).
# - In the live case, the user provided firstboot networking config files in
# `/etc` (most likely by using `coreos-installer iso network embed`).
#
# Since this unit is modifying network configuration there are some
# dependencies that we have:
#
# - In the diskful case, we need to look for networking configuration on the
# /boot partition
# - i.e. after /dev/disk/by-label/boot is available
# - which is implied by running after coreos-gpt-setup (see below)
# - Need to run before networking is brought up.
# - This is done in nm-initrd.service [1]
# - i.e. Before=nm-initrd.service
# - Need to make sure karg networking configuration isn't applied
# - There are two ways to do this.
# - One is to run *before* the nm-config.sh [2] that runs as part of
# dracut-cmdline [3] and `ln -sf /bin/true /usr/libexec/nm-initrd-generator`.
# - i.e. Before=dracut-cmdline.service
# - Another is to run *after* nm-config.sh [2] in dracut-cmdline [3]
# and just delete all the files created by nm-initrd-generator.
# - i.e. After=dracut-cmdline.service, but Before=nm-initrd.service
# - We'll go with the second option here because the need for the /boot
# device (mentioned above) means we can't start before dracut-cmdline.service
#
# [1] https://github.com/dracutdevs/dracut/blob/master/modules.d/35network-manager/nm-initrd.service
# [2] https://github.com/dracutdevs/dracut/blob/master/modules.d/35network-manager/nm-config.sh
# [3] https://github.com/dracutdevs/dracut/blob/master/modules.d/35network-manager/module-setup.sh#L34
#
[Unit]
Description=Copy CoreOS Firstboot Networking Config
ConditionPathExists=/usr/lib/initrd-release
DefaultDependencies=false
# We're pulled in by ignition-complete.target; as good practice, add a matching
# Before to be explicit about it gating on this unit passing.
Before=ignition-complete.target
Before=nm-initrd.service
# compat: remove when everyone is on dracut 054+
Before=dracut-initqueue.service
After=dracut-cmdline.service
# Any services looking at mounts need to order after this
# because it causes device re-probing.
After=coreos-gpt-setup.service
# And since the boot device may be on multipath; optionally wait for it to
# appear via the dynamic target.
After=coreos-multipath-wait.target
# Need to run after coreos-enable-network since it may re-run the NM cmdline
# hook which will generate NM configs from the network kargs, but we want to
# have precedence.
After=coreos-enable-network.service
# We've seen races with ignition-kargs.service, which accesses /boot rw.
# Let's introduce some ordering here. Need to use `Before` because otherwise
# we get a systemd ordering cycle. https://github.com/coreos/fedora-coreos-tracker/issues/883
Before=ignition-kargs.service
[Service]
Type=oneshot
RemainAfterExit=yes
# The MountFlags=slave is so the umount of /boot is guaranteed to happen
# /boot will only be mounted for the lifetime of the unit.
MountFlags=slave
ExecStart=/usr/sbin/coreos-copy-firstboot-network

View File

@ -0,0 +1,49 @@
#!/bin/bash
set -euo pipefail
# For a description of how this is used see coreos-copy-firstboot-network.service
bootmnt=/mnt/boot_partition
bootdev=/dev/disk/by-label/boot
firstboot_network_dir_basename="coreos-firstboot-network"
boot_firstboot_network_dir="${bootmnt}/${firstboot_network_dir_basename}"
etc_firstboot_network_dir="/etc/${firstboot_network_dir_basename}"
initramfs_network_dir="/run/NetworkManager/system-connections/"
copy_firstboot_network() {
local src=$1; shift
# Clear out any files that may have already been generated from
# kargs by nm-initrd-generator
rm -f ${initramfs_network_dir}/*
# Copy files that were placed into the source
# to the appropriate location for NetworkManager to use the configuration.
echo "info: copying files from ${src} to ${initramfs_network_dir}"
mkdir -p ${initramfs_network_dir}
cp -v ${src}/* ${initramfs_network_dir}/
}
if ! is-live-image; then
# Mount /boot. Note that we mount /boot but we don't unmount boot because we
# are run in a systemd unit with MountFlags=slave so it is unmounted for us.
# Mount as read-only since we don't strictly need write access and we may be
# running alongside other code that also has it mounted ro
mkdir -p ${bootmnt}
mount -o ro ${bootdev} ${bootmnt}
if [ -n "$(ls -A ${boot_firstboot_network_dir} 2>/dev/null)" ]; then
# Likely placed there by coreos-installer, see:
# https://github.com/coreos/coreos-installer/pull/212
copy_firstboot_network "${boot_firstboot_network_dir}"
else
echo "info: no files to copy from ${boot_firstboot_network_dir}; skipping"
fi
else
if [ -n "$(ls -A ${etc_firstboot_network_dir} 2>/dev/null)" ]; then
# Also placed there by coreos-installer but in a different flow, see:
# https://github.com/coreos/coreos-installer/pull/713
copy_firstboot_network "${etc_firstboot_network_dir}"
else
echo "info: no files to copy from ${etc_firstboot_network_dir}; skipping"
fi
fi

View File

@ -0,0 +1,30 @@
[Unit]
Description=CoreOS Enable Network
ConditionPathExists=/etc/initrd-release
DefaultDependencies=false
After=basic.target
# Triggering conditions for cases where we need network:
# * when Ignition signals that it is required for provisioning.
# * on live systems fetching the remote rootfs in initramfs.
# * on Azure and Azure Stack Hub, for hostname fetching (metadata endpoint) and boot check-in (wireserver).
ConditionPathExists=|/run/ignition/neednet
ConditionKernelCommandLine=|coreos.live.rootfs_url
ConditionKernelCommandLine=|ignition.platform.id=azure
ConditionKernelCommandLine=|ignition.platform.id=azurestack
# Creates /run/ignition/neednet
After=ignition-fetch-offline.service
# Needs networking
Before=ignition-fetch.service
# See hack in coreos-enable-network, as well as coreos-copy-firstboot-network.service.
After=dracut-cmdline.service
Before=nm-initrd.service
# compat: remove when everyone is on dracut 054+
Before=dracut-initqueue.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/sbin/coreos-enable-network

View File

@ -0,0 +1,27 @@
#!/bin/bash
set -euo pipefail
set +euo pipefail
. /usr/lib/dracut-lib.sh
set -euo pipefail
dracut_func() {
# dracut is not friendly to set -eu
set +euo pipefail
"$@"; local rc=$?
set -euo pipefail
return $rc
}
# If networking hasn't been requested yet, request it.
if ! dracut_func getargbool 0 'rd.neednet'; then
echo "rd.neednet=1" > /etc/cmdline.d/40-coreos-neednet.conf
# Hack: we need to rerun the NM cmdline hook because we run after
# dracut-cmdline.service because we need udev. We should be able to move
# away from this once we run NM as a systemd unit. See also:
# https://github.com/coreos/fedora-coreos-config/pull/346#discussion_r409843428
set +euo pipefail
. /usr/lib/dracut/hooks/cmdline/99-nm-config.sh
set -euo pipefail
fi

View File

@ -0,0 +1,26 @@
install_and_enable_unit() {
unit="$1"; shift
target="$1"; shift
inst_simple "$moddir/$unit" "$systemdsystemunitdir/$unit"
# note we `|| exit 1` here so we error out if e.g. the units are missing
# see https://github.com/coreos/fedora-coreos-config/issues/799
systemctl -q --root="$initdir" add-requires "$target" "$unit" || exit 1
}
install() {
inst_simple "$moddir/coreos-enable-network.sh" \
"/usr/sbin/coreos-enable-network"
install_and_enable_unit "coreos-enable-network.service" \
"initrd.target"
inst_simple "$moddir/coreos-copy-firstboot-network.sh" \
"/usr/sbin/coreos-copy-firstboot-network"
install_and_enable_unit "coreos-copy-firstboot-network.service" \
"ignition-complete.target"
# Dropin with firstboot network configuration kargs, applied via
# Afterburn.
inst_simple "$moddir/50-afterburn-network-kargs-default.conf" \
"/usr/lib/systemd/system/afterburn-network-kargs.service.d/50-afterburn-network-kargs-default.conf"
}

View File

@ -0,0 +1,19 @@
{
"ignition": {
"version": "3.0.0"
},
"passwd": {
"users": [
{
"name": "core",
"gecos": "CoreOS Admin",
"groups": [
"adm",
"sudo",
"systemd-journal",
"wheel"
]
}
]
}
}

View File

@ -0,0 +1 @@
`00-core.ign` is the base config shared between FCOS and RHCOS. The configs specific to FCOS are in [50ignition-conf-fcos](../../../../../../15fcos/usr/lib/dracut/modules.d/50ignition-conf-fcos).

View File

@ -0,0 +1,13 @@
#!/bin/bash
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# ex: ts=8 sw=4 sts=4 et filetype=sh
depends() {
echo ignition
}
install() {
mkdir -p "$initdir/usr/lib/ignition/base.d"
inst "$moddir/00-core.ign" \
"/usr/lib/ignition/base.d/00-core.ign"
}

View File

@ -0,0 +1,37 @@
#!/bin/bash
set -euo pipefail
# See also ignition-ostree-check-rootfs-size.service
# https://github.com/coreos/fedora-coreos-tracker/issues/586#issuecomment-777220000
srcdev=$(findmnt -nvr -o SOURCE /sysroot | tail -n1)
size=$(lsblk --nodeps --noheadings --bytes -o SIZE "${srcdev}")
MINIMUM_GB=8
MINIMUM_BYTES=$((1024 * 1024 * 1024 * MINIMUM_GB))
MOTD_DROPIN=/etc/motd.d/60-coreos-rootfs-size.motd
YELLOW=$(echo -e '\033[0;33m')
RESET=$(echo -e '\033[0m')
if [ "${size}" -lt "${MINIMUM_BYTES}" ]; then
mkdir -p "/sysroot/$(dirname "${MOTD_DROPIN}")"
cat > "/sysroot/${MOTD_DROPIN}" <<EOF
${YELLOW}
############################################################################
WARNING: The root filesystem is too small. It is strongly recommended to
allocate at least ${MINIMUM_GB} GiB of space to allow for upgrades. From June 2021, this
condition will trigger a failure in some cases. For more information, see:
https://docs.fedoraproject.org/en-US/fedora-coreos/storage/
You may delete this warning using:
sudo rm ${MOTD_DROPIN}
############################################################################
${RESET}
EOF
# And also write it on stdout for the journal and console
cat "/sysroot/${MOTD_DROPIN}"
coreos-relabel "${MOTD_DROPIN}"
fi

View File

@ -0,0 +1,35 @@
#!/bin/bash
set -euo pipefail
err() {
echo "$@" >&2
}
fatal() {
err "$@"
exit 1
}
if [ $# -eq 0 ]; then
err "Usage: $0 [PATTERN...]"
err " e.g.: $0 /etc/passwd '/etc/group*'"
fi
if [ ! -f /sysroot/etc/selinux/config ]; then
exit 0
fi
source /sysroot/etc/selinux/config
if [ -z "${SELINUXTYPE:-}" ]; then
fatal "Couldn't find SELINUXTYPE in /sysroot/etc/selinux/config"
fi
file_contexts="/sysroot/etc/selinux/${SELINUXTYPE}/contexts/files/file_contexts"
prefixed_patterns=()
while [ $# -ne 0 ]; do
pattern=$1; shift
prefixed_patterns+=("/sysroot/$pattern")
done
setfiles -vFi0 -r /sysroot "$file_contexts" "${prefixed_patterns[@]}"

View File

@ -0,0 +1,30 @@
#!/bin/bash
set -euo pipefail
# see related comment block in transposefs.sh re. inspecting the config directly
ignition_cfg=/run/ignition.json
rootpath=/dev/disk/by-label/root
query_rootfs() {
local filter=$1
jq -re ".storage?.filesystems? // [] |
map(select(.label == \"root\" and .wipeFilesystem == true)) |
.[0] | $filter" "${ignition_cfg}"
}
# If the rootfs was reprovisioned, then the mountOptions from the Ignition
# config has priority.
if [ -d /run/ignition-ostree-transposefs/root ]; then
if query_rootfs 'has("mountOptions")' >/dev/null; then
query_rootfs '.mountOptions | join(",")'
exit 0
fi
fi
eval $(blkid -o export ${rootpath})
if [ "${TYPE}" == "xfs" ]; then
# We use prjquota on XFS by default to aid multi-tenant Kubernetes (and
# other container) clusters. See
# https://github.com/coreos/coreos-assembler/pull/303/commits/6103effbd006bb6109467830d6a3e42dd847668d
echo "prjquota"
fi

View File

@ -0,0 +1,15 @@
[Unit]
Description=Ignition OSTree: Check Root Filesystem Size
Documentation=https://docs.fedoraproject.org/en-US/fedora-coreos/storage/
DefaultDependencies=false
ConditionKernelCommandLine=ostree
ConditionPathExists=!/run/ostree-live
After=ignition-ostree-growfs.service
After=ostree-prepare-root.service
# Allow Ignition config to blank out the warning
Before=ignition-files.service
[Service]
Type=oneshot
ExecStart=/usr/libexec/coreos-check-rootfs-size
RemainAfterExit=yes

View File

@ -0,0 +1,68 @@
#!/bin/bash
set -euo pipefail
# https://github.com/coreos/fedora-coreos-tracker/issues/465
# coreos-assembler generates disk images which are installed bit-for-bit
# or booted directly in the cloud.
# Generate new UUID on firstboot; this is general best practice, but in the future
# we may use this for mounting by e.g. adding a boot=<uuid> and root=<uuid> kernel args.
label=$1
# Keep this in sync with https://github.com/coreos/coreos-assembler/blob/e3905fd2e138de04184c1cd86b99b0fd83cbe5cf/src/create_disk.sh#L17
bootfs_uuid="96d15588-3596-4b3c-adca-a2ff7279ea63"
rootfs_uuid="910678ff-f77e-4a7d-8d53-86f2ac47a823"
target=/dev/disk/by-label/${label}
if ! [ -b "${target}" ]; then
echo "$0: Failed to find block device ${target}" 1>&2
exit 1
fi
eval $(blkid -o export ${target})
case "${label}" in
root) orig_uuid="${rootfs_uuid}"; orig_type=xfs ;;
boot) orig_uuid="${bootfs_uuid}"; orig_type=ext4 ;;
*) echo "unexpected ${label}"; exit 1 ;;
esac
if [ "${TYPE}" == "${orig_type}" ] && [ "${UUID}" == "${orig_uuid}" ]; then
case "${TYPE}" in
ext4)
# If the filesystem supports metadata_csum_seed then the UUID is stored
# in the superblock and there is no need to worry with an fsck. For the
# boot filesystem this FS feature wasn't supported by GRUB until recently.
# https://lists.gnu.org/archive/html/grub-devel/2021-06/msg00031.html
# Once grub is updated in all systems we care about we can standardize
# on the metadata_csum_seed and delete the `else` code block.
if tune2fs -l ${target} | grep 'metadata_csum_seed'; then
tune2fs -U random "${target}"
else
# Run an fsck since tune2fs -U requires the FS to be clean
e2fsck -fy "${target}"
# We just ran an fsck, but there is a bug where tune2fs -U will still
# complain. It will still error if the last checked timestamp (just
# set by the e2fsck above) is older than the last mount timestamp (happens
# on systems with out of date or non-functioning hardware clocks).
# See https://github.com/coreos/fedora-coreos-tracker/issues/735#issuecomment-859605953
# Potentially fixed in future by: https://www.spinics.net/lists/linux-ext4/msg78012.html
tune2fsinfo="$(tune2fs -l ${target})"
lastmount=$(echo "$tune2fsinfo" | grep '^Last mount time:' | cut -d ':' -f 2,3,4)
lastfsck=$(echo "$tune2fsinfo" | grep '^Last checked:' | cut -d ':' -f 2,3,4)
lastmountsse=$(date --date="$lastmount" +%s)
lastfscksse=$(date --date="$lastfsck" +%s)
if (( lastfscksse < lastmountsse )); then
echo "Detected timestamp of last fsck is older than timestamp of last mount."
echo "Setting "${target}" timestamp of last fsck to same time as last mount."
tune2fs -T $(date --date="$lastmount" +%Y%m%d%H%M%S) "${target}"
fi
# Finally, we can randomize the UUID
tune2fs -U random "${target}"
fi ;;
xfs) xfs_admin -U generate "${target}" ;;
*) echo "unexpected filesystem type ${TYPE}" 1>&2; exit 1 ;;
esac
udevadm settle || :
echo "Regenerated UUID for ${target}"
else
echo "No changes required for ${target} TYPE=${TYPE} UUID=${UUID}"
fi

View File

@ -0,0 +1,15 @@
[Unit]
Description=Ignition OSTree: Grow root filesystem
DefaultDependencies=false
ConditionKernelCommandLine=ostree
ConditionPathExists=!/run/ostree-live
Before=initrd-root-fs.target
After=sysroot.mount ignition-ostree-mount-firstboot-sysroot.service
# This shouldn't be strictly necessary, but it's cleaner to not have OSTree muck
# around with moving mounts while we're still resizing the filesystem.
Before=ostree-prepare-root.service
[Service]
Type=oneshot
ExecStart=/usr/sbin/ignition-ostree-growfs
RemainAfterExit=yes

View File

@ -0,0 +1,126 @@
#!/bin/bash
set -euo pipefail
# This script is run by ignition-ostree-growfs.service. It grows the root
# partition, unless it determines that either the rootfs was moved or the
# partition was already resized (e.g. via Ignition).
# If root reprovisioning was triggered, this file contains state of the root
# partition *before* ignition-disks.
saved_partstate=/run/ignition-ostree-rootfs-partstate.sh
# We run after the rootfs is mounted at /sysroot, but before ostree-prepare-root
# moves it to /sysroot/sysroot.
path=/sysroot
# The use of tail is to avoid errors from duplicate mounts;
# this shouldn't happen for us but we're being conservative.
src=$(findmnt -nvr -o SOURCE "$path" | tail -n1)
# In the IBM Secure Execution case we use Ignition to grow and reencrypt rootfs
# see overlay.d/05core/usr/lib/dracut/modules.d/35coreos-ignition/coreos-diskful-generator
if [[ -f /run/coreos/secure-execution ]]; then
exit 0
fi
if [ ! -f "${saved_partstate}" ]; then
partition=$(realpath /dev/disk/by-label/root)
else
# The rootfs was reprovisioned. Our rule in this case is: we only grow if
# the partition backing the rootfs is the same and its size didn't change
# (IOW, it was an in-place reprovisioning; e.g. LUKS or xfs -> btrfs).
source "${saved_partstate}"
if [ "${TYPE}" != "part" ]; then
# this really should never happen; but play nice
echo "$0: original rootfs blockdev not of type 'part'; not auto-growing"
exit 0
fi
partition=$(realpath "${NAME}")
if [ "${SIZE}" != "$(lsblk --nodeps -bno SIZE "${partition}")" ]; then
echo "$0: original root partition changed size; not auto-growing"
exit 0
fi
if ! lsblk -no MOUNTPOINT "${partition}" | grep -q '^/sysroot$'; then
echo "$0: original root partition no longer backing rootfs; not auto-growing"
exit 0
fi
fi
# Go through each blockdev in the hierarchy and verify we know how to grow them
lsblk -no TYPE "${partition}" | while read dev; do
case "${dev}" in
part|crypt) ;;
*) echo "error: Unsupported blockdev type ${dev}" 1>&2; exit 1 ;;
esac
done
# Get the filesystem type before extending the partition. This matters
# because the partition, once extended, might include leftover superblocks
# from the previous contents of the disk (notably ZFS), causing blkid to
# refuse to return any filesystem type at all.
eval $(blkid -o export "${src}")
ROOTFS_TYPE=${TYPE:-}
case "${ROOTFS_TYPE}" in
xfs|ext4|btrfs) ;;
*) echo "error: Unsupported filesystem for ${path}: '${ROOTFS_TYPE}'" 1>&2; exit 1 ;;
esac
# Now, go through the hierarchy, growing everything. Note we go one device at a
# time using --nodeps, because ordering is buggy in el8:
# https://bugzilla.redhat.com/show_bug.cgi?id=1940607
current_blkdev=${partition}
while true; do
eval "$(lsblk --paths --nodeps --pairs -o NAME,TYPE,PKNAME "${current_blkdev}")"
MAJMIN=$(echo $(lsblk -dno MAJ:MIN "${NAME}"))
case "${TYPE}" in
part)
eval $(udevadm info --query property --export "${current_blkdev}" | grep ^DM_ || :)
if [ -n "${DM_MPATH:-}" ]; then
# Since growpart does not understand device mapper, we have to use sfdisk.
echo ", +" | sfdisk --no-reread --no-tell-kernel --force -N "${DM_PART}" "/dev/mapper/${DM_MPATH}"
udevadm settle || : # Wait for udev-triggered kpartx to update mappings
else
partnum=$(cat "/sys/dev/block/${MAJMIN}/partition")
# XXX: ideally this'd be idempotent and we wouldn't `|| :`
growpart "${PKNAME}" "${partnum}" || :
fi
;;
crypt)
# XXX: yuck... we need to expose this sanely in clevis
(. /usr/bin/clevis-luks-common-functions
eval $(udevadm info --query=property --export "${NAME}")
# lsblk doesn't print PKNAME of crypt devices with --nodeps
PKNAME=/dev/$(ls "/sys/dev/block/${MAJMIN}/slaves")
clevis_luks_unlock_device "${PKNAME}" | cryptsetup resize -d- "${DM_NAME}"
)
;;
# already checked
*) echo "unreachable" 1>&2; exit 1 ;;
esac
holders="/sys/dev/block/${MAJMIN}/holders"
[ -d "${holders}" ] || break
nholders="$(ls "${holders}" | wc -l)"
if [ "${nholders}" -eq 0 ]; then
break
elif [ "${nholders}" -gt 1 ]; then
# this shouldn't happen since we've checked the partition types already
echo "error: Unsupported block device with multiple children: ${NAME}" 1>&2
exit 1
fi
current_blkdev=/dev/$(ls "${holders}")
done
# Wipe any filesystem signatures from the extended partition that don't
# correspond to the FS type we detected earlier.
wipefs -af -t "no${ROOTFS_TYPE}" "${src}"
# TODO: Add XFS to https://github.com/systemd/systemd/blob/master/src/partition/growfs.c
# and use it instead.
case "${ROOTFS_TYPE}" in
xfs) xfs_growfs "${path}" ;;
ext4) resize2fs "${src}" ;;
btrfs) btrfs filesystem resize max ${path} ;;
esac
# this is useful for tests
touch /run/ignition-ostree-growfs.stamp

View File

@ -0,0 +1,25 @@
[Unit]
Description=Ignition OSTree: Mount (firstboot) /sysroot
# These dependencies should match the "other" in
# ignition-ostree-mount-subsequent-sysroot.service
DefaultDependencies=false
# If root is specified, then systemd's generator will win
ConditionKernelCommandLine=!root
ConditionKernelCommandLine=ostree
# This is redundant since we're queued on -diskful.target, but eh.
ConditionPathExists=!/run/ostree-live
# There can be only one, Highlander style
Conflicts=ignition-ostree-mount-subsequent-sysroot.service
Before=initrd-root-fs.target
After=ignition-disks.service
# Note we don't have a Requires: /dev/disk/by-label/root here like
# the -subsequent service does because ignition-disks may have
# regenerated it.
Requires=ignition-disks.service
# These have an explicit dependency on After=sysroot.mount today
Before=ostree-prepare-root.service ignition-remount-sysroot.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/sbin/ignition-ostree-mount-sysroot

View File

@ -0,0 +1,24 @@
# Note this unit is conditionally enabled by ignition-ostree-generator
[Unit]
Description=CoreOS: Mount (subsequent) /sysroot
# These dependencies should match the "other" in
# ignition-ostree-mount-firsboot-sysroot.service
DefaultDependencies=false
# If root is specified, then systemd's generator will win
ConditionKernelCommandLine=!root
ConditionKernelCommandLine=ostree
ConditionPathExists=!/run/ostree-live
# There can be only one, Highlander style
Conflicts=ignition-ostree-mount-firstboot-sysroot.service
# And in contrast to the firstboot, we expect
# the root device to be ready.
Requires=dev-disk-by\x2dlabel-root.device
After=dev-disk-by\x2dlabel-root.device
Before=initrd-root-fs.target
# This has an explicit dependency on After=sysroot.mount today
Before=ostree-prepare-root.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/sbin/ignition-ostree-mount-sysroot

View File

@ -0,0 +1,18 @@
#!/bin/bash
set -euo pipefail
# Note that on *new machines* this script is now only ever used on firstboot. On
# subsequent boots, systemd-fstab-generator mounts /sysroot from the
# root=UUID=... and rootflags=... kargs.
# We may do a migration window at some point where older machines have these
# kargs injected so that we can simplify the model further.
rootpath=/dev/disk/by-label/root
if ! [ -b "${rootpath}" ]; then
echo "ignition-ostree-mount-sysroot: Failed to find ${rootpath}" 1>&2
exit 1
fi
echo "Mounting ${rootpath} ($(realpath "${rootpath}")) to /sysroot"
mount -o "$(coreos-rootflags)" "${rootpath}" /sysroot

View File

@ -0,0 +1,26 @@
[Unit]
Description=Mount OSTree /var
DefaultDependencies=false
ConditionKernelCommandLine=ostree
ConditionPathExists=!/run/ostree-live
# Make sure ExecStop= runs before we switch root
Before=initrd-switch-root.target
# Make sure if ExecStop= fails, the boot fails
OnFailure=emergency.target
OnFailureJobMode=isolate
# Make sure /sysroot is mounted first, since we're mounting under there
Requires=initrd-root-fs.target
After=initrd-root-fs.target
# Need to do this before Ignition mounts any other filesystems (potentially
# shadowing our own bind mount).
Before=ignition-mount.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/sbin/ignition-ostree-mount-var mount
ExecStop=/usr/sbin/ignition-ostree-mount-var umount

View File

@ -0,0 +1,52 @@
#!/bin/bash
set -euo pipefail
fatal() {
echo "$@" >&2
exit 1
}
if [ $# -ne 1 ] || { [[ $1 != mount ]] && [[ $1 != umount ]]; }; then
fatal "Usage: $0 <mount|umount>"
fi
get_ostree_arg() {
# yes, this doesn't account for spaces within args, e.g. myarg="my val", but
# it still works for our purposes
(
IFS=$' '
# shellcheck disable=SC2013
for arg in $(cat /proc/cmdline); do
if [[ $arg == ostree=* ]]; then
echo "${arg#ostree=}"
fi
done
)
}
do_mount() {
ostree=$(get_ostree_arg)
if [ -z "${ostree}" ]; then
fatal "No ostree= kernel argument in /proc/cmdline"
fi
deployment_path=/sysroot/${ostree}
if [ ! -L "${deployment_path}" ]; then
fatal "${deployment_path} is not a symlink"
fi
stateroot_var_path=$(realpath "${deployment_path}/../../var")
if [ ! -d "${stateroot_var_path}" ]; then
fatal "${stateroot_var_path} is not a directory"
fi
echo "Mounting $stateroot_var_path"
mount --bind "$stateroot_var_path" /sysroot/var
}
do_umount() {
echo "Unmounting /sysroot/var"
umount /sysroot/var
}
"do_$1"

View File

@ -0,0 +1,16 @@
[Unit]
Description=Populate OSTree /var
DefaultDependencies=false
ConditionKernelCommandLine=|ostree
ConditionPathExists=|/run/ostree-live
# Need to do this with all mount points active
After=ignition-mount.service
# But *before* we start dumping files in there
Before=ignition-files.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/sbin/ignition-ostree-populate-var

View File

@ -0,0 +1,45 @@
#!/bin/bash
set -euo pipefail
fatal() {
echo "$@" >&2
exit 1
}
if [ $# -ne 0 ]; then
fatal "Usage: $0"
fi
# See the similar code block in Anaconda, which handles this today for Atomic
# Host and Silverblue:
# https://github.com/rhinstaller/anaconda/blob/b9ea8ce4e68196b30a524c1cc5680dcdc4b89371/pyanaconda/payload/rpmostreepayload.py#L332
for varsubdir in lib log home roothome opt srv usrlocal mnt media; do
# If the directory already existed, just ignore. This addresses the live
# image case with persistent `/var`; we don't want to relabel all the files
# there on each boot.
if [ -d "/sysroot/var/${varsubdir}" ]; then
continue
fi
if [[ $varsubdir == lib ]] || [[ $varsubdir == log ]]; then
# Simply manually mkdir /var/{lib,log}; the tmpfiles.d entries otherwise
# reference users/groups which we don't have access to from here
# (though... we *could* import them from the sysroot, and have
# nss-altfiles in the initrd, but meh... let's just wait for
# systemd-sysusers which will make this way easier:
# https://github.com/coreos/fedora-coreos-config/pull/56/files#r262592361).
mkdir -p /sysroot/var/${varsubdir}
else
systemd-tmpfiles --create --boot --root=/sysroot --prefix="/var/${varsubdir}"
fi
if [[ $varsubdir == roothome ]]; then
# TODO move this to tmpfiles.d once systemd-tmpfiles handles C! with --root correctly.
# See https://github.com/coreos/fedora-coreos-config/pull/137
cp /sysroot/etc/skel/.bash* /sysroot/var/${varsubdir}
fi
coreos-relabel "/var/${varsubdir}"
done

View File

@ -0,0 +1,18 @@
# RHOCS 4.12.s390x has an old kernel with a known issue: https://bugzilla.redhat.com/show_bug.cgi?id=2075085
# Once we have kernel >= 4.18.0-387.el8.s390x we should drop this unit and copy config in coreos-diskful-generator
[Unit]
Description=Ignition OSTree: Inject Secure Execution Config
DefaultDependencies=false
ConditionArchitecture=s390x
ConditionKernelCommandLine=ostree
ConditionPathExists=/run/coreos/secure-execution
OnFailure=emergency.target
OnFailureJobMode=isolate
After=coreos-gpt-setup.service
Before=ignition-fetch-offline.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/libexec/ignition-ostree-secex-config

View File

@ -0,0 +1,5 @@
#!/bin/bash
set -euo pipefail
bootdev=$(blkid --list-one --output device --match-token PARTLABEL=boot | sed 's,[0-9]\+$,,')
sed "s,\${BOOTDEV},$bootdev," < /usr/lib/coreos/01-secex.ign > /usr/lib/ignition/base.d/01-secex.ign

View File

@ -0,0 +1,20 @@
[Unit]
Description=Ignition OSTree: Detect Partition Transposition
DefaultDependencies=false
After=ignition-fetch.service
Before=ignition-disks.service
Before=initrd-root-fs.target
Before=sysroot.mount
ConditionKernelCommandLine=ostree
OnFailure=emergency.target
OnFailureJobMode=isolate
# This stage requires udevd to detect disks
Requires=systemd-udevd.service
After=systemd-udevd.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/libexec/ignition-ostree-transposefs detect
ExecStop=/usr/libexec/ignition-ostree-transposefs cleanup

View File

@ -0,0 +1,20 @@
[Unit]
Description=Ignition OSTree: Restore Partitions
DefaultDependencies=false
After=ignition-disks.service
# Avoid racing with UUID regeneration
After=ignition-ostree-uuid-root.service
Before=ignition-ostree-growfs.service
Before=ignition-ostree-mount-firstboot-sysroot.service
OnFailure=emergency.target
OnFailureJobMode=isolate
ConditionKernelCommandLine=ostree
ConditionPathIsDirectory=/run/ignition-ostree-transposefs
[Service]
Type=oneshot
RemainAfterExit=yes
# So we can transiently mount sysroot
MountFlags=slave
ExecStart=/usr/libexec/ignition-ostree-transposefs restore

View File

@ -0,0 +1,19 @@
[Unit]
Description=Ignition OSTree: Save Partitions
DefaultDependencies=false
After=ignition-ostree-transposefs-detect.service
Before=ignition-disks.service
ConditionKernelCommandLine=ostree
ConditionPathIsDirectory=/run/ignition-ostree-transposefs
# Any services looking at mounts need to order after this
# because it causes device re-probing.
After=coreos-gpt-setup.service
OnFailure=emergency.target
OnFailureJobMode=isolate
[Service]
Type=oneshot
RemainAfterExit=yes
# So we can transiently mount sysroot
MountFlags=slave
ExecStart=/usr/libexec/ignition-ostree-transposefs save

View File

@ -0,0 +1,299 @@
#!/bin/bash
set -euo pipefail
boot_sector_size=440
esp_typeguid=c12a7328-f81f-11d2-ba4b-00a0c93ec93b
bios_typeguid=21686148-6449-6e6f-744e-656564454649
prep_typeguid=9e1a2d38-c612-4316-aa26-8b49521e5a8b
# This is implementation details of Ignition; in the future, we should figure
# out a way to ask Ignition directly whether there's a filesystem with label
# "root" being set up.
ignition_cfg=/run/ignition.json
root_part=/dev/disk/by-label/root
boot_part=/dev/disk/by-label/boot
esp_part=/dev/disk/by-label/EFI-SYSTEM
bios_part=/dev/disk/by-partlabel/BIOS-BOOT
prep_part=/dev/disk/by-partlabel/PowerPC-PReP-boot
saved_data=/run/ignition-ostree-transposefs
saved_root=${saved_data}/root
saved_boot=${saved_data}/boot
saved_esp=${saved_data}/esp
saved_bios=${saved_data}/bios
saved_prep=${saved_data}/prep
zram_dev=${saved_data}/zram_dev
partstate_root=/run/ignition-ostree-rootfs-partstate.sh
# Print jq query string for wiped filesystems with label $1
query_fslabel() {
echo ".storage?.filesystems? // [] | map(select(.label == \"$1\" and .wipeFilesystem == true))"
}
# Print jq query string for partitions with type GUID $1
query_parttype() {
echo ".storage?.disks? // [] | map(.partitions?) | flatten | map(select(try .typeGuid catch \"\" | ascii_downcase == \"$1\"))"
}
# Print partition labels for partitions with type GUID $1
get_partlabels_for_parttype() {
jq -r "$(query_parttype $1) | .[].label" "${ignition_cfg}"
}
# Mounts device to directory, with extra logging of the src device
mount_verbose() {
local srcdev=$1; shift
local destdir=$1; shift
local mode=${1:-ro}
echo "Mounting ${srcdev} ${mode} ($(realpath "$srcdev")) to $destdir"
mkdir -p "${destdir}"
mount -o "${mode}" "${srcdev}" "${destdir}"
}
# Sometimes, for some reason the by-label symlinks aren't updated. Detect these
# cases, and explicitly `udevadm trigger`.
# See: https://bugzilla.redhat.com/show_bug.cgi?id=1908780
udev_trigger_on_label_mismatch() {
local label=$1; shift
local expected_dev=$1; shift
local actual_dev
expected_dev=$(realpath "${expected_dev}")
# We `|| :` here because sometimes /dev/disk/by-label/$label is missing.
# We've seen this on Fedora kernels with debug enabled (common in `rawhide`).
# See https://github.com/coreos/fedora-coreos-tracker/issues/1092
actual_dev=$(realpath "/dev/disk/by-label/$label" || :)
if [ "$actual_dev" != "$expected_dev" ]; then
echo "Expected /dev/disk/by-label/$label to point to $expected_dev, but points to $actual_dev; triggering udev"
udevadm trigger --settle "$expected_dev"
fi
}
# Print partition offset for device node $1
get_partition_offset() {
local devpath=$(udevadm info --query=path "$1")
cat "/sys${devpath}/start"
}
# copied from generator-lib.sh
karg() {
local name="$1" value="${2:-}"
local cmdline=( $(</proc/cmdline) )
for arg in "${cmdline[@]}"; do
if [[ "${arg%%=*}" == "${name}" ]]; then
value="${arg#*=}"
fi
done
echo "${value}"
}
mount_and_restore_filesystem_by_label() {
local label=$1; shift
local mountpoint=$1; shift
local saved_fs=$1; shift
local new_dev
new_dev=$(jq -r "$(query_fslabel "${label}") | .[0].device" "${ignition_cfg}")
udev_trigger_on_label_mismatch "${label}" "${new_dev}"
mount_verbose "/dev/disk/by-label/${label}" "${mountpoint}" rw
find "${saved_fs}" -mindepth 1 -maxdepth 1 -exec mv -t "${mountpoint}" {} +
}
mount_and_save_filesystem_by_label() {
local label=$1; shift
local saved_fs=$1; shift
local fs=/dev/disk/by-label/${label}
if [[ -f /run/coreos/secure-execution ]]; then
local roothash_karg=${label}fs.roothash
local roothash=$(karg "${roothash_karg}")
if [ -z "${roothash}" ]; then
echo "Missing kernel argument ${roothash_karg}; aborting"
exit 1
fi
local roothash_part=/dev/disk/by-partlabel/${label}hash
veritysetup open "${fs}" "${label}" "${roothash_part}" "${roothash}"
fs=/dev/mapper/${label}
fi
mount_verbose "${fs}" /var/tmp/mnt
cp -aT /var/tmp/mnt "${saved_fs}"
umount /var/tmp/mnt
if [[ -f /run/coreos/secure-execution ]]; then
veritysetup close "${label}"
fi
}
# In Secure Execution case user is not allowed to modify partition table
check_and_set_secex_config() {
if [[ -f /run/coreos/secure-execution ]]; then
local wr=$(jq "$(query_fslabel root) | length" "${ignition_cfg}")
local wb=$(jq "$(query_fslabel boot) | length" "${ignition_cfg}")
if [ "${wr}${wb}" != "00" ]; then
echo "Modifying bootfs and rootfs is not supported in Secure Execution mode"
exit 1
fi
# Cached config isn't merged, so reset it and recheck again, just to make sure
ignition_cfg=/usr/lib/ignition/base.d/01-secex.ign
fi
}
# We could have done this during 'detect' below, but other cases also request
# info from config, so just check cached one and reset to secex.ign now
check_and_set_secex_config
case "${1:-}" in
detect)
# Mounts are not in a private namespace so we can mount ${saved_data}
wipes_root=$(jq "$(query_fslabel root) | length" "${ignition_cfg}")
wipes_boot=$(jq "$(query_fslabel boot) | length" "${ignition_cfg}")
creates_esp=$(jq "$(query_parttype ${esp_typeguid}) | length" "${ignition_cfg}")
creates_bios=$(jq "$(query_parttype ${bios_typeguid}) | length" "${ignition_cfg}")
creates_prep=$(jq "$(query_parttype ${prep_typeguid}) | length" "${ignition_cfg}")
if [ "${wipes_root}${wipes_boot}${creates_esp}${creates_bios}${creates_prep}" = "00000" ]; then
exit 0
fi
echo "Detected partition replacement in fetched Ignition config: /run/ignition.json"
# verify all ESP, BIOS, and PReP partitions have non-null unique labels
unique_esp=$(jq -r "$(query_parttype ${esp_typeguid}) | [.[].label | values] | unique | length" "${ignition_cfg}")
unique_bios=$(jq -r "$(query_parttype ${bios_typeguid}) | [.[].label | values] | unique | length" "${ignition_cfg}")
unique_prep=$(jq -r "$(query_parttype ${prep_typeguid}) | [.[].label | values] | unique | length" "${ignition_cfg}")
if [ "${creates_esp}" != "${unique_esp}" -o "${creates_bios}" != "${unique_bios}" -o "${creates_prep}" != "${unique_prep}" ]; then
echo "Found duplicate or missing ESP, BIOS-BOOT, or PReP labels in config" >&2
exit 1
fi
mem_available=$(grep MemAvailable /proc/meminfo | awk '{print $2}')
# Just error out early if we don't even have 1G to work with. This
# commonly happens if you `cosa run` but forget to add `--memory`. That
# way you get a nicer error instead of the spew of EIO errors from `cp`.
# The amount we need is really dependent on a bunch of factors, but just
# ballpark it at 3G.
if [ "${mem_available}" -lt $((1*1024*1024)) ] && [ "${wipes_root}" != 0 ]; then
echo "Root reprovisioning requires at least 3G of RAM" >&2
exit 1
fi
modprobe zram num_devices=0
read dev < /sys/class/zram-control/hot_add
# disksize is set arbitrarily large, as zram is capped by mem_limit
echo 10G > /sys/block/zram"${dev}"/disksize
# Limit zram to 90% of available RAM: we want to be greedy since the
# boot breaks anyway, but we still want to leave room for everything
# else so it hits ENOSPC and doesn't invoke the OOM killer
echo $(( mem_available * 90 / 100 ))K > /sys/block/zram"${dev}"/mem_limit
mkfs.xfs -q /dev/zram"${dev}"
mkdir "${saved_data}"
mount /dev/zram"${dev}" "${saved_data}"
# save the zram device number created for when called to cleanup
echo "${dev}" > "${zram_dev}"
if [ "${wipes_root}" != "0" ]; then
mkdir "${saved_root}"
fi
if [ "${wipes_boot}" != "0" ]; then
mkdir "${saved_boot}"
fi
if [ "${creates_esp}" != "0" ]; then
mkdir "${saved_esp}"
fi
if [ "${creates_bios}" != "0" ]; then
mkdir "${saved_bios}"
fi
if [ "${creates_prep}" != "0" ]; then
mkdir "${saved_prep}"
fi
;;
save)
# Mounts happen in a private mount namespace since we're not "offically" mounting
if [ -d "${saved_root}" ]; then
echo "Moving rootfs to RAM..."
mount_and_save_filesystem_by_label root "${saved_root}"
# also store the state of the partition
lsblk "${root_part}" --nodeps --pairs -b --paths -o NAME,TYPE,SIZE > "${partstate_root}"
fi
if [ -d "${saved_boot}" ]; then
echo "Moving bootfs to RAM..."
mount_and_save_filesystem_by_label boot "${saved_boot}"
fi
if [ -d "${saved_esp}" ]; then
echo "Moving EFI System Partition to RAM..."
mount_verbose "${esp_part}" /sysroot/boot/efi
cp -aT /sysroot/boot/efi "${saved_esp}"
fi
if [ -d "${saved_bios}" ]; then
echo "Moving BIOS Boot partition and boot sector to RAM..."
# save partition
cat "${bios_part}" > "${saved_bios}/partition"
# save boot sector
bios_disk=$(lsblk --noheadings --output PKNAME --paths "${bios_part}")
dd if="${bios_disk}" of="${saved_bios}/boot-sector" bs="${boot_sector_size}" count=1 status=none
# store partition start offset so we can check it later
get_partition_offset "${bios_part}" > "${saved_bios}/start"
fi
if [ -d "${saved_prep}" ]; then
echo "Moving PReP partition to RAM..."
cat "${prep_part}" > "${saved_prep}/partition"
fi
echo "zram usage:"
read dev < "${zram_dev}"
cat /sys/block/zram"${dev}"/mm_stat
;;
restore)
# Mounts happen in a private mount namespace since we're not "offically" mounting
if [ -d "${saved_root}" ]; then
echo "Restoring rootfs from RAM..."
mount_and_restore_filesystem_by_label root /sysroot "${saved_root}"
chcon -v --reference "${saved_root}" /sysroot # the root of the fs itself
chattr +i $(ls -d /sysroot/ostree/deploy/*/deploy/*/)
fi
if [ -d "${saved_boot}" ]; then
echo "Restoring bootfs from RAM..."
mount_and_restore_filesystem_by_label boot /sysroot/boot "${saved_boot}"
chcon -v --reference "${saved_boot}" /sysroot/boot # the root of the fs itself
fi
if [ -d "${saved_esp}" ]; then
echo "Restoring EFI System Partition from RAM..."
get_partlabels_for_parttype "${esp_typeguid}" | while read label; do
# Don't use mount_and_restore_filesystem_by_label because:
# 1. We're mounting by partlabel, not FS label
# 2. We need to copy the contents to each partition, not move
# them once
# 3. We don't need the by-label symlink to be correct and
# nothing later in boot will be mounting the filesystem
mountpoint="/mnt/esp-${label}"
mount_verbose "/dev/disk/by-partlabel/${label}" "${mountpoint}" rw
find "${saved_esp}" -mindepth 1 -maxdepth 1 -exec cp -at "${mountpoint}" {} +
done
fi
if [ -d "${saved_bios}" ]; then
echo "Restoring BIOS Boot partition and boot sector from RAM..."
expected_start=$(cat "${saved_bios}/start")
get_partlabels_for_parttype "${bios_typeguid}" | while read label; do
cur_part="/dev/disk/by-partlabel/${label}"
# boot sector hardcodes the partition start; ensure it matches
cur_start=$(get_partition_offset "${cur_part}")
if [ "${cur_start}" != "${expected_start}" ]; then
echo "Partition ${cur_part} starts at ${cur_start}; expected ${expected_start}" >&2
exit 1
fi
# copy partition contents
cat "${saved_bios}/partition" > "${cur_part}"
# copy boot sector
cur_disk=$(lsblk --noheadings --output PKNAME --paths "${cur_part}")
cat "${saved_bios}/boot-sector" > "${cur_disk}"
done
fi
if [ -d "${saved_prep}" ]; then
echo "Restoring PReP partition from RAM..."
get_partlabels_for_parttype "${prep_typeguid}" | while read label; do
cat "${saved_prep}/partition" > "/dev/disk/by-partlabel/${label}"
done
fi
;;
cleanup)
# Mounts are not in a private namespace so we can unmount ${saved_data}
if [ -d "${saved_data}" ]; then
read dev < "${zram_dev}"
umount "${saved_data}"
rm -rf "${saved_data}" "${partstate_root}"
echo "${dev}" > /sys/class/zram-control/hot_remove
fi
;;
*)
echo "Unsupported operation: ${1:-}" 1>&2; exit 1
;;
esac

View File

@ -0,0 +1,24 @@
[Unit]
Description=Ignition OSTree: Regenerate Filesystem UUID (boot)
DefaultDependencies=false
ConditionPathExists=/usr/lib/initrd-release
ConditionKernelCommandLine=ostree
ConditionPathExists=!/run/ostree-live
# We run pretty early
Before=coreos-copy-firstboot-network.service
Before=coreos-ignition-setup-user.service
Before=ignition-fetch-offline.service
# Any services looking at mounts need to order after this
# because it causes device re-probing.
After=coreos-gpt-setup.service
# If we're going to reprovision the bootfs, then there's no need to restamp
ConditionKernelCommandLine=!bootfs.roothash
Before=systemd-fsck@dev-disk-by\x2dlabel-boot.service
Requires=dev-disk-by\x2dlabel-boot.device
After=dev-disk-by\x2dlabel-boot.device
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/sbin/ignition-ostree-firstboot-uuid boot

View File

@ -0,0 +1,26 @@
[Unit]
Description=Ignition OSTree: Regenerate Filesystem UUID (root)
# These conditions match ignition-ostree-mount-firstboot-sysroot.service
DefaultDependencies=false
ConditionKernelCommandLine=ostree
ConditionPathExists=!/run/ostree-live
Before=sysroot.mount initrd-root-fs.target
After=ignition-disks.service
# If we've reprovisioned the rootfs, then there's no need to restamp
ConditionPathExists=!/run/ignition-ostree-transposefs
ConditionKernelCommandLine=!rootfs.roothash
After=dev-disk-by\x2dlabel-root.device
# Avoid racing with fsck
Before=systemd-fsck@dev-disk-by\x2dlabel-root.service
Before=systemd-fsck@dev-disk-by\x2dlabel-dm-mpath-root.service
# Note we don't have a Requires: /dev/disk/by-label/root here like
# the -subsequent service does because ignition-disks may have
# regenerated it.
Before=ignition-ostree-mount-firstboot-sysroot.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/sbin/ignition-ostree-firstboot-uuid root

View File

@ -0,0 +1,115 @@
#!/bin/bash
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# ex: ts=8 sw=4 sts=4 et filetype=sh
depends() {
echo ignition rdcore
}
install_ignition_unit() {
local unit=$1; shift
local target=${1:-complete}
inst_simple "$moddir/$unit" "$systemdsystemunitdir/$unit"
# note we `|| exit 1` here so we error out if e.g. the units are missing
# see https://github.com/coreos/fedora-coreos-config/issues/799
systemctl -q --root="$initdir" add-requires "ignition-${target}.target" "$unit" || exit 1
}
installkernel() {
# Used by ignition-ostree-transposefs
instmods -c zram
}
install() {
inst_multiple \
realpath \
setfiles \
chcon \
systemd-sysusers \
systemd-tmpfiles \
sort \
uniq
if [[ $(uname -m) = s390x ]]; then
# for Secure Execution
inst_multiple \
veritysetup
fi
# ignition-ostree-growfs deps
inst_multiple \
basename \
blkid \
cat \
dirname \
findmnt \
growpart \
realpath \
resize2fs \
tail \
tune2fs \
touch \
xfs_admin \
xfs_growfs \
wc \
wipefs
# growpart deps
# Mostly generated from the following command:
# $ bash --rpm-requires /usr/bin/growpart | sort | uniq | grep executable
# with a few false positives (rq, rqe, -v) and one missed (mktemp)
inst_multiple \
awk \
cat \
dd \
grep \
mktemp \
partx \
rm \
sed \
sfdisk \
sgdisk \
find
for x in mount populate; do
install_ignition_unit ignition-ostree-${x}-var.service
inst_script "$moddir/ignition-ostree-${x}-var.sh" "/usr/sbin/ignition-ostree-${x}-var"
done
inst_simple \
/usr/lib/udev/rules.d/90-coreos-device-mapper.rules
inst_multiple jq chattr
inst_script "$moddir/ignition-ostree-transposefs.sh" "/usr/libexec/ignition-ostree-transposefs"
for x in detect save restore; do
install_ignition_unit ignition-ostree-transposefs-${x}.service
done
# Disk support
install_ignition_unit ignition-ostree-mount-firstboot-sysroot.service diskful
for p in boot root; do
install_ignition_unit ignition-ostree-uuid-${p}.service diskful
done
inst_script "$moddir/ignition-ostree-firstboot-uuid" \
"/usr/sbin/ignition-ostree-firstboot-uuid"
install_ignition_unit ignition-ostree-mount-subsequent-sysroot.service diskful-subsequent
inst_script "$moddir/ignition-ostree-mount-sysroot.sh" \
"/usr/sbin/ignition-ostree-mount-sysroot"
inst_script "$moddir/coreos-rootflags.sh" \
"/usr/sbin/coreos-rootflags"
install_ignition_unit ignition-ostree-growfs.service
inst_script "$moddir/ignition-ostree-growfs.sh" \
/usr/sbin/ignition-ostree-growfs
install_ignition_unit ignition-ostree-check-rootfs-size.service
inst_script "$moddir/coreos-check-rootfs-size" \
/usr/libexec/coreos-check-rootfs-size
inst_script "$moddir/coreos-relabel" /usr/bin/coreos-relabel
# Workaround for https://bugzilla.redhat.com/show_bug.cgi?id=2075085
install_ignition_unit ignition-ostree-secex-config.service
inst_script "$moddir/ignition-ostree-secex-config.sh" \
/usr/libexec/ignition-ostree-secex-config
}

View File

@ -0,0 +1,10 @@
[Unit]
Description=Check that initrd matches kernel
DefaultDependencies=false
Before=sysinit.target systemd-modules-load.service
ConditionPathIsDirectory=!/usr/lib/modules/%v
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/false

View File

@ -0,0 +1,15 @@
install_unit() {
unit="$1"; shift
target="$1"; shift
inst_simple "$moddir/$unit" "$systemdsystemunitdir/$unit"
# note we `|| exit 1` here so we error out if e.g. the units are missing
# see https://github.com/coreos/fedora-coreos-config/issues/799
systemctl -q --root="$initdir" add-requires "$target" "$unit" || exit 1
}
install() {
inst_multiple \
false
install_unit "coreos-check-kernel.service" "sysinit.target"
}

View File

@ -0,0 +1,13 @@
# Temporary hack to work around agetty SELinux denials.
# https://github.com/coreos/fedora-coreos-config/pull/859#issuecomment-783713383
# https://bugzilla.redhat.com/show_bug.cgi?id=1932053
[Unit]
Description=CoreOS: Touch /run/agetty.reload
Documentation=https://bugzilla.redhat.com/show_bug.cgi?id=1932053
DefaultDependencies=false
Before=initrd.target
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/touch /run/agetty.reload

View File

@ -0,0 +1,21 @@
#!/bin/bash
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# ex: ts=8 sw=4 sts=4 et filetype=sh
# Temporary workaround for https://bugzilla.redhat.com/show_bug.cgi?id=1932053.
install_unit() {
local unit=$1; shift
inst_simple "$moddir/$unit" "$systemdsystemunitdir/$unit"
# note we `|| exit 1` here so we error out if e.g. the units are missing
# see https://github.com/coreos/fedora-coreos-config/issues/799
systemctl -q --root="$initdir" add-requires initrd.target "$unit" || exit 1
}
install() {
inst_multiple \
touch
# TODO f35: check if we can drop this whole module
install_unit coreos-touch-run-agetty.service
}

View File

@ -0,0 +1,78 @@
# Display relevant errors then enter emergency shell
# _wait_for_journalctl_to_stop will block until either:
# - no messages have appeared in journalctl for the past 5 seconds
# - 15 seconds have elapsed
_wait_for_journalctl_to_stop() {
local time_since_last_log=0
local time_started="$(date '+%s')"
local now="$(date '+%s')"
while [ ${time_since_last_log} -lt 5 -a $((now-time_started)) -lt 15 ]; do
sleep 1
local last_log_timestamp="$(journalctl -e -n 1 -q -o short-unix | cut -d '.' -f 1)"
local now="$(date '+%s')"
local time_since_last_log=$((now-last_log_timestamp))
done
}
_display_relevant_errors() {
failed=$(systemctl --failed --no-legend --plain | cut -f 1 -d ' ')
if [ -n "${failed}" ]; then
# Something failed, suppress kernel logs so that it's more likely
# the useful bits from the journal are available.
dmesg --console-off
# There's a couple straggler systemd messages. Wait until it's been 5
# seconds since something was written to the journal.
_wait_for_journalctl_to_stop
# Print Ignition logs
if echo ${failed} | grep -qFe 'ignition-'; then
cat <<EOF
------
Ignition has failed. Please ensure your config is valid. Note that only
Ignition spec v3.0.0+ configs are accepted.
A CLI validation tool to check this called ignition-validate can be
downloaded from GitHub:
https://github.com/coreos/ignition/releases
------
EOF
fi
# If this is a live boot, check for ENOSPC in initramfs filesystem
# Try creating a 64 KiB file, in case a small file was deleted on
# service failure
# https://github.com/coreos/fedora-coreos-tracker/issues/1055
if [ -f /etc/coreos-live-initramfs ] && \
! dd if=/dev/zero of=/tmp/check-space bs=4K count=16 2>/dev/null; then
cat <<EOF
------
Ran out of memory when unpacking initrd filesystem. Ensure your system has
at least 2 GiB RAM if booting with coreos.live.rootfs_url, or 4 GiB otherwise.
------
EOF
# Don't show logs from failed units, since they'll just be
# random misleading errors.
else
echo "Displaying logs from failed units: ${failed}"
for unit in ${failed}; do
# 10 lines should be enough for everyone
SYSTEMD_COLORS=true journalctl -b --no-pager --no-hostname -u ${unit} -n 10
done
fi
fi
}
# Print warnings/informational messages to all configured consoles on the
# machine. Code inspired by https://github.com/dracutdevs/dracut/commit/32f68c1
MESSAGE="$(_display_relevant_errors)"
while read -r _tty rest; do
echo -e "$MESSAGE" > /dev/"$_tty"
done < /proc/consoles

View File

@ -0,0 +1,16 @@
[Unit]
Description=Dump journal to virtio port
ConditionPathExists=/etc/initrd-release
DefaultDependencies=false
ConditionVirtualization=|kvm
ConditionVirtualization=|qemu
Requires=systemd-journald.service
After=systemd-journald.service
After=basic.target
Before=initrd.target
[Service]
Type=oneshot
RemainAfterExit=yes
EnvironmentFile=/run/ignition.env
ExecStart=/usr/bin/ignition-virtio-dump-journal

View File

@ -0,0 +1,13 @@
#!/bin/bash
set -euo pipefail
port=/dev/virtio-ports/com.coreos.ignition.journal
if [ -e "${port}" ]; then
# Sync to backing filesystem before dumping what's there
journalctl --sync
journalctl -o json > "${port}"
# And this signals end of stream
echo '{}' > "${port}"
else
echo "Didn't find virtio port ${port}"
fi

View File

@ -0,0 +1,25 @@
#!/bin/bash
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# ex: ts=8 sw=4 sts=4 et filetype=sh
install_unit_wants() {
local unit="$1"; shift
local target="$1"; shift
local instantiated="${1:-$unit}"; shift
inst_simple "$moddir/$unit" "$systemdsystemunitdir/$unit"
# note we `|| exit 1` here so we error out if e.g. the units are missing
# see https://github.com/coreos/fedora-coreos-config/issues/799
systemctl -q --root="$initdir" add-wants "$target" "$instantiated" || exit 1
}
install() {
inst_multiple \
cut \
date \
dd
inst_hook emergency 99 "${moddir}/emergency-shell.sh"
inst_script "$moddir/ignition-virtio-dump-journal.sh" "/usr/bin/ignition-virtio-dump-journal"
install_unit_wants ignition-virtio-dump-journal.service emergency.target
}

View File

@ -0,0 +1,12 @@
[Journal]
# For now we are using kmsg for multiplexing output to
# multiple console devices during early boot.
#
# We do not want to use kmsg in the future as there may be sensitive
# ignition data that leaks to non-root users (by reading the kernel
# ring buffer using `dmesg`). In the future we will rely on kernel
# console multiplexing (link below) for this and will not use kmsg.
#
# https://github.com/coreos/fedora-coreos-tracker/issues/136
ForwardToKMsg=yes
MaxLevelKMsg=info

View File

@ -0,0 +1,12 @@
#!/bin/bash
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# ex: ts=8 sw=4 sts=4 et filetype=sh
depends() {
echo systemd
}
install() {
inst_simple "$moddir/00-journal-log-forwarding.conf" \
"/etc/systemd/journald.conf.d/00-journal-log-forwarding.conf"
}

View File

@ -0,0 +1,3 @@
# See also 10coreos-sysctl dracut module, which turns off ratelimiting in the
# initrd.
kernel.printk_devkmsg = ratelimit

View File

@ -0,0 +1,6 @@
# Hardcode persistent journal by default. journald has this "auto" behaviour
# that only makes logs persistent if `/var/log/journal` exists, which it won't
# on first boot because `/var` isn't fully populated. We should be able to get
# rid of this once we move to sysusers and create the dir in the initrd.
[Journal]
Storage=persistent

View File

@ -0,0 +1,115 @@
#!/bin/bash
export PATH="/usr/bin:/usr/sbin:${PATH}"
set -euo pipefail
. /usr/lib/coreos/generator-lib.sh
# Turn out if you boot with "root=..." $UNIT_DIR is not writable.
[ -w "${UNIT_DIR}" ] || {
echo "skipping coreos-boot-mount-generator: ${UNIT_DIR} is not writable"
exit 0
}
# If there's already an /etc/fstab entries for /boot, then this is is a non-FCOS
# system, likely RHCOS pre-4.3 (which still used Anaconda). In that case, we
# don't want to overwrite what the systemd-fstab-generator will do.
if findmnt --fstab /boot &>/dev/null; then
exit 0
fi
# Don't create mount units for /boot on live systems.
# ConditionPathExists won't work here because conditions don't affect
# the dependency on the underlying device unit.
if [ -f /run/ostree-live ]; then
exit 0
fi
add_wants() {
local name="$1"; shift
local wants_dir="${UNIT_DIR}/local-fs.target.wants"
mkdir -p "${wants_dir}"
ln -sf "../${name}" "${wants_dir}/${name}"
}
# Generate mount units that work with device mapper. The traditional
# device unit (dev-disk-by\x2dlabel...) does not work since it is not the
# device that systemd will fsck. This code ensures that if the label
# is backed by a device-mapper target the dev-mapper.*.device is used.
mk_mount() {
local mount_pt="${1}"; shift
local path="${1}"; shift
local options="${1}"; shift
local devservice=$(systemd-escape -p ${path} --suffix=service)
local unit_name=$(systemd-escape -p ${mount_pt} --suffix=mount)
cat > "${UNIT_DIR}/${unit_name}" <<EOF
# Automatically created by coreos-boot-mount-generator
[Unit]
Description=CoreOS Dynamic Mount for ${mount_pt}
Documentation=https://github.com/coreos/fedora-coreos-config
Before=local-fs.target
Requires=systemd-fsck@${devservice}
After=systemd-fsck@${devservice}
[Mount]
What=${path}
Where=${mount_pt}
Options=${options}
EOF
add_wants "${unit_name}"
}
# Copied from
# https://github.com/dracutdevs/dracut/blob/9491e599282d0d6bb12063eddbd192c0d2ce8acf/modules.d/99base/dracut-lib.sh#L586
# rather than sourcing it.
label_uuid_to_dev() {
local _dev
_dev="${1#block:}"
case "$_dev" in
LABEL=*)
echo "/dev/disk/by-label/$(echo "${_dev#LABEL=}" | sed 's,/,\\x2f,g;s, ,\\x20,g')"
;;
PARTLABEL=*)
echo "/dev/disk/by-partlabel/$(echo "${_dev#PARTLABEL=}" | sed 's,/,\\x2f,g;s, ,\\x20,g')"
;;
UUID=*)
echo "/dev/disk/by-uuid/$(echo "${_dev#UUID=}" | tr "[:upper:]" "[:lower:]")"
;;
PARTUUID=*)
echo "/dev/disk/by-partuuid/$(echo "${_dev#PARTUUID=}" | tr "[:upper:]" "[:lower:]")"
;;
esac
}
# If the root device is multipath, hook up /boot to use that too,
# based on our custom udev rules in 90-coreos-device-mapper.rules
# that creates "label found on mpath" links.
# Otherwise, use the usual by-label symlink.
# See discussion in https://github.com/coreos/fedora-coreos-config/pull/1022
bootdev=/dev/disk/by-label/boot
bootkarg=$(karg boot)
mpath=$(karg rd.multipath)
if [ -n "${mpath}" ] && [ "${mpath}" != 0 ]; then
bootdev=/dev/disk/by-label/dm-mpath-boot
# Newer nodes inject boot=UUID=..., but we support a larger subset of the dracut/fips API
elif [ -n "${bootkarg}" ]; then
# Adapted from https://github.com/dracutdevs/dracut/blob/9491e599282d0d6bb12063eddbd192c0d2ce8acf/modules.d/01fips/fips.sh#L17
case "$bootkarg" in
LABEL=* | UUID=* | PARTUUID=* | PARTLABEL=*)
bootdev="$(label_uuid_to_dev "$bootkarg")";;
/dev/*) bootdev=$bootkarg;;
*) echo "Unknown boot karg '${bootkarg}'; falling back to ${bootdev}";;
esac
# This is used for the first boot only
elif [ -f /run/coreos/bootfs_uuid ]; then
bootdev=/dev/disk/by-uuid/$(cat /run/coreos/bootfs_uuid)
fi
# We mount read-only by default mostly to protect
# against accidental damage. Only a few things
# owned by CoreOS should be touching /boot or the ESP.
# Use nodev,nosuid because some hardening guides want
# that even though it's of minimal value.
mk_mount /boot "${bootdev}" ro,nodev,nosuid

View File

@ -0,0 +1,105 @@
#!/bin/bash
set -euo pipefail
. /usr/lib/coreos/generator-lib.sh
write_dropin() {
local service="$1"; shift
local args="$1"; shift
local out_dir="${UNIT_DIR}/${service}.d"
mkdir -p "${out_dir}"
# /tmp isn't r/w yet, and the shell needs to cache the here-document
TMPDIR=/run
cat > "${out_dir}/10-autologin.conf" <<EOF
[Service]
ExecStart=
ExecStart=-/sbin/agetty --autologin core -o '-p -f core' ${args} %I \$TERM
EOF
}
quiet_kernel_console_messages() {
cat <<'EOF' > /etc/sysctl.d/20-coreos-autologin-kernel-printk.conf
# Raise console message logging level from DEBUG (7) to WARNING (4)
# so that kernel debug message don't get interspersed on the console
# that
# may frustrate a user trying to interactively do an install with
# nmtui and coreos-installer.
kernel.printk=4
EOF
}
write_interactive_live_motd() {
# Write motd to a tmp file and not directly to /etc/motd because
# SELinux denies write from init_t to etc_t
cat <<EOF > /run/interactive-live-motd
###########################################################################
Welcome to the CoreOS live environment. This system is running completely
from memory, making it a good candidate for hardware discovery and
installing persistently to disk. Here is an example of running an install
to disk via coreos-installer:
sudo coreos-installer install /dev/sda \\
--ignition-url https://example.com/example.ign
You may configure networking via 'sudo nmcli' or 'sudo nmtui' and have
that configuration persist into the installed system by passing the
'--copy-network' argument to 'coreos-installer install'. Please run
'coreos-installer install --help' for more information on the possible
install options.
###########################################################################
EOF
# Create coreos-cp-interactive-live-motd.service to copy over the motd in
# place. Note this intentionally overwrites the existing motd, which is
# blank on FCOS and populated on RHCOS.
service="coreos-cp-interactive-live-motd.service"
cat <<EOF > "${UNIT_DIR}/${service}"
# generated by coreos-liveiso-autologin-generator
[Unit]
Description=Copy CoreOS Interactive Live MOTD
Before=systemd-user-sessions.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/cp -v /run/interactive-live-motd /etc/motd
EOF
mkdir -p "${UNIT_DIR}/multi-user.target.wants"
ln -sf "../${service}" "${UNIT_DIR}/multi-user.target.wants/"
}
# Only allow automatic autologin on live systems
if [ ! -e /run/ostree-live ]; then
exit 0
fi
# Autologin on ISO boots but not PXE boots. The only way to tell the
# difference is a kernel argument.
if ! have_karg coreos.liveiso; then
exit 0
fi
# If the user supplied an Ignition config, they have the ability to enable
# autologin themselves. Don't automatically render them insecure, since
# they might be running in production and booting via e.g. IPMI.
if jq -e .userConfigProvided /etc/.ignition-result.json &>/dev/null; then
exit 0
fi
write_dropin "getty@.service" "--noclear"
# Also autologin on serial console if someone enables that
write_dropin "serial-getty@.service" "--keep-baud 115200,38400,9600"
# When the installer runs a lot of things happen on the system (audit
# messages from running via sudo, re-reading partition table messages,
# mounting filesystem messages, etc.). Quieting the verbosity of the
# kernel console will help us keep our sanity.
quiet_kernel_console_messages
# Write an motd that will let the user know about the live environment
# and what is possible.
write_interactive_live_motd

View File

@ -0,0 +1,16 @@
# This file contains overrides for systemd services that are
# enabled by default, but conflict with things we ship.
# We don't have swap by default, and systemd-oomd hard requires it.
disable systemd-oomd.service
# Disable systemd-firstboot because it conflicts with Ignition.
# In most cases this is handled via the remove-from-packages
# bits in the manifest (ignition-and-ostree.yaml), but
# we want to support overlaying builds of systemd from git.
disable systemd-firstboot.service
# This hasn't been tested with ostree/rpm-ostree and heavily overlaps
# with the latter. Preemptively disable the service; it will hopefully
# be subpackaged though for Fedora.
disable systemd-sysext.service

View File

@ -0,0 +1,34 @@
# Presets here that eventually should live in the generic fedora presets
# console-login-helper-messages - https://github.com/coreos/console-login-helper-messages
enable console-login-helper-messages-gensnippet-os-release.service
enable console-login-helper-messages-gensnippet-ssh-keys.service
# CA certs (probably to add to base fedora eventually)
enable coreos-update-ca-trust.service
# Set kernel console log level
enable coreos-printk-quiet.service
# https://github.com/coreos/ignition/issues/1125
enable coreos-ignition-firstboot-complete.service
# Delete Ignition config from provider on platforms where it's possible
# https://github.com/coreos/ignition/pull/1350
enable ignition-delete-config.service
# Delete Ignition config from provider when upgrading existing nodes
enable coreos-ignition-delete-config.service
# Boot checkin services for cloud providers.
enable afterburn-checkin.service
enable afterburn-firstboot-checkin.service
# Target to write SSH key snippets from cloud providers.
enable afterburn-sshkeys.target
# Update agent
enable zincati.service
# Testing aid
enable coreos-liveiso-success.service
# See bootupd.yaml
enable bootupd.socket
# Enable rtas_errd for ppc64le to discover dynamically attached pci devices - https://bugzilla.redhat.com/show_bug.cgi?id=1811537
# The event for the attached device comes as a diag event.
# Ideally it should have been added as part of base Fedora - but since it was arch specific, it was not added: https://bugzilla.redhat.com/show_bug.cgi?id=1433859
enable rtas_errd.service
enable clevis-luks-askpass.path
# Provide status information about the Ignition run
enable coreos-ignition-write-issues.service

View File

@ -0,0 +1,28 @@
# Can be removed from FCOS in Fedora 37 or after the next barrier release,
# whichever comes first. Can be removed from RHCOS in the first release
# after every node is guaranteed to have booted at least once with 4.11 or
# higher.
[Unit]
Description=CoreOS Delete Ignition Config From Hypervisor
Documentation=https://coreos.github.io/ignition/
ConditionKernelCommandLine=|ignition.platform.id=virtualbox
ConditionKernelCommandLine=|ignition.platform.id=vmware
ConditionPathExists=!/var/lib/coreos-ignition-delete-config.stamp
# Hack: if the user masked ignition-delete-config.service, we shouldn't run
# either.
ConditionPathIsSymbolicLink=!/etc/systemd/system/ignition-delete-config.service
# We check a stamp file written by ignition-delete-config.service. That
# service runs Before=sysinit.target, on which we have a default dependency,
# so this is really just documentation.
After=ignition-delete-config.service
[Service]
Type=oneshot
ExecStart=/usr/libexec/coreos-ignition-delete-config
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,21 @@
[Unit]
Description=CoreOS Mark Ignition Boot Complete
Documentation=https://docs.fedoraproject.org/en-US/fedora-coreos/
ConditionKernelCommandLine=ignition.firstboot
ConditionPathExists=!/run/ostree-live
RequiresMountsFor=/boot
[Service]
Type=oneshot
RemainAfterExit=yes
# The MountFlags=slave is so we remount /boot temporarily writable;
# see https://github.com/ostreedev/ostree/issues/1265 for the bigger picture.
# This option creates a new mount namespace; from the point of view of
# everything else, /boot stays readonly. We only have a transient writable mount
# for the lifetime of the unit.
MountFlags=slave
ExecStart=/usr/libexec/coreos-ignition-firstboot-complete
[Install]
# Part of basic.target so this happens early on in firstboot
WantedBy=basic.target

View File

@ -0,0 +1,16 @@
# This service writes issue files describing status
# information about the Ignition run, which includes
# Ignition warnings and information if no Ignition
# config is provided.
[Unit]
Description=Create Ignition Status Issue Files
Before=systemd-user-sessions.service
ConditionPathExists=/etc/.ignition-result.json
[Service]
Type=oneshot
ExecStart=/usr/libexec/coreos-ignition-write-issues
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,26 @@
# This is used by our test framework in coreos-assembler
# since for the "live ISO without Ignition" case we
# don't have an easy way to test it.
[Unit]
Description=CoreOS Live ISO virtio success
Documentation=https://github.com/coreos/fedora-coreos-config
# Only run on the Live ISO, and only if there's no Ignition config
ConditionKernelCommandLine=coreos.liveiso
ConditionPathExists=!/config.ign
ConditionVirtualization=|kvm
ConditionVirtualization=|qemu
# Start running late to help ensure that the below conditional works
After=systemd-user-sessions.service
ConditionPathExists=/dev/virtio-ports/coreos.liveiso-success
[Service]
Type=simple
# Wait for a user session to start, then write a static message to the
# virtio channel, which https://github.com/coreos/coreos-assembler/pull/1330
# knows how to read. We previously did "journalctl -f ... | head -1" here,
# but RHEL 8 has systemd 239, which has
# https://github.com/systemd/systemd/issues/9374.
ExecStart=/bin/sh -c 'while [ -z "$(loginctl list-sessions --no-legend)" ]; do sleep 1; done; echo coreos-liveiso-success > /dev/virtio-ports/coreos.liveiso-success'
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,27 @@
[Unit]
Description=CoreOS: Set printk To Level 4 (warn)
Documentation=https://github.com/coreos/fedora-coreos-tracker/issues/1244
# We can run right after `/proc` being mounted at least
DefaultDependencies=no
# We run as early as possible; the only dependency we have really
# is the implicit After=systemd-journald.socket injected by the
# default of our stdout writing to the journal.
Conflicts=shutdown.target
Before=sysinit.target shutdown.target
# We want this service to read what we wrote
Before=systemd-sysctl.service
# Relatedly, we don't want to override an explicitly specified kernel argument
ConditionKernelCommandLine=!debug
ConditionKernelCommandLine=!quiet
ConditionKernelCommandLine=!loglevel
[Service]
Type=oneshot
RemainAfterExit=yes
# We need to make /run/sysctl.d if it doesn't exist and also
# ensure it has a SELinux label that works for systemd-sysctl.service.
# Then we just generate a sysctl file which is read by systemd-sysctl.service.
ExecStart=/bin/bash -euo pipefail -c 'mkdir -p /run/sysctl.d && chcon --reference=/etc/sysctl.d /run/sysctl.d && echo "kernel.printk = 4" > /run/sysctl.d/01-coreos-printk.conf'
[Install]
WantedBy=sysinit.target

Some files were not shown because too many files have changed in this diff Show More