Improve partition type detection, assignment, and misconfig handling (#3336)
This commit is contained in:
parent
e6b0ebb5f3
commit
fa581021eb
|
|
@ -95,13 +95,19 @@ class PartitioningList(ListManager):
|
|||
'assign_mountpoint': str(_('Assign mountpoint')),
|
||||
'mark_formatting': str(_('Mark/Unmark to be formatted (wipes data)')),
|
||||
'mark_bootable': str(_('Mark/Unmark as bootable')),
|
||||
'mark_xbootldr': str(_('Mark/Unmark as XBOOTLDR')),
|
||||
}
|
||||
if self._using_gpt:
|
||||
self._actions.update({
|
||||
'mark_esp': str(_('Mark/Unmark as ESP')),
|
||||
'mark_xbootldr': str(_('Mark/Unmark as XBOOTLDR'))
|
||||
})
|
||||
self._actions.update({
|
||||
'set_filesystem': str(_('Change filesystem')),
|
||||
'btrfs_mark_compressed': str(_('Mark/Unmark as compressed')), # btrfs only
|
||||
'btrfs_mark_nodatacow': str(_('Mark/Unmark as nodatacow')), # btrfs only
|
||||
'btrfs_set_subvolumes': str(_('Set subvolumes')), # btrfs only
|
||||
'delete_partition': str(_('Delete partition'))
|
||||
}
|
||||
})
|
||||
|
||||
device_partitions = []
|
||||
|
||||
|
|
@ -239,8 +245,14 @@ class PartitioningList(ListManager):
|
|||
# how do we know it was the original one?
|
||||
not_filter += [
|
||||
self._actions['set_filesystem'],
|
||||
self._actions['mark_bootable'],
|
||||
self._actions['mark_xbootldr'],
|
||||
self._actions['mark_bootable']
|
||||
]
|
||||
if self._using_gpt:
|
||||
not_filter += [
|
||||
self._actions['mark_esp'],
|
||||
self._actions['mark_xbootldr']
|
||||
]
|
||||
not_filter += [
|
||||
self._actions['btrfs_mark_compressed'],
|
||||
self._actions['btrfs_mark_nodatacow'],
|
||||
self._actions['btrfs_set_subvolumes']
|
||||
|
|
@ -287,23 +299,46 @@ class PartitioningList(ListManager):
|
|||
action_key = [k for k, v in self._actions.items() if v == action][0]
|
||||
match action_key:
|
||||
case 'assign_mountpoint':
|
||||
partition.mountpoint = self._prompt_mountpoint()
|
||||
if partition.mountpoint == Path('/boot'):
|
||||
partition.set_flag(PartitionFlag.BOOT)
|
||||
if self._using_gpt:
|
||||
partition.set_flag(PartitionFlag.ESP)
|
||||
new_mountpoint = self._prompt_mountpoint()
|
||||
if not partition.is_swap():
|
||||
if partition.is_home():
|
||||
partition.invert_flag(PartitionFlag.LINUX_HOME)
|
||||
partition.mountpoint = new_mountpoint
|
||||
if partition.is_root():
|
||||
partition.flags = []
|
||||
if partition.is_boot():
|
||||
partition.flags = []
|
||||
partition.set_flag(PartitionFlag.BOOT)
|
||||
if self._using_gpt:
|
||||
partition.set_flag(PartitionFlag.ESP)
|
||||
if partition.is_home():
|
||||
partition.flags = []
|
||||
partition.set_flag(PartitionFlag.LINUX_HOME)
|
||||
case 'mark_formatting':
|
||||
self._prompt_formatting(partition)
|
||||
case 'mark_bootable':
|
||||
partition.invert_flag(PartitionFlag.BOOT)
|
||||
if self._using_gpt:
|
||||
if not partition.is_swap():
|
||||
partition.invert_flag(PartitionFlag.BOOT)
|
||||
case 'mark_esp':
|
||||
if not partition.is_root() and not partition.is_home() and not partition.is_swap():
|
||||
if PartitionFlag.XBOOTLDR in partition.flags:
|
||||
partition.invert_flag(PartitionFlag.XBOOTLDR)
|
||||
partition.invert_flag(PartitionFlag.ESP)
|
||||
case 'mark_xbootldr':
|
||||
partition.invert_flag(PartitionFlag.XBOOTLDR)
|
||||
if not partition.is_root() and not partition.is_home() and not partition.is_swap():
|
||||
if PartitionFlag.ESP in partition.flags:
|
||||
partition.invert_flag(PartitionFlag.ESP)
|
||||
partition.invert_flag(PartitionFlag.XBOOTLDR)
|
||||
case 'set_filesystem':
|
||||
fs_type = self._prompt_partition_fs_type()
|
||||
if fs_type:
|
||||
if partition.is_swap():
|
||||
partition.invert_flag(PartitionFlag.SWAP)
|
||||
partition.fs_type = fs_type
|
||||
if partition.is_swap():
|
||||
partition.mountpoint = None
|
||||
partition.flags = []
|
||||
partition.set_flag(PartitionFlag.SWAP)
|
||||
# btrfs subvolumes will define mountpoints
|
||||
if fs_type == FilesystemType.Btrfs:
|
||||
partition.mountpoint = None
|
||||
|
|
@ -390,7 +425,6 @@ class PartitioningList(ListManager):
|
|||
|
||||
def _prompt_mountpoint(self) -> Path:
|
||||
header = str(_('Partition mount-points are relative to inside the installation, the boot would be /boot as an example.')) + '\n'
|
||||
header += str(_('If mountpoint /boot is set, then the partition will also be marked as bootable.')) + '\n'
|
||||
prompt = str(_('Mountpoint'))
|
||||
|
||||
mountpoint = prompt_dir(prompt, header, validate=False, allow_skip=False)
|
||||
|
|
@ -520,6 +554,8 @@ class PartitioningList(ListManager):
|
|||
if self._using_gpt:
|
||||
partition.set_flag(PartitionFlag.ESP)
|
||||
elif partition.is_swap():
|
||||
partition.mountpoint = None
|
||||
partition.flags = []
|
||||
partition.set_flag(PartitionFlag.SWAP)
|
||||
|
||||
return partition
|
||||
|
|
|
|||
|
|
@ -425,21 +425,40 @@ class GlobalMenu(AbstractMenu):
|
|||
shim if necessary.
|
||||
"""
|
||||
bootloader = self._item_group.find_by_key('bootloader').value
|
||||
root_partition: PartitionModification | None = None
|
||||
boot_partition: PartitionModification | None = None
|
||||
efi_partition: PartitionModification | None = None
|
||||
|
||||
if disk_config := self._item_group.find_by_key('disk_config').value:
|
||||
for layout in disk_config.device_modifications:
|
||||
if root_partition := layout.get_root_partition():
|
||||
break
|
||||
for layout in disk_config.device_modifications:
|
||||
if boot_partition := layout.get_boot_partition():
|
||||
break
|
||||
if SysInfo.has_uefi():
|
||||
for layout in disk_config.device_modifications:
|
||||
if efi_partition := layout.get_efi_partition():
|
||||
break
|
||||
else:
|
||||
return "No disk layout selected"
|
||||
|
||||
if root_partition is None:
|
||||
return "Root partition not found"
|
||||
|
||||
if boot_partition is None:
|
||||
return "Boot partition not found"
|
||||
|
||||
if SysInfo.has_uefi():
|
||||
if efi_partition is None:
|
||||
return "EFI system partition (ESP) not found"
|
||||
|
||||
if efi_partition.fs_type not in [FilesystemType.Fat12, FilesystemType.Fat16, FilesystemType.Fat32]:
|
||||
return "ESP must be formatted as a FAT filesystem"
|
||||
|
||||
if bootloader == Bootloader.Limine:
|
||||
if boot_partition.fs_type != FilesystemType.Fat32:
|
||||
return "Limine does not support booting without a FAT boot partition"
|
||||
if boot_partition.fs_type not in [FilesystemType.Fat12, FilesystemType.Fat16, FilesystemType.Fat32]:
|
||||
return "Limine does not support booting with a non-FAT boot partition"
|
||||
|
||||
return None
|
||||
|
||||
|
|
|
|||
|
|
@ -871,9 +871,6 @@ class PartitionModification:
|
|||
partuuid: str | None = None
|
||||
uuid: str | None = None
|
||||
|
||||
_efi_indicator_flags = (PartitionFlag.BOOT, PartitionFlag.ESP)
|
||||
_boot_indicator_flags = (PartitionFlag.BOOT, PartitionFlag.XBOOTLDR)
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
# needed to use the object as a dictionary key due to hash func
|
||||
if not hasattr(self, '_obj_id'):
|
||||
|
|
@ -951,26 +948,16 @@ class PartitionModification:
|
|||
raise ValueError('Mountpoint is not specified')
|
||||
|
||||
def is_efi(self) -> bool:
|
||||
return (
|
||||
any(set(self.flags) & set(self._efi_indicator_flags))
|
||||
and (
|
||||
self.fs_type == FilesystemType.Fat12
|
||||
or self.fs_type == FilesystemType.Fat16
|
||||
or self.fs_type == FilesystemType.Fat32
|
||||
)
|
||||
and PartitionFlag.XBOOTLDR not in self.flags
|
||||
)
|
||||
return PartitionFlag.ESP in self.flags
|
||||
|
||||
def is_boot(self) -> bool:
|
||||
"""
|
||||
Returns True if any of the boot indicator flags are found in self.flags
|
||||
or if the partition is mounted on /boot
|
||||
"""
|
||||
return any(set(self.flags) & set(self._boot_indicator_flags)) or Path('/boot') == self.mountpoint
|
||||
if self.mountpoint is not None:
|
||||
return self.mountpoint == Path('/boot')
|
||||
return False
|
||||
|
||||
def is_root(self) -> bool:
|
||||
if self.mountpoint is not None:
|
||||
return Path('/') == self.mountpoint
|
||||
return self.mountpoint == Path('/')
|
||||
else:
|
||||
for subvol in self.btrfs_subvols:
|
||||
if subvol.is_root():
|
||||
|
|
@ -979,10 +966,9 @@ class PartitionModification:
|
|||
return False
|
||||
|
||||
def is_home(self) -> bool:
|
||||
return (
|
||||
self.mountpoint == Path('/home')
|
||||
or PartitionFlag.LINUX_HOME in self.flags
|
||||
)
|
||||
if self.mountpoint is not None:
|
||||
return self.mountpoint == Path('/home')
|
||||
return False
|
||||
|
||||
def is_swap(self) -> bool:
|
||||
return self.fs_type == FilesystemType.LinuxSwap
|
||||
|
|
@ -1377,26 +1363,12 @@ class DeviceModification:
|
|||
self.partitions.append(partition)
|
||||
|
||||
def get_efi_partition(self) -> PartitionModification | None:
|
||||
"""
|
||||
Similar to get_boot_partition() but excludes XBOOTLDR partitions from it's candidates.
|
||||
"""
|
||||
filtered = filter(lambda x: x.is_efi() and x.mountpoint, self.partitions)
|
||||
return next(filtered, None)
|
||||
|
||||
def get_boot_partition(self) -> PartitionModification | None:
|
||||
"""
|
||||
Returns the first partition marked as XBOOTLDR (PARTTYPE id of bc13c2ff-...) or Boot and has a mountpoint.
|
||||
Only returns XBOOTLDR if separate EFI is detected using self.get_efi_partition()
|
||||
Will return None if no suitable partition is found.
|
||||
"""
|
||||
if efi_partition := self.get_efi_partition():
|
||||
filtered = filter(lambda x: x.is_boot() and x != efi_partition and x.mountpoint, self.partitions)
|
||||
if boot_partition := next(filtered, None):
|
||||
return boot_partition
|
||||
return efi_partition
|
||||
else:
|
||||
filtered = filter(lambda x: x.is_boot() and x.mountpoint, self.partitions)
|
||||
return next(filtered, None)
|
||||
filtered = filter(lambda x: x.is_boot() and x.mountpoint, self.partitions)
|
||||
return next(filtered, None)
|
||||
|
||||
def get_root_partition(self) -> PartitionModification | None:
|
||||
filtered = filter(lambda x: x.is_root(), self.partitions)
|
||||
|
|
|
|||
Loading…
Reference in New Issue