* [PATCH v4 1/4] runqemu: Add support for running compressed .zst rootfs images
@ 2025-07-31 10:23 Yoann Congal
2025-07-31 10:23 ` [PATCH v4 2/4] selftest: runqemu: add tests for booting zst compressed image Yoann Congal
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Yoann Congal @ 2025-07-31 10:23 UTC (permalink / raw)
To: openembedded-core; +Cc: Yoann Congal, Lamine REHAHLIA
From: Lamine REHAHLIA <lamine.rehahlia@smile.fr>
Enhance runqemu to detect and decompress .zst-compressed rootfs images
(e.g. ext4.zst, wic.zst) automatically. If a decompressed image already
exists in the original directory, it will be reused to avoid overwriting
build artifacts. Otherwise, the image is decompressed and removed after
the QEMU session ends.
This allows runqemu to be used seamlessly with compressed image formats
generated by the build system or during releases.
Note: support for .zst images is only available when snapshot mode is
enabled
IMPORTANT:
This patch assumes that the original directory of the .zst-compressed
image is writable. If, for some reason, the path passed from CI or
another system to the script is read-only, the decompression step will
fail when trying to write the uncompressed image to the same directory.
Signed-off-by: Lamine REHAHLIA <lamine.rehahlia@smile.fr>
Signed-off-by: Yoann Congal <yoann.congal@smile.fr>
---
v4: moved the feature to support calling "runqemu <image recipe name>"
and support usign snapshot after the image.
Also improved the error message when a compressed image is used without
snapshot mode.
---
scripts/runqemu | 45 ++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 44 insertions(+), 1 deletion(-)
diff --git a/scripts/runqemu b/scripts/runqemu
index 3d77046972..c668906bdd 100755
--- a/scripts/runqemu
+++ b/scripts/runqemu
@@ -197,7 +197,7 @@ class BaseConfig(object):
self.portlocks = {}
self.bitbake_e = ''
self.snapshot = False
- self.wictypes = ('wic', 'wic.vmdk', 'wic.qcow2', 'wic.vdi', "wic.vhd", "wic.vhdx")
+ self.wictypes = ('wic.zst', 'wic', 'wic.vmdk', 'wic.qcow2', 'wic.vdi', "wic.vhd", "wic.vhdx")
self.fstypes = ('ext2', 'ext3', 'ext4', 'jffs2', 'nfs', 'btrfs',
'cpio.gz', 'cpio', 'ramfs', 'tar.bz2', 'tar.gz',
'squashfs', 'squashfs-xz', 'squashfs-lzo',
@@ -418,6 +418,48 @@ class BaseConfig(object):
else:
raise RunQemuError("Unknown path arg %s" % p)
+ def uncompress_rootfs(self):
+ """Decompress ZST rootfs image if needed"""
+ if not self.rootfs or not self.fstype.endswith('.zst'):
+ return
+
+ # Ensure snapshot mode is active before allowing decompression.
+ if not self.snapshot:
+ raise RunQemuError(".zst images are only supported with snapshot mode. " \
+ "You can either use the \"snapshot\" option or use an uncompressed image.")
+
+ # Get the real path to the image to avoid issues when a symbolic link is passed.
+ # This ensures we always operate on the actual file.
+ image_path = os.path.realpath(self.rootfs)
+ # Extract target filename by removing .zst
+ image_dir = os.path.dirname(image_path)
+ uncompressed_name = os.path.basename(image_path).replace(".zst", "")
+ uncompressed_path = os.path.join(image_dir, uncompressed_name)
+
+ # If the decompressed image already exists (e.g., in the deploy directory),
+ # we use it directly to avoid overwriting artifacts generated by the build system.
+ # This prevents redundant decompression and preserves build outputs.
+ if os.path.exists(uncompressed_path):
+ logger.warning(f"Found existing decompressed image: {uncompressed_path}, Using it directly.")
+ else:
+ logger.info(f"Decompressing {self.rootfs} to {uncompressed_path}")
+ # Ensure the 'zstd' tool is installed before attempting to decompress.
+ if not shutil.which('zstd'):
+ raise RunQemuError(f"'zstd' is required to decompress {self.rootfs} but was not found in PATH")
+ try:
+ with open(uncompressed_path, 'wb') as out_file:
+ subprocess.check_call(['zstd', '-d', '-c', image_path], stdout=out_file)
+ except subprocess.CalledProcessError as e:
+ self.cleanup_files.append(uncompressed_path)
+ raise RunQemuError(f"Failed to decompress {self.rootfs}: {e}")
+
+ # Mark for deletion at the end
+ self.cleanup_files.append(uncompressed_path)
+
+ # Use the decompressed image as the rootfs
+ self.rootfs = uncompressed_path
+ self.fstype = self.fstype.removesuffix(".zst")
+
def check_arg_machine(self, arg):
"""Check whether it is a machine"""
if self.get('MACHINE') == arg:
@@ -1762,6 +1804,7 @@ def main():
config.check_args()
config.read_qemuboot()
config.check_and_set()
+ config.uncompress_rootfs()
# Check whether the combos is valid or not
config.validate_combos()
config.print_config()
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH v4 2/4] selftest: runqemu: add tests for booting zst compressed image
2025-07-31 10:23 [PATCH v4 1/4] runqemu: Add support for running compressed .zst rootfs images Yoann Congal
@ 2025-07-31 10:23 ` Yoann Congal
2025-07-31 14:55 ` [OE-core] " Mathieu Dubois-Briand
2025-07-31 10:23 ` [PATCH v4 3/4] runqemu: accept vmtypes and wictypes for rootfs paths extensions Yoann Congal
2025-07-31 10:23 ` [PATCH v4 4/4] runqemu: print snapshot mode state in console Yoann Congal
2 siblings, 1 reply; 5+ messages in thread
From: Yoann Congal @ 2025-07-31 10:23 UTC (permalink / raw)
To: openembedded-core; +Cc: Yoann Congal
From: Yoann Congal <yoann.congal@smile.fr>
Add a simple tests booting a compressed image given to runqemu as path
and as image recipe name.
Signed-off-by: Yoann Congal <yoann.congal@smile.fr>
---
meta/lib/oeqa/selftest/cases/runqemu.py | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/meta/lib/oeqa/selftest/cases/runqemu.py b/meta/lib/oeqa/selftest/cases/runqemu.py
index f01e1eec66..46ca0b4480 100644
--- a/meta/lib/oeqa/selftest/cases/runqemu.py
+++ b/meta/lib/oeqa/selftest/cases/runqemu.py
@@ -31,7 +31,7 @@ class RunqemuTests(OESelftestTestCase):
if self.td["HOST_ARCH"] in ('i586', 'i686', 'x86_64'):
self.fstypes += " iso hddimg"
if self.machine == "qemux86-64":
- self.fstypes += " wic.vmdk wic.qcow2 wic.vdi"
+ self.fstypes += " wic.vmdk wic.qcow2 wic.vdi wic.zst"
self.cmd_common = "runqemu nographic"
kvm = oe.types.qemu_use_kvm(get_bb_var('QEMU_USE_KVM'), self.td["TARGET_ARCH"])
@@ -152,6 +152,23 @@ SYSLINUX_TIMEOUT = "10"
with open(qemu.qemurunnerlog) as f:
self.assertTrue(qemu.runner.logged, "Failed: %s, %s" % (cmd, f.read()))
+ def test_boot_compressed_wic_by_path(self):
+ """Test runqemu /path/to/rootfs.wic.zst"""
+ rootfs = "%s.wic.zst" % (self.image_link_name)
+ rootfs = os.path.join(self.deploy_dir_image, rootfs)
+ if not os.path.exists(rootfs):
+ self.skipTest("%s not found" % rootfs)
+ cmd = "%s %s snapshot" % (self.cmd_common, rootfs)
+ with runqemu(self.recipe, ssh=False, launch_cmd=cmd) as qemu:
+ with open(qemu.qemurunnerlog) as f:
+ self.assertTrue(qemu.runner.logged, "Failed: %s, %s" % (cmd, f.read()))
+
+ def test_boot_compressed_wic_by_recipe(self):
+ """Test runqemu recipe-image wic.zst"""
+ cmd = "%s %s snapshot wic.zst" % (self.cmd_common, self.recipe)
+ with runqemu(self.recipe, ssh=False, launch_cmd=cmd) as qemu:
+ with open(qemu.qemurunnerlog) as f:
+ self.assertTrue(qemu.runner.logged, "Failed: %s, %s" % (cmd, f.read()))
# This test was designed as a separate class to test that shutdown
# command will shutdown qemu as expected on each qemu architecture
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH v4 3/4] runqemu: accept vmtypes and wictypes for rootfs paths extensions
2025-07-31 10:23 [PATCH v4 1/4] runqemu: Add support for running compressed .zst rootfs images Yoann Congal
2025-07-31 10:23 ` [PATCH v4 2/4] selftest: runqemu: add tests for booting zst compressed image Yoann Congal
@ 2025-07-31 10:23 ` Yoann Congal
2025-07-31 10:23 ` [PATCH v4 4/4] runqemu: print snapshot mode state in console Yoann Congal
2 siblings, 0 replies; 5+ messages in thread
From: Yoann Congal @ 2025-07-31 10:23 UTC (permalink / raw)
To: openembedded-core; +Cc: Yoann Congal
From: Yoann Congal <yoann.congal@smile.fr>
When using a .wic.zst image, its fstype is detected by default as
".zst" which prevent booting correctly.
Fix this by adding wictypes (and vmtypes while at it) to the list of
known fstypes. After this fix, the initial fstype is correctly ".wic.zst".
Signed-off-by: Yoann Congal <yoann.congal@smile.fr>
---
scripts/runqemu | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/runqemu b/scripts/runqemu
index c668906bdd..da53265219 100755
--- a/scripts/runqemu
+++ b/scripts/runqemu
@@ -380,7 +380,7 @@ class BaseConfig(object):
# Check filename against self.fstypes can handle <file>.cpio.gz,
# otherwise, its type would be "gz", which is incorrect.
fst = ""
- for t in self.fstypes:
+ for t in self.fstypes + self.vmtypes + self.wictypes:
if p.endswith(t):
fst = t
break
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH v4 4/4] runqemu: print snapshot mode state in console
2025-07-31 10:23 [PATCH v4 1/4] runqemu: Add support for running compressed .zst rootfs images Yoann Congal
2025-07-31 10:23 ` [PATCH v4 2/4] selftest: runqemu: add tests for booting zst compressed image Yoann Congal
2025-07-31 10:23 ` [PATCH v4 3/4] runqemu: accept vmtypes and wictypes for rootfs paths extensions Yoann Congal
@ 2025-07-31 10:23 ` Yoann Congal
2 siblings, 0 replies; 5+ messages in thread
From: Yoann Congal @ 2025-07-31 10:23 UTC (permalink / raw)
To: openembedded-core; +Cc: Yoann Congal
From: Yoann Congal <yoann.congal@smile.fr>
With snapshot enabled, no change on rootfs will be saved after qemu
shutdown. Since this is not what a user might expect, print the snapshot
mode state and its consequence in console at runqemu start.
Signed-off-by: Yoann Congal <yoann.congal@smile.fr>
---
v4: reformat message handling
---
scripts/runqemu | 3 +++
1 file changed, 3 insertions(+)
diff --git a/scripts/runqemu b/scripts/runqemu
index da53265219..a57fe794dc 100755
--- a/scripts/runqemu
+++ b/scripts/runqemu
@@ -1053,6 +1053,9 @@ to your build configuration.
logoutput.append('NFS_DIR: [%s]' % self.rootfs)
else:
logoutput.append('ROOTFS: [%s]' % self.rootfs)
+ logoutput.append('SNAPSHOT: [%s]' %
+ "Enabled. Changes on rootfs won't be kept after QEMU shutdown." if self.snapshot
+ else "Disabled. Changes on rootfs will be kept after QEMU shutdown.")
if self.ovmf_bios:
logoutput.append('OVMF: %s' % self.ovmf_bios)
if (self.ovmf_secboot_pkkek1):
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2025-07-31 14:55 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-31 10:23 [PATCH v4 1/4] runqemu: Add support for running compressed .zst rootfs images Yoann Congal
2025-07-31 10:23 ` [PATCH v4 2/4] selftest: runqemu: add tests for booting zst compressed image Yoann Congal
2025-07-31 14:55 ` [OE-core] " Mathieu Dubois-Briand
2025-07-31 10:23 ` [PATCH v4 3/4] runqemu: accept vmtypes and wictypes for rootfs paths extensions Yoann Congal
2025-07-31 10:23 ` [PATCH v4 4/4] runqemu: print snapshot mode state in console Yoann Congal
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox