From a9bb68b26fed19d55b21a97b70eae8aa285f46d1 Mon Sep 17 00:00:00 2001 From: David Shea Date: Thu, 28 Mar 2019 11:04:51 -0400 Subject: [PATCH] Add an option to align the image size to a multiplier. If provided, round the disk image size up to a multiple of the value. This allows for image formats with specific size-alignment requirements (e.g., disk size must be in GiB). (cherry picked from commit 8ef4f431d803e02c52281f5346f64dcc38846a61) Related: rhbz#1689140 --- src/pylorax/api/compose.py | 9 +++++++++ src/pylorax/cmdline.py | 2 ++ src/pylorax/creator.py | 3 +++ tests/pylorax/test_creator.py | 21 ++++++++++++++++----- 4 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/pylorax/api/compose.py b/src/pylorax/api/compose.py index e021bf2e..d6510da1 100644 --- a/src/pylorax/api/compose.py +++ b/src/pylorax/api/compose.py @@ -596,6 +596,7 @@ def compose_args(compose_type): "ostree": False, "live_rootfs_keep_size": False, "live_rootfs_size": 0, + "image_size_align": 0, "image_type": False, # False instead of None because of TOML "qemu_args": [], "image_name": default_image_name("xz", "root.tar"), @@ -617,6 +618,7 @@ def compose_args(compose_type): "ostree": False, "live_rootfs_keep_size": False, "live_rootfs_size": 0, + "image_size_align": 0, "image_type": False, # False instead of None because of TOML "qemu_args": [], "image_name": "live.iso", @@ -641,6 +643,7 @@ def compose_args(compose_type): "ostree": False, "live_rootfs_keep_size": False, "live_rootfs_size": 0, + "image_size_align": 0, "image_type": False, # False instead of None because of TOML "qemu_args": [], "image_name": "disk.img", @@ -663,6 +666,7 @@ def compose_args(compose_type): "ostree": False, "live_rootfs_keep_size": False, "live_rootfs_size": 0, + "image_size_align": 0, "image_type": "qcow2", "qemu_args": [], "image_name": "disk.qcow2", @@ -685,6 +689,7 @@ def compose_args(compose_type): "ostree": False, "live_rootfs_keep_size": False, "live_rootfs_size": 0, + "image_size_align": 0, "image_type": False, # False instead of None because of TOML "qemu_args": [], "image_name": "filesystem.img", @@ -707,6 +712,7 @@ def compose_args(compose_type): "ostree": False, "live_rootfs_keep_size": False, "live_rootfs_size": 0, + "image_size_align": 0, "image_type": False, "qemu_args": [], "image_name": "disk.ami", @@ -729,6 +735,7 @@ def compose_args(compose_type): "ostree": False, "live_rootfs_keep_size": False, "live_rootfs_size": 0, + "image_size_align": 0, "image_type": "vpc", "qemu_args": ["-o", "subformat=fixed,force_size"], "image_name": "disk.vhd", @@ -751,6 +758,7 @@ def compose_args(compose_type): "ostree": False, "live_rootfs_keep_size": False, "live_rootfs_size": 0, + "image_size_align": 0, "image_type": "vmdk", "qemu_args": [], "image_name": "disk.vmdk", @@ -773,6 +781,7 @@ def compose_args(compose_type): "ostree": False, "live_rootfs_keep_size": False, "live_rootfs_size": 0, + "image_size_align": 0, "image_type": "qcow2", "qemu_args": [], "image_name": "disk.qcow2", diff --git a/src/pylorax/cmdline.py b/src/pylorax/cmdline.py index 193222d5..d0590192 100644 --- a/src/pylorax/cmdline.py +++ b/src/pylorax/cmdline.py @@ -213,6 +213,8 @@ def lmc_parser(dracut_default=""): help="Name of output file to create. Used for tar, fs and disk image. Default is a random name.") image_group.add_argument("--fs-label", default="Anaconda", help="Label to set on fsimage, default is 'Anaconda'") + image_group.add_argument("--image-size-align", type=int, default=0, + help="Create a disk image with a size that is a multiple of this value in MiB.") image_group.add_argument("--image-type", default=None, help="Create an image with qemu-img. See qemu-img --help for supported formats.") image_group.add_argument("--qemu-arg", action="append", dest="qemu_args", default=[], diff --git a/src/pylorax/creator.py b/src/pylorax/creator.py index 8068100f..2b694fdc 100644 --- a/src/pylorax/creator.py +++ b/src/pylorax/creator.py @@ -467,6 +467,9 @@ def calculate_disk_size(opts, ks): log.info("Adding 1024M for reqpart --addboot") disk_size += 1024 + if opts.image_size_align: + disk_size += opts.image_size_align - (disk_size % opts.image_size_align) + log.info("Using disk size of %sMiB", disk_size) return disk_size diff --git a/tests/pylorax/test_creator.py b/tests/pylorax/test_creator.py index ad05ec77..b831a461 100644 --- a/tests/pylorax/test_creator.py +++ b/tests/pylorax/test_creator.py @@ -247,7 +247,7 @@ class CreatorTest(unittest.TestCase): def disk_size_simple_test(self): """Test calculating the disk size with a simple / partition""" - opts = DataHolder(no_virt=True, make_fsimage=False, make_iso=False, make_pxe_live=False) + opts = DataHolder(no_virt=True, make_fsimage=False, make_iso=False, make_pxe_live=False, image_size_align=0) ks_version = makeVersion() ks = KickstartParser(ks_version, errorsAreFatal=False, missingIncludeIsFatal=False) ks.readKickstartFromString("url --url=http://dl.fedoraproject.com\n" @@ -259,7 +259,7 @@ class CreatorTest(unittest.TestCase): def disk_size_boot_test(self): """Test calculating the disk size with / and /boot partitions""" - opts = DataHolder(no_virt=True, make_fsimage=False, make_iso=False, make_pxe_live=False) + opts = DataHolder(no_virt=True, make_fsimage=False, make_iso=False, make_pxe_live=False, image_size_align=0) ks_version = makeVersion() ks = KickstartParser(ks_version, errorsAreFatal=False, missingIncludeIsFatal=False) ks.readKickstartFromString("url --url=http://dl.fedoraproject.com\n" @@ -272,7 +272,7 @@ class CreatorTest(unittest.TestCase): def disk_size_boot_fsimage_test(self): """Test calculating the disk size with / and /boot partitions on a fsimage""" - opts = DataHolder(no_virt=True, make_fsimage=True, make_iso=False, make_pxe_live=False) + opts = DataHolder(no_virt=True, make_fsimage=True, make_iso=False, make_pxe_live=False, image_size_align=0) ks_version = makeVersion() ks = KickstartParser(ks_version, errorsAreFatal=False, missingIncludeIsFatal=False) ks.readKickstartFromString("url --url=http://dl.fedoraproject.com\n" @@ -285,7 +285,7 @@ class CreatorTest(unittest.TestCase): def disk_size_reqpart_test(self): """Test calculating the disk size with reqpart and a / partition""" - opts = DataHolder(no_virt=True, make_fsimage=False, make_iso=False, make_pxe_live=False) + opts = DataHolder(no_virt=True, make_fsimage=False, make_iso=False, make_pxe_live=False, image_size_align=0) ks_version = makeVersion() ks = KickstartParser(ks_version, errorsAreFatal=False, missingIncludeIsFatal=False) ks.readKickstartFromString("url --url=http://dl.fedoraproject.com\n" @@ -298,7 +298,7 @@ class CreatorTest(unittest.TestCase): def disk_size_reqpart_boot_test(self): """Test calculating the disk size with reqpart --add-boot and a / partition""" - opts = DataHolder(no_virt=True, make_fsimage=False, make_iso=False, make_pxe_live=False) + opts = DataHolder(no_virt=True, make_fsimage=False, make_iso=False, make_pxe_live=False, image_size_align=0) ks_version = makeVersion() ks = KickstartParser(ks_version, errorsAreFatal=False, missingIncludeIsFatal=False) ks.readKickstartFromString("url --url=http://dl.fedoraproject.com\n" @@ -309,6 +309,17 @@ class CreatorTest(unittest.TestCase): "shutdown\n") self.assertEqual(calculate_disk_size(opts, ks), 5622) + def disk_size_align_test(self): + """Test aligning the disk size""" + opts = DataHolder(no_virt=True, make_fsimage=False, make_iso=False, make_pxe_live=False, image_size_align=1024) + ks_version = makeVersion() + ks = KickstartParser(ks_version, errorsAreFatal=False, missingIncludeIsFatal=False) + ks.readKickstartFromString("url --url=http://dl.fedoraproject.com\n" + "network --bootproto=dhcp --activate\n" + "repo --name=other --baseurl=http://dl.fedoraproject.com\n" + "part / --size=4096\n" + "shutdown\n") + self.assertEqual(calculate_disk_size(opts, ks), 5120) @unittest.skipUnless(os.geteuid() == 0 and not os.path.exists("/.in-container"), "requires root privileges, and no containers") def boot_over_root_test(self):