summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBruce Ashfield <bruce.ashfield@gmail.com>2026-02-19 22:39:14 +0000
committerBruce Ashfield <bruce.ashfield@gmail.com>2026-02-26 01:05:01 +0000
commit6d94266a86246ac23abdbc28ac3b5c6e522fb748 (patch)
treef3c14a73c232c1393d491b7f5d1cec318e12e285
parent5c891aab54f1432f2afe75bf0dee0027fbb2e4bd (diff)
downloadmeta-virtualization-6d94266a86246ac23abdbc28ac3b5c6e522fb748.tar.gz
xen: add configuration tests and update documentation
Add TestXenImageMinimalX86Config test class verifying: - QB_CPU_KVM host passthrough for Xen CPUID filtering - QB_MEM_VALUE override (not QB_MEM which can't override bbclass) - dom0_mem in both QB_XEN_CMDLINE_EXTRA and WKS syslinux config - vgabios SAVANNAH_GNU_MIRROR usage Update Alpine recipe tests for per-arch checksums (name=${ALPINE_ARCH}) and S variable. Add qemux86-64 build and boot section to README-xen.md. Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
-rw-r--r--recipes-extended/images/README-xen.md35
-rw-r--r--tests/test_xen_guest_bundle.py129
2 files changed, 156 insertions, 8 deletions
diff --git a/recipes-extended/images/README-xen.md b/recipes-extended/images/README-xen.md
index f16aa743..e5b4ca4a 100644
--- a/recipes-extended/images/README-xen.md
+++ b/recipes-extended/images/README-xen.md
@@ -165,6 +165,8 @@ Guests can be launched after boot with: xl create -c /etc/xen/<guest>.cfg
165Build and boot 165Build and boot
166-------------- 166--------------
167 167
168### qemuarm64
169
168Using a reference qemuarm64 MACHINE, the following are the commands 170Using a reference qemuarm64 MACHINE, the following are the commands
169to build and boot a guest. 171to build and boot a guest.
170 172
@@ -205,3 +207,36 @@ Name ID Mem VCPUs State Time(s)
205Domain-0 0 192 4 r----- 696.2 207Domain-0 0 192 4 r----- 696.2
206xen-guest-image-minimal 1 512 1 -b---- 153.0 208xen-guest-image-minimal 1 512 1 -b---- 153.0
207root@qemuarm64:~# xl destroy xen-guest-image-minimal 209root@qemuarm64:~# xl destroy xen-guest-image-minimal
210
211### qemux86-64
212
213The xen-image-minimal recipe includes x86-64 specific configuration:
214
215 - QB_CPU_KVM uses -cpu host to avoid AVX stripping by Xen's CPUID
216 filtering (required for x86-64-v3 tune)
217 - QB_MEM_VALUE = "1024" for 1GB Dom0 memory
218 - dom0_mem=512M reserves memory for DomU guests
219
220 % MACHINE=qemux86-64 bitbake xen-guest-image-minimal
221 % MACHINE=qemux86-64 bitbake xen-image-minimal
222
223 % runqemu qemux86-64 nographic slirp kvm
224
225qemux86-64 login: root
226
227root@qemux86-64:~# xl list
228Name ID Mem VCPUs State Time(s)
229Domain-0 0 512 4 r----- 12.3
230alpine 1 256 1 -b---- 0.8
231xen-guest-image-minimal 2 256 1 -b---- 3.1
232
233vxn standalone test:
234
235root@qemux86-64:~# vxn run --rm alpine echo hello
236hello
237
238containerd test:
239
240root@qemux86-64:~# ctr image pull docker.io/library/alpine:latest
241root@qemux86-64:~# vctr run --rm docker.io/library/alpine:latest test1 echo hello
242hello
diff --git a/tests/test_xen_guest_bundle.py b/tests/test_xen_guest_bundle.py
index 2035a5f9..dd56dcc9 100644
--- a/tests/test_xen_guest_bundle.py
+++ b/tests/test_xen_guest_bundle.py
@@ -281,14 +281,32 @@ class TestAlpineRecipe:
281 assert "alpine-minirootfs" in alpine_recipe_content 281 assert "alpine-minirootfs" in alpine_recipe_content
282 assert "subdir=alpine-rootfs" in alpine_recipe_content 282 assert "subdir=alpine-rootfs" in alpine_recipe_content
283 283
284 def test_sha256sum(self, alpine_recipe_content): 284 def test_per_arch_checksums(self, alpine_recipe_content):
285 """Test sha256sum is set (not placeholder).""" 285 """Test per-architecture sha256sums are set."""
286 match = re.search(r'SRC_URI\[sha256sum\]\s*=\s*"([^"]*)"', 286 aarch64_match = re.search(
287 alpine_recipe_content) 287 r'SRC_URI\[aarch64\.sha256sum\]\s*=\s*"([^"]*)"',
288 assert match, "sha256sum not found" 288 alpine_recipe_content)
289 sha = match.group(1) 289 x86_64_match = re.search(
290 assert len(sha) == 64, f"sha256sum wrong length: {len(sha)}" 290 r'SRC_URI\[x86_64\.sha256sum\]\s*=\s*"([^"]*)"',
291 assert sha != "x" * 64, "sha256sum is still placeholder" 291 alpine_recipe_content)
292 assert aarch64_match, "aarch64 sha256sum not found"
293 assert x86_64_match, "x86_64 sha256sum not found"
294 for name, match in [("aarch64", aarch64_match), ("x86_64", x86_64_match)]:
295 sha = match.group(1)
296 assert len(sha) == 64, f"{name} sha256sum wrong length: {len(sha)}"
297 assert sha != "x" * 64, f"{name} sha256sum is still placeholder"
298 # Checksums must differ (different arch tarballs)
299 assert aarch64_match.group(1) != x86_64_match.group(1), \
300 "aarch64 and x86_64 checksums should differ"
301
302 def test_src_uri_per_arch_name(self, alpine_recipe_content):
303 """Test SRC_URI uses name= for per-arch checksum matching."""
304 assert "name=${ALPINE_ARCH}" in alpine_recipe_content, \
305 "SRC_URI should use name=${ALPINE_ARCH} for per-arch checksums"
306
307 def test_s_variable(self, alpine_recipe_content):
308 """Test S variable is set to avoid UNPACKDIR warning."""
309 assert 'S = "${UNPACKDIR}"' in alpine_recipe_content
292 310
293 def test_guest_bundles(self, alpine_recipe_content): 311 def test_guest_bundles(self, alpine_recipe_content):
294 """Test XEN_GUEST_BUNDLES is set.""" 312 """Test XEN_GUEST_BUNDLES is set."""
@@ -359,3 +377,98 @@ class TestReadme:
359 """Test custom handler instructions.""" 377 """Test custom handler instructions."""
360 assert "xen_guest_import_" in readme_content 378 assert "xen_guest_import_" in readme_content
361 assert "XEN_GUEST_IMPORT_DEPENDS_" in readme_content 379 assert "XEN_GUEST_IMPORT_DEPENDS_" in readme_content
380
381
382# ============================================================================
383# x86-64 configuration tests
384# ============================================================================
385
386class TestXenImageMinimalX86Config:
387 """Test xen-image-minimal.bb x86-64 configuration.
388
389 These verify the fixes needed for Xen on qemux86-64:
390 - CPU passthrough to avoid AVX stripping by Xen CPUID filtering
391 - Memory configuration using QB_MEM_VALUE (not QB_MEM)
392 - dom0_mem in QB_XEN_CMDLINE_EXTRA for runqemu
393 - dom0_mem in static WKS syslinux config for guest autostart
394 - vgabios using reliable download mirror
395 """
396
397 @pytest.fixture(scope="class")
398 def image_recipe_content(self, meta_virt_dir):
399 path = meta_virt_dir / "recipes-extended" / "images" / "xen-image-minimal.bb"
400 if not path.exists():
401 pytest.skip("xen-image-minimal.bb not found")
402 return path.read_text()
403
404 @pytest.fixture(scope="class")
405 def wks_cfg_content(self, meta_virt_dir):
406 path = meta_virt_dir / "wic" / "qemuboot-xen-x86-64.cfg"
407 if not path.exists():
408 pytest.skip("qemuboot-xen-x86-64.cfg not found")
409 return path.read_text()
410
411 @pytest.fixture(scope="class")
412 def vgabios_recipe_content(self, meta_virt_dir):
413 recipes = list((meta_virt_dir / "recipes-extended" / "vgabios").glob(
414 "vgabios_*.bb"))
415 if not recipes:
416 pytest.skip("vgabios recipe not found")
417 return recipes[0].read_text()
418
419 def test_cpu_kvm_host_passthrough(self, image_recipe_content):
420 """Test QB_CPU_KVM uses -cpu host for qemux86-64.
421
422 Xen's CPUID filtering strips AVX/AVX2 when using fixed CPU models
423 (e.g. Skylake-Client), causing illegal instruction crashes with
424 x86-64-v3 tune. -cpu host passes real features through KVM.
425 """
426 assert 'QB_CPU_KVM:qemux86-64 = "-cpu host' in image_recipe_content
427
428 def test_qb_mem_value_not_qb_mem(self, image_recipe_content):
429 """Test memory uses QB_MEM_VALUE, not QB_MEM.
430
431 qemuboot-xen-defaults.bbclass uses a hard assign:
432 QB_MEM = "-m ${QB_MEM_VALUE}"
433 A recipe-level QB_MEM ?= cannot override it. QB_MEM_VALUE ??=
434 in the class is the intended override point.
435 """
436 assert 'QB_MEM_VALUE' in image_recipe_content
437 # Should NOT have QB_MEM ?= (common mistake)
438 assert 'QB_MEM ?=' not in image_recipe_content
439
440 def test_dom0_mem_in_xen_cmdline(self, image_recipe_content):
441 """Test dom0_mem is in QB_XEN_CMDLINE_EXTRA for runqemu."""
442 match = re.search(
443 r'QB_XEN_CMDLINE_EXTRA\s*=\s*"([^"]*)"', image_recipe_content)
444 assert match, "QB_XEN_CMDLINE_EXTRA not found"
445 assert "dom0_mem=" in match.group(1), \
446 "dom0_mem= must be in QB_XEN_CMDLINE_EXTRA"
447
448 def test_dom0_mem_in_wks_syslinux(self, wks_cfg_content):
449 """Test dom0_mem is in static WKS syslinux config.
450
451 Without dom0_mem in the syslinux config, Xen gives ALL memory
452 to Dom0 and guest autostart fails with 'failed to free memory'.
453 QB_XEN_CMDLINE_EXTRA only affects runqemu's dynamic command line.
454 """
455 assert "dom0_mem=" in wks_cfg_content, \
456 "dom0_mem= must be in qemuboot-xen-x86-64.cfg for guest autostart"
457
458 def test_wks_xen_kernel_cmdline(self, wks_cfg_content):
459 """Test WKS config has correct Xen and kernel boot params."""
460 assert "mboot.c32" in wks_cfg_content
461 assert "/xen.gz" in wks_cfg_content
462 assert "console=hvc0" in wks_cfg_content
463
464 def test_vgabios_savannah_mirror(self, vgabios_recipe_content):
465 """Test vgabios uses ${SAVANNAH_GNU_MIRROR} for reliable downloads.
466
467 The old http://savannah.gnu.org/download/ URL can redirect to
468 broken mirrors that return HTML instead of the tarball.
469 """
470 assert "${SAVANNAH_GNU_MIRROR}" in vgabios_recipe_content, \
471 "vgabios should use ${SAVANNAH_GNU_MIRROR} variable"
472 # Should NOT use raw savannah.gnu.org URL
473 assert "http://savannah.gnu.org/download" not in vgabios_recipe_content, \
474 "Should not use raw savannah.gnu.org URL (broken redirects)"