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

Initial support for live PXE and ISO images #155

Merged
merged 7 commits into from
Sep 16, 2019
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions live/EFI/fedora/grub.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Note this file mostly matches the grub.cfg file from within the
# efiboot.img on the Fedora Server DVD iso. Diff this file with that
# file in the future to pick up changes.
#
# One diff to note is we use linux and initrd instead of linuxefi and
# initrdefi. We do this because it works and allows us to use this same
# file on other architecutres. https://github.com/coreos/fedora-coreos-config/issues/63
#
# This file gets embedded into the efiboot.img on our Fedora CoreOS ISO.
set default="1"

function load_video {
insmod efi_gop
insmod efi_uga
insmod video_bochs
insmod video_cirrus
insmod all_video
}

load_video
set gfxpayload=keep
insmod gzio
insmod part_gpt
insmod ext2

set timeout=1
### END /etc/grub.d/00_header ###

### BEGIN /etc/grub.d/10_linux ###
menuentry 'Fedora CoreOS (Live)' --class fedora --class gnu-linux --class gnu --class os {
linux /images/vmlinuz mitigations=auto,nosmt rd.neednet=1 ip=dhcp ignition.firstboot ignition.platform.id=metal
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm. It feels cleaner if we pulled this stuff out of an existing disk image. But OK for now.

initrd /images/initramfs.img
}
13 changes: 13 additions & 0 deletions live/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
These files will be copied to the target live ISO
via the CoreOS Assembler buildextend-live call. It
picks up all files in the coreos/fedora-coreos-config/live/
directory and copies them to the base of the ISO.

Files currently copied are:

- isolinux/boot.msg
- isolinux/isolinux.cfg

Files that get copied into efiboot.img in the ISO:

- EFI/grub.cfg
5 changes: 5 additions & 0 deletions live/isolinux/boot.msg
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@

splash.lss

- Press the 01<ENTER>07 key to boot.

73 changes: 73 additions & 0 deletions live/isolinux/isolinux.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Note this file mostly matches the isolinux.cfg file from the Fedora
# Server DVD iso. Diff this file with that file in the future to pick up
# changes.
serial 0
default vesamenu.c32
timeout 10

display boot.msg

# Clear the screen when exiting the menu, instead of leaving the menu displayed.
# For vesamenu, this means the graphical background is still displayed without
# the menu itself for as long as the screen remains in graphics mode.
menu clear
menu background splash.png
menu title Fedora CoreOS
menu vshift 8
menu rows 18
menu margin 8
#menu hidden
menu helpmsgrow 15
menu tabmsgrow 13

# Border Area
menu color border * #00000000 #00000000 none

# Selected item
menu color sel 0 #ffffffff #00000000 none

# Title bar
menu color title 0 #ff7ba3d0 #00000000 none

# Press [Tab] message
menu color tabmsg 0 #ff3a6496 #00000000 none

# Unselected menu item
menu color unsel 0 #84b8ffff #00000000 none

# Selected hotkey
menu color hotsel 0 #84b8ffff #00000000 none

# Unselected hotkey
menu color hotkey 0 #ffffffff #00000000 none

# Help text
menu color help 0 #ffffffff #00000000 none

# A scrollbar of some type? Not sure.
menu color scrollbar 0 #ffffffff #ff355594 none

# Timeout msg
menu color timeout 0 #ffffffff #00000000 none
menu color timeout_msg 0 #ffffffff #00000000 none

# Command prompt text
menu color cmdmark 0 #84b8ffff #00000000 none
menu color cmdline 0 #ffffffff #00000000 none

# Do not display the actual menu unless the user presses a key. All that is displayed is a timeout message.

menu tabmsg Press Tab for full configuration options on menu items.

menu separator # insert an empty line
menu separator # insert an empty line

label linux
menu label ^Fedora CoreOS (Live)
menu default
kernel /images/vmlinuz
append initrd=/images/initramfs.img mitigations=auto,nosmt rd.neednet=1 ip=dhcp ignition.firstboot ignition.platform.id=metal

menu separator # insert an empty line

