예제 #1
0
    def setUp(self):
        disk1 = DiskDevice("testdisk", size=Size("300 GiB"), exists=True,
                           fmt=get_format("disklabel", exists=True))
        disk1.format._supported = False

        with self.assertLogs("blivet", level="INFO") as cm:
            partition1 = PartitionDevice("testpart1", size=Size("150 GiB"), exists=True,
                                         parents=[disk1], fmt=get_format("ext4", exists=True))
        self.assertTrue("disklabel is unsupported" in "\n".join(cm.output))

        with self.assertLogs("blivet", level="INFO") as cm:
            partition2 = PartitionDevice("testpart2", size=Size("100 GiB"), exists=True,
                                         parents=[disk1], fmt=get_format("lvmpv", exists=True))
        self.assertTrue("disklabel is unsupported" in "\n".join(cm.output))

        # To be supported, all of a devices ancestors must be supported.
        disk2 = DiskDevice("testdisk2", size=Size("300 GiB"), exists=True,
                           fmt=get_format("lvmpv", exists=True))

        vg = LVMVolumeGroupDevice("testvg", exists=True, parents=[partition2, disk2])

        lv = LVMLogicalVolumeDevice("testlv", exists=True, size=Size("64 GiB"),
                                    parents=[vg], fmt=get_format("ext4", exists=True))

        with sparsetmpfile("addparttest", Size("50 MiB")) as disk_file:
            disk3 = DiskFile(disk_file)
            disk3.format = get_format("disklabel", device=disk3.path, exists=False)

        self.disk1 = disk1
        self.disk2 = disk2
        self.disk3 = disk3
        self.partition1 = partition1
        self.partition2 = partition2
        self.vg = vg
        self.lv = lv
예제 #2
0
    def test_msdos_disk_chunk1(self):
        disk_size = Size("100 MiB")
        with sparsetmpfile("chunktest", disk_size) as disk_file:
            disk = DiskFile(disk_file)
            disk.format = get_format("disklabel",
                                     device=disk.path,
                                     exists=False,
                                     label_type="msdos")

            p1 = PartitionDevice("p1", size=Size("10 MiB"), grow=True)
            p2 = PartitionDevice("p2", size=Size("30 MiB"), grow=True)

            disks = [disk]
            partitions = [p1, p2]
            free = get_free_regions([disk])
            self.assertEqual(len(free), 1,
                             "free region count %d not expected" % len(free))

            b = Mock(spec=Blivet)
            allocate_partitions(b, disks, partitions, free)

            requests = [PartitionRequest(p) for p in partitions]
            chunk = DiskChunk(free[0], requests=requests)

            # parted reports a first free sector of 32 for msdos on disk files. whatever.
            # XXX on gpt, the start is increased to 34 and the end is reduced from 204799 to 204766,
            #     yielding an expected length of 204733
            length_expected = 204768
            self.assertEqual(chunk.length, length_expected)

            base_expected = sum(p.parted_partition.geometry.length
                                for p in partitions)
            self.assertEqual(chunk.base, base_expected)

            pool_expected = chunk.length - base_expected
            self.assertEqual(chunk.pool, pool_expected)

            self.assertEqual(chunk.done, False)
            self.assertEqual(chunk.remaining, 2)

            chunk.grow_requests()

            self.assertEqual(chunk.done, True)
            self.assertEqual(chunk.pool, 0)
            self.assertEqual(chunk.remaining, 2)

            #
            # validate the growth (everything in sectors)
            #
            # The chunk length is 204768. The base of p1 is 20480. The base of
            # p2 is 61440. The chunk has a base of 81920 and a pool of 122848.
            #
            # p1 should grow by 30712 while p2 grows by 92136 since p2's base
            # size is exactly three times that of p1.
            self.assertEqual(requests[0].growth, 30712)
            self.assertEqual(requests[1].growth, 92136)
예제 #3
0
    def test_msdos_disk_chunk1(self):
        disk_size = Size("100 MiB")
        with sparsetmpfile("chunktest", disk_size) as disk_file:
            disk = DiskFile(disk_file)
            disk.format = get_format("disklabel", device=disk.path, exists=False, label_type="msdos")

            p1 = PartitionDevice("p1", size=Size("10 MiB"), grow=True)
            p2 = PartitionDevice("p2", size=Size("30 MiB"), grow=True)

            disks = [disk]
            partitions = [p1, p2]
            free = get_free_regions([disk])
            self.assertEqual(len(free), 1,
                             "free region count %d not expected" % len(free))

            b = Mock(spec=Blivet)
            allocate_partitions(b, disks, partitions, free)

            requests = [PartitionRequest(p) for p in partitions]
            chunk = DiskChunk(free[0], requests=requests)

            # parted reports a first free sector of 32 for msdos on disk files. whatever.
            # XXX on gpt, the start is increased to 34 and the end is reduced from 204799 to 204766,
            #     yielding an expected length of 204733
            length_expected = 204768
            self.assertEqual(chunk.length, length_expected)

            base_expected = sum(p.parted_partition.geometry.length for p in partitions)
            self.assertEqual(chunk.base, base_expected)

            pool_expected = chunk.length - base_expected
            self.assertEqual(chunk.pool, pool_expected)

            self.assertEqual(chunk.done, False)
            self.assertEqual(chunk.remaining, 2)

            chunk.grow_requests()

            self.assertEqual(chunk.done, True)
            self.assertEqual(chunk.pool, 0)
            self.assertEqual(chunk.remaining, 2)

            #
            # validate the growth (everything in sectors)
            #
            # The chunk length is 204768. The base of p1 is 20480. The base of
            # p2 is 61440. The chunk has a base of 81920 and a pool of 122848.
            #
            # p1 should grow by 30712 while p2 grows by 92136 since p2's base
            # size is exactly three times that of p1.
            self.assertEqual(requests[0].growth, 30712)
            self.assertEqual(requests[1].growth, 92136)
