From 60378fc7bf193acafd5a530992fbb711077b9fcb Mon Sep 17 00:00:00 2001 From: Dan Bungert Date: Fri, 5 Aug 2022 13:30:30 -0600 Subject: [PATCH] filesystem: guided creates logicals if in_extended --- subiquity/common/filesystem/manipulator.py | 5 +- subiquity/server/controllers/filesystem.py | 21 +++--- .../controllers/tests/test_filesystem.py | 65 +++++++++++++++++-- 3 files changed, 72 insertions(+), 19 deletions(-) diff --git a/subiquity/common/filesystem/manipulator.py b/subiquity/common/filesystem/manipulator.py index 2daa9213..8a364d43 100644 --- a/subiquity/common/filesystem/manipulator.py +++ b/subiquity/common/filesystem/manipulator.py @@ -78,8 +78,11 @@ class FilesystemManipulator: delete_format = delete_filesystem def create_partition(self, device, gap, spec, **kw): + flag = kw.pop('flag', None) + if gap.in_extended: + flag = 'logical' part = self.model.add_partition( - device, size=gap.size, offset=gap.offset, **kw) + device, size=gap.size, offset=gap.offset, flag=flag, **kw) self.create_filesystem(part, spec) return part diff --git a/subiquity/server/controllers/filesystem.py b/subiquity/server/controllers/filesystem.py index 574372e4..8a54e99d 100644 --- a/subiquity/server/controllers/filesystem.py +++ b/subiquity/server/controllers/filesystem.py @@ -138,7 +138,7 @@ class FilesystemController(SubiquityController, FilesystemManipulator): "autoinstall config did not create needed bootloader " "partition") - def setup_disk_for_guided(self, target, mode): + def setup_gap_for_guided(self, target, mode): if isinstance(target, gaps.Gap): disk = target.device gap = target @@ -150,27 +150,26 @@ class FilesystemController(SubiquityController, FilesystemManipulator): if DeviceAction.TOGGLE_BOOT in DeviceAction.supported(disk): self.add_boot_disk(disk) if gap is None: - return disk, gaps.largest_gap(disk) + return 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('failed to locate gap after adding boot') - return disk, gap + return gap 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) + gap = self.setup_gap_for_guided(target, mode) + self.create_partition( + gap.device, gap, dict(fstype="ext4", mount="/")) def guided_lvm(self, target, mode=None, lvm_options=None): - disk, gap = self.setup_disk_for_guided(target, mode) + gap = self.setup_gap_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) - - part = self.create_partition( - device=disk, gap=gap_rest, spec=dict(fstype=None)) + device = gap.device + self.create_partition(device, gap_boot, spec) + part = self.create_partition(device, gap_rest, dict(fstype=None)) vg_name = 'ubuntu-vg' i = 0 diff --git a/subiquity/server/controllers/tests/test_filesystem.py b/subiquity/server/controllers/tests/test_filesystem.py index 469f9227..389c07b9 100644 --- a/subiquity/server/controllers/tests/test_filesystem.py +++ b/subiquity/server/controllers/tests/test_filesystem.py @@ -36,6 +36,12 @@ from subiquity.models.tests.test_filesystem import ( ) +bootloaders = [(bl, ) for bl in list(Bootloader)] +bootloaders_and_ptables = [(bl, pt) + for bl in list(Bootloader) + for pt in ('gpt', 'msdos', 'vtoc')] + + class TestSubiquityControllerFilesystem(IsolatedAsyncioTestCase): def setUp(self): self.app = make_app() @@ -74,11 +80,13 @@ class TestGuided(TestCase): (Bootloader.PREP, 'msdos', None), ] - def _guided_setup(self, bootloader, ptable): + def _guided_setup(self, bootloader, ptable, storage_version=None): self.app = make_app() self.app.opts.bootloader = bootloader.value self.controller = FilesystemController(self.app) - self.controller.model = self.model = make_model(bootloader) + self.controller.supports_resilient_boot = True + self.model = make_model(bootloader, storage_version) + self.controller.model = self.model self.model._probe_data = {'blockdev': {}} self.d1 = make_disk(self.model, ptable=ptable) @@ -122,6 +130,54 @@ class TestGuided(TestCase): self.assertEqual(None, d1p2.mount) self.assertIsNone(gaps.largest_gap(self.d1)) + def _guided_side_by_side(self, bl): + self._guided_setup(bl, 'msdos', storage_version=2) + self.controller.add_boot_disk(self.d1) + for p in self.d1._partitions: + p.preserve = True + if bl == Bootloader.UEFI: + # let it pass the is_esp check + self.model._probe_data['blockdev'][p._path()] = { + "ID_PART_ENTRY_TYPE": str(0xef) + } + # create an extended partition, + # and a few other partitions to make it more interesting + g = gaps.largest_gap(self.d1) + make_partition(self.model, self.d1, preserve=True, + size=10 << 30, offset=g.offset) + g = gaps.largest_gap(self.d1) + make_partition(self.model, self.d1, preserve=True, + flag='extended', size=g.size, offset=g.offset) + g = gaps.largest_gap(self.d1) + make_partition(self.model, self.d1, preserve=True, + flag='logical', size=10 << 30, offset=g.offset) + + @parameterized.expand(bootloaders) + def test_guided_direct_side_by_side_logical(self, bl): + self._guided_side_by_side(bl) + parts_before = self.d1._partitions.copy() + g = gaps.largest_gap(self.d1) + self.controller.guided_direct(g, mode='use_gap') + parts_after = gaps.parts_and_gaps(self.d1)[:-1] + self.assertEqual(parts_before, parts_after) + p6 = gaps.parts_and_gaps(self.d1)[-1] + self.assertEqual('/', p6.mount) + self.assertEqual('logical', p6.flag) + + @parameterized.expand(bootloaders) + def test_guided_lvm_side_by_side_logical(self, bl): + self._guided_side_by_side(bl) + parts_before = self.d1._partitions.copy() + g = gaps.largest_gap(self.d1) + self.controller.guided_lvm(g, mode='use_gap') + parts_after = gaps.parts_and_gaps(self.d1)[:-2] + self.assertEqual(parts_before, parts_after) + p6, p7 = gaps.parts_and_gaps(self.d1)[-2:] + self.assertEqual('/boot', p6.mount) + self.assertEqual('logical', p6.flag) + self.assertEqual(None, p7.mount) + self.assertEqual('logical', p7.flag) + class TestLayout(TestCase): def setUp(self): @@ -139,11 +195,6 @@ class TestLayout(TestCase): self.fsc.validate_layout_mode(mode) -bootloaders_and_ptables = [(bl, pt) - for bl in list(Bootloader) - for pt in ('gpt', 'msdos', 'vtoc')] - - class TestGuidedV2(IsolatedAsyncioTestCase): def _setup(self, bootloader, ptable, fix_bios=True, **kw): self.app = make_app()