menu end
1 change: 1 addition & 0 deletions live/zipl.prm
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
mitigations=auto,nosmt rd.neednet=1 ip=dhcp ignition.firstboot ignition.platform.id=metal
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

regarding the mitigations=auto,nosmt (the last commit in this series) it seems like this is going to be a bit of a maintenance burden because we store that information currently in image.yaml can we pull those args from there?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean just the extra-kargs? We can, but there are also args coming from other places (ignition.platform.id, console, the temporary networking args, rootflags, etc). We could read them out of the BLS config and filter out the undesired ones, but I thought that might be more trouble than it's worth. Thoughts?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could read them out of the BLS config and filter out the undesired ones, but I thought that might be more trouble than it's worth. Thoughts?

I like that, depending on how much trouble it really is. Basically we'd maintain a blacklist in a single place vs duplicated kernel args in various places.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK. Can I queue that for a followup PR?

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[Unit]
DefaultDependencies=false
RequiresMountsFor=/writable
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we preserve /run from the initramfs? If so, let's put stuff in /run/coreos-live-writable or so?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do. I thought it'd be cleaner to have a dedicated tmpfs for user-created state. Also, this avoids exposing the overlayfs upperdir and workdir within the directory structure.

Before=sysroot-etc.mount sysroot-var.mount

[Service]
Type=oneshot
bgilbert marked this conversation as resolved.
Show resolved Hide resolved
RemainAfterExit=yes
ExecStart=/usr/bin/mkdir -m 755 -p /writable/etc/upper /writable/var
ExecStart=/usr/bin/mkdir -m 700 -p /writable/etc/work
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/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 may not have been created yet.
[ -e /root.squashfs ]
101 changes: 101 additions & 0 deletions overlay.d/05core/usr/lib/dracut/modules.d/20live/live-generator
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
#!/bin/bash
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# ex: ts=8 sw=4 sts=4 et filetype=sh

set -e

UNIT_DIR="${1:-/tmp}"

add_requires() {
local name="$1"
local requires_dir="${UNIT_DIR}/initrd-root-fs.target.requires"
mkdir -p "${requires_dir}"
ln -sf "../${name}" "${requires_dir}/${name}"
}

if [ -e /root.squashfs ]; then
# Create stamp file that everything else should use to detect a live boot
> /run/ostree-live

add_requires sysroot.mount
add_requires sysroot-etc.mount
add_requires sysroot-var.mount

mkdir -p "${UNIT_DIR}/ostree-prepare-root.service.d"
cat > "${UNIT_DIR}/ostree-prepare-root.service.d/10-live.conf" <<EOF
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm OK with this, though I'd also like to consider standardizing support for this in ostree itself at some point.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that'd be good. This is meant as a starting point.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's definitely hacky to bind mount over /proc/cmdline but is a creative way to get this working now. Can you open an RFE against ostree to support this natively and copy the URL to the issue in this dropin unit as well as a comment in the ostree-cmdline.sh script?

# 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

cat >"${UNIT_DIR}/sysroot.mount" <<EOF
# Automatically generated by live-generator

[Unit]
DefaultDependencies=false
Before=initrd-root-fs.target

[Mount]
What=/root.squashfs
Where=/sysroot
Type=squashfs
EOF

cat >"${UNIT_DIR}/sysroot-etc.mount" <<EOF
# Automatically generated by live-generator
[Unit]
DefaultDependencies=false

# Make sure /sysroot is mounted first, since we're mounting under there
Requires=initrd-root-fs.target
After=initrd-root-fs.target

# Make sure our upperdir is available
RequiresMountsFor=/writable

# Need to do this before Ignition mounts any other filesystems (potentially
# shadowing our own mount).
Before=ignition-mount.service

[Mount]
What=overlay
Where=/sysroot/etc
Type=overlay
Options=lowerdir=/sysroot/etc,upperdir=/writable/etc/upper,workdir=/writable/etc/work,redirect_dir=on,index=on,xino=on
EOF

cat >"${UNIT_DIR}/sysroot-var.mount" <<EOF
# Automatically generated by live-generator
[Unit]
DefaultDependencies=false

