replace free_for_paritions with largest_gap_size

This commit is contained in:
Michael Hudson-Doyle 2021-12-13 20:27:19 +13:00
parent 5429e97854
commit 83cfdbdfea
9 changed files with 48 additions and 46 deletions

View File

@ -88,3 +88,10 @@ def largest_gap(device):
largest = pg
largest_size = pg.size
return largest
def largest_gap_size(device):
largest = largest_gap(device)
if largest is not None:
return largest.size
return 0

View File

@ -292,7 +292,7 @@ def _for_client_disk(disk, *, min_size=0):
preserve=disk.preserve,
usage_labels=usage_labels(disk),
partitions=[for_client(p) for p in disk._partitions],
free_for_partitions=disk.free_for_partitions,
free_for_partitions=gaps.largest_gap_size(disk),
boot_device=boot.is_boot_device(disk),
ok_for_guided=disk.size >= min_size,
model=getattr(disk, 'model', None),

View File

@ -15,7 +15,7 @@
import logging
from subiquity.common.filesystem import boot
from subiquity.common.filesystem import boot, gaps
from subiquity.common.types import Bootloader
from subiquity.models.filesystem import (
align_up,
@ -199,12 +199,12 @@ class FilesystemManipulator:
def partition_disk_handler(self, disk, partition, spec):
log.debug('partition_disk_handler: %s %s %s', disk, partition, spec)
log.debug('disk.freespace: {}'.format(disk.free_for_partitions))
log.debug('disk.freespace: {}'.format(gaps.largest_gap_size(disk)))
if partition is not None:
if 'size' in spec:
partition.size = align_up(spec['size'])
if disk.free_for_partitions < 0:
if gaps.largest_gap_size(disk) < 0:
raise Exception("partition size too large")
self.delete_filesystem(partition.fs())
self.create_filesystem(partition, spec)
@ -225,11 +225,11 @@ class FilesystemManipulator:
# adjust downward the partition size (if necessary) to accommodate
# bios/grub partition
if spec['size'] > disk.free_for_partitions:
if spec['size'] > gaps.largest_gap_size(disk):
log.debug(
"Adjusting request down: %s - %s = %s",
spec['size'], part.size, disk.free_for_partitions)
spec['size'] = disk.free_for_partitions
spec['size'], part.size, gaps.largest_gap_size(disk))
spec['size'] = gaps.largest_gap_size(disk)
self.create_partition(disk, spec)
@ -237,14 +237,14 @@ class FilesystemManipulator:
def logical_volume_handler(self, vg, lv, spec):
log.debug('logical_volume_handler: %s %s %s', vg, lv, spec)
log.debug('vg.freespace: {}'.format(vg.free_for_partitions))
log.debug('vg.freespace: {}'.format(gaps.largest_gap_size(vg)))
if lv is not None:
if 'name' in spec:
lv.name = spec['name']
if 'size' in spec:
lv.size = align_up(spec['size'])
if vg.free_for_partitions < 0:
if gaps.largest_gap_size(vg) < 0:
raise Exception("lv size too large")
self.delete_filesystem(lv.fs())
self.create_filesystem(lv, spec)
@ -322,7 +322,7 @@ class FilesystemManipulator:
self.model.add_filesystem(
p, p.original_fstype(), preserve=True)
else:
full = boot_disk.free_for_partitions == 0
full = gaps.largest_gap_size(boot_disk) == 0
tot_size = 0
for p in partitions:
tot_size += p.size
@ -371,9 +371,9 @@ class FilesystemManipulator:
elif bootloader == Bootloader.BIOS:
part_size = BIOS_GRUB_SIZE_BYTES
log.debug("bootloader %s", bootloader)
if part_size > new_boot_disk.free_for_partitions:
if part_size > gaps.largest_gap_size(new_boot_disk):
largest_part = max(
new_boot_disk.partitions(), key=lambda p: p.size)
largest_part.size -= (
part_size - new_boot_disk.free_for_partitions)
part_size - gaps.largest_gap_size(new_boot_disk))
self._create_boot_partition(new_boot_disk)

View File

