Skip to content

Commit 96b2934

Browse files
tmt: Add tests for composefs system-reinstall
Mostly generated by LLM with some tweaks by me Do not remove /usr/lib/bootupd/updates even when going down the systemd-boot installation path as we require the metadata for testing system reinstall Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
1 parent eade909 commit 96b2934

4 files changed

Lines changed: 179 additions & 1 deletion

File tree

contrib/packaging/switch-to-sdboot

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ shift
1111
# Uninstall bootupd if present (we're switching to sd-boot managed differently)
1212
if rpm -q bootupd &>/dev/null; then
1313
rpm -e bootupd
14-
rm -vrf /usr/lib/bootupd/updates
1514
fi
1615

1716
# First install the unsigned systemd-boot RPM to get the package in place

tmt/plans/integration.fmf

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,4 +292,11 @@ execute:
292292
how: fmf
293293
test:
294294
- /tmt/tests/tests/test-46-etc-merge-conflict
295+
296+
/plan-47-system-reinstall-composefs:
297+
summary: Test system-reinstall with composefs backend and bootloader compatibility
298+
discover:
299+
how: fmf
300+
test:
301+
- /tmt/tests/tests/test-47-system-reinstall-composefs
295302
# END GENERATED PLANS
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
# number: 47
2+
# tmt:
3+
# summary: Test system-reinstall with composefs backend and bootloader compatibility
4+
# duration: 60m
5+
#
6+
# Tests that system-reinstall-bootc works with composefs backend by running
7+
# `bootc install to-existing-root --composefs-backend` on the live root,
8+
# matching the invocation pattern of system-reinstall-bootc.
9+
#
10+
# Three scenarios across three reboot cycles:
11+
#
12+
# Reboot 0:
13+
# Same bootloader: image supports the host's bootloader
14+
# → that bootloader should be installed
15+
#
16+
# Reboot 1:
17+
# Verify same-bootloader result, then:
18+
# Bootloader mismatch: image lacks support for the host's bootloader
19+
# → fallback bootloader should be installed
20+
# (skipped for UKI boot type where switching bootloaders is unsafe)
21+
#
22+
# Reboot 2:
23+
# Verify mismatch fallback result
24+
#
25+
use std assert
26+
use tap.nu
27+
28+
if not (tap is_composefs) {
29+
exit 0
30+
}
31+
32+
let st = bootc status --json | from json
33+
34+
# Run bootc install to-existing-root --composefs-backend via podman,
35+
# matching the system-reinstall-bootc invocation from podman.rs.
36+
# Key details tested by these flags:
37+
# /:/target:rslave — propagates boot automount (commit 3bf1acba)
38+
# --composefs-backend — exercises composefs repo init fix (commit fa18de18)
39+
# efivars read — bootloader detection (commits fa18de18, 4cb1e63b)
40+
def run_reinstall [image: string] {
41+
(podman run
42+
--rm
43+
--privileged
44+
--pid=host
45+
--user=root:root
46+
-v /var/lib/containers:/var/lib/containers
47+
-v /dev:/dev
48+
--security-opt label=type:unconfined_t
49+
-v /:/target:rslave
50+
$image
51+
bootc install to-existing-root
52+
--acknowledge-destructive
53+
--skip-fetch-check
54+
--composefs-backend
55+
--disable-selinux)
56+
}
57+
58+
def first_boot [] {
59+
tap begin "system-reinstall composefs + bootloader compatibility"
60+
61+
let bootloader = ($st.status.booted.composefs.bootloader | str downcase)
62+
let boot_type = ($st.status.booted.composefs.bootType | str downcase)
63+
64+
# Persist host state for verification across reboots
65+
$bootloader | save /var/host-bootloader
66+
$boot_type | save /var/host-boot-type
67+
68+
print $"Host bootloader: ($bootloader), boot type: ($boot_type)"
69+
70+
bootc image copy-to-storage
71+
72+
# Build derived image preserving the same bootloader support as the host.
73+
# make_uki_containerfile appends UKI sealing stages when running on UKI.
74+
let containerfile = (tap make_uki_containerfile "
75+
FROM localhost/bootc as base
76+
RUN rm -rf /usr/lib/bootc/bound-images.d
77+
RUN touch /usr/share/testing-reinstall-same-bl
78+
")
79+
80+
let td = mktemp -d
81+
cd $td
82+
$containerfile | save Dockerfile
83+
podman build -t localhost/bootc-reinstall-same .
84+
85+
print "Running to-existing-root --composefs-backend (same bootloader)"
86+
run_reinstall localhost/bootc-reinstall-same
87+
88+
tmt-reboot
89+
}
90+
91+
def second_boot [] {
92+
print "Verifying reinstall with same bootloader"
93+
94+
assert (tap is_composefs) "composefs should be active after reinstall"
95+
assert ("/usr/share/testing-reinstall-same-bl" | path exists) "same-bootloader marker should exist"
96+
97+
let orig_bootloader = (open /var/host-bootloader | str trim)
98+
let current_bootloader = ($st.status.booted.composefs.bootloader | str downcase)
99+
100+
print $"Original bootloader: ($orig_bootloader), Current: ($current_bootloader)"
101+
assert equal $current_bootloader $orig_bootloader "bootloader should match host after same-bootloader reinstall"
102+
103+
# Build image that lacks the host's bootloader, forcing a fallback:
104+
# host=systemd-boot -> remove bootctl -> falls back to grub
105+
# host=grub/grub-cc -> remove bootupd -> falls back to systemd-boot
106+
bootc image copy-to-storage
107+
108+
let containerfile = if $orig_bootloader == "systemd" {
109+
print "Building image without systemd-boot support (removing bootctl)"
110+
"
111+
FROM localhost/bootc as base
112+
RUN rpm -e systemd-boot-unsigned
113+
RUN rm -f /usr/bin/bootctl
114+
RUN rm -rf /usr/lib/bootc/bound-images.d
115+
RUN dnf install -y bootupd
116+
RUN touch /usr/share/testing-reinstall-mismatch
117+
"
118+
} else {
119+
print "Building image without grub/bootupd support"
120+
"
121+
FROM localhost/bootc as base
122+
RUN rpm -e bootupd
123+
RUN rm -rf /usr/lib/bootc/bound-images.d
124+
RUN dnf install -y systemd-boot-unsigned
125+
RUN touch /usr/share/testing-reinstall-mismatch
126+
"
127+
}
128+
129+
let td = mktemp -d
130+
cd $td
131+
$containerfile | save Dockerfile
132+
podman build -t localhost/bootc-reinstall-mismatch .
133+
134+
print "Running to-existing-root --composefs-backend (mismatched bootloader)"
135+
run_reinstall localhost/bootc-reinstall-mismatch
136+
137+
tmt-reboot
138+
}
139+
140+
def third_boot [] {
141+
print "Verifying reinstall with mismatched bootloader"
142+
143+
assert (tap is_composefs) "composefs should be active after mismatch reinstall"
144+
assert ("/usr/share/testing-reinstall-mismatch" | path exists) "mismatch marker should exist"
145+
146+
let orig_bootloader = (open /var/host-bootloader | str trim)
147+
let current_bootloader = ($st.status.booted.composefs.bootloader | str downcase)
148+
149+
print $"Original host bootloader: ($orig_bootloader), Installed: ($current_bootloader)"
150+
151+
if $orig_bootloader == "systemd" {
152+
assert equal $current_bootloader "grub" "should fall back to grub when image lacks systemd-boot"
153+
} else {
154+
assert equal $current_bootloader "systemd" "should fall back to systemd-boot when image lacks grub"
155+
}
156+
157+
tap ok
158+
}
159+
160+
def main [] {
161+
match $env.TMT_REBOOT_COUNT? {
162+
null | "0" => first_boot,
163+
"1" => second_boot,
164+
"2" => third_boot,
165+
$o => { error make { msg: $"Invalid TMT_REBOOT_COUNT ($o)" } },
166+
}
167+
}

tmt/tests/tests.fmf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,3 +183,8 @@ check:
183183
summary: Verify etc merge conflicts are caught during upgrade, not finalization
184184
duration: 15m
185185
test: nu booted/test-etc-merge-conflict.nu
186+
187+
/test-47-system-reinstall-composefs:
188+
summary: Test system-reinstall with composefs backend and bootloader compatibility
189+
duration: 60m
190+
test: nu booted/test-system-reinstall-composefs.nu

0 commit comments

Comments
 (0)