From 1aa738691e261b3dfaf5195ec7636617a283d47a Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Tue, 25 Jan 2022 16:09:34 +0100 Subject: Fixing the 'device_instance' being None in some partition places (#902) * Added a new return value from add_partition. Also added an exception to make sure `add_partition` can't continue silently * Added a log of debugging to add_partition * Removed a blank line (flake8) * Misconfigured variable * Added some more debugging information to partprobe * FIX: disk layout: partprobe should be called and checked only for target device (#896) * disk layout: partprobe should be called and checked only for target device * disk layout: partprobe: removed unnecessary bash subprocess * Properly defined BlockDevice() on Partition() creation. Also made sure mount-checks got some rrro handling and non-block devices should no longer attempt to return a size Co-authored-by: Anton Hvornum Co-authored-by: Victor Gavro --- archinstall/lib/disk/filesystem.py | 46 ++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 12 deletions(-) (limited to 'archinstall/lib/disk/filesystem.py') diff --git a/archinstall/lib/disk/filesystem.py b/archinstall/lib/disk/filesystem.py index a4fe2cff..b5dcdf85 100644 --- a/archinstall/lib/disk/filesystem.py +++ b/archinstall/lib/disk/filesystem.py @@ -89,12 +89,16 @@ class Filesystem: print("Re-using partition_instance:", partition_instance) partition['device_instance'] = partition_instance else: - raise ValueError(f"{self}.load_layout() doesn't know how to continue without a new partition definition or a UUID ({partition.get('PARTUUID')}) on the device ({self.blockdevice.get_partition(uuid=partition_uuid)}).") + raise ValueError(f"{self}.load_layout() doesn't know how to continue without a new partition definition or a UUID ({partition.get('PARTUUID')}) on the device ({self.blockdevice.get_partition(uuid=partition.get('PARTUUID'))}).") if partition.get('filesystem', {}).get('format', False): + # needed for backward compatibility with the introduction of the new "format_options" format_options = partition.get('options',[]) + partition.get('filesystem',{}).get('format_options',[]) if partition.get('encrypted', False): + if not partition['device_instance']: + raise DiskError(f"Internal error caused us to loose the partition. Please report this issue upstream!") + if not partition.get('!password'): if not storage['arguments'].get('!encryption-password'): if storage['arguments'] == 'silent': @@ -109,6 +113,7 @@ class Filesystem: loopdev = f"{storage.get('ENC_IDENTIFIER', 'ai')}{pathlib.Path(partition['mountpoint']).name}loop" else: loopdev = f"{storage.get('ENC_IDENTIFIER', 'ai')}{pathlib.Path(partition['device_instance'].path).name}" + partition['device_instance'].encrypt(password=partition['!password']) # Immediately unlock the encrypted device to format the inner volume with luks2(partition['device_instance'], loopdev, partition['!password'], auto_unmount=True) as unlocked_device: @@ -129,6 +134,9 @@ class Filesystem: unlocked_device.format(partition['filesystem']['format'], options=format_options) elif partition.get('format', False): + if not partition['device_instance']: + raise DiskError(f"Internal error caused us to loose the partition. Please report this issue upstream!") + partition['device_instance'].format(partition['filesystem']['format'], options=format_options) if partition.get('boot', False): @@ -141,7 +149,13 @@ class Filesystem: return partition def partprobe(self) -> bool: - return SysCommand(f'partprobe {self.blockdevice.device}').exit_code == 0 + result = SysCommand(f'partprobe {self.blockdevice.device}') + + if result.exit_code != 0: + log(f"Could not execute partprobe: {result!r}", level=logging.ERROR, fg="red") + raise DiskError(f"Could not run partprobe: {result!r}") + + return True def raw_parted(self, string: str) -> SysCommand: if (cmd_handle := SysCommand(f'/usr/bin/parted -s {string}')).exit_code != 0: @@ -157,9 +171,7 @@ class Filesystem: :type string: str """ if (parted_handle := self.raw_parted(string)).exit_code == 0: - if self.partprobe(): - return True - return False + return self.partprobe() else: raise DiskError(f"Parted failed to add a partition: {parted_handle}") @@ -167,7 +179,7 @@ class Filesystem: # TODO: Implement this with declarative profiles instead. raise ValueError("Installation().use_entire_disk() has to be re-worked.") - def add_partition(self, partition_type :str, start :str, end :str, partition_format :Optional[str] = None) -> None: + def add_partition(self, partition_type :str, start :str, end :str, partition_format :Optional[str] = None) -> Partition: log(f'Adding partition to {self.blockdevice}, {start}->{end}', level=logging.INFO) previous_partition_uuids = {partition.uuid for partition in self.blockdevice.partitions.values()} @@ -181,31 +193,41 @@ class Filesystem: else: parted_string = f'{self.blockdevice.device} mkpart {partition_type} {start} {end}' + log(f"Adding partition using the following parted command: {parted_string}", level=logging.DEBUG) + if self.parted(parted_string): count = 0 while count < 10: new_uuid = None new_uuid_set = (previous_partition_uuids ^ {partition.uuid for partition in self.blockdevice.partitions.values()}) + if len(new_uuid_set) > 0: new_uuid = new_uuid_set.pop() + if new_uuid: try: return self.blockdevice.get_partition(new_uuid) except Exception as err: - print('Blockdevice:', self.blockdevice) - print('Partitions:', self.blockdevice.partitions) - print('Partition set:', new_uuid_set) - print('New UUID:', [new_uuid]) - print('get_partition():', self.blockdevice.get_partition) + log(f'Blockdevice: {self.blockdevice}', level=logging.ERROR, fg="red") + log(f'Partitions: {self.blockdevice.partitions}', level=logging.ERROR, fg="red") + log(f'Partition set: {new_uuid_set}', level=logging.ERROR, fg="red") + log(f'New UUID: {[new_uuid]}', level=logging.ERROR, fg="red") + log(f'get_partition(): {self.blockdevice.get_partition}', level=logging.ERROR, fg="red") raise err else: count += 1 log(f"Could not get UUID for partition. Waiting before retry attempt {count} of 10 ...",level=logging.DEBUG) time.sleep(float(storage['arguments'].get('disk-sleep', 0.2))) else: - log("Add partition is exiting due to excessive wait time",level=logging.INFO) + log("Add partition is exiting due to excessive wait time", level=logging.ERROR, fg="red") raise DiskError(f"New partition never showed up after adding new partition on {self}.") + # TODO: This should never be able to happen + log(f"Could not find the new PARTUUID after adding the partition.", level=logging.ERROR, fg="red") + log(f"Previous partitions: {previous_partition_uuids}", level=logging.ERROR, fg="red") + log(f"New partitions: {(previous_partition_uuids ^ {partition.uuid for partition in self.blockdevice.partitions.values()})}", level=logging.ERROR, fg="red") + raise DiskError(f"Could not add partition using: {parted_string}") + def set_name(self, partition: int, name: str) -> bool: return self.parted(f'{self.blockdevice.device} name {partition + 1} "{name}"') == 0 -- cgit v1.2.3-54-g00ecf