From 5483b218fd62fcea8648525eb8aa6b7af4cc200b Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 14 Mar 2021 11:53:59 +0100 Subject: Removing hardcoded boot-loader config name. #51. --- archinstall/lib/installer.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 06bdd05a..b45ad1dc 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -311,18 +311,24 @@ class Installer(): self.log(f'Adding bootloader {bootloader} to {self.boot_partition}', level=LOG_LEVELS.Info) if bootloader == 'systemd-bootctl': + # TODO: Ideally we would want to check if another config + # points towards the same disk and/or partition. + # And in which case we should do some clean up. + unique_loader_conf_name = hashlib.md5(os.urandom(12)+bytes(str(time.time()), 'UTF-8')).hexdigest() + o = b''.join(sys_command(f'/usr/bin/arch-chroot {self.mountpoint} bootctl --no-variables --path=/boot install')) with open(f'{self.mountpoint}/boot/loader/loader.conf', 'w') as loader: - loader.write('default arch\n') - loader.write('timeout 5\n') + loader.write(f'default {unique_loader_conf_name}\n') + loader.write(f'timeout 5\n') ## For some reason, blkid and /dev/disk/by-uuid are not getting along well. ## And blkid is wrong in terms of LUKS. #UUID = sys_command('blkid -s PARTUUID -o value {drive}{partition_2}'.format(**args)).decode('UTF-8').strip() - with open(f'{self.mountpoint}/boot/loader/entries/arch.conf', 'w') as entry: - entry.write('title Arch Linux\n') - entry.write('linux /vmlinuz-linux\n') - entry.write('initrd /initramfs-linux.img\n') + + with open(f'{self.mountpoint}/boot/loader/entries/{unique_loader_conf_name}.conf', 'w') as entry: + entry.write(f'title Arch Linux\n') + entry.write(f'linux /vmlinuz-linux\n') + entry.write(f'initrd /initramfs-linux.img\n') ## blkid doesn't trigger on loopback devices really well, ## so we'll use the old manual method until we get that sorted out. -- cgit v1.2.3-54-g00ecf From 577428f1b20da6f7f583c9c3c276ee1d38abb01d Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 14 Mar 2021 12:13:08 +0100 Subject: Added a partition.umount() and a check when running cryptsetup if the disk is in use. --- archinstall/lib/disk.py | 5 +++++ archinstall/lib/luks.py | 10 ++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index c05ba757..16756df8 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -312,6 +312,11 @@ class Partition(): self.mountpoint = target return True + def unmount(self): + if sys_command(f'/usr/bin/umount {self.path}').exit_code == 0: + self.mountpoint = None + return True + def filesystem_supported(self): """ The support for a filesystem (this partition) is tested by calling diff --git a/archinstall/lib/luks.py b/archinstall/lib/luks.py index e54641b8..de53c05e 100644 --- a/archinstall/lib/luks.py +++ b/archinstall/lib/luks.py @@ -64,8 +64,14 @@ class luks2(): with open(key_file, 'wb') as fh: fh.write(password) - o = b''.join(sys_command(f'/usr/bin/cryptsetup -q -v --type luks2 --pbkdf argon2i --hash {hash_type} --key-size {key_size} --iter-time {iter_time} --key-file {os.path.abspath(key_file)} --use-urandom luksFormat {partition.path}')) - if b'Command successful.' not in o: + cmd_handle = sys_command(f'/usr/bin/cryptsetup -q -v --type luks2 --pbkdf argon2i --hash {hash_type} --key-size {key_size} --iter-time {iter_time} --key-file {os.path.abspath(key_file)} --use-urandom luksFormat {partition.path}') + if cmd_handle.exit_code == 256: + # Partition was in use, unmount it and + partition.unmount() + sys_command(f'cryptsetup close {partition.path}') + cmd_handle = sys_command(f'/usr/bin/cryptsetup -q -v --type luks2 --pbkdf argon2i --hash {hash_type} --key-size {key_size} --iter-time {iter_time} --key-file {os.path.abspath(key_file)} --use-urandom luksFormat {partition.path}') + + if b'Command successful.' not in b''.join(cmd_handle): raise DiskError(f'Could not encrypt volume "{partition.path}": {o}') return key_file -- cgit v1.2.3-54-g00ecf From f589750a3cff6f061bc4b78ef857e52a7fbc874c Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 14 Mar 2021 12:16:46 +0100 Subject: Tweaked SysCallError() exception to include the exit code in a machine readable manner. Since it's useful as an indicator where calls might go wrong and for what reason. --- archinstall/lib/exceptions.py | 5 ++++- archinstall/lib/general.py | 2 +- archinstall/lib/luks.py | 14 +++++++++----- 3 files changed, 14 insertions(+), 7 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/exceptions.py b/archinstall/lib/exceptions.py index 5a5d47c6..558a397d 100644 --- a/archinstall/lib/exceptions.py +++ b/archinstall/lib/exceptions.py @@ -7,7 +7,10 @@ class UnknownFilesystemFormat(BaseException): class ProfileError(BaseException): pass class SysCallError(BaseException): - pass + def __init__(self, message, error_code): + super(SysCallError, self).__init__(message) + self.message = message + self.error_code = error_code class ProfileNotFound(BaseException): pass class HardwareIncompatibilityError(BaseException): diff --git a/archinstall/lib/general.py b/archinstall/lib/general.py index e87e4102..28fc0934 100644 --- a/archinstall/lib/general.py +++ b/archinstall/lib/general.py @@ -251,7 +251,7 @@ class sys_command():#Thread): if self.exit_code != 0 and not self.kwargs['suppress_errors']: #self.log(self.trace_log.decode('UTF-8'), level=LOG_LEVELS.Debug) #self.log(f"'{self.raw_cmd}' did not exit gracefully, exit code {self.exit_code}.", level=LOG_LEVELS.Error) - raise SysCallError(f"{self.trace_log.decode('UTF-8')}\n'{self.raw_cmd}' did not exit gracefully (trace log above), exit code: {self.exit_code}") + raise SysCallError(message=f"{self.trace_log.decode('UTF-8')}\n'{self.raw_cmd}' did not exit gracefully (trace log above), exit code: {self.exit_code}", exit_code=self.exit_code) self.ended = time.time() with open(f'{self.cwd}/trace.log', 'wb') as fh: diff --git a/archinstall/lib/luks.py b/archinstall/lib/luks.py index de53c05e..a4d2a07d 100644 --- a/archinstall/lib/luks.py +++ b/archinstall/lib/luks.py @@ -64,12 +64,16 @@ class luks2(): with open(key_file, 'wb') as fh: fh.write(password) - cmd_handle = sys_command(f'/usr/bin/cryptsetup -q -v --type luks2 --pbkdf argon2i --hash {hash_type} --key-size {key_size} --iter-time {iter_time} --key-file {os.path.abspath(key_file)} --use-urandom luksFormat {partition.path}') - if cmd_handle.exit_code == 256: - # Partition was in use, unmount it and - partition.unmount() - sys_command(f'cryptsetup close {partition.path}') + try: cmd_handle = sys_command(f'/usr/bin/cryptsetup -q -v --type luks2 --pbkdf argon2i --hash {hash_type} --key-size {key_size} --iter-time {iter_time} --key-file {os.path.abspath(key_file)} --use-urandom luksFormat {partition.path}') + except SysCallError as err: + if err.exit_code == 256: + # Partition was in use, unmount it and try again + partition.unmount() + sys_command(f'cryptsetup close {partition.path}') + cmd_handle = sys_command(f'/usr/bin/cryptsetup -q -v --type luks2 --pbkdf argon2i --hash {hash_type} --key-size {key_size} --iter-time {iter_time} --key-file {os.path.abspath(key_file)} --use-urandom luksFormat {partition.path}') + else: + raise err if b'Command successful.' not in b''.join(cmd_handle): raise DiskError(f'Could not encrypt volume "{partition.path}": {o}') -- cgit v1.2.3-54-g00ecf From 2ef7be9787c4d3acb91f91308acf7bf5c8715c1a Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 14 Mar 2021 12:17:30 +0100 Subject: Wrong variable name. --- archinstall/lib/exceptions.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/exceptions.py b/archinstall/lib/exceptions.py index 558a397d..a320eef6 100644 --- a/archinstall/lib/exceptions.py +++ b/archinstall/lib/exceptions.py @@ -7,10 +7,10 @@ class UnknownFilesystemFormat(BaseException): class ProfileError(BaseException): pass class SysCallError(BaseException): - def __init__(self, message, error_code): + def __init__(self, message, exit_code): super(SysCallError, self).__init__(message) self.message = message - self.error_code = error_code + self.exit_code = exit_code class ProfileNotFound(BaseException): pass class HardwareIncompatibilityError(BaseException): -- cgit v1.2.3-54-g00ecf From d2804993dbcd9fc6ff743d2886000407ec3b019e Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 14 Mar 2021 12:24:37 +0100 Subject: Added some error handling for umount(). --- archinstall/lib/disk.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index 16756df8..54f86f7a 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -313,9 +313,19 @@ class Partition(): return True def unmount(self): - if sys_command(f'/usr/bin/umount {self.path}').exit_code == 0: - self.mountpoint = None - return True + try: + exit_code = sys_command(f'/usr/bin/umount {self.path}').exit_code + except SysCallError as err: + exit_code = err.exit_code + + # Without to much research, it seams that low error codes are errors. + # And above 8k is indicators such as "/dev/x not mounted.". + # So anything in between 0 and 8k are errors (?). + if exit_code > 0 and exit_code < 8000: + raise err + + self.mountpoint = None + return True def filesystem_supported(self): """ -- cgit v1.2.3-54-g00ecf From 4ac252882291861c612ad1b69a0ce547cbf73ae8 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 14 Mar 2021 12:25:06 +0100 Subject: Added alias umount() to unmount(). --- archinstall/lib/disk.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'archinstall') diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index 54f86f7a..b8a77ef8 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -327,6 +327,9 @@ class Partition(): self.mountpoint = None return True + def umount(self): + return self.unmount() + def filesystem_supported(self): """ The support for a filesystem (this partition) is tested by calling -- cgit v1.2.3-54-g00ecf From e4514e8fc37995656528835d4fd81dc997136575 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 14 Mar 2021 12:27:48 +0100 Subject: Some more error handling. --- archinstall/lib/luks.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'archinstall') diff --git a/archinstall/lib/luks.py b/archinstall/lib/luks.py index a4d2a07d..77622304 100644 --- a/archinstall/lib/luks.py +++ b/archinstall/lib/luks.py @@ -70,7 +70,14 @@ class luks2(): if err.exit_code == 256: # Partition was in use, unmount it and try again partition.unmount() - sys_command(f'cryptsetup close {partition.path}') + try: + sys_command(f'cryptsetup close {partition.path}') + except SysCallError as err: + # 0 Means everything went smoothly, + # 1024 means the device was not found. + if err.exit_code not in (0, 1024): + raise err + cmd_handle = sys_command(f'/usr/bin/cryptsetup -q -v --type luks2 --pbkdf argon2i --hash {hash_type} --key-size {key_size} --iter-time {iter_time} --key-file {os.path.abspath(key_file)} --use-urandom luksFormat {partition.path}') else: raise err -- cgit v1.2.3-54-g00ecf From 1c6d70571481e30651f62f216fcc9653e03c9c62 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 14 Mar 2021 12:50:47 +0100 Subject: Enhanced the error handling on crypt-devices. --- archinstall/lib/luks.py | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/luks.py b/archinstall/lib/luks.py index 77622304..f4c787ab 100644 --- a/archinstall/lib/luks.py +++ b/archinstall/lib/luks.py @@ -65,19 +65,28 @@ class luks2(): fh.write(password) try: + # Try to setup the crypt-device cmd_handle = sys_command(f'/usr/bin/cryptsetup -q -v --type luks2 --pbkdf argon2i --hash {hash_type} --key-size {key_size} --iter-time {iter_time} --key-file {os.path.abspath(key_file)} --use-urandom luksFormat {partition.path}') except SysCallError as err: if err.exit_code == 256: # Partition was in use, unmount it and try again partition.unmount() - try: - sys_command(f'cryptsetup close {partition.path}') - except SysCallError as err: - # 0 Means everything went smoothly, - # 1024 means the device was not found. - if err.exit_code not in (0, 1024): - raise err + # Get crypt-information about the device by doing a reverse lookup starting with the partition path + # For instance: /dev/sda + devinfo = json.loads(b''.join(sys_command(f"lsblk --fs -J {partition.path}")).decode('UTF-8'))['blockdevices'][0] + + # For each child (sub-partition/sub-device) + if len(children := devinfo.get('children', [])): + for child in children: + # Unmount the child location + if child_mountpoint := child.get('mountpoint', None): + sys_command(f"umount {child_mountpoint}") + + # And close it if possible. + sys_command(f"cryptsetup close {child['name']}") + + # Then try again to set up the crypt-device cmd_handle = sys_command(f'/usr/bin/cryptsetup -q -v --type luks2 --pbkdf argon2i --hash {hash_type} --key-size {key_size} --iter-time {iter_time} --key-file {os.path.abspath(key_file)} --use-urandom luksFormat {partition.path}') else: raise err -- cgit v1.2.3-54-g00ecf From 7ac68b2436b3a542d8004b26defb89ebb2905fa9 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 14 Mar 2021 13:54:01 +0100 Subject: Removed redundant error handling as well as added some more debug logs. --- archinstall/lib/luks.py | 3 +++ examples/guided.py | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/luks.py b/archinstall/lib/luks.py index f4c787ab..ff5e2057 100644 --- a/archinstall/lib/luks.py +++ b/archinstall/lib/luks.py @@ -69,6 +69,7 @@ class luks2(): cmd_handle = sys_command(f'/usr/bin/cryptsetup -q -v --type luks2 --pbkdf argon2i --hash {hash_type} --key-size {key_size} --iter-time {iter_time} --key-file {os.path.abspath(key_file)} --use-urandom luksFormat {partition.path}') except SysCallError as err: if err.exit_code == 256: + log(f'{partition} is being used, trying to unmount and crypt-close the device and running one more attempt at encrypting the device.', level=LOG_LEVELS.Debug) # Partition was in use, unmount it and try again partition.unmount() @@ -81,9 +82,11 @@ class luks2(): for child in children: # Unmount the child location if child_mountpoint := child.get('mountpoint', None): + log(f'Unmounting {child_mountpoint}', level=LOG_LEVELS.Debug) sys_command(f"umount {child_mountpoint}") # And close it if possible. + log(f"Closing crypt device {child['name']}", level=LOG_LEVELS.Debug) sys_command(f"cryptsetup close {child['name']}") # Then try again to set up the crypt-device diff --git a/examples/guided.py b/examples/guided.py index 9339f969..74d413aa 100644 --- a/examples/guided.py +++ b/examples/guided.py @@ -305,8 +305,8 @@ def perform_installation(device, boot_partition, language, mirrors): if archinstall.arguments.get('packages', None) and archinstall.arguments.get('packages', None)[0] != '': installation.add_additional_packages(archinstall.arguments.get('packages', None)) - if archinstall.arguments.get('profile', None) and len(profile := archinstall.arguments.get('profile').strip()): - installation.install_profile(profile) + if archinstall.arguments.get('profile', None): + installation.install_profile(archinstall.arguments.get('profile', None)) if archinstall.arguments.get('users', None): for user in archinstall.arguments.get('users'): -- cgit v1.2.3-54-g00ecf From c897421e1d5450450e0ef54118ad40c1d883b7c3 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 14 Mar 2021 13:56:24 +0100 Subject: Using 'umount -R' rather than just 'umount' since we're going to wipe the partition, we need do unmount anything that's mounted beneeth it to continue. --- archinstall/lib/luks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'archinstall') diff --git a/archinstall/lib/luks.py b/archinstall/lib/luks.py index ff5e2057..30c38ec8 100644 --- a/archinstall/lib/luks.py +++ b/archinstall/lib/luks.py @@ -83,7 +83,7 @@ class luks2(): # Unmount the child location if child_mountpoint := child.get('mountpoint', None): log(f'Unmounting {child_mountpoint}', level=LOG_LEVELS.Debug) - sys_command(f"umount {child_mountpoint}") + sys_command(f"umount -R {child_mountpoint}") # And close it if possible. log(f"Closing crypt device {child['name']}", level=LOG_LEVELS.Debug) -- cgit v1.2.3-54-g00ecf From 37b1e618280c8b428824f202902e392792e10c18 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 14 Mar 2021 14:00:52 +0100 Subject: Corrected some spelling errors and wrong variables. --- archinstall/lib/user_interaction.py | 6 +++--- examples/guided.py | 14 +++++--------- 2 files changed, 8 insertions(+), 12 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/user_interaction.py b/archinstall/lib/user_interaction.py index 7e7f5873..ab2b19bc 100644 --- a/archinstall/lib/user_interaction.py +++ b/archinstall/lib/user_interaction.py @@ -31,7 +31,7 @@ def ask_for_superuser_account(prompt='Create a required super-user with sudo pri raise UserError("No superuser was created.") password = get_password(prompt=f'Password for user {new_user}: ') - return {new_user: password} + return {new_user: {"!password" : password}} def ask_for_additional_users(prompt='Any additional users to install (leave blank for no users): '): users = {} @@ -44,9 +44,9 @@ def ask_for_additional_users(prompt='Any additional users to install (leave blan password = get_password(prompt=f'Password for user {new_user}: ') if input("Should this user be a sudo (super) user (y/N): ").strip(' ').lower() in ('y', 'yes'): - super_users[new_user] = password + super_users[new_user] = {"!password" : password} else: - users[new_user] = password + users[new_user] = {"!password" : password} return users, super_users diff --git a/examples/guided.py b/examples/guided.py index 74d413aa..4e6aaf34 100644 --- a/examples/guided.py +++ b/examples/guided.py @@ -308,15 +308,11 @@ def perform_installation(device, boot_partition, language, mirrors): if archinstall.arguments.get('profile', None): installation.install_profile(archinstall.arguments.get('profile', None)) - if archinstall.arguments.get('users', None): - for user in archinstall.arguments.get('users'): - password = users[user] - installation.user_create(user, password, sudo=False) - if archinstall.arguments.get('superusers', None): - for user in archinstall.arguments.get('users'): - password = users[user] - installation.user_create(user, password, sudo=Tru) - + for user, user_info in archinstall.arguments.get('users', {}).items(): + installation.user_create(user, user_info["!password"], sudo=False) + + for superuser, user_info in archinstall.arguments.get('superusers', {}).items(): + installation.user_create(superuser, user_info["!password"], sudo=True) if (root_pw := archinstall.arguments.get('!root-password', None)) and len(root_pw): installation.user_set_pw('root', root_pw) -- cgit v1.2.3-54-g00ecf From abd15f9ff5a53face8b5d8efc29118b7362735b2 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 14 Mar 2021 14:41:13 +0100 Subject: Added error handling for install_profile() if string vs Profile() is given as an argument. --- archinstall/lib/installer.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'archinstall') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index b45ad1dc..3daf96f4 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -363,7 +363,8 @@ class Installer(): return self.pacstrap(*packages) def install_profile(self, profile): - profile = Profile(self, profile) + if type(profile) == str: + profile = Profile(self, profile) self.log(f'Installing network profile {profile}', level=LOG_LEVELS.Info) return profile.install() -- cgit v1.2.3-54-g00ecf From b90820c1c0e4848b683bbee8e3ffe489b4031935 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 14 Mar 2021 14:58:06 +0100 Subject: Made add_bootloader() a little bit more robust, it shouldn't overwrite the existing loader.conf completely, only the default option. We're still left with a lot of garbage entries if installed multiple times on the same boot partition. #51 --- archinstall/lib/installer.py | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 3daf96f4..39e3447d 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -314,18 +314,35 @@ class Installer(): # TODO: Ideally we would want to check if another config # points towards the same disk and/or partition. # And in which case we should do some clean up. - unique_loader_conf_name = hashlib.md5(os.urandom(12)+bytes(str(time.time()), 'UTF-8')).hexdigest() - o = b''.join(sys_command(f'/usr/bin/arch-chroot {self.mountpoint} bootctl --no-variables --path=/boot install')) + # Install the boot loader + sys_command(f'/usr/bin/arch-chroot {self.mountpoint} bootctl --no-variables --path=/boot install') + + # Modify or create a loader.conf + if os.path.isfile(f'{self.mountpoint}/boot/loader/loader.conf'): + with open(f'{self.mountpoint}/boot/loader/loader.conf', 'r') as loader: + loader_data = loader.read().split('\n') + else: + loader_data = [ + f"default {self.init_time}", + f"timeout 5" + ] + with open(f'{self.mountpoint}/boot/loader/loader.conf', 'w') as loader: - loader.write(f'default {unique_loader_conf_name}\n') - loader.write(f'timeout 5\n') + for line in loader_data: + if line[:8] == 'default ': + loader.write(f'default {self.init_time}\n') + else: + loader.write(f"{line}") ## For some reason, blkid and /dev/disk/by-uuid are not getting along well. ## And blkid is wrong in terms of LUKS. #UUID = sys_command('blkid -s PARTUUID -o value {drive}{partition_2}'.format(**args)).decode('UTF-8').strip() - with open(f'{self.mountpoint}/boot/loader/entries/{unique_loader_conf_name}.conf', 'w') as entry: + # Setup the loader entry + with open(f'{self.mountpoint}/boot/loader/entries/{self.init_time}.conf', 'w') as entry: + entry.write(f'# Created by: archinstall\n') + entry.write(f'# Created on: {self.init_time}\n') entry.write(f'title Arch Linux\n') entry.write(f'linux /vmlinuz-linux\n') entry.write(f'initrd /initramfs-linux.img\n') -- cgit v1.2.3-54-g00ecf From dabaebe2216fbc53a00c9c3580b5ca0aa2e515e1 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 14 Mar 2021 15:11:05 +0100 Subject: encrypted devices won't always report as a child to a device, can't reliably look for a 'parent' of a encrypted drive when it doesn't show up. Hence, the DiskError() can't be raised just because we can't find a parent. The parent should be the current path if no other option was found. --- archinstall/lib/disk.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'archinstall') diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index b8a77ef8..0e76cb0e 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -187,7 +187,8 @@ class Partition(): for blockdevice in json.loads(b''.join(sys_command('lsblk -J')).decode('UTF-8'))['blockdevices']: if (parent := self.find_parent_of(blockdevice, os.path.basename(self.path))): return f"/dev/{parent}" - raise DiskError(f'Could not find appropriate parent for encrypted partition {self}') + # raise DiskError(f'Could not find appropriate parent for encrypted partition {self}') + return self.path def detect_inner_filesystem(self, password): log(f'Trying to detect inner filesystem format on {self} (This might take a while)', level=LOG_LEVELS.Info) -- cgit v1.2.3-54-g00ecf From 40440e575caf28d55cead7c16871e03cd9afc0c1 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 14 Mar 2021 15:25:41 +0100 Subject: Added some error handling. --- archinstall/lib/disk.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index 0e76cb0e..d7dfd9f4 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -193,8 +193,12 @@ class Partition(): def detect_inner_filesystem(self, password): log(f'Trying to detect inner filesystem format on {self} (This might take a while)', level=LOG_LEVELS.Info) from .luks import luks2 - with luks2(self, 'luksloop', password, auto_unmount=True) as unlocked_device: - return unlocked_device.filesystem + + try: + with luks2(self, 'luksloop', password, auto_unmount=True) as unlocked_device: + return unlocked_device.filesystem + except SysCallError: + return None def has_content(self): temporary_mountpoint = '/tmp/'+hashlib.md5(bytes(f"{time.time()}", 'UTF-8')+os.urandom(12)).hexdigest() -- cgit v1.2.3-54-g00ecf From b67257233f43fa8d34dacd6ecc3dc7cbbf60d221 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sat, 20 Mar 2021 17:26:48 +0100 Subject: Fixed #64. installation.set_timezone() already excisted since earlier versions of archinstall in the library section. The guided.py example simply never asked for a time-zone. There's still no NTP option, which I'll add in later. Mostly because there's a lot of settings one can do to a time-client configuration, and I'm not sure all users want the default time servers etc. --- archinstall/lib/installer.py | 5 +++-- archinstall/lib/user_interaction.py | 7 ++++++- examples/guided.py | 6 ++++++ 3 files changed, 15 insertions(+), 3 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 39e3447d..2604e77d 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -1,4 +1,4 @@ -import os, stat, time, shutil +import os, stat, time, shutil, pathlib from .exceptions import * from .disk import * @@ -171,7 +171,8 @@ class Installer(): def set_timezone(self, zone, *args, **kwargs): if not len(zone): return True - o = b''.join(sys_command(f'/usr/bin/arch-chroot {self.mountpoint} ln -s /usr/share/zoneinfo/{zone} /etc/localtime')) + (pathlib.Path(self.mountpoint)/"etc"/"localtime").unlink(missing_ok=True) + sys_command(f'/usr/bin/arch-chroot {self.mountpoint} ln -s /usr/share/zoneinfo/{zone} /etc/localtime') return True def activate_ntp(self): diff --git a/archinstall/lib/user_interaction.py b/archinstall/lib/user_interaction.py index ab2b19bc..6b3e5faa 100644 --- a/archinstall/lib/user_interaction.py +++ b/archinstall/lib/user_interaction.py @@ -1,4 +1,4 @@ -import getpass +import getpass, pathlib from .exceptions import * from .profiles import Profile from .locale_helpers import search_keyboard_layout @@ -50,6 +50,11 @@ def ask_for_additional_users(prompt='Any additional users to install (leave blan return users, super_users +def ask_for_a_timezone(): + timezone = input('Enter a valid timezone (Example: Europe/Stockholm): ').strip() + if pathlib.Path(timezone).exists(): + return timezone + def ask_to_configure_network(): # Optionally configure one network interface. #while 1: diff --git a/examples/guided.py b/examples/guided.py index 655fc29f..e9edac09 100644 --- a/examples/guided.py +++ b/examples/guided.py @@ -190,6 +190,9 @@ def ask_user_questions(): if not archinstall.arguments['nic']: archinstall.log(f"No network configuration was selected. Network is going to be unavailable until configured manually!", fg="yellow") + if not archinstall.arguments.get('timezone', None): + archinstall.arguments['timezone'] = archinstall.ask_for_a_timezone() + def perform_installation_steps(): global SIG_TRIGGER @@ -323,6 +326,9 @@ def perform_installation(device, boot_partition, language, mirrors): for superuser, user_info in archinstall.arguments.get('superusers', {}).items(): installation.user_create(superuser, user_info["!password"], sudo=True) + if (timezone := archinstall.arguments.get('timezone', None)): + installation.set_timezone(timezone) + if (root_pw := archinstall.arguments.get('!root-password', None)) and len(root_pw): installation.user_set_pw('root', root_pw) -- cgit v1.2.3-54-g00ecf From e209767d13bb8887ad7449cab59501fdc0eb4f77 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sat, 20 Mar 2021 18:26:38 +0100 Subject: Added helper functions for #81. So that we have a basic information about the terminal when outputting large lists/options. --- archinstall/lib/user_interaction.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'archinstall') diff --git a/archinstall/lib/user_interaction.py b/archinstall/lib/user_interaction.py index 6b3e5faa..b9689d05 100644 --- a/archinstall/lib/user_interaction.py +++ b/archinstall/lib/user_interaction.py @@ -1,4 +1,4 @@ -import getpass, pathlib +import getpass, pathlib, os, shutil from .exceptions import * from .profiles import Profile from .locale_helpers import search_keyboard_layout @@ -9,6 +9,15 @@ from .networking import list_interfaces ## TODO: Some inconsistencies between the selection processes. ## Some return the keys from the options, some the values? +def get_terminal_height(): + return shutil.get_terminal_size().lines + +def get_terminal_width(): + return shutil.get_terminal_size().columns + +def get_longest_option(options): + return max([len(x) for x in options]) + def get_password(prompt="Enter a password: "): while (passwd := getpass.getpass(prompt)): passwd_verification = getpass.getpass(prompt='And one more time for verification: ') -- cgit v1.2.3-54-g00ecf From 9f87b6963d6b195c35891366cbd5421324a593e3 Mon Sep 17 00:00:00 2001 From: Ninchester <5041877+ninchester@users.noreply.github.com> Date: Sat, 20 Mar 2021 21:41:56 +0100 Subject: Print options in columns --- archinstall/lib/user_interaction.py | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/user_interaction.py b/archinstall/lib/user_interaction.py index b9689d05..b3baebf8 100644 --- a/archinstall/lib/user_interaction.py +++ b/archinstall/lib/user_interaction.py @@ -27,6 +27,21 @@ def get_password(prompt="Enter a password: "): return passwd return None +def print_large_list(options, padding=5, margin_bottom=0, separator=': '): + longest_line = len(str(len(options))) + len(separator) + get_longest_option(options) + padding + num_of_columns = get_terminal_width() // longest_line + max_options_in_cells = num_of_columns * (get_terminal_height()-margin_bottom) + + if (len(options) > max_options_in_cells): + for index, option in enumerate(options): + print(f"{index}: {option}") + else: + for row in range(0, (get_terminal_height()-margin_bottom)): + for column in range(row, len(options), (get_terminal_height()-margin_bottom)): + spaces = " "*(longest_line - len(options[column])) + print(f"{str(column+1).zfill(2)}{separator}{options[column]}", end = spaces) + print() + def ask_for_superuser_account(prompt='Create a required super-user with sudo privileges: ', forced=False): while 1: new_user = input(prompt).strip(' ') @@ -279,8 +294,7 @@ def select_mirror_regions(mirrors, show_top_mirrors=True): selected_mirrors = {} if len(regions) >= 1: - for index, region in enumerate(regions): - print(f"{index}: {region}") + print_large_list(regions) print(' -- You can enter ? or help to search for more regions --') print(' -- You can skip this step by leaving the option blank --') -- cgit v1.2.3-54-g00ecf From 0318125a7b70114531951da300b06f47f427b89f Mon Sep 17 00:00:00 2001 From: Ninchester <5041877+ninchester@users.noreply.github.com> Date: Sat, 20 Mar 2021 21:48:34 +0100 Subject: Add margin at the bottom --- archinstall/lib/user_interaction.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/user_interaction.py b/archinstall/lib/user_interaction.py index b3baebf8..25ca71f0 100644 --- a/archinstall/lib/user_interaction.py +++ b/archinstall/lib/user_interaction.py @@ -29,8 +29,8 @@ def get_password(prompt="Enter a password: "): def print_large_list(options, padding=5, margin_bottom=0, separator=': '): longest_line = len(str(len(options))) + len(separator) + get_longest_option(options) + padding - num_of_columns = get_terminal_width() // longest_line - max_options_in_cells = num_of_columns * (get_terminal_height()-margin_bottom) + max_num_of_columns = get_terminal_width() // longest_line + max_options_in_cells = max_num_of_columns * (get_terminal_height()-margin_bottom) if (len(options) > max_options_in_cells): for index, option in enumerate(options): @@ -294,7 +294,7 @@ def select_mirror_regions(mirrors, show_top_mirrors=True): selected_mirrors = {} if len(regions) >= 1: - print_large_list(regions) + print_large_list(regions, margin_bottom=4) print(' -- You can enter ? or help to search for more regions --') print(' -- You can skip this step by leaving the option blank --') -- cgit v1.2.3-54-g00ecf From 6dea24ad22a84f35b3416da3440b03768a2afefe Mon Sep 17 00:00:00 2001 From: Ninchester <5041877+ninchester@users.noreply.github.com> Date: Sat, 20 Mar 2021 21:51:57 +0100 Subject: Make option list 0-index based --- archinstall/lib/user_interaction.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'archinstall') diff --git a/archinstall/lib/user_interaction.py b/archinstall/lib/user_interaction.py index 25ca71f0..e7fba747 100644 --- a/archinstall/lib/user_interaction.py +++ b/archinstall/lib/user_interaction.py @@ -39,7 +39,7 @@ def print_large_list(options, padding=5, margin_bottom=0, separator=': '): for row in range(0, (get_terminal_height()-margin_bottom)): for column in range(row, len(options), (get_terminal_height()-margin_bottom)): spaces = " "*(longest_line - len(options[column])) - print(f"{str(column+1).zfill(2)}{separator}{options[column]}", end = spaces) + print(f"{str(column).zfill(2)}{separator}{options[column]}", end = spaces) print() def ask_for_superuser_account(prompt='Create a required super-user with sudo privileges: ', forced=False): -- cgit v1.2.3-54-g00ecf From 42ba36b5d8ab5a8442bb4996815598ef517003a2 Mon Sep 17 00:00:00 2001 From: Ninchester <5041877+ninchester@users.noreply.github.com> Date: Sat, 20 Mar 2021 22:01:00 +0100 Subject: Fix number padding based on length of the highest option index - instead of using zeroes, now spaces are used --- archinstall/lib/user_interaction.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/user_interaction.py b/archinstall/lib/user_interaction.py index e7fba747..d82068a7 100644 --- a/archinstall/lib/user_interaction.py +++ b/archinstall/lib/user_interaction.py @@ -28,7 +28,8 @@ def get_password(prompt="Enter a password: "): return None def print_large_list(options, padding=5, margin_bottom=0, separator=': '): - longest_line = len(str(len(options))) + len(separator) + get_longest_option(options) + padding + highest_index_number_length = len(str(len(options))) + longest_line = highest_index_number_length + len(separator) + get_longest_option(options) + padding max_num_of_columns = get_terminal_width() // longest_line max_options_in_cells = max_num_of_columns * (get_terminal_height()-margin_bottom) @@ -39,7 +40,7 @@ def print_large_list(options, padding=5, margin_bottom=0, separator=': '): for row in range(0, (get_terminal_height()-margin_bottom)): for column in range(row, len(options), (get_terminal_height()-margin_bottom)): spaces = " "*(longest_line - len(options[column])) - print(f"{str(column).zfill(2)}{separator}{options[column]}", end = spaces) + print(f"{str(column): >{highest_index_number_length}}{separator}{options[column]}", end = spaces) print() def ask_for_superuser_account(prompt='Create a required super-user with sudo privileges: ', forced=False): -- cgit v1.2.3-54-g00ecf From f3b93c1c1ce774375aedfa02c2220d9b5d4512c2 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sat, 20 Mar 2021 22:15:42 +0100 Subject: Removed search logic for mirrors since we now have column-printouts, the columns enabled us to print all the regions which means the search was an excessive feature. --- archinstall/lib/user_interaction.py | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/user_interaction.py b/archinstall/lib/user_interaction.py index d82068a7..296fa8db 100644 --- a/archinstall/lib/user_interaction.py +++ b/archinstall/lib/user_interaction.py @@ -295,23 +295,13 @@ def select_mirror_regions(mirrors, show_top_mirrors=True): selected_mirrors = {} if len(regions) >= 1: - print_large_list(regions, margin_bottom=4) + print_large_list(regions, margin_bottom=2) - print(' -- You can enter ? or help to search for more regions --') print(' -- You can skip this step by leaving the option blank --') - print(' -- (You can use Shift + PageUp to scroll in the list --') selected_mirror = input('Select one of the above regions to download packages from (by number or full name): ') if len(selected_mirror.strip()) == 0: return {} - elif selected_mirror.lower() in ('?', 'help'): - filter_string = input('Search for a region containing (example: "united"): ').strip().lower() - for region in mirrors: - if filter_string in region.lower(): - selected_mirrors[region] = mirrors[region] - - return selected_mirrors - elif selected_mirror.isdigit() and (pos := int(selected_mirror)) <= len(regions)-1: region = regions[int(selected_mirror)] selected_mirrors[region] = mirrors[region] -- cgit v1.2.3-54-g00ecf From 24964e4865c66f32a5c656b62f4cfdd47aaaaba2 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 21 Mar 2021 11:05:57 +0100 Subject: Fixing minor issue in v2.1.2-rc3. The use_entire_disk() helper function was adding a partition with the format vfat, but parted doesn't understand this and needs fat32. --- archinstall/lib/disk.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'archinstall') diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index d7dfd9f4..77aa6528 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -407,7 +407,7 @@ class Filesystem(): return self.raw_parted(string).exit_code def use_entire_disk(self, root_filesystem_type='ext4', encrypt_root_partition=True): - self.add_partition('primary', start='1MiB', end='513MiB', format='vfat') + self.add_partition('primary', start='1MiB', end='513MiB', format='fat32') self.set_name(0, 'EFI') self.set(0, 'boot on') # TODO: Probably redundant because in GPT mode 'esp on' is an alias for "boot on"? -- cgit v1.2.3-54-g00ecf From 886c60f9bca47d4053acd77685f8e19f48d57a04 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 21 Mar 2021 11:31:49 +0100 Subject: Added some more debugging and error logs to the project. Mainly to indicate background tasks and errors to the debug log in case users need to submit it. --- archinstall/lib/disk.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'archinstall') diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index 77aa6528..fcc53981 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -233,6 +233,7 @@ class Partition(): raise DiskError(f"Attempting to encrypt a partition that was not marked for encryption: {self}") if not self.safe_to_format(): + log(f"Partition {self} was marked as protected but encrypt() was called on it!", level=LOG_LEVELS.Error, fg="red") return False handle = luks2(self, None, None) @@ -407,6 +408,7 @@ class Filesystem(): return self.raw_parted(string).exit_code def use_entire_disk(self, root_filesystem_type='ext4', encrypt_root_partition=True): + log(f"Using and formatting the entire {self.blockdevice}.", level=LOG_LEVELS.Debug) self.add_partition('primary', start='1MiB', end='513MiB', format='fat32') self.set_name(0, 'EFI') self.set(0, 'boot on') @@ -417,11 +419,13 @@ class Filesystem(): self.blockdevice.partition[0].filesystem = 'vfat' self.blockdevice.partition[1].filesystem = root_filesystem_type + log(f"Set the root partition {self.blockdevice.partition[1]} to use filesystem {root_filesystem_type}.", level=LOG_LEVELS.Debug) self.blockdevice.partition[0].target_mountpoint = '/boot' self.blockdevice.partition[1].target_mountpoint = '/' if encrypt_root_partition: + log(f"Marking partition {self.blockdevice.partition[1]} as encrypted.", level=LOG_LEVELS.Debug) self.blockdevice.partition[1].encrypted = True def add_partition(self, type, start, end, format=None): -- cgit v1.2.3-54-g00ecf From 75d1395b107d983c8b97f10ee757ee6f28487afa Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 21 Mar 2021 13:00:37 +0100 Subject: Marking newly created partitions as safe to format in use_entire_disk(), by adding allow_formatting=True to the partitions. Also added some debugging to help aiding in support cases. --- archinstall/lib/disk.py | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'archinstall') diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index fcc53981..0a182eb0 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -217,8 +217,10 @@ class Partition(): def safe_to_format(self): if self.allow_formatting is False: + log(f"Partition {self} is not marked for formatting.", level=LOG_LEVELS.Debug) return False elif self.target_mountpoint == '/boot' and self.has_content(): + log(f"Partition {self} is a boot partition and has content inside.", level=LOG_LEVELS.Debug) return False return True @@ -424,6 +426,9 @@ class Filesystem(): self.blockdevice.partition[0].target_mountpoint = '/boot' self.blockdevice.partition[1].target_mountpoint = '/' + self.blockdevice.partition[0].allow_formatting = True + self.blockdevice.partition[1].allow_formatting = True + if encrypt_root_partition: log(f"Marking partition {self.blockdevice.partition[1]} as encrypted.", level=LOG_LEVELS.Debug) self.blockdevice.partition[1].encrypted = True -- cgit v1.2.3-54-g00ecf From df1ed2034d17ff15bb321ff2c306c9e8aaedeec6 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 21 Mar 2021 14:04:06 +0100 Subject: Debugging tainted namespace on profile modules. --- archinstall/lib/profiles.py | 1 + 1 file changed, 1 insertion(+) (limited to 'archinstall') diff --git a/archinstall/lib/profiles.py b/archinstall/lib/profiles.py index 01c3288c..92c9a140 100644 --- a/archinstall/lib/profiles.py +++ b/archinstall/lib/profiles.py @@ -125,6 +125,7 @@ class Script(): raise ProfileNotFound(f"Cannot handle scheme {parsed_url.scheme}") def load_instructions(self, namespace=None): + print(f"Load instructions for {self} with namespace {namespace}") if namespace: self.namespace = namespace -- cgit v1.2.3-54-g00ecf From b81d5e054d59df523a30f997e0ae66eb2c7107ff Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 21 Mar 2021 14:19:39 +0100 Subject: Debugging tainted namespace on profile modules. --- archinstall/lib/profiles.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'archinstall') diff --git a/archinstall/lib/profiles.py b/archinstall/lib/profiles.py index 92c9a140..bafa76df 100644 --- a/archinstall/lib/profiles.py +++ b/archinstall/lib/profiles.py @@ -129,6 +129,9 @@ class Script(): if namespace: self.namespace = namespace + if '.py' in self.namespace: + raise KeyError("Debugging") + self.spec = importlib.util.spec_from_file_location(self.namespace, self.path) imported = importlib.util.module_from_spec(self.spec) sys.modules[self.namespace] = imported -- cgit v1.2.3-54-g00ecf From 1998e0378cbf2348289a56679ddcfbfd58160987 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 21 Mar 2021 14:21:47 +0100 Subject: Debugging tainted namespace on profile modules. --- archinstall/lib/profiles.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/profiles.py b/archinstall/lib/profiles.py index bafa76df..a8a18f54 100644 --- a/archinstall/lib/profiles.py +++ b/archinstall/lib/profiles.py @@ -129,8 +129,8 @@ class Script(): if namespace: self.namespace = namespace - if '.py' in self.namespace: - raise KeyError("Debugging") + #if '.py' in self.namespace: + # raise KeyError("Debugging") self.spec = importlib.util.spec_from_file_location(self.namespace, self.path) imported = importlib.util.module_from_spec(self.spec) -- cgit v1.2.3-54-g00ecf From e1e1a916fcb8b769f0be4c5fa303a2eb5670c19b Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 21 Mar 2021 14:32:36 +0100 Subject: Debugging tainted namespace on profile modules. --- archinstall/lib/profiles.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/profiles.py b/archinstall/lib/profiles.py index a8a18f54..bafa76df 100644 --- a/archinstall/lib/profiles.py +++ b/archinstall/lib/profiles.py @@ -129,8 +129,8 @@ class Script(): if namespace: self.namespace = namespace - #if '.py' in self.namespace: - # raise KeyError("Debugging") + if '.py' in self.namespace: + raise KeyError("Debugging") self.spec = importlib.util.spec_from_file_location(self.namespace, self.path) imported = importlib.util.module_from_spec(self.spec) -- cgit v1.2.3-54-g00ecf From 1fb61bf8fcb5319cc5e1e99d9b92763f1271ae33 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 21 Mar 2021 14:34:03 +0100 Subject: Debugging tainted namespace on profile modules. --- archinstall/lib/profiles.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'archinstall') diff --git a/archinstall/lib/profiles.py b/archinstall/lib/profiles.py index bafa76df..f90facc8 100644 --- a/archinstall/lib/profiles.py +++ b/archinstall/lib/profiles.py @@ -129,7 +129,7 @@ class Script(): if namespace: self.namespace = namespace - if '.py' in self.namespace: + if '.py.py' in self.namespace: raise KeyError("Debugging") self.spec = importlib.util.spec_from_file_location(self.namespace, self.path) @@ -173,6 +173,7 @@ class Profile(Script): # trigger a traditional: # if __name__ == 'moduleName' if '__name__' in source_data and '_prep_function' in source_data: + print(f"Checking if {self} has _prep_function by importing with namespace {self.namespace}.py") with self.load_instructions(namespace=f"{self.namespace}.py") as imported: if hasattr(imported, '_prep_function'): return True -- cgit v1.2.3-54-g00ecf From f76f5458daa63b06cf356f40a0eb27f957308b66 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 21 Mar 2021 14:48:26 +0100 Subject: Debugging tainted namespace on profile modules. --- archinstall/lib/profiles.py | 1 + 1 file changed, 1 insertion(+) (limited to 'archinstall') diff --git a/archinstall/lib/profiles.py b/archinstall/lib/profiles.py index f90facc8..7b6e9b4d 100644 --- a/archinstall/lib/profiles.py +++ b/archinstall/lib/profiles.py @@ -76,6 +76,7 @@ class Script(): self.spec = None self.examples = None self.namespace = os.path.splitext(os.path.basename(self.path))[0] + print(f"Script loaded with namespace: {self.namespace}") def __enter__(self, *args, **kwargs): self.execute() -- cgit v1.2.3-54-g00ecf From c1e8e6b58dd71f14f2720f532c327d29e8473dbe Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 21 Mar 2021 14:50:57 +0100 Subject: Debugging tainted namespace on profile modules. --- archinstall/lib/profiles.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/profiles.py b/archinstall/lib/profiles.py index 7b6e9b4d..63d32afa 100644 --- a/archinstall/lib/profiles.py +++ b/archinstall/lib/profiles.py @@ -76,7 +76,7 @@ class Script(): self.spec = None self.examples = None self.namespace = os.path.splitext(os.path.basename(self.path))[0] - print(f"Script loaded with namespace: {self.namespace}") + print(f"Script {self} loaded with namespace: {self.namespace}") def __enter__(self, *args, **kwargs): self.execute() @@ -126,17 +126,18 @@ class Script(): raise ProfileNotFound(f"Cannot handle scheme {parsed_url.scheme}") def load_instructions(self, namespace=None): - print(f"Load instructions for {self} with namespace {namespace}") - if namespace: - self.namespace = namespace + if not namespace: + namespace = self.namespace - if '.py.py' in self.namespace: - raise KeyError("Debugging") + if namespace in sys.modules: + print(f"Found {self} in sys.modules, returning cached import.") + return self - self.spec = importlib.util.spec_from_file_location(self.namespace, self.path) + self.spec = importlib.util.spec_from_file_location(namespace, self.path) imported = importlib.util.module_from_spec(self.spec) - sys.modules[self.namespace] = imported + sys.modules[namespace] = imported + print(f"Imported {self} into sys.modules. Returning fresh copy.") return self def execute(self): -- cgit v1.2.3-54-g00ecf From ec9059c039c3d47dc17e457cdc8a42549de87d5b Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 21 Mar 2021 14:51:59 +0100 Subject: Debugging tainted namespace on profile modules. --- archinstall/lib/profiles.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/profiles.py b/archinstall/lib/profiles.py index 63d32afa..e22a3587 100644 --- a/archinstall/lib/profiles.py +++ b/archinstall/lib/profiles.py @@ -129,15 +129,11 @@ class Script(): if not namespace: namespace = self.namespace - if namespace in sys.modules: - print(f"Found {self} in sys.modules, returning cached import.") - return self - self.spec = importlib.util.spec_from_file_location(namespace, self.path) imported = importlib.util.module_from_spec(self.spec) sys.modules[namespace] = imported - print(f"Imported {self} into sys.modules. Returning fresh copy.") + print(f"Imported {self} into sys.modules with namespace {namespace}.") return self def execute(self): -- cgit v1.2.3-54-g00ecf From c99abb1a7b6b0fe75f8bc1b7558e0e13afb283c5 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 21 Mar 2021 14:56:26 +0100 Subject: Debugging tainted namespace on profile modules. --- archinstall/lib/profiles.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'archinstall') diff --git a/archinstall/lib/profiles.py b/archinstall/lib/profiles.py index e22a3587..724b92e7 100644 --- a/archinstall/lib/profiles.py +++ b/archinstall/lib/profiles.py @@ -134,6 +134,9 @@ class Script(): sys.modules[namespace] = imported print(f"Imported {self} into sys.modules with namespace {namespace}.") + + if '.py' not in namespace: + raise KeyError("Debugging") return self def execute(self): -- cgit v1.2.3-54-g00ecf From 27bde44b8de447e8612a83bc6964fc1b5237e07d Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 21 Mar 2021 15:00:08 +0100 Subject: Debugging tainted namespace on profile modules. --- archinstall/lib/profiles.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/profiles.py b/archinstall/lib/profiles.py index 724b92e7..5d425a22 100644 --- a/archinstall/lib/profiles.py +++ b/archinstall/lib/profiles.py @@ -126,17 +126,15 @@ class Script(): raise ProfileNotFound(f"Cannot handle scheme {parsed_url.scheme}") def load_instructions(self, namespace=None): - if not namespace: - namespace = self.namespace + if namespace: + self.namespace = namespace - self.spec = importlib.util.spec_from_file_location(namespace, self.path) + self.spec = importlib.util.spec_from_file_location(self.namespace, self.path) imported = importlib.util.module_from_spec(self.spec) - sys.modules[namespace] = imported + sys.modules[self.namespace] = imported - print(f"Imported {self} into sys.modules with namespace {namespace}.") + print(f"Imported {self} into sys.modules with namespace {self.namespace}.") - if '.py' not in namespace: - raise KeyError("Debugging") return self def execute(self): -- cgit v1.2.3-54-g00ecf From 9ee64797011b541b38e68610a746eb6f303ab63d Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 21 Mar 2021 15:04:23 +0100 Subject: Enabling load_instructions() to set a temporary namespace, and then reverting it after the instructions are loaded. This is to temporarly override the namespace during import - enabling avoidance of triggering __name__ checks, and at the same time reverting back the namespace automatically to enable .execute() on the script (reusability of classes) --- archinstall/lib/profiles.py | 9 +++++++-- examples/guided.py | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/profiles.py b/archinstall/lib/profiles.py index 5d425a22..ef7bba00 100644 --- a/archinstall/lib/profiles.py +++ b/archinstall/lib/profiles.py @@ -125,7 +125,9 @@ class Script(): else: raise ProfileNotFound(f"Cannot handle scheme {parsed_url.scheme}") - def load_instructions(self, namespace=None): + def load_instructions(self, namespace=None, reset_namespace=False): + original_namespace = self.namespace + if namespace: self.namespace = namespace @@ -135,6 +137,9 @@ class Script(): print(f"Imported {self} into sys.modules with namespace {self.namespace}.") + if reset_namespace: + self.namespace = original_namespace + return self def execute(self): @@ -173,7 +178,7 @@ class Profile(Script): # if __name__ == 'moduleName' if '__name__' in source_data and '_prep_function' in source_data: print(f"Checking if {self} has _prep_function by importing with namespace {self.namespace}.py") - with self.load_instructions(namespace=f"{self.namespace}.py") as imported: + with self.load_instructions(namespace=f"{self.namespace}.py", reset_namespace=True) as imported: if hasattr(imported, '_prep_function'): return True return False diff --git a/examples/guided.py b/examples/guided.py index f4fc533b..4e3dd082 100644 --- a/examples/guided.py +++ b/examples/guided.py @@ -170,7 +170,7 @@ def ask_user_questions(): # Check the potentially selected profiles preperations to get early checks if some additional questions are needed. if archinstall.arguments['profile'] and archinstall.arguments['profile'].has_prep_function(): print(f"{archinstall.arguments['profile']} has prep-function, loading with namespace {archinstall.arguments['profile'].namespace}.py") - with archinstall.arguments['profile'].load_instructions(namespace=f"{archinstall.arguments['profile'].namespace}.py") as imported: + with archinstall.arguments['profile'].load_instructions(namespace=f"{archinstall.arguments['profile'].namespace}.py", reset_namespace=True) as imported: if not imported._prep_function(): archinstall.log( ' * Profile\'s preparation requirements was not fulfilled.', -- cgit v1.2.3-54-g00ecf From 28606cde6127921615692460bbb4d80f68b7b727 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 21 Mar 2021 15:07:45 +0100 Subject: Enabling load_instructions() to set a temporary namespace, and then reverting it after the instructions are loaded. This is to temporarly override the namespace during import - enabling avoidance of triggering __name__ checks, and at the same time reverting back the namespace automatically to enable .execute() on the script (reusability of classes) --- archinstall/lib/profiles.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/profiles.py b/archinstall/lib/profiles.py index ef7bba00..8284bf40 100644 --- a/archinstall/lib/profiles.py +++ b/archinstall/lib/profiles.py @@ -135,11 +135,14 @@ class Script(): imported = importlib.util.module_from_spec(self.spec) sys.modules[self.namespace] = imported - print(f"Imported {self} into sys.modules with namespace {self.namespace}.") + print(f"Imported {self} into sys.modules with namespace {self.namespace}") + + if '.py' not in self.namespace: + raise KeyError(f"Debugging: {self.namespace}, {reset_namespace}, {self}") if reset_namespace: self.namespace = original_namespace - + return self def execute(self): -- cgit v1.2.3-54-g00ecf From a9f177e722d80ecbacb0c8e74ea0e8a4b88212be Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 21 Mar 2021 15:13:08 +0100 Subject: Reverted reset_namespace idea. Didn't turn out as clean as I wanted it to. --- archinstall/lib/profiles.py | 12 ++---------- examples/guided.py | 2 +- 2 files changed, 3 insertions(+), 11 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/profiles.py b/archinstall/lib/profiles.py index 8284bf40..a0f2dc77 100644 --- a/archinstall/lib/profiles.py +++ b/archinstall/lib/profiles.py @@ -125,9 +125,7 @@ class Script(): else: raise ProfileNotFound(f"Cannot handle scheme {parsed_url.scheme}") - def load_instructions(self, namespace=None, reset_namespace=False): - original_namespace = self.namespace - + def load_instructions(self, namespace=None): if namespace: self.namespace = namespace @@ -137,12 +135,6 @@ class Script(): print(f"Imported {self} into sys.modules with namespace {self.namespace}") - if '.py' not in self.namespace: - raise KeyError(f"Debugging: {self.namespace}, {reset_namespace}, {self}") - - if reset_namespace: - self.namespace = original_namespace - return self def execute(self): @@ -181,7 +173,7 @@ class Profile(Script): # if __name__ == 'moduleName' if '__name__' in source_data and '_prep_function' in source_data: print(f"Checking if {self} has _prep_function by importing with namespace {self.namespace}.py") - with self.load_instructions(namespace=f"{self.namespace}.py", reset_namespace=True) as imported: + with self.load_instructions(namespace=f"{self.namespace}.py") as imported: if hasattr(imported, '_prep_function'): return True return False diff --git a/examples/guided.py b/examples/guided.py index 4e3dd082..f4fc533b 100644 --- a/examples/guided.py +++ b/examples/guided.py @@ -170,7 +170,7 @@ def ask_user_questions(): # Check the potentially selected profiles preperations to get early checks if some additional questions are needed. if archinstall.arguments['profile'] and archinstall.arguments['profile'].has_prep_function(): print(f"{archinstall.arguments['profile']} has prep-function, loading with namespace {archinstall.arguments['profile'].namespace}.py") - with archinstall.arguments['profile'].load_instructions(namespace=f"{archinstall.arguments['profile'].namespace}.py", reset_namespace=True) as imported: + with archinstall.arguments['profile'].load_instructions(namespace=f"{archinstall.arguments['profile'].namespace}.py") as imported: if not imported._prep_function(): archinstall.log( ' * Profile\'s preparation requirements was not fulfilled.', -- cgit v1.2.3-54-g00ecf From 60817334224a8ade4c7e600498fe9bd8f540bf29 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 21 Mar 2021 15:16:41 +0100 Subject: Storing original namespace of profiles as they were during initation. Namespaces now get reverted back to the original state just before .install() is called. This ensures any temporary namespace changes made during prep-checks etc doesn't stick around when we try to install. --- archinstall/lib/profiles.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/profiles.py b/archinstall/lib/profiles.py index a0f2dc77..34ba09da 100644 --- a/archinstall/lib/profiles.py +++ b/archinstall/lib/profiles.py @@ -76,6 +76,7 @@ class Script(): self.spec = None self.examples = None self.namespace = os.path.splitext(os.path.basename(self.path))[0] + self.original_namespace = self.namespace print(f"Script {self} loaded with namespace: {self.namespace}") def __enter__(self, *args, **kwargs): @@ -149,7 +150,6 @@ class Script(): class Profile(Script): def __init__(self, installer, path, args={}): super(Profile, self).__init__(path, installer) - self._cache = None def __dump__(self, *args, **kwargs): return {'path' : self.path} @@ -158,6 +158,10 @@ class Profile(Script): return f'Profile({os.path.basename(self.profile)})' def install(self): + # Before installing, revert any temporary changes to the namespace. + # This ensures that the namespace during installation is the original initation namespace. + # (For instance awesome instead of aweosme.py or app-awesome.py) + self.namespace = self.original_namespace return self.execute() def has_prep_function(self): @@ -206,4 +210,11 @@ class Application(Profile): elif parsed_url.scheme in ('https', 'http'): return self.localize_path(self.profile) else: - raise ProfileNotFound(f"Application cannot handle scheme {parsed_url.scheme}") \ No newline at end of file + raise ProfileNotFound(f"Application cannot handle scheme {parsed_url.scheme}") + + def install(self): + # Before installing, revert any temporary changes to the namespace. + # This ensures that the namespace during installation is the original initation namespace. + # (For instance awesome instead of aweosme.py or app-awesome.py) + self.namespace = self.original_namespace + return self.execute() \ No newline at end of file -- cgit v1.2.3-54-g00ecf From 93faf07b6948074e9071faf75f96ff220714d5f9 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 21 Mar 2021 15:25:24 +0100 Subject: Moved the globalization of 'installation' variable. Since Profile() might be created before the installation instance, we need to move the global variable declaration after installation has begun and there's an installation instance. --- archinstall/lib/installer.py | 9 +++++++++ archinstall/lib/profiles.py | 1 - 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'archinstall') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 2604e77d..8d7d6967 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -381,6 +381,15 @@ class Installer(): return self.pacstrap(*packages) def install_profile(self, profile): + # TODO: Replace this with a import archinstall.session instead in the profiles. + # The tricky thing with doing the import archinstall.session instead is that + # profiles might be run from a different chroot, and there's no way we can + # guarantee file-path safety when accessing the installer object that way. + # Doing the __builtins__ replacement, ensures that the global vriable "installation" + # is always kept up to date. It's considered a nasty hack - but it's a safe way + # of ensuring 100% accuracy of archinstall session variables. + __builtins__['installation'] = self.installer + if type(profile) == str: profile = Profile(self, profile) diff --git a/archinstall/lib/profiles.py b/archinstall/lib/profiles.py index 34ba09da..ee2ff39a 100644 --- a/archinstall/lib/profiles.py +++ b/archinstall/lib/profiles.py @@ -142,7 +142,6 @@ class Script(): if not self.namespace in sys.modules or self.spec is None: self.load_instructions() - __builtins__['installation'] = self.installer # TODO: Replace this with a import archinstall.session instead self.spec.loader.exec_module(sys.modules[self.namespace]) return sys.modules[self.namespace] -- cgit v1.2.3-54-g00ecf From 35e774f5f60e09f5a9a4deb7fb6317d87c9a131f Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 21 Mar 2021 15:28:11 +0100 Subject: Spelling error on variable. --- archinstall/lib/installer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'archinstall') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 8d7d6967..db73d324 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -388,7 +388,7 @@ class Installer(): # Doing the __builtins__ replacement, ensures that the global vriable "installation" # is always kept up to date. It's considered a nasty hack - but it's a safe way # of ensuring 100% accuracy of archinstall session variables. - __builtins__['installation'] = self.installer + __builtins__['installation'] = self if type(profile) == str: profile = Profile(self, profile) -- cgit v1.2.3-54-g00ecf From 3baaefb97db79f52f49f1d5e203cf03fb5cb4c86 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 21 Mar 2021 16:35:26 +0100 Subject: Cleaned up after some debugging. --- archinstall/lib/profiles.py | 7 ++----- examples/guided.py | 1 - 2 files changed, 2 insertions(+), 6 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/profiles.py b/archinstall/lib/profiles.py index ee2ff39a..e9639451 100644 --- a/archinstall/lib/profiles.py +++ b/archinstall/lib/profiles.py @@ -1,7 +1,7 @@ import os, urllib.request, urllib.parse, ssl, json, re import importlib.util, sys, glob, hashlib from collections import OrderedDict -from .general import multisplit, sys_command, log +from .general import multisplit, sys_command from .exceptions import * from .networking import * from .output import log, LOG_LEVELS @@ -77,7 +77,7 @@ class Script(): self.examples = None self.namespace = os.path.splitext(os.path.basename(self.path))[0] self.original_namespace = self.namespace - print(f"Script {self} loaded with namespace: {self.namespace}") + log(f"Script {self} has been loaded with namespace '{self.namespace}'") def __enter__(self, *args, **kwargs): self.execute() @@ -133,8 +133,6 @@ class Script(): self.spec = importlib.util.spec_from_file_location(self.namespace, self.path) imported = importlib.util.module_from_spec(self.spec) sys.modules[self.namespace] = imported - - print(f"Imported {self} into sys.modules with namespace {self.namespace}") return self @@ -175,7 +173,6 @@ class Profile(Script): # trigger a traditional: # if __name__ == 'moduleName' if '__name__' in source_data and '_prep_function' in source_data: - print(f"Checking if {self} has _prep_function by importing with namespace {self.namespace}.py") with self.load_instructions(namespace=f"{self.namespace}.py") as imported: if hasattr(imported, '_prep_function'): return True diff --git a/examples/guided.py b/examples/guided.py index f4fc533b..b6aa5810 100644 --- a/examples/guided.py +++ b/examples/guided.py @@ -169,7 +169,6 @@ def ask_user_questions(): # Check the potentially selected profiles preperations to get early checks if some additional questions are needed. if archinstall.arguments['profile'] and archinstall.arguments['profile'].has_prep_function(): - print(f"{archinstall.arguments['profile']} has prep-function, loading with namespace {archinstall.arguments['profile'].namespace}.py") with archinstall.arguments['profile'].load_instructions(namespace=f"{archinstall.arguments['profile'].namespace}.py") as imported: if not imported._prep_function(): archinstall.log( -- cgit v1.2.3-54-g00ecf From 2fab088314d4d7e9f580376d035db1c2a96e043a Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 21 Mar 2021 16:48:22 +0100 Subject: Added some debugging to help identify why archinstall cannot find unencrypted devices when setting up the boot loader. --- archinstall/lib/installer.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'archinstall') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index db73d324..4b964773 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -352,6 +352,7 @@ class Installer(): if self.partition.encrypted: + log(f"Identifying root partition {self.partition} to boot based on disk UUID, looking for '{os.path.basename(self.partition.real_device)}'.", level=LOG_LEVELS.Info) for root, folders, uids in os.walk('/dev/disk/by-uuid'): for uid in uids: real_path = os.path.realpath(os.path.join(root, uid)) @@ -363,6 +364,7 @@ class Installer(): return True break else: + log(f"Identifying root partition {self.partition} to boot based on partition UUID, looking for '{os.path.basename(self.partition.path)}'.", level=LOG_LEVELS.Info) for root, folders, uids in os.walk('/dev/disk/by-partuuid'): for uid in uids: real_path = os.path.realpath(os.path.join(root, uid)) @@ -373,6 +375,7 @@ class Installer(): self.helper_flags['bootloader'] = bootloader return True break + raise RequirementError(f"Could not identify the UUID of {self.partition}, there for {self.mountpoint}/boot/loader/entries/arch.conf will be broken until fixed.") else: raise RequirementError(f"Unknown (or not yet implemented) bootloader added to add_bootloader(): {bootloader}") -- cgit v1.2.3-54-g00ecf From dbe086024d5fc1ab25218f1ea0e063881e66efd6 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 21 Mar 2021 16:58:27 +0100 Subject: Moved some info logs into debug instead to minimize user splash. --- archinstall/lib/installer.py | 4 ++-- archinstall/lib/profiles.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 4b964773..1c66f6ac 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -352,7 +352,7 @@ class Installer(): if self.partition.encrypted: - log(f"Identifying root partition {self.partition} to boot based on disk UUID, looking for '{os.path.basename(self.partition.real_device)}'.", level=LOG_LEVELS.Info) + log(f"Identifying root partition {self.partition} to boot based on disk UUID, looking for '{os.path.basename(self.partition.real_device)}'.", level=LOG_LEVELS.Debug) for root, folders, uids in os.walk('/dev/disk/by-uuid'): for uid in uids: real_path = os.path.realpath(os.path.join(root, uid)) @@ -364,7 +364,7 @@ class Installer(): return True break else: - log(f"Identifying root partition {self.partition} to boot based on partition UUID, looking for '{os.path.basename(self.partition.path)}'.", level=LOG_LEVELS.Info) + log(f"Identifying root partition {self.partition} to boot based on partition UUID, looking for '{os.path.basename(self.partition.path)}'.", level=LOG_LEVELS.Debug) for root, folders, uids in os.walk('/dev/disk/by-partuuid'): for uid in uids: real_path = os.path.realpath(os.path.join(root, uid)) diff --git a/archinstall/lib/profiles.py b/archinstall/lib/profiles.py index e9639451..08b1d618 100644 --- a/archinstall/lib/profiles.py +++ b/archinstall/lib/profiles.py @@ -77,7 +77,7 @@ class Script(): self.examples = None self.namespace = os.path.splitext(os.path.basename(self.path))[0] self.original_namespace = self.namespace - log(f"Script {self} has been loaded with namespace '{self.namespace}'") + log(f"Script {self} has been loaded with namespace '{self.namespace}'", level=LOG_LEVELS.Debug) def __enter__(self, *args, **kwargs): self.execute() -- cgit v1.2.3-54-g00ecf From 6a2dd8f5112f6f087772baf647a5c3b961541af5 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 21 Mar 2021 17:11:29 +0100 Subject: Added more debug level information to parted in case it goes heywire. --- archinstall/lib/disk.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'archinstall') diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index 0a182eb0..a1880198 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -397,7 +397,7 @@ class Filesystem(): def raw_parted(self, string:str): x = sys_command(f'/usr/bin/parted -s {string}') - o = b''.join(x) + log(f"'parted -s {string}' returned: {b''.join(x)}", level=LOG_LEVELS.Debug) return x def parted(self, string:str): -- cgit v1.2.3-54-g00ecf From c00e09517fdb5ddfbc4d40b74b11a56795cebfde Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 21 Mar 2021 17:18:00 +0100 Subject: Centralized a partition call to use the logging feature raw_parted(). --- archinstall/lib/disk.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'archinstall') diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index a1880198..ed5d1b28 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -365,7 +365,7 @@ class Filesystem(): if self.blockdevice.keep_partitions is False: log(f'Wiping {self.blockdevice} by using partition format {self.mode}', level=LOG_LEVELS.Debug) if self.mode == GPT: - if sys_command(f'/usr/bin/parted -s {self.blockdevice.device} mklabel gpt',).exit_code == 0: + if self.raw_parted(f'{self.blockdevice.device} mklabel gpt').exit_code == 0: return self else: raise DiskError(f'Problem setting the partition format to GPT:', f'/usr/bin/parted -s {self.blockdevice.device} mklabel gpt') -- cgit v1.2.3-54-g00ecf From c8470b81a6f2e8395f74ce0c1168d133fb24b811 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 21 Mar 2021 17:22:11 +0100 Subject: Debugging a partioning case. --- archinstall/lib/disk.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'archinstall') diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index ed5d1b28..fe891b28 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -437,6 +437,7 @@ class Filesystem(): log(f'Adding partition to {self.blockdevice}', level=LOG_LEVELS.Info) previous_partitions = self.blockdevice.partitions + print(previous_partitions) if format: partitioning = self.parted(f'{self.blockdevice.device} mkpart {type} {format} {start} {end}') == 0 else: @@ -444,6 +445,8 @@ class Filesystem(): if partitioning: start_wait = time.time() + time.sleep(2) + print(self.blockdevice.partitions) while previous_partitions == self.blockdevice.partitions: time.sleep(0.025) # Let the new partition come up in the kernel if time.time() - start_wait > 10: -- cgit v1.2.3-54-g00ecf From 298ed315318e75fe546144b781e4f9e9031d72db Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 21 Mar 2021 17:25:18 +0100 Subject: Added an option to force-flush a blockdevice cache. creating a new Filesystem() now triggers a flush of the cache since all partitions are removed. There shouldn't be any harm in even bypassing the cache, but it's there for a few reasons. --- archinstall/lib/disk.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'archinstall') diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index fe891b28..efe3f50d 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -129,6 +129,9 @@ class BlockDevice(): return True return False + def flush_cache(self): + self.part_cache = OrderedDict() + class Partition(): def __init__(self, path, part_id=None, size=-1, filesystem=None, mountpoint=None, encrypted=False, autodetect_filesystem=True): if not part_id: @@ -366,6 +369,7 @@ class Filesystem(): log(f'Wiping {self.blockdevice} by using partition format {self.mode}', level=LOG_LEVELS.Debug) if self.mode == GPT: if self.raw_parted(f'{self.blockdevice.device} mklabel gpt').exit_code == 0: + self.blockdevice.flush_cache() return self else: raise DiskError(f'Problem setting the partition format to GPT:', f'/usr/bin/parted -s {self.blockdevice.device} mklabel gpt') -- cgit v1.2.3-54-g00ecf From 83c0ee4b225d3263b7aa564035130151f8163584 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 21 Mar 2021 17:26:29 +0100 Subject: Removed some debugging output. --- archinstall/lib/disk.py | 3 --- 1 file changed, 3 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index efe3f50d..b66aa162 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -441,7 +441,6 @@ class Filesystem(): log(f'Adding partition to {self.blockdevice}', level=LOG_LEVELS.Info) previous_partitions = self.blockdevice.partitions - print(previous_partitions) if format: partitioning = self.parted(f'{self.blockdevice.device} mkpart {type} {format} {start} {end}') == 0 else: @@ -449,8 +448,6 @@ class Filesystem(): if partitioning: start_wait = time.time() - time.sleep(2) - print(self.blockdevice.partitions) while previous_partitions == self.blockdevice.partitions: time.sleep(0.025) # Let the new partition come up in the kernel if time.time() - start_wait > 10: -- cgit v1.2.3-54-g00ecf From fd4594d08cbf6de37bdd82e31af64fbec6cce4b5 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 21 Mar 2021 20:56:15 +0100 Subject: Added a mkinitcpio configuration for non-btrfs volumes but where encryption is still used. Also added keymap to the HOOKS so that we can get non-us layouts depending on the locale chosen during installation. --- archinstall/lib/installer.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 1c66f6ac..2200db8e 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -290,13 +290,22 @@ class Installer(): # TODO: Use python functions for this sys_command(f'/usr/bin/arch-chroot {self.mountpoint} chmod 700 /root') + # Configure mkinitcpio to handle some specific use cases. + # TODO: Yes, we should not overwrite the entire thing, but for now this should be fine + # since we just installed the base system. if self.partition.filesystem == 'btrfs': with open(f'{self.mountpoint}/etc/mkinitcpio.conf', 'w') as mkinit: - ## TODO: Don't replace it, in case some update in the future actually adds something. mkinit.write('MODULES=(btrfs)\n') mkinit.write('BINARIES=(/usr/bin/btrfs)\n') mkinit.write('FILES=()\n') - mkinit.write('HOOKS=(base udev autodetect modconf block encrypt filesystems keyboard fsck)\n') + mkinit.write('HOOKS=(base udev autodetect modconf block encrypt filesystems keymap keyboard fsck)\n') + sys_command(f'/usr/bin/arch-chroot {self.mountpoint} mkinitcpio -p linux') + elif self.partition.encrypted: + with open(f'{self.mountpoint}/etc/mkinitcpio.conf', 'w') as mkinit: + mkinit.write('MODULES=()\n') + mkinit.write('BINARIES=()\n') + mkinit.write('FILES=()\n') + mkinit.write('HOOKS=(base udev autodetect modconf block encrypt filesystems keymap keyboard fsck)\n') sys_command(f'/usr/bin/arch-chroot {self.mountpoint} mkinitcpio -p linux') self.helper_flags['base'] = True -- cgit v1.2.3-54-g00ecf From a3aef119b24201078857e605f2b62c7f6000e91a Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 21 Mar 2021 21:30:52 +0100 Subject: Improved english grammar and dialogues. Some 'questions' were formatted in a way where the user would enter 'yes' instead of the expected input. For instance, 'Any additional users to install:' which is a question where 'yes' is a appropriate response, but the expected input was the username to be created. Rephrased it to 'Enter a username to create a additional user:' instead for instance. --- archinstall/lib/user_interaction.py | 8 ++++---- examples/guided.py | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/user_interaction.py b/archinstall/lib/user_interaction.py index 296fa8db..c883d6a3 100644 --- a/archinstall/lib/user_interaction.py +++ b/archinstall/lib/user_interaction.py @@ -136,7 +136,7 @@ def ask_for_main_filesystem_format(): 'vfat' : 'vfat' } - value = generic_select(options.values(), "Select your main partitions filesystem by number or free-text: ") + value = generic_select(options.values(), "Select which filesystem your main partition should use (by number of name): ") return next((key for key, val in options.items() if val == value), None) def generic_select(options, input_text="Select one of the above by index or absolute value: ", sort=True): @@ -212,10 +212,10 @@ def select_profile(options): for index, profile in enumerate(profiles): print(f"{index}: {profile}") - print(' -- The above list is pre-programmed profiles. --') + print(' -- The above list is a set of pre-programmed profiles. --') print(' -- They might make it easier to install things like desktop environments. --') - print(' -- (Leave blank to skip this next optional step) --') - selected_profile = input('Any particular pre-programmed profile you want to install: ') + print(' -- (Leave blank and hit enter to skip this step and continue) --') + selected_profile = input('Enter a pre-programmed profile name if you want to install one: ') if len(selected_profile.strip()) <= 0: return None diff --git a/examples/guided.py b/examples/guided.py index b6aa5810..4766301e 100644 --- a/examples/guided.py +++ b/examples/guided.py @@ -53,7 +53,7 @@ def ask_user_questions(): # 3. Check that we support the current partitions # 2. If so, ask if we should keep them or wipe everything if archinstall.arguments['harddrive'].has_partitions(): - archinstall.log(f"{archinstall.arguments['harddrive']} contains the following partitions:", fg='red') + archinstall.log(f"{archinstall.arguments['harddrive']} contains the following partitions:", fg='yellow') # We curate a list pf supported paritions # and print those that we don't support. @@ -149,7 +149,7 @@ def ask_user_questions(): # Ask for a root password (optional, but triggers requirement for super-user if skipped) if not archinstall.arguments.get('!root-password', None): - archinstall.arguments['!root-password'] = archinstall.get_password(prompt='Enter root password (Recommended: leave blank to leave root disabled): ') + archinstall.arguments['!root-password'] = archinstall.get_password(prompt='Enter root password (Recommendation: leave blank to leave root disabled): ') # Ask for additional users (super-user if root pw was not set) archinstall.arguments['users'] = {} @@ -157,7 +157,7 @@ def ask_user_questions(): if not archinstall.arguments.get('!root-password', None): archinstall.arguments['superusers'] = archinstall.ask_for_superuser_account('Create a required super-user with sudo privileges: ', forced=True) - users, superusers = archinstall.ask_for_additional_users('Any additional users to install (leave blank for no users): ') + users, superusers = archinstall.ask_for_additional_users('Enter a username to create a additional user (leave blank to skip & continue): ') archinstall.arguments['users'] = users archinstall.arguments['superusers'] = {**archinstall.arguments['superusers'], **superusers} @@ -180,7 +180,7 @@ def ask_user_questions(): # Additional packages (with some light weight error handling for invalid package names) if not archinstall.arguments.get('packages', None): - archinstall.arguments['packages'] = [package for package in input('Additional packages aside from base (space separated): ').split(' ') if len(package)] + archinstall.arguments['packages'] = [package for package in input('Write additional packages to install (space separated, leave blank to skip): ').split(' ') if len(package)] # Verify packages that were given try: -- cgit v1.2.3-54-g00ecf From c5f6c4b71263ebfc2a6d840847328b672fd8d5c2 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Tue, 23 Mar 2021 11:28:52 +0100 Subject: Partially corrects for #116. We still don't detect if we're running as root (need to investigate if we need to run as root first). But this should at least hot-swap the log-file to the current working directory and place the logfile there. --- archinstall/lib/output.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'archinstall') diff --git a/archinstall/lib/output.py b/archinstall/lib/output.py index 0e0a295b..18cbefe0 100644 --- a/archinstall/lib/output.py +++ b/archinstall/lib/output.py @@ -96,7 +96,16 @@ def log(*args, **kwargs): if (filename := storage.get('LOG_FILE', None)): absolute_logfile = os.path.join(storage.get('LOG_PATH', './'), filename) if not os.path.isfile(absolute_logfile): - os.makedirs(os.path.dirname(absolute_logfile)) + try: + os.makedirs(os.path.dirname(absolute_logfile)) + except PermissionError: + # Fallback to creating the log file in the current folder + log(f"Not enough permission to place log file at {absolute_logfile}, creating it in {Path('./').absolute()} instead.", fg="red") + absolute_logfile = Path('./').absolute()/filename + absolute_logfile.makedirs(exist_ok=True) + storage['LOG_PATH'] = './' + + Path(absolute_logfile).touch() # Overkill? with open(absolute_logfile, 'a') as log_file: -- cgit v1.2.3-54-g00ecf From aceb0f3e98ea1009474f24cf02fdcf3e5923bcc7 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Tue, 23 Mar 2021 11:42:12 +0100 Subject: Corrected recursion loop in log() calling log() before setting the new path for the log file on errors. --- archinstall/lib/output.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/output.py b/archinstall/lib/output.py index 18cbefe0..537fb695 100644 --- a/archinstall/lib/output.py +++ b/archinstall/lib/output.py @@ -97,14 +97,15 @@ def log(*args, **kwargs): absolute_logfile = os.path.join(storage.get('LOG_PATH', './'), filename) if not os.path.isfile(absolute_logfile): try: - os.makedirs(os.path.dirname(absolute_logfile)) + Path(absolute_logfile).parents[0].mkdir(exist_ok=True, parents=True) except PermissionError: # Fallback to creating the log file in the current folder - log(f"Not enough permission to place log file at {absolute_logfile}, creating it in {Path('./').absolute()} instead.", fg="red") + err_string = f"Not enough permission to place log file at {absolute_logfile}, creating it in {Path('./').absolute()/filename} instead." absolute_logfile = Path('./').absolute()/filename - absolute_logfile.makedirs(exist_ok=True) + absolute_logfile.parents[0].mkdir(exist_ok=True) + absolute_logfile = str(absolute_logfile) storage['LOG_PATH'] = './' - + log(err_string, fg="red") Path(absolute_logfile).touch() # Overkill? -- cgit v1.2.3-54-g00ecf From b672efdf6b5951e53fa3548cc06cd1c319f82217 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Tue, 23 Mar 2021 14:18:03 +0100 Subject: Enabling archinstall.sys_command() to get a working directory when executing. The sys_command() is working pretty well for this very specific need, but this is an attempt to making it a bit more generic. A more general overhaul of the command should be done at some point. --- archinstall/lib/general.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'archinstall') diff --git a/archinstall/lib/general.py b/archinstall/lib/general.py index 28fc0934..d79bbaa2 100644 --- a/archinstall/lib/general.py +++ b/archinstall/lib/general.py @@ -106,7 +106,11 @@ class sys_command():#Thread): user_catalogue = os.path.expanduser('~') self.cwd = f"{user_catalogue}/.cache/archinstall/workers/{kwargs['worker_id']}/" - self.exec_dir = f'{self.cwd}/{os.path.basename(self.cmd[0])}_workingdir' + + if (workdir := kwargs.get('workdir', None)): + self.exec_dir = workdir + else: + self.exec_dir = f'{self.cwd}/{os.path.basename(self.cmd[0])}_workingdir' if not self.cmd[0][0] == '/': # "which" doesn't work as it's a builtin to bash. -- cgit v1.2.3-54-g00ecf From becd29fa54beaced554f6cf54d44706192ea9a9c Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Tue, 23 Mar 2021 14:22:38 +0100 Subject: Also setting cwd (bad choice of name) to the workdir if one was specified. Which makes the trace.log to end up in the workdir as well. --- archinstall/lib/general.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'archinstall') diff --git a/archinstall/lib/general.py b/archinstall/lib/general.py index d79bbaa2..f2a714e7 100644 --- a/archinstall/lib/general.py +++ b/archinstall/lib/general.py @@ -105,11 +105,12 @@ class sys_command():#Thread): self.status = 'starting' user_catalogue = os.path.expanduser('~') - self.cwd = f"{user_catalogue}/.cache/archinstall/workers/{kwargs['worker_id']}/" if (workdir := kwargs.get('workdir', None)): + self.cwd = workdir self.exec_dir = workdir else: + self.cwd = f"{user_catalogue}/.cache/archinstall/workers/{kwargs['worker_id']}/" self.exec_dir = f'{self.cwd}/{os.path.basename(self.cmd[0])}_workingdir' if not self.cmd[0][0] == '/': -- cgit v1.2.3-54-g00ecf From 037332a18d2c506d1dd0bef7b3450c8308792f61 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Wed, 24 Mar 2021 15:26:32 +0100 Subject: Removed vfat as an option for the root partition --- archinstall/lib/user_interaction.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/user_interaction.py b/archinstall/lib/user_interaction.py index c883d6a3..e462c370 100644 --- a/archinstall/lib/user_interaction.py +++ b/archinstall/lib/user_interaction.py @@ -132,8 +132,7 @@ def ask_for_main_filesystem_format(): 'btrfs' : 'btrfs', 'ext4' : 'ext4', 'xfs' : 'xfs', - 'f2fs' : 'f2fs', - 'vfat' : 'vfat' + 'f2fs' : 'f2fs' } value = generic_select(options.values(), "Select which filesystem your main partition should use (by number of name): ") @@ -317,4 +316,4 @@ def select_mirror_regions(mirrors, show_top_mirrors=True): return selected_mirrors - raise RequirementError("Selecting mirror region require a least one region to be given as an option.") \ No newline at end of file + raise RequirementError("Selecting mirror region require a least one region to be given as an option.") -- cgit v1.2.3-54-g00ecf From 89a2e1eb2b4f02df2d5ccab4c11f4c9f22dd9b48 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Wed, 24 Mar 2021 15:49:54 +0100 Subject: Fixes an issue with completely empty hard drives If empty hard drives are being set up for the first time, then `.has_content()`'s `mount` call will fail with `wrong fstype` since there's no filesystem yet. First step in this case is to check for that scenario, then check for content. --- archinstall/lib/disk.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'archinstall') diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index b66aa162..2eef0e82 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -204,6 +204,9 @@ class Partition(): return None def has_content(self): + if not get_filesystem_type(self.path): + return False + temporary_mountpoint = '/tmp/'+hashlib.md5(bytes(f"{time.time()}", 'UTF-8')+os.urandom(12)).hexdigest() temporary_path = pathlib.Path(temporary_mountpoint) @@ -529,4 +532,4 @@ def get_filesystem_type(path): handle = sys_command(f"blkid -o value -s TYPE {path}") return b''.join(handle).strip().decode('UTF-8') except SysCallError: - return None \ No newline at end of file + return None -- cgit v1.2.3-54-g00ecf From 37a6018aaeed53ca95d9c7f81981db98aab24eab Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 28 Mar 2021 22:36:47 +0200 Subject: Fixed a path-check issue with Time Zones. --- archinstall/lib/installer.py | 16 ++++++++++++---- archinstall/lib/user_interaction.py | 8 +++++++- 2 files changed, 19 insertions(+), 5 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 2200db8e..ff47be01 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -169,11 +169,19 @@ class Installer(): return True if sys_command(f'/usr/bin/arch-chroot {self.mountpoint} locale-gen').exit_code == 0 else False def set_timezone(self, zone, *args, **kwargs): - if not len(zone): return True + if not zone: return True + if not len(zone): return True # Redundant - (pathlib.Path(self.mountpoint)/"etc"/"localtime").unlink(missing_ok=True) - sys_command(f'/usr/bin/arch-chroot {self.mountpoint} ln -s /usr/share/zoneinfo/{zone} /etc/localtime') - return True + if (pathlib.Path("/usr")/"share"/"zoneinfo"/zone).exists(): + (pathlib.Path(self.mountpoint)/"etc"/"localtime").unlink(missing_ok=True) + sys_command(f'/usr/bin/arch-chroot {self.mountpoint} ln -s /usr/share/zoneinfo/{zone} /etc/localtime') + return True + else: + self.log( + f"Time zone {zone} does not exist, continuing with system default.", + level=LOG_LEVELS.Warning, + fg='red' + ) def activate_ntp(self): self.log(f'Installing and activating NTP.', level=LOG_LEVELS.Info) diff --git a/archinstall/lib/user_interaction.py b/archinstall/lib/user_interaction.py index e462c370..a79b4847 100644 --- a/archinstall/lib/user_interaction.py +++ b/archinstall/lib/user_interaction.py @@ -77,8 +77,14 @@ def ask_for_additional_users(prompt='Any additional users to install (leave blan def ask_for_a_timezone(): timezone = input('Enter a valid timezone (Example: Europe/Stockholm): ').strip() - if pathlib.Path(timezone).exists(): + if (pathlib.Path("/usr")/"share"/"zoneinfo"/timezone).exists(): return timezone + else: + log( + f"Time zone {timezone} does not exist, continuing with system default.", + level=LOG_LEVELS.Warning, + fg='red' + ) def ask_to_configure_network(): # Optionally configure one network interface. -- cgit v1.2.3-54-g00ecf From 0637ab6eb0b4be84bb03ffae41113c6a424f71e6 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 28 Mar 2021 23:03:41 +0200 Subject: Adding debug to correct for a potential issue where partitions get marked as encrypted even tho \!disk-password was neven set. --- archinstall/lib/disk.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index 2eef0e82..c1db3dc9 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -142,7 +142,7 @@ class Partition(): self.target_mountpoint = mountpoint self.filesystem = filesystem self.size = size # TODO: Refresh? - self.encrypted = encrypted + self._encrypted = encrypted self.allow_formatting = False # A fail-safe for unconfigured partitions, such as windows NTFS partitions. if mountpoint: @@ -161,7 +161,7 @@ class Partition(): self.filesystem = fstype if self.filesystem == 'crypto_LUKS': - self.encrypted = True + self._encrypted = True def __lt__(self, left_comparitor): if type(left_comparitor) == Partition: @@ -177,14 +177,23 @@ class Partition(): elif self.target_mountpoint: mount_repr = f", rel_mountpoint={self.target_mountpoint}" - if self.encrypted: + if self._encrypted: return f'Partition(path={self.path}, real_device={self.real_device}, fs={self.filesystem}{mount_repr})' else: return f'Partition(path={self.path}, fs={self.filesystem}{mount_repr})' + @property + def encrypted(self): + return self._encrypted + + @encrypted.setter + def encrypted(self, value :bool): + log(f'Marking {self} as encrypted', level=LOG_LEVELS.Debug) + self._encrypted = value + @property def real_device(self): - if not self.encrypted: + if not self._encrypted: return self.path else: for blockdevice in json.loads(b''.join(sys_command('lsblk -J')).decode('UTF-8'))['blockdevices']: @@ -237,7 +246,7 @@ class Partition(): """ from .luks import luks2 - if not self.encrypted: + if not self._encrypted: raise DiskError(f"Attempting to encrypt a partition that was not marked for encryption: {self}") if not self.safe_to_format(): -- cgit v1.2.3-54-g00ecf From 37ad64147f4f20823e789a16a2e48016299d0607 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 28 Mar 2021 23:10:23 +0200 Subject: Added some more useful debug data to the log. --- archinstall/lib/installer.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index ff47be01..d161c3b7 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -369,10 +369,12 @@ class Installer(): if self.partition.encrypted: - log(f"Identifying root partition {self.partition} to boot based on disk UUID, looking for '{os.path.basename(self.partition.real_device)}'.", level=LOG_LEVELS.Debug) + log(f"Identifying root partition by DISK-UUID on {self.partition}, looking for '{os.path.basename(self.partition.real_device)}'.", level=LOG_LEVELS.Debug) for root, folders, uids in os.walk('/dev/disk/by-uuid'): for uid in uids: real_path = os.path.realpath(os.path.join(root, uid)) + + log(f"Checking root partition match {os.path.basename(real_path)} against {os.path.basename(self.partition.real_device)}: {os.path.basename(real_path) == os.path.basename(self.partition.real_device)}", level=LOG_LEVELS.Debug) if not os.path.basename(real_path) == os.path.basename(self.partition.real_device): continue entry.write(f'options cryptdevice=UUID={uid}:luksdev root=/dev/mapper/luksdev rw intel_pstate=no_hwp\n') @@ -381,10 +383,12 @@ class Installer(): return True break else: - log(f"Identifying root partition {self.partition} to boot based on partition UUID, looking for '{os.path.basename(self.partition.path)}'.", level=LOG_LEVELS.Debug) + log(f"Identifying root partition by PART-UUID on {self.partition}, looking for '{os.path.basename(self.partition.path)}'.", level=LOG_LEVELS.Debug) for root, folders, uids in os.walk('/dev/disk/by-partuuid'): for uid in uids: real_path = os.path.realpath(os.path.join(root, uid)) + + log(f"Checking root partition match {os.path.basename(real_path)} against {os.path.basename(self.partition.path)}: {os.path.basename(real_path) == os.path.basename(self.partition.path)}", level=LOG_LEVELS.Debug) if not os.path.basename(real_path) == os.path.basename(self.partition.path): continue entry.write(f'options root=PARTUUID={uid} rw intel_pstate=no_hwp\n') -- cgit v1.2.3-54-g00ecf From a156f224a87a02d6b0f9a54eef2ce18e418e5187 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 29 Mar 2021 08:56:41 +0200 Subject: Fixing un-encrypted drives matching on block encrypted. --- archinstall/lib/disk.py | 5 +++-- examples/guided.py | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index c1db3dc9..85b08bc0 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -142,7 +142,8 @@ class Partition(): self.target_mountpoint = mountpoint self.filesystem = filesystem self.size = size # TODO: Refresh? - self._encrypted = encrypted + self._encrypted = None + self.encrypted = encrypted self.allow_formatting = False # A fail-safe for unconfigured partitions, such as windows NTFS partitions. if mountpoint: @@ -161,7 +162,7 @@ class Partition(): self.filesystem = fstype if self.filesystem == 'crypto_LUKS': - self._encrypted = True + self.encrypted = True def __lt__(self, left_comparitor): if type(left_comparitor) == Partition: diff --git a/examples/guided.py b/examples/guided.py index 4766301e..d9dfe0df 100644 --- a/examples/guided.py +++ b/examples/guided.py @@ -292,6 +292,7 @@ def perform_installation(device, boot_partition, language, mirrors): Only requirement is that the block devices are formatted and setup prior to entering this function. """ + print('Installing on:', device) with archinstall.Installer(device, boot_partition=boot_partition, hostname=archinstall.arguments.get('hostname', 'Archinstall')) as installation: ## if len(mirrors): # Certain services might be running that affects the system during installation. -- cgit v1.2.3-54-g00ecf From 3161cd8afff2def3d4d3057cb028c666c4db55a3 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 29 Mar 2021 09:09:25 +0200 Subject: Fixing rare occation where partitions dissapear just before .format(). --- archinstall/lib/disk.py | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'archinstall') diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index 85b08bc0..9afece2e 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -270,6 +270,11 @@ class Partition(): if allow_formatting is None: allow_formatting = self.allow_formatting + # To avoid "unable to open /dev/x: No such file or directory" + start_wait = time.time() + while pathlib.Path(path).exists() is False and time.time() - start_wait < 10: + time.sleep(0.025) + if not allow_formatting: raise PermissionError(f"{self} is not formatable either because instance is locked ({self.allow_formatting}) or a blocking flag was given ({allow_formatting})") -- cgit v1.2.3-54-g00ecf From f452dc695a6a2929ecf796f1730af3b683b1a449 Mon Sep 17 00:00:00 2001 From: Didr Date: Mon, 29 Mar 2021 10:16:20 +0200 Subject: Fix spelling error in filesystem choice Fixes a simple spelling error when the user is asked to select a filesystem. "Select which filesystem your main partition should use (by number **of** name)" should be **or**. --- archinstall/lib/user_interaction.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'archinstall') diff --git a/archinstall/lib/user_interaction.py b/archinstall/lib/user_interaction.py index a79b4847..a782197e 100644 --- a/archinstall/lib/user_interaction.py +++ b/archinstall/lib/user_interaction.py @@ -141,7 +141,7 @@ def ask_for_main_filesystem_format(): 'f2fs' : 'f2fs' } - value = generic_select(options.values(), "Select which filesystem your main partition should use (by number of name): ") + value = generic_select(options.values(), "Select which filesystem your main partition should use (by number or name): ") return next((key for key, val in options.items() if val == value), None) def generic_select(options, input_text="Select one of the above by index or absolute value: ", sort=True): -- cgit v1.2.3-54-g00ecf From 36dfa2e1c42add691243850b62b705b26a0a796c Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 29 Mar 2021 10:20:35 +0200 Subject: Reverting .strip() logic and moving the check into the get_password() function. --- archinstall/lib/user_interaction.py | 4 ++++ examples/guided.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'archinstall') diff --git a/archinstall/lib/user_interaction.py b/archinstall/lib/user_interaction.py index a79b4847..bee7b569 100644 --- a/archinstall/lib/user_interaction.py +++ b/archinstall/lib/user_interaction.py @@ -24,6 +24,10 @@ def get_password(prompt="Enter a password: "): if passwd != passwd_verification: log(' * Passwords did not match * ', bg='black', fg='red') continue + + if len(passwd.strip()) <= 0: + break + return passwd return None diff --git a/examples/guided.py b/examples/guided.py index 009f9fa6..92331450 100644 --- a/examples/guided.py +++ b/examples/guided.py @@ -139,7 +139,7 @@ def ask_user_questions(): # Get disk encryption password (or skip if blank) if not archinstall.arguments.get('!encryption-password', None): - if (passwd := archinstall.get_password(prompt='Enter disk encryption password (leave blank for no encryption): ')).strip(): + if (passwd := archinstall.get_password(prompt='Enter disk encryption password (leave blank for no encryption): ')): archinstall.arguments['!encryption-password'] = passwd archinstall.arguments['harddrive'].encryption_password = archinstall.arguments['!encryption-password'] -- cgit v1.2.3-54-g00ecf From e94a8d8b25060e0ab2a47215d773825e649a43aa Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 29 Mar 2021 13:16:42 +0200 Subject: Debugging --- archinstall/lib/disk.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'archinstall') diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index 9afece2e..5e16558e 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -452,6 +452,8 @@ class Filesystem(): self.blockdevice.partition[1].allow_formatting = True if encrypt_root_partition: + raise ValueError("moo") + exit(1) log(f"Marking partition {self.blockdevice.partition[1]} as encrypted.", level=LOG_LEVELS.Debug) self.blockdevice.partition[1].encrypted = True -- cgit v1.2.3-54-g00ecf From 0e269752479ff68fba73d4c04ea0f28718f945cd Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 29 Mar 2021 15:55:36 +0200 Subject: Adding callstack to debug output for easier debugging. Removed hardcoded debug crash --- archinstall/lib/disk.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index 5e16558e..3efee8b4 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -1,5 +1,5 @@ import glob, re, os, json, time, hashlib -import pathlib +import pathlib, traceback from collections import OrderedDict from .exceptions import DiskError from .general import * @@ -452,9 +452,9 @@ class Filesystem(): self.blockdevice.partition[1].allow_formatting = True if encrypt_root_partition: - raise ValueError("moo") - exit(1) log(f"Marking partition {self.blockdevice.partition[1]} as encrypted.", level=LOG_LEVELS.Debug) + log(f"Callstrack when marking the partition: {''.join(traceback.format_stack())}", level=LOG_LEVELS.Debug) + self.blockdevice.partition[1].encrypted = True def add_partition(self, type, start, end, format=None): -- cgit v1.2.3-54-g00ecf From 39cb0b94d94c3f4fa0dec4002e8d9221fb28c753 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 29 Mar 2021 15:57:31 +0200 Subject: Moved some debugging to catch more variable settings. --- archinstall/lib/disk.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'archinstall') diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index 3efee8b4..7bc09a0b 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -190,6 +190,7 @@ class Partition(): @encrypted.setter def encrypted(self, value :bool): log(f'Marking {self} as encrypted', level=LOG_LEVELS.Debug) + log(f"Callstrack when marking the partition: {''.join(traceback.format_stack())}", level=LOG_LEVELS.Debug) self._encrypted = value @property @@ -453,7 +454,6 @@ class Filesystem(): if encrypt_root_partition: log(f"Marking partition {self.blockdevice.partition[1]} as encrypted.", level=LOG_LEVELS.Debug) - log(f"Callstrack when marking the partition: {''.join(traceback.format_stack())}", level=LOG_LEVELS.Debug) self.blockdevice.partition[1].encrypted = True -- cgit v1.2.3-54-g00ecf From d26c1f820ddef17bfd9d1a536fbc8a068e815ff6 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 29 Mar 2021 16:11:30 +0200 Subject: Toned down the debugging a bit. --- archinstall/lib/disk.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index 7bc09a0b..0e42feca 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -189,8 +189,9 @@ class Partition(): @encrypted.setter def encrypted(self, value :bool): - log(f'Marking {self} as encrypted', level=LOG_LEVELS.Debug) - log(f"Callstrack when marking the partition: {''.join(traceback.format_stack())}", level=LOG_LEVELS.Debug) + if value: + log(f'Marking {self} as encrypted: {value}', level=LOG_LEVELS.Debug) + log(f"Callstrack when marking the partition: {''.join(traceback.format_stack())}", level=LOG_LEVELS.Debug) self._encrypted = value @property -- cgit v1.2.3-54-g00ecf From 5e9c973d42125bb809443670c1e30439e4b11b17 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 29 Mar 2021 16:51:30 +0200 Subject: Added support for flushing a BlockDevice() cache after a partition has been formatted. This is to avoid internal confusion of which partitions are encrypted or not when going from Encrypted -> Un-encrypted setups. --- archinstall/lib/disk.py | 11 +++++++++-- archinstall/lib/luks.py | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index 0e42feca..518c1503 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -107,7 +107,7 @@ class BlockDevice(): if part_id not in self.part_cache: ## TODO: Force over-write even if in cache? if part_id not in self.part_cache or self.part_cache[part_id].size != part['size']: - self.part_cache[part_id] = Partition(root_path + part_id, part_id=part_id, size=part['size']) + self.part_cache[part_id] = Partition(root_path + part_id, self, part_id=part_id, size=part['size']) return {k: self.part_cache[k] for k in sorted(self.part_cache)} @@ -133,9 +133,11 @@ class BlockDevice(): self.part_cache = OrderedDict() class Partition(): - def __init__(self, path, part_id=None, size=-1, filesystem=None, mountpoint=None, encrypted=False, autodetect_filesystem=True): + def __init__(self, path :str, block_device :BlockDevice, part_id=None, size=-1, filesystem=None, mountpoint=None, encrypted=False, autodetect_filesystem=True): if not part_id: part_id = os.path.basename(path) + + self.block_device = block_device self.path = path self.part_id = part_id self.mountpoint = mountpoint @@ -192,6 +194,7 @@ class Partition(): if value: log(f'Marking {self} as encrypted: {value}', level=LOG_LEVELS.Debug) log(f"Callstrack when marking the partition: {''.join(traceback.format_stack())}", level=LOG_LEVELS.Debug) + self._encrypted = value @property @@ -318,6 +321,10 @@ class Partition(): else: raise UnknownFilesystemFormat(f"Fileformat '{filesystem}' is not yet implemented.") + + if self.block_device: + self.block_device.flush_cache() + return True def find_parent_of(self, data, name, parent=None): diff --git a/archinstall/lib/luks.py b/archinstall/lib/luks.py index 30c38ec8..19c21795 100644 --- a/archinstall/lib/luks.py +++ b/archinstall/lib/luks.py @@ -113,7 +113,7 @@ class luks2(): sys_command(f'/usr/bin/cryptsetup open {partition.path} {mountpoint} --key-file {os.path.abspath(key_file)} --type luks2') if os.path.islink(f'/dev/mapper/{mountpoint}'): self.mapdev = f'/dev/mapper/{mountpoint}' - unlocked_partition = Partition(self.mapdev, encrypted=True, filesystem=get_filesystem_type(self.mapdev), autodetect_filesystem=False) + unlocked_partition = Partition(self.mapdev, None, encrypted=True, filesystem=get_filesystem_type(self.mapdev), autodetect_filesystem=False) unlocked_partition.allow_formatting = self.partition.allow_formatting return unlocked_partition -- cgit v1.2.3-54-g00ecf From f3907310e3fbbc07ad31f3558279cd73ba774472 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 29 Mar 2021 16:59:09 +0200 Subject: Allowing individual partitions safety checks to rely on the parent blockdevice keep_partitions status. --- archinstall/lib/disk.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'archinstall') diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index 518c1503..d6d28935 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -237,6 +237,9 @@ class Partition(): return True if files > 0 else False def safe_to_format(self): + if self.block_device and self.block_device.keep_partitions is True: + return True + if self.allow_formatting is False: log(f"Partition {self} is not marked for formatting.", level=LOG_LEVELS.Debug) return False -- cgit v1.2.3-54-g00ecf From a0980afff1d2458d348e144cb0d8351f862564c1 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 29 Mar 2021 17:32:48 +0200 Subject: Experimenting with carrying over flags across cache flush. This to solve issues when flush is cleared and target mountpoints gets lost, making it impossible to do .find_mountpoint('/') later on for instance. --- archinstall/lib/disk.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'archinstall') diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index d6d28935..84a4ff37 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -130,7 +130,20 @@ class BlockDevice(): return False def flush_cache(self): + old_partitions = {**self.partitions} + self.part_cache = OrderedDict() + # Trigger a refresh of the cache + if len(self.partitions): + pass + + # Carry over any flags from the previous partitions + for partition in old_partitions: + if partition in self.part_cache: + if self.part_cache[partition].size == old_partitions[partition].size and \ + self.part_cache[partition].filesystem == old_partitions[partition].filesystem: + print('Carrying over', self.part_cache[partition].target_mountpoint) + self.part_cache[partition].target_mountpoint = old_partitions[partition].target_mountpoint class Partition(): def __init__(self, path :str, block_device :BlockDevice, part_id=None, size=-1, filesystem=None, mountpoint=None, encrypted=False, autodetect_filesystem=True): @@ -237,7 +250,9 @@ class Partition(): return True if files > 0 else False def safe_to_format(self): - if self.block_device and self.block_device.keep_partitions is True: + if self.block_device and self.block_device.keep_partitions is False: + # If we don't intend to keep any partitions on the parent block device + # We're good to format. return True if self.allow_formatting is False: @@ -325,6 +340,7 @@ class Partition(): else: raise UnknownFilesystemFormat(f"Fileformat '{filesystem}' is not yet implemented.") + # self.encrypted = False if self.filesystem != 'crypto_LUKS' else True if self.block_device: self.block_device.flush_cache() -- cgit v1.2.3-54-g00ecf From 512f0327f0d5eb9e507050ff9a4325e9728df705 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 29 Mar 2021 17:34:13 +0200 Subject: Experimenting with cache, carrying over .allow_formatting --- archinstall/lib/disk.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'archinstall') diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index 84a4ff37..3e512034 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -142,8 +142,9 @@ class BlockDevice(): if partition in self.part_cache: if self.part_cache[partition].size == old_partitions[partition].size and \ self.part_cache[partition].filesystem == old_partitions[partition].filesystem: - print('Carrying over', self.part_cache[partition].target_mountpoint) + print('Carrying over', self.part_cache[partition].target_mountpoint, self.part_cache[partition].allow_formatting) self.part_cache[partition].target_mountpoint = old_partitions[partition].target_mountpoint + self.part_cache[partition].allow_formatting = old_partitions[partition].allow_formatting class Partition(): def __init__(self, path :str, block_device :BlockDevice, part_id=None, size=-1, filesystem=None, mountpoint=None, encrypted=False, autodetect_filesystem=True): -- cgit v1.2.3-54-g00ecf From a29bd759548c02c609aa43d9536475b1259a70f9 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 29 Mar 2021 17:46:07 +0200 Subject: Removing a flush of the cache that was excessive. --- archinstall/lib/disk.py | 25 ++----------------------- examples/guided.py | 8 ++++---- 2 files changed, 6 insertions(+), 27 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index 3e512034..4e70a4a5 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -130,21 +130,7 @@ class BlockDevice(): return False def flush_cache(self): - old_partitions = {**self.partitions} - self.part_cache = OrderedDict() - # Trigger a refresh of the cache - if len(self.partitions): - pass - - # Carry over any flags from the previous partitions - for partition in old_partitions: - if partition in self.part_cache: - if self.part_cache[partition].size == old_partitions[partition].size and \ - self.part_cache[partition].filesystem == old_partitions[partition].filesystem: - print('Carrying over', self.part_cache[partition].target_mountpoint, self.part_cache[partition].allow_formatting) - self.part_cache[partition].target_mountpoint = old_partitions[partition].target_mountpoint - self.part_cache[partition].allow_formatting = old_partitions[partition].allow_formatting class Partition(): def __init__(self, path :str, block_device :BlockDevice, part_id=None, size=-1, filesystem=None, mountpoint=None, encrypted=False, autodetect_filesystem=True): @@ -341,9 +327,7 @@ class Partition(): else: raise UnknownFilesystemFormat(f"Fileformat '{filesystem}' is not yet implemented.") - # self.encrypted = False if self.filesystem != 'crypto_LUKS' else True - if self.block_device: - self.block_device.flush_cache() + self.encrypted = False if self.filesystem != 'crypto_LUKS' else True return True @@ -460,7 +444,7 @@ class Filesystem(): """ return self.raw_parted(string).exit_code - def use_entire_disk(self, root_filesystem_type='ext4', encrypt_root_partition=True): + def use_entire_disk(self, root_filesystem_type='ext4'): log(f"Using and formatting the entire {self.blockdevice}.", level=LOG_LEVELS.Debug) self.add_partition('primary', start='1MiB', end='513MiB', format='fat32') self.set_name(0, 'EFI') @@ -480,11 +464,6 @@ class Filesystem(): self.blockdevice.partition[0].allow_formatting = True self.blockdevice.partition[1].allow_formatting = True - if encrypt_root_partition: - log(f"Marking partition {self.blockdevice.partition[1]} as encrypted.", level=LOG_LEVELS.Debug) - - self.blockdevice.partition[1].encrypted = True - def add_partition(self, type, start, end, format=None): log(f'Adding partition to {self.blockdevice}', level=LOG_LEVELS.Info) diff --git a/examples/guided.py b/examples/guided.py index 92331450..71e1e01d 100644 --- a/examples/guided.py +++ b/examples/guided.py @@ -247,10 +247,10 @@ def perform_installation_steps(): with archinstall.Filesystem(archinstall.arguments['harddrive'], archinstall.GPT) as fs: # Wipe the entire drive if the disk flag `keep_partitions`is False. if archinstall.arguments['harddrive'].keep_partitions is False: - fs.use_entire_disk(root_filesystem_type=archinstall.arguments.get('filesystem', 'btrfs'), - encrypt_root_partition=archinstall.arguments.get('!encryption-password', False)) - # Otherwise, check if encryption is desired and mark the root partition as encrypted. - elif archinstall.arguments.get('!encryption-password', None): + fs.use_entire_disk(root_filesystem_type=archinstall.arguments.get('filesystem', 'btrfs')) + + # Check if encryption is desired and mark the root partition as encrypted. + if archinstall.arguments.get('!encryption-password', None): root_partition = fs.find_partition('/') root_partition.encrypted = True -- cgit v1.2.3-54-g00ecf From 0c86440e2e63c5e66e64679e79ff675b9cc3f1dd Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 29 Mar 2021 17:47:34 +0200 Subject: Rolling back change to check parent blockdevice for safe formatting, it would wipe the boot partition if the boot partition for multiple drives was shared on the specific drive. --- archinstall/lib/disk.py | 5 ----- 1 file changed, 5 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index 4e70a4a5..f0651685 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -237,11 +237,6 @@ class Partition(): return True if files > 0 else False def safe_to_format(self): - if self.block_device and self.block_device.keep_partitions is False: - # If we don't intend to keep any partitions on the parent block device - # We're good to format. - return True - if self.allow_formatting is False: log(f"Partition {self} is not marked for formatting.", level=LOG_LEVELS.Debug) return False -- cgit v1.2.3-54-g00ecf From 1b903550b588d1ade90eae034b757e2950398550 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 29 Mar 2021 17:53:30 +0200 Subject: Reworking cache logic to not loose .encrypted flag on partitions after flushing cache. --- archinstall/lib/disk.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'archinstall') diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index f0651685..18006311 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -322,7 +322,8 @@ class Partition(): else: raise UnknownFilesystemFormat(f"Fileformat '{filesystem}' is not yet implemented.") - self.encrypted = False if self.filesystem != 'crypto_LUKS' else True + if get_filesystem_type(path) == 'crypto_LUKS': + self.encrypted = True return True -- cgit v1.2.3-54-g00ecf From 8c8a441c2627a180671eb7fcd95b3a0f8d0a102e Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 29 Mar 2021 18:10:02 +0200 Subject: Added some debugging. --- archinstall/lib/disk.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'archinstall') diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index 18006311..23fbf621 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -322,7 +322,9 @@ class Partition(): else: raise UnknownFilesystemFormat(f"Fileformat '{filesystem}' is not yet implemented.") - if get_filesystem_type(path) == 'crypto_LUKS': + print('Checking if encrypted:', path) + print('Also checking:', self.real_device) + if get_filesystem_type(path) == 'crypto_LUKS' or get_filesystem_type(self.real_device) == 'crypto_LUKS': self.encrypted = True return True -- cgit v1.2.3-54-g00ecf From a50aa59060591a121a7b58e58487b6a2840825f3 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 29 Mar 2021 18:11:46 +0200 Subject: Adding .encrypted logic after .format calls to correctly identify partitions as encrypted/not-encrypted. This after a .flush_cache has been called. --- archinstall/lib/disk.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index 23fbf621..9ad49ac2 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -322,10 +322,10 @@ class Partition(): else: raise UnknownFilesystemFormat(f"Fileformat '{filesystem}' is not yet implemented.") - print('Checking if encrypted:', path) - print('Also checking:', self.real_device) if get_filesystem_type(path) == 'crypto_LUKS' or get_filesystem_type(self.real_device) == 'crypto_LUKS': self.encrypted = True + else: + self.encrypted = False return True -- cgit v1.2.3-54-g00ecf From 151c90a56d2dbf4daa7edb5545d25e2484df08f7 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 29 Mar 2021 18:12:05 +0200 Subject: Added some debugging. --- archinstall/lib/disk.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'archinstall') diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index 9ad49ac2..0425321d 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -322,6 +322,8 @@ class Partition(): else: raise UnknownFilesystemFormat(f"Fileformat '{filesystem}' is not yet implemented.") + print('Checking if encrypted:', path) + print('Also checking:', self.real_device) if get_filesystem_type(path) == 'crypto_LUKS' or get_filesystem_type(self.real_device) == 'crypto_LUKS': self.encrypted = True else: -- cgit v1.2.3-54-g00ecf From b03de49f0f6d29ec8cb7588c2216eb70d523e74d Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 29 Mar 2021 18:17:09 +0200 Subject: Removed debugging and finalized fix. --- archinstall/lib/disk.py | 2 -- 1 file changed, 2 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index 0425321d..9ad49ac2 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -322,8 +322,6 @@ class Partition(): else: raise UnknownFilesystemFormat(f"Fileformat '{filesystem}' is not yet implemented.") - print('Checking if encrypted:', path) - print('Also checking:', self.real_device) if get_filesystem_type(path) == 'crypto_LUKS' or get_filesystem_type(self.real_device) == 'crypto_LUKS': self.encrypted = True else: -- cgit v1.2.3-54-g00ecf From 82342a0e94ed6d591b9855db590719764e9cb460 Mon Sep 17 00:00:00 2001 From: kpcyrd Date: Tue, 30 Mar 2021 16:12:52 +0200 Subject: Add range check to generic_select --- archinstall/lib/user_interaction.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'archinstall') diff --git a/archinstall/lib/user_interaction.py b/archinstall/lib/user_interaction.py index defc2cfc..b3e0b665 100644 --- a/archinstall/lib/user_interaction.py +++ b/archinstall/lib/user_interaction.py @@ -170,7 +170,10 @@ def generic_select(options, input_text="Select one of the above by index or abso if len(selected_option.strip()) <= 0: return None elif selected_option.isdigit(): - selected_option = options[int(selected_option)] + selected_option = int(selected_option) + if selected_option >= len(options): + raise RequirementError(f'Selected option "{selected_option}" is out of range') + selected_option = options[selected_option] elif selected_option in options: pass # We gave a correct absolute value else: -- cgit v1.2.3-54-g00ecf From 40dbb5791c4be60d671d0a4abd2e9ba70e11b896 Mon Sep 17 00:00:00 2001 From: kpcyrd Date: Tue, 30 Mar 2021 16:24:48 +0200 Subject: Add range check to disk selection --- archinstall/lib/user_interaction.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'archinstall') diff --git a/archinstall/lib/user_interaction.py b/archinstall/lib/user_interaction.py index b3e0b665..80db7be1 100644 --- a/archinstall/lib/user_interaction.py +++ b/archinstall/lib/user_interaction.py @@ -198,7 +198,10 @@ def select_disk(dict_o_disks): print(f"{index}: {drive} ({dict_o_disks[drive]['size'], dict_o_disks[drive].device, dict_o_disks[drive]['label']})") drive = input('Select one of the above disks (by number or full path): ') if drive.isdigit(): - drive = dict_o_disks[drives[int(drive)]] + drive = int(drive) + if drive >= len(drives): + raise DiskError(f'Selected option "{drive}" is out of range') + drive = dict_o_disks[drives[drive]] elif drive in dict_o_disks: drive = dict_o_disks[drive] else: -- cgit v1.2.3-54-g00ecf