diff mbox series

[5/5,v4] image: add check_image_max_size as post function to check file size against IMAGE_FILE_MAXSIZE

Message ID 20260329134716.3185469-6-charles-antoine.couret@mind.be
State Under Review
Headers show
Series image_types: use IMAGE_FILE_MAXSIZE variable to create fixed partition size | expand

Commit Message

Couret Charles-Antoine March 29, 2026, 1:47 p.m. UTC
From: Charles-Antoine Couret <charles-antoine.couret@mind.be>

Trigger an error if the final size is above IMAGE_FILE_MAXSIZE value. Which is relevant if the
partition size is fixed and the user wants to be sure that the image can be entirely installed
into its partition.

If the variable is not set, no error is trigger. It works for all filesystems.

Signed-off-by: Charles-Antoine Couret <charles-antoine.couret@mind.be>
---
 meta/classes-recipe/image.bbclass             | 29 ++++++++++
 meta/lib/oeqa/selftest/cases/imagefeatures.py | 53 +++++++++++++++++++
 2 files changed, 82 insertions(+)

Comments

patchtest@automation.yoctoproject.org March 29, 2026, 2:01 p.m. UTC | #1
Thank you for your submission. Patchtest identified one
or more issues with the patch. Please see the log below for
more information:

---
Testing patch /home/patchtest/share/mboxes/5-5-v4-image-add-check_image_max_size-as-post-function-to-check-file-size-against-IMAGE_FILE_MAXSIZE.patch

FAIL: test shortlog length: Edit shortlog so that it is 90 characters or less (currently 94 characters) (test_mbox.TestMbox.test_shortlog_length)

PASS: pretest pylint (test_python_pylint.PyLint.pretest_pylint)
PASS: test Signed-off-by presence (test_mbox.TestMbox.test_signed_off_by_presence)
PASS: test author valid (test_mbox.TestMbox.test_author_valid)
PASS: test commit message presence (test_mbox.TestMbox.test_commit_message_presence)
PASS: test commit message user tags (test_mbox.TestMbox.test_commit_message_user_tags)
PASS: test mbox format (test_mbox.TestMbox.test_mbox_format)
PASS: test non-AUH upgrade (test_mbox.TestMbox.test_non_auh_upgrade)
PASS: test pylint (test_python_pylint.PyLint.test_pylint)
PASS: test shortlog format (test_mbox.TestMbox.test_shortlog_format)
PASS: test target mailing list (test_mbox.TestMbox.test_target_mailing_list)

SKIP: test CVE tag format: No new CVE patches introduced (test_patch.TestPatch.test_cve_tag_format)
SKIP: test Signed-off-by presence: No new CVE patches introduced (test_patch.TestPatch.test_signed_off_by_presence)
SKIP: test Upstream-Status presence: No new CVE patches introduced (test_patch.TestPatch.test_upstream_status_presence_format)
SKIP: test bugzilla entry format: No bug ID found (test_mbox.TestMbox.test_bugzilla_entry_format)
SKIP: test series merge on head: Merge test is disabled for now (test_mbox.TestMbox.test_series_merge_on_head)

---

Please address the issues identified and
submit a new revision of the patch, or alternatively, reply to this
email with an explanation of why the patch should be accepted. If you
believe these results are due to an error in patchtest, please submit a
bug at https://bugzilla.yoctoproject.org/ (use the 'Patchtest' category
under 'Yocto Project Subprojects'). For more information on specific
failures, see: https://wiki.yoctoproject.org/wiki/Patchtest. Thank
you!
diff mbox series

Patch

