public inbox for isar-users@googlegroups.com
 help / color / mirror / Atom feed
* [PATCH v2 1/2] image: remove unrequested intermediate image types
@ 2026-11-04  7:25 'Clara Kowalsky' via isar-users
  2026-11-04  7:26 ` [PATCH v2 2/2] imagetypes_vm: add support for standalone vmdk images 'Clara Kowalsky' via isar-users
  0 siblings, 1 reply; 2+ messages in thread
From: 'Clara Kowalsky' via isar-users @ 2026-11-04  7:25 UTC (permalink / raw)
  To: isar-users; +Cc: Clara Kowalsky

Images built only as dependencies currently remain in the deploy
directory even when they are not listed in IMAGE_FSTYPES.
Fix this by keeping only explicitly requested image outputs and removing
dependency-only images and conversion intermediates. Users who need a
dependency image retained should include it in IMAGE_FSTYPES.

Since dependencies are now also removed, run cleanup after all image
tasks finish rather than at the end of each producing task. This keeps
dependency images available until their consumers have completed.
Expanded file paths are recorded, so cleanup also handles type-specific
filenames and deploy directories.
Unittests are added to test dependency cleanup and retention of
requested outputs.

Signed-off-by: Clara Kowalsky <clara.kowalsky@siemens.com>
---
 meta/classes-recipe/image.bbclass             | 24 ++---
 .../unittests/test_image_type_cleanup.py      | 92 +++++++++++++++++++
 2 files changed, 104 insertions(+), 12 deletions(-)
 create mode 100644 testsuite/unittests/test_image_type_cleanup.py

diff --git a/meta/classes-recipe/image.bbclass b/meta/classes-recipe/image.bbclass
index ce19ae1c..229a37fe 100644
--- a/meta/classes-recipe/image.bbclass
+++ b/meta/classes-recipe/image.bbclass
@@ -187,6 +187,8 @@ SUDO_CHROOT = "imager_run -d ${PP_ROOTFS} -u root --"
 # hook up IMAGE_CMD_*
 python() {
     image_types = (d.getVar('IMAGE_FSTYPES') or '').split()
+    requested_types = set(image_types)
+    intermediate_files = set()
     conversions = set(d.getVar('IMAGE_CONVERSIONS').split())
     chroot_mode = d.getVar('ISAR_CHROOT_MODE')
 
@@ -285,8 +287,10 @@ python() {
 
         # add conversions
         conversion_depends = set()
-        rm_images = set()
         def create_conversions(t):
+            localdata.setVar('type', t)
+            if t not in requested_types:
+                intermediate_files.add(localdata.getVar('IMAGE_FILE_HOST'))
             for c in sorted(conversions):
                 if t.endswith('.' + c):
                     t = t[:-len(c) - 1]
@@ -301,20 +305,9 @@ python() {
                     for dep in (localdata.getVar('CONVERSION_DEPS:' + c) or '').split():
                         conversion_install.add(dep)
                         local_conversion_install.add(dep)
-                    # remove temporary image files
-                    if t not in image_types:
-                        rm_images.add(localdata.expand('${IMAGE_FILE_HOST}'))
-
         for t in basetypes[bt]:
             create_conversions(t)
 
-        if bt not in image_types:
-            localdata.setVar('type', t)
-            rm_images.add(localdata.expand('${IMAGE_FILE_HOST}'))
-
-        for image in rm_images:
-            cmds.append('\trm ' + image)
-
         # image type dependencies
         after = 'do_image_tools'
         for dep in typedeps[bt]:
@@ -340,6 +333,7 @@ python() {
         d.appendVar('INSTALL_image_%s' % bt_clean, ' ' + ' '.join(sorted(local_imager_install | local_conversion_install)))
         d.appendVarFlag(task, 'vardeps', ' INSTALL_image_%s' % bt_clean)
 
+    d.setVar('IMAGE_INTERMEDIATE_FILES', ' '.join(sorted(intermediate_files)))
     d.appendVar('IMAGER_INSTALL', ' ' + ' '.join(sorted(imager_install | conversion_install)))
     d.appendVar('IMAGER_BOM', ' ' + ' '.join(sorted(imager_bom)))
     d.appendVar('IMAGER_BUILD_DEPS', ' ' + ' '.join(sorted(imager_build_deps)))
@@ -429,6 +423,12 @@ python do_image() {
     """Virtual task"""
     pass
 }
+python cleanup_image_intermediates() {
+    for image in (d.getVar('IMAGE_INTERMEDIATE_FILES') or '').split():
+        bb.utils.remove(image)
+}
+do_image[postfuncs] += "cleanup_image_intermediates"
+do_image[vardeps] += "IMAGE_INTERMEDIATE_FILES"
 addtask image before do_build after do_image_tools
 
 python do_deploy() {
diff --git a/testsuite/unittests/test_image_type_cleanup.py b/testsuite/unittests/test_image_type_cleanup.py
new file mode 100644
index 00000000..1e2ad5b9
--- /dev/null
+++ b/testsuite/unittests/test_image_type_cleanup.py
@@ -0,0 +1,92 @@
+# This software is a part of Isar.
+# Copyright (C) Siemens AG, 2026
+#
+# SPDX-License-Identifier: MIT
+
+import sys
+import tempfile
+import unittest
+from pathlib import Path
+
+root = Path(__file__).resolve().parents[2]
+sys.path.extend([
+    str(root / 'bitbake/lib'),
+    str(root / 'meta/lib'),
+])
+
+import bb.data
+from bb.build import exec_func
+from bb.parse import handle
+
+
+data = bb.data.init()
+data.setVar('BBPATH', f'{root}/meta:{root}/bitbake')
+data.setVar('__bbclasstype', 'recipe')
+data.setVar('IMGCLASSES', '')
+parsed = handle(str(root / 'meta/classes-recipe/image.bbclass'), data)
+data.setVar('IMAGE_TYPEDEP:ova', 'vmdk')
+data.setVar('IMAGE_TYPEDEP:vmdk', 'wic')
+data.setVar('IMAGE_CMD:vmdk', ':')
+namespace = {'bb': bb}
+exec(parsed['get_base_type'], namespace)
+image_tasks = next(
+    function for function in parsed.getVar('__BBANONFUNCS', False)
+    if 'def collect_image_type(' in parsed.getVar(function, False)
+)
+exec(parsed[image_tasks], namespace)
+
+
+class TestImageTypeCleanup(unittest.TestCase):
+    def generate_image_tasks(self, image_types, deploy_dir='/deploy'):
+        d = bb.data.createCopy(data)
+        d.setVar('IMAGE_FSTYPES', image_types)
+        d.setVar('DEPLOY_DIR_IMAGE', str(deploy_dir))
+        d.setVar('IMAGE_FULLNAME', 'image')
+        namespace[image_tasks](d)
+        return d
+
+    def assert_intermediates(self, image_types, expected):
+        d = self.generate_image_tasks(image_types)
+        self.assertEqual(
+            set(d.getVar('IMAGE_INTERMEDIATE_FILES').split()),
+            {'/deploy/image.' + image_type for image_type in expected},
+        )
+
+    def test_only_unrequested_types_are_intermediates(self):
+        self.assert_intermediates('ova.zst', {'ova', 'vmdk', 'wic'})
+        self.assert_intermediates('vmdk ova.zst', {'ova', 'wic'})
+        self.assert_intermediates('ova ova.zst vmdk wic', set())
+
+    def test_unrequested_conversion_stages_are_cleaned(self):
+        self.assert_intermediates('tar.gz.xz', {'tar', 'tar.gz'})
+        self.assert_intermediates('tar.gz tar.gz.xz', {'tar'})
+
+    def test_cleanup_uses_image_type_filename_overrides(self):
+        d = bb.data.createCopy(data)
+        d.setVar('IMAGE_FSTYPES', 'tar.gz')
+        d.setVar('IMAGE_FULLNAME:tar', 'custom-image')
+        d.setVar('DEPLOY_DIR_IMAGE:tar', '/custom-deploy')
+        namespace[image_tasks](d)
+        self.assertEqual(
+            d.getVar('IMAGE_INTERMEDIATE_FILES'),
+            '/custom-deploy/custom-image.tar',
+        )
+
+    def test_cleanup_removes_only_intermediate_files(self):
+        with tempfile.TemporaryDirectory() as deploy_dir:
+            deploy_dir = Path(deploy_dir)
+            for image_type in ('ova', 'wic', 'vmdk', 'ova.zst'):
+                (deploy_dir / ('image.' + image_type)).touch()
+
+            d = self.generate_image_tasks('vmdk ova.zst', deploy_dir)
+            d.setVar('T', str(deploy_dir / 'temp'))
+            exec_func('cleanup_image_intermediates', d)
+
+            self.assertEqual(
+                {path.name for path in deploy_dir.glob('image.*')},
+                {'image.vmdk', 'image.ova.zst'},
+            )
+
+
+if __name__ == '__main__':
+    unittest.main()
-- 
2.56.0

-- 
You received this message because you are subscribed to the Google Groups "isar-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to isar-users+unsubscribe@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/isar-users/20261104072600.3229817-1-clara.kowalsky%40siemens.com.

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-11-04  7:26 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-04  7:25 [PATCH v2 1/2] image: remove unrequested intermediate image types 'Clara Kowalsky' via isar-users
2026-11-04  7:26 ` [PATCH v2 2/2] imagetypes_vm: add support for standalone vmdk images 'Clara Kowalsky' via isar-users

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox