Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion archinstall/lib/disk/device_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -561,7 +561,7 @@ def partition(
# Wipe filesystem/LVM signatures from newly created partitions
# to prevent "signature detected" errors
for part_mod in filtered_part:
if part_mod.dev_path:
if part_mod.is_create_or_modify() and part_mod.dev_path:
debug(f'Wiping signatures from: {part_mod.dev_path}')
SysCommand(f'wipefs --all {part_mod.dev_path}')

Expand Down
4 changes: 2 additions & 2 deletions archinstall/lib/disk/encryption_menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -315,8 +315,8 @@ async def select_partitions_to_encrypt(
for mod in modification:
partitions += [p for p in mod.partitions if p.mountpoint != Path('/boot') and not p.is_swap()]

# do not allow encrypting existing partitions that are not marked as wipe
avail_partitions = [p for p in partitions if not p.exists()]
# do not allow encrypting existing or deleted partitions
avail_partitions = [p for p in partitions if p.is_create_or_modify()]

if avail_partitions:
group = MenuItemGroup.from_objects(avail_partitions)
Expand Down
10 changes: 4 additions & 6 deletions archinstall/lib/disk/filesystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,14 +293,12 @@ def _encrypt_partitions(
for mod in self._disk_config.device_modifications:
partitions = mod.partitions

# don't touch existing partitions
filtered_part = [p for p in partitions if not p.exists()]
# don't touch existing or deleted partitions
create_or_modify_parts = [p for p in partitions if p.is_create_or_modify()]

self._validate_partitions(filtered_part)
self._validate_partitions(create_or_modify_parts)

enc_mods = {}

for part_mod in filtered_part:
for part_mod in create_or_modify_parts:
if part_mod in enc_config.partitions:
luks_handler = device_handler.encrypt(
part_mod.safe_dev_path,
Expand Down
127 changes: 127 additions & 0 deletions tests/test_disk_partitioning.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
from pathlib import Path
from unittest.mock import MagicMock

from pytest import MonkeyPatch

from archinstall.lib.disk.device_handler import DeviceHandler
from archinstall.lib.disk.filesystem import FilesystemHandler
from archinstall.lib.models.device import (
BDevice,
DeviceModification,
DiskEncryption,
DiskLayoutConfiguration,
DiskLayoutType,
EncryptionType,
FilesystemType,
ModificationStatus,
PartitionModification,
PartitionTable,
PartitionType,
SectorSize,
Size,
Unit,
)
from archinstall.lib.models.users import Password


def _make_partition_mod(
status: ModificationStatus,
dev_path: Path | None,
fs_type: FilesystemType | None = FilesystemType.EXT4,
) -> PartitionModification:
sector_size = SectorSize.default()
return PartitionModification(
status=status,
type=PartitionType.PRIMARY,
start=Size(1, Unit.MiB, sector_size),
length=Size(100, Unit.MiB, sector_size),
fs_type=fs_type,
dev_path=dev_path,
)


def test_partition_skips_wipefs_for_deleted_partitions(monkeypatch: MonkeyPatch) -> None:
handler = object.__new__(DeviceHandler)

mock_disk = MagicMock()
mock_bdevice = MagicMock(spec=BDevice)
mock_bdevice.disk = mock_disk
mock_bdevice.device_info = MagicMock()
mock_bdevice.device_info.path = Path('/dev/sda')

part_exist = _make_partition_mod(ModificationStatus.EXIST, Path('/dev/sda1'))
part_delete = _make_partition_mod(ModificationStatus.DELETE, Path('/dev/sda2'), fs_type=None)
part_modify = _make_partition_mod(ModificationStatus.MODIFY, Path('/dev/sda3'))
part_create = _make_partition_mod(ModificationStatus.CREATE, None)

setup_calls: list[PartitionModification] = []

def fake_setup_partition(
part_mod: PartitionModification,
_block_device: BDevice,
_disk: object,
**_kwargs: object,
) -> None:
setup_calls.append(part_mod)
if part_mod.status == ModificationStatus.CREATE:
part_mod.dev_path = Path('/dev/sda4')

monkeypatch.setattr(handler, '_setup_partition', fake_setup_partition)

wipefs_cmds: list[str] = []
monkeypatch.setattr(
'archinstall.lib.disk.device_handler.SysCommand',
lambda cmd: wipefs_cmds.append(str(cmd)),
)
monkeypatch.setattr('archinstall.lib.disk.device_handler.udev_sync', lambda: None)

mod = DeviceModification(
device=mock_bdevice,
wipe=False,
partitions=[part_exist, part_delete, part_modify, part_create],
)

handler.partition(mod, partition_table=PartitionTable.GPT)

assert setup_calls == [part_delete, part_modify, part_create]
mock_disk.commit.assert_called_once()
assert wipefs_cmds == [
'wipefs --all /dev/sda3',
'wipefs --all /dev/sda4',
]


def test_encrypt_partitions_ignores_deleted_and_preserves_multi_disk(monkeypatch: MonkeyPatch) -> None:
mock_bdevice1 = MagicMock(spec=BDevice)
mock_bdevice1.device_info = MagicMock(path=Path('/dev/sda'))
mock_bdevice2 = MagicMock(spec=BDevice)
mock_bdevice2.device_info = MagicMock(path=Path('/dev/sdb'))

part_deleted = _make_partition_mod(ModificationStatus.DELETE, Path('/dev/sda1'), fs_type=None)
part_enc1 = _make_partition_mod(ModificationStatus.CREATE, Path('/dev/sda2'))
part_enc2 = _make_partition_mod(ModificationStatus.CREATE, Path('/dev/sdb1'))

mod1 = DeviceModification(device=mock_bdevice1, wipe=False, partitions=[part_deleted, part_enc1])
mod2 = DeviceModification(device=mock_bdevice2, wipe=False, partitions=[part_enc2])

enc_config = DiskEncryption(
encryption_type=EncryptionType.LVM_ON_LUKS,
encryption_password=Password('secret'),
partitions=[part_enc1, part_enc2],
)

disk_config = DiskLayoutConfiguration(
config_type=DiskLayoutType.Manual,
device_modifications=[mod1, mod2],
disk_encryption=enc_config,
)

monkeypatch.setattr(
'archinstall.lib.disk.filesystem.device_handler.encrypt',
lambda dev_path, *_args, **_kwargs: MagicMock(dev_path=dev_path),
)

fs_handler = FilesystemHandler(disk_config)
enc_mods = fs_handler._encrypt_partitions(enc_config, lock_after_create=False)

assert set(enc_mods.keys()) == {part_enc1, part_enc2}