Skip to content

Commit d47e064

Browse files
tmt: Add tests for composefs system-reinstall
Mostly generated by LLM with some tweaks by me Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
1 parent 4cb1e63 commit d47e064

3 files changed

Lines changed: 176 additions & 0 deletions

File tree

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: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
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 rm -f /usr/bin/bootctl
113+
RUN rm -rf /usr/lib/bootc/bound-images.d
114+
RUN touch /usr/share/testing-reinstall-mismatch
115+
"
116+
} else {
117+
print "Building image without grub/bootupd support"
118+
"
119+
FROM localhost/bootc as base
120+
RUN rm -rf /usr/lib/bootupd/updates /usr/bin/bootupctl
121+
RUN rm -rf /usr/lib/bootc/bound-images.d
122+
RUN touch /usr/share/testing-reinstall-mismatch
123+
"
124+
}
125+
126+
let td = mktemp -d
127+
cd $td
128+
$containerfile | save Dockerfile
129+
podman build -t localhost/bootc-reinstall-mismatch .
130+
131+
print "Running to-existing-root --composefs-backend (mismatched bootloader)"
132+
run_reinstall localhost/bootc-reinstall-mismatch
133+
134+
tmt-reboot
135+
}
136+
137+
def third_boot [] {
138+
print "Verifying reinstall with mismatched bootloader"
139+
140+
assert (tap is_composefs) "composefs should be active after mismatch reinstall"
141+
assert ("/usr/share/testing-reinstall-mismatch" | path exists) "mismatch marker should exist"
142+
143+
let orig_bootloader = (open /var/host-bootloader | str trim)
144+
let current_bootloader = ($st.status.booted.composefs.bootloader | str downcase)
145+
146+
print $"Original host bootloader: ($orig_bootloader), Installed: ($current_bootloader)"
147+
148+
if $orig_bootloader == "systemd" {
149+
assert equal $current_bootloader "grub" "should fall back to grub when image lacks systemd-boot"
150+
} else {
151+
assert equal $current_bootloader "systemd" "should fall back to systemd-boot when image lacks grub"
152+
}
153+
154+
tap ok
155+
}
156+
157+
def main [] {
158+
match $env.TMT_REBOOT_COUNT? {
159+
null | "0" => first_boot,
160+
"1" => second_boot,
161+
"2" => third_boot,
162+
$o => { error make { msg: $"Invalid TMT_REBOOT_COUNT ($o)" } },
163+
}
164+
}

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)