예제 #4
0
    def setUp(self):
        disk1 = DiskDevice("testdisk",
                           size=Size("300 GiB"),
                           exists=True,
                           fmt=get_format("disklabel", exists=True))
        disk1.format._supported = False

        with self.assertLogs("blivet", level="INFO") as cm:
            partition1 = PartitionDevice("testpart1",
                                         size=Size("150 GiB"),
                                         exists=True,
                                         parents=[disk1],
                                         fmt=get_format("ext4", exists=True))
        self.assertTrue("disklabel is unsupported" in "\n".join(cm.output))

        with self.assertLogs("blivet", level="INFO") as cm:
            partition2 = PartitionDevice("testpart2",
                                         size=Size("100 GiB"),
                                         exists=True,
                                         parents=[disk1],
                                         fmt=get_format("lvmpv", exists=True))
        self.assertTrue("disklabel is unsupported" in "\n".join(cm.output))

        # To be supported, all of a devices ancestors must be supported.
        disk2 = DiskDevice("testdisk2",
                           size=Size("300 GiB"),
                           exists=True,
                           fmt=get_format("lvmpv", exists=True))

        vg = LVMVolumeGroupDevice("testvg",
                                  exists=True,
                                  parents=[partition2, disk2])

        lv = LVMLogicalVolumeDevice("testlv",
                                    exists=True,
                                    size=Size("64 GiB"),
                                    parents=[vg],
                                    fmt=get_format("ext4", exists=True))

        with sparsetmpfile("addparttest", Size("50 MiB")) as disk_file:
            disk3 = DiskFile(disk_file)
            disk3.format = get_format("disklabel",
                                      device=disk3.path,
                                      exists=False)

        self.disk1 = disk1
        self.disk2 = disk2
        self.disk3 = disk3
        self.partition1 = partition1
        self.partition2 = partition2
        self.vg = vg
        self.lv = lv
예제 #5
0
    def test_extended_min_size(self):
        with sparsetmpfile("extendedtest", Size("10 MiB")) as disk_file:
            disk = DiskFile(disk_file)
            disk.format = get_format("disklabel",
                                     device=disk.path,
                                     label_type="msdos")
            grain_size = Size(disk.format.alignment.grainSize)
            sector_size = Size(disk.format.parted_device.sectorSize)

            extended_start = int(grain_size)
            extended_end = extended_start + int(Size("6 MiB") / sector_size)
            disk.format.add_partition(extended_start, extended_end,
                                      parted.PARTITION_EXTENDED)
            extended = disk.format.extended_partition
            self.assertNotEqual(extended, None)

            extended_device = PartitionDevice(os.path.basename(extended.path))
            extended_device.disk = disk
            extended_device.exists = True
            extended_device.parted_partition = extended

            # existing extended partition should be always resizable
            self.assertTrue(extended_device.resizable)

            # no logical partitions --> min size should be max of 1 KiB and grain_size
            self.assertEqual(
                extended_device.min_size,
                extended_device.align_target_size(
                    max(grain_size, Size("1 KiB"))))

            logical_start = extended_start + 1
            logical_end = extended_end // 2
            disk.format.add_partition(logical_start, logical_end,
                                      parted.PARTITION_LOGICAL)
            logical = disk.format.parted_disk.getPartitionBySector(
                logical_start)
            self.assertNotEqual(logical, None)

            logical_device = PartitionDevice(os.path.basename(logical.path))
            logical_device.disk = disk
            logical_device.exists = True
            logical_device.parted_partition = logical

            # logical partition present --> min size should be based on its end sector
            end_free = (extended_end - logical_end) * sector_size
            self.assertEqual(
                extended_device.min_size,
                extended_device.align_target_size(
                    extended_device.current_size - end_free))
