Skip to content

Commit

Permalink
storage: honor matchers in use_gap autoinstall mode
Browse files Browse the repository at this point in the history
When using the use_gap mode in autoinstall, one may want to ensure that
we use a gap on a specific disk. Unfortunately, the match directives
were silently ignored.

Let's make sure they are honored.

LP: #2080608

Signed-off-by: Olivier Gayot <[email protected]>
  • Loading branch information
ogayot committed Sep 18, 2024
1 parent fc5e4bb commit 9fd3c92
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 2 deletions.
5 changes: 3 additions & 2 deletions subiquity/server/controllers/filesystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -1624,8 +1624,9 @@ async def run_autoinstall_guided(self, layout):
disk = self.get_bootable_matching_disk(match)
target = GuidedStorageTargetReformat(disk_id=disk.id, allowed=[])
elif mode == "use_gap":
bootable = self.potential_boot_disks(with_reformatting=False)
gap = gaps.largest_gap(bootable)
match = layout.get("match", {})
bootable_disks = self.get_bootable_matching_disks(match)
gap = gaps.largest_gap(bootable_disks)
if not gap:
raise Exception(
"autoinstall cannot configure storage "
Expand Down
72 changes: 72 additions & 0 deletions subiquity/server/controllers/tests/test_filesystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,78 @@ async def test__get_system_api_error_logged(self):
self.assertIn("cannot load assertions for label", logs.output[0])


class TestRunAutoinstallGuided(IsolatedAsyncioTestCase):
def setUp(self):
self.app = make_app()
self.app.opts.bootloader = None
self.fsc = FilesystemController(self.app)
self.model = self.fsc.model = make_model()

# This is needed for examine_systems_task
self.app.base_model.source.current.type = "fsimage"
self.app.base_model.source.current.variations = {
"default": CatalogEntryVariation(path="", size=1),
}

async def asyncSetUp(self):
self.fsc._examine_systems_task.start_sync()

await self.fsc._examine_systems_task.wait()

async def test_direct_use_gap__install_media(self):
"""Match directives were previously not honored when using mode: use_gap.
This made it not possible for the OEM team to install to the
installation media. LP: #2080608"""
layout = {
"name": "direct",
"mode": "use_gap",
"match": {
"install-media": True,
},
}

# The matcher for "install-media": True looks for
# _has_in_use_partition.
iso = make_disk(self.model)
iso._has_in_use_partition = True

make_disk(self.model)

p_guided = mock.patch.object(self.fsc, "guided")
p_guided_choice_v2 = mock.patch(
"subiquity.server.controllers.filesystem.GuidedChoiceV2",
wraps=GuidedChoiceV2,
)
p_largest_gap = mock.patch(
"subiquity.server.controllers.filesystem.gaps.largest_gap",
wraps=gaps.largest_gap,
)

with (
p_guided as m_guided,
p_guided_choice_v2 as m_guided_choice_v2,
p_largest_gap as m_largest_gap,
):
await self.fsc.run_autoinstall_guided(layout)

# largest_gap will call itself recursively, so we should not expect a
# single call to it.
m_largest_gap.mock_calls[0] = mock.call([iso])

m_guided.assert_called_once()
m_guided_choice_v2.assert_called_once_with(
target=GuidedStorageTargetUseGap(
disk_id=iso.id, gap=gaps.largest_gap([iso]), allowed=[]
),
capability=GuidedCapability.DIRECT,
password=mock.ANY,
recovery_key=mock.ANY,
sizing_policy=mock.ANY,
reset_partition=mock.ANY,
reset_partition_size=mock.ANY,
)


class TestGuided(IsolatedAsyncioTestCase):
boot_expectations = [
(Bootloader.UEFI, "gpt", "/boot/efi"),
Expand Down

0 comments on commit 9fd3c92

Please sign in to comment.