# Make sure /sysroot is mounted first, since we're mounting under there
Requires=initrd-root-fs.target
After=initrd-root-fs.target

# Make sure our tmpfs is available
RequiresMountsFor=/writable

# Need to do this before Ignition mounts any other filesystems (potentially
# shadowing our own bind mount).
Before=ignition-mount.service

[Mount]
What=/writable/var
Where=/sysroot/var
Type=none
Options=bind
EOF
fi
16 changes: 16 additions & 0 deletions overlay.d/05core/usr/lib/dracut/modules.d/20live/module-setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
install() {
inst_script "$moddir/is-live-image.sh" \
"/usr/bin/is-live-image"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this is just the initramfs but I am not a fan of "/usr/bin pollution". /usr/libexec/coreos-is-live-image ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an API with ignition-dracut, which is distro-independent, so it shouldn't be coreos-. We could use /usr/libexec but nothing else in the initrd does (except coreos-installer), and /usr/bin pollution is rampant in the initrd, so I'm inclined to leave it.


inst_script "$moddir/ostree-cmdline.sh" \
"/usr/sbin/ostree-cmdline"

inst_simple "$moddir/live-generator" \
"$systemdutildir/system-generators/live-generator"

inst_simple "$moddir/coreos-populate-writable.service" \
"$systemdsystemunitdir/coreos-populate-writable.service"

inst_simple "$moddir/writable.mount" \
"$systemdsystemunitdir/writable.mount"
}
25 changes: 25 additions & 0 deletions overlay.d/05core/usr/lib/dracut/modules.d/20live/ostree-cmdline.sh
Original file line number Diff line number Diff line change
@@ -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
10 changes: 10 additions & 0 deletions overlay.d/05core/usr/lib/dracut/modules.d/20live/writable.mount
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[Unit]
DefaultDependencies=false
Requires=coreos-populate-writable.service
Before=coreos-populate-writable.service

[Mount]
What=tmpfs
Where=/writable
Type=tmpfs
Options=mode=0700
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[Unit]
Description=Mount OSTree /var
DefaultDependencies=false
ConditionPathExists=!/run/ostree-live

# Make sure ExecStop= runs before we switch root
Before=initrd-switch-root.target
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#!/bin/bash

set -euo pipefail

UNIT_DIR="${1:-/tmp}"

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}"
}

# Don't create mount units for /boot or /boot/efi 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
bgilbert marked this conversation as resolved.
Show resolved Hide resolved
add_wants boot.mount
cat > "${UNIT_DIR}/boot.mount" <<EOF
# Automatically created by coreos-boot-mount-generator
[Unit]
Description=Boot partition
Documentation=https://github.com/coreos/fedora-coreos-config
Before=local-fs.target

[Mount]
What=/dev/disk/by-label/boot
Where=/boot
EOF

# Only mount the EFI System Partition on machines where it exists,
# which are 1) machines actually booted through EFI, and 2) x86_64
# when booted through BIOS.
if [ "$(uname -m)" = "x86_64" -o -d /sys/firmware/efi ]; then
add_wants boot-efi.mount
cat > "${UNIT_DIR}/boot-efi.mount" <<EOF
# Automatically created by coreos-boot-mount-generator
[Unit]
Description=EFI System Partition
Documentation=https://github.com/coreos/fedora-coreos-config
Before=local-fs.target

[Mount]
What=/dev/disk/by-label/EFI-SYSTEM
Where=/boot/efi
EOF
fi
fi
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,5 @@ enable afterburn-checkin.service
enable afterburn-firstboot-checkin.service
# Service to write SSH key snippets from cloud providers.
enable afterburn-sshkeys@.service
# mount /boot/efi
enable boot-efi.mount
# Update agent
enable zincati.service
11 changes: 0 additions & 11 deletions overlay.d/05core/usr/lib/systemd/system/boot-efi.mount

This file was deleted.

7 changes: 0 additions & 7 deletions overlay.d/05core/usr/lib/systemd/system/boot.mount

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# See also coreos-growpart script.

[Unit]
ConditionPathExists=!/run/ostree-live
ConditionPathExists=!/var/lib/coreos-growpart.stamp
Before=sshd.service

Expand Down