filesystem: fix logical part. using gap outside extended

When defining a partition with size: -1, the partition should expand to
the size of the largest gap. To determine which gap to use, we call the
function largest_gap(partition.disk).

That being said, the gap returned is sometimes bigger than expected when
using a msdos partition table. This happens because we return the
largest gap without checking if it is inside or outside the extended
partition.

Fixed by making sure that:

* for a logical partition, we pick the largest gap within the extended
  partition
* for a primary partition, we pick the largest gap outside the extended
  partition (if any).

Signed-off-by: Olivier Gayot <olivier.gayot@canonical.com>
This commit is contained in:
Olivier Gayot 2022-09-30 12:29:58 +02:00
parent 45a00c0864
commit 73d9ecd1be
2 changed files with 102 additions and 2 deletions

View File

@ -1216,7 +1216,9 @@ class FilesystemModel(object):
from subiquity.common.filesystem.gaps import ( from subiquity.common.filesystem.gaps import (
largest_gap_size, largest_gap_size,
) )
p.size = largest_gap_size(filtered_parent) p.size = largest_gap_size(
filtered_parent,
in_extended=is_logical_partition(p))
elif isinstance(p.size, str): elif isinstance(p.size, str):
if p.size.endswith("%"): if p.size.endswith("%"):
percentage = int(p.size[:-1]) percentage = int(p.size[:-1])

View File

@ -635,7 +635,6 @@ class TestAutoInstallConfig(unittest.TestCase):
'flag': 'logical', 'flag': 'logical',
# p1 (extended) offset + ebr_space # p1 (extended) offset + ebr_space
'offset': start_offset + dehumanize_size('40M') + ebr_space, 'offset': start_offset + dehumanize_size('40M') + ebr_space,
}, },
]) ])
extended = model._one(type="partition", id="part1") extended = model._one(type="partition", id="part1")
@ -643,6 +642,105 @@ class TestAutoInstallConfig(unittest.TestCase):
extended.size, extended.size,
disk.available_for_partitions - dehumanize_size('40M')) disk.available_for_partitions - dehumanize_size('40M'))
def test_logical_partition_remaining_size(self):
model = make_model(bootloader=Bootloader.BIOS, storage_version=2)
disk = make_disk(model, serial='aaaa', size=dehumanize_size("100M"),
ptable='msdos')
ebr_space = disk.alignment_data().ebr_space
start_offset = disk.alignment_data().min_start_offset
fake_up_blockdata(model)
model.apply_autoinstall_config([
{
'type': 'disk',
'id': 'disk0',
},
{
'type': 'partition',
'id': 'part0',
'device': 'disk0',
'size': dehumanize_size('40M'),
'flag': 'extended',
'offset': start_offset,
},
{
'type': 'partition',
'number': 5,
'id': 'part5',
'device': 'disk0',
'size': -1,
'flag': 'logical',
# p0 (extended) offset + ebr_space
'offset': start_offset + ebr_space,
},
])
extended = model._one(type="partition", id="part0")
logical = model._one(type="partition", id="part5")
# At this point, there should be one large gap outside the extended
# partition and one smaller one inside the extended partition.
# Make sure our logical partition picks up the smaller one.
self.assertEqual(logical.size, extended.size - ebr_space)
def test_partition_remaining_size_in_extended_and_logical(self):
model = make_model(bootloader=Bootloader.BIOS, storage_version=2)
disk = make_disk(model, serial='aaaa', size=dehumanize_size("100M"),
ptable='msdos')
ebr_space = disk.alignment_data().ebr_space
start_offset = disk.alignment_data().min_start_offset
fake_up_blockdata(model)
model.apply_autoinstall_config([
{
'type': 'disk',
'id': 'disk0',
},
{
'type': 'partition',
'id': 'part0',
'device': 'disk0',
'size': dehumanize_size('40M'),
'offset': start_offset,
},
{
'type': 'partition',
'id': 'part1',
'device': 'disk0',
'size': -1,
'flag': 'extended',
# p0 offset + size of p0
'offset': start_offset + dehumanize_size('40M'),
},
{
'type': 'partition',
'number': 5,
'id': 'part5',
'device': 'disk0',
'size': dehumanize_size('10M'),
'flag': 'logical',
# p1 offset + ebr_space
'offset': start_offset + dehumanize_size('40M') + ebr_space,
},
{
'type': 'partition',
'number': 6,
'id': 'part6',
'device': 'disk0',
'size': -1,
'flag': 'logical',
# p5 offset + p5 size + ebr_space
'offset': start_offset + dehumanize_size('40M') + ebr_space \
+ dehumanize_size('10M') + ebr_space
},
])
extended = model._one(type="partition", id="part1")
p5 = model._one(type="partition", id="part5")
p6 = model._one(type="partition", id="part6")
self.assertEqual(
extended.size,
disk.available_for_partitions - dehumanize_size('40M'))
self.assertEqual(
p6.size,
extended.size - p5.size - 2 * ebr_space)
def test_lv_percent(self): def test_lv_percent(self):
model = make_model() model = make_model()
make_disk(model, serial='aaaa', size=dehumanize_size("100M")) make_disk(model, serial='aaaa', size=dehumanize_size("100M"))