From d9d21d3cf4eaad5cc7f2959a4abdafed781bb9cf Mon Sep 17 00:00:00 2001 From: Lubomír Sedlář Date: Aug 28 2024 11:07:12 +0000 Subject: [PATCH 1/2] kiwibuild: Fix location and metadata for ISOs When Kiwi builds an ISO, it is always supposed to be bootable and should be located in the iso/ subdirectory. Any other kind of image should still land in images/ and be listed as not bootable in the metadata. Relates: https://pagure.io/pungi-fedora/issue/1342 Signed-off-by: Lubomír Sedlář --- diff --git a/pungi/phases/kiwibuild.py b/pungi/phases/kiwibuild.py index 7ce3a54..12ec26d 100644 --- a/pungi/phases/kiwibuild.py +++ b/pungi/phases/kiwibuild.py @@ -184,10 +184,20 @@ class RunKiwiBuildThread(WorkerThread): # image_dir is absolute path to which the image should be copied. # We also need the same path as relative to compose directory for # including in the metadata. - image_dir = compose.paths.compose.image_dir(variant) % {"arch": arch} - rel_image_dir = compose.paths.compose.image_dir( - variant, relative=True - ) % {"arch": arch} + if format_ == "iso": + # If the produced image is actually an ISO, it should go to + # iso/ subdirectory. + image_dir = compose.paths.compose.iso_dir(arch, variant) + rel_image_dir = compose.paths.compose.iso_dir( + arch, variant, relative=True + ) + else: + image_dir = compose.paths.compose.image_dir(variant) % { + "arch": arch + } + rel_image_dir = compose.paths.compose.image_dir( + variant, relative=True + ) % {"arch": arch} util.makedirs(image_dir) filename = os.path.basename(path) @@ -211,7 +221,8 @@ class RunKiwiBuildThread(WorkerThread): img.arch = arch img.disc_number = 1 # We don't expect multiple disks img.disc_count = 1 - img.bootable = False + # Kiwi produces only bootable ISOs. Other kinds of images are + img.bootable = format_ == "iso" img.subvariant = config.get("subvariant", variant.uid) setattr(img, "can_fail", arch in self.failable_arches) setattr(img, "deliverable", "kiwibuild") diff --git a/tests/test_kiwibuildphase.py b/tests/test_kiwibuildphase.py index 50116a2..491dbf3 100644 --- a/tests/test_kiwibuildphase.py +++ b/tests/test_kiwibuildphase.py @@ -242,13 +242,14 @@ class TestKiwiBuildPhase(PungiTestCase): @mock.patch("pungi.util.get_file_size") @mock.patch("pungi.wrappers.kojiwrapper.KojiWrapper") class TestKiwiBuildThread(PungiTestCase): - def _img_path(self, arch, filename=None): - path = self.topdir + "/compose/Server/%s/images" % arch + def _img_path(self, arch, filename=None, dir=None): + dir = dir or "images" + path = self.topdir + "/compose/Server/%s/%s" % (arch, dir) if filename: path += "/" + filename return path - def test_process(self, KojiWrapper, get_file_size, get_mtime, Linker): + def test_process_vagrant_box(self, KojiWrapper, get_file_size, get_mtime, Linker): img_name = "FCBG.{arch}-Rawhide-1.6.vagrant.libvirt.box" self.repo = self.topdir + "/compose/Server/$arch/os" compose = DummyCompose( @@ -353,6 +354,114 @@ class TestKiwiBuildThread(PungiTestCase): assert "vagrant-libvirt.box" == image.format assert "vagrant-libvirt" == image.type assert "Test" == image.subvariant + assert not image.bootable + + def test_process_iso(self, KojiWrapper, get_file_size, get_mtime, Linker): + img_name = "FCBG.{arch}-Rawhide-1.6.iso" + self.repo = self.topdir + "/compose/Server/$arch/os" + compose = DummyCompose( + self.topdir, + { + "koji_profile": "koji", + "kiwibuild_bundle_format": "%N-%P-40_Beta-%I.%A.%T", + }, + ) + config = _merge({"subvariant": "Test"}, MINIMAL_CONF) + pool = mock.Mock() + + get_image_paths = KojiWrapper.return_value.get_image_paths + get_image_paths.return_value = { + "x86_64": [ + "/koji/task/1234/FCBG.x86_64-Rawhide-1.6.packages", + "/koji/task/1234/%s" % img_name.format(arch="x86_64"), + ], + "amd64": [ + "/koji/task/1234/FCBG.amd64-Rawhide-1.6.packages", + "/koji/task/1234/%s" % img_name.format(arch="amd64"), + ], + } + + KojiWrapper.return_value.koji_proxy.kiwiBuild.return_value = 1234 + KojiWrapper.return_value.watch_task.return_value = 0 + + t = RunKiwiBuildThread(pool) + get_file_size.return_value = 1024 + get_mtime.return_value = 13579 + t.process( + ( + compose, + compose.variants["Server"], + config, + ["amd64", "x86_64"], + { + "release": "1.6", + "target": "f40", + "descscm": MINIMAL_CONF["description_scm"], + "descpath": MINIMAL_CONF["description_path"], + "type": "t", + "type_attr": ["ta"], + "bundle_name_format": "fmt", + "version": "v", + "repo_releasever": "r", + }, + [self.repo], + [], + ), + 1, + ) + + assert KojiWrapper.return_value.koji_proxy.kiwiBuild.mock_calls == [ + mock.call( + "f40", + ["amd64", "x86_64"], + MINIMAL_CONF["description_scm"], + MINIMAL_CONF["description_path"], + profile=MINIMAL_CONF["kiwi_profile"], + release="1.6", + repos=[self.repo], + type="t", + type_attr=["ta"], + result_bundle_name_format="fmt", + optional_arches=[], + version="v", + repo_releasever="r", + ) + ] + + assert get_image_paths.mock_calls == [mock.call(1234)] + assert os.path.isdir(self._img_path("x86_64", dir="iso")) + assert os.path.isdir(self._img_path("amd64", dir="iso")) + Linker.return_value.link.assert_has_calls( + [ + mock.call( + "/koji/task/1234/FCBG.amd64-Rawhide-1.6.iso", + self._img_path("amd64", img_name.format(arch="amd64"), dir="iso"), + link_type="hardlink-or-copy", + ), + mock.call( + "/koji/task/1234/FCBG.x86_64-Rawhide-1.6.iso", + self._img_path("x86_64", img_name.format(arch="x86_64"), dir="iso"), + link_type="hardlink-or-copy", + ), + ], + any_order=True, + ) + + assert len(compose.im.add.call_args_list) == 2 + for call in compose.im.add.call_args_list: + _, kwargs = call + image = kwargs["image"] + expected_path = "Server/{0.arch}/iso/{1}".format( + image, img_name.format(arch=image.arch) + ) + assert kwargs["variant"] == "Server" + assert kwargs["arch"] in ("amd64", "x86_64") + assert kwargs["arch"] == image.arch + assert image.path == expected_path + assert "iso" == image.format + assert "iso" == image.type + assert image.bootable + assert "Test" == image.subvariant def test_handle_koji_fail(self, KojiWrapper, get_file_size, get_mtime, Linker): self.repo = self.topdir + "/compose/Server/$arch/os" From cd2ae81e3c63316997b9617ff2e30e3148af14f2 Mon Sep 17 00:00:00 2001 From: Lubomír Sedlář Date: Aug 29 2024 06:46:10 +0000 Subject: [PATCH 2/2] kiwibuild: Allow setting metadata type explicitly It is not possible to reliably detect what the type for an image should be in the metadata. This commit adds an option for user to explicitly provide it. It can only be configured on the specific image, not globally. Signed-off-by: Lubomír Sedlář --- diff --git a/doc/configuration.rst b/doc/configuration.rst index c6f936a..ded479e 100644 --- a/doc/configuration.rst +++ b/doc/configuration.rst @@ -1574,6 +1574,9 @@ KiwiBuild Settings described in :ref:`automatic versioning `. * ``repo_releasever`` -- (*str*) Override default releasever of the output image. + * ``manifest_type`` -- the image type that is put into the manifest by + pungi. If not supplied, an autodetected value will be provided. It may or + may not make sense. The options can be set either for the specific image, or at the phase level (see below). Version also falls back to ``global_version``. diff --git a/pungi/checks.py b/pungi/checks.py index bcf23e5..cc16d12 100644 --- a/pungi/checks.py +++ b/pungi/checks.py @@ -1214,6 +1214,7 @@ def make_schema(): "bundle_name_format": {"type": "string"}, "version": {"type": "string"}, "repo_releasever": {"type": "string"}, + "manifest_type": {"type": "string"}, }, "required": [ # description_scm and description_path diff --git a/pungi/phases/kiwibuild.py b/pungi/phases/kiwibuild.py index 12ec26d..bb26812 100644 --- a/pungi/phases/kiwibuild.py +++ b/pungi/phases/kiwibuild.py @@ -211,9 +211,9 @@ class RunKiwiBuildThread(WorkerThread): # Update image manifest img = Image(compose.im) - # Get the manifest type from the config if supplied, otherwise we - # determine the manifest type based on the koji output - img.type = type_ + # If user configured exact type, use it, otherwise try to + # figure it out based on the koji output. + img.type = config.get("manifest_type", type_) img.format = format_ img.path = os.path.join(rel_image_dir, filename) img.mtime = util.get_mtime(image_dest) diff --git a/tests/test_kiwibuildphase.py b/tests/test_kiwibuildphase.py index 491dbf3..e3ccdb7 100644 --- a/tests/test_kiwibuildphase.py +++ b/tests/test_kiwibuildphase.py @@ -73,6 +73,7 @@ class TestKiwiBuildPhase(PungiTestCase): "bundle_name_format": "fmt", "version": "Rawhide", "repo_releasever": "41", + "manifest_type": "live-kiwi", }, MINIMAL_CONF, ) @@ -366,7 +367,9 @@ class TestKiwiBuildThread(PungiTestCase): "kiwibuild_bundle_format": "%N-%P-40_Beta-%I.%A.%T", }, ) - config = _merge({"subvariant": "Test"}, MINIMAL_CONF) + config = _merge( + {"subvariant": "Test", "manifest_type": "live-kiwi"}, MINIMAL_CONF + ) pool = mock.Mock() get_image_paths = KojiWrapper.return_value.get_image_paths @@ -459,7 +462,7 @@ class TestKiwiBuildThread(PungiTestCase): assert kwargs["arch"] == image.arch assert image.path == expected_path assert "iso" == image.format - assert "iso" == image.type + assert "live-kiwi" == image.type assert image.bootable assert "Test" == image.subvariant