Merge pull request #1346 from dbungert/fix-guided-resize-gap

guided resize: improve post-resize gap handling
This commit is contained in:
Dan Bungert 2022-07-11 20:04:49 -06:00 committed by GitHub
commit aa59399d6c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 1477 additions and 4 deletions

File diff suppressed because it is too large Load Diff

View File

@ -241,3 +241,12 @@ def within(device, gap):
if pg.offset >= gap.offset and pg_end <= gap_end:
return pg
return None
def after(device, offset):
"""Find the first gap that is after this offset."""
for pg in parts_and_gaps(device):
if isinstance(pg, Gap):
if pg.offset > offset:
return pg
return None

View File

@ -135,6 +135,35 @@ class TestWithin(unittest.TestCase):
self.assertEqual(g2, gaps.within(d, orig_g2))
class TestAfter(unittest.TestCase):
def test_basic(self):
d = make_disk()
[gap] = gaps.parts_and_gaps(d)
self.assertEqual(gap, gaps.after(d, 0))
def test_no_equals(self):
d = make_disk()
[gap] = gaps.parts_and_gaps(d)
self.assertIsNone(gaps.after(d, gap.offset))
def test_partition_resize_full_part(self):
m, d = make_model_and_disk()
[g1] = gaps.parts_and_gaps(d)
p1 = make_partition(m, d, size=g1.size)
p1.size //= 2
gap = gaps.after(d, p1.offset)
self.assertIsNotNone(gap)
def test_partition_resize_half_part(self):
m, d = make_model_and_disk()
make_partition(m, d)
[p1, g1] = gaps.parts_and_gaps(d)
p1.size //= 2
gap = gaps.after(d, p1.offset)
self.assertNotEqual(gap, g1)
self.assertTrue(gap.offset < g1.offset)
class TestDiskGaps(unittest.TestCase):
def test_no_partition_gpt(self):

View File

@ -223,11 +223,16 @@ class FilesystemController(SubiquityController, FilesystemManipulator):
new_size = align_up(choice.target.new_size, part_align)
if new_size > partition.size:
raise Exception(f'Aligned requested size {new_size} too large')
gap_offset = partition.offset + new_size
partition.size = new_size
partition.resize = True
mode = 'use_gap'
target = gaps.at_offset(disk, gap_offset)
# Calculating where that gap will be can be tricky due to alignment
# needs and the possibility that we may be splitting a logical
# partition, which needs an extra 1MiB spacer.
target = gaps.after(disk, partition.offset)
if target is None:
pgs = gaps.parts_and_gaps(disk)
raise Exception(f'gap not found after resize, pgs={pgs}')
else:
raise Exception(f'Unknown guided target {choice.target}')

View File

@ -184,8 +184,6 @@ class TestGuidedV2(IsolatedAsyncioTestCase):
use_gap = resp.possible.pop(0)
self.assertEqual(self.disk.id, use_gap.disk_id)
if gap_offset != use_gap.gap.offset:
breakpoint()
self.assertEqual(gap_offset, use_gap.gap.offset)
resize = resp.possible.pop(0)

View File

@ -479,6 +479,20 @@ class TestGuided(TestAPI):
}
self.assertDictSubset(expected_p5, p5)
@timeout()
async def test_guided_v2_resize_logical(self):
cfg = 'examples/threebuntu-on-msdos.json'
extra = ['--storage-version', '2']
async with start_server(cfg, extra_args=extra) as inst:
resp = await inst.get('/storage/v2/guided')
[resize] = match(
resp['possible'], _type='GuidedStorageTargetResize',
partition_number=6)
data = {'target': resize}
resp = await inst.post('/storage/v2/guided', data)
self.assertEqual(resize, resp['configured']['target'])
# should not throw a Gap Not Found exception
class TestAdd(TestAPI):
@timeout()