filesystem: guided_method can take a gap
This commit is contained in:
parent
7a9e920de1
commit
1f3d36510f
|
@ -63,6 +63,7 @@ from subiquity.common.types import (
|
|||
StorageResponseV2,
|
||||
)
|
||||
from subiquity.models.filesystem import (
|
||||
align_up,
|
||||
align_down,
|
||||
LVM_CHUNK_SIZE,
|
||||
Raid,
|
||||
|
@ -137,20 +138,33 @@ class FilesystemController(SubiquityController, FilesystemManipulator):
|
|||
"autoinstall config did not create needed bootloader "
|
||||
"partition")
|
||||
|
||||
def setup_disk_for_guided(self, disk, mode):
|
||||
def setup_disk_for_guided(self, target, mode):
|
||||
if isinstance(target, gaps.Gap):
|
||||
disk = target.device
|
||||
gap = target
|
||||
else:
|
||||
disk = target
|
||||
gap = None
|
||||
if mode is None or mode == 'reformat_disk':
|
||||
self.reformat(disk, wipe='superblock-recursive')
|
||||
if DeviceAction.TOGGLE_BOOT in DeviceAction.supported(disk):
|
||||
self.add_boot_disk(disk)
|
||||
return gaps.largest_gap(disk)
|
||||
self.add_boot_disk(target)
|
||||
if gap is None:
|
||||
return disk, gaps.largest_gap(disk)
|
||||
else:
|
||||
# find what's left of the gap after adding boot
|
||||
gap = gaps.within(disk, gap)
|
||||
if gap is None:
|
||||
raise Exception(f'failed to locate gap after adding boot')
|
||||
return disk, gap
|
||||
|
||||
def guided_direct(self, disk, mode=None):
|
||||
gap = self.setup_disk_for_guided(disk, mode)
|
||||
def guided_direct(self, target, mode=None):
|
||||
disk, gap = self.setup_disk_for_guided(target, mode)
|
||||
spec = dict(fstype="ext4", mount="/")
|
||||
self.create_partition(device=disk, gap=gap, spec=spec)
|
||||
|
||||
def guided_lvm(self, disk, mode=None, lvm_options=None):
|
||||
gap = self.setup_disk_for_guided(disk, mode)
|
||||
def guided_lvm(self, target, mode=None, lvm_options=None):
|
||||
disk, gap = self.setup_disk_for_guided(target, mode)
|
||||
gap_boot, gap_rest = gap.split(sizes.get_bootfs_size(gap.size))
|
||||
spec = dict(fstype="ext4", mount='/boot')
|
||||
self.create_partition(device=disk, gap=gap_boot, spec=spec)
|
||||
|
@ -195,15 +209,27 @@ class FilesystemController(SubiquityController, FilesystemManipulator):
|
|||
def guided(self, choice: GuidedChoiceV2):
|
||||
self.model.guided_configuration = choice
|
||||
|
||||
disk = self.model._one(id=choice.target.disk_id)
|
||||
if isinstance(choice.target, GuidedStorageTargetReformat):
|
||||
mode = 'reformat_disk'
|
||||
target = disk
|
||||
elif isinstance(choice.target, GuidedStorageTargetUseGap):
|
||||
mode = 'use_gap' # FIXME not the correct gap
|
||||
mode = 'use_gap'
|
||||
target = gaps.at_offset(disk, choice.target.gap.offset)
|
||||
elif isinstance(choice.target, GuidedStorageTargetResize):
|
||||
mode = 'resize' # FIXME not actually working
|
||||
partition = self.get_partition(
|
||||
disk, choice.target.partition_number)
|
||||
part_align = disk.alignment_data().part_align
|
||||
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)
|
||||
else:
|
||||
raise Exception(f'Unknown guided target {choice.target}')
|
||||
disk = self.model._one(id=choice.target.disk_id)
|
||||
|
||||
if choice.use_lvm:
|
||||
lvm_options = None
|
||||
|
@ -214,9 +240,9 @@ class FilesystemController(SubiquityController, FilesystemManipulator):
|
|||
'password': choice.password,
|
||||
},
|
||||
}
|
||||
self.guided_lvm(disk, mode=mode, lvm_options=lvm_options)
|
||||
self.guided_lvm(target, mode=mode, lvm_options=lvm_options)
|
||||
else:
|
||||
self.guided_direct(disk, mode=mode)
|
||||
self.guided_direct(target, mode=mode)
|
||||
|
||||
async def _probe_response(self, wait, resp_cls):
|
||||
if self._probe_task.task is None or not self._probe_task.task.done():
|
||||
|
@ -381,7 +407,10 @@ class FilesystemController(SubiquityController, FilesystemManipulator):
|
|||
for disk in self.get_guided_disks(with_reformatting=False):
|
||||
gap = gaps.largest_gap(disk)
|
||||
if gap is not None and gap.size >= install_min:
|
||||
use_gap = GuidedStorageTargetUseGap(disk_id=disk.id, gap=gap)
|
||||
api_gap = labels.for_client(gap)
|
||||
use_gap = GuidedStorageTargetUseGap(
|
||||
disk_id=disk.id,
|
||||
gap=api_gap)
|
||||
scenarios.append((gap.size, use_gap))
|
||||
|
||||
for disk in self.get_guided_disks(check_boot=False):
|
||||
|
@ -539,8 +568,8 @@ class FilesystemController(SubiquityController, FilesystemManipulator):
|
|||
|
||||
if mode == 'reformat_disk':
|
||||
match = layout.get("match", {'size': 'largest'})
|
||||
disk = self.model.disk_for_match(self.model.all_disks(), match)
|
||||
if not disk:
|
||||
target = self.model.disk_for_match(self.model.all_disks(), match)
|
||||
if not target:
|
||||
raise Exception("autoinstall cannot configure storage "
|
||||
"- no disk found large enough for install")
|
||||
elif mode == 'use_gap':
|
||||
|
@ -552,10 +581,10 @@ class FilesystemController(SubiquityController, FilesystemManipulator):
|
|||
"- no gap found large enough for install")
|
||||
# This is not necessarily the exact gap to be used, as the gap size
|
||||
# may change once add_boot_disk has sorted things out.
|
||||
disk = gap.device
|
||||
target = gap
|
||||
log.info(f'autoinstall: running guided {name} install in mode {mode} '
|
||||
f'using {disk}')
|
||||
guided_method(disk=disk, mode=mode)
|
||||
f'using {target}')
|
||||
guided_method(target=target, mode=mode)
|
||||
|
||||
def validate_layout_mode(self, mode):
|
||||
if mode not in ('reformat_disk', 'use_gap'):
|
||||
|
|
|
@ -21,6 +21,7 @@ from subiquity.server.controllers.filesystem import FilesystemController
|
|||
|
||||
from subiquitycore.tests.mocks import make_app
|
||||
from subiquity.common.filesystem import gaps
|
||||
from subiquity.common import types
|
||||
from subiquity.common.types import (
|
||||
Bootloader,
|
||||
GuidedStorageTargetReformat,
|
||||
|
@ -154,10 +155,11 @@ class TestGuidedV2(IsolatedAsyncioTestCase):
|
|||
@parameterized.expand(bootloaders)
|
||||
async def test_blank_disk(self, bootloader):
|
||||
self._setup(bootloader)
|
||||
d = make_disk(self.model)
|
||||
d = make_disk(self.model, size=(30 << 30) + (2 << 20))
|
||||
gap = types.Gap(offset=1 << 20, size=30 << 30)
|
||||
expected = [
|
||||
GuidedStorageTargetReformat(disk_id=d.id),
|
||||
GuidedStorageTargetUseGap(disk_id=d.id, gap=gaps.largest_gap(d)),
|
||||
GuidedStorageTargetUseGap(disk_id=d.id, gap=gap),
|
||||
]
|
||||
resp = await self.fsc.v2_guided_GET()
|
||||
self.assertEqual(expected, resp.possible)
|
||||
|
@ -165,14 +167,14 @@ class TestGuidedV2(IsolatedAsyncioTestCase):
|
|||
@parameterized.expand(bootloaders)
|
||||
async def test_used_half_disk(self, bootloader):
|
||||
self._setup(bootloader)
|
||||
d = make_disk(self.model)
|
||||
p1 = make_partition(self.model, d)
|
||||
d = make_disk(self.model, size=(30 << 30) + (2 << 20))
|
||||
p1 = make_partition(self.model, d, preserve=True, size=15 << 30)
|
||||
self.fs_probe[p1._path()] = {'ESTIMATED_MIN_SIZE': 1 << 20}
|
||||
resp = await self.fsc.v2_guided_GET()
|
||||
reformat = resp.possible[0]
|
||||
self.assertEqual(GuidedStorageTargetReformat(disk_id=d.id), reformat)
|
||||
if bootloader != Bootloader.BIOS:
|
||||
gap = gaps.largest_gap(d)
|
||||
gap = types.Gap(offset=(15 << 30) + (1 << 20), size=15 << 30)
|
||||
self.assertEqual(
|
||||
GuidedStorageTargetUseGap(disk_id=d.id, gap=gap),
|
||||
resp.possible[1])
|
||||
|
|
Loading…
Reference in New Issue