filesystem: offer autoinstall use_gap
Accept a new 'mode' parameter when using autoinstall guided storage. The default mode is 'reformat_disk', which acts as today. A new mode of 'use_gap' is available, which does not reformat the disk.
This commit is contained in:
parent
b2d5fffcc0
commit
d622c383f6
|
@ -133,19 +133,20 @@ class FilesystemController(SubiquityController, FilesystemManipulator):
|
||||||
"autoinstall config did not create needed bootloader "
|
"autoinstall config did not create needed bootloader "
|
||||||
"partition")
|
"partition")
|
||||||
|
|
||||||
def setup_disk_for_guided(self, disk):
|
def setup_disk_for_guided(self, disk, mode):
|
||||||
self.reformat(disk, wipe='superblock-recursive')
|
if mode is None or mode == 'reformat_disk':
|
||||||
|
self.reformat(disk, wipe='superblock-recursive')
|
||||||
if DeviceAction.TOGGLE_BOOT in DeviceAction.supported(disk):
|
if DeviceAction.TOGGLE_BOOT in DeviceAction.supported(disk):
|
||||||
self.add_boot_disk(disk)
|
self.add_boot_disk(disk)
|
||||||
return gaps.largest_gap(disk)
|
return gaps.largest_gap(disk)
|
||||||
|
|
||||||
def guided_direct(self, disk):
|
def guided_direct(self, disk, mode=None):
|
||||||
gap = self.setup_disk_for_guided(disk)
|
gap = self.setup_disk_for_guided(disk, mode)
|
||||||
spec = dict(fstype="ext4", mount="/")
|
spec = dict(fstype="ext4", mount="/")
|
||||||
self.create_partition(device=disk, gap=gap, spec=spec)
|
self.create_partition(device=disk, gap=gap, spec=spec)
|
||||||
|
|
||||||
def guided_lvm(self, disk, lvm_options=None):
|
def guided_lvm(self, disk, mode=None, lvm_options=None):
|
||||||
gap = self.setup_disk_for_guided(disk)
|
gap = self.setup_disk_for_guided(disk, mode)
|
||||||
gap_boot, gap_rest = gap.split(sizes.get_bootfs_size(gap.size))
|
gap_boot, gap_rest = gap.split(sizes.get_bootfs_size(gap.size))
|
||||||
spec = dict(fstype="ext4", mount='/boot')
|
spec = dict(fstype="ext4", mount='/boot')
|
||||||
self.create_partition(device=disk, gap=gap_boot, spec=spec)
|
self.create_partition(device=disk, gap=gap_boot, spec=spec)
|
||||||
|
@ -198,7 +199,7 @@ class FilesystemController(SubiquityController, FilesystemManipulator):
|
||||||
'password': choice.password,
|
'password': choice.password,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
self.guided_lvm(disk, lvm_options)
|
self.guided_lvm(disk, lvm_options=lvm_options)
|
||||||
else:
|
else:
|
||||||
self.guided_direct(disk)
|
self.guided_direct(disk)
|
||||||
|
|
||||||
|
@ -459,19 +460,36 @@ class FilesystemController(SubiquityController, FilesystemManipulator):
|
||||||
continue
|
continue
|
||||||
break
|
break
|
||||||
|
|
||||||
|
def run_guided(self, layout):
|
||||||
|
guided_method = getattr(self, "guided_" + layout['name'])
|
||||||
|
mode = layout.get('mode', 'reformat_disk')
|
||||||
|
self.validate_layout_mode(mode)
|
||||||
|
|
||||||
|
if mode == 'reformat_disk':
|
||||||
|
match = layout.get("match", {'size': 'largest'})
|
||||||
|
disk = self.model.disk_for_match(self.model.all_disks(), match)
|
||||||
|
if not disk:
|
||||||
|
raise Exception("autoinstall cannot configure storage "
|
||||||
|
"- no disk found large enough for install")
|
||||||
|
elif mode == 'use_gap':
|
||||||
|
gap = gaps.largest_gap(self.model.all_disks())
|
||||||
|
if not gap:
|
||||||
|
raise Exception("autoinstall cannot configure storage "
|
||||||
|
"- 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
|
||||||
|
guided_method(disk=disk, mode=mode)
|
||||||
|
|
||||||
|
def validate_layout_mode(self, mode):
|
||||||
|
if mode not in ('reformat_disk', 'use_gap'):
|
||||||
|
raise ValueError(f'Unknown layout mode {mode}')
|
||||||
|
|
||||||
@with_context()
|
@with_context()
|
||||||
def convert_autoinstall_config(self, context=None):
|
def convert_autoinstall_config(self, context=None):
|
||||||
log.debug("self.ai_data = %s", self.ai_data)
|
log.debug("self.ai_data = %s", self.ai_data)
|
||||||
if 'layout' in self.ai_data:
|
if 'layout' in self.ai_data:
|
||||||
layout = self.ai_data['layout']
|
self.run_guided(self.ai_data['layout'])
|
||||||
meth = getattr(self, "guided_" + layout['name'])
|
|
||||||
disk = self.model.disk_for_match(
|
|
||||||
self.model.all_disks(),
|
|
||||||
layout.get("match", {'size': 'largest'}))
|
|
||||||
if not disk:
|
|
||||||
raise Exception("autoinstall cannot configure storage "
|
|
||||||
"- no disk found large enough for install")
|
|
||||||
meth(disk)
|
|
||||||
elif 'config' in self.ai_data:
|
elif 'config' in self.ai_data:
|
||||||
self.model.apply_autoinstall_config(self.ai_data['config'])
|
self.model.apply_autoinstall_config(self.ai_data['config'])
|
||||||
self.model.grub = self.ai_data.get('grub')
|
self.model.grub = self.ai_data.get('grub')
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
|
|
||||||
from unittest import mock, TestCase
|
from unittest import mock, TestCase
|
||||||
|
|
||||||
|
from parameterized import parameterized
|
||||||
|
|
||||||
from subiquity.server.controllers.filesystem import FilesystemController
|
from subiquity.server.controllers.filesystem import FilesystemController
|
||||||
|
|
||||||
from subiquitycore.tests.util import run_coro
|
from subiquitycore.tests.util import run_coro
|
||||||
|
@ -103,3 +105,21 @@ class TestGuided(TestCase):
|
||||||
self.assertEqual(None, d1p1.mount)
|
self.assertEqual(None, d1p1.mount)
|
||||||
self.assertEqual('/', d1p2.mount)
|
self.assertEqual('/', d1p2.mount)
|
||||||
self.assertEqual(d1p1.size + d1p1.offset, d1p2.offset)
|
self.assertEqual(d1p1.size + d1p1.offset, d1p2.offset)
|
||||||
|
|
||||||
|
|
||||||
|
class TestLayout(TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.app = make_app()
|
||||||
|
self.app.opts.bootloader = 'UEFI'
|
||||||
|
self.app.report_start_event = mock.Mock()
|
||||||
|
self.app.report_finish_event = mock.Mock()
|
||||||
|
self.fsc = FilesystemController(app=self.app)
|
||||||
|
|
||||||
|
@parameterized.expand([('reformat_disk',), ('use_gap',)])
|
||||||
|
def test_good_modes(self, mode):
|
||||||
|
self.fsc.validate_layout_mode(mode)
|
||||||
|
|
||||||
|
@parameterized.expand([('resize_biggest',), ('use_free',)])
|
||||||
|
def test_bad_modes(self, mode):
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
self.fsc.validate_layout_mode(mode)
|
||||||
|
|
Loading…
Reference in New Issue