From 5244759e27b64dfae21652c8354fee373c754276 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 15 Jan 2024 18:47:43 +0100 Subject: [PATCH] test: add boot test on arm64 as well This commit enables arm64 boot tests for the generated image. --- test/test_smoke.py | 1 - test/vm.py | 58 +++++++++++++++++++++++++++++++++++----------- 2 files changed, 45 insertions(+), 14 deletions(-) diff --git a/test/test_smoke.py b/test/test_smoke.py index 51d21a628..16f228923 100644 --- a/test/test_smoke.py +++ b/test/test_smoke.py @@ -169,7 +169,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", SUPPORTED_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 d22a39027..3e2d4649e 100644 --- a/test/vm.py +++ b/test/vm.py @@ -1,5 +1,7 @@ import abc +import glob import pathlib +import platform import subprocess import sys import uuid @@ -85,32 +87,62 @@ class QEMU(VM): # TODO: support qemu-system-aarch64 too :) QEMU = "qemu-system-x86_64" - def __init__(self, img, snapshot=True): + def __init__(self, img, arch="", snapshot=True): super().__init__() self._img = pathlib.Path(img) + if arch in ("", "native"): + arch = platform.machine() + self._arch = arch self._qemu_p = None self._snapshot = snapshot - def start(self): - 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", - "-m", self.MEM, - # get "illegal instruction" inside the VM otherwise + def _find_ovmf_bios(self): + match self._arch: + case "arm64", "aarch64": + p = "/opt/homebrew/Cellar/qemu/*/share/qemu/edk2-aarch64-code.fd" + m = glob.glob(p) + if len(m) != 1: + raise ValueError("cannot find edk2 bios in {p}: {m}") + return m[0] + case _: + raise ValueError("ovmf bios only supported on arm64 right now") + + def _gen_qemu_cmdline(self): + qemu_cmdline_common = [ "-cpu", "host", "-nographic", "-serial", "stdio", "-monitor", "none", "-netdev", f"user,id=net.0,hostfwd=tcp::{self._ssh_port}-:22", "-device", "rtl8139,netdev=net.0", + "-m", self.MEM, ] if self._snapshot: - qemu_cmdline.append("-snapshot") - qemu_cmdline.append(self._img) + qemu_cmdline_common.append("-snapshot") + qemu_cmdline_common.append(self._img) + match self._arch: + case "arm64", "aarch64": + return [ + "qemu-system-aarch64", + "-M", "accel=hvf", + "-machine", "virt", + "-bios", self._find_ovmf_bios(), + ] + case "amd64", "x86_64": + return [ + "qemu-system-x86_64", + "-M", "accel=kvm", + ] + qemu_cmdline_common + case _: + raise ValueError(f"unsupported architecture {self._arch}") + + def start(self): + if self.running(): + return + log_path = self._img.with_suffix(".serial-log") + self._ssh_port = get_free_port() + self._address = "localhost" + qemu_cmdline = self._gen_qemu_cmdline() self._log(f"vm starting, log available at {log_path}") # XXX: use systemd-run to ensure cleanup?