isos: Check maximum expected size
This patch allows the configuration to express maximum expected size for ISOs created in createiso and extra_isos phases. If the image is larger than this limit, a warning is emitted in test phase. The compose itself is not affected in any way. JIRA: COMPOSE-2824 Signed-off-by: Lubomír Sedlář <lsedlar@redhat.com>
This commit is contained in:
parent
7693e562b1
commit
6c6d4759f5
@ -1003,6 +1003,12 @@ Options
|
||||
**createiso_skip** = False
|
||||
(*list*) -- mapping that defines which variants and arches to skip during createiso; format: [(variant_uid_regex, {arch|*: True})]
|
||||
|
||||
**createiso_max_size**
|
||||
(*list*) -- mapping that defines maximum expected size for each variant and
|
||||
arch. If the ISO is larger than the limit, a warning will be issued.
|
||||
|
||||
Format: ``[(variant_uid_regex, {arch|*: number})]``
|
||||
|
||||
**create_jigdo** = True
|
||||
(*bool*) -- controls the creation of jigdo from ISO
|
||||
|
||||
@ -1574,6 +1580,9 @@ will reuse boot configuration from that variant.
|
||||
are ignored. If you want to include them in the ISO, set this option to
|
||||
``True``.
|
||||
|
||||
* ``max_size`` -- (*int*) expected maximum size in bytes. If the final
|
||||
image is larger, a warning will be issued.
|
||||
|
||||
Example config
|
||||
--------------
|
||||
::
|
||||
|
@ -730,6 +730,7 @@ def make_schema():
|
||||
"default": {},
|
||||
},
|
||||
"createiso_skip": _variant_arch_mapping({"type": "boolean"}),
|
||||
"createiso_max_size": _variant_arch_mapping({"type": "number"}),
|
||||
"createiso_break_hardlinks": {
|
||||
"type": "boolean",
|
||||
"default": False,
|
||||
@ -969,6 +970,7 @@ def make_schema():
|
||||
"type": "boolean",
|
||||
"default": False,
|
||||
},
|
||||
"max_size": {"type": "number"},
|
||||
},
|
||||
"required": ["include_variants"],
|
||||
"additionalProperties": False
|
||||
|
@ -263,6 +263,7 @@ def add_iso_to_metadata(
|
||||
compose.im.add(variant.uid, variant_arch, img)
|
||||
else:
|
||||
compose.im.add(variant.uid, arch, img)
|
||||
return img
|
||||
|
||||
|
||||
def run_createiso_command(runroot, num, compose, bootable, arch, cmd, mounts,
|
||||
|
@ -125,7 +125,7 @@ class ExtraIsosThread(WorkerThread):
|
||||
arch, "extraiso-%s" % os.path.basename(iso_path)),
|
||||
with_jigdo=compose.conf['create_jigdo'])
|
||||
|
||||
add_iso_to_metadata(
|
||||
img = add_iso_to_metadata(
|
||||
compose,
|
||||
variant,
|
||||
arch,
|
||||
@ -133,6 +133,7 @@ class ExtraIsosThread(WorkerThread):
|
||||
bootable,
|
||||
additional_variants=config["include_variants"],
|
||||
)
|
||||
img._max_size = config.get("max_size")
|
||||
|
||||
self.pool.log_info("[DONE ] %s" % msg)
|
||||
|
||||
|
@ -114,10 +114,11 @@ def check_image_sanity(compose):
|
||||
if arch not in im.images[variant.uid]:
|
||||
continue
|
||||
for img in im.images[variant.uid][arch]:
|
||||
check(compose, variant, arch, img)
|
||||
check_sanity(compose, variant, arch, img)
|
||||
check_size_limit(compose, variant, arch, img)
|
||||
|
||||
|
||||
def check(compose, variant, arch, image):
|
||||
def check_sanity(compose, variant, arch, image):
|
||||
path = os.path.join(compose.paths.compose.topdir(), image.path)
|
||||
deliverable = getattr(image, 'deliverable')
|
||||
can_fail = getattr(image, 'can_fail', False)
|
||||
@ -159,3 +160,22 @@ def has_gpt(f):
|
||||
|
||||
def has_eltorito(f):
|
||||
return _check_magic(f, 0x8801, b'CD001\1EL TORITO SPECIFICATION')
|
||||
|
||||
|
||||
def check_size_limit(compose, variant, arch, img):
|
||||
"""If a size of the ISO image is over the configured limit, report a
|
||||
warning. Do nothing for other types of images.
|
||||
"""
|
||||
if img.format != "iso":
|
||||
return
|
||||
limits = get_arch_variant_data(compose.conf, "createiso_max_size", arch, variant)
|
||||
if not limits and not getattr(img, "_max_size", None):
|
||||
return
|
||||
# For ISOs created in extra_isos phase we add an attribute with the limit,
|
||||
# and there is a global option otherwise.
|
||||
limit = getattr(img, "_max_size", None) or limits[0]
|
||||
|
||||
if img.size > limit:
|
||||
compose.log_warning(
|
||||
"ISO %s is too big. Expected max %dB, got %dB" % (img.path, limit, img.size)
|
||||
)
|
||||
|
@ -169,7 +169,9 @@ class DummyCompose(object):
|
||||
self.log_debug = mock.Mock()
|
||||
self.log_warning = mock.Mock()
|
||||
self.get_image_name = mock.Mock(return_value='image-name')
|
||||
self.image = mock.Mock(path='Client/i386/iso/image.iso', can_fail=False, size=123)
|
||||
self.image = mock.Mock(
|
||||
path='Client/i386/iso/image.iso', can_fail=False, size=123, _max_size=None,
|
||||
)
|
||||
self.im = mock.Mock(images={'Client': {'amd64': [self.image]}})
|
||||
self.old_composes = []
|
||||
self.config_dir = '/home/releng/config'
|
||||
|
@ -220,6 +220,63 @@ class ExtraIsosThreadTest(helpers.PungiTestCase):
|
||||
)
|
||||
self.assertEqual(pmm.call_args_list, [mock.call(compose, server, "x86_64")])
|
||||
|
||||
def test_image_with_max_size(self, aitm, rcc, gef, gic, gfn, gvi, pmm):
|
||||
compose = helpers.DummyCompose(self.topdir, {
|
||||
"bootable": True,
|
||||
"buildinstall_method": "lorax"
|
||||
})
|
||||
server = compose.variants["Server"]
|
||||
cfg = {
|
||||
"include_variants": ["Client"],
|
||||
"max_size": 15,
|
||||
}
|
||||
|
||||
gfn.return_value = "my.iso"
|
||||
gvi.return_value = "my volume id"
|
||||
gic.return_value = "/tmp/iso-graft-points"
|
||||
|
||||
t = extra_isos.ExtraIsosThread(mock.Mock())
|
||||
with mock.patch("time.sleep"):
|
||||
t.process((compose, cfg, server, "x86_64"), 1)
|
||||
|
||||
self.assertEqual(gfn.call_args_list,
|
||||
[mock.call(compose, server, "x86_64", None)])
|
||||
self.assertEqual(gvi.call_args_list,
|
||||
[mock.call(compose, server, "x86_64", [])])
|
||||
self.assertEqual(gef.call_args_list,
|
||||
[mock.call(compose, server, "x86_64", [])])
|
||||
self.assertEqual(
|
||||
gic.call_args_list,
|
||||
[
|
||||
mock.call(
|
||||
compose,
|
||||
server,
|
||||
"x86_64",
|
||||
["Client"],
|
||||
"my.iso",
|
||||
bootable=True,
|
||||
inherit_extra_files=False,
|
||||
),
|
||||
],
|
||||
)
|
||||
self.assertEqual(
|
||||
rcc.call_args_list,
|
||||
[mock.call(False, 1, compose, True, "x86_64",
|
||||
["bash", os.path.join(self.topdir, "work/x86_64/tmp-Server/extraiso-my.iso.sh")],
|
||||
[self.topdir],
|
||||
log_file=os.path.join(self.topdir, "logs/x86_64/extraiso-my.iso.x86_64.log"),
|
||||
with_jigdo=True)]
|
||||
|
||||
)
|
||||
self.assertEqual(
|
||||
aitm.call_args_list,
|
||||
[mock.call(compose, server, "x86_64",
|
||||
os.path.join(self.topdir, "compose/Server/x86_64/iso/my.iso"),
|
||||
True, additional_variants=["Client"])]
|
||||
)
|
||||
self.assertEqual(aitm.return_value._max_size, 15)
|
||||
self.assertEqual(pmm.call_args_list, [mock.call(compose, server, "x86_64")])
|
||||
|
||||
def test_binary_image_custom_naming(self, aitm, rcc, gef, gic, gfn, gvi, pmm):
|
||||
compose = helpers.DummyCompose(self.topdir, {})
|
||||
server = compose.variants['Server']
|
||||
|
@ -166,6 +166,60 @@ class TestCheckImageSanity(PungiTestCase):
|
||||
except Exception:
|
||||
self.fail('Checking optional variant must not raise')
|
||||
|
||||
@mock.patch("pungi.phases.test.check_sanity", new=mock.Mock())
|
||||
def test_too_big_iso(self):
|
||||
compose = DummyCompose(self.topdir, {"createiso_max_size": [(".*", {"*": 10})]})
|
||||
compose.image.format = 'iso'
|
||||
compose.image.bootable = False
|
||||
compose.image.size = 20
|
||||
|
||||
test_phase.check_image_sanity(compose)
|
||||
|
||||
warnings = [call[0][0] for call in compose.log_warning.call_args_list]
|
||||
self.assertIn(
|
||||
"ISO Client/i386/iso/image.iso is too big. Expected max 10B, got 20B",
|
||||
warnings,
|
||||
)
|
||||
|
||||
@mock.patch("pungi.phases.test.check_sanity", new=mock.Mock())
|
||||
def test_too_big_unified(self):
|
||||
compose = DummyCompose(self.topdir, {})
|
||||
compose.image.format = 'iso'
|
||||
compose.image.bootable = False
|
||||
compose.image.size = 20
|
||||
compose.image.unified = True
|
||||
setattr(compose.image, "_max_size", 10)
|
||||
|
||||
test_phase.check_image_sanity(compose)
|
||||
|
||||
warnings = [call[0][0] for call in compose.log_warning.call_args_list]
|
||||
self.assertIn(
|
||||
"ISO Client/i386/iso/image.iso is too big. Expected max 10B, got 20B",
|
||||
warnings,
|
||||
)
|
||||
|
||||
@mock.patch("pungi.phases.test.check_sanity", new=mock.Mock())
|
||||
def test_fits_in_limit(self):
|
||||
compose = DummyCompose(self.topdir, {"createiso_max_size": [(".*", {"*": 20})]})
|
||||
compose.image.format = 'iso'
|
||||
compose.image.bootable = False
|
||||
compose.image.size = 5
|
||||
|
||||
test_phase.check_image_sanity(compose)
|
||||
|
||||
self.assertEqual(compose.log_warning.call_args_list, [])
|
||||
|
||||
@mock.patch("pungi.phases.test.check_sanity", new=mock.Mock())
|
||||
def test_non_iso(self):
|
||||
compose = DummyCompose(self.topdir, {"createiso_max_size": [(".*", {"*": 10})]})
|
||||
compose.image.format = 'qcow2'
|
||||
compose.image.bootable = False
|
||||
compose.image.size = 20
|
||||
|
||||
test_phase.check_image_sanity(compose)
|
||||
|
||||
self.assertEqual(compose.log_warning.call_args_list, [])
|
||||
|
||||
|
||||
class TestRepoclosure(PungiTestCase):
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user