From e717a72a10907a02bc485b763f195cddcc68bbe0 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Thu, 8 Apr 2021 22:47:13 +0200 Subject: Starting implementing #124. The installer will be detatched from block devices and partitions. Instead it will rely on a given destination to pacstrap to. From there, it should be able to do reverse-lookups on the target and base it's information and choises from there. This removes any form of partitioning logic, hardware logic and other things from the initialization of the installer. These things should be explicitly called from the installers functions instead. Such as .set_hostname() instead of passing it as a initiation variable. --- archinstall/lib/installer.py | 6 ++---- examples/minimal.py | 15 +++++++++------ 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index b7fe5e9d..c6734a1a 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -34,10 +34,8 @@ class Installer(): :type hostname: str, optional """ - def __init__(self, partition, boot_partition, *, base_packages='base base-devel linux linux-firmware efibootmgr', profile=None, mountpoint='/mnt', hostname='ArchInstalled', logdir=None, logfile=None): - self.profile = profile - self.hostname = hostname - self.mountpoint = mountpoint + def __init__(self, target, *, base_packages='base base-devel linux linux-firmware efibootmgr', logdir=None, logfile=None): + self.target = target self.init_time = time.strftime('%Y-%m-%d_%H-%M-%S') self.milliseconds = int(str(time.time()).split('.')[1]) diff --git a/examples/minimal.py b/examples/minimal.py index 367574b5..afd64a2e 100644 --- a/examples/minimal.py +++ b/examples/minimal.py @@ -12,12 +12,13 @@ if archinstall.arguments.get('help', None): archinstall.arguments['harddrive'] = archinstall.select_disk(archinstall.all_disks()) archinstall.arguments['harddrive'].keep_partitions = False -def install_on(root, boot): - # We kick off the installer by telling it where the root and boot lives - with archinstall.Installer(root, boot_partition=boot, hostname='minimal-arch') as installation: +def install_on(mountpoint): + # We kick off the installer by telling it where the + with archinstall.Installer(mountpoint) as installation: # Strap in the base system, add a boot loader and configure # some other minor details as specified by this profile and user. if installation.minimal_installation(): + installation.set_hostname('minimal-arch') installation.add_bootloader() # Optionally enable networking: @@ -57,8 +58,10 @@ with archinstall.Filesystem(archinstall.arguments['harddrive'], archinstall.GPT) with archinstall.luks2(root, 'luksloop', archinstall.arguments.get('!encryption-password', None)) as unlocked_root: unlocked_root.format(root.filesystem) - - install_on(unlocked_root) + unlocked_root.mount('/mnt') else: root.format(root.filesystem) - install_on(root, boot) \ No newline at end of file + root.mount('/mnt') + + boot.mount('/mnt/boot') + install_on('/mnt') \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 08cf788eaad2ec9ecdfd2c1da1da70bfd4180984 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Thu, 8 Apr 2021 22:58:45 +0200 Subject: Reworked the mkinitcpio configuration to be more robust according to the logic behind #91 and in prep for #145. Also in prep for #124 the lookup of partitions have been prepared here. We now need a reverse-lookup function. --- archinstall/lib/installer.py | 67 ++++++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 37 deletions(-) diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index c6734a1a..11f75f99 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -34,28 +34,21 @@ class Installer(): :type hostname: str, optional """ - def __init__(self, target, *, base_packages='base base-devel linux linux-firmware efibootmgr', logdir=None, logfile=None): + def __init__(self, target, *, base_packages='base base-devel linux linux-firmware efibootmgr'): self.target = target self.init_time = time.strftime('%Y-%m-%d_%H-%M-%S') self.milliseconds = int(str(time.time()).split('.')[1]) - if logdir: - storage['LOG_PATH'] = logdir - if logfile: - storage['LOG_FILE'] = logfile - self.helper_flags = { - 'bootloader' : False, 'base' : False, - 'user' : False # Root counts as a user, if additional users are skipped. + 'bootloader' : False } self.base_packages = base_packages.split(' ') if type(base_packages) is str else base_packages self.post_base_install = [] - storage['session'] = self - self.partition = partition - self.boot_partition = boot_partition + storage['session'] = self + self.partitions = get_partitions_in_use(self.target) def log(self, *args, level=LOG_LEVELS.Debug, **kwargs): """ @@ -65,9 +58,6 @@ class Installer(): log(*args, level=level, **kwargs) def __enter__(self, *args, **kwargs): - self.partition.mount(self.mountpoint) - os.makedirs(f'{self.mountpoint}/boot', exist_ok=True) - self.boot_partition.mount(f'{self.mountpoint}/boot') return self def __exit__(self, *args, **kwargs): @@ -272,18 +262,25 @@ class Installer(): ## (encrypted partitions default to btrfs for now, so we need btrfs-progs) ## TODO: Perhaps this should be living in the function which dictates ## the partitioning. Leaving here for now. - if self.partition.filesystem == 'btrfs': - #if self.partition.encrypted: - self.base_packages.append('btrfs-progs') - if self.partition.filesystem == 'xfs': - self.base_packages.append('xfsprogs') - if self.partition.filesystem == 'f2fs': - self.base_packages.append('f2fs-tools') + MODULES = [] + BINARIES = [] + FILES = [] + HOOKS = ["base", "udev", "autodetect", "keyboard", "keymap", "modconf", "block", "filesystems", "fsck"] + + for partition in self.partitions: + if partition.filesystem == 'btrfs': + #if partition.encrypted: + self.base_packages.append('btrfs-progs') + if partition.filesystem == 'xfs': + self.base_packages.append('xfsprogs') + if partition.filesystem == 'f2fs': + self.base_packages.append('f2fs-tools') + self.pacstrap(self.base_packages) self.helper_flags['base-strapped'] = True #self.genfstab() - with open(f"{self.mountpoint}/etc/fstab", "a") as fstab: + with open(f"{self.target}/etc/fstab", "a") as fstab: fstab.write( "\ntmpfs /tmp tmpfs defaults,noatime,mode=1777 0 0\n" ) # Redundant \n at the start? who knows? @@ -296,25 +293,21 @@ class Installer(): self.set_locale('en_US') # TODO: Use python functions for this - sys_command(f'/usr/bin/arch-chroot {self.mountpoint} chmod 700 /root') + sys_command(f'/usr/bin/arch-chroot {self.target} 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: - mkinit.write('MODULES=(btrfs)\n') - mkinit.write('BINARIES=(/usr/bin/btrfs)\n') - mkinit.write('FILES=()\n') - mkinit.write('HOOKS=(base udev autodetect keyboard keymap modconf block encrypt filesystems fsck)\n') - sys_command(f'/usr/bin/arch-chroot {self.mountpoint} mkinitcpio -p linux') + MODULES.append('btrfs') + BINARIES.append('/usr/bin/btrfs') 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 keyboard keymap modconf block encrypt filesystems fsck)\n') - sys_command(f'/usr/bin/arch-chroot {self.mountpoint} mkinitcpio -p linux') + HOOKS.patch('encrypt', before='filesystems') + + with open(f'{self.target}/etc/mkinitcpio.conf', 'w') as mkinit: + mkinit.write(f"MODULES=({' '.join(MODULES)})\n") + mkinit.write(f"BINARIES=({' '.join(BINARIES)})\n") + mkinit.write(f"FILES=({' '.join(FILES)})\n") + mkinit.write(f"HOOKS=({' '.join(HOOKS)})\n") + sys_command(f'/usr/bin/arch-chroot {self.target} mkinitcpio -p linux') self.helper_flags['base'] = True -- cgit v1.2.3-70-g09d2 From 05e848ce626c768bc6bfbcdbfa65083abb035b87 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Fri, 9 Apr 2021 11:45:06 +0200 Subject: Made sure the mount target path exists before mounting. --- archinstall/lib/disk.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index dbb69662..7e02c539 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -366,14 +366,16 @@ class Partition(): if not fs: if not self.filesystem: raise DiskError(f'Need to format (or define) the filesystem on {self} before mounting.') fs = self.filesystem - ## libc has some issues with loop devices, defaulting back to sys calls - # ret = libc.mount(self.path.encode(), target.encode(), fs.encode(), 0, options.encode()) - # if ret < 0: - # errno = ctypes.get_errno() - # raise OSError(errno, f"Error mounting {self.path} ({fs}) on {target} with options '{options}': {os.strerror(errno)}") - if sys_command(f'/usr/bin/mount {self.path} {target}').exit_code == 0: - self.mountpoint = target - return True + + pathlib.Path(self.path).mkdir(parents=True, exist_ok=True) + + try: + sys_command(f'/usr/bin/mount {self.path} {target}') + except SysCallError as err: + raise err + + self.mountpoint = target + return True def unmount(self): try: -- cgit v1.2.3-70-g09d2 From 1395f0888c52f01a231aec6c437d570895a03210 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Fri, 9 Apr 2021 11:45:45 +0200 Subject: Wrong variable. --- archinstall/lib/disk.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index 7e02c539..f0fe7181 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -367,7 +367,7 @@ class Partition(): if not self.filesystem: raise DiskError(f'Need to format (or define) the filesystem on {self} before mounting.') fs = self.filesystem - pathlib.Path(self.path).mkdir(parents=True, exist_ok=True) + pathlib.Path(target).mkdir(parents=True, exist_ok=True) try: sys_command(f'/usr/bin/mount {self.path} {target}') -- cgit v1.2.3-70-g09d2 From eb0ae8b1c35e421f88b7eabcc445d1069969ba76 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Fri, 9 Apr 2021 11:53:54 +0200 Subject: Added disk helper function get_partitions_in_use(). Which returns which partions are being used at a given mount location, including children. --- archinstall/lib/disk.py | 18 ++++++++++++++++++ archinstall/lib/installer.py | 1 + 2 files changed, 19 insertions(+) diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index f0fe7181..af40e36f 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -574,6 +574,24 @@ def get_mount_info(path): return output['filesystems'][0] +def get_partitions_in_use(mountpoint): + try: + output = b''.join(sys_command(f'/usr/bin/findmnt --json -R {path}')) + except SysCallError: + return {} + + mounts = [] + + output = output.decode('UTF-8') + output = json.loads(output) + for target in output.get('filesystems', []): + mounts.append(Partition(target['source'], filesystem=target.get('fstype', None), mountpoint=target['target'])) + + for child in target.get('children', []): + mounts.append(Partition(child['source'], filesystem=child.get('fstype', None), mountpoint=child['target'])) + + return mounts + def get_filesystem_type(path): try: handle = sys_command(f"blkid -o value -s TYPE {path}") diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 11f75f99..d17ee77c 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -49,6 +49,7 @@ class Installer(): storage['session'] = self self.partitions = get_partitions_in_use(self.target) + print(self.partitions) def log(self, *args, level=LOG_LEVELS.Debug, **kwargs): """ -- cgit v1.2.3-70-g09d2 From eb7ed1126bcfece5ec2fba40b24227e02082bea0 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Fri, 9 Apr 2021 11:54:48 +0200 Subject: Wrong variable name --- archinstall/lib/disk.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index af40e36f..f8bdc040 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -576,7 +576,7 @@ def get_mount_info(path): def get_partitions_in_use(mountpoint): try: - output = b''.join(sys_command(f'/usr/bin/findmnt --json -R {path}')) + output = b''.join(sys_command(f'/usr/bin/findmnt --json -R {mountpoint}')) except SysCallError: return {} -- cgit v1.2.3-70-g09d2 From db7b3c8cca10068f3c2186b3c1d6eb316741f3a0 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Fri, 9 Apr 2021 11:56:35 +0200 Subject: Attempting default value None for block device to partition. --- archinstall/lib/disk.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index f8bdc040..f6dc16eb 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -585,10 +585,10 @@ def get_partitions_in_use(mountpoint): output = output.decode('UTF-8') output = json.loads(output) for target in output.get('filesystems', []): - mounts.append(Partition(target['source'], filesystem=target.get('fstype', None), mountpoint=target['target'])) + mounts.append(Partition(target['source'], None, filesystem=target.get('fstype', None), mountpoint=target['target'])) for child in target.get('children', []): - mounts.append(Partition(child['source'], filesystem=child.get('fstype', None), mountpoint=child['target'])) + mounts.append(Partition(child['source'], None, filesystem=child.get('fstype', None), mountpoint=child['target'])) return mounts -- cgit v1.2.3-70-g09d2 From 7f6220528175a15606c329638ffcd961ad771df6 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Fri, 9 Apr 2021 11:58:12 +0200 Subject: Reworked Installation() to have self.target instead of self.mountpoint, to be more consistent and remove the hits that it has anything to do with partitions/hardware. --- archinstall/lib/installer.py | 66 ++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index d17ee77c..173f4666 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -122,7 +122,7 @@ class Installer(): self.log(f'Installing packages: {packages}', level=LOG_LEVELS.Info) if (sync_mirrors := sys_command('/usr/bin/pacman -Syy')).exit_code == 0: - if (pacstrap := sys_command(f'/usr/bin/pacstrap {self.mountpoint} {" ".join(packages)}', **kwargs)).exit_code == 0: + if (pacstrap := sys_command(f'/usr/bin/pacstrap {self.target} {" ".join(packages)}', **kwargs)).exit_code == 0: return True else: self.log(f'Could not strap in packages: {pacstrap.exit_code}', level=LOG_LEVELS.Info) @@ -130,42 +130,42 @@ class Installer(): self.log(f'Could not sync mirrors: {sync_mirrors.exit_code}', level=LOG_LEVELS.Info) def set_mirrors(self, mirrors): - return use_mirrors(mirrors, destination=f'{self.mountpoint}/etc/pacman.d/mirrorlist') + return use_mirrors(mirrors, destination=f'{self.target}/etc/pacman.d/mirrorlist') def genfstab(self, flags='-pU'): - self.log(f"Updating {self.mountpoint}/etc/fstab", level=LOG_LEVELS.Info) + self.log(f"Updating {self.target}/etc/fstab", level=LOG_LEVELS.Info) - fstab = sys_command(f'/usr/bin/genfstab {flags} {self.mountpoint}').trace_log - with open(f"{self.mountpoint}/etc/fstab", 'ab') as fstab_fh: + fstab = sys_command(f'/usr/bin/genfstab {flags} {self.target}').trace_log + with open(f"{self.target}/etc/fstab", 'ab') as fstab_fh: fstab_fh.write(fstab) - if not os.path.isfile(f'{self.mountpoint}/etc/fstab'): + if not os.path.isfile(f'{self.target}/etc/fstab'): raise RequirementError(f'Could not generate fstab, strapping in packages most likely failed (disk out of space?)\n{fstab}') return True def set_hostname(self, hostname=None, *args, **kwargs): if not hostname: hostname = self.hostname - with open(f'{self.mountpoint}/etc/hostname', 'w') as fh: + with open(f'{self.target}/etc/hostname', 'w') as fh: fh.write(self.hostname + '\n') def set_locale(self, locale, encoding='UTF-8', *args, **kwargs): if not len(locale): return True - with open(f'{self.mountpoint}/etc/locale.gen', 'a') as fh: + with open(f'{self.target}/etc/locale.gen', 'a') as fh: fh.write(f'{locale}.{encoding} {encoding}\n') - with open(f'{self.mountpoint}/etc/locale.conf', 'w') as fh: + with open(f'{self.target}/etc/locale.conf', 'w') as fh: fh.write(f'LANG={locale}.{encoding}\n') - return True if sys_command(f'/usr/bin/arch-chroot {self.mountpoint} locale-gen').exit_code == 0 else False + return True if sys_command(f'/usr/bin/arch-chroot {self.target} locale-gen').exit_code == 0 else False def set_timezone(self, zone, *args, **kwargs): if not zone: return True if not len(zone): return True # Redundant 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') + (pathlib.Path(self.target)/"etc"/"localtime").unlink(missing_ok=True) + sys_command(f'/usr/bin/arch-chroot {self.target} ln -s /usr/share/zoneinfo/{zone} /etc/localtime') return True else: self.log( @@ -185,7 +185,7 @@ class Installer(): return self.arch_chroot(f'systemctl enable {service}').exit_code == 0 def run_command(self, cmd, *args, **kwargs): - return sys_command(f'/usr/bin/arch-chroot {self.mountpoint} {cmd}') + return sys_command(f'/usr/bin/arch-chroot {self.target} {cmd}') def arch_chroot(self, cmd, *args, **kwargs): return self.run_command(cmd) @@ -205,15 +205,15 @@ class Installer(): conf = Networkd(Match={"Name": nic}, Network=network) - with open(f"{self.mountpoint}/etc/systemd/network/10-{nic}.network", "a") as netconf: + with open(f"{self.target}/etc/systemd/network/10-{nic}.network", "a") as netconf: netconf.write(str(conf)) def copy_ISO_network_config(self, enable_services=False): # Copy (if any) iwd password and config files if os.path.isdir('/var/lib/iwd/'): if (psk_files := glob.glob('/var/lib/iwd/*.psk')): - if not os.path.isdir(f"{self.mountpoint}/var/lib/iwd"): - os.makedirs(f"{self.mountpoint}/var/lib/iwd") + if not os.path.isdir(f"{self.target}/var/lib/iwd"): + os.makedirs(f"{self.target}/var/lib/iwd") if enable_services: # If we haven't installed the base yet (function called pre-maturely) @@ -233,15 +233,15 @@ class Installer(): self.enable_service('iwd') for psk in psk_files: - shutil.copy2(psk, f"{self.mountpoint}/var/lib/iwd/{os.path.basename(psk)}") + shutil.copy2(psk, f"{self.target}/var/lib/iwd/{os.path.basename(psk)}") # Copy (if any) systemd-networkd config files if (netconfigurations := glob.glob('/etc/systemd/network/*')): - if not os.path.isdir(f"{self.mountpoint}/etc/systemd/network/"): - os.makedirs(f"{self.mountpoint}/etc/systemd/network/") + if not os.path.isdir(f"{self.target}/etc/systemd/network/"): + os.makedirs(f"{self.target}/etc/systemd/network/") for netconf_file in netconfigurations: - shutil.copy2(netconf_file, f"{self.mountpoint}/etc/systemd/network/{os.path.basename(netconf_file)}") + shutil.copy2(netconf_file, f"{self.target}/etc/systemd/network/{os.path.basename(netconf_file)}") if enable_services: # If we haven't installed the base yet (function called pre-maturely) @@ -287,8 +287,8 @@ class Installer(): ) # Redundant \n at the start? who knows? ## TODO: Support locale and timezone - #os.remove(f'{self.mountpoint}/etc/localtime') - #sys_command(f'/usr/bin/arch-chroot {self.mountpoint} ln -s /usr/share/zoneinfo/{localtime} /etc/localtime') + #os.remove(f'{self.target}/etc/localtime') + #sys_command(f'/usr/bin/arch-chroot {self.target} ln -s /usr/share/zoneinfo/{localtime} /etc/localtime') #sys_command('/usr/bin/arch-chroot /mnt hwclock --hctosys --localtime') self.set_hostname() self.set_locale('en_US') @@ -328,11 +328,11 @@ class Installer(): # And in which case we should do some clean up. # Install the boot loader - sys_command(f'/usr/bin/arch-chroot {self.mountpoint} bootctl --no-variables --path=/boot install') + sys_command(f'/usr/bin/arch-chroot {self.target} 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: + if os.path.isfile(f'{self.target}/boot/loader/loader.conf'): + with open(f'{self.target}/boot/loader/loader.conf', 'r') as loader: loader_data = loader.read().split('\n') else: loader_data = [ @@ -340,7 +340,7 @@ class Installer(): f"timeout 5" ] - with open(f'{self.mountpoint}/boot/loader/loader.conf', 'w') as loader: + with open(f'{self.target}/boot/loader/loader.conf', 'w') as loader: for line in loader_data: if line[:8] == 'default ': loader.write(f'default {self.init_time}\n') @@ -352,7 +352,7 @@ class Installer(): #UUID = sys_command('blkid -s PARTUUID -o value {drive}{partition_2}'.format(**args)).decode('UTF-8').strip() # Setup the loader entry - with open(f'{self.mountpoint}/boot/loader/entries/{self.init_time}.conf', 'w') as entry: + with open(f'{self.target}/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') @@ -383,7 +383,7 @@ class Installer(): self.helper_flags['bootloader'] = bootloader return True - 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.") + raise RequirementError(f"Could not identify the UUID of {self.partition}, there for {self.target}/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}") @@ -408,19 +408,19 @@ class Installer(): def enable_sudo(self, entity :str, group=False): self.log(f'Enabling sudo permissions for {entity}.', level=LOG_LEVELS.Info) - with open(f'{self.mountpoint}/etc/sudoers', 'a') as sudoers: + with open(f'{self.target}/etc/sudoers', 'a') as sudoers: sudoers.write(f'{"%" if group else ""}{entity} ALL=(ALL) ALL\n') return True def user_create(self, user :str, password=None, groups=[], sudo=False): self.log(f'Creating user {user}', level=LOG_LEVELS.Info) - o = b''.join(sys_command(f'/usr/bin/arch-chroot {self.mountpoint} useradd -m -G wheel {user}')) + o = b''.join(sys_command(f'/usr/bin/arch-chroot {self.target} useradd -m -G wheel {user}')) if password: self.user_set_pw(user, password) if groups: for group in groups: - o = b''.join(sys_command(f'/usr/bin/arch-chroot {self.mountpoint} gpasswd -a {user} {group}')) + o = b''.join(sys_command(f'/usr/bin/arch-chroot {self.target} gpasswd -a {user} {group}')) if sudo and self.enable_sudo(user): self.helper_flags['user'] = True @@ -432,12 +432,12 @@ class Installer(): # This means the root account isn't locked/disabled with * in /etc/passwd self.helper_flags['user'] = True - o = b''.join(sys_command(f"/usr/bin/arch-chroot {self.mountpoint} sh -c \"echo '{user}:{password}' | chpasswd\"")) + o = b''.join(sys_command(f"/usr/bin/arch-chroot {self.target} sh -c \"echo '{user}:{password}' | chpasswd\"")) pass def set_keyboard_language(self, language): if len(language.strip()): - with open(f'{self.mountpoint}/etc/vconsole.conf', 'w') as vconsole: + with open(f'{self.target}/etc/vconsole.conf', 'w') as vconsole: vconsole.write(f'KEYMAP={language}\n') vconsole.write(f'FONT=lat9w-16\n') return True -- cgit v1.2.3-70-g09d2 From 276414079bff0249d1d788eb64534bbbe66ad8a4 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Fri, 9 Apr 2021 12:00:51 +0200 Subject: Reworked Installation() to have self.target instead of self.mountpoint, to be more consistent and remove the hits that it has anything to do with partitions/hardware. --- archinstall/lib/installer.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 173f4666..593a812d 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -101,18 +101,18 @@ class Installer(): if (filename := storage.get('LOG_FILE', None)): absolute_logfile = os.path.join(storage.get('LOG_PATH', './'), filename) - if not os.path.isdir(f"{self.mountpoint}/{os.path.dirname(absolute_logfile)}"): - os.makedirs(f"{self.mountpoint}/{os.path.dirname(absolute_logfile)}") + if not os.path.isdir(f"{self.target}/{os.path.dirname(absolute_logfile)}"): + os.makedirs(f"{self.target}/{os.path.dirname(absolute_logfile)}") - shutil.copy2(absolute_logfile, f"{self.mountpoint}/{absolute_logfile}") + shutil.copy2(absolute_logfile, f"{self.target}/{absolute_logfile}") return True def mount(self, partition, mountpoint, create_mountpoint=True): - if create_mountpoint and not os.path.isdir(f'{self.mountpoint}{mountpoint}'): - os.makedirs(f'{self.mountpoint}{mountpoint}') + if create_mountpoint and not os.path.isdir(f'{self.target}{mountpoint}'): + os.makedirs(f'{self.target}{mountpoint}') - partition.mount(f'{self.mountpoint}{mountpoint}') + partition.mount(f'{self.target}{mountpoint}') def post_install_check(self, *args, **kwargs): return [step for step, flag in self.helper_flags.items() if flag is False] -- cgit v1.2.3-70-g09d2 From 59e3408de838206bad24fa0d8ca34b47f71e17aa Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Fri, 9 Apr 2021 12:28:52 +0200 Subject: Fixed set_hostname() default. --- archinstall/lib/installer.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 593a812d..d242f1ee 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -144,8 +144,7 @@ class Installer(): return True - def set_hostname(self, hostname=None, *args, **kwargs): - if not hostname: hostname = self.hostname + def set_hostname(self, hostname :str, *args, **kwargs): with open(f'{self.target}/etc/hostname', 'w') as fh: fh.write(self.hostname + '\n') @@ -290,7 +289,7 @@ class Installer(): #os.remove(f'{self.target}/etc/localtime') #sys_command(f'/usr/bin/arch-chroot {self.target} ln -s /usr/share/zoneinfo/{localtime} /etc/localtime') #sys_command('/usr/bin/arch-chroot /mnt hwclock --hctosys --localtime') - self.set_hostname() + self.set_hostname('archinstall') self.set_locale('en_US') # TODO: Use python functions for this -- cgit v1.2.3-70-g09d2 From 5c8d210f5f2024723b69af6f260f055a98ce9903 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Fri, 9 Apr 2021 12:43:14 +0200 Subject: Wrong use of hostname in the set_hostname() function. --- archinstall/lib/installer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index d242f1ee..5af3c226 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -146,7 +146,7 @@ class Installer(): def set_hostname(self, hostname :str, *args, **kwargs): with open(f'{self.target}/etc/hostname', 'w') as fh: - fh.write(self.hostname + '\n') + fh.write(hostname + '\n') def set_locale(self, locale, encoding='UTF-8', *args, **kwargs): if not len(locale): return True -- cgit v1.2.3-70-g09d2 From ee89c55466ec5181b938a03282c0cececd813d58 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Fri, 9 Apr 2021 13:01:01 +0200 Subject: Started patching HOOKS and MODULES based on partition iteration. Also fixed some pseudo code. --- archinstall/lib/installer.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 5af3c226..d8021e05 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -276,6 +276,16 @@ class Installer(): if partition.filesystem == 'f2fs': self.base_packages.append('f2fs-tools') + # Configure mkinitcpio to handle some specific use cases. + if partition.filesystem == 'btrfs' + if 'btrfs' not in MODULES: + MODULES.append('btrfs') + if '/usr/bin/btrfs-progs' not in BINARIES: + BINARIES.append('/usr/bin/btrfs') + + elif partition.encrypted and 'encrypt' not in HOOKS: + HOOKS.insert(HOOKS.find('filesystems'), 'encrypt') + self.pacstrap(self.base_packages) self.helper_flags['base-strapped'] = True #self.genfstab() @@ -295,13 +305,6 @@ class Installer(): # TODO: Use python functions for this sys_command(f'/usr/bin/arch-chroot {self.target} chmod 700 /root') - # Configure mkinitcpio to handle some specific use cases. - if self.partition.filesystem == 'btrfs': - MODULES.append('btrfs') - BINARIES.append('/usr/bin/btrfs') - elif self.partition.encrypted: - HOOKS.patch('encrypt', before='filesystems') - with open(f'{self.target}/etc/mkinitcpio.conf', 'w') as mkinit: mkinit.write(f"MODULES=({' '.join(MODULES)})\n") mkinit.write(f"BINARIES=({' '.join(BINARIES)})\n") -- cgit v1.2.3-70-g09d2 From fdcaeae6f2243ff401409cc869a4c02430aa89c3 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Fri, 9 Apr 2021 13:01:22 +0200 Subject: Syntax error --- archinstall/lib/installer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index d8021e05..02c63a11 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -277,7 +277,7 @@ class Installer(): self.base_packages.append('f2fs-tools') # Configure mkinitcpio to handle some specific use cases. - if partition.filesystem == 'btrfs' + if partition.filesystem == 'btrfs': if 'btrfs' not in MODULES: MODULES.append('btrfs') if '/usr/bin/btrfs-progs' not in BINARIES: -- cgit v1.2.3-70-g09d2 From 56239d89b58a6ee7bc3d0c299833a8aa6635ae79 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Fri, 9 Apr 2021 13:06:47 +0200 Subject: Fixed some log output logic for the boot partition. --- archinstall/lib/installer.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 02c63a11..4c617582 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -322,7 +322,15 @@ class Installer(): return True def add_bootloader(self, bootloader='systemd-bootctl'): - self.log(f'Adding bootloader {bootloader} to {self.boot_partition}', level=LOG_LEVELS.Info) + # This logic is only for debug/log purposes: + # (it could be completely ommitted if we just print /mnt instead) + boot_partition = None + for partition in self.partitions: + if partition.mountpoint == self.target+'/boot' + boot_partition = partition + break + + self.log(f'Adding bootloader {bootloader} to {boot_partition}', level=LOG_LEVELS.Info) if bootloader == 'systemd-bootctl': # TODO: Ideally we would want to check if another config -- cgit v1.2.3-70-g09d2 From 72ad1ad5e0765f12fef5ea27a5c8dcb290c5b682 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Fri, 9 Apr 2021 13:07:08 +0200 Subject: Fixed some log output logic for the boot partition. --- archinstall/lib/installer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 4c617582..3fd6cfe3 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -326,7 +326,7 @@ class Installer(): # (it could be completely ommitted if we just print /mnt instead) boot_partition = None for partition in self.partitions: - if partition.mountpoint == self.target+'/boot' + if partition.mountpoint == self.target+'/boot': boot_partition = partition break -- cgit v1.2.3-70-g09d2 From 9ebd8b8719d9f2643a4b503b9e9aca02edeee0bd Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Fri, 9 Apr 2021 13:13:14 +0200 Subject: Change of variables to support new partition lookup. --- archinstall/lib/installer.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 3fd6cfe3..48ef7259 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -322,13 +322,13 @@ class Installer(): return True def add_bootloader(self, bootloader='systemd-bootctl'): - # This logic is only for debug/log purposes: - # (it could be completely ommitted if we just print /mnt instead) boot_partition = None + root_partition = None for partition in self.partitions: if partition.mountpoint == self.target+'/boot': boot_partition = partition - break + elif partition.mountpoint == self.target: + root_partition = partition self.log(f'Adding bootloader {bootloader} to {boot_partition}', level=LOG_LEVELS.Info) @@ -372,14 +372,14 @@ class Installer(): ## so we'll use the old manual method until we get that sorted out. - if self.partition.encrypted: - log(f"Identifying root partition by DISK-UUID on {self.partition}, looking for '{os.path.basename(self.partition.real_device)}'.", level=LOG_LEVELS.Debug) + if root_partition.encrypted: + log(f"Identifying root partition by DISK-UUID on {root_partition}, looking for '{os.path.basename(root_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 + log(f"Checking root partition match {os.path.basename(real_path)} against {os.path.basename(root_partition.real_device)}: {os.path.basename(real_path) == os.path.basename(root_partition.real_device)}", level=LOG_LEVELS.Debug) + if not os.path.basename(real_path) == os.path.basename(root_partition.real_device): continue entry.write(f'options cryptdevice=UUID={uid}:luksdev root=/dev/mapper/luksdev rw intel_pstate=no_hwp\n') @@ -387,13 +387,13 @@ class Installer(): return True break else: - log(f"Identifying root partition by PART-UUID on {self.partition}, looking for '{os.path.basename(self.partition.path)}'.", level=LOG_LEVELS.Debug) - entry.write(f'options root=PARTUUID={self.partition.uuid} rw intel_pstate=no_hwp\n') + log(f"Identifying root partition by PART-UUID on {root_partition}, looking for '{os.path.basename(root_partition.path)}'.", level=LOG_LEVELS.Debug) + entry.write(f'options root=PARTUUID={root_partition.uuid} rw intel_pstate=no_hwp\n') self.helper_flags['bootloader'] = bootloader return True - raise RequirementError(f"Could not identify the UUID of {self.partition}, there for {self.target}/boot/loader/entries/arch.conf will be broken until fixed.") + raise RequirementError(f"Could not identify the UUID of {root_partition}, there for {self.target}/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-70-g09d2 From cea8892c7c7a46548d4d946b3e5ed5142757ea13 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Fri, 9 Apr 2021 13:44:03 +0200 Subject: Setting .encrypted flag in minimal. --- examples/minimal.py | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/minimal.py b/examples/minimal.py index afd64a2e..adb033b6 100644 --- a/examples/minimal.py +++ b/examples/minimal.py @@ -54,6 +54,7 @@ with archinstall.Filesystem(archinstall.arguments['harddrive'], archinstall.GPT) # We encrypt the root partition if we got a password to do so with, # Otherwise we just skip straight to formatting and installation if archinstall.arguments.get('!encryption-password', None): + root.encrypted = True root.encrypt() with archinstall.luks2(root, 'luksloop', archinstall.arguments.get('!encryption-password', None)) as unlocked_root: -- cgit v1.2.3-70-g09d2 From da12f3630575976d43a6c717235bc273c63da7bd Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Fri, 9 Apr 2021 13:59:55 +0200 Subject: Forgot to give a password during encryption. --- examples/minimal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/minimal.py b/examples/minimal.py index adb033b6..d40ce2f8 100644 --- a/examples/minimal.py +++ b/examples/minimal.py @@ -55,7 +55,7 @@ with archinstall.Filesystem(archinstall.arguments['harddrive'], archinstall.GPT) # Otherwise we just skip straight to formatting and installation if archinstall.arguments.get('!encryption-password', None): root.encrypted = True - root.encrypt() + root.encrypt(password=archinstall.arguments.get('!encryption-password', None)) with archinstall.luks2(root, 'luksloop', archinstall.arguments.get('!encryption-password', None)) as unlocked_root: unlocked_root.format(root.filesystem) -- cgit v1.2.3-70-g09d2 From 740eccb213c69fb706d10003a1305a93442afb62 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Fri, 9 Apr 2021 15:06:34 +0200 Subject: Removed 'getpass' from imports. --- examples/minimal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/minimal.py b/examples/minimal.py index d40ce2f8..90bd9227 100644 --- a/examples/minimal.py +++ b/examples/minimal.py @@ -1,4 +1,4 @@ -import archinstall, getpass +import archinstall # Select a harddrive and a disk password archinstall.log(f"Minimal only supports:") -- cgit v1.2.3-70-g09d2 From f298b9e39387cae7a77a0677b1d1e4478bfdc8d0 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Fri, 9 Apr 2021 15:27:22 +0200 Subject: Added a 'use /mnt' option to the formatted #124. This has not yet been tested, but the logic should work according to the new API layout for Installation(). --- archinstall/lib/user_interaction.py | 1 + examples/guided.py | 109 +++++++++++++++++++----------------- 2 files changed, 58 insertions(+), 52 deletions(-) diff --git a/archinstall/lib/user_interaction.py b/archinstall/lib/user_interaction.py index 1f5924e4..949689c7 100644 --- a/archinstall/lib/user_interaction.py +++ b/archinstall/lib/user_interaction.py @@ -179,6 +179,7 @@ def ask_to_configure_network(): def ask_for_disk_layout(): options = { 'keep-existing' : 'Keep existing partition layout and select which ones to use where.', + 'use-mnt' : 'Use whatever is mounted under /mnt and don\'t format anything', 'format-all' : 'Format entire drive and setup a basic partition scheme.', 'abort' : 'Abort the installation.' } diff --git a/examples/guided.py b/examples/guided.py index 6feebd00..0d8030c7 100644 --- a/examples/guided.py +++ b/examples/guided.py @@ -53,6 +53,9 @@ def ask_user_questions(): if (option := archinstall.ask_for_disk_layout()) == 'abort': archinstall.log(f"Safely aborting the installation. No changes to the disk or system has been made.") exit(1) + elif option == 'use-mnt': + archinstall.arguments['harddrive'] = None + archinstall.arguments['target-mount'] = '/mnt' elif option == 'keep-existing': archinstall.arguments['harddrive'].keep_partitions = True @@ -197,62 +200,63 @@ def perform_installation_steps(): We mention the drive one last time, and count from 5 to 0. """ - print(f" ! Formatting {archinstall.arguments['harddrive']} in ", end='') - archinstall.do_countdown() - - """ - Setup the blockdevice, filesystem (and optionally encryption). - Once that's done, we'll hand over to perform_installation() - """ - 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')) - - # 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 - - # After the disk is ready, iterate the partitions and check - # which ones are safe to format, and format those. - for partition in archinstall.arguments['harddrive']: - if partition.safe_to_format(): - # Partition might be marked as encrypted due to the filesystem type crypt_LUKS - # But we might have omitted the encryption password question to skip encryption. - # In which case partition.encrypted will be true, but passwd will be false. - if partition.encrypted and (passwd := archinstall.arguments.get('!encryption-password', None)): - partition.encrypt(password=passwd) + if archinstall.arguments.get('harddrive', None): + print(f" ! Formatting {archinstall.arguments['harddrive']} in ", end='') + archinstall.do_countdown() + + """ + Setup the blockdevice, filesystem (and optionally encryption). + Once that's done, we'll hand over to perform_installation() + """ + 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')) + + # 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 + + # After the disk is ready, iterate the partitions and check + # which ones are safe to format, and format those. + for partition in archinstall.arguments['harddrive']: + if partition.safe_to_format(): + # Partition might be marked as encrypted due to the filesystem type crypt_LUKS + # But we might have omitted the encryption password question to skip encryption. + # In which case partition.encrypted will be true, but passwd will be false. + if partition.encrypted and (passwd := archinstall.arguments.get('!encryption-password', None)): + partition.encrypt(password=passwd) + else: + partition.format() else: - partition.format() + archinstall.log(f"Did not format {partition} because .safe_to_format() returned False or .allow_formatting was False.", level=archinstall.LOG_LEVELS.Debug) + + fs.find_partition('/boot').format('vfat') + + if archinstall.arguments.get('!encryption-password', None): + # First encrypt and unlock, then format the desired partition inside the encrypted part. + # archinstall.luks2() encrypts the partition when entering the with context manager, and + # unlocks the drive so that it can be used as a normal block-device within archinstall. + with archinstall.luks2(fs.find_partition('/'), 'luksloop', archinstall.arguments.get('!encryption-password', None)) as unlocked_device: + unlocked_device.format(fs.find_partition('/').filesystem) + unlocked_device.mount('/mnt') else: - archinstall.log(f"Did not format {partition} because .safe_to_format() returned False or .allow_formatting was False.", level=archinstall.LOG_LEVELS.Debug) - - if archinstall.arguments.get('!encryption-password', None): - # First encrypt and unlock, then format the desired partition inside the encrypted part. - # archinstall.luks2() encrypts the partition when entering the with context manager, and - # unlocks the drive so that it can be used as a normal block-device within archinstall. - with archinstall.luks2(fs.find_partition('/'), 'luksloop', archinstall.arguments.get('!encryption-password', None)) as unlocked_device: - unlocked_device.format(fs.find_partition('/').filesystem) - - perform_installation(device=unlocked_device, - boot_partition=fs.find_partition('/boot'), - language=archinstall.arguments['keyboard-language'], - mirrors=archinstall.arguments['mirror-region']) - else: - perform_installation(device=fs.find_partition('/'), - boot_partition=fs.find_partition('/boot'), - language=archinstall.arguments['keyboard-language'], - mirrors=archinstall.arguments['mirror-region']) - - -def perform_installation(device, boot_partition, language, mirrors): + fs.find_partition('/').format(fs.find_partition('/').filesystem) + fs.find_partition('/').mount('/mnt') + + fs.find_partition('/boot').mount('/mnt/boot') + + perform_installation('/mnt') + + +def perform_installation(mountpoint): """ Performs the installation steps on a block device. Only requirement is that the block devices are formatted and setup prior to entering this function. """ - with archinstall.Installer(device, boot_partition=boot_partition, hostname=archinstall.arguments.get('hostname', 'Archinstall')) as installation: + with archinstall.Installer(mountpoint) as installation: ## if len(mirrors): # Certain services might be running that affects the system during installation. # Currently, only one such service is "reflector.service" which updates /etc/pacman.d/mirrorlist @@ -261,10 +265,11 @@ def perform_installation(device, boot_partition, language, mirrors): while 'dead' not in (status := archinstall.service_state('reflector')): time.sleep(1) - archinstall.use_mirrors(mirrors) # Set the mirrors for the live medium + archinstall.use_mirrors(archinstall.arguments['mirror-region']) # Set the mirrors for the live medium if installation.minimal_installation(): - installation.set_mirrors(mirrors) # Set the mirrors in the installation medium - installation.set_keyboard_language(language) + installation.set_hostname(archinstall.arguments['hostname']) + installation.set_mirrors(archinstall.arguments['mirror-region']) # Set the mirrors in the installation medium + installation.set_keyboard_language(archinstall.arguments['keyboard-language']) installation.add_bootloader() # If user selected to copy the current ISO network configuration -- cgit v1.2.3-70-g09d2 From ce044064485027647e123b71522729469261113d Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Fri, 9 Apr 2021 15:40:48 +0200 Subject: Added some debugging --- examples/guided.py | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/guided.py b/examples/guided.py index 0d8030c7..06f91346 100644 --- a/examples/guided.py +++ b/examples/guided.py @@ -247,6 +247,7 @@ def perform_installation_steps(): fs.find_partition('/boot').mount('/mnt/boot') + exit(1) perform_installation('/mnt') -- cgit v1.2.3-70-g09d2 From 0dafeacabd37f77f3ffc6e4a4bf769a7fe3ea2bb Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Fri, 9 Apr 2021 15:42:35 +0200 Subject: Removed some debugging --- examples/guided.py | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/guided.py b/examples/guided.py index 06f91346..0d8030c7 100644 --- a/examples/guided.py +++ b/examples/guided.py @@ -247,7 +247,6 @@ def perform_installation_steps(): fs.find_partition('/boot').mount('/mnt/boot') - exit(1) perform_installation('/mnt') -- cgit v1.2.3-70-g09d2 From bd134c5db0f9fb93b51e00b3a2df992715d28d81 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Fri, 9 Apr 2021 17:33:44 +0200 Subject: Moved the 'use /mnt' logic to during disk selection. --- archinstall/lib/user_interaction.py | 7 ++++--- examples/guided.py | 5 ++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/archinstall/lib/user_interaction.py b/archinstall/lib/user_interaction.py index 949689c7..cb0fb012 100644 --- a/archinstall/lib/user_interaction.py +++ b/archinstall/lib/user_interaction.py @@ -179,7 +179,6 @@ def ask_to_configure_network(): def ask_for_disk_layout(): options = { 'keep-existing' : 'Keep existing partition layout and select which ones to use where.', - 'use-mnt' : 'Use whatever is mounted under /mnt and don\'t format anything', 'format-all' : 'Format entire drive and setup a basic partition scheme.', 'abort' : 'Abort the installation.' } @@ -246,8 +245,10 @@ def select_disk(dict_o_disks): if len(drives) >= 1: for index, drive in enumerate(drives): 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 = input('Select one of the above disks (by number or full path) or write /mnt to skip partitioning: ') + if drive.strip() == '/mnt': + return None + elif drive.isdigit(): drive = int(drive) if drive >= len(drives): raise DiskError(f'Selected option "{drive}" is out of range') diff --git a/examples/guided.py b/examples/guided.py index 0d8030c7..2028c0c4 100644 --- a/examples/guided.py +++ b/examples/guided.py @@ -30,6 +30,8 @@ def ask_user_questions(): archinstall.arguments['harddrive'] = archinstall.BlockDevice(archinstall.arguments['harddrive']) else: archinstall.arguments['harddrive'] = archinstall.select_disk(archinstall.all_disks()) + if archinstall.arguments['harddrive'] is None: + archinstall.arguments['target-mount'] = '/mnt' # Perform a quick sanity check on the selected harddrive. # 1. Check if it has partitions @@ -53,9 +55,6 @@ def ask_user_questions(): if (option := archinstall.ask_for_disk_layout()) == 'abort': archinstall.log(f"Safely aborting the installation. No changes to the disk or system has been made.") exit(1) - elif option == 'use-mnt': - archinstall.arguments['harddrive'] = None - archinstall.arguments['target-mount'] = '/mnt' elif option == 'keep-existing': archinstall.arguments['harddrive'].keep_partitions = True -- cgit v1.2.3-70-g09d2 From 5099376dcdf59cbfcd146f3c2fa92872b2b1920c Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Fri, 9 Apr 2021 21:50:53 +0200 Subject: Attempting to fix auto-detection of encrypted drives. So that #124 can perform reverse detection on partitions and detect encryption. --- archinstall/lib/disk.py | 4 ++++ archinstall/lib/installer.py | 5 +++-- examples/minimal.py | 4 ++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index f6dc16eb..fe06ac00 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -214,6 +214,10 @@ class Partition(): self._encrypted = value + @property + def parent(self): + return self.real_device + @property def real_device(self): if not self._encrypted: diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 48ef7259..7fd775b1 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -283,8 +283,9 @@ class Installer(): if '/usr/bin/btrfs-progs' not in BINARIES: BINARIES.append('/usr/bin/btrfs') - elif partition.encrypted and 'encrypt' not in HOOKS: - HOOKS.insert(HOOKS.find('filesystems'), 'encrypt') + elif (partition.encrypted or Partition(partition.parent, None).filesystem == 'crypto_LUKS'): + if 'encrypt' not in HOOKS: + HOOKS.insert(HOOKS.find('filesystems'), 'encrypt') self.pacstrap(self.base_packages) self.helper_flags['base-strapped'] = True diff --git a/examples/minimal.py b/examples/minimal.py index 90bd9227..de896d48 100644 --- a/examples/minimal.py +++ b/examples/minimal.py @@ -1,5 +1,9 @@ import archinstall +# Unmount and close previous runs +archinstall.sys_command(f'umount -R /mnt', suppress_errors=True) +archinstall.sys_command(f'cryptsetup close /dev/mapper/luksloop', suppress_errors=True) + # Select a harddrive and a disk password archinstall.log(f"Minimal only supports:") archinstall.log(f" * Being installed to a single disk") -- cgit v1.2.3-70-g09d2 From 97540293b8fd1e867006d52f07b3817bf491c7cf Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Fri, 9 Apr 2021 22:06:17 +0200 Subject: Removed some debugging auto-unmount --- examples/minimal.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/examples/minimal.py b/examples/minimal.py index de896d48..90bd9227 100644 --- a/examples/minimal.py +++ b/examples/minimal.py @@ -1,9 +1,5 @@ import archinstall -# Unmount and close previous runs -archinstall.sys_command(f'umount -R /mnt', suppress_errors=True) -archinstall.sys_command(f'cryptsetup close /dev/mapper/luksloop', suppress_errors=True) - # Select a harddrive and a disk password archinstall.log(f"Minimal only supports:") archinstall.log(f" * Being installed to a single disk") -- cgit v1.2.3-70-g09d2 From 0370c44ed812961460de48d6e8888f8e868cc7fa Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Fri, 9 Apr 2021 22:08:33 +0200 Subject: Enabled skipping partitioning in minimal. It now can take /mnt just as guided as it's destination, and skips partitioning all together. Which makes it go straight to installation. --- examples/minimal.py | 51 +++++++++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/examples/minimal.py b/examples/minimal.py index 90bd9227..98d9a6f0 100644 --- a/examples/minimal.py +++ b/examples/minimal.py @@ -10,7 +10,6 @@ if archinstall.arguments.get('help', None): archinstall.log(f" - Optional systemd network via --network") archinstall.arguments['harddrive'] = archinstall.select_disk(archinstall.all_disks()) -archinstall.arguments['harddrive'].keep_partitions = False def install_on(mountpoint): # We kick off the installer by telling it where the @@ -37,32 +36,36 @@ def install_on(mountpoint): archinstall.log(f" * root (password: airoot)") archinstall.log(f" * devel (password: devel)") -print(f" ! Formatting {archinstall.arguments['harddrive']} in ", end='') -archinstall.do_countdown() +if archinstall.arguments['harddrive']: + archinstall.arguments['harddrive'].keep_partitions = False + + print(f" ! Formatting {archinstall.arguments['harddrive']} in ", end='') + archinstall.do_countdown() -# First, we configure the basic filesystem layout -with archinstall.Filesystem(archinstall.arguments['harddrive'], archinstall.GPT) as fs: - # We use the entire disk instead of setting up partitions on your own - if archinstall.arguments['harddrive'].keep_partitions is False: - fs.use_entire_disk(root_filesystem_type=archinstall.arguments.get('filesystem', 'btrfs')) + # First, we configure the basic filesystem layout + with archinstall.Filesystem(archinstall.arguments['harddrive'], archinstall.GPT) as fs: + # We use the entire disk instead of setting up partitions on your own + if archinstall.arguments['harddrive'].keep_partitions is False: + fs.use_entire_disk(root_filesystem_type=archinstall.arguments.get('filesystem', 'btrfs')) - boot = fs.find_partition('/boot') - root = fs.find_partition('/') + boot = fs.find_partition('/boot') + root = fs.find_partition('/') - boot.format('vfat') + boot.format('vfat') - # We encrypt the root partition if we got a password to do so with, - # Otherwise we just skip straight to formatting and installation - if archinstall.arguments.get('!encryption-password', None): - root.encrypted = True - root.encrypt(password=archinstall.arguments.get('!encryption-password', None)) + # We encrypt the root partition if we got a password to do so with, + # Otherwise we just skip straight to formatting and installation + if archinstall.arguments.get('!encryption-password', None): + root.encrypted = True + root.encrypt(password=archinstall.arguments.get('!encryption-password', None)) - with archinstall.luks2(root, 'luksloop', archinstall.arguments.get('!encryption-password', None)) as unlocked_root: - unlocked_root.format(root.filesystem) - unlocked_root.mount('/mnt') - else: - root.format(root.filesystem) - root.mount('/mnt') + with archinstall.luks2(root, 'luksloop', archinstall.arguments.get('!encryption-password', None)) as unlocked_root: + unlocked_root.format(root.filesystem) + unlocked_root.mount('/mnt') + else: + root.format(root.filesystem) + root.mount('/mnt') - boot.mount('/mnt/boot') - install_on('/mnt') \ No newline at end of file + boot.mount('/mnt/boot') + +install_on('/mnt') \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 8f096001b6f5c8a864bc1e65b56bbfad1a9c9a3f Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Fri, 9 Apr 2021 22:34:26 +0200 Subject: Attempting to correct some inconsitencies in disk-parent reporting. --- archinstall/lib/disk.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index fe06ac00..1f0e584a 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -220,12 +220,9 @@ class Partition(): @property def real_device(self): - if not self._encrypted: - return self.path - else: - 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}" + 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}') return self.path -- cgit v1.2.3-70-g09d2 From c7b213337613ed586bed24486440b4635054b57d Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Fri, 9 Apr 2021 22:58:41 +0200 Subject: Attempting to correct some inconsitencies in disk-parent reporting. --- archinstall/lib/installer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 7fd775b1..a60955b7 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -283,7 +283,7 @@ class Installer(): if '/usr/bin/btrfs-progs' not in BINARIES: BINARIES.append('/usr/bin/btrfs') - elif (partition.encrypted or Partition(partition.parent, None).filesystem == 'crypto_LUKS'): + if (partition.encrypted or Partition(partition.parent, None, autodetect_filesystem=True).filesystem == 'crypto_LUKS'): if 'encrypt' not in HOOKS: HOOKS.insert(HOOKS.find('filesystems'), 'encrypt') -- cgit v1.2.3-70-g09d2 From e49b73cef41b39e0046a8dc10fddfc4337255a5b Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Fri, 9 Apr 2021 23:12:47 +0200 Subject: Attempting to correct some inconsitencies in disk-parent reporting. --- archinstall/lib/disk.py | 3 +++ archinstall/lib/installer.py | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index 1f0e584a..d0d7d4ea 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -166,6 +166,9 @@ class Partition(): self.mountpoint = target if not self.filesystem and autodetect_filesystem: + print(f'Auto-detecting filesystem for: {path}') + print('Mount information:', mount_information.get('fstype', None)) + print('Real device:', get_filesystem_type(self.real_device)) if (fstype := mount_information.get('fstype', get_filesystem_type(self.real_device))): self.filesystem = fstype diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index a60955b7..8adc3515 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -283,7 +283,7 @@ class Installer(): if '/usr/bin/btrfs-progs' not in BINARIES: BINARIES.append('/usr/bin/btrfs') - if (partition.encrypted or Partition(partition.parent, None, autodetect_filesystem=True).filesystem == 'crypto_LUKS'): + if (partition.encrypted or (partition.parent not in partition.path and Partition(partition.parent, None, autodetect_filesystem=True).filesystem == 'crypto_LUKS')): if 'encrypt' not in HOOKS: HOOKS.insert(HOOKS.find('filesystems'), 'encrypt') -- cgit v1.2.3-70-g09d2 From 0531e3a0d6368ee2ae606d2f390ffffaf53e4f2e Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Fri, 9 Apr 2021 23:18:04 +0200 Subject: Attempting to correct some inconsitencies in disk-parent reporting. --- archinstall/lib/disk.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index d0d7d4ea..15071c00 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -168,8 +168,8 @@ class Partition(): if not self.filesystem and autodetect_filesystem: print(f'Auto-detecting filesystem for: {path}') print('Mount information:', mount_information.get('fstype', None)) - print('Real device:', get_filesystem_type(self.real_device)) - if (fstype := mount_information.get('fstype', get_filesystem_type(self.real_device))): + print('Real device:', get_filesystem_type(path)) + if (fstype := mount_information.get('fstype', get_filesystem_type(path))): self.filesystem = fstype if self.filesystem == 'crypto_LUKS': -- cgit v1.2.3-70-g09d2 From f031bb077ce8e4eee3745f4f109b451856aab372 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Fri, 9 Apr 2021 23:18:59 +0200 Subject: List function call error. --- archinstall/lib/installer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 8adc3515..74978ef6 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -285,7 +285,7 @@ class Installer(): if (partition.encrypted or (partition.parent not in partition.path and Partition(partition.parent, None, autodetect_filesystem=True).filesystem == 'crypto_LUKS')): if 'encrypt' not in HOOKS: - HOOKS.insert(HOOKS.find('filesystems'), 'encrypt') + HOOKS.insert(HOOKS.index('filesystems'), 'encrypt') self.pacstrap(self.base_packages) self.helper_flags['base-strapped'] = True -- cgit v1.2.3-70-g09d2 From 99c18d5d663453d792683464ce6b077333ec7775 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Fri, 9 Apr 2021 23:26:16 +0200 Subject: Removed some debugging. --- archinstall/lib/disk.py | 3 --- archinstall/lib/installer.py | 1 - 2 files changed, 4 deletions(-) diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index 15071c00..e5aa9a85 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -166,9 +166,6 @@ class Partition(): self.mountpoint = target if not self.filesystem and autodetect_filesystem: - print(f'Auto-detecting filesystem for: {path}') - print('Mount information:', mount_information.get('fstype', None)) - print('Real device:', get_filesystem_type(path)) if (fstype := mount_information.get('fstype', get_filesystem_type(path))): self.filesystem = fstype diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 74978ef6..c4e4e515 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -49,7 +49,6 @@ class Installer(): storage['session'] = self self.partitions = get_partitions_in_use(self.target) - print(self.partitions) def log(self, *args, level=LOG_LEVELS.Debug, **kwargs): """ -- cgit v1.2.3-70-g09d2 From 9b2f627d9eb024e5068e317c00e7f8d8bb0ffa09 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Fri, 9 Apr 2021 23:41:13 +0200 Subject: Fixing broken logic in guided --- examples/guided.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/guided.py b/examples/guided.py index 2028c0c4..ed0a485a 100644 --- a/examples/guided.py +++ b/examples/guided.py @@ -37,7 +37,7 @@ def ask_user_questions(): # 1. Check if it has partitions # 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(): + if archinstall.arguments['harddrive'] and archinstall.arguments['harddrive'].has_partitions(): archinstall.log(f"{archinstall.arguments['harddrive']} contains the following partitions:", fg='yellow') # We curate a list pf supported partitions -- cgit v1.2.3-70-g09d2 From 22eb6e023ddf04552777d5c59a1054836964dd42 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Fri, 9 Apr 2021 23:42:28 +0200 Subject: Fixing broken logic in guided --- examples/guided.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/guided.py b/examples/guided.py index ed0a485a..b4b970bb 100644 --- a/examples/guided.py +++ b/examples/guided.py @@ -116,7 +116,7 @@ def ask_user_questions(): elif option == 'format-all': archinstall.arguments['filesystem'] = archinstall.ask_for_main_filesystem_format() archinstall.arguments['harddrive'].keep_partitions = False - else: + elif archinstall.arguments['harddrive']: # If the drive doesn't have any partitions, safely mark the disk with keep_partitions = False # and ask the user for a root filesystem. archinstall.arguments['filesystem'] = archinstall.ask_for_main_filesystem_format() -- cgit v1.2.3-70-g09d2 From 103320b06188565f2166e0330dd3a8bedb9f8572 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Fri, 9 Apr 2021 23:43:17 +0200 Subject: Fixing broken logic in guided --- examples/guided.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/guided.py b/examples/guided.py index b4b970bb..79023012 100644 --- a/examples/guided.py +++ b/examples/guided.py @@ -123,7 +123,7 @@ def ask_user_questions(): archinstall.arguments['harddrive'].keep_partitions = False # Get disk encryption password (or skip if blank) - if not archinstall.arguments.get('!encryption-password', None): + if archinstall.arguments['harddrive'] and archinstall.arguments.get('!encryption-password', None) is None: 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-70-g09d2 From e7ad4038bda9fb5906c4708eb8b48babe9778387 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sat, 10 Apr 2021 00:06:25 +0200 Subject: Fixing UUID on encrypted partitions. --- archinstall/lib/installer.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index c4e4e515..af973227 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -256,6 +256,9 @@ class Installer(): return True + def detect_encryption(self, partition): + return partition.encrypted or (partition.parent not in partition.path and Partition(partition.parent, None, autodetect_filesystem=True).filesystem == 'crypto_LUKS') + def minimal_installation(self): ## Add necessary packages if encrypting the drive ## (encrypted partitions default to btrfs for now, so we need btrfs-progs) @@ -282,7 +285,7 @@ class Installer(): if '/usr/bin/btrfs-progs' not in BINARIES: BINARIES.append('/usr/bin/btrfs') - if (partition.encrypted or (partition.parent not in partition.path and Partition(partition.parent, None, autodetect_filesystem=True).filesystem == 'crypto_LUKS')): + if self.detect_encryption(partition): if 'encrypt' not in HOOKS: HOOKS.insert(HOOKS.index('filesystems'), 'encrypt') @@ -372,7 +375,7 @@ class Installer(): ## so we'll use the old manual method until we get that sorted out. - if root_partition.encrypted: + if self.detect_encryption(root_partition): log(f"Identifying root partition by DISK-UUID on {root_partition}, looking for '{os.path.basename(root_partition.real_device)}'.", level=LOG_LEVELS.Debug) for root, folders, uids in os.walk('/dev/disk/by-uuid'): for uid in uids: -- cgit v1.2.3-70-g09d2 From 1e0770e582b8a32175dfda224a153bf19522fb03 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sat, 10 Apr 2021 10:14:15 +0200 Subject: Modified encrypted partitions to use partuuid for now. --- archinstall/lib/disk.py | 12 ++++++++++++ archinstall/lib/installer.py | 30 ++++++++++++------------------ 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index e5aa9a85..1a2dc4dc 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -126,6 +126,18 @@ class BlockDevice(): def partition_table_type(self): return GPT + @property + def uuid(self): + log(f'BlockDevice().uuid is untested!', level=LOG_LEVELS.Warning, fg='yellow') + """ + Returns the disk UUID as returned by lsblk. + This is more reliable than relying on /dev/disk/by-partuuid as + it doesn't seam to be able to detect md raid partitions. + """ + lsblk = b''.join(sys_command(f'lsblk -J -o+UUID {self.path}')) + for partition in json.loads(lsblk.decode('UTF-8'))['blockdevices']: + return partition.get('uuid', None) + def has_partitions(self): return len(self.partitions) diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index af973227..0c622129 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -257,7 +257,12 @@ class Installer(): return True def detect_encryption(self, partition): - return partition.encrypted or (partition.parent not in partition.path and Partition(partition.parent, None, autodetect_filesystem=True).filesystem == 'crypto_LUKS') + if partition.encrypted: + return partition + elif partition.parent not in partition.path and Partition(partition.parent, None, autodetect_filesystem=True).filesystem == 'crypto_LUKS': + return Partition(partition.parent, None, autodetect_filesystem=True) + + return False def minimal_installation(self): ## Add necessary packages if encrypting the drive @@ -375,26 +380,15 @@ class Installer(): ## so we'll use the old manual method until we get that sorted out. - if self.detect_encryption(root_partition): - log(f"Identifying root partition by DISK-UUID on {root_partition}, looking for '{os.path.basename(root_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(root_partition.real_device)}: {os.path.basename(real_path) == os.path.basename(root_partition.real_device)}", level=LOG_LEVELS.Debug) - if not os.path.basename(real_path) == os.path.basename(root_partition.real_device): continue - - entry.write(f'options cryptdevice=UUID={uid}:luksdev root=/dev/mapper/luksdev rw intel_pstate=no_hwp\n') - - self.helper_flags['bootloader'] = bootloader - return True - break + if (real_device := self.detect_encryption(root_partition)): + log(f"Identifying root partition by PART-UUID on {real_device}: '{real_device.uuid}'.", level=LOG_LEVELS.Debug) + entry.write(f'options cryptdevice=PARTUUID={real_device.uuid}:luksdev root=/dev/mapper/luksdev rw intel_pstate=no_hwp\n') else: - log(f"Identifying root partition by PART-UUID on {root_partition}, looking for '{os.path.basename(root_partition.path)}'.", level=LOG_LEVELS.Debug) + log(f"Identifying root partition by PART-UUID on {root_partition}, looking for '{root_partition.uuid}'.", level=LOG_LEVELS.Debug) entry.write(f'options root=PARTUUID={root_partition.uuid} rw intel_pstate=no_hwp\n') - self.helper_flags['bootloader'] = bootloader - return True + self.helper_flags['bootloader'] = bootloader + return True raise RequirementError(f"Could not identify the UUID of {root_partition}, there for {self.target}/boot/loader/entries/arch.conf will be broken until fixed.") else: -- cgit v1.2.3-70-g09d2 From d9fc8abf02c70ad8177048f85a06294d63e41faf Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sat, 10 Apr 2021 10:25:59 +0200 Subject: Added a #TODO --- archinstall/lib/installer.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 0c622129..92e89f26 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -381,6 +381,8 @@ class Installer(): if (real_device := self.detect_encryption(root_partition)): + # TODO: We need to detect if the encrypted device is a whole disk encryption, + # or simply a partition encryption. Right now we assume it's a partition (and we always have) log(f"Identifying root partition by PART-UUID on {real_device}: '{real_device.uuid}'.", level=LOG_LEVELS.Debug) entry.write(f'options cryptdevice=PARTUUID={real_device.uuid}:luksdev root=/dev/mapper/luksdev rw intel_pstate=no_hwp\n') else: -- cgit v1.2.3-70-g09d2 From 48e801e6fdbc1f74885a3541011d4cce5876ab21 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sat, 10 Apr 2021 11:21:24 +0200 Subject: Added a mission statement, and updated the minimal example in the readme. --- README.md | 59 ++++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 46 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 2f3881e1..a48f0a91 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,18 @@ Assuming you are on a Arch Linux live-ISO and booted into EFI mode. # python -m archinstall guided +# Mission Statement + +Archinstall promises to ship a [guided installer](https://github.com/archlinux/archinstall/blob/master/examples/guided.py) that follows the [Arch Principles](https://wiki.archlinux.org/index.php/Arch_Linux#Principles) as well as a library to manage services, packages and other Arch Linux aspects. + +The guided installer will provide user friendly options along the way, but the keyword here is options, they are optional and will never be forced upon anyone. The guided installer itself is also optional to use if so desired and not forced upon anyone. + +--- + +Archinstall has one fundamental function which is to be a flexible library to manage services, packages and other aspects inside the installed system. This library is in turn used by the provided guided installer but is also for anyone who wants to script their own installations. + +Therefore, Archinstall will try its best to not introduce any breaking changes except for major releases which may break backwards compability after notifying about such changes. + # Scripting your own installation You could just copy [guided.py](examples/guided.py) as a starting point. @@ -35,23 +47,44 @@ import archinstall, getpass harddrive = archinstall.select_disk(archinstall.all_disks()) disk_password = getpass.getpass(prompt='Disk password (won\'t echo): ') -with archinstall.Filesystem(harddrive, archinstall.GPT) as fs: - # use_entire_disk() is a helper to not have to format manually - fs.use_entire_disk('luks2') +# We disable safety precautions in the library that protects the partitions +harddrive.keep_partitions = False + +# First, we configure the basic filesystem layout +with archinstall.Filesystem(archinstall.arguments['harddrive'], archinstall.GPT) as fs: + # We create a filesystem layout that will use the entire drive + # (this is a helper function, you can partition manually as well) + fs.use_entire_disk(root_filesystem_type='btrfs') + + boot = fs.find_partition('/boot') + root = fs.find_partition('/') + + boot.format('vfat') + + # Set the flat for encrypted to allow for encryption and then encrypt + root.encrypted = True + root.encrypt(password=archinstall.arguments.get('!encryption-password', None)) + +with archinstall.luks2(root, 'luksloop', disk_password) as unlocked_root: + unlocked_root.format(root.filesystem) + unlocked_root.mount('/mnt') + + boot.mount('/mnt/boot') - harddrive.partition[0].format('fat32') - with archinstall.luks2(harddrive.partition[1], 'luksloop', disk_password) as unlocked_device: - unlocked_device.format('btrfs') +with archinstall.Installer('/mnt') as installation: + if installation.minimal_installation(): + installation.set_hostname('minimal-arch') + installation.add_bootloader() - with archinstall.Installer(unlocked_device, hostname='testmachine') as installation: - if installation.minimal_installation(): - installation.add_bootloader(harddrive.partition[0]) + installation.add_additional_packages(['nano', 'wget', 'git']) - installation.add_additional_packages(['nano', 'wget', 'git']) - installation.install_profile('awesome') + # Optionally, install a profile of choice. + # In this case, we install a minimal profile that is empty + installation.install_profile('minimal') - installation.user_create('anton', 'test') - installation.user_set_pw('root', 'toor') + installation.user_create('devel', 'devel') + installation.user_set_pw('root', 'airoot') + ``` This installer will perform the following: -- cgit v1.2.3-70-g09d2