예제 #6
0
    def test_extended_min_size(self):
        with sparsetmpfile("extendedtest", Size("10 MiB")) as disk_file:
            disk = DiskFile(disk_file)
            disk.format = get_format("disklabel", device=disk.path, label_type="msdos")
            grain_size = Size(disk.format.alignment.grainSize)
            sector_size = Size(disk.format.parted_device.sectorSize)

            extended_start = int(grain_size)
            extended_end = extended_start + int(Size("6 MiB") / sector_size)
            disk.format.add_partition(extended_start, extended_end, parted.PARTITION_EXTENDED)
            extended = disk.format.extended_partition
            self.assertNotEqual(extended, None)

            extended_device = PartitionDevice(os.path.basename(extended.path))
            extended_device.disk = disk
            extended_device.exists = True
            extended_device.parted_partition = extended

            # no logical partitions --> min size should be max of 1 KiB and grain_size
            self.assertEqual(extended_device.min_size,
                             extended_device.align_target_size(max(grain_size, Size("1 KiB"))))

            logical_start = extended_start + 1
            logical_end = extended_end // 2
            disk.format.add_partition(logical_start, logical_end, parted.PARTITION_LOGICAL)
            logical = disk.format.parted_disk.getPartitionBySector(logical_start)
            self.assertNotEqual(logical, None)

            logical_device = PartitionDevice(os.path.basename(logical.path))
            logical_device.disk = disk
            logical_device.exists = True
            logical_device.parted_partition = logical

            # logical partition present --> min size should be based on its end sector
            end_free = (extended_end - logical_end) * sector_size
            self.assertEqual(extended_device.min_size,
                             extended_device.align_target_size(extended_device.current_size - end_free))
예제 #7
0
    def test_msdos_disk_chunk2(self):
        disk_size = Size("100 MiB")
        with sparsetmpfile("chunktest", disk_size) as disk_file:
            disk = DiskFile(disk_file)
            disk.format = get_format("disklabel", device=disk.path, exists=False, label_type="msdos")

            p1 = PartitionDevice("p1", size=Size("10 MiB"), grow=True)
            p2 = PartitionDevice("p2", size=Size("30 MiB"), grow=True)

            # format max size should be reflected in request max growth
            fmt = get_format("dummy")
            fmt._max_size = Size("12 MiB")
            p3 = PartitionDevice("p3", size=Size("10 MiB"), grow=True,
                                 fmt=fmt)

            p4 = PartitionDevice("p4", size=Size("7 MiB"))

            # partition max size should be reflected in request max growth
            p5 = PartitionDevice("p5", size=Size("5 MiB"), grow=True,
                                 maxsize=Size("6 MiB"))

            disks = [disk]
            partitions = [p1, p2, p3, p4, p5]
            free = get_free_regions([disk])
            self.assertEqual(len(free), 1,
                             "free region count %d not expected" % len(free))

            b = Mock(spec=Blivet)
            allocate_partitions(b, disks, partitions, free)

            requests = [PartitionRequest(p) for p in partitions]
            chunk = DiskChunk(free[0], requests=requests)

            self.assertEqual(len(chunk.requests), len(partitions))

            # parted reports a first free sector of 32 for disk files. whatever.
            length_expected = 204768
            self.assertEqual(chunk.length, length_expected)

            growable = [p for p in partitions if p.req_grow]
            fixed = [p for p in partitions if not p.req_grow]
            base_expected = sum(p.parted_partition.geometry.length for p in growable)
            self.assertEqual(chunk.base, base_expected)

            base_fixed = sum(p.parted_partition.geometry.length for p in fixed)
            pool_expected = chunk.length - base_expected - base_fixed
            self.assertEqual(chunk.pool, pool_expected)

            self.assertEqual(chunk.done, False)

            # since p5 is not growable it is initially done
            self.assertEqual(chunk.remaining, 4)

            chunk.grow_requests()

            #
            # validate the growth (in sectors)
            #
            # The chunk length is 204768.
            # Request bases:
            #   p1 20480
            #   p2 61440
            #   p3 20480
            #   p4 14336 (not included in chunk base since it isn't growable)
            #   p5 10240
            #
            # The chunk has a base 112640 and a pool of 77792.
            #
            # Request max growth:
            #   p1 0
            #   p2 0
            #   p3 4096
            #   p4 0
            #   p5 2048
            #
            # The first round should allocate to p1, p2, p3, p5 at a ratio of
            # 2:6:2:1, which is 14144, 42432, 14144, 7072. Due to max growth,
            # p3 and p5 will be limited and the extra (10048, 5024) will remain
            # in the pool. In the second round the remaining requests will be
            # p1 and p2. They will divide up the pool of 15072 at a ratio of
            # 1:3, which is 3768 and 11304. At this point the pool should be
            # empty.
            #
            # Total growth:
            #   p1 17912
            #   p2 53736
            #   p3 4096
            #   p4 0
            #   p5 2048
            #
            self.assertEqual(chunk.done, True)
            self.assertEqual(chunk.pool, 0)
            self.assertEqual(chunk.remaining, 2)    # p1, p2 have no max

            # chunk.requests got sorted, so use the list whose order we know
            self.assertEqual(requests[0].growth, 17912)
            self.assertEqual(requests[1].growth, 53736)
            self.assertEqual(requests[2].growth, 4096)
            self.assertEqual(requests[3].growth, 0)
            self.assertEqual(requests[4].growth, 2048)
