From 4e9b1c163574b44517c6e09de4c91c4ef5995969 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Thu, 10 Jun 2021 20:38:35 +0200 Subject: Renamed vfat -> fat32 for the purpose of consistency. Most actions are referring to fat32, it's only mkfs that has the notion vfat and then -F32 for format 32. And I think vfat confuses more people than it does good, so sticking with fat32 which works better with parted as well. Also added the partitioning logic, started on the mounting logic --- archinstall/lib/disk.py | 79 +++++++++++++++++++++++++++---------- archinstall/lib/user_interaction.py | 19 ++------- examples/guided.py | 1 + 3 files changed, 63 insertions(+), 36 deletions(-) diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index 211bbcb5..4fb3d1e0 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -13,10 +13,19 @@ GPT = 0b00000001 MBR = 0b00000010 -# import ctypes -# import ctypes.util -# libc = ctypes.CDLL(ctypes.util.find_library('c'), use_errno=True) -# libc.mount.argtypes = (ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_ulong, ctypes.c_char_p) +def valid_fs_type(fstype :str) -> bool: + # https://www.gnu.org/software/parted/manual/html_node/mkpart.html + + return fstype in [ + "ext2", + "fat16", "fat32", + "hfs", "hfs+", "hfsx", + "linux-swap", + "NTFS", + "reiserfs", + "ufs", + "btrfs", + ] class BlockDevice: @@ -177,6 +186,11 @@ class BlockDevice: def flush_cache(self): self.part_cache = {} + def get_partition(self, uuid): + for partition in self: + if partition.uuid == uuid: + return partition + class Partition: def __init__(self, path: str, block_device: BlockDevice, part_id=None, size=-1, filesystem=None, mountpoint=None, encrypted=False, autodetect_filesystem=True): @@ -425,34 +439,34 @@ class Partition: if filesystem == 'btrfs': if b'UUID' not in (mkfs := SysCommand(f'/usr/bin/mkfs.btrfs -f {path}')): raise DiskError(f'Could not format {path} with {filesystem} because: {mkfs}') - self.filesystem = 'btrfs' + self.filesystem = filesystem - elif filesystem == 'vfat': + elif filesystem == 'fat32': mkfs = SysCommand(f'/usr/bin/mkfs.vfat -F32 {path}') if (b'mkfs.fat' not in mkfs and b'mkfs.vfat' not in mkfs) or b'command not found' in mkfs: raise DiskError(f"Could not format {path} with {filesystem} because: {mkfs}") - self.filesystem = 'vfat' + self.filesystem = filesystem elif filesystem == 'ext4': if (handle := SysCommand(f'/usr/bin/mkfs.ext4 -F {path}')).exit_code != 0: raise DiskError(f"Could not format {path} with {filesystem} because: {handle.decode('UTF-8')}") - self.filesystem = 'ext4' + self.filesystem = filesystem elif filesystem == 'xfs': if (handle := SysCommand(f'/usr/bin/mkfs.xfs -f {path}')).exit_code != 0: raise DiskError(f"Could not format {path} with {filesystem} because: {handle.decode('UTF-8')}") - self.filesystem = 'xfs' + self.filesystem = filesystem elif filesystem == 'f2fs': if (handle := SysCommand(f'/usr/bin/mkfs.f2fs -f {path}')).exit_code != 0: raise DiskError(f"Could not format {path} with {filesystem} because: {handle.decode('UTF-8')}") - self.filesystem = 'f2fs' + self.filesystem = filesystem elif filesystem == 'crypto_LUKS': # from .luks import luks2 # encrypted_partition = luks2(self, None, None) # encrypted_partition.format(path) - self.filesystem = 'crypto_LUKS' + self.filesystem = filesystem else: raise UnknownFilesystemFormat(f"Fileformat '{filesystem}' is not yet implemented.") @@ -583,12 +597,32 @@ class Filesystem: # We then iterate the partitions in order for partition in layout.get('partitions', []): # We don't want to re-add an existing partition (those containing a UUID already) - if 'UUID' not in partition: - self.add_partition(partition.get('type', 'primary'), - start=partition.get('start', '1MiB'), # TODO: Revisit sane block starts (4MB for memorycards for instance) - end=partition.get('size', '100%'), - partition_format=partition.get('filesystem', {}).get('format', 'btrfs')) + if partition.get('format', False) and not partition.get('uuid', None): + partition['device_instance'] = self.add_partition(partition.get('type', 'primary'), + start=partition.get('start', '1MiB'), # TODO: Revisit sane block starts (4MB for memorycards for instance) + end=partition.get('size', '100%'), + partition_format=partition.get('filesystem', {}).get('format', 'btrfs')) + + elif partition_uuid := partition.get('uuid'): + if partition_instance := self.blockdevice.get_partition(uuid=partition_uuid): + partition['device_instance'] = partition_instance + else: + raise ValueError("BlockDevice().load_layout() doesn't know how to continue without either a UUID or creation of partition.") + + if partition.get('filesystem', {}).get('format', None): + if partition.get('encrypt', False): + assert partition.get('password') + partition['device_instance'].encrypt(password=partition['password']) + with archinstall.luks2(partition['device_instance'], 'luksloop', partition['password']) as unlocked_device: + unlocked_device.format(partition['filesystem']['format'], allow_formatting=partition.get('format', False)) + else: + partition['device_instance'].format(partition['filesystem']['format'], allow_formatting=partition.get('format', False)) + + def mount_ordered_layout(self, layout :dict): + mountpoints = {} + for partition in layout['partitions']: + print(partition) exit(0) def find_partition(self, mountpoint): @@ -610,17 +644,19 @@ class Filesystem: """ return self.raw_parted(string).exit_code - def use_entire_disk(self, root_filesystem_type='ext4'): + def use_entire_disk(self, root_filesystem_type='ext4') -> Partition: # TODO: Implement this with declarative profiles instead. raise ValueError("Installation().use_entire_disk() has to be re-worked.") def add_partition(self, partition_type, start, end, partition_format=None): log(f'Adding partition to {self.blockdevice}, {start}->{end}', level=logging.INFO) - previous_partitions = self.blockdevice.partitions + previous_partition_uuids = {partition.uuid for partition in self.blockdevice.partitions.values()} + if self.mode == MBR: if len(self.blockdevice.partitions) > 3: DiskError("Too many partitions on disk, MBR disks can only have 3 parimary partitions") + if partition_format: partitioning = self.parted(f'{self.blockdevice.device} mkpart {partition_type} {partition_format} {start} {end}') == 0 else: @@ -628,12 +664,13 @@ class Filesystem: if partitioning: start_wait = time.time() - while previous_partitions == self.blockdevice.partitions: - time.sleep(0.025) # Let the new partition come up in the kernel + while previous_partition_uuids == {partition.uuid for partition in self.blockdevice.partitions.values()}: if time.time() - start_wait > 10: raise DiskError(f"New partition never showed up after adding new partition on {self} (timeout 10 seconds).") + time.sleep(0.025) - return True + time.sleep(0.5) # Let the kernel catch up with quick block devices (nvme for instance) + return self.blockdevice.get_partition(uuid=(previous_partition_uuids ^ {partition.uuid for partition in self.blockdevice.partitions.values()}).pop()) def set_name(self, partition: int, name: str): return self.parted(f'{self.blockdevice.device} name {partition + 1} "{name}"') == 0 diff --git a/archinstall/lib/user_interaction.py b/archinstall/lib/user_interaction.py index 2c333d3a..6860f00b 100644 --- a/archinstall/lib/user_interaction.py +++ b/archinstall/lib/user_interaction.py @@ -9,7 +9,7 @@ import signal import sys import time -from .disk import BlockDevice +from .disk import BlockDevice, valid_fs_type from .exceptions import * from .general import SysCommand from .hardware import AVAILABLE_GFX_DRIVERS, has_uefi @@ -580,20 +580,6 @@ def select_partition_layout(block_device): } } -def valid_fs_type(fstype :str) -> bool: - # https://www.gnu.org/software/parted/manual/html_node/mkpart.html - - return fstype in [ - "ext2", - "fat16", "fat32", - "hfs", "hfs+", "hfsx", - "linux-swap", - "NTFS", - "reiserfs", - "ufs", - "btrfs", - ] - def valid_parted_position(pos :str): if not len(pos): return False @@ -630,6 +616,7 @@ def get_default_partition_layout(block_devices): "start" : "1MiB", "size" : "513MiB", "boot" : True, + "format" : True, "mountpoint" : "/boot", "filesystem" : { "format" : "fat32" @@ -640,6 +627,7 @@ def get_default_partition_layout(block_devices): "type" : "primary", "start" : "513MiB", "encrypted" : True, + "format" : True, "size" : "100%" if block_devices[0].size < MIN_SIZE_TO_ALLOW_HOME_PART else f"{min(block_devices[0].size, 20)*1024}MiB", "mountpoint" : "/", "filesystem" : { @@ -652,6 +640,7 @@ def get_default_partition_layout(block_devices): # Home "type" : "primary", "encrypted" : True, + "format" : True, "start" : f"{min(block_devices[0].size*0.2, 20)*1024}MiB", "size" : "100%", "mountpoint" : "/home", diff --git a/examples/guided.py b/examples/guided.py index f477a738..2e2d0d98 100644 --- a/examples/guided.py +++ b/examples/guided.py @@ -223,6 +223,7 @@ def perform_filesystem_operations(): for drive in archinstall.arguments['harddrives']: with archinstall.Filesystem(drive, mode) as fs: fs.load_layout(archinstall.storage['disk_layouts'][drive]) + fs.mount_ordered_layout(archinstall.storage['disk_layouts'][drive]) perform_installation(archinstall.storage.get('MOUNT_POINT', '/mnt')) -- cgit v1.2.3-70-g09d2