diff --git a/test/containerbuild.py b/test/containerbuild.py index 96b24fc3a..e51764a02 100644 --- a/test/containerbuild.py +++ b/test/containerbuild.py @@ -1,4 +1,5 @@ import os +import platform import subprocess import pytest @@ -22,7 +23,10 @@ def build_container_fixture(): def container_to_build_ref(): # TODO: make this another indirect fixture input, e.g. by making # making "image_type" an "image" tuple (type, container_ref_to_test) - return os.getenv( - "BIB_TEST_BOOTC_CONTAINER_TAG", - "quay.io/centos-bootc/fedora-bootc:eln", - ) + default_container_tag = "quay.io/centos-bootc/fedora-bootc:eln" + if platform.machine() == "arm64": + # TODO move to gen_testcases() once + # https://github.com/osbuild/bootc-image-builder/pull/148 + # landed. fedora:eln does not currently work on aarch64 + default_container_tag = "quay.io/centos-bootc/centos-bootc:stream9" + return os.getenv("BIB_TEST_BOOTC_CONTAINER_TAG", default_container_tag) diff --git a/test/test_build.py b/test/test_build.py index 1364fe279..451e3e62c 100644 --- a/test/test_build.py +++ b/test/test_build.py @@ -152,7 +152,6 @@ def test_image_is_generated(image_type): f"content: {os.listdir(os.fspath(image_type.img_path))}" -@pytest.mark.skipif(platform.system() != "Linux", reason="boot test only runs on linux right now") @pytest.mark.parametrize("image_type", DIRECT_BOOT_IMAGE_TYPES, indirect=["image_type"]) def test_image_boots(image_type): with QEMU(image_type.img_path) as test_vm: diff --git a/test/vm.py b/test/vm.py index ad6401881..3e58fe215 100644 --- a/test/vm.py +++ b/test/vm.py @@ -1,6 +1,8 @@ import abc +import glob import os import pathlib +import platform import subprocess import sys import time @@ -88,6 +90,11 @@ def find_ovmf(): ]: if os.path.exists(p): return p + # macos + p = "/opt/homebrew/Cellar/qemu/*/share/qemu/edk2-aarch64-code.fd" + m = glob.glob(p) + if len(m) == 1: + return m[0] raise ValueError("cannot find a OVMF bios") @@ -96,7 +103,7 @@ class QEMU(VM): # TODO: support qemu-system-aarch64 too :) QEMU = "qemu-system-x86_64" - def __init__(self, img, snapshot=True, cdrom=None): + def __init__(self, img, arch="", snapshot=True, cdrom=None): super().__init__() self._img = pathlib.Path(img) self._qmp_socket = self._img.with_suffix(".qemp-socket") @@ -104,19 +111,31 @@ def __init__(self, img, snapshot=True, cdrom=None): self._snapshot = snapshot self._cdrom = cdrom self._ssh_port = None + if arch in ("", "native"): + arch = platform.machine() + self._arch = arch def __del__(self): self.force_stop() - # XXX: move args to init() so that __enter__ can use them? - def start(self, wait_event="ssh", snapshot=True, use_ovmf=False): - if self.running(): - return - log_path = self._img.with_suffix(".serial-log") - self._ssh_port = get_free_port() - self._address = "localhost" - qemu_cmdline = [ - self.QEMU, "-enable-kvm", + def _gen_qemu_cmdline(self, snapshot, use_ovmf): + if self._arch in ("arm64", "aarch64"): + qemu_cmdline = [ + "qemu-system-aarch64", + "-M", "accel=hvf", + "-machine", "virt", + "-smp 2", + "-bios", find_ovmf(), + ] + elif self._arch in ("amd64", "x86_64"): + qemu_cmdline = [ + "qemu-system-x86_64", + "-M", "accel=kvm", + ] + else: + raise ValueError(f"unsupported architecture {self._arch}") + # common part + qemu_cmdline += [ "-m", self.MEM, # get "illegal instruction" inside the VM otherwise "-cpu", "host", @@ -135,7 +154,15 @@ def start(self, wait_event="ssh", snapshot=True, use_ovmf=False): if snapshot: qemu_cmdline.append("-snapshot") qemu_cmdline.append(self._img) - self._log(f"vm starting, log available at {log_path}") + return qemu_cmdline + + # XXX: move args to init() so that __enter__ can use them? + def start(self, wait_event="ssh", snapshot=True, use_ovmf=False): + if self.running(): + return + self._ssh_port = get_free_port() + self._address = "localhost" + qemu_cmdline = self._gen_qemu_cmdline(snapshot, use_ovmf) # XXX: use systemd-run to ensure cleanup? self._qemu_p = subprocess.Popen(