Merge pull request #1313 from dbungert/largest-gap-multidisk

gaps: allow largest_gap to accept a list
This commit is contained in:
Dan Bungert 2022-06-14 18:16:30 -06:00 committed by GitHub
commit df1a5adf0b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 72 additions and 3 deletions

View File

@ -47,7 +47,7 @@ class Gap:
the supplied size. If size is equal to the gap size, the second gap is the supplied size. If size is equal to the gap size, the second gap is
None. The original gap is unmodified.""" None. The original gap is unmodified."""
if size > self.size: if size > self.size:
raise Exception('requested size larger than gap') raise ValueError('requested size larger than gap')
if size == self.size: if size == self.size:
return (self, None) return (self, None)
first_gap = Gap(device=self.device, first_gap = Gap(device=self.device,
@ -169,7 +169,15 @@ def _parts_and_gaps_vg(device):
return r return r
def largest_gap(device): @functools.singledispatch
def largest_gap(target):
raise NotImplementedError(target)
@largest_gap.register(Disk)
@largest_gap.register(Raid)
@largest_gap.register(LVM_VolGroup)
def _largest_gap_disk(device):
largest_size = 0 largest_size = 0
largest = None largest = None
for pg in parts_and_gaps(device): for pg in parts_and_gaps(device):
@ -180,6 +188,15 @@ def largest_gap(device):
return largest return largest
@largest_gap.register(list)
def _largest_gap_list(disks):
largest = None
for gap in (largest_gap(d) for d in disks):
if largest is None or (gap is not None and gap.size > largest.size):
largest = gap
return largest
def largest_gap_size(device): def largest_gap_size(device):
largest = largest_gap(device) largest = largest_gap(device)
if largest is not None: if largest is not None:

View File

@ -23,6 +23,7 @@ from subiquity.models.filesystem import (
) )
from subiquity.models.tests.test_filesystem import ( from subiquity.models.tests.test_filesystem import (
make_disk, make_disk,
make_model,
make_model_and_disk, make_model_and_disk,
make_partition, make_partition,
) )
@ -45,7 +46,7 @@ class TestSplitGap(unittest.TestCase):
def test_too_big(self): def test_too_big(self):
[gap] = gaps.parts_and_gaps(make_disk()) [gap] = gaps.parts_and_gaps(make_disk())
with self.assertRaises(Exception): with self.assertRaises(ValueError):
gap.split(gap.size + MiB) gap.split(gap.size + MiB)
def test_split(self): def test_split(self):
@ -359,3 +360,54 @@ class TestMovableTrailingPartitionsAndGapSize(unittest.TestCase):
self.assertEqual( self.assertEqual(
([], 0), ([], 0),
gaps.movable_trailing_partitions_and_gap_size(p1)) gaps.movable_trailing_partitions_and_gap_size(p1))
class TestLargestGaps(unittest.TestCase):
def test_basic(self):
d = make_disk()
[gap] = gaps.parts_and_gaps(d)
self.assertEqual(gap, gaps.largest_gap(d))
def test_two_gaps(self):
m, d = make_model_and_disk(size=100 << 20)
m.storage_version = 2
make_partition(m, d, offset=0, size=20 << 20)
make_partition(m, d, offset=40 << 20, size=20 << 20)
[_, g1, _, g2] = gaps.parts_and_gaps(d)
self.assertEqual(g2, gaps.largest_gap(d))
def test_two_disks(self):
m = make_model()
m.storage_version = 2
d1 = make_disk(m, size=100 << 20)
d2 = make_disk(m, size=200 << 20)
[d1g1] = gaps.parts_and_gaps(d1)
[d2g1] = gaps.parts_and_gaps(d2)
self.assertEqual(d1g1, gaps.largest_gap(d1))
self.assertEqual(d2g1, gaps.largest_gap(d2))
def test_across_two_disks(self):
m = make_model()
m.storage_version = 2
d1 = make_disk(m, size=100 << 20)
d2 = make_disk(m, size=200 << 20)
[d2g1] = gaps.parts_and_gaps(d2)
self.assertEqual(d2g1, gaps.largest_gap([d1, d2]))
def test_across_two_disks_one_gap(self):
m = make_model()
m.storage_version = 2
d1 = make_disk(m, size=100 << 20)
d2 = make_disk(m, size=200 << 20)
make_partition(m, d2, offset=0, size=200 << 20)
[d1g1] = gaps.parts_and_gaps(d1)
self.assertEqual(d1g1, gaps.largest_gap([d1, d2]))
def test_across_two_disks_no_gaps(self):
m = make_model()
m.storage_version = 2
d1 = make_disk(m, size=100 << 20)
d2 = make_disk(m, size=200 << 20)
make_partition(m, d1, offset=0, size=100 << 20)
make_partition(m, d2, offset=0, size=200 << 20)
self.assertIsNone(gaps.largest_gap([d1, d2]))