|
1 | 1 | import os |
| 2 | +import random |
| 3 | +import json |
2 | 4 | import platform |
| 5 | +import string |
3 | 6 | import subprocess |
| 7 | +import textwrap |
4 | 8 | from contextlib import ExitStack |
5 | 9 |
|
6 | 10 | import pytest |
7 | 11 | # local test utils |
8 | 12 | import testutil |
9 | 13 | from containerbuild import build_container_fixture # pylint: disable=unused-import |
| 14 | +from containerbuild import make_container |
10 | 15 | from testcases import gen_testcases |
11 | 16 | from vm import QEMU |
12 | 17 |
|
@@ -83,3 +88,120 @@ def test_iso_install_img_is_squashfs(tmp_path, image_type): |
83 | 88 | # was an intermediate ext4 image "squashfs-root/LiveOS/rootfs.img" |
84 | 89 | output = subprocess.check_output(["unsquashfs", "-ls", mount_point / "images/install.img"], text=True) |
85 | 90 | 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 | + # If https://github.com/osbuild/osbuild/pull/2204 would get merged we |
| 165 | + # can update images/ to set the correct efi_src_dirs and this can |
| 166 | + # be removed (but its rather ugly). |
| 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