Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

overlay.d: move CoreOS specific dracut modules here #526

Merged
merged 2 commits into from Jul 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion manifest-lock.overrides.aarch64.yaml
Expand Up @@ -2,7 +2,7 @@ packages:
# Fast-track new Ignition release
# https://bodhi.fedoraproject.org/updates/FEDORA-2020-58ce0a6896
ignition:
evra: 2.4.1-1.git5260a5b.fc32.aarch64
evra: 2.5.0-1.git0d6f3e5.fc32.aarch64
# Fast-track coreos-installer release
# https://bodhi.fedoraproject.org/updates/FEDORA-2020-e078b3c893
coreos-installer:
Expand Down
2 changes: 1 addition & 1 deletion manifest-lock.overrides.ppc64le.yaml
Expand Up @@ -2,7 +2,7 @@ packages:
# Fast-track new Ignition release
# https://bodhi.fedoraproject.org/updates/FEDORA-2020-58ce0a6896
ignition:
evra: 2.4.1-1.git5260a5b.fc32.ppc64le
evra: 2.5.0-1.git0d6f3e5.fc32.ppc64le
# Fast-track coreos-installer release
# https://bodhi.fedoraproject.org/updates/FEDORA-2020-e078b3c893
coreos-installer:
Expand Down
2 changes: 1 addition & 1 deletion manifest-lock.overrides.s390x.yaml
Expand Up @@ -2,7 +2,7 @@ packages:
# Fast-track new Ignition release
# https://bodhi.fedoraproject.org/updates/FEDORA-2020-58ce0a6896
ignition:
evra: 2.4.1-1.git5260a5b.fc32.s390x
evra: 2.5.0-1.git0d6f3e5.fc32.s390x
# Fast-track coreos-installer release
# https://bodhi.fedoraproject.org/updates/FEDORA-2020-e078b3c893
coreos-installer:
Expand Down
2 changes: 1 addition & 1 deletion manifest-lock.overrides.x86_64.yaml
Expand Up @@ -2,7 +2,7 @@ packages:
# Fast-track new Ignition release
# https://bodhi.fedoraproject.org/updates/FEDORA-2020-58ce0a6896
ignition:
evra: 2.4.1-1.git5260a5b.fc32.x86_64
evra: 2.5.0-1.git0d6f3e5.fc32.x86_64
# Fast-track coreos-installer release
# https://bodhi.fedoraproject.org/updates/FEDORA-2020-e078b3c893
coreos-installer:
Expand Down
@@ -0,0 +1,57 @@
#!/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 ! command -v is-live-image >/dev/null || ! is-live-image; then
# ignition-setup-user.service should depend on the boot device node
# only on diskful boots
mkdir -p "${UNIT_DIR}/ignition-setup-user.service.d"
cat > "${UNIT_DIR}/ignition-setup-user.service.d/diskful-gpt.conf" <<EOF
[Unit]
Requires=coreos-gpt-setup.service
After=coreos-gpt-setup.service
EOF
fi
@@ -0,0 +1,33 @@
[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 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

# Run before services that use device nodes, preventing them from racing
# with udev activity generated by sgdisk
Before=ignition-setup-base.service 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
@@ -0,0 +1,25 @@
#!/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'

# 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

[ "$PTUUID" != "$UNINITIALIZED_GUID" ] && exit 0

sgdisk --disk-guid=R --move-second-header "$PKNAME"
udevadm settle
@@ -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
@@ -0,0 +1,187 @@
#!/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
}

selinux_relabel() {
# If we have access to coreos-relabel then let's use that because
# it allows us to set labels on things before switching root
# If not, fallback to tmpfiles.
if command -v coreos-relabel; then
coreos-relabel $1
else
echo "Z $1 - - -" >> "/run/tmpfiles.d/$(basename $0)-relabel.conf"
fi
}

# 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.
#
# See https://github.com/coreos/fedora-coreos-tracker/issues/394#issuecomment-599721173
propagate_initramfs_networking() {
# Check 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
if [ -n "$(ls -A /sysroot/etc/NetworkManager/system-connections/)" -o \
-n "$(ls -A /sysroot/etc/sysconfig/network-scripts/)" ]; then
echo "info: networking config is defined in the real root"
echo "info: will not attempt to propagate initramfs networking"
else
echo "info: no networking config is defined in the real root"
if [ -n "$(ls -A /run/NetworkManager/system-connections/)" ]; then
echo "info: propagating initramfs networking config to the real root"
cp /run/NetworkManager/system-connections/* /sysroot/etc/NetworkManager/system-connections/
selinux_relabel /etc/NetworkManager/system-connections/
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 is specified in static networking ip= kargs
# - AND no hostname was set via Ignition (realroot `/etc/hostname`)
# - THEN we make the last hostname specified in an ip= karg apply
# permanently by writing it into `/etc/hostname`
#
# This may no longer be needed when the following bug is fixed:
# https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/issues/419
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
# Detect if any hostname was provided via static ip= kargs
# run in a subshell so we don't pollute our environment
hostnamefile=$(mktemp)
(
last_nonempty_hostname=''
# Inspired from ifup.sh from the 40network dracut module. Note that
# $hostname from ip_to_var will only be nonempty for static networking.
for iparg in $(dracut_func getargs ip=); do
dracut_func ip_to_var $iparg
[ -n "${hostname:-}" ] && last_nonempty_hostname="$hostname"
done
echo -n "$last_nonempty_hostname" > $hostnamefile
)
hostname=$(<$hostnamefile); rm $hostnamefile
if [ -n "$hostname" ]; then
echo "info: propagating initramfs hostname (${hostname}) to the real root"
echo $hostname > /sysroot/etc/hostname
selinux_relabel /etc/hostname
else
echo "info: no initramfs hostname information to propagate"
fi
}

# Persist automatic multipath configuration, if any.
# When booting with `rd.multipath=default`, the default multipath
# configuration is written. We need to ensure that the mutlipath configuration
# is persisted to the final target.
propagate_initramfs_multipath() {
if [ ! -f /sysroot/etc/multipath.conf ] && [ -f /etc/multipath.conf ]; then
echo "info: propagating automatic multipath configuration"
cp -v /etc/multipath.conf /sysroot/etc/
mkdir -p /sysroot/etc/multipath/multipath.conf.d
selinux_relabel /etc/multipath.conf
selinux_relabel /etc/multipath/multipath.conf.d
else
echo "info: no initramfs automatic multipath configuration 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
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/

# If automated multipath configuration has been enabled, ensure
# that its propagated to the real rootfs.
propagate_initramfs_multipath
}

main