예제 #8
0
    def test_add_partition(self):
        with sparsetmpfile("addparttest", Size("50 MiB")) as disk_file:
            disk = DiskFile(disk_file)
            disk.format = get_format("disklabel", device=disk.path, exists=False, label_type="msdos")

            free = disk.format.parted_disk.getFreeSpaceRegions()[0]

            #
            # add a partition with an unaligned size
            #
            self.assertEqual(len(disk.format.partitions), 0)
            part = add_partition(disk.format, free, parted.PARTITION_NORMAL,
                                 Size("10 MiB") - Size(37))
            self.assertEqual(len(disk.format.partitions), 1)

            # an unaligned size still yields an aligned partition
            alignment = disk.format.alignment
            geom = part.geometry
            sector_size = Size(geom.device.sectorSize)
            self.assertEqual(alignment.isAligned(free, geom.start), True)
            self.assertEqual(alignment.isAligned(free, geom.end + 1), True)
            self.assertEqual(part.geometry.length, int(Size("10 MiB") // sector_size))

            disk.format.remove_partition(part)
            self.assertEqual(len(disk.format.partitions), 0)

            #
            # adding a partition smaller than the optimal io size should yield
            # a partition aligned using the minimal io size instead
            #
            opt_str = 'parted.Device.optimumAlignment'
            min_str = 'parted.Device.minimumAlignment'
            opt_al = parted.Alignment(offset=0, grainSize=8192)  # 4 MiB
            min_al = parted.Alignment(offset=0, grainSize=2048)  # 1 MiB
            with patch(opt_str, opt_al) as optimal, patch(min_str, min_al) as minimal:
                optimal_end = disk.format.get_end_alignment(alignment=optimal)
                minimal_end = disk.format.get_end_alignment(alignment=minimal)

                sector_size = Size(disk.format.sector_size)
                length = 4096  # 2 MiB
                size = Size(sector_size * length)
                part = add_partition(disk.format, free, parted.PARTITION_NORMAL,
                                     size)
                self.assertEqual(part.geometry.length, length)
                self.assertEqual(optimal.isAligned(free, part.geometry.start),
                                 False)
                self.assertEqual(minimal.isAligned(free, part.geometry.start),
                                 True)
                self.assertEqual(optimal_end.isAligned(free, part.geometry.end),
                                 False)
                self.assertEqual(minimal_end.isAligned(free, part.geometry.end),
                                 True)

                disk.format.remove_partition(part)
                self.assertEqual(len(disk.format.partitions), 0)

            #
            # add a partition with an unaligned start sector
            #
            start_sector = 5003
            end_sector = 15001
            part = add_partition(disk.format, free, parted.PARTITION_NORMAL,
                                 None, start_sector, end_sector)
            self.assertEqual(len(disk.format.partitions), 1)

            # start and end sectors are exactly as specified
            self.assertEqual(part.geometry.start, start_sector)
            self.assertEqual(part.geometry.end, end_sector)

            disk.format.remove_partition(part)
            self.assertEqual(len(disk.format.partitions), 0)

            #
            # fail: add a logical partition to a primary free region
            #
            with six.assertRaisesRegex(self, parted.PartitionException,
                                       "no extended partition"):
                part = add_partition(disk.format, free, parted.PARTITION_LOGICAL,
                                     Size("10 MiB"))

            # add an extended partition to the disk
            placeholder = add_partition(disk.format, free,
                                        parted.PARTITION_NORMAL, Size("10 MiB"))
            all_free = disk.format.parted_disk.getFreeSpaceRegions()
            add_partition(disk.format, all_free[1],
                          parted.PARTITION_EXTENDED, Size("30 MiB"),
                          alignment.alignUp(all_free[1],
                                            placeholder.geometry.end))

            disk.format.remove_partition(placeholder)
            self.assertEqual(len(disk.format.partitions), 1)
            all_free = disk.format.parted_disk.getFreeSpaceRegions()

            #
            # add a logical partition to an extended free regions
            #
            part = add_partition(disk.format, all_free[1],
                                 parted.PARTITION_LOGICAL,
                                 Size("10 MiB"), all_free[1].start)
            self.assertEqual(part.type, parted.PARTITION_LOGICAL)

            disk.format.remove_partition(part)
            self.assertEqual(len(disk.format.partitions), 1)

            #
            # fail: add a primary partition to an extended free region
            #
            with six.assertRaisesRegex(self, parted.PartitionException, "overlap"):
                part = add_partition(disk.format, all_free[1],
                                     parted.PARTITION_NORMAL,
                                     Size("10 MiB"), all_free[1].start)
예제 #9
0
    def test_target_size(self):
        with sparsetmpfile("targetsizetest", Size("10 MiB")) as disk_file:
            disk = DiskFile(disk_file)
            disk.format = get_format("disklabel", device=disk.path, label_type="msdos")
            grain_size = Size(disk.format.alignment.grainSize)
            sector_size = Size(disk.format.parted_device.sectorSize)
            start = int(grain_size)
            orig_size = Size("6 MiB")
            end = start + int(orig_size / sector_size) - 1
            disk.format.add_partition(start, end)
            partition = disk.format.parted_disk.getPartitionBySector(start)
            self.assertNotEqual(partition, None)
            self.assertEqual(orig_size, Size(partition.getLength(unit='B')))

            device = PartitionDevice(os.path.basename(partition.path),
                                     size=orig_size)
            device.disk = disk
            device.exists = True
            device.parted_partition = partition

            device.format = get_format("ext4", device=device.path)
            device.format.exists = True
            # grain size should be 1 MiB
            device.format._min_instance_size = Size("2 MiB") + (grain_size / 2)
            device.format._resizable = True

            # Make sure things are as expected to begin with.
            self.assertEqual(device.size, orig_size)
            self.assertEqual(device.min_size, Size("3 MiB"))
            # start sector's at 1 MiB
            self.assertEqual(device.max_size, Size("9 MiB"))

            # ValueError if not Size
            with six.assertRaisesRegex(self, ValueError,
                                       "new size must.*type Size"):
                device.target_size = 22

            self.assertEqual(device.target_size, orig_size)

            # ValueError if size smaller than min_size
            with six.assertRaisesRegex(self, ValueError,
                                       "size.*smaller than the minimum"):
                device.target_size = Size("1 MiB")

            self.assertEqual(device.target_size, orig_size)

            # ValueError if size larger than max_size
            with six.assertRaisesRegex(self, ValueError,
                                       "size.*larger than the maximum"):
                device.target_size = Size("11 MiB")

            self.assertEqual(device.target_size, orig_size)

            # ValueError if unaligned
            with six.assertRaisesRegex(self, ValueError, "new size.*not.*aligned"):
                device.target_size = Size("3.1 MiB")

            self.assertEqual(device.target_size, orig_size)

            # successfully set a new target size
            new_target = device.max_size
            device.target_size = new_target
            self.assertEqual(device.target_size, new_target)
            self.assertEqual(device.size, new_target)
            parted_size = Size(device.parted_partition.getLength(unit='B'))
            self.assertEqual(parted_size, device.target_size)

            # reset target size to original size
            device.target_size = orig_size
            self.assertEqual(device.target_size, orig_size)
            self.assertEqual(device.size, orig_size)
            parted_size = Size(device.parted_partition.getLength(unit='B'))
            self.assertEqual(parted_size, device.target_size)
예제 #10
0
    def test_min_max_size_alignment(self):
        with sparsetmpfile("minsizetest", Size("10 MiB")) as disk_file:
            disk = DiskFile(disk_file)
            disk.format = get_format("disklabel", device=disk.path)
            grain_size = Size(disk.format.alignment.grainSize)
            sector_size = Size(disk.format.parted_device.sectorSize)
            start = int(grain_size)
            end = start + int(Size("6 MiB") / sector_size)
            disk.format.add_partition(start, end)
            partition = disk.format.parted_disk.getPartitionBySector(start)
            self.assertNotEqual(partition, None)

            device = PartitionDevice(os.path.basename(partition.path))
            device.disk = disk
            device.exists = True
            device.parted_partition = partition

            # Typical sector size is 512 B.
            # Default optimum alignment grain size is 2048 sectors, or 1 MiB.
            device.format = get_format("ext4", device=device.path)
            device.format.exists = True
            device.format._min_instance_size = Size("2 MiB") + (grain_size / 2)
            device.format._resizable = True

            ##
            # min_size
            ##

            # The end sector based only on format min size should be unaligned.
            min_sectors = int(device.format.min_size / sector_size)
            min_end_sector = partition.geometry.start + min_sectors - 1
            self.assertEqual(
                disk.format.end_alignment.isAligned(partition.geometry,
                                                    min_end_sector),
                False)

            # The end sector based on device min size should be aligned.
            min_sectors = int(device.min_size / sector_size)
            min_end_sector = partition.geometry.start + min_sectors - 1
            self.assertEqual(
                disk.format.end_alignment.isAligned(partition.geometry,
                                                    min_end_sector),
                True)

            ##
            # max_size
            ##

            # Add a partition starting three sectors past an aligned sector and
            # extending to the end of the disk so that there's a free region
            # immediately following the first partition with an unaligned end
            # sector.
            free = disk.format.parted_disk.getFreeSpaceRegions()[-1]
            raw_start = int(Size("9 MiB") / sector_size)
            start = disk.format.alignment.alignUp(free, raw_start) + 3
            disk.format.add_partition(start, disk.format.parted_device.length - 1)

            # Verify the end of the free region immediately following the first
            # partition is unaligned.
            free = disk.format.parted_disk.getFreeSpaceRegions()[1]
            self.assertEqual(disk.format.end_alignment.isAligned(free, free.end),
                             False)

            # The end sector based on device min size should be aligned.
            max_sectors = int(device.max_size / sector_size)
            max_end_sector = partition.geometry.start + max_sectors - 1
            self.assertEqual(
                disk.format.end_alignment.isAligned(free, max_end_sector),
                True)
예제 #11
0
    def test_disk_chunk2(self):
        disk_size = Size("100 MiB")
        with sparsetmpfile("chunktest", disk_size) as disk_file:
            disk = DiskFile(disk_file)
            disk.format = get_format("disklabel",
                                     device=disk.path,
                                     exists=False)

            p1 = PartitionDevice("p1", size=Size("10 MiB"), grow=True)
            p2 = PartitionDevice("p2", size=Size("30 MiB"), grow=True)

            # format max size should be reflected in request max growth
            fmt = get_format("dummy")
            fmt._max_size = Size("12 MiB")
            p3 = PartitionDevice("p3", size=Size("10 MiB"), grow=True, fmt=fmt)

            p4 = PartitionDevice("p4", size=Size("7 MiB"))

            # partition max size should be reflected in request max growth
            p5 = PartitionDevice("p5",
                                 size=Size("5 MiB"),
                                 grow=True,
                                 maxsize=Size("6 MiB"))

            disks = [disk]
            partitions = [p1, p2, p3, p4, p5]
            free = get_free_regions([disk])
            self.assertEqual(len(free), 1,
                             "free region count %d not expected" % len(free))

            b = Mock(spec=Blivet)
            allocate_partitions(b, disks, partitions, free)

            requests = [PartitionRequest(p) for p in partitions]
            chunk = DiskChunk(free[0], requests=requests)

            self.assertEqual(len(chunk.requests), len(partitions))

            # parted reports a first free sector of 32 for disk files. whatever.
            length_expected = 204768
            self.assertEqual(chunk.length, length_expected)

            growable = [p for p in partitions if p.req_grow]
            fixed = [p for p in partitions if not p.req_grow]
            base_expected = sum(p.parted_partition.geometry.length
                                for p in growable)
            self.assertEqual(chunk.base, base_expected)

            base_fixed = sum(p.parted_partition.geometry.length for p in fixed)
            pool_expected = chunk.length - base_expected - base_fixed
            self.assertEqual(chunk.pool, pool_expected)

            self.assertEqual(chunk.done, False)

            # since p5 is not growable it is initially done
            self.assertEqual(chunk.remaining, 4)

            chunk.grow_requests()

            #
            # validate the growth (in sectors)
            #
            # The chunk length is 204768.
            # Request bases:
            #   p1 20480
            #   p2 61440
            #   p3 20480
            #   p4 14336 (not included in chunk base since it isn't growable)
            #   p5 10240
            #
            # The chunk has a base 112640 and a pool of 77792.
            #
            # Request max growth:
            #   p1 0
            #   p2 0
            #   p3 4096
            #   p4 0
            #   p5 2048
            #
            # The first round should allocate to p1, p2, p3, p5 at a ratio of
            # 2:6:2:1, which is 14144, 42432, 14144, 7072. Due to max growth,
            # p3 and p5 will be limited and the extra (10048, 5024) will remain
            # in the pool. In the second round the remaining requests will be
            # p1 and p2. They will divide up the pool of 15072 at a ratio of
            # 1:3, which is 3768 and 11304. At this point the pool should be
            # empty.
            #
            # Total growth:
            #   p1 17912
            #   p2 53736
            #   p3 4096
            #   p4 0
            #   p5 2048
            #
            self.assertEqual(chunk.done, True)
            self.assertEqual(chunk.pool, 0)
            self.assertEqual(chunk.remaining, 2)  # p1, p2 have no max

            # chunk.requests got sorted, so use the list whose order we know
            self.assertEqual(requests[0].growth, 17912)
            self.assertEqual(requests[1].growth, 53736)
            self.assertEqual(requests[2].growth, 4096)
            self.assertEqual(requests[3].growth, 0)
            self.assertEqual(requests[4].growth, 2048)
예제 #12
0
    def test_add_partition(self):
        with sparsetmpfile("addparttest", Size("50 MiB")) as disk_file:
            disk = DiskFile(disk_file)
            disk.format = get_format("disklabel",
                                     device=disk.path,
                                     exists=False)

            free = disk.format.parted_disk.getFreeSpaceRegions()[0]

            #
            # add a partition with an unaligned size
            #
            self.assertEqual(len(disk.format.partitions), 0)
            part = add_partition(disk.format, free, parted.PARTITION_NORMAL,
                                 Size("10 MiB") - Size(37))
            self.assertEqual(len(disk.format.partitions), 1)

            # an unaligned size still yields an aligned partition
            alignment = disk.format.alignment
            geom = part.geometry
            sector_size = Size(geom.device.sectorSize)
            self.assertEqual(alignment.isAligned(free, geom.start), True)
            self.assertEqual(alignment.isAligned(free, geom.end + 1), True)
            self.assertEqual(part.geometry.length,
                             int(Size("10 MiB") // sector_size))

            disk.format.remove_partition(part)
            self.assertEqual(len(disk.format.partitions), 0)

            #
            # adding a partition smaller than the optimal io size should yield
            # a partition aligned using the minimal io size instead
            #
            opt_str = 'parted.Device.optimumAlignment'
            min_str = 'parted.Device.minimumAlignment'
            opt_al = parted.Alignment(offset=0, grainSize=8192)  # 4 MiB
            min_al = parted.Alignment(offset=0, grainSize=2048)  # 1 MiB
            with patch(opt_str, opt_al) as optimal, patch(min_str,
                                                          min_al) as minimal:
                optimal_end = disk.format.get_end_alignment(alignment=optimal)
                minimal_end = disk.format.get_end_alignment(alignment=minimal)

                sector_size = Size(disk.format.sector_size)
                length = 4096  # 2 MiB
                size = Size(sector_size * length)
                part = add_partition(disk.format, free,
                                     parted.PARTITION_NORMAL, size)
                self.assertEqual(part.geometry.length, length)
                self.assertEqual(optimal.isAligned(free, part.geometry.start),
                                 False)
                self.assertEqual(minimal.isAligned(free, part.geometry.start),
                                 True)
                self.assertEqual(
                    optimal_end.isAligned(free, part.geometry.end), False)
                self.assertEqual(
                    minimal_end.isAligned(free, part.geometry.end), True)

                disk.format.remove_partition(part)
                self.assertEqual(len(disk.format.partitions), 0)

            #
            # add a partition with an unaligned start sector
            #
            start_sector = 5003
            end_sector = 15001
            part = add_partition(disk.format, free, parted.PARTITION_NORMAL,
                                 None, start_sector, end_sector)
            self.assertEqual(len(disk.format.partitions), 1)

            # start and end sectors are exactly as specified
            self.assertEqual(part.geometry.start, start_sector)
            self.assertEqual(part.geometry.end, end_sector)

            disk.format.remove_partition(part)
            self.assertEqual(len(disk.format.partitions), 0)

            #
            # fail: add a logical partition to a primary free region
            #
            with self.assertRaisesRegex(parted.PartitionException,
                                        "no extended partition"):
                part = add_partition(disk.format, free,
                                     parted.PARTITION_LOGICAL, Size("10 MiB"))

            # add an extended partition to the disk
            placeholder = add_partition(disk.format,
                                        free, parted.PARTITION_NORMAL,
                                        Size("10 MiB"))
            all_free = disk.format.parted_disk.getFreeSpaceRegions()
            add_partition(
                disk.format, all_free[1], parted.PARTITION_EXTENDED,
                Size("30 MiB"),
                alignment.alignUp(all_free[1], placeholder.geometry.end))

            disk.format.remove_partition(placeholder)
            self.assertEqual(len(disk.format.partitions), 1)
            all_free = disk.format.parted_disk.getFreeSpaceRegions()

            #
            # add a logical partition to an extended free regions
            #
            part = add_partition(disk.format,
                                 all_free[1], parted.PARTITION_LOGICAL,
                                 Size("10 MiB"), all_free[1].start)
            self.assertEqual(part.type, parted.PARTITION_LOGICAL)

            disk.format.remove_partition(part)
            self.assertEqual(len(disk.format.partitions), 1)

            #
            # fail: add a primary partition to an extended free region
            #
            with self.assertRaisesRegex(parted.PartitionException, "overlap"):
                part = add_partition(disk.format,
                                     all_free[1], parted.PARTITION_NORMAL,
                                     Size("10 MiB"), all_free[1].start)
예제 #13
0
    def testAddPartition(self):
        with sparsetmpfile("addparttest", Size("50 MiB")) as disk_file:
            disk = DiskFile(disk_file)
            disk.format = getFormat("disklabel", device=disk.path, exists=False)

            free = disk.format.partedDisk.getFreeSpaceRegions()[0]

            #
            # add a partition with an unaligned size
            #
            self.assertEqual(len(disk.format.partitions), 0)
            part = addPartition(disk.format, free, parted.PARTITION_NORMAL,
                                Size("10 MiB") - Size(37))
            self.assertEqual(len(disk.format.partitions), 1)

            # an unaligned size still yields an aligned partition
            alignment = disk.format.alignment
            geom = part.geometry
            sector_size = Size(geom.device.sectorSize)
            self.assertEqual(alignment.isAligned(free, geom.start), True)
            self.assertEqual(alignment.isAligned(free, geom.end + 1), True)
            self.assertEqual(part.geometry.length, int(Size("10 MiB") // sector_size))

            disk.format.removePartition(part)
            self.assertEqual(len(disk.format.partitions), 0)

            #
            # add a partition with an unaligned start sector
            #
            start_sector = 5003
            end_sector = 15001
            part = addPartition(disk.format, free, parted.PARTITION_NORMAL,
                                None, start_sector, end_sector)
            self.assertEqual(len(disk.format.partitions), 1)

            # start and end sectors are exactly as specified
            self.assertEqual(part.geometry.start, start_sector)
            self.assertEqual(part.geometry.end, end_sector)

            disk.format.removePartition(part)
            self.assertEqual(len(disk.format.partitions), 0)

            #
            # fail: add a logical partition to a primary free region
            #
            with self.assertRaisesRegex(parted.PartitionException,
                                         "no extended partition"):
                part = addPartition(disk.format, free, parted.PARTITION_LOGICAL,
                                    Size("10 MiB"))

            ## add an extended partition to the disk
            placeholder = addPartition(disk.format, free,
                                       parted.PARTITION_NORMAL, Size("10 MiB"))
            all_free = disk.format.partedDisk.getFreeSpaceRegions()
            addPartition(disk.format, all_free[1],
                         parted.PARTITION_EXTENDED, Size("30 MiB"),
                         alignment.alignUp(all_free[1],
                                           placeholder.geometry.end))

            disk.format.removePartition(placeholder)
            self.assertEqual(len(disk.format.partitions), 1)
            all_free = disk.format.partedDisk.getFreeSpaceRegions()

            #
            # add a logical partition to an extended free regions
            #
            part = addPartition(disk.format, all_free[1],
                                parted.PARTITION_LOGICAL,
                                Size("10 MiB"), all_free[1].start)
            self.assertEqual(part.type, parted.PARTITION_LOGICAL)

            disk.format.removePartition(part)
            self.assertEqual(len(disk.format.partitions), 1)

            #
            # fail: add a primary partition to an extended free region
            #
            with self.assertRaisesRegex(parted.PartitionException, "overlap"):
                part = addPartition(disk.format, all_free[1],
                                    parted.PARTITION_NORMAL,
                                    Size("10 MiB"), all_free[1].start)
예제 #14
0
    def testAddPartition(self):
        with sparsetmpfile("addparttest", Size("50 MiB")) as disk_file:
            disk = DiskFile(disk_file)
            disk.format = getFormat("disklabel", device=disk.path, exists=False)

            free = disk.format.partedDisk.getFreeSpaceRegions()[0]

            #
            # add a partition with an unaligned size
            #
            self.assertEqual(len(disk.format.partitions), 0)
            part = addPartition(disk.format, free, parted.PARTITION_NORMAL,
                                Size("10 MiB") - Size(37))
            self.assertEqual(len(disk.format.partitions), 1)

            # an unaligned size still yields an aligned partition
            alignment = disk.format.alignment
            geom = part.geometry
            sector_size = Size(geom.device.sectorSize)
            self.assertEqual(alignment.isAligned(free, geom.start), True)
            self.assertEqual(alignment.isAligned(free, geom.end + 1), True)
            self.assertEqual(part.geometry.length, int(Size("10 MiB") // sector_size))

            disk.format.removePartition(part)
            self.assertEqual(len(disk.format.partitions), 0)

            #
            # add a partition with an unaligned start sector
            #
            start_sector = 5003
            end_sector = 15001
            part = addPartition(disk.format, free, parted.PARTITION_NORMAL,
                                None, start_sector, end_sector)
            self.assertEqual(len(disk.format.partitions), 1)

            # start and end sectors are exactly as specified
            self.assertEqual(part.geometry.start, start_sector)
            self.assertEqual(part.geometry.end, end_sector)

            disk.format.removePartition(part)
            self.assertEqual(len(disk.format.partitions), 0)

            #
            # fail: add a logical partition to a primary free region
            #
            with self.assertRaisesRegex(parted.PartitionException,
                                         "no extended partition"):
                part = addPartition(disk.format, free, parted.PARTITION_LOGICAL,
                                    Size("10 MiB"))

            ## add an extended partition to the disk
            placeholder = addPartition(disk.format, free,
                                       parted.PARTITION_NORMAL, Size("10 MiB"))
            all_free = disk.format.partedDisk.getFreeSpaceRegions()
            addPartition(disk.format, all_free[1],
                         parted.PARTITION_EXTENDED, Size("30 MiB"),
                         alignment.alignUp(all_free[1],
                                           placeholder.geometry.end))

            disk.format.removePartition(placeholder)
            self.assertEqual(len(disk.format.partitions), 1)
            all_free = disk.format.partedDisk.getFreeSpaceRegions()

            #
            # add a logical partition to an extended free regions
            #
            part = addPartition(disk.format, all_free[1],
                                parted.PARTITION_LOGICAL,
                                Size("10 MiB"), all_free[1].start)
            self.assertEqual(part.type, parted.PARTITION_LOGICAL)

            disk.format.removePartition(part)
            self.assertEqual(len(disk.format.partitions), 1)

            #
            # fail: add a primary partition to an extended free region
            #
            with self.assertRaisesRegex(parted.PartitionException, "overlap"):
                part = addPartition(disk.format, all_free[1],
                                    parted.PARTITION_NORMAL,
                                    Size("10 MiB"), all_free[1].start)