@ -142,7 +142,8 @@ class TestActions(unittest.TestCase):
self.assertActionPossible(dos_disk, DeviceAction.TOGGLE_BOOT)
# Even if they have existing partitions
make_partition(
model, dos_disk, size=dos_disk.free_for_partitions, preserve=True)
model, dos_disk, size=gaps.largest_gap_size(dos_disk),
preserve=True)
self.assertActionPossible(dos_disk, DeviceAction.TOGGLE_BOOT)
# (we never create dos partition tables so no need to test
# preserve=False case).
@ -151,7 +152,7 @@ class TestActions(unittest.TestCase):
gpt_disk = make_disk(model, ptable='gpt', preserve=False)
self.assertActionPossible(gpt_disk, DeviceAction.TOGGLE_BOOT)
# Even if they are filled with partitions (we resize partitions to fit)
make_partition(model, gpt_disk, size=dos_disk.free_for_partitions)
make_partition(model, gpt_disk, size=gaps.largest_gap_size(dos_disk))
self.assertActionPossible(gpt_disk, DeviceAction.TOGGLE_BOOT)
# GPT disks with existing partition tables but no partitions can be the
@ -187,7 +188,8 @@ class TestActions(unittest.TestCase):
new_disk = make_disk(model, preserve=False)
self.assertActionPossible(new_disk, DeviceAction.TOGGLE_BOOT)
# Even if they are filled with partitions (we resize partitions to fit)
make_partition(model, new_disk, size=new_disk.free_for_partitions)
make_partition(
model, new_disk, size=gaps.largest_gap_size(new_disk))
self.assertActionPossible(new_disk, DeviceAction.TOGGLE_BOOT)
# A disk with an existing but empty partitions can also be the
@ -363,7 +365,7 @@ class TestActions(unittest.TestCase):
def test_vg_action_EDIT(self):
model, vg = make_model_and_vg()
self.assertActionPossible(vg, DeviceAction.EDIT)
model.add_logical_volume(vg, 'lv1', size=vg.free_for_partitions//2)
model.add_logical_volume(vg, 'lv1', size=gaps.largest_gap_size(vg))
self.assertActionNotPossible(vg, DeviceAction.EDIT)
vg2 = make_vg(model)
@ -391,7 +393,7 @@ class TestActions(unittest.TestCase):
self.assertActionPossible(vg, DeviceAction.DELETE)
self.assertActionPossible(vg, DeviceAction.DELETE)
lv = model.add_logical_volume(
vg, 'lv0', size=vg.free_for_partitions//2)
vg, 'lv0', size=gaps.largest_gap_size(vg)//2)
self.assertActionPossible(vg, DeviceAction.DELETE)
fs = model.add_filesystem(lv, 'ext4')
self.assertActionPossible(vg, DeviceAction.DELETE)

View File

@ -18,6 +18,7 @@ import unittest
from subiquity.common.filesystem.actions import (
DeviceAction,
)
from subiquity.common.filesystem import gaps
from subiquity.common.filesystem.manipulator import (
FilesystemManipulator,
)
@ -130,7 +131,7 @@ class TestFilesystemManipulator(unittest.TestCase):
disk1 = make_disk(manipulator.model, preserve=False)
disk2 = make_disk(manipulator.model, preserve=False)
disk2p1 = manipulator.model.add_partition(
disk2, size=disk2.free_for_partitions)
disk2, size=gaps.largest_gap_size(disk2))
manipulator.add_boot_disk(disk1)
self.assertIsBootDisk(manipulator, disk1)
@ -171,7 +172,7 @@ class TestFilesystemManipulator(unittest.TestCase):
disk1 = make_disk(manipulator.model, preserve=False)
disk2 = make_disk(manipulator.model, preserve=False)
disk2p1 = manipulator.model.add_partition(
disk2, size=disk2.free_for_partitions)
disk2, size=gaps.largest_gap_size(disk2))
manipulator.add_boot_disk(disk1)
self.assertIsBootDisk(manipulator, disk1)
@ -218,7 +219,7 @@ class TestFilesystemManipulator(unittest.TestCase):
disk1, size=512 << 20, flag="boot")
disk1p1.preserve = True
disk1p2 = manipulator.model.add_partition(
disk1, size=disk1.free_for_partitions)
disk1, size=gaps.largest_gap_size(disk1))
disk1p2.preserve = True
manipulator.partition_disk_handler(
disk1, disk1p2, {'fstype': 'ext4', 'mount': '/'})

View File