diff --git a/meta/classes-recipe/image.bbclass b/meta/classes-recipe/image.bbclass
index 53f1a9dc45..e0c66f0a31 100644
--- a/meta/classes-recipe/image.bbclass
+++ b/meta/classes-recipe/image.bbclass
@@ -524,6 +524,7 @@  python () {
         d.setVarFlag(task, 'imagetype', t)
 
         d.appendVarFlag(task, 'prefuncs', ' ' + debug + ' set_image_size')
+        d.prependVarFlag(task, 'postfuncs', 'check_image_max_size ')
         d.prependVarFlag(task, 'postfuncs', 'create_symlinks ')
         d.appendVarFlag(task, 'subimages', ' ' + ' '.join(subimages))
         d.appendVarFlag(task, 'vardeps', ' ' + ' '.join(vardeps))
@@ -626,6 +627,34 @@  python create_symlinks() {
             bb.note("Skipping symlink, source does not exist: %s -> %s" % (dst, src))
 }
 
+#
+# Check if image size is lighter than maximum size
+#
+python check_image_max_size() {
+    def get_max_image_size(d, fs):
+        max_size = d.getVar("IMAGE_FILE_MAXSIZE:%s" % fs)
+        if max_size is not None:
+            return int(max_size)
+
+        return None
+
+    deploy_dir = d.getVar('IMGDEPLOYDIR')
+    img_name = d.getVar('IMAGE_NAME')
+    taskname = d.getVar("BB_CURRENTTASK")
+    subimages = (d.getVarFlag("do_" + taskname, 'subimages', False) or "").split()
+
+    for type in subimages:
+        file_name = os.path.join(deploy_dir, img_name + "." + type)
+
+        if os.path.exists(file_name):
+            file_size = os.stat(file_name).st_size / 1024
+            max_size = get_max_image_size(d, type)
+            if max_size is not None:
+                if file_size > max_size:
+                    bb.fatal("The image %s size %d(K) exceeds IMAGE_FILE_MAXSIZE: %d(K)" % \
+                   (file_name, file_size, max_size))
+}
+
 python write_image_output_manifest() {
     import json
     from pathlib import Path
diff --git a/meta/lib/oeqa/selftest/cases/imagefeatures.py b/meta/lib/oeqa/selftest/cases/imagefeatures.py
index 87c3da228a..b956cfd32a 100644
--- a/meta/lib/oeqa/selftest/cases/imagefeatures.py
+++ b/meta/lib/oeqa/selftest/cases/imagefeatures.py
@@ -234,6 +234,59 @@  UBINIZE_ARGS_mtd_4_256 ?= "-m 4096 -p 256KiB"
                 self.assertTrue(os.path.exists(image_path),
                                 "%s image %s doesn't exist" % (itype, image_path))
 
+    def test_image_maxsize_success(self):
+        """
+        Summary:     Check if the image built is below maximum size if set
+        Expected:    image is built, size below the limit and no error are reported
+        Product:     oe-core
+        Author:      Charles-Antoine Couret <charles-antoine.couret@mind.be>
+        """
+        image = 'core-image-minimal'
+
+        config = """
+IMAGE_FSTYPES += "ext4"
+IMAGE_FILE_MAXSIZE:ext4 = "300000"
+"""
+        self.write_config(config)
+
+        res = bitbake(image)
+        bb_vars = get_bb_vars(['DEPLOY_DIR_IMAGE', 'IMAGE_LINK_NAME'], image)
+
+        link_path = os.path.join(bb_vars['DEPLOY_DIR_IMAGE'], "%s.%s" % (bb_vars['IMAGE_LINK_NAME'], "ext4"))
+        image_path = os.path.realpath(link_path)
+        # check if result image is in deploy directory
+        self.assertTrue(os.path.exists(link_path),
+                        "%s image %s does not exist" % ("ext4", link_path))
+        # check if result image size is below than maximum value
+        self.assertTrue(os.stat(image_path).st_size / 1024 <= 300000)
+        # No error during execution
+        self.assertEqual(res.status, 0)
+
+    def test_image_maxsize_failure(self):
+        """
+        Summary:     Check if the image built with size above limit is triggering error
+        Expected:    the image size is above limit and triggers error
+        Product:     oe-core
+        Author:      Charles-Antoine Couret <charles-antoine.couret@mind.be>
+        """
+        image = 'core-image-minimal'
+
+        config = """
+IMAGE_FSTYPES += "ext4"
+IMAGE_FILE_MAXSIZE:ext4 = "1000"
+"""
+        self.write_config(config)
+
+        res = bitbake(image, ignore_status=True)
+        bb_vars = get_bb_vars(['DEPLOY_DIR_IMAGE', 'IMAGE_LINK_NAME'], image)
+
+        link_path = os.path.join(bb_vars['DEPLOY_DIR_IMAGE'], "%s.%s" % (bb_vars['IMAGE_LINK_NAME'], "ext4"))
+        # check if result image is not generated
+        self.assertFalse(os.path.exists(link_path),
+                        "%s image %s exists" % ("ext4", link_path))
+        # Error triggered during execution
+        self.assertNotEqual(res.status, 0)
+
     def test_useradd_static(self):
         config = """
 USERADDEXTENSION = "useradd-staticids"