Skip to content

Commit 2f6ea26

Browse files
committed
test: add bootc-installer image type test
Add an integration test that uses the new `bootc-installer` image type to perform a full install and validate that booting into the resulting image works.
1 parent 7a360fa commit 2f6ea26

File tree

1 file changed

+122
-0
lines changed

1 file changed

+122
-0
lines changed

test/test_build_iso.py

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
import os
2+
import random
3+
import json
24
import platform
5+
import string
36
import subprocess
7+
import textwrap
48
from contextlib import ExitStack
59

610
import pytest
711
# local test utils
812
import testutil
913
from containerbuild import build_container_fixture # pylint: disable=unused-import
14+
from containerbuild import make_container
1015
from testcases import gen_testcases
1116
from vm import QEMU
1217

@@ -83,3 +88,120 @@ def test_iso_install_img_is_squashfs(tmp_path, image_type):
8388
# was an intermediate ext4 image "squashfs-root/LiveOS/rootfs.img"
8489
output = subprocess.check_output(["unsquashfs", "-ls", mount_point / "images/install.img"], text=True)
8590
assert "usr/bin/bootc" in output
91+
92+
93+
@pytest.mark.skipif(platform.system() != "Linux", reason="boot test only runs on linux right now")
94+
@pytest.mark.parametrize("container_ref", [
95+
"quay.io/centos-bootc/centos-bootc:stream10",
96+
"quay.io/fedora/fedora-bootc:42",
97+
"quay.io/centos-bootc/centos-bootc:stream9",
98+
])
99+
# pylint: disable=too-many-locals
100+
def test_bootc_installer_iso_installs(tmp_path, build_container, container_ref):
101+
# XXX: duplicated from test_build_disk.py
102+
username = "test"
103+
password = "".join(
104+
random.choices(string.ascii_uppercase + string.digits, k=18))
105+
ssh_keyfile_private_path = tmp_path / "ssh-keyfile"
106+
ssh_keyfile_public_path = ssh_keyfile_private_path.with_suffix(".pub")
107+
if not ssh_keyfile_private_path.exists():
108+
subprocess.run([
109+
"ssh-keygen",
110+
"-N", "",
111+
# be very conservative with keys for paramiko
112+
"-b", "2048",
113+
"-t", "rsa",
114+
"-f", os.fspath(ssh_keyfile_private_path),
115+
], check=True)
116+
ssh_pubkey = ssh_keyfile_public_path.read_text(encoding="utf8").strip()
117+
cfg = {
118+
"customizations": {
119+
"user": [
120+
{
121+
"name": "root",
122+
"key": ssh_pubkey,
123+
# note that we have no "home" here for ISOs
124+
}, {
125+
"name": username,
126+
"password": password,
127+
"groups": ["wheel"],
128+
},
129+
],
130+
"kernel": {
131+
# XXX: we need https://github.com/osbuild/images/pull/1786 or no kargs are added to anaconda
132+
# XXX2: drop a bunch of the debug flags
133+
#
134+
# Use console=ttyS0 so that we see output in our debug
135+
# logs. by default anaconda prints to the last console=
136+
# from the kernel commandline
137+
"append": "systemd.debug-shell=1 rd.systemd.debug-shell=1 inst.debug console=ttyS0",
138+
},
139+
},
140+
}
141+
config_json_path = tmp_path / "config.json"
142+
config_json_path.write_text(json.dumps(cfg), encoding="utf-8")
143+
# create anaconda iso from base
144+
cntf_path = tmp_path / "Containerfile"
145+
cntf_path.write_text(textwrap.dedent(f"""\n
146+
FROM {container_ref}
147+
RUN dnf install -y \
148+
anaconda-core \
149+
anaconda-dracut \
150+
anaconda-install-img-deps \
151+
biosdevname \
152+
grub2-efi-x64-cdboot \
153+
net-tools \
154+
prefixdevname \
155+
python3-mako \
156+
lorax-templates-* \
157+
squashfs-tools \
158+
&& dnf clean all
159+
# shim-x64 is marked installed but the files are not in the expected
160+
# place for https://github.com/osbuild/osbuild/blob/v160/stages/org.osbuild.grub2.iso#L91, see
161+
# workaround via reinstall, we could add a config to the grub2.iso
162+
# stage to allow a different prefix that then would be used by
163+
# anaconda.
164+
# once https://github.com/osbuild/osbuild/pull/2202 is merged we
165+
# can update images/ to set the correct efi_src_dir and this can
166+
# be removed
167+
# see also https://bugzilla.redhat.com/show_bug.cgi?id=1750708
168+
RUN dnf reinstall -y shim-x64
169+
# lorax wants to create a symlink in /mnt which points to /var/mnt
170+
# on bootc but /var/mnt does not exist on some images.
171+
#
172+
# If https://gitlab.com/fedora/bootc/base-images/-/merge_requests/294
173+
# gets merged this will be no longer needed
174+
RUN mkdir /var/mnt
175+
"""), encoding="utf8")
176+
output_path = tmp_path / "output"
177+
output_path.mkdir()
178+
with make_container(tmp_path) as container_tag:
179+
cmd = [
180+
*testutil.podman_run_common,
181+
"-v", f"{config_json_path}:/config.json:ro",
182+
"-v", f"{output_path}:/output",
183+
"-v", "/var/tmp/osbuild-test-store:/store", # share the cache between builds
184+
"-v", "/var/lib/containers/storage:/var/lib/containers/storage",
185+
build_container,
186+
"--type", "bootc-installer",
187+
"--rootfs", "ext4",
188+
"--installer-payload-ref", container_ref,
189+
f"localhost/{container_tag}",
190+
]
191+
subprocess.check_call(cmd)
192+
installer_iso_path = output_path / "bootiso" / "install.iso"
193+
test_disk_path = installer_iso_path.with_name("test-disk.img")
194+
with open(test_disk_path, "w", encoding="utf8") as fp:
195+
fp.truncate(10_1000_1000_1000)
196+
# install to test disk
197+
with QEMU(test_disk_path, cdrom=installer_iso_path) as vm:
198+
vm.start(wait_event="qmp:RESET", snapshot=False, use_ovmf=True)
199+
vm.force_stop()
200+
# boot test disk and do extremly simple check
201+
with QEMU(test_disk_path) as vm:
202+
vm.start(use_ovmf=True)
203+
exit_status, _ = vm.run("true", user=username, password=password)
204+
assert exit_status == 0
205+
exit_status, output = vm.run("bootc status", user="root", keyfile=ssh_keyfile_private_path)
206+
assert exit_status == 0
207+
assert f"Booted image: {container_ref}" in output

0 commit comments

Comments
 (0)