From 51eb05691a5845652a9dc583de05519f095961f3 Mon Sep 17 00:00:00 2001 From: Hamad Al Marri Date: Wed, 7 Jul 2021 18:38:55 +0300 Subject: Fix encryption + grub both in UEFI and BIOS systems. We need to have two partitions in BIOS one for boot (grub) and the other for root (/). The format of the boot partition is ext2 (so it is added). If disk is chosen to be encrypted, `then /etc/default/grub` is edited as the followings: https://wiki.archlinux.org/title/Dm-crypt/Encrypting_an_entire_system#Configuring_GRUB_2 Issue: https://github.com/archlinux/archinstall/issues/586 This work is done while working on CachyOS which is Arch based and it is using customized archinstaller. To test these changes you can try CachyOS installer which supports encrypted disk with grub (https://wiki.cachyos.org/). Hamad --- archinstall/lib/disk.py | 23 ++++++++++++++++++----- archinstall/lib/installer.py | 18 ++++++++++++------ 2 files changed, 30 insertions(+), 11 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index de39bafd..954dc732 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -347,6 +347,11 @@ class Partition: raise DiskError(f'Could not format {path} with {filesystem} because: {b"".join(handle)}') self.filesystem = 'ext4' + elif filesystem == 'ext2': + if (handle := SysCommand(f'/usr/bin/mkfs.ext2 -F {path}')).exit_code != 0: + raise DiskError(f'Could not format {path} with {filesystem} because: {b"".join(handle)}') + self.filesystem = 'ext2' + elif filesystem == 'xfs': if (handle := SysCommand(f'/usr/bin/mkfs.xfs -f {path}')).exit_code != 0: raise DiskError(f'Could not format {path} with {filesystem} because: {b"".join(handle)}') @@ -518,12 +523,20 @@ class Filesystem: self.blockdevice.partition[0].allow_formatting = True self.blockdevice.partition[1].allow_formatting = True else: - # we don't need a seprate boot partition it would be a waste of space - self.add_partition('primary', start='1MB', end='100%') - self.blockdevice.partition[0].filesystem = root_filesystem_type - log(f"Set the root partition {self.blockdevice.partition[0]} to use filesystem {root_filesystem_type}.", level=logging.DEBUG) - self.blockdevice.partition[0].target_mountpoint = '/' + self.add_partition('primary', start='1MiB', end='513MiB', partition_format='ext2') + self.set(0, 'boot on') + self.add_partition('primary', start='513MiB', end='100%') + + self.blockdevice.partition[0].filesystem = 'ext2' + 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=logging.DEBUG) + + 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 def add_partition(self, partition_type, start, end, partition_format=None): log(f'Adding partition to {self.blockdevice}', level=logging.INFO) diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index da6f6a9b..25b5331a 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -409,7 +409,7 @@ class Installer: return True - def add_bootloader(self, bootloader='systemd-bootctl'): + def add_bootloader(self, _device, bootloader='systemd-bootctl'): for plugin in plugins.values(): if hasattr(plugin, 'on_add_bootloader'): # Allow plugins to override the boot-loader handling. @@ -500,7 +500,16 @@ class Installer: self.helper_flags['bootloader'] = bootloader elif bootloader == "grub-install": - self.pacstrap('grub') + self.pacstrap('grub') # no need? + + if real_device := self.detect_encryption(root_partition): + _file = "/etc/default/grub" + root_uuid = SysCommand(f"blkid -s UUID -o value {real_device.path}").decode().rstrip() + add_to_CMDLINE_LINUX = f"sed -i 's/GRUB_CMDLINE_LINUX=\"\"/GRUB_CMDLINE_LINUX=\"cryptdevice=UUID={root_uuid}:cryptlvm\"/'" + enable_CRYPTODISK = "sed -i 's/#GRUB_ENABLE_CRYPTODISK=y/GRUB_ENABLE_CRYPTODISK=y/'" + + SysCommand(f"/usr/bin/arch-chroot {self.target} {add_to_CMDLINE_LINUX} {_file}") + SysCommand(f"/usr/bin/arch-chroot {self.target} {enable_CRYPTODISK} {_file}") if has_uefi(): self.pacstrap('efibootmgr') @@ -509,10 +518,7 @@ class Installer: self.helper_flags['bootloader'] = True return True else: - root_device = subprocess.check_output(f'basename "$(readlink -f /sys/class/block/{root_partition.path.replace("/dev/", "")}/..)"', shell=True).decode().strip() - if root_device == "block": - root_device = f"{root_partition.path}" - o = b''.join(SysCommand(f'/usr/bin/arch-chroot {self.target} grub-install --target=i386-pc /dev/{root_device}')) + o = b''.join(SysCommand(f'/usr/bin/arch-chroot {self.target} grub-install --target=i386-pc --recheck {_device.path}')) SysCommand('/usr/bin/arch-chroot /mnt grub-mkconfig -o /boot/grub/grub.cfg') self.helper_flags['bootloader'] = True else: -- cgit v1.2.3-70-g09d2 From 3d4f58a04e06ef4bdd023effc52d4cb33b49080c Mon Sep 17 00:00:00 2001 From: monosans Date: Fri, 16 Jul 2021 10:42:29 +0300 Subject: Replace for loops with comprehensions --- archinstall/lib/general.py | 5 +---- archinstall/lib/hardware.py | 5 ++++- archinstall/lib/mirrors.py | 4 +--- archinstall/lib/packages.py | 15 ++++++--------- docs/conf.py | 4 +--- 5 files changed, 13 insertions(+), 20 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/general.py b/archinstall/lib/general.py index b9dc66ab..5200033a 100644 --- a/archinstall/lib/general.py +++ b/archinstall/lib/general.py @@ -98,10 +98,7 @@ class JsonEncoder: elif isinstance(obj, (datetime, date)): return obj.isoformat() elif isinstance(obj, (list, set, tuple)): - r = [] - for item in obj: - r.append(json.loads(json.dumps(item, cls=JSON))) - return r + return [json.loads(json.dumps(item, cls=JSON)) for item in obj] else: return obj diff --git a/archinstall/lib/hardware.py b/archinstall/lib/hardware.py index a63155f5..b1ac516d 100644 --- a/archinstall/lib/hardware.py +++ b/archinstall/lib/hardware.py @@ -131,7 +131,10 @@ def product_name() -> Optional[str]: def mem_info(): # This implementation is from https://stackoverflow.com/a/28161352 - return dict((i.split()[0].rstrip(':'), int(i.split()[1])) for i in open('/proc/meminfo').readlines()) + return { + i.split()[0].rstrip(':'): int(i.split()[1]) + for i in open('/proc/meminfo').readlines() + } def mem_available() -> Optional[str]: diff --git a/archinstall/lib/mirrors.py b/archinstall/lib/mirrors.py index 95fb5ac6..1b62a61b 100644 --- a/archinstall/lib/mirrors.py +++ b/archinstall/lib/mirrors.py @@ -59,9 +59,7 @@ def filter_mirrors_by_region(regions, destination='/etc/pacman.d/mirrorlist', so :param regions: A series of country codes separated by `,`. For instance `SE,US` for sweden and United States. :type regions: str """ - region_list = [] - for region in regions.split(','): - region_list.append(f'country={region}') + region_list = [f'country={region}' for region in regions.split(',')] response = urllib.request.urlopen(urllib.request.Request(f"https://archlinux.org/mirrorlist/?{'&'.join(region_list)}&protocol=https&protocol=http&ip_version=4&ip_version=6&use_mirror_status=on'", headers={'User-Agent': 'ArchInstall'})) new_list = response.read().replace(b"#Server", b"Server") diff --git a/archinstall/lib/packages.py b/archinstall/lib/packages.py index 0ea195d2..0178d257 100644 --- a/archinstall/lib/packages.py +++ b/archinstall/lib/packages.py @@ -46,10 +46,7 @@ def find_packages(*names): The function itself is rather slow, so consider not sending to many packages to the search query. """ - result = {} - for package in names: - result[package] = find_package(package) - return result + return {package: find_package(package) for package in names} def validate_package_list(packages: list): @@ -57,11 +54,11 @@ def validate_package_list(packages: list): Validates a list of given packages. Raises `RequirementError` if one or more packages are not found. """ - invalid_packages = [] - for package in packages: - if not find_package(package)['results'] and not find_group(package): - invalid_packages.append(package) - + invalid_packages = [ + package + for package in packages + if not find_package(package)['results'] and not find_group(package) + ] if invalid_packages: raise RequirementError(f"Invalid package names: {invalid_packages}") diff --git a/docs/conf.py b/docs/conf.py index add1c5e7..33aeeae8 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -7,9 +7,7 @@ sys.path.insert(0, os.path.abspath('..')) def process_docstring(app, what, name, obj, options, lines): spaces_pat = re.compile(r"( {8})") - ll = [] - for line in lines: - ll.append(spaces_pat.sub(" ", line)) + ll = [spaces_pat.sub(" ", line) for line in lines] lines[:] = ll -- cgit v1.2.3-70-g09d2 From d55b1786c5797c191cfbaad79c33b1079d1d53c5 Mon Sep 17 00:00:00 2001 From: Yash Tripathi Date: Sun, 18 Jul 2021 01:28:41 +0530 Subject: created load_config() to load configuration --- archinstall/lib/user_interaction.py | 3 +- examples/guided.py | 70 +++++++++++++++---------------------- 2 files changed, 31 insertions(+), 42 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/user_interaction.py b/archinstall/lib/user_interaction.py index 2c5810ae..44dabbe6 100644 --- a/archinstall/lib/user_interaction.py +++ b/archinstall/lib/user_interaction.py @@ -710,7 +710,8 @@ def select_driver(options=AVAILABLE_GFX_DRIVERS): if has_nvidia_graphics(): print('For the best compatibility with your Nvidia hardware, you may want to use the Nvidia proprietary driver.') - arguments['gfx_driver'] = generic_select(drivers, input_text="Select your graphics card driver: ") + if not arguments.get('gfx_driver', None): + arguments['gfx_driver'] = generic_select(drivers, input_text="Select a graphics driver or leave blank to install all open-source drivers: ") if arguments.get('gfx_driver', None) is None: arguments['gfx_driver'] = "All open-source (default)" diff --git a/examples/guided.py b/examples/guided.py index aebebcfa..0ec9834f 100644 --- a/examples/guided.py +++ b/examples/guided.py @@ -26,6 +26,29 @@ archinstall.log(f"Graphics devices detected: {archinstall.graphics_devices().key # For support reasons, we'll log the disk layout pre installation to match against post-installation layout archinstall.log(f"Disk states before installing: {archinstall.disk_layouts()}", level=logging.DEBUG) +def load_config(): + if archinstall.arguments.get('harddrive', None) is not None: + archinstall.arguments['harddrive'] = archinstall.BlockDevice(path=archinstall.arguments['harddrive']['path']) + # Temporarily disabling keep_partitions if config file is loaded + archinstall.arguments['harddrive'].keep_partitions = False + # Temporary workaround to make Desktop Environments work + if archinstall.arguments.get('profile', None) is not None: + if type(archinstall.arguments.get('profile', None)) is dict: + archinstall.arguments['profile'] = archinstall.Profile(None, archinstall.arguments.get('profile', None)['path']) + else: + archinstall.arguments['profile'] = archinstall.Profile(None, archinstall.arguments.get('profile', None)) + if archinstall.arguments.get('mirror-region', None) is not None: + if type(archinstall.arguments.get('mirror-region', None)) is dict: + archinstall.arguments['mirror-region'] = archinstall.arguments.get('mirror-region', None) + else: + selected_region = archinstall.arguments.get('mirror-region', None) + archinstall.arguments['mirror-region'] = {selected_region: archinstall.list_mirrors()[selected_region]} + if archinstall.arguments.get('sys-language', None) is not None: + archinstall.arguments['sys-language'] = archinstall.arguments.get('sys-language', 'en_US') + if archinstall.arguments.get('sys-encoding', None) is not None: + archinstall.arguments['sys-encoding'] = archinstall.arguments.get('sys-encoding', 'utf-8') + if archinstall.arguments.get('gfx_driver', None) is not None: + archinstall.storage['gfx_driver_packages'] = AVAILABLE_GFX_DRIVERS.get(archinstall.arguments.get('gfx_driver', None), None) def ask_user_questions(): """ @@ -54,9 +77,6 @@ def ask_user_questions(): break except archinstall.RequirementError as e: archinstall.log(e, fg="red") - else: - selected_region = archinstall.arguments['mirror-region'] - archinstall.arguments['mirror-region'] = {selected_region: archinstall.list_mirrors()[selected_region]} if not archinstall.arguments.get('sys-language', None) and archinstall.arguments.get('advanced', False): archinstall.arguments['sys-language'] = input("Enter a valid locale (language) for your OS, (Default: en_US): ").strip() @@ -69,9 +89,7 @@ def ask_user_questions(): archinstall.arguments['sys-encoding'] = 'utf-8' # Ask which harddrive/block-device we will install to - if archinstall.arguments.get('harddrive', None): - archinstall.arguments['harddrive'] = archinstall.BlockDevice(archinstall.arguments['harddrive']) - else: + if not archinstall.arguments.get('harddrive', None): archinstall.arguments['harddrive'] = archinstall.select_disk(archinstall.all_disks()) if archinstall.arguments['harddrive'] is None: archinstall.arguments['target-mount'] = archinstall.storage.get('MOUNT_POINT', '/mnt') @@ -188,20 +206,15 @@ def ask_user_questions(): 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'] = {} - archinstall.arguments['superusers'] = {} - if not archinstall.arguments.get('!root-password', None): + if not archinstall.arguments.get('!root-password', None) and not archinstall.arguments.get('superusers', 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('Enter a username to create a additional user (leave blank to skip & continue): ') - archinstall.arguments['users'] = users - archinstall.arguments['superusers'] = {**archinstall.arguments['superusers'], **superusers} + 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} # Ask for archinstall-specific profiles (such as desktop environments etc) if not archinstall.arguments.get('profile', None): archinstall.arguments['profile'] = archinstall.select_profile() - else: - archinstall.arguments['profile'] = Profile(installer=None, path=archinstall.arguments['profile']) # Check the potentially selected profiles preparations to get early checks if some additional questions are needed. if archinstall.arguments['profile'] and archinstall.arguments['profile'].has_prep_function(): @@ -437,33 +450,8 @@ if not check_mirror_reachable(): archinstall.log(f"Arch Linux mirrors are not reachable. Please check your internet connection and the log file '{log_file}'.", level=logging.INFO, fg="red") exit(1) +load_config() if not archinstall.arguments.get('silent'): ask_user_questions() -else: - # Workarounds if config is loaded from a file - # The harddrive section should be moved to perform_installation_steps, where it's actually being performed - # Blockdevice object should be created in perform_installation_steps - # This needs to be done until then - archinstall.arguments['harddrive'] = archinstall.BlockDevice(path=archinstall.arguments['harddrive']['path']) - # Temporarily disabling keep_partitions if config file is loaded - archinstall.arguments['harddrive'].keep_partitions = False - # Temporary workaround to make Desktop Environments work - if archinstall.arguments.get('profile', None) is not None: - if type(archinstall.arguments.get('profile', None)) is dict: - archinstall.arguments['profile'] = archinstall.Profile(None, archinstall.arguments.get('profile', None)['path']) - else: - archinstall.arguments['profile'] = archinstall.Profile(None, archinstall.arguments.get('profile', None)) - else: - archinstall.arguments['profile'] = None - if archinstall.arguments.get('mirror-region', None) is not None: - if type(archinstall.arguments.get('mirror-region', None)) is dict: - archinstall.arguments['mirror-region'] = archinstall.arguments.get('mirror-region', None) - else: - selected_region = archinstall.arguments.get('mirror-region', None) - archinstall.arguments['mirror-region'] = {selected_region: archinstall.list_mirrors()[selected_region]} - archinstall.arguments['sys-language'] = archinstall.arguments.get('sys-language', 'en_US') - archinstall.arguments['sys-encoding'] = archinstall.arguments.get('sys-encoding', 'utf-8') - if archinstall.arguments.get('gfx_driver', None) is not None: - archinstall.storage['gfx_driver_packages'] = AVAILABLE_GFX_DRIVERS.get(archinstall.arguments.get('gfx_driver', None), None) perform_installation_steps() -- cgit v1.2.3-70-g09d2 From b1998ddebf5bb73ae944c021e910c4fcb08878ec Mon Sep 17 00:00:00 2001 From: Yash Tripathi Date: Sun, 18 Jul 2021 16:37:02 +0530 Subject: fix for #602, running mklabel before formatting --- archinstall/lib/disk.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'archinstall') diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index de39bafd..be0e6518 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -519,6 +519,8 @@ class Filesystem: self.blockdevice.partition[1].allow_formatting = True else: # we don't need a seprate boot partition it would be a waste of space + if not self.parted_mklabel(self.blockdevice.device, "msdos"): + raise KeyError(f"Could not create a MSDOS label on {self}") self.add_partition('primary', start='1MB', end='100%') self.blockdevice.partition[0].filesystem = root_filesystem_type log(f"Set the root partition {self.blockdevice.partition[0]} to use filesystem {root_filesystem_type}.", level=logging.DEBUG) @@ -539,11 +541,9 @@ class Filesystem: if partitioning: start_wait = time.time() - while previous_partitions == self.blockdevice.partitions: - time.sleep(0.025) # Let the new partition come up in the kernel - if time.time() - start_wait > 10: - raise DiskError(f"New partition never showed up after adding new partition on {self} (timeout 10 seconds).") - + time.sleep(0.025) # Let the new partition come up in the kernel + if time.time() - start_wait > 20: + raise DiskError(f"New partition never showed up after adding new partition on {self} (timeout 10 seconds).") return True def set_name(self, partition: int, name: str): -- cgit v1.2.3-70-g09d2 From b60e8dfd10d4d4c2b2918bad8df2b8354a7f4996 Mon Sep 17 00:00:00 2001 From: Yash Tripathi Date: Sun, 18 Jul 2021 21:45:24 +0530 Subject: changed dry_run to dry-run --- archinstall/__init__.py | 2 +- examples/guided.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'archinstall') diff --git a/archinstall/__init__.py b/archinstall/__init__.py index 84595528..2eec1ce6 100644 --- a/archinstall/__init__.py +++ b/archinstall/__init__.py @@ -64,7 +64,7 @@ def initialize_arguments(): config[key] = val config["script"] = args.script if args.dry_run is not None: - config["dry_run"] = args.dry_run + config["dry-run"] = args.dry_run return config diff --git a/examples/guided.py b/examples/guided.py index 6054387a..6cb80190 100644 --- a/examples/guided.py +++ b/examples/guided.py @@ -280,7 +280,7 @@ def perform_installation_steps(): config_file.write(user_configuration) print() - if archinstall.arguments.get('dry_run'): + if archinstall.arguments.get('dry-run'): exit(0) if not archinstall.arguments.get('silent'): -- cgit v1.2.3-70-g09d2