def test_vgchunk_with_cache_pvfree(self): pv = StorageDevice("pv1", size=Size("40 GiB"), fmt=get_format("lvmpv")) # 1069 MiB so that the PV provides 1068 MiB of free space (see # LVMVolumeGroupDevice.extents) which is 44 MiB more than the caches # need and which should thus be split into the LVs pv2 = StorageDevice("pv2", size=Size("1069 MiB"), fmt=get_format("lvmpv")) vg = LVMVolumeGroupDevice("vg", parents=[pv, pv2]) cache_req1 = LVMCacheRequest(Size("512 MiB"), [pv2], "writethrough") lv1 = LVMLogicalVolumeDevice("lv1", parents=[vg], size=Size("1 GiB"), grow=True, cache_request=cache_req1) cache_req2 = LVMCacheRequest(Size("512 MiB"), [pv2], "writethrough") lv2 = LVMLogicalVolumeDevice("lv2", parents=[vg], size=Size("10 GiB"), grow=True, cache_request=cache_req2) lv3 = LVMLogicalVolumeDevice("lv3", parents=[vg], size=Size("10 GiB"), grow=True, maxsize=Size("12 GiB")) req1 = LVRequest(lv1) req2 = LVRequest(lv2) req3 = LVRequest(lv3) chunk = VGChunk(vg, requests=[req1, req2, req3]) chunk.grow_requests() # the chunk is done growing since its pool has been exhausted self.assertEqual(chunk.done, True) # there are still two requests remaining since lv1 and lv2 have no max self.assertEqual(chunk.remaining, 2) # All the sizes should be the same as without the caches (see the # test_vgchunk test for their "rationales") because the space for the # caches should just be reserved. # The extra 11 extents available on the pv2 should go in the 1:10 ratio # to req1 and req2. self.assertEqual(req1.growth, 395 + 1) self.assertEqual(req2.growth, 3956 + 10) self.assertEqual(req3.growth, 512)
def test_vgchunk(self): pv = StorageDevice("pv1", size=Size("40 GiB"), fmt=get_format("lvmpv")) vg = LVMVolumeGroupDevice("vg", parents=[pv]) lv1 = LVMLogicalVolumeDevice("lv1", parents=[vg], size=Size("1 GiB"), grow=True) lv2 = LVMLogicalVolumeDevice("lv2", parents=[vg], size=Size("10 GiB"), grow=True) lv3 = LVMLogicalVolumeDevice("lv3", parents=[vg], size=Size("10 GiB"), grow=True, maxsize=Size("12 GiB")) req1 = LVRequest(lv1) req2 = LVRequest(lv2) req3 = LVRequest(lv3) chunk = VGChunk(vg, requests=[req1, req2, req3]) self.assertEqual(chunk.length, vg.extents) self.assertEqual(chunk.pool, vg.free_extents) base_size = vg.align(sum((lv.size for lv in vg.lvs), Size(0)), roundup=True) base = base_size / vg.pe_size self.assertEqual(chunk.base, base) # default extent size is 4 MiB self.assertEqual(chunk.length_to_size(4), Size("16 MiB")) self.assertEqual(chunk.size_to_length(Size("33 MiB")), 8) self.assertEqual(chunk.has_growable, True) self.assertEqual(chunk.remaining, 3) self.assertEqual(chunk.done, False) chunk.grow_requests() # the chunk is done growing since its pool has been exhausted self.assertEqual(chunk.done, True) # there are still two requests remaining since lv1 and lv2 have no max self.assertEqual(chunk.remaining, 2) # # validate the resulting growth # # lv1 has size 1 GiB (256 extents) and is growable with no limit # lv2 has size 10 GiB (2560 extents) and is growable with no limit # lv3 has size 10 GiB (2560 extents) and is growable with a max size of # 12 GiB (max growth of 512 extents) # # The vg initially has 4863 free extents. # The growth ratio should be 1:10:10. # # The first pass through should allocate 231 extents to lv1 and 2315 # extents to each of lv2 and lv3, leaving one remaining extent, but # it should reclaim 1803 extents from lv3 since it has a maximum growth # of 512 extents (2 GiB). # # The second pass should then split up the remaining 1805 extents # between lv1 and lv2 at a ratio of 1:10, which ends up being 164 for # lv1 and 1640 for lv2. The remaining extent goes to lv2 because it is # first in the list after sorting with blivet.partitioning.lv_compare. # # Grand totals should be as follows: # lv1 should grow by 395 extents, or 1.54 GiB # lv2 should grow by 3956 extents, or 15.45 GiB # lv3 should grow by 512 extents, or 2 GiB self.assertEqual(req1.growth, 395) self.assertEqual(req2.growth, 3956) self.assertEqual(req3.growth, 512)