@ -524,10 +524,6 @@ class _Device(_Formattable, ABC):
def available_for_partitions(self):
return align_down(self.size, 1 << 20) - GPT_OVERHEAD
@property
def free_for_partitions(self):
return self.available_for_partitions - self.used
def available(self):
# A _Device is available if:
# 1) it is not part of a device like a RAID or LVM or zpool or ...
@ -540,9 +536,11 @@ class _Device(_Formattable, ABC):
return False
if self._fs is not None:
return self._fs._available()
if self.free_for_partitions > 0:
if not self._has_preexisting_partition():
return True
from subiquity.common.filesystem.gaps import (
largest_gap_size,
)
if largest_gap_size(self) > 0:
return True
return any(p.available() for p in self._partitions)
def has_unavailable_partition(self):
@ -803,11 +801,6 @@ class LVM_VolGroup(_Device):
def available_for_partitions(self):
return self.size
@property
def free_for_partitions(self):
return align_down(
self.available_for_partitions - self.used, LVM_CHUNK_SIZE)
ok_for_raid = False
ok_for_lvm_vg = False
@ -1083,10 +1076,10 @@ class FilesystemModel(object):
raise Exception(
"{} has negative size but is not final partition "
"of {}".format(p, parent))
p.size = 0
p.size = parent.free_for_partitions
if p.type == 'lvm_partition':
p.size = align_down(p.size, LVM_CHUNK_SIZE)
from subiquity.common.filesystem.gaps import (
largest_gap_size,
)
p.size = largest_gap_size(parent)
elif isinstance(p.size, str):
if p.size.endswith("%"):
percentage = int(p.size[:-1])
@ -1346,8 +1339,6 @@ class FilesystemModel(object):
def add_partition(self, device, size, flag="", wipe=None,
grub_device=None):
from subiquity.common.filesystem import boot
if size > device.free_for_partitions:
raise Exception("%s > %s", size, device.free_for_partitions)
real_size = align_up(size)
log.debug("add_partition: rounded size from %s to %s", size, real_size)
if device._fs is not None:

View File

@ -28,6 +28,7 @@ from subiquity.models.filesystem import (
align_down,
LVM_CHUNK_SIZE,
)
from subiquity.common.filesystem import gaps
class TestHumanizeSize(unittest.TestCase):
@ -164,7 +165,7 @@ def make_partition(model, device=None, *, preserve=False, size=None, **kw):
if device is None:
device = make_disk(model)
if size is None:
size = device.free_for_partitions//2
size = gaps.largest_gap_size(device)//2
partition = Partition(
m=model, device=device, size=size, preserve=preserve, **kw)
if preserve:
@ -203,7 +204,7 @@ def make_model_and_vg(bootloader=None):
def make_lv(model):
vg = make_vg(model)
name = 'lv%s' % len(model._actions)
return model.add_logical_volume(vg, name, vg.free_for_partitions//2)
return model.add_logical_volume(vg, name, gaps.largest_gap_size(vg))
def make_model_and_lv(bootloader=None):

View File

@ -40,7 +40,7 @@ from subiquity.common.errorreport import ErrorReportKind
from subiquity.common.filesystem.actions import (
DeviceAction,
)
from subiquity.common.filesystem import boot, labels
from subiquity.common.filesystem import boot, gaps, labels
from subiquity.common.filesystem.manipulator import FilesystemManipulator
from subiquity.common.types import (
Bootloader,
@ -126,7 +126,7 @@ class FilesystemController(SubiquityController, FilesystemManipulator):
def guided_direct(self, disk):
self.reformat(disk)
result = {
"size": disk.free_for_partitions,
"size": gaps.largest_gap_size(disk),
"fstype": "ext4",
"mount": "/",
}
@ -144,7 +144,7 @@ class FilesystemController(SubiquityController, FilesystemManipulator):
))
part = self.create_partition(
device=disk, spec=dict(
size=disk.free_for_partitions,
size=gaps.largest_gap_size(disk),
fstype=None,
))
vg_name = 'ubuntu-vg'
@ -348,7 +348,7 @@ class FilesystemController(SubiquityController, FilesystemManipulator):
disk = self.model._one(id=data.disk_id)
size = data.partition.size
if size is None or size < 0:
size = disk.free_for_partitions
size = gaps.largest_gap_size(disk)
spec = {
'size': size,
'fstype': data.partition.format,

View File

@ -37,7 +37,7 @@ from subiquitycore.ui.container import Pile
from subiquitycore.ui.stretchy import Stretchy
from subiquitycore.ui.utils import rewrap
from subiquity.common.filesystem import boot, labels
from subiquity.common.filesystem import boot, gaps, labels
from subiquity.models.filesystem import (
align_up,
Disk,
@ -375,7 +375,7 @@ class PartitionStretchy(Stretchy):
self.model = parent.model
self.controller = parent.controller
self.parent = parent
max_size = disk.free_for_partitions
max_size = gaps.largest_gap_size(disk)
initial = {}
label = _("Create")