Skip to content
Open
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
1 change: 0 additions & 1 deletion .cci.jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ parallel build: {
}
stage("Unit tests") {
shwrap("""
dnf install -y grub2-tools-minimal
cargo test --features rpm
cargo test
""")
Expand Down
55 changes: 47 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,33 @@ env:
CARGO_TERM_COLOR: always

jobs:
c9s-bootc-e2e:
bootc-e2e:
strategy:
matrix:
runner:
- ubuntu-24.04
- ubuntu-24.04-arm
grubcc:
- 0
- 1

runs-on: [ "${{ matrix.runner }}" ]

steps:
- name: Setup env
run: |
IMG_NAME=localhost/bootupd-grubcc-${{ matrix.grubcc }}
echo "IMG_NAME=${IMG_NAME}" >> $GITHUB_ENV

if [[ "${{ matrix.grubcc }}" == "1" ]]; then
# we only have grub-cc in feodra (for now)
OS_ID="fedora"
else
OS_ID="centos"
fi

echo "OS_ID=${OS_ID}" >> $GITHUB_ENV

- name: Get a newer podman for heredoc support (from debian testing)
run: |
set -eux
Expand All @@ -51,22 +68,34 @@ jobs:
sudo apt update -y
sudo apt install -y podman

- name: build
run: sudo podman build -t localhost/bootupd:latest -f Dockerfile .
- name: build with grubcc=${{ matrix.grubcc }}
run: |
dockerfile=Dockerfile
build_args=()

if [[ "${{ matrix.grubcc }}" == "1" ]]; then
dockerfile=Dockerfile.bls
build_args=(--build-arg "grubcc=${{ matrix.grubcc }}")
fi

sudo podman build "${build_args[@]}" . -t "$IMG_NAME" -f "$dockerfile"

- name: bootupctl status in container
run: |
set -xeuo pipefail
sudo podman run --rm -v $PWD:/run/src -w /run/src --privileged localhost/bootupd:latest tests/tests/bootupctl-status-in-bootc.sh
sudo podman run --rm -v $PWD:/run/src -w /run/src --privileged "$IMG_NAME" tests/tests/bootupctl-status-in-bootc.sh

# Make sure grub stuff works with and without grubcc in the container image
# TODO: Test GrubCC installation with composefs after a bootc release includes
# https://github.com/bootc-dev/bootc/pull/2223
- name: bootc install to disk
run: |
set -xeuo pipefail
sudo truncate -s 10G myimage.raw
sudo podman run --rm --privileged -v .:/target --pid=host --security-opt label=disable \
-v /var/lib/containers:/var/lib/containers \
-v /dev:/dev \
localhost/bootupd:latest bootc install to-disk --skip-fetch-check \
"$IMG_NAME" bootc install to-disk --filesystem ext4 --skip-fetch-check \
--disable-selinux --generic-image --via-loopback /target/myimage.raw
# Verify we installed grub.cfg and shim on the disk
sudo losetup -P -f myimage.raw
Expand All @@ -80,7 +109,7 @@ jobs:
# Assume aarch64 for now
shim="shimaa64.efi"
fi
sudo ls /mnt/EFI/centos/{grub.cfg,${shim}}
sudo ls /mnt/EFI/$OS_ID/{grub.cfg,${shim}}
sudo umount /mnt
# check /boot/grub2/grub.cfg permission
root_part=$(sudo sfdisk -l -J "${device}" | jq -r '.partitiontable.partitions[] | select(.name == "root").node')
Expand All @@ -99,7 +128,7 @@ jobs:
set -xeuo pipefail
sudo podman run --rm -ti --privileged -v /:/target --pid=host --security-opt label=disable \
-v /dev:/dev -v /var/lib/containers:/var/lib/containers \
localhost/bootupd:latest env BOOTC_BOOTLOADER_DEBUG=1 \
"$IMG_NAME" env BOOTC_BOOTLOADER_DEBUG=1 \
bootc install to-filesystem --skip-fetch-check \
--acknowledge-destructive \
--disable-selinux --replace=alongside /target
Expand All @@ -113,4 +142,14 @@ jobs:
- name: bootupctl generate-update-metadata
run: |
set -xeuo pipefail
sudo podman run --rm -v $PWD:/run/src -w /run/src --privileged localhost/bootupd:latest tests/tests/generate-update-metadata.sh
sudo podman run --rm -v $PWD:/run/src -w /run/src --privileged "$IMG_NAME" tests/tests/generate-update-metadata.sh

- name: Test GrubCC and SystemdBoot
run: |
if [[ "${{ matrix.grubcc }}" == "0" ]]; then
exit 0
fi

set -xeuo pipefail
sudo ./scripts/test-bootloader.sh "$IMG_NAME" "grub-cc"
sudo ./scripts/test-bootloader.sh "$IMG_NAME" "systemd-boot"
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ path = "src/main.rs"
anyhow = "1.0"
bootc-internal-blockdev = "1.16.0"
bootc-internal-utils = "1.16.0"
bootc-internal-mount = "1.16.0"
cap-std-ext = "5.0.0"
camino = "1.2.2"
chrono = { version = "0.4.44", features = ["serde"] }
Expand Down
125 changes: 125 additions & 0 deletions Dockerfile.bls
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# Dockerfile to test GrubCC and systemd-boot
# Build from the current git into a fedora44 container image.

ARG base=quay.io/fedora/fedora-bootc:44

FROM $base as build
# This installs our package dependencies, and we want to cache it independently of the rest.
# Basically we don't want changing a .rs file to blow out the cache of packages.
RUN <<EORUN
set -xeuo pipefail
dnf -y install cargo git openssl-devel
EORUN
# Now copy the source
COPY . /build
WORKDIR /build
# See https://www.reddit.com/r/rust/comments/126xeyx/exploring_the_problem_of_faster_cargo_docker/
# We aren't using the full recommendations there, just the simple bits.
RUN --mount=type=cache,target=/build/target --mount=type=cache,target=/var/roothome \
make && make install-all DESTDIR=/out


# Get the latest GrubCC binary
FROM quay.io/fedora/eln:latest AS grub-cc-download
RUN --mount=type=tmpfs,target=/run --mount=type=tmpfs,target=/tmp <<EOF
set -eux

# There isn't a generic grub2-efi-cc package that DNF can automatically resolve
case "$(uname -m)" in
x86_64)
dnf download grub2-efi-x64-cc
;;
aarch64)
dnf download grub2-efi-aa64-cc
;;
*)
echo "Unsupported architecture: $(uname -m)" >&2
exit 1
;;
esac

mv ./*.rpm grub-cc.rpm

EOF

FROM $base
# Clean out the default to ensure we're using our updated content
RUN rpm -e bootupd
COPY --from=build /out/ /
COPY --from=grub-cc-download /grub-cc.rpm /var/grub-cc.rpm
# Install bootc from copr
RUN --mount=type=tmpfs,target=/run --mount=type=tmpfs,target=/tmp <<EORUN
set -xeuo pipefail
dnf -y install dnf-plugins-core bootc systemd-boot tree
dnf clean all
rm -rf /var/log
rm -rf /var/lib
rm -rf /var/cache
rm -rf /run/rhsm
rm -rf /tmp/*
EORUN

# Install systemd-boot
RUN --mount=type=tmpfs,target=/run --mount=type=tmpfs,target=/tmp <<EOF
set -eux
# epoch for systemd-boot-unsigned is "(none)"
evr=$(rpm -q --qf '%{EPOCH}:%{VERSION}-%{RELEASE}\n' systemd-boot-unsigned)
rpm -ql systemd-boot-unsigned

. /etc/os-release

# Create the expected directory structure at /usr/lib/efi/grub-cc/<evr>/EFI/fedora/
mkdir -p "/usr/lib/efi/systemd-boot/${evr}/EFI/$ID"

if [[ $(uname -m) == x86_64 ]]; then
grubName="grubx64.efi"
else
grubName="grubaa64.efi"
fi

cp /usr/lib/systemd/boot/efi/systemd-boot*.efi "/usr/lib/efi/systemd-boot/${evr}/EFI/$ID/$grubName"

EOF

# Install grub-cc
RUN --mount=type=tmpfs,target=/run --mount=type=tmpfs,target=/tmp <<EOF

set -eux

cleanup() {
# Clean up temporary files
rm -rvf /var/grub-cc*
}

# Extract and install grub-cc at the correct path
mkdir /var/grub-cc
rpm2archive /var/grub-cc.rpm | tar -xvz -C /var/grub-cc
file=$(find /var/grub-cc -name '*.efi')

# Get the EVR from the RPM filename
evr=$(rpm -qp --qf '%{EPOCH}:%{VERSION}-%{RELEASE}' /var/grub-cc.rpm)

. /etc/os-release

if [[ $(uname -m) == x86_64 ]]; then
grubName="grubx64.efi"
else
grubName="grubaa64.efi"
fi

# Create the expected directory structure at /usr/lib/efi/grub-cc/<evr>/EFI/fedora/
mkdir -p "/usr/lib/efi/grub-cc/${evr}/EFI/$ID/"
cp "$file" "/usr/lib/efi/grub-cc/${evr}/EFI/$ID/$grubName"

cleanup

# Regenerate metadata
bootupctl backend generate-update-metadata -vvv

# Set grub as default
bootupctl backend set-default-bootloader grub

EOF

# Sanity check this too
RUN bootc container lint --fatal-warnings
11 changes: 11 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
fn main() {
println!("cargo::rustc-check-cfg=cfg(efi_arch)");

if cfg!(any(
target_arch = "x86_64",
target_arch = "aarch64",
target_arch = "riscv64"
)) {
println!("cargo:rustc-cfg=efi_arch");
}
}
76 changes: 76 additions & 0 deletions scripts/test-bootloader.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#!/bin/bash

set -eux

IMG_NAME=$1
BOOTLOADER=$2

cat <<-EOF > sfdisk-buf
label: gpt
label-id: 65be9332-59ba-11f1-9b26-6a8e2ab625e4
size=1Gib, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B, name="EFI-SYSTEM"
type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, name="root"
EOF

truncate -s4G "${BOOTLOADER}-test.img"

cat sfdisk-buf | sfdisk --wipe=always "${BOOTLOADER}-test.img"

mkdir -p /var/mnt

# Also update kernel partition tables
loopdev=$(losetup --find --show --partscan "${BOOTLOADER}-test.img")
sleep 1

mkfs.vfat "${loopdev}p1"
mkfs.ext4 "${loopdev}p2"

mount "${loopdev}p2" /var/mnt

ESP="/var/mnt/efi"

mkdir -p $ESP
mount "${loopdev}p1" $ESP


# Test installing the bootloader
podman run --rm --net=host --privileged --pid=host \
--privileged \
--security-opt label=type:unconfined_t \
--env RUST_LOG=trace \
-v /dev:/dev \
-v /var/mnt:/var/mnt \
"$IMG_NAME" \
bootupctl backend install --bootloader "$BOOTLOADER" /var/mnt -vvvv

# Make sure bootupd-state.json is in the esp
test -f "$ESP/bootupd-state.json"

cat "$ESP/bootupd-state.json" | jq

version=$(cat "$ESP/bootupd-state.json" | jq -r ".installed.EFI.meta.version")

if [[ $version != *shim* ]]; then echo "shim not found in version"; exit 1; fi
if [[ $version != *"$BOOTLOADER"* ]]; then echo "$BOOTLOADER not found in version"; exit 1; fi

# Test if the correct binary has been installed
actualShasum=$(podman run --rm "$IMG_NAME" find "/usr/lib/efi/$BOOTLOADER" -type f -exec sha512sum {} + | awk '{print $1}')
actualShasum="sha512:$actualShasum"

if [[ $(uname -m) == "x86_64" ]]; then
grubName="grubx64.efi"
else
grubName="grubaa64.efi"
fi

# TODO: Remove hardcoded "fedora" once we have support in centos
storedShasum=$(cat "$ESP/bootupd-state.json" | jq -r --arg grub "$grubName" '.installed.EFI.filetree.children["fedora/\($grub)"].sha512')

test "$actualShasum" == "$storedShasum"

efiBinShasum=$(find "$ESP" -type f -name "$grubName" -exec sha512sum {} + | awk '{print $1}')
efiBinShasum="sha512:$efiBinShasum"

test "$efiBinShasum" == "$actualShasum"

umount -Rl /var/mnt
Loading