From 850fd2efa812508e2df67aa2b50cff8820389a0d Mon Sep 17 00:00:00 2001 From: advaithm Date: Fri, 12 Mar 2021 11:30:32 +0530 Subject: Started work on BIOS support --- archinstall/lib/installer.py | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 06bdd05a..ecc3c9c9 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -1,4 +1,4 @@ -import os, stat, time, shutil +import os, stat, time, shutil, subprocess from .exceptions import * from .disk import * @@ -53,6 +53,8 @@ class Installer(): } self.base_packages = base_packages.split(' ') + if not hasUEFI(): + base_packages.append('grub') # if it isn't uefi is must be bios therefore we need grub as systemd-boot is uefi only self.post_base_install = [] storage['session'] = self @@ -332,8 +334,10 @@ class Installer(): for uid in uids: real_path = os.path.realpath(os.path.join(root, uid)) if not os.path.basename(real_path) == os.path.basename(self.partition.real_device): continue - - entry.write(f'options cryptdevice=UUID={uid}:luksdev root=/dev/mapper/luksdev rw intel_pstate=no_hwp\n') + if subprocess.check_output("lscpu | grep AMD", shell=True).strip().decode(): # intel_paste is intel only, it's redudant on AMD systens + entry.write(f'options cryptdevice=UUID={uid}:luksdev root=/dev/mapper/luksdev rw\n') + else: + 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 @@ -343,13 +347,22 @@ class Installer(): for uid in uids: real_path = os.path.realpath(os.path.join(root, uid)) if not os.path.basename(real_path) == os.path.basename(self.partition.path): continue - - entry.write(f'options root=PARTUUID={uid} rw intel_pstate=no_hwp\n') + if subprocess.check_output("lscpu | grep AMD", shell=True).strip().decode(): + entry.write(f'options root=PARTUUID={uid} rw\n') + else: + entry.write(f'options root=PARTUUID={uid} rw intel_pstate=no_hwp\n') self.helper_flags['bootloader'] = bootloader return True break raise RequirementError(f"Could not identify the UUID of {self.partition}, there for {self.mountpoint}/boot/loader/entries/arch.conf will be broken until fixed.") + elif bootloader == 'grub-install': + if hasUEFI(): + o = b''.join(sys_command(f'/usr/bin/arch-chroot {self.mountpoint} grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB')) + sys_command('/usr/bin/arch-chroot grub-mkconfig -o /boot/grub/grub.cfg') + else: + o = b''.join(sys_command(f'/usr/bin/arch-chroot {self.mountpoint} grub-install --target=--target=i386-pc {self}')) + sys_command('/usr/bin/arch-chroot grub-mkconfig -o /boot/grub/grub.cfg') else: raise RequirementError(f"Unknown (or not yet implemented) bootloader added to add_bootloader(): {bootloader}") -- cgit v1.2.3-70-g09d2 From ceadb59b26cd99f11480058c072a678dc8ae2476 Mon Sep 17 00:00:00 2001 From: advaithm Date: Fri, 12 Mar 2021 11:38:48 +0530 Subject: raise error if systemd-boot is used on a BIOS system --- archinstall/lib/installer.py | 89 +++++++++++++++++++++++--------------------- 1 file changed, 46 insertions(+), 43 deletions(-) (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index ecc3c9c9..5ab560f4 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -313,49 +313,52 @@ class Installer(): self.log(f'Adding bootloader {bootloader} to {self.boot_partition}', level=LOG_LEVELS.Info) if bootloader == 'systemd-bootctl': - o = b''.join(sys_command(f'/usr/bin/arch-chroot {self.mountpoint} bootctl --no-variables --path=/boot install')) - with open(f'{self.mountpoint}/boot/loader/loader.conf', 'w') as loader: - loader.write('default arch\n') - loader.write('timeout 5\n') - - ## For some reason, blkid and /dev/disk/by-uuid are not getting along well. - ## And blkid is wrong in terms of LUKS. - #UUID = sys_command('blkid -s PARTUUID -o value {drive}{partition_2}'.format(**args)).decode('UTF-8').strip() - with open(f'{self.mountpoint}/boot/loader/entries/arch.conf', 'w') as entry: - entry.write('title Arch Linux\n') - entry.write('linux /vmlinuz-linux\n') - entry.write('initrd /initramfs-linux.img\n') - ## blkid doesn't trigger on loopback devices really well, - ## so we'll use the old manual method until we get that sorted out. - - - if self.partition.encrypted: - 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)) - if not os.path.basename(real_path) == os.path.basename(self.partition.real_device): continue - if subprocess.check_output("lscpu | grep AMD", shell=True).strip().decode(): # intel_paste is intel only, it's redudant on AMD systens - entry.write(f'options cryptdevice=UUID={uid}:luksdev root=/dev/mapper/luksdev rw\n') - else: - 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 - else: - for root, folders, uids in os.walk('/dev/disk/by-partuuid'): - for uid in uids: - real_path = os.path.realpath(os.path.join(root, uid)) - if not os.path.basename(real_path) == os.path.basename(self.partition.path): continue - if subprocess.check_output("lscpu | grep AMD", shell=True).strip().decode(): - entry.write(f'options root=PARTUUID={uid} rw\n') - else: - entry.write(f'options root=PARTUUID={uid} rw intel_pstate=no_hwp\n') - - self.helper_flags['bootloader'] = bootloader - return True - break - raise RequirementError(f"Could not identify the UUID of {self.partition}, there for {self.mountpoint}/boot/loader/entries/arch.conf will be broken until fixed.") + if hasUEFI(): + o = b''.join(sys_command(f'/usr/bin/arch-chroot {self.mountpoint} bootctl --no-variables --path=/boot install')) + with open(f'{self.mountpoint}/boot/loader/loader.conf', 'w') as loader: + loader.write('default arch\n') + loader.write('timeout 5\n') + + ## For some reason, blkid and /dev/disk/by-uuid are not getting along well. + ## And blkid is wrong in terms of LUKS. + #UUID = sys_command('blkid -s PARTUUID -o value {drive}{partition_2}'.format(**args)).decode('UTF-8').strip() + with open(f'{self.mountpoint}/boot/loader/entries/arch.conf', 'w') as entry: + entry.write('title Arch Linux\n') + entry.write('linux /vmlinuz-linux\n') + entry.write('initrd /initramfs-linux.img\n') + ## blkid doesn't trigger on loopback devices really well, + ## so we'll use the old manual method until we get that sorted out. + + + if self.partition.encrypted: + 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)) + if not os.path.basename(real_path) == os.path.basename(self.partition.real_device): continue + if subprocess.check_output("lscpu | grep AMD", shell=True).strip().decode(): # intel_paste is intel only, it's redudant on AMD systens + entry.write(f'options cryptdevice=UUID={uid}:luksdev root=/dev/mapper/luksdev rw\n') + else: + 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 + else: + for root, folders, uids in os.walk('/dev/disk/by-partuuid'): + for uid in uids: + real_path = os.path.realpath(os.path.join(root, uid)) + if not os.path.basename(real_path) == os.path.basename(self.partition.path): continue + if subprocess.check_output("lscpu | grep AMD", shell=True).strip().decode(): + entry.write(f'options root=PARTUUID={uid} rw\n') + else: + entry.write(f'options root=PARTUUID={uid} rw intel_pstate=no_hwp\n') + + self.helper_flags['bootloader'] = bootloader + return True + break + raise RequirementError(f"Could not identify the UUID of {self.partition}, there for {self.mountpoint}/boot/loader/entries/arch.conf will be broken until fixed.") + else: + raise RequirementError("Systemd boot is UEFI only it can not be installed or used on bios") elif bootloader == 'grub-install': if hasUEFI(): o = b''.join(sys_command(f'/usr/bin/arch-chroot {self.mountpoint} grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB')) -- cgit v1.2.3-70-g09d2 From 43a0134f2e59dd34252195ff4d5bae4ebaaa6117 Mon Sep 17 00:00:00 2001 From: advaithm Date: Fri, 12 Mar 2021 11:40:30 +0530 Subject: fixed typo --- archinstall/lib/installer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 5ab560f4..e393d50e 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -358,7 +358,7 @@ class Installer(): break raise RequirementError(f"Could not identify the UUID of {self.partition}, there for {self.mountpoint}/boot/loader/entries/arch.conf will be broken until fixed.") else: - raise RequirementError("Systemd boot is UEFI only it can not be installed or used on bios") + raise RequirementError("Systemd-boot is UEFI only it can not be installed or used on bios") elif bootloader == 'grub-install': if hasUEFI(): o = b''.join(sys_command(f'/usr/bin/arch-chroot {self.mountpoint} grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB')) -- cgit v1.2.3-70-g09d2 From 94456bf8ba692fb33c819d416636b34d9b14f7af Mon Sep 17 00:00:00 2001 From: advaithm Date: Fri, 12 Mar 2021 11:57:02 +0530 Subject: add function to check cpu vendor to allow for cpu specific command line arguments --- archinstall/lib/hardware.py | 7 ++++++- archinstall/lib/installer.py | 5 +++-- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/lib/hardware.py b/archinstall/lib/hardware.py index 93eb560f..3586ad09 100644 --- a/archinstall/lib/hardware.py +++ b/archinstall/lib/hardware.py @@ -1,4 +1,4 @@ -import os +import os, subprocess from .general import sys_command from .networking import list_interfaces, enrichIfaceTypes @@ -7,6 +7,11 @@ def hasWifi(): return True return False +def hasAMDCPU(): + if subprocess.check_output("lscpu | grep AMD", shell=True).strip().decode(): + return True + return False + def hasUEFI(): return os.path.isdir('/sys/firmware/efi') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index e393d50e..dbcfb973 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -9,6 +9,7 @@ from .mirrors import * from .systemd import Networkd from .output import log, LOG_LEVELS from .storage import storage +from .hardware import * class Installer(): """ @@ -335,7 +336,7 @@ class Installer(): for uid in uids: real_path = os.path.realpath(os.path.join(root, uid)) if not os.path.basename(real_path) == os.path.basename(self.partition.real_device): continue - if subprocess.check_output("lscpu | grep AMD", shell=True).strip().decode(): # intel_paste is intel only, it's redudant on AMD systens + if hasAMDCPU(): # intel_paste is intel only, it's redudant on AMD systens entry.write(f'options cryptdevice=UUID={uid}:luksdev root=/dev/mapper/luksdev rw\n') else: entry.write(f'options cryptdevice=UUID={uid}:luksdev root=/dev/mapper/luksdev rw intel_pstate=no_hwp\n') @@ -348,7 +349,7 @@ class Installer(): for uid in uids: real_path = os.path.realpath(os.path.join(root, uid)) if not os.path.basename(real_path) == os.path.basename(self.partition.path): continue - if subprocess.check_output("lscpu | grep AMD", shell=True).strip().decode(): + if hasAMDCPU(): entry.write(f'options root=PARTUUID={uid} rw\n') else: entry.write(f'options root=PARTUUID={uid} rw intel_pstate=no_hwp\n') -- cgit v1.2.3-70-g09d2 From f249476ea7c296459d175262f45c1f8273c6e8ea Mon Sep 17 00:00:00 2001 From: advaithm Date: Fri, 12 Mar 2021 13:40:54 +0530 Subject: figured out a way to get root device for installing grub --- archinstall/lib/disk.py | 18 ++++++++++-------- archinstall/lib/installer.py | 3 ++- 2 files changed, 12 insertions(+), 9 deletions(-) (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index cd740571..d05588a6 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -394,18 +394,20 @@ class Filesystem(): def use_entire_disk(self, root_filesystem_type='ext4', encrypt_root_partition=True): self.add_partition('primary', start='1MiB', end='513MiB', format='vfat') - self.set_name(0, 'EFI') - self.set(0, 'boot on') + #TODO: figure out what do for bios, we don't need a seprate partion for the bootloader + if hasUEFI(): + self.set_name(0, 'EFI') + self.set(0, 'boot on') # TODO: Probably redundant because in GPT mode 'esp on' is an alias for "boot on"? # https://www.gnu.org/software/parted/manual/html_node/set.html - self.set(0, 'esp on') - self.add_partition('primary', start='513MiB', end='100%') + self.set(0, 'esp on') + self.add_partition('primary', start='513MiB', end='100%') - self.blockdevice.partition[0].filesystem = 'vfat' - self.blockdevice.partition[1].filesystem = root_filesystem_type + self.blockdevice.partition[0].filesystem = 'vfat' + self.blockdevice.partition[1].filesystem = root_filesystem_type - self.blockdevice.partition[0].target_mountpoint = '/boot' - self.blockdevice.partition[1].target_mountpoint = '/' + self.blockdevice.partition[0].target_mountpoint = '/boot' + self.blockdevice.partition[1].target_mountpoint = '/' if encrypt_root_partition: self.blockdevice.partition[1].encrypted = True diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index dbcfb973..176b26f4 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -365,7 +365,8 @@ class Installer(): o = b''.join(sys_command(f'/usr/bin/arch-chroot {self.mountpoint} grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB')) sys_command('/usr/bin/arch-chroot grub-mkconfig -o /boot/grub/grub.cfg') else: - o = b''.join(sys_command(f'/usr/bin/arch-chroot {self.mountpoint} grub-install --target=--target=i386-pc {self}')) + root_device = subprocess.check_output(f'basename "$(readlink -f "/sys/class/block/{self.partition.path}/..")',shell=True).decode().strip() + o = b''.join(sys_command(f'/usr/bin/arch-chroot {self.mountpoint} grub-install --target=--target=i386-pc /dev/{root_device}')) sys_command('/usr/bin/arch-chroot grub-mkconfig -o /boot/grub/grub.cfg') else: raise RequirementError(f"Unknown (or not yet implemented) bootloader added to add_bootloader(): {bootloader}") -- cgit v1.2.3-70-g09d2 From 0a47dfe5d5bbc795366828fb7e453a8ef9d307cf Mon Sep 17 00:00:00 2001 From: advaithm Date: Fri, 12 Mar 2021 13:42:52 +0530 Subject: add a if statment to prevent a possible error --- archinstall/lib/installer.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 176b26f4..463f104a 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -366,6 +366,8 @@ class Installer(): sys_command('/usr/bin/arch-chroot grub-mkconfig -o /boot/grub/grub.cfg') else: root_device = subprocess.check_output(f'basename "$(readlink -f "/sys/class/block/{self.partition.path}/..")',shell=True).decode().strip() + if root_device == "block": + root_device = f"{self.partition.path}" o = b''.join(sys_command(f'/usr/bin/arch-chroot {self.mountpoint} grub-install --target=--target=i386-pc /dev/{root_device}')) sys_command('/usr/bin/arch-chroot grub-mkconfig -o /boot/grub/grub.cfg') else: -- cgit v1.2.3-70-g09d2 From 72284e2b2a96f4c8c6603f3a900b956121253b92 Mon Sep 17 00:00:00 2001 From: advaithm Date: Fri, 12 Mar 2021 14:10:08 +0530 Subject: stip /dev/ since path is /dev/sdxN --- archinstall/lib/installer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 463f104a..e8829296 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -365,7 +365,7 @@ class Installer(): o = b''.join(sys_command(f'/usr/bin/arch-chroot {self.mountpoint} grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB')) sys_command('/usr/bin/arch-chroot grub-mkconfig -o /boot/grub/grub.cfg') else: - root_device = subprocess.check_output(f'basename "$(readlink -f "/sys/class/block/{self.partition.path}/..")',shell=True).decode().strip() + root_device = subprocess.check_output(f'basename "$(readlink -f "/sys/class/block/{self.partition.path.strip("/dev/")}/..")',shell=True).decode().strip() if root_device == "block": root_device = f"{self.partition.path}" o = b''.join(sys_command(f'/usr/bin/arch-chroot {self.mountpoint} grub-install --target=--target=i386-pc /dev/{root_device}')) -- cgit v1.2.3-70-g09d2 From 99dd9b1fb7856b864d816119f0742950941e97a8 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Thu, 25 Mar 2021 15:07:49 +0100 Subject: New feature: Profile() now supports .packages which returns any defined packages for that specific profile, as well as archinstall.__packages__ contain any packages that Installer() is responsible for. This can be used to quickly gather any required packages and dependencies by archinstall. Not all profiles have it yet, so .packages might return None. --- archinstall/__init__.py | 2 +- archinstall/lib/installer.py | 6 +++++- archinstall/lib/profiles.py | 22 ++++++++++++++++++++++ profiles/applications/awesome.py | 6 +++--- profiles/awesome.py | 10 ++-------- 5 files changed, 33 insertions(+), 13 deletions(-) (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/__init__.py b/archinstall/__init__.py index d4452d38..91cf17be 100644 --- a/archinstall/__init__.py +++ b/archinstall/__init__.py @@ -2,7 +2,7 @@ from .lib.general import * from .lib.disk import * from .lib.user_interaction import * from .lib.exceptions import * -from .lib.installer import * +from .lib.installer import __packages__, __base_packages__, Installer from .lib.profiles import * from .lib.luks import * from .lib.mirrors import * diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 2200db8e..c31ade84 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -10,6 +10,10 @@ from .systemd import Networkd from .output import log, LOG_LEVELS from .storage import storage +# Any package that the Installer() is responsible for (optional and the default ones) +__packages__ = ["base", "base-devel", "linux", "linux-firmware", "efibootmgr", "nano", "ntp", "iwd"] +__base_packages__ = __packages__[:6] + class Installer(): """ `Installer()` is the wrapper for most basic installation steps. @@ -34,7 +38,7 @@ class Installer(): :type hostname: str, optional """ - def __init__(self, partition, boot_partition, *, base_packages='base base-devel linux linux-firmware efibootmgr nano', profile=None, mountpoint='/mnt', hostname='ArchInstalled', logdir=None, logfile=None): + def __init__(self, partition, boot_partition, *, base_packages=__base_packages__, profile=None, mountpoint='/mnt', hostname='ArchInstalled', logdir=None, logfile=None): self.profile = profile self.hostname = hostname self.mountpoint = mountpoint diff --git a/archinstall/lib/profiles.py b/archinstall/lib/profiles.py index 08b1d618..8198ff11 100644 --- a/archinstall/lib/profiles.py +++ b/archinstall/lib/profiles.py @@ -178,6 +178,28 @@ class Profile(Script): return True return False + @property + def packages(self) -> list: + """ + Returns a list of packages baked into the profile definition. + If no package definition has been done, .packages() will return None. + """ + with open(self.path, 'r') as source: + source_data = source.read() + + # Some crude safety checks, make sure the imported profile has + # a __name__ check before importing. + # + # If the requirements are met, import with .py in the namespace to not + # trigger a traditional: + # if __name__ == 'moduleName' + if '__name__' in source_data and '__packages__' in source_data: + with self.load_instructions(namespace=f"{self.namespace}.py") as imported: + if hasattr(imported, '__packages__'): + return imported.__packages__ + return None + + class Application(Profile): def __repr__(self, *args, **kwargs): return f'Application({os.path.basename(self.profile)})' diff --git a/profiles/applications/awesome.py b/profiles/applications/awesome.py index 578f246e..b8d779c0 100644 --- a/profiles/applications/awesome.py +++ b/profiles/applications/awesome.py @@ -1,10 +1,10 @@ import archinstall +__packages__ = ["awesome", "xorg-xrandr", "xterm", "feh", "slock", "terminus-font", "gnu-free-fonts", "ttf-liberation", "xsel"] + installation.install_profile('xorg') -installation.add_additional_packages( - "awesome xorg-xrandr xterm feh slock terminus-font gnu-free-fonts ttf-liberation xsel" -) +installation.add_additional_packages(__packages__) with open(f'{installation.mountpoint}/etc/X11/xinit/xinitrc', 'r') as xinitrc: xinitrc_data = xinitrc.read() diff --git a/profiles/awesome.py b/profiles/awesome.py index b914b175..8004fc62 100644 --- a/profiles/awesome.py +++ b/profiles/awesome.py @@ -2,6 +2,7 @@ import archinstall +__packages__ = ['nano', 'nemo', 'gpicview-gtk3', 'chromium', 'openssh', 'sshfs', 'htop', 'scrot', 'wget'] def _prep_function(*args, **kwargs): """ @@ -28,14 +29,7 @@ if __name__ == 'awesome': awesome = archinstall.Application(installation, 'awesome') awesome.install() - # Then setup and configure the desktop environment: awesome - editor = "nano" - filebrowser = "nemo gpicview-gtk3" - webbrowser = "chromium" # TODO: Ask the user to select one instead - utils = "openssh sshfs htop scrot wget" - - - installation.add_additional_packages(f"{webbrowser} {utils} {filebrowser} {editor}") + installation.add_additional_packages(__packages__) alacritty = archinstall.Application(installation, 'alacritty') alacritty.install() -- cgit v1.2.3-70-g09d2 From b974b93004efa9912e404f5d3fca7c44a58dc0e3 Mon Sep 17 00:00:00 2001 From: advaithm Date: Fri, 2 Apr 2021 10:08:16 +0530 Subject: fixed some issues with the changes --- archinstall/lib/disk.py | 7 ++----- archinstall/lib/installer.py | 12 +++++++++++- examples/guided.py | 8 +++++++- 3 files changed, 20 insertions(+), 7 deletions(-) (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index fbc11ca3..8e9e0234 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -390,12 +390,9 @@ class Filesystem(): # TODO: # When instance of a HDD is selected, check all usages and gracefully unmount them # as well as close any crypto handles. - def __init__(self, blockdevice): + def __init__(self, blockdevice,mode): self.blockdevice = blockdevice - if hasUEFI(): - self.mode = GPT - else: - self.mode = MBR + self.mode = mode def __enter__(self, *args, **kwargs): if self.blockdevice.keep_partitions is False: diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index d161c3b7..492d7715 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -1,4 +1,4 @@ -import os, stat, time, shutil, pathlib +import os, stat, time, shutil, pathlib, subprocess from .exceptions import * from .disk import * @@ -398,6 +398,16 @@ class Installer(): break raise RequirementError(f"Could not identify the UUID of {self.partition}, there for {self.mountpoint}/boot/loader/entries/arch.conf will be broken until fixed.") + elif bootloader == "grub-install": + if hasUEFI(): + o = b''.join(sys_command(f'/usr/bin/arch-chroot {self.mountpoint} grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB')) + sys_command('/usr/bin/arch-chroot grub-mkconfig -o /boot/grub/grub.cfg') + else: + root_device = subprocess.check_output(f'basename "$(readlink -f "/sys/class/block/{self.partition.path.strip("/dev/")}/..")',shell=True).decode().strip() + if root_device == "block": + root_device = f"{self.partition.path}" + o = b''.join(sys_command(f'/usr/bin/arch-chroot {self.mountpoint} grub-install --target=--target=i386-pc /dev/{root_device}')) + sys_command('/usr/bin/arch-chroot grub-mkconfig -o /boot/grub/grub.cfg') else: raise RequirementError(f"Unknown (or not yet implemented) bootloader added to add_bootloader(): {bootloader}") diff --git a/examples/guided.py b/examples/guided.py index 71e1e01d..f374a41c 100644 --- a/examples/guided.py +++ b/examples/guided.py @@ -1,5 +1,6 @@ import getpass, time, json, sys, signal, os import archinstall +from archinstall.lib.hardware import hasUEFI """ This signal-handler chain (and global variable) @@ -244,7 +245,12 @@ def perform_installation_steps(): 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: + # maybe we can ask the user what they would prefer on uefi systems? + if hasUEFI(): + mode = archinstall.GPT + else: + mode = archinstall.MBR + with archinstall.Filesystem(archinstall.arguments['harddrive'],mode) 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')) -- cgit v1.2.3-70-g09d2 From 6b218e555be5860a00297be30da22a1c09944ed2 Mon Sep 17 00:00:00 2001 From: advaithm Date: Fri, 2 Apr 2021 10:16:48 +0530 Subject: changed __enter__ --- archinstall/lib/installer.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 492d7715..1411688c 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -67,9 +67,11 @@ 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') + if hasUEFI(): + # on bios we don't have a boot partition + 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): -- cgit v1.2.3-70-g09d2 From b5e32f980a27f272c1e3c42969323dff82617a84 Mon Sep 17 00:00:00 2001 From: advaithm Date: Fri, 2 Apr 2021 10:28:04 +0530 Subject: added hardwareincompatibilty erros and updated readme --- README.md | 4 ++-- archinstall/lib/installer.py | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'archinstall/lib/installer.py') diff --git a/README.md b/README.md index a65e92fa..9e611dd6 100644 --- a/README.md +++ b/README.md @@ -57,10 +57,10 @@ with archinstall.Filesystem(harddrive, archinstall.GPT) as fs: This installer will perform the following: * Prompt the user to select a disk and disk-password - * Proceed to wipe the selected disk with a `GPT` partition table. + * Proceed to wipe the selected disk with a `GPT` partition table on a UEFI system and MBR on a bios system. * Sets up a default 100% used disk with encryption. * Installs a basic instance of Arch Linux *(base base-devel linux linux-firmware btrfs-progs efibootmgr)* - * Installs and configures a bootloader to partition 0. + * Installs and configures a bootloader to partition 0 on uefi. on bios it sets the root to partition 0. * Install additional packages *(nano, wget, git)* * Installs a network-profile called [workstation](https://github.com/Torxed/archinstall/blob/master/profiles/workstation.json) *(more on network profiles in the docs)* diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 1411688c..e38860d3 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -331,6 +331,8 @@ class Installer(): self.log(f'Adding bootloader {bootloader} to {self.boot_partition}', level=LOG_LEVELS.Info) if bootloader == 'systemd-bootctl': + if not hasUEFI(): + raise HardwareIncompatibilityError # TODO: Ideally we would want to check if another config # points towards the same disk and/or partition. # And in which case we should do some clean up. -- cgit v1.2.3-70-g09d2 From 0ba4e631efd5dc02390e6de0a309010be2dc08eb Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Fri, 2 Apr 2021 11:38:42 +0200 Subject: Fixing glitch in variable use after moving to __packages__ definition. --- archinstall/lib/installer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 7f4f4104..2ffcb007 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -56,7 +56,7 @@ class Installer(): 'user' : False # Root counts as a user, if additional users are skipped. } - self.base_packages = base_packages.split(' ') + self.base_packages = base_packages.split(' ') if type(base_packages) is str else base_packages self.post_base_install = [] storage['session'] = self -- cgit v1.2.3-70-g09d2 From 81822e64443e4e43554ae4f891dfc8af79ea48d5 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 4 Apr 2021 15:13:06 +0200 Subject: Added error handling to sys_command's peak function. --- archinstall/lib/general.py | 10 ++++++++-- archinstall/lib/installer.py | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/lib/general.py b/archinstall/lib/general.py index ded2c5a3..41a83651 100644 --- a/archinstall/lib/general.py +++ b/archinstall/lib/general.py @@ -159,10 +159,16 @@ class sys_command():#Thread): 'exit_code': self.exit_code } - def peak(self, output): + def peak(self, output :str): + if type(output) == bytes: + try: + output = output.decode('UTF-8') + except UnicodeDecodeError: + return None + if self.peak_output: from .user_interaction import get_terminal_width - + # Move back to the beginning of the terminal sys.stdout.flush() sys.stdout.write("\033[%dG" % 0) diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index c0323c61..a99bc944 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -137,7 +137,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.mountpoint} {" ".join(packages)}', peak_output=True, **kwargs)).exit_code == 0: return True else: self.log(f'Could not strap in packages: {pacstrap.exit_code}', level=LOG_LEVELS.Info) -- cgit v1.2.3-70-g09d2 From 36bad8254f4097a080c29ef54cf98ee80620639e Mon Sep 17 00:00:00 2001 From: advaithm Date: Wed, 7 Apr 2021 17:21:31 +0530 Subject: added support to automatically add ucode to initrd --- archinstall/lib/installer.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index a99bc944..d9a36859 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -9,7 +9,7 @@ from .mirrors import * from .systemd import Networkd from .output import log, LOG_LEVELS from .storage import storage - +from .hardware import * # Any package that the Installer() is responsible for (optional and the default ones) __packages__ = ["base", "base-devel", "linux", "linux-firmware", "efibootmgr", "nano", "ntp", "iwd"] __base_packages__ = __packages__[:6] @@ -288,7 +288,14 @@ class Installer(): self.pacstrap(self.base_packages) self.helper_flags['base-strapped'] = True #self.genfstab() - + if not isVM(): + vendor = cpuVendor() + if vendor == "AuthenticAMD": + self.base_packages.append("amd-ucode") + elif vendor == "GenuineIntel": + self.base_packages.append("intel-ucode") + else: + self.log("unknown cpu vendor not installing ucode") with open(f"{self.mountpoint}/etc/fstab", "a") as fstab: fstab.write( "\ntmpfs /tmp tmpfs defaults,noatime,mode=1777 0 0\n" @@ -364,13 +371,20 @@ class Installer(): ## For some reason, blkid and /dev/disk/by-uuid are not getting along well. ## And blkid is wrong in terms of LUKS. #UUID = sys_command('blkid -s PARTUUID -o value {drive}{partition_2}'.format(**args)).decode('UTF-8').strip() - # Setup the loader entry with open(f'{self.mountpoint}/boot/loader/entries/{self.init_time}.conf', 'w') as entry: entry.write(f'# Created by: archinstall\n') entry.write(f'# Created on: {self.init_time}\n') entry.write(f'title Arch Linux\n') entry.write(f'linux /vmlinuz-linux\n') + if not isVM(): + vendor = cpuVendor() + if vendor == "AuthenticAMD": + entry.write("initrd /amd-ucode.img") + elif vendor == "GenuineIntel": + entry.write("initrd /amd-ucode.img") + else: + self.log("unknow cpu vendor, not adding ucode to systemd-boot config") entry.write(f'initrd /initramfs-linux.img\n') ## blkid doesn't trigger on loopback devices really well, ## so we'll use the old manual method until we get that sorted out. -- cgit v1.2.3-70-g09d2 From d6a92df7896f850a3c7f36c9d299f15a70ee50f7 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Wed, 7 Apr 2021 14:52:15 +0200 Subject: Reverted a change with newline to open --- archinstall/lib/installer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index c99d0017..e02bbf75 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -153,11 +153,11 @@ class Installer(): self.log(f"Updating {self.mountpoint}/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',newline='\n') as fstab_fh: + with open(f"{self.mountpoint}/etc/fstab", 'ab') as fstab_fh: fstab_fh.write(fstab) if not os.path.isfile(f'{self.mountpoint}/etc/fstab'): - raise RequirementError(f'Could not generate fstab, strapping in packages most likely failed (disk out of space?)\n{b"".join(fstab)}') + raise RequirementError(f'Could not generate fstab, strapping in packages most likely failed (disk out of space?)\n{fstab}') return True -- cgit v1.2.3-70-g09d2 From 8ad22004414f141897bbfe959b4864ffc29070a1 Mon Sep 17 00:00:00 2001 From: nullrequest <30698906+advaithm@users.noreply.github.com> Date: Wed, 7 Apr 2021 21:12:43 +0530 Subject: Fixed typos --- archinstall/lib/installer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index d9a36859..8938b371 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -380,9 +380,9 @@ class Installer(): if not isVM(): vendor = cpuVendor() if vendor == "AuthenticAMD": - entry.write("initrd /amd-ucode.img") + entry.write("initrd /amd-ucode.img\n") elif vendor == "GenuineIntel": - entry.write("initrd /amd-ucode.img") + entry.write("initrd /intel-ucode.img\n") else: self.log("unknow cpu vendor, not adding ucode to systemd-boot config") entry.write(f'initrd /initramfs-linux.img\n') -- cgit v1.2.3-70-g09d2 From 78aba78db7a30a97550e4683d1ed33ced5b86205 Mon Sep 17 00:00:00 2001 From: Dylan Taylor Date: Sat, 10 Apr 2021 12:09:02 -0400 Subject: Fix issue #263 --- archinstall/lib/installer.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index e9343cd1..5523b1e1 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -10,6 +10,8 @@ from .systemd import Networkd from .output import log, LOG_LEVELS from .storage import storage from .hardware import * +from .gfx_drivers import * + # Any package that the Installer() is responsible for (optional and the default ones) __packages__ = ["base", "base-devel", "linux", "linux-firmware", "efibootmgr", "nano", "ntp", "iwd"] __base_packages__ = __packages__[:6] -- cgit v1.2.3-70-g09d2 From 1292c07796b763b926fd5edb21905a663eaef8f0 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 11 Apr 2021 10:20:33 +0200 Subject: Fixed PR #273. Moved the graphic drivers into hardware since they are hardware specific, in the long run maybe we move them into 'drivers' or something. And moved the user interaction from gfx_drivers into user_interactions. And removed the import from installer.py to __init__.py since we don't want to import 'global functions' in extension imports. --- archinstall/lib/hardware.py | 19 +++++++++++ archinstall/lib/installer.py | 1 - archinstall/lib/user_interaction.py | 67 +++++++++++++++++++++++++++++++++++++ profiles/sway.py | 2 +- profiles/xorg.py | 2 +- 5 files changed, 88 insertions(+), 3 deletions(-) (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/lib/hardware.py b/archinstall/lib/hardware.py index 3da333de..047b3491 100644 --- a/archinstall/lib/hardware.py +++ b/archinstall/lib/hardware.py @@ -2,6 +2,25 @@ import os, subprocess, json from .general import sys_command from .networking import list_interfaces, enrichIfaceTypes from typing import Optional + +AVAILABLE_GFX_DRIVERS = { + # Sub-dicts are layer-2 options to be selected + # and lists are a list of packages to be installed + 'AMD / ATI' : { + 'amd' : ['xf86-video-amdgpu'], + 'ati' : ['xf86-video-ati'] + }, + 'intel' : ['xf86-video-intel'], + 'nvidia' : { + 'open source' : ['xf86-video-nouveau'], + 'proprietary' : ['nvidia'] + }, + 'mesa' : ['mesa'], + 'fbdev' : ['xf86-video-fbdev'], + 'vesa' : ['xf86-video-vesa'], + 'vmware' : ['xf86-video-vmware'] +} + def hasWifi()->bool: return 'WIRELESS' in enrichIfaceTypes(list_interfaces().values()).values() diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 5523b1e1..484e7407 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -10,7 +10,6 @@ from .systemd import Networkd from .output import log, LOG_LEVELS from .storage import storage from .hardware import * -from .gfx_drivers import * # Any package that the Installer() is responsible for (optional and the default ones) __packages__ = ["base", "base-devel", "linux", "linux-firmware", "efibootmgr", "nano", "ntp", "iwd"] diff --git a/archinstall/lib/user_interaction.py b/archinstall/lib/user_interaction.py index b94bf3f5..d17691de 100644 --- a/archinstall/lib/user_interaction.py +++ b/archinstall/lib/user_interaction.py @@ -5,6 +5,8 @@ from .locale_helpers import search_keyboard_layout from .output import log, LOG_LEVELS from .storage import storage from .networking import list_interfaces +from .general import sys_command +from .hardware import AVAILABLE_GFX_DRIVERS ## TODO: Some inconsistencies between the selection processes. ## Some return the keys from the options, some the values? @@ -363,3 +365,68 @@ def select_mirror_regions(mirrors, show_top_mirrors=True): return selected_mirrors raise RequirementError("Selecting mirror region require a least one region to be given as an option.") + +def select_driver(options=AVAILABLE_GFX_DRIVERS): + """ + Some what convoluted function, which's job is simple. + Select a graphics driver from a pre-defined set of popular options. + + (The template xorg is for beginner users, not advanced, and should + there for appeal to the general public first and edge cases later) + """ + drivers = sorted(list(options)) + + if len(drivers) >= 1: + for index, driver in enumerate(drivers): + print(f"{index}: {driver}") + + print(' -- The above list are supported graphic card drivers. --') + print(' -- You need to select (and read about) which one you need. --') + + lspci = sys_command(f'/usr/bin/lspci') + for line in lspci.trace_log.split(b'\r\n'): + if b' vga ' in line.lower(): + if b'nvidia' in line.lower(): + print(' ** nvidia card detected, suggested driver: nvidia **') + elif b'amd' in line.lower(): + print(' ** AMD card detected, suggested driver: AMD / ATI **') + + selected_driver = input('Select your graphics card driver: ') + initial_option = selected_driver + + # Disabled search for now, only a few profiles exist anyway + # + #print(' -- You can enter ? or help to search for more drivers --') + #if selected_driver.lower() in ('?', 'help'): + # filter_string = input('Search for layout containing (example: "sv-"): ') + # new_options = search_keyboard_layout(filter_string) + # return select_language(new_options) + if selected_driver.isdigit() and (pos := int(selected_driver)) <= len(drivers)-1: + selected_driver = options[drivers[pos]] + elif selected_driver in options: + selected_driver = options[options.index(selected_driver)] + elif len(selected_driver) == 0: + raise RequirementError("At least one graphics driver is needed to support a graphical environment. Please restart the installer and try again.") + else: + raise RequirementError("Selected driver does not exist.") + + if type(selected_driver) == dict: + driver_options = sorted(list(selected_driver)) + for index, driver_package_group in enumerate(driver_options): + print(f"{index}: {driver_package_group}") + + selected_driver_package_group = input(f'Which driver-type do you want for {initial_option}: ') + if selected_driver_package_group.isdigit() and (pos := int(selected_driver_package_group)) <= len(driver_options)-1: + selected_driver_package_group = selected_driver[driver_options[pos]] + elif selected_driver_package_group in selected_driver: + selected_driver_package_group = selected_driver[selected_driver.index(selected_driver_package_group)] + elif len(selected_driver_package_group) == 0: + raise RequirementError(f"At least one driver package is required for a graphical environment using {selected_driver}. Please restart the installer and try again.") + else: + raise RequirementError(f"Selected driver-type does not exist for {initial_option}.") + + return selected_driver_package_group + + return selected_driver + + raise RequirementError("Selecting drivers require a least one profile to be given as an option.") \ No newline at end of file diff --git a/profiles/sway.py b/profiles/sway.py index 10e30753..f1d2c1f1 100644 --- a/profiles/sway.py +++ b/profiles/sway.py @@ -10,7 +10,7 @@ def _prep_function(*args, **kwargs): for more input before any other installer steps start. """ - __builtins__['_gfx_driver_packages'] = archinstall.lib.gfx_drivers.select_driver() + __builtins__['_gfx_driver_packages'] = archinstall.select_driver() return True diff --git a/profiles/xorg.py b/profiles/xorg.py index 6ee72487..42597a37 100644 --- a/profiles/xorg.py +++ b/profiles/xorg.py @@ -12,7 +12,7 @@ def _prep_function(*args, **kwargs): for more input before any other installer steps start. """ - __builtins__['_gfx_driver_packages'] = archinstall.lib.gfx_drivers.select_driver() + __builtins__['_gfx_driver_packages'] = archinstall.select_driver() # TODO: Add language section and/or merge it with the locale selected # earlier in for instance guided.py installer. -- cgit v1.2.3-70-g09d2 From 459f161cf0432393443272ac5b1aa5fc0cd7fd16 Mon Sep 17 00:00:00 2001 From: Aggam Rahamim Date: Fri, 16 Apr 2021 12:01:20 +0300 Subject: added option to choose kernel --- .gitignore | 2 +- archinstall/lib/installer.py | 3 ++- examples/guided.py | 11 ++++++++++- 3 files changed, 13 insertions(+), 3 deletions(-) (limited to 'archinstall/lib/installer.py') diff --git a/.gitignore b/.gitignore index dc75bed8..246880ba 100644 --- a/.gitignore +++ b/.gitignore @@ -20,4 +20,4 @@ SAFETY_LOCK **/**.network **/**.target **/**.qcow2 -**/test.py +**/test.py \ No newline at end of file diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 758033a7..d21040fa 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -34,7 +34,8 @@ class Installer(): :type hostname: str, optional """ - def __init__(self, target, *, base_packages='base base-devel linux linux-firmware efibootmgr'): + def __init__(self, target, *, base_packages='base base-devel linux-firmware efibootmgr', kernel='linux'): + base_packages += ' '+kernel 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/guided.py b/examples/guided.py index d47a949c..a927d86b 100644 --- a/examples/guided.py +++ b/examples/guided.py @@ -176,6 +176,15 @@ def ask_user_questions(): # packages installed by a profile may depend on audio and something may get installed anyways, not much we can do about that. # we will not try to remove packages post-installation to not have audio, as that may cause multiple issues archinstall.arguments['audio'] = None + + # Ask what kernel user wants: + kernel = input("choose a kernel:\n1. linux\n2. linux-lts\n3. linux-zen") + try: + archinstall.arguments['kernel'] = ['linux', 'linux-lts', 'linux-zen'][int(kernel) - 1] + except: + archinstall.log('invalid kernel selected. defaulting to \'linux\'.') + archinstall.arguments['kernel'] = 'linux' + # Additional packages (with some light weight error handling for invalid package names) if not archinstall.arguments.get('packages', None): @@ -272,7 +281,7 @@ def perform_installation(mountpoint): Only requirement is that the block devices are formatted and setup prior to entering this function. """ - with archinstall.Installer(mountpoint) as installation: + with archinstall.Installer(mountpoint, kernel=archinstall.arguments['kernel']) 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 -- cgit v1.2.3-70-g09d2 From f6fdc119276457d18d5ff1fb30ab9ff06826f576 Mon Sep 17 00:00:00 2001 From: Aggam Rahamim Date: Fri, 16 Apr 2021 13:54:22 +0300 Subject: fixing - letting user choose kernel --- .gitignore | 3 +- archinstall/lib/installer.py | 4 +- "archiso;\n\t\techo Running" | 0 examples/guided.py | 2 +- guided.py | 359 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 364 insertions(+), 4 deletions(-) create mode 100644 "archiso;\n\t\techo Running" create mode 100644 guided.py (limited to 'archinstall/lib/installer.py') diff --git a/.gitignore b/.gitignore index 246880ba..78595b08 100644 --- a/.gitignore +++ b/.gitignore @@ -20,4 +20,5 @@ SAFETY_LOCK **/**.network **/**.target **/**.qcow2 -**/test.py \ No newline at end of file +**/test.py +**/archiso \ No newline at end of file diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index d21040fa..9b0f9c8b 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -34,8 +34,8 @@ class Installer(): :type hostname: str, optional """ - def __init__(self, target, *, base_packages='base base-devel linux-firmware efibootmgr', kernel='linux'): - base_packages += ' '+kernel + def __init__(self, target, *, base_packages=' base base-devel linux-firmware efibootmgr', kernel='linux'): + base_packages = kernel + base_packages 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/archiso;\n\t\techo Running" "b/archiso;\n\t\techo Running" new file mode 100644 index 00000000..e69de29b diff --git a/examples/guided.py b/examples/guided.py index a927d86b..f4ab0b70 100644 --- a/examples/guided.py +++ b/examples/guided.py @@ -178,7 +178,7 @@ def ask_user_questions(): archinstall.arguments['audio'] = None # Ask what kernel user wants: - kernel = input("choose a kernel:\n1. linux\n2. linux-lts\n3. linux-zen") + kernel = input("\n1. linux\n2. linux-lts\n3. linux-zen\nchoose a kernel of the following: ") try: archinstall.arguments['kernel'] = ['linux', 'linux-lts', 'linux-zen'][int(kernel) - 1] except: diff --git a/guided.py b/guided.py new file mode 100644 index 00000000..a927d86b --- /dev/null +++ b/guided.py @@ -0,0 +1,359 @@ +import getpass, time, json, os +import archinstall +from archinstall.lib.hardware import hasUEFI +from archinstall.lib.profiles import Profile + +if hasUEFI() is False: + log("ArchInstall currently only supports machines booted with UEFI. MBR & GRUB support is coming in version 2.2.0!", fg="red", level=archinstall.LOG_LEVELS.Error) + exit(1) + +def ask_user_questions(): + """ + First, we'll ask the user for a bunch of user input. + Not until we're satisfied with what we want to install + will we continue with the actual installation steps. + """ + if not archinstall.arguments.get('keyboard-language', None): + archinstall.arguments['keyboard-language'] = archinstall.select_language(archinstall.list_keyboard_languages()).strip() + + # Before continuing, set the preferred keyboard layout/language in the current terminal. + # This will just help the user with the next following questions. + if len(archinstall.arguments['keyboard-language']): + archinstall.set_keyboard_language(archinstall.arguments['keyboard-language']) + + # Set which region to download packages from during the installation + if not archinstall.arguments.get('mirror-region', None): + archinstall.arguments['mirror-region'] = archinstall.select_mirror_regions(archinstall.list_mirrors()) + else: + selected_region = archinstall.arguments['mirror-region'] + archinstall.arguments['mirror-region'] = {selected_region : archinstall.list_mirrors()[selected_region]} + + + # Ask which harddrive/block-device we will install to + if archinstall.arguments.get('harddrive', None): + 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 + # 3. Check that we support the current partitions + # 2. If so, ask if we should keep them or wipe everything + 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 + # and print those that we don't support. + partition_mountpoints = {} + for partition in archinstall.arguments['harddrive']: + try: + if partition.filesystem_supported(): + archinstall.log(f" {partition}") + partition_mountpoints[partition] = None + except archinstall.UnknownFilesystemFormat as err: + archinstall.log(f" {partition} (Filesystem not supported)", fg='red') + + # We then ask what to do with the partitions. + 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 == 'keep-existing': + archinstall.arguments['harddrive'].keep_partitions = True + + archinstall.log(f" ** You will now select which partitions to use by selecting mount points (inside the installation). **") + archinstall.log(f" ** The root would be a simple / and the boot partition /boot (as all paths are relative inside the installation). **") + while True: + # Select a partition + partition = archinstall.generic_select(partition_mountpoints.keys(), + "Select a partition by number that you want to set a mount-point for (leave blank when done): ") + if not partition: + break + + # Select a mount-point + mountpoint = input(f"Enter a mount-point for {partition}: ").strip(' ') + if len(mountpoint): + + # Get a valid & supported filesystem for the partition: + while 1: + new_filesystem = input(f"Enter a valid filesystem for {partition} (leave blank for {partition.filesystem}): ").strip(' ') + if len(new_filesystem) <= 0: + if partition.encrypted and partition.filesystem == 'crypto_LUKS': + old_password = archinstall.arguments.get('!encryption-password', None) + if not old_password: + old_password = input(f'Enter the old encryption password for {partition}: ') + + if (autodetected_filesystem := partition.detect_inner_filesystem(old_password)): + new_filesystem = autodetected_filesystem + else: + archinstall.log(f"Could not auto-detect the filesystem inside the encrypted volume.", fg='red') + archinstall.log(f"A filesystem must be defined for the unlocked encrypted partition.") + continue + break + + # Since the potentially new filesystem is new + # we have to check if we support it. We can do this by formatting /dev/null with the partitions filesystem. + # There's a nice wrapper for this on the partition object itself that supports a path-override during .format() + try: + partition.format(new_filesystem, path='/dev/null', log_formating=False, allow_formatting=True) + except archinstall.UnknownFilesystemFormat: + archinstall.log(f"Selected filesystem is not supported yet. If you want archinstall to support '{new_filesystem}', please create a issue-ticket suggesting it on github at https://github.com/archlinux/archinstall/issues.") + archinstall.log(f"Until then, please enter another supported filesystem.") + continue + except archinstall.SysCallError: + pass # Expected exception since mkfs. can not format /dev/null. + # But that means our .format() function supported it. + break + + # When we've selected all three criteria, + # We can safely mark the partition for formatting and where to mount it. + # TODO: allow_formatting might be redundant since target_mountpoint should only be + # set if we actually want to format it anyway. + partition.allow_formatting = True + partition.target_mountpoint = mountpoint + # Only overwrite the filesystem definition if we selected one: + if len(new_filesystem): + partition.filesystem = new_filesystem + + archinstall.log('Using existing partition table reported above.') + elif option == 'format-all': + archinstall.arguments['filesystem'] = archinstall.ask_for_main_filesystem_format() + archinstall.arguments['harddrive'].keep_partitions = False + 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() + archinstall.arguments['harddrive'].keep_partitions = False + + # Get disk encryption password (or skip if blank) + 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'] + + # Get the hostname for the machine + if not archinstall.arguments.get('hostname', None): + archinstall.arguments['hostname'] = input('Desired hostname for the installation: ').strip(' ') + + # Ask for a root password (optional, but triggers requirement for super-user if skipped) + if not archinstall.arguments.get('!root-password', None): + archinstall.arguments['!root-password'] = archinstall.get_password(prompt='Enter root password (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): + 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} + + # Ask for archinstall-specific profiles (such as desktop environments etc) + if not archinstall.arguments.get('profile', None): + archinstall.arguments['profile'] = archinstall.select_profile(filter(lambda profile: (Profile(None, profile).is_top_level_profile()), archinstall.list_profiles())) + else: + archinstall.arguments['profile'] = archinstall.list_profiles()[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(): + with archinstall.arguments['profile'].load_instructions(namespace=f"{archinstall.arguments['profile'].namespace}.py") as imported: + if not imported._prep_function(): + archinstall.log( + ' * Profile\'s preparation requirements was not fulfilled.', + fg='red' + ) + exit(1) + + # Ask about audio server selection if one is not already set + if not archinstall.arguments.get('audio', None): + + # only ask for audio server selection on a desktop profile + if str(archinstall.arguments['profile']) == 'Profile(desktop)': + archinstall.arguments['audio'] = archinstall.ask_for_audio_selection() + else: + # packages installed by a profile may depend on audio and something may get installed anyways, not much we can do about that. + # we will not try to remove packages post-installation to not have audio, as that may cause multiple issues + archinstall.arguments['audio'] = None + + # Ask what kernel user wants: + kernel = input("choose a kernel:\n1. linux\n2. linux-lts\n3. linux-zen") + try: + archinstall.arguments['kernel'] = ['linux', 'linux-lts', 'linux-zen'][int(kernel) - 1] + except: + archinstall.log('invalid kernel selected. defaulting to \'linux\'.') + archinstall.arguments['kernel'] = 'linux' + + + # Additional packages (with some light weight error handling for invalid package names) + if not archinstall.arguments.get('packages', None): + print("Packages not part of the desktop environment are not installed by default.") + print("If you desire a web browser, such as firefox or chromium, you may specify it in the following prompt.") + archinstall.arguments['packages'] = [package for package in input('Write additional packages to install (space separated, leave blank to skip): ').split(' ') if len(package)] + + if len(archinstall.arguments['packages']): + # Verify packages that were given + try: + archinstall.log(f"Verifying that additional packages exist (this might take a few seconds)") + archinstall.validate_package_list(archinstall.arguments['packages']) + except archinstall.RequirementError as e: + archinstall.log(e, fg='red') + exit(1) + + # Ask or Call the helper function that asks the user to optionally configure a network. + if not archinstall.arguments.get('nic', None): + archinstall.arguments['nic'] = archinstall.ask_to_configure_network() + if not archinstall.arguments['nic']: + archinstall.log(f"No network configuration was selected. Network is going to be unavailable until configured manually!", fg="yellow") + + if not archinstall.arguments.get('timezone', None): + archinstall.arguments['timezone'] = archinstall.ask_for_a_timezone() + + +def perform_installation_steps(): + print() + print('This is your chosen configuration:') + archinstall.log("-- Guided template chosen (with below config) --", level=archinstall.LOG_LEVELS.Debug) + archinstall.log(json.dumps(archinstall.arguments, indent=4, sort_keys=True, cls=archinstall.JSON), level=archinstall.LOG_LEVELS.Info) + print() + + input('Press Enter to continue.') + + """ + Issue a final warning before we continue with something un-revertable. + We mention the drive one last time, and count from 5 to 0. + """ + + 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: + 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: + 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(mountpoint, kernel=archinstall.arguments['kernel']) 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 + # We need to wait for it before we continue since we opted in to use a custom mirror/region. + installation.log(f'Waiting for automatic mirror selection (reflector) to complete.', level=archinstall.LOG_LEVELS.Info) + while archinstall.service_state('reflector') not in ('dead', 'failed'): + time.sleep(1) + + # Set mirrors used by pacstrap (outside of installation) + if archinstall.arguments.get('mirror-region', None): + archinstall.use_mirrors(archinstall.arguments['mirror-region']) # Set the mirrors for the live medium + + if installation.minimal_installation(): + installation.set_hostname(archinstall.arguments['hostname']) + + # Configure the selected mirrors in the installation + if archinstall.arguments.get('mirror-region', None): + 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 + # Perform a copy of the config + if archinstall.arguments.get('nic', {}) == 'Copy ISO network configuration to installation': + installation.copy_ISO_network_config(enable_services=True) # Sources the ISO network configuration to the install medium. + elif archinstall.arguments.get('nic', {}).get('NetworkManager',False): + installation.add_additional_packages("networkmanager") + installation.enable_service('NetworkManager.service') + # Otherwise, if a interface was selected, configure that interface + elif archinstall.arguments.get('nic', {}): + installation.configure_nic(**archinstall.arguments.get('nic', {})) + installation.enable_service('systemd-networkd') + installation.enable_service('systemd-resolved') + + if archinstall.arguments.get('audio', None) != None: + installation.log(f"This audio server will be used: {archinstall.arguments.get('audio', None)}", level=archinstall.LOG_LEVELS.Info) + if archinstall.arguments.get('audio', None) == 'pipewire': + print('Installing pipewire ...') + installation.add_additional_packages(["pipewire", "pipewire-alsa", "pipewire-jack", "pipewire-media-session", "pipewire-pulse", "gst-plugin-pipewire", "libpulse"]) + elif archinstall.arguments.get('audio', None) == 'pulseaudio': + print('Installing pulseaudio ...') + installation.add_additional_packages("pulseaudio") + else: + installation.log("No audio server will be installed.", level=archinstall.LOG_LEVELS.Info) + + if archinstall.arguments.get('packages', None) and archinstall.arguments.get('packages', None)[0] != '': + installation.add_additional_packages(archinstall.arguments.get('packages', None)) + + if archinstall.arguments.get('profile', None): + installation.install_profile(archinstall.arguments.get('profile', None)) + + for user, user_info in archinstall.arguments.get('users', {}).items(): + installation.user_create(user, user_info["!password"], sudo=False) + + for superuser, user_info in archinstall.arguments.get('superusers', {}).items(): + installation.user_create(superuser, user_info["!password"], sudo=True) + + if (timezone := archinstall.arguments.get('timezone', None)): + installation.set_timezone(timezone) + + if (root_pw := archinstall.arguments.get('!root-password', None)) and len(root_pw): + installation.user_set_pw('root', root_pw) + + installation.log("For post-installation tips, see https://wiki.archlinux.org/index.php/Installation_guide#Post-installation", fg="yellow") + choice = input("Would you like to chroot into the newly created installation and perform post-installation configuration? [Y/n] ") + if choice.lower() in ("y", ""): + try: + installation.drop_to_shell() + except: + pass + +ask_user_questions() +perform_installation_steps() + -- cgit v1.2.3-70-g09d2 From 81b0fa1792716b9a5ec889003dba334d3987918b Mon Sep 17 00:00:00 2001 From: Aggam Rahamim Date: Fri, 16 Apr 2021 14:31:59 +0300 Subject: fixed mkinitcpio --- archinstall/lib/installer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 9b0f9c8b..7f6311c9 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -323,7 +323,7 @@ class Installer(): 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') + sys_command(f'/usr/bin/arch-chroot {self.target} mkinitcpio -P') self.helper_flags['base'] = True -- cgit v1.2.3-70-g09d2 From 77894df51c581d26c958f07524e576d3bc118efd Mon Sep 17 00:00:00 2001 From: Malccolm Haak Date: Sat, 17 Apr 2021 14:37:14 +1000 Subject: Whitespace needs to be tabs. Added test for UEFI, if not found add grub-install to pacstrap install --- archinstall/lib/installer.py | 20 +++++++++++--------- examples/guided.py | 8 ++++---- 2 files changed, 15 insertions(+), 13 deletions(-) (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index a99bc944..70ff86f2 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -22,7 +22,7 @@ class Installer(): :param partition: Requires a partition as the first argument, this is so that the installer can mount to `mountpoint` and strap packages there. :type partition: class:`archinstall.Partition` - + :param boot_partition: There's two reasons for needing a boot partition argument, The first being so that `mkinitcpio` can place the `vmlinuz` kernel at the right place during the `pacstrap` or `linux` and the base packages for a minimal installation. @@ -33,7 +33,7 @@ class Installer(): :param profile: A profile to install, this is optional and can be called later manually. This just simplifies the process by not having to call :py:func:`~archinstall.Installer.install_profile` later on. :type profile: str, optional - + :param hostname: The given /etc/hostname for the machine. :type hostname: str, optional @@ -118,7 +118,7 @@ class Installer(): if not os.path.isdir(f"{self.mountpoint}/{os.path.dirname(absolute_logfile)}"): os.makedirs(f"{self.mountpoint}/{os.path.dirname(absolute_logfile)}") - + shutil.copy2(absolute_logfile, f"{self.mountpoint}/{absolute_logfile}") return True @@ -126,7 +126,7 @@ class Installer(): 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}') - + partition.mount(f'{self.mountpoint}{mountpoint}') def post_install_check(self, *args, **kwargs): @@ -149,14 +149,14 @@ class Installer(): def genfstab(self, flags='-pU'): self.log(f"Updating {self.mountpoint}/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_fh.write(fstab) if not os.path.isfile(f'{self.mountpoint}/etc/fstab'): raise RequirementError(f'Could not generate fstab, strapping in packages most likely failed (disk out of space?)\n{o}') - + return True def set_hostname(self, hostname=None, *args, **kwargs): @@ -219,7 +219,7 @@ class Installer(): network["DNS"] = dns conf = Networkd(Match={"Name": nic}, Network=network) - + with open(f"{self.mountpoint}/etc/systemd/network/10-{nic}.network", "a") as netconf: netconf.write(str(conf)) @@ -234,7 +234,7 @@ class Installer(): # If we haven't installed the base yet (function called pre-maturely) if self.helper_flags.get('base', False) is False: self.base_packages.append('iwd') - # This function will be called after minimal_installation() + # This function will be called after minimal_installation() # as a hook for post-installs. This hook is only needed if # base is not installed yet. def post_install_enable_iwd_service(*args, **kwargs): @@ -285,6 +285,8 @@ class Installer(): self.base_packages.append('xfsprogs') if self.partition.filesystem == 'f2fs': self.base_packages.append('f2fs-tools') + if not(hasUEFI()): + self.base_packages.append('grub-install') self.pacstrap(self.base_packages) self.helper_flags['base-strapped'] = True #self.genfstab() @@ -353,7 +355,7 @@ class Installer(): f"default {self.init_time}", f"timeout 5" ] - + with open(f'{self.mountpoint}/boot/loader/loader.conf', 'w') as loader: for line in loader_data: if line[:8] == 'default ': diff --git a/examples/guided.py b/examples/guided.py index dfc2da07..38d5d653 100644 --- a/examples/guided.py +++ b/examples/guided.py @@ -314,10 +314,10 @@ def perform_installation(device, boot_partition, language, mirrors): if installation.minimal_installation(): installation.set_mirrors(mirrors) # Set the mirrors in the installation medium installation.set_keyboard_language(language) - if hasUEFI(): - installation.add_bootloader() - else: - installation.add_bootloader(bootloder='grub-install') + if hasUEFI(): + installation.add_bootloader() + else: + installation.add_bootloader(bootloder='grub-install') # If user selected to copy the current ISO network configuration -- cgit v1.2.3-70-g09d2 From e32dbfbd108e9b8598e148a0873d20384c573034 Mon Sep 17 00:00:00 2001 From: Malccolm Haak Date: Sat, 17 Apr 2021 14:38:00 +1000 Subject: Package called grub not grub-install --- archinstall/lib/installer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 70ff86f2..2122ebd9 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -286,7 +286,7 @@ class Installer(): if self.partition.filesystem == 'f2fs': self.base_packages.append('f2fs-tools') if not(hasUEFI()): - self.base_packages.append('grub-install') + self.base_packages.append('grub') self.pacstrap(self.base_packages) self.helper_flags['base-strapped'] = True #self.genfstab() -- cgit v1.2.3-70-g09d2 From adeae68123314742dd76e2e231400c5cf6237c1e Mon Sep 17 00:00:00 2001 From: advaithm Date: Tue, 20 Apr 2021 19:58:23 +0530 Subject: reworked how we remove efimanager and add grub --- archinstall/lib/installer.py | 3 ++- examples/guided.py | 7 ++----- 2 files changed, 4 insertions(+), 6 deletions(-) (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 2f90560f..4cf658c1 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -48,7 +48,8 @@ class Installer(): 'base' : False, 'bootloader' : False } - + if hasUEFI() == False: + base_packages.replace(" efibootmgr","") self.base_packages = base_packages.split(' ') if type(base_packages) is str else base_packages self.post_base_install = [] diff --git a/examples/guided.py b/examples/guided.py index 02a39e8c..8308d22c 100644 --- a/examples/guided.py +++ b/examples/guided.py @@ -300,18 +300,15 @@ def perform_installation(mountpoint): installation.log(f'Waiting for automatic mirror selection (reflector) to complete.', level=archinstall.LOG_LEVELS.Info) while archinstall.service_state('reflector') not in ('dead', 'failed'): time.sleep(1) - # Set mirrors used by pacstrap (outside of installation) if archinstall.arguments.get('mirror-region', None): archinstall.use_mirrors(archinstall.arguments['mirror-region']) # Set the mirrors for the live medium - if hasUEFI()==False: - installation.base_packages.pop(installation.base_packages.index("efibootmgr"))# if we aren't on a uefi system why install efibootmgr - if archinstall.arguments["bootloader"] == "grub-install": - installation.base_packages = installation.base_packages.append("grub") if installation.minimal_installation(): installation.set_hostname(archinstall.arguments['hostname']) if archinstall.arguments['mirror-region'].get("mirrors",{})!= None: installation.set_mirrors(archinstall.arguments['mirror-region']) # Set the mirrors in the installation medium + if archinstall.arguments["bootloader"]=="grub-install": + installation.add_additional_packages("grub") installation.set_keyboard_language(archinstall.arguments['keyboard-language']) installation.add_bootloader(archinstall.arguments["bootloader"]) -- cgit v1.2.3-70-g09d2 From 64a785e0ec302daca8372205106a0990574bda9e Mon Sep 17 00:00:00 2001 From: advaithm Date: Tue, 20 Apr 2021 20:01:15 +0530 Subject: reworked how we remove efimanager --- archinstall/lib/installer.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 4cf658c1..10532296 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -48,9 +48,10 @@ class Installer(): 'base' : False, 'bootloader' : False } - if hasUEFI() == False: - base_packages.replace(" efibootmgr","") + self.base_packages = base_packages.split(' ') if type(base_packages) is str else base_packages + if hasUEFI() == False: + self.base_packages.pop(self.base_packages.index("efibootmgr")) self.post_base_install = [] storage['session'] = self -- cgit v1.2.3-70-g09d2 From 4a9f56ed2d8dba0e116467857305d1992761588c Mon Sep 17 00:00:00 2001 From: advaithm Date: Tue, 20 Apr 2021 20:26:19 +0530 Subject: fixed shell command in add bootloader --- archinstall/lib/installer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 10532296..e74501c6 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -429,7 +429,7 @@ class Installer(): o = b''.join(sys_command(f'/usr/bin/arch-chroot {self.target} grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB')) sys_command('/usr/bin/arch-chroot grub-mkconfig -o /boot/grub/grub.cfg') else: - root_device = subprocess.check_output(f'basename "$(readlink -f "/sys/class/block/{root_partition.path.strip("/dev/")}/..")', shell=True).decode().strip() + 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(sys_command(f'/usr/bin/arch-chroot {self.target} grub-install --target=--target=i386-pc /dev/{root_device}')) -- cgit v1.2.3-70-g09d2 From b4312ab95df579e395da55d8018934a492812faf Mon Sep 17 00:00:00 2001 From: advaithm Date: Tue, 20 Apr 2021 20:46:49 +0530 Subject: removed unnessacry --target --- archinstall/lib/installer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index e74501c6..9b56ad92 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -432,7 +432,7 @@ class Installer(): 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(sys_command(f'/usr/bin/arch-chroot {self.target} grub-install --target=--target=i386-pc /dev/{root_device}')) + o = b''.join(sys_command(f'/usr/bin/arch-chroot {self.target} grub-install --target=i386-pc /dev/{root_device}')) sys_command('/usr/bin/arch-chroot grub-mkconfig -o /boot/grub/grub.cfg') else: raise RequirementError(f"Unknown (or not yet implemented) bootloader added to add_bootloader(): {bootloader}") -- cgit v1.2.3-70-g09d2 From e2444de5a218645b880707d9d1adc3b0387474b2 Mon Sep 17 00:00:00 2001 From: advaithm Date: Tue, 20 Apr 2021 21:06:31 +0530 Subject: added /mnt to grubcfg genration --- archinstall/lib/installer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 9b56ad92..e81e4c45 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -427,13 +427,13 @@ class Installer(): elif bootloader == "grub-install": if hasUEFI(): o = b''.join(sys_command(f'/usr/bin/arch-chroot {self.target} grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB')) - sys_command('/usr/bin/arch-chroot grub-mkconfig -o /boot/grub/grub.cfg') + sys_command('/usr/bin/arch-chroot /mnt grub-mkconfig -o /boot/grub/grub.cfg') 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(sys_command(f'/usr/bin/arch-chroot {self.target} grub-install --target=i386-pc /dev/{root_device}')) - sys_command('/usr/bin/arch-chroot grub-mkconfig -o /boot/grub/grub.cfg') + sys_command('/usr/bin/arch-chroot /mnt grub-mkconfig -o /boot/grub/grub.cfg') else: raise RequirementError(f"Unknown (or not yet implemented) bootloader added to add_bootloader(): {bootloader}") -- cgit v1.2.3-70-g09d2 From 85a8215eb7fbe7e5a73c6cf557701e319cf4a089 Mon Sep 17 00:00:00 2001 From: advaithm Date: Tue, 20 Apr 2021 21:06:57 +0530 Subject: fixed some weird grammer --- archinstall/lib/installer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index e81e4c45..7b1a673d 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -435,7 +435,7 @@ class Installer(): o = b''.join(sys_command(f'/usr/bin/arch-chroot {self.target} grub-install --target=i386-pc /dev/{root_device}')) sys_command('/usr/bin/arch-chroot /mnt grub-mkconfig -o /boot/grub/grub.cfg') else: - raise RequirementError(f"Unknown (or not yet implemented) bootloader added to add_bootloader(): {bootloader}") + raise RequirementError(f"Unknown (or not yet implemented) bootloader requested: {bootloader}") def add_additional_packages(self, *packages): return self.pacstrap(*packages) -- cgit v1.2.3-70-g09d2 From a02c35920d7d2f984e1e962c3c7a7556df148e13 Mon Sep 17 00:00:00 2001 From: advaithm Date: Tue, 20 Apr 2021 21:21:17 +0530 Subject: added return true --- archinstall/lib/installer.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 7b1a673d..10a9ad4b 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -428,12 +428,14 @@ class Installer(): if hasUEFI(): o = b''.join(sys_command(f'/usr/bin/arch-chroot {self.target} grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB')) sys_command('/usr/bin/arch-chroot /mnt grub-mkconfig -o /boot/grub/grub.cfg') + 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(sys_command(f'/usr/bin/arch-chroot {self.target} grub-install --target=i386-pc /dev/{root_device}')) sys_command('/usr/bin/arch-chroot /mnt grub-mkconfig -o /boot/grub/grub.cfg') + return True else: raise RequirementError(f"Unknown (or not yet implemented) bootloader requested: {bootloader}") -- cgit v1.2.3-70-g09d2 From 63a94a57708bdfb4cdfde0c24af2d324ba191beb Mon Sep 17 00:00:00 2001 From: advaithm Date: Tue, 20 Apr 2021 22:09:27 +0530 Subject: add efibootmgr only on uefi systems --- archinstall/lib/installer.py | 8 +++++--- archinstall/lib/user_interaction.py | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 10a9ad4b..f6c891a3 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -39,7 +39,7 @@ class Installer(): :type hostname: str, optional """ - def __init__(self, target, *, base_packages='base base-devel linux linux-firmware efibootmgr'): + def __init__(self, target, *, base_packages='base base-devel linux linux-firmware'): self.target = target self.init_time = time.strftime('%Y-%m-%d_%H-%M-%S') self.milliseconds = int(str(time.time()).split('.')[1]) @@ -50,8 +50,10 @@ class Installer(): } self.base_packages = base_packages.split(' ') if type(base_packages) is str else base_packages - if hasUEFI() == False: - self.base_packages.pop(self.base_packages.index("efibootmgr")) + if hasUEFI(): + self.base_packages.append("efibootmgr") + else: + self.base_packages.append("grub") self.post_base_install = [] storage['session'] = self diff --git a/archinstall/lib/user_interaction.py b/archinstall/lib/user_interaction.py index 175079ee..70ff7a1e 100644 --- a/archinstall/lib/user_interaction.py +++ b/archinstall/lib/user_interaction.py @@ -149,7 +149,7 @@ def ask_for_bootloader() -> str: if hasUEFI()==False: bootloader="grub-install" else: - bootloader_choice = input("Would you like to use GRUB as a bootloader instead off systemd-boot [y/N] ").lower() + bootloader_choice = input("Would you like to use GRUB as a bootloader instead of systemd-boot? [y/N] ").lower() if bootloader_choice == "y": bootloader="grub-install" return bootloader -- cgit v1.2.3-70-g09d2 From 5c9859d316b8064949370c03745cfd99e0d67670 Mon Sep 17 00:00:00 2001 From: Aggam Rahamim Date: Sun, 25 Apr 2021 14:55:39 +0300 Subject: having ability to use multiple kernels --- archinstall/lib/installer.py | 4 ++-- archinstall/lib/user_interaction.py | 4 +++- examples/guided.py | 19 +++++++++++-------- 3 files changed, 16 insertions(+), 11 deletions(-) (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 7f6311c9..d952a6ed 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -34,8 +34,8 @@ class Installer(): :type hostname: str, optional """ - def __init__(self, target, *, base_packages=' base base-devel linux-firmware efibootmgr', kernel='linux'): - base_packages = kernel + base_packages + def __init__(self, target, *, base_packages='base base-devel linux-firmware efibootmgr ', kernels='linux'): + base_packages = base_packages + kernels.replace(',', ' ') 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/archinstall/lib/user_interaction.py b/archinstall/lib/user_interaction.py index 99cf6274..3da24684 100644 --- a/archinstall/lib/user_interaction.py +++ b/archinstall/lib/user_interaction.py @@ -218,6 +218,8 @@ def generic_select(options, input_text="Select one of the above by index or abso 1: first 2: second 3: third option + + it will return the selected text. """ if type(options) == dict: options = list(options) @@ -263,7 +265,7 @@ def select_disk(dict_o_disks): elif drive.isdigit(): drive = int(drive) if drive >= len(drives): - raise DiskError(f'Selected option "{drive}" is out of range') + raise Dis1ror(f'Selected option "{drive}" is out of range') drive = dict_o_disks[drives[drive]] elif drive in dict_o_disks: drive = dict_o_disks[drive] diff --git a/examples/guided.py b/examples/guided.py index e6abe872..ee7b63d9 100644 --- a/examples/guided.py +++ b/examples/guided.py @@ -2,6 +2,7 @@ import getpass, time, json, os import archinstall from archinstall.lib.hardware import hasUEFI from archinstall.lib.profiles import Profile +from archinstall.lib.user_interaction import generic_select if hasUEFI() is False: log("ArchInstall currently only supports machines booted with UEFI. MBR & GRUB support is coming in version 2.2.0!", fg="red", level=archinstall.LOG_LEVELS.Error) @@ -168,7 +169,6 @@ def ask_user_questions(): # Ask about audio server selection if one is not already set if not archinstall.arguments.get('audio', None): - # only ask for audio server selection on a desktop profile if str(archinstall.arguments['profile']) == 'Profile(desktop)': archinstall.arguments['audio'] = archinstall.ask_for_audio_selection() @@ -178,12 +178,15 @@ def ask_user_questions(): archinstall.arguments['audio'] = None # Ask what kernel user wants: - kernel = input("1. linux\n2. linux-lts\n3. linux-zen\nchoose a kernel of the following: ") - try: - archinstall.arguments['kernel'] = ['linux', 'linux-lts', 'linux-zen'][int(kernel) - 1] - except: - archinstall.log('invalid kernel selected. defaulting to \'linux\'.') - archinstall.arguments['kernel'] = 'linux' + while True: + kernel = generic_select(["linux", "linux-lts", "linux-zen", "continue"], "choose a kernel:") + if (archinstall.arguments['kernels'] == None or archinstall.arguments['kernels'] == ""): + archinstall.arguments['kernels'] = kernel + else: + if (kernel == "continue"): + break + archinstall.arguments['kernels'] += "," + kernel + # Additional packages (with some light weight error handling for invalid package names) @@ -281,7 +284,7 @@ def perform_installation(mountpoint): Only requirement is that the block devices are formatted and setup prior to entering this function. """ - with archinstall.Installer(mountpoint, kernel=archinstall.arguments['kernel']) as installation: + with archinstall.Installer(mountpoint, kernels=archinstall.arguments['kernels']) 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 -- cgit v1.2.3-70-g09d2 From 090b98b8307fd924882e78b69df9227b4621ec6b Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Tue, 27 Apr 2021 14:43:17 +0000 Subject: Moving away from custom log levels, to something that's well defined. (#360) * Moving away from custom log levels, to something that's well defined. * Added backward compability to log() as well. * Added an option to force log messages out on screen even if the level is below the log level threashold. * Added force log messages when wrong notation is used. * Added some more length to the deprecated message * Swapped all log levels to use logging. instead. Co-authored-by: Anton Hvornum --- archinstall/lib/disk.py | 42 +++++++++++------------ archinstall/lib/general.py | 30 ++++++++--------- archinstall/lib/installer.py | 55 +++++++++++++++--------------- archinstall/lib/luks.py | 11 +++--- archinstall/lib/mirrors.py | 6 ++-- archinstall/lib/output.py | 67 +++++++++++++++++++++++++++---------- archinstall/lib/profiles.py | 6 ++-- archinstall/lib/user_interaction.py | 12 +++---- examples/guided.py | 14 ++++---- 9 files changed, 139 insertions(+), 104 deletions(-) (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index 67c2bdcd..8c7c6818 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -1,9 +1,9 @@ import glob, re, os, json, time, hashlib -import pathlib, traceback +import pathlib, traceback, logging from collections import OrderedDict from .exceptions import DiskError from .general import * -from .output import log, LOG_LEVELS +from .output import log from .storage import storage from .hardware import hasUEFI @@ -88,7 +88,7 @@ class BlockDevice(): raise DiskError(f'A crypt device ({self.path}) without a parent kernel device name.') return f"/dev/{self.info['pkname']}" else: - log(f"Unknown blockdevice type for {self.path}: {self.info['type']}", level=LOG_LEVELS.Debug) + log(f"Unknown blockdevice type for {self.path}: {self.info['type']}", level=logging.DEBUG) # if not stat.S_ISBLK(os.stat(full_path).st_mode): # raise DiskError(f'Selected disk "{full_path}" is not a block device.') @@ -129,7 +129,7 @@ class BlockDevice(): @property def uuid(self): - log(f'BlockDevice().uuid is untested!', level=LOG_LEVELS.Warning, fg='yellow') + log(f'BlockDevice().uuid is untested!', level=logging.WARNING, fg='yellow') """ Returns the disk UUID as returned by lsblk. This is more reliable than relying on /dev/disk/by-partuuid as @@ -222,8 +222,8 @@ class Partition(): @encrypted.setter def encrypted(self, value :bool): if value: - log(f'Marking {self} as encrypted: {value}', level=LOG_LEVELS.Debug) - log(f"Callstrack when marking the partition: {''.join(traceback.format_stack())}", level=LOG_LEVELS.Debug) + log(f'Marking {self} as encrypted: {value}', level=logging.DEBUG) + log(f"Callstrack when marking the partition: {''.join(traceback.format_stack())}", level=logging.DEBUG) self._encrypted = value @@ -240,7 +240,7 @@ class Partition(): return self.path def detect_inner_filesystem(self, password): - log(f'Trying to detect inner filesystem format on {self} (This might take a while)', level=LOG_LEVELS.Info) + log(f'Trying to detect inner filesystem format on {self} (This might take a while)', level=logging.INFO) from .luks import luks2 try: @@ -269,16 +269,16 @@ class Partition(): def safe_to_format(self): if self.allow_formatting is False: - log(f"Partition {self} is not marked for formatting.", level=LOG_LEVELS.Debug) + log(f"Partition {self} is not marked for formatting.", level=logging.DEBUG) return False elif self.target_mountpoint == '/boot': try: if self.has_content(): - log(f"Partition {self} is a boot partition and has content inside.", level=LOG_LEVELS.Debug) + log(f"Partition {self} is a boot partition and has content inside.", level=logging.DEBUG) return False except SysCallError as err: - log(err.message, LOG_LEVELS.Debug) - log(f"Partition {self} was identified as /boot but we could not mount to check for content, continuing!", level=LOG_LEVELS.Debug) + log(err.message, logging.DEBUG) + log(f"Partition {self} was identified as /boot but we could not mount to check for content, continuing!", level=logging.DEBUG) pass return True @@ -293,7 +293,7 @@ class Partition(): raise DiskError(f"Attempting to encrypt a partition that was not marked for encryption: {self}") if not self.safe_to_format(): - log(f"Partition {self} was marked as protected but encrypt() was called on it!", level=LOG_LEVELS.Error, fg="red") + log(f"Partition {self} was marked as protected but encrypt() was called on it!", level=logging.ERROR, fg="red") return False handle = luks2(self, None, None) @@ -321,7 +321,7 @@ class Partition(): raise PermissionError(f"{self} is not formatable either because instance is locked ({self.allow_formatting}) or a blocking flag was given ({allow_formatting})") if log_formatting: - log(f'Formatting {path} -> {filesystem}', level=LOG_LEVELS.Info) + log(f'Formatting {path} -> {filesystem}', level=logging.INFO) if filesystem == 'btrfs': o = b''.join(sys_command(f'/usr/bin/mkfs.btrfs -f {path}')) @@ -376,7 +376,7 @@ class Partition(): def mount(self, target, fs=None, options=''): if not self.mountpoint: - log(f'Mounting {self} to {target}', level=LOG_LEVELS.Info) + log(f'Mounting {self} to {target}', level=logging.INFO) if not fs: if not self.filesystem: raise DiskError(f'Need to format (or define) the filesystem on {self} before mounting.') fs = self.filesystem @@ -434,7 +434,7 @@ class Filesystem(): def __enter__(self, *args, **kwargs): if self.blockdevice.keep_partitions is False: - log(f'Wiping {self.blockdevice} by using partition format {self.mode}', level=LOG_LEVELS.Debug) + log(f'Wiping {self.blockdevice} by using partition format {self.mode}', level=logging.DEBUG) if self.mode == GPT: if self.raw_parted(f'{self.blockdevice.device} mklabel gpt').exit_code == 0: self.blockdevice.flush_cache() @@ -451,7 +451,7 @@ class Filesystem(): # TODO: partition_table_type is hardcoded to GPT at the moment. This has to be changed. elif self.mode == self.blockdevice.partition_table_type: - log(f'Kept partition format {self.mode} for {self.blockdevice}', level=LOG_LEVELS.Debug) + log(f'Kept partition format {self.mode} for {self.blockdevice}', level=logging.DEBUG) else: raise DiskError(f'The selected partition table format {self.mode} does not match that of {self.blockdevice}.') @@ -474,7 +474,7 @@ class Filesystem(): def raw_parted(self, string:str): x = sys_command(f'/usr/bin/parted -s {string}') - log(f"'parted -s {string}' returned: {b''.join(x)}", level=LOG_LEVELS.Debug) + log(f"'parted -s {string}' returned: {b''.join(x)}", level=logging.DEBUG) return x def parted(self, string:str): @@ -487,7 +487,7 @@ class Filesystem(): return self.raw_parted(string).exit_code def use_entire_disk(self, root_filesystem_type='ext4'): - log(f"Using and formatting the entire {self.blockdevice}.", level=LOG_LEVELS.Debug) + log(f"Using and formatting the entire {self.blockdevice}.", level=logging.DEBUG) if hasUEFI(): self.add_partition('primary', start='1MiB', end='513MiB', format='fat32') self.set_name(0, 'EFI') @@ -499,7 +499,7 @@ class Filesystem(): self.blockdevice.partition[0].filesystem = 'vfat' self.blockdevice.partition[1].filesystem = root_filesystem_type - log(f"Set the root partition {self.blockdevice.partition[1]} to use filesystem {root_filesystem_type}.", level=LOG_LEVELS.Debug) + 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 = '/' @@ -510,12 +510,12 @@ class Filesystem(): #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=LOG_LEVELS.Debug) + 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.blockdevice.partition[0].allow_formatting = True def add_partition(self, type, start, end, format=None): - log(f'Adding partition to {self.blockdevice}', level=LOG_LEVELS.Info) + log(f'Adding partition to {self.blockdevice}', level=logging.INFO) previous_partitions = self.blockdevice.partitions if self.mode == MBR: diff --git a/archinstall/lib/general.py b/archinstall/lib/general.py index dc0f018a..eb0c5d14 100644 --- a/archinstall/lib/general.py +++ b/archinstall/lib/general.py @@ -1,10 +1,10 @@ import os, json, hashlib, shlex, sys -import time, pty +import time, pty, logging from datetime import datetime, date from subprocess import Popen, STDOUT, PIPE, check_output from select import epoll, EPOLLIN, EPOLLHUP from .exceptions import * -from .output import log, LOG_LEVELS +from .output import log def gen_uid(entropy_length=256): return hashlib.sha512(os.urandom(entropy_length)).hexdigest() @@ -84,7 +84,7 @@ class sys_command():#Thread): self.log = kwargs.get('log', log) if kwargs['emulate']: - self.log(f"Starting command '{cmd}' in emulation mode.", level=LOG_LEVELS.Debug) + self.log(f"Starting command '{cmd}' in emulation mode.", level=logging.DEBUG) if type(cmd) is list: # if we get a list of arguments @@ -204,7 +204,7 @@ class sys_command():#Thread): os.execve(self.cmd[0], self.cmd, {**os.environ, **self.environment_vars}) except FileNotFoundError: self.status = 'done' - self.log(f"{self.cmd[0]} does not exist.", level=LOG_LEVELS.Debug) + self.log(f"{self.cmd[0]} does not exist.", level=logging.DEBUG) self.exit_code = 1 return False @@ -214,8 +214,8 @@ class sys_command():#Thread): poller.register(child_fd, EPOLLIN | EPOLLHUP) if 'events' in self.kwargs and 'debug' in self.kwargs: - self.log(f'[D] Using triggers for command: {self.cmd}', level=LOG_LEVELS.Debug) - self.log(json.dumps(self.kwargs['events']), level=LOG_LEVELS.Debug) + self.log(f'[D] Using triggers for command: {self.cmd}', level=logging.DEBUG) + self.log(json.dumps(self.kwargs['events']), level=logging.DEBUG) alive = True last_trigger_pos = 0 @@ -230,7 +230,7 @@ class sys_command():#Thread): break if 'debug' in self.kwargs and self.kwargs['debug'] and len(output): - self.log(self.cmd, 'gave:', output.decode('UTF-8'), level=LOG_LEVELS.Debug) + self.log(self.cmd, 'gave:', output.decode('UTF-8'), level=logging.DEBUG) if 'on_output' in self.kwargs: self.kwargs['on_output'](self.kwargs['worker'], output) @@ -251,8 +251,8 @@ class sys_command():#Thread): trigger_pos = self.trace_log[last_trigger_pos:].lower().find(trigger.lower()) if 'debug' in self.kwargs and self.kwargs['debug']: - self.log(f"Writing to subprocess {self.cmd[0]}: {self.kwargs['events'][trigger].decode('UTF-8')}", level=LOG_LEVELS.Debug) - self.log(f"Writing to subprocess {self.cmd[0]}: {self.kwargs['events'][trigger].decode('UTF-8')}", level=LOG_LEVELS.Debug) + self.log(f"Writing to subprocess {self.cmd[0]}: {self.kwargs['events'][trigger].decode('UTF-8')}", level=logging.DEBUG) + self.log(f"Writing to subprocess {self.cmd[0]}: {self.kwargs['events'][trigger].decode('UTF-8')}", level=logging.DEBUG) last_trigger_pos = trigger_pos os.write(child_fd, self.kwargs['events'][trigger]) @@ -266,18 +266,18 @@ class sys_command():#Thread): ## Adding a exit trigger: if len(self.kwargs['events']) == 0: if 'debug' in self.kwargs and self.kwargs['debug']: - self.log(f"Waiting for last command {self.cmd[0]} to finish.", level=LOG_LEVELS.Debug) + self.log(f"Waiting for last command {self.cmd[0]} to finish.", level=logging.DEBUG) if bytes(f']$'.lower(), 'UTF-8') in self.trace_log[0-len(f']$')-5:].lower(): if 'debug' in self.kwargs and self.kwargs['debug']: - self.log(f"{self.cmd[0]} has finished.", level=LOG_LEVELS.Debug) + self.log(f"{self.cmd[0]} has finished.", level=logging.DEBUG) alive = False break self.status = 'done' if 'debug' in self.kwargs and self.kwargs['debug']: - self.log(f"{self.cmd[0]} waiting for exit code.", level=LOG_LEVELS.Debug) + self.log(f"{self.cmd[0]} waiting for exit code.", level=logging.DEBUG) if not self.kwargs['emulate']: try: @@ -291,14 +291,14 @@ class sys_command():#Thread): self.exit_code = 0 if 'debug' in self.kwargs and self.kwargs['debug']: - self.log(f"{self.cmd[0]} got exit code: {self.exit_code}", level=LOG_LEVELS.Debug) + self.log(f"{self.cmd[0]} got exit code: {self.exit_code}", level=logging.DEBUG) if 'ignore_errors' in self.kwargs: self.exit_code = 0 if self.exit_code != 0 and not self.kwargs['suppress_errors']: - #self.log(self.trace_log.decode('UTF-8'), level=LOG_LEVELS.Debug) - #self.log(f"'{self.raw_cmd}' did not exit gracefully, exit code {self.exit_code}.", level=LOG_LEVELS.Error) + #self.log(self.trace_log.decode('UTF-8'), level=logging.DEBUG) + #self.log(f"'{self.raw_cmd}' did not exit gracefully, exit code {self.exit_code}.", level=logging.ERROR) raise SysCallError(message=f"{self.trace_log.decode('UTF-8')}\n'{self.raw_cmd}' did not exit gracefully (trace log above), exit code: {self.exit_code}", exit_code=self.exit_code) self.ended = time.time() diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index e2762603..04fe44c8 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -1,4 +1,5 @@ -import os, stat, time, shutil, pathlib, subprocess +import os, stat, time, shutil, pathlib +import subprocess, logging from .exceptions import * from .disk import * @@ -7,7 +8,7 @@ from .user_interaction import * from .profiles import Profile from .mirrors import * from .systemd import Networkd -from .output import log, LOG_LEVELS +from .output import log from .storage import storage from .hardware import * @@ -60,7 +61,7 @@ class Installer(): storage['session'] = self self.partitions = get_partitions_in_use(self.target) - def log(self, *args, level=LOG_LEVELS.Debug, **kwargs): + def log(self, *args, level=logging.DEBUG, **kwargs): """ installer.log() wraps output.log() mainly to set a default log-level for this install session. Any manual override can be done per log() call. @@ -75,8 +76,8 @@ class Installer(): # TODO: https://stackoverflow.com/questions/28157929/how-to-safely-handle-an-exception-inside-a-context-manager if len(args) >= 2 and args[1]: - #self.log(self.trace_log.decode('UTF-8'), level=LOG_LEVELS.Debug) - self.log(args[1], level=LOG_LEVELS.Error, fg='red') + #self.log(self.trace_log.decode('UTF-8'), level=logging.DEBUG) + self.log(args[1], level=logging.ERROR, fg='red') self.sync_log_to_install_medium() @@ -89,17 +90,17 @@ class Installer(): self.genfstab() if not (missing_steps := self.post_install_check()): - self.log('Installation completed without any errors. You may now reboot.', bg='black', fg='green', level=LOG_LEVELS.Info) + self.log('Installation completed without any errors. You may now reboot.', bg='black', fg='green', level=logging.INFO) self.sync_log_to_install_medium() return True else: - self.log('Some required steps were not successfully installed/configured before leaving the installer:', bg='black', fg='red', level=LOG_LEVELS.Warning) + self.log('Some required steps were not successfully installed/configured before leaving the installer:', bg='black', fg='red', level=logging.WARNING) for step in missing_steps: - self.log(f' - {step}', bg='black', fg='red', level=LOG_LEVELS.Warning) + self.log(f' - {step}', bg='black', fg='red', level=logging.WARNING) - self.log(f"Detailed error logs can be found at: {storage['LOG_PATH']}", level=LOG_LEVELS.Warning) - self.log(f"Submit this zip file as an issue to https://github.com/archlinux/archinstall/issues", level=LOG_LEVELS.Warning) + self.log(f"Detailed error logs can be found at: {storage['LOG_PATH']}", level=logging.WARNING) + self.log(f"Submit this zip file as an issue to https://github.com/archlinux/archinstall/issues", level=logging.WARNING) self.sync_log_to_install_medium() return False @@ -129,21 +130,21 @@ class Installer(): def pacstrap(self, *packages, **kwargs): if type(packages[0]) in (list, tuple): packages = packages[0] - self.log(f'Installing packages: {packages}', level=LOG_LEVELS.Info) + self.log(f'Installing packages: {packages}', level=logging.INFO) if (sync_mirrors := sys_command('/usr/bin/pacman -Syy')).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) + self.log(f'Could not strap in packages: {pacstrap.exit_code}', level=logging.INFO) else: - self.log(f'Could not sync mirrors: {sync_mirrors.exit_code}', level=LOG_LEVELS.Info) + self.log(f'Could not sync mirrors: {sync_mirrors.exit_code}', level=logging.INFO) def set_mirrors(self, mirrors): return use_mirrors(mirrors, destination=f'{self.target}/etc/pacman.d/mirrorlist') def genfstab(self, flags='-pU'): - self.log(f"Updating {self.target}/etc/fstab", level=LOG_LEVELS.Info) + self.log(f"Updating {self.target}/etc/fstab", level=logging.INFO) fstab = sys_command(f'/usr/bin/genfstab {flags} {self.target}').trace_log with open(f"{self.target}/etc/fstab", 'ab') as fstab_fh: @@ -179,19 +180,19 @@ class Installer(): else: self.log( f"Time zone {zone} does not exist, continuing with system default.", - level=LOG_LEVELS.Warning, + level=logging.WARNING, fg='red' ) def activate_ntp(self): - self.log(f'Installing and activating NTP.', level=LOG_LEVELS.Info) + self.log(f'Installing and activating NTP.', level=logging.INFO) if self.pacstrap('ntp'): if self.enable_service('ntpd'): return True def enable_service(self, *services): for service in services: - self.log(f'Enabling service {service}', level=LOG_LEVELS.Info) + self.log(f'Enabling service {service}', level=logging.INFO) if (output := self.arch_chroot(f'systemctl enable {service}')).exit_code != 0: raise ServiceException(f"Unable to start service {service}: {output}") @@ -349,7 +350,7 @@ class Installer(): # Run registered post-install hooks for function in self.post_base_install: - self.log(f"Running post-installation hook: {function}", level=LOG_LEVELS.Info) + self.log(f"Running post-installation hook: {function}", level=logging.INFO) function(self) return True @@ -363,7 +364,7 @@ class Installer(): elif partition.mountpoint == self.target: root_partition = partition - self.log(f'Adding bootloader {bootloader} to {boot_partition}', level=LOG_LEVELS.Info) + self.log(f'Adding bootloader {bootloader} to {boot_partition}', level=logging.INFO) if bootloader == 'systemd-bootctl': if not hasUEFI(): @@ -417,10 +418,10 @@ 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) + log(f"Identifying root partition by PART-UUID on {real_device}: '{real_device.uuid}'.", level=logging.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 '{root_partition.uuid}'.", level=LOG_LEVELS.Debug) + log(f"Identifying root partition by PART-UUID on {root_partition}, looking for '{root_partition.uuid}'.", level=logging.DEBUG) entry.write(f'options root=PARTUUID={root_partition.uuid} rw intel_pstate=no_hwp\n') self.helper_flags['bootloader'] = bootloader @@ -458,17 +459,17 @@ class Installer(): if type(profile) == str: profile = Profile(self, profile) - self.log(f'Installing network profile {profile}', level=LOG_LEVELS.Info) + self.log(f'Installing network profile {profile}', level=logging.INFO) return profile.install() def enable_sudo(self, entity :str, group=False): - self.log(f'Enabling sudo permissions for {entity}.', level=LOG_LEVELS.Info) + self.log(f'Enabling sudo permissions for {entity}.', level=logging.INFO) 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) + self.log(f'Creating user {user}', level=logging.INFO) 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) @@ -481,7 +482,7 @@ class Installer(): self.helper_flags['user'] = True def user_set_pw(self, user, password): - self.log(f'Setting password for {user}', level=LOG_LEVELS.Info) + self.log(f'Setting password for {user}', level=logging.INFO) if user == 'root': # This means the root account isn't locked/disabled with * in /etc/passwd @@ -491,7 +492,7 @@ class Installer(): pass def user_set_shell(self, user, shell): - self.log(f'Setting shell for {user} to {shell}', level=LOG_LEVELS.Info) + self.log(f'Setting shell for {user} to {shell}', level=logging.INFO) o = b''.join(sys_command(f"/usr/bin/arch-chroot {self.target} sh -c \"chsh -s {shell} {user}\"")) pass @@ -502,5 +503,5 @@ class Installer(): vconsole.write(f'KEYMAP={language}\n') vconsole.write(f'FONT=lat9w-16\n') else: - self.log(f'Keyboard language was not changed from default (no language specified).', fg="yellow", level=LOG_LEVELS.Info) + self.log(f'Keyboard language was not changed from default (no language specified).', fg="yellow", level=logging.INFO) return True diff --git a/archinstall/lib/luks.py b/archinstall/lib/luks.py index 894be1c8..7f8485e6 100644 --- a/archinstall/lib/luks.py +++ b/archinstall/lib/luks.py @@ -2,10 +2,11 @@ import os import shlex import time import pathlib +import logging from .exceptions import * from .general import * from .disk import Partition -from .output import log, LOG_LEVELS +from .output import log from .storage import storage class luks2(): @@ -48,7 +49,7 @@ class luks2(): if not self.partition.allow_formatting: raise DiskError(f'Could not encrypt volume {self.partition} due to it having a formatting lock.') - log(f'Encrypting {partition} (This might take a while)', level=LOG_LEVELS.Info) + log(f'Encrypting {partition} (This might take a while)', level=logging.INFO) if not key_file: if self.key_file: @@ -84,7 +85,7 @@ class luks2(): cmd_handle = sys_command(cryptsetup_args) except SysCallError as err: if err.exit_code == 256: - log(f'{partition} is being used, trying to unmount and crypt-close the device and running one more attempt at encrypting the device.', level=LOG_LEVELS.Debug) + log(f'{partition} is being used, trying to unmount and crypt-close the device and running one more attempt at encrypting the device.', level=logging.DEBUG) # Partition was in use, unmount it and try again partition.unmount() @@ -97,11 +98,11 @@ class luks2(): for child in children: # Unmount the child location if child_mountpoint := child.get('mountpoint', None): - log(f'Unmounting {child_mountpoint}', level=LOG_LEVELS.Debug) + log(f'Unmounting {child_mountpoint}', level=logging.DEBUG) sys_command(f"umount -R {child_mountpoint}") # And close it if possible. - log(f"Closing crypt device {child['name']}", level=LOG_LEVELS.Debug) + log(f"Closing crypt device {child['name']}", level=logging.DEBUG) sys_command(f"cryptsetup close {child['name']}") # Then try again to set up the crypt-device diff --git a/archinstall/lib/mirrors.py b/archinstall/lib/mirrors.py index 04f47c0d..ae6c6422 100644 --- a/archinstall/lib/mirrors.py +++ b/archinstall/lib/mirrors.py @@ -1,4 +1,4 @@ -import urllib.request +import urllib.request, logging from .exceptions import * from .general import * @@ -59,7 +59,7 @@ def insert_mirrors(mirrors, *args, **kwargs): return True def use_mirrors(regions :dict, destination='/etc/pacman.d/mirrorlist'): - log(f'A new package mirror-list has been created: {destination}', level=LOG_LEVELS.Info) + log(f'A new package mirror-list has been created: {destination}', level=logging.INFO) for region, mirrors in regions.items(): with open(destination, 'w') as mirrorlist: for mirror in mirrors: @@ -79,7 +79,7 @@ def list_mirrors(): try: response = urllib.request.urlopen(url) except urllib.error.URLError as err: - log(f'Could not fetch an active mirror-list: {err}', level=LOG_LEVELS.Warning, fg="yellow") + log(f'Could not fetch an active mirror-list: {err}', level=logging.WARNING, fg="yellow") return regions diff --git a/archinstall/lib/output.py b/archinstall/lib/output.py index 6b184b4b..73819422 100644 --- a/archinstall/lib/output.py +++ b/archinstall/lib/output.py @@ -17,8 +17,32 @@ class LOG_LEVELS: class journald(dict): @abc.abstractmethod - def log(message, level=LOG_LEVELS.Debug): - import systemd.journal + def log(message, level=logging.DEBUG): + try: + import systemd.journal + except ModuleNotFoundError: + return False + + # For backwards compability, convert old style log-levels + # to logging levels (and warn about deprecated usage) + # There's some code re-usage here but that should be fine. + # TODO: Remove these in a few versions: + if level == LOG_LEVELS.Critical: + log("Deprecated level detected in log message, please use new logging. instead for the following log message:", fg="red", level=logging.ERROR, force=True) + level = logging.CRITICAL + elif level == LOG_LEVELS.Error: + log("Deprecated level detected in log message, please use new logging. instead for the following log message:", fg="red", level=logging.ERROR, force=True) + level = logging.ERROR + elif level == LOG_LEVELS.Warning: + log("Deprecated level detected in log message, please use new logging. instead for the following log message:", fg="red", level=logging.ERROR, force=True) + level = logging.WARNING + elif level == LOG_LEVELS.Info: + log("Deprecated level detected in log message, please use new logging. instead for the following log message:", fg="red", level=logging.ERROR, force=True) + level = logging.INFO + elif level == LOG_LEVELS.Debug: + log("Deprecated level detected in log message, please use new logging. instead for the following log message:", fg="red", level=logging.ERROR, force=True) + level = logging.DEBUG + log_adapter = logging.getLogger('archinstall') log_fmt = logging.Formatter("[%(levelname)s]: %(message)s") log_ch = systemd.journal.JournalHandler() @@ -26,19 +50,7 @@ class journald(dict): log_adapter.addHandler(log_ch) log_adapter.setLevel(logging.DEBUG) - if level == LOG_LEVELS.Critical: - log_adapter.critical(message) - elif level == LOG_LEVELS.Error: - log_adapter.error(message) - elif level == LOG_LEVELS.Warning: - log_adapter.warning(message) - elif level == LOG_LEVELS.Info: - log_adapter.info(message) - elif level == LOG_LEVELS.Debug: - log_adapter.debug(message) - else: - # Fallback logger - log_adapter.debug(message) + log_adapter.log(level, message) # TODO: Replace log() for session based logging. class SessionLogging(): @@ -112,17 +124,38 @@ def log(*args, **kwargs): with open(absolute_logfile, 'a') as log_file: log_file.write(f"{orig_string}\n") + # If we assigned a level, try to log it to systemd's journald. # Unless the level is higher than we've decided to output interactively. # (Remember, log files still get *ALL* the output despite level restrictions) if 'level' in kwargs: - if kwargs['level'] > storage.get('LOG_LEVEL', LOG_LEVELS.Info): + # For backwards compability, convert old style log-levels + # to logging levels (and warn about deprecated usage) + # There's some code re-usage here but that should be fine. + # TODO: Remove these in a few versions: + if kwargs['level'] == LOG_LEVELS.Critical: + log("Deprecated level detected in log message, please use new logging. instead for the following log message:", fg="red", level=logging.ERROR, force=True) + kwargs['level'] = logging.CRITICAL + elif kwargs['level'] == LOG_LEVELS.Error: + log("Deprecated level detected in log message, please use new logging. instead for the following log message:", fg="red", level=logging.ERROR, force=True) + kwargs['level'] = logging.ERROR + elif kwargs['level'] == LOG_LEVELS.Warning: + log("Deprecated level detected in log message, please use new logging. instead for the following log message:", fg="red", level=logging.ERROR, force=True) + kwargs['level'] = logging.WARNING + elif kwargs['level'] == LOG_LEVELS.Info: + log("Deprecated level detected in log message, please use new logging. instead for the following log message:", fg="red", level=logging.ERROR, force=True) + kwargs['level'] = logging.INFO + elif kwargs['level'] == LOG_LEVELS.Debug: + log("Deprecated level detected in log message, please use new logging. instead for the following log message:", fg="red", level=logging.ERROR, force=True) + kwargs['level'] = logging.DEBUG + + if kwargs['level'] > storage.get('LOG_LEVEL', logging.INFO) and not 'force' in kwargs: # Level on log message was Debug, but output level is set to Info. # In that case, we'll drop it. return None try: - journald.log(string, level=kwargs.get('level', LOG_LEVELS.Info)) + journald.log(string, level=kwargs.get('level', logging.INFO)) except ModuleNotFoundError: pass # Ignore writing to journald diff --git a/archinstall/lib/profiles.py b/archinstall/lib/profiles.py index 265ca26a..4988e7ab 100644 --- a/archinstall/lib/profiles.py +++ b/archinstall/lib/profiles.py @@ -1,10 +1,10 @@ import os, urllib.request, urllib.parse, ssl, json, re -import importlib.util, sys, glob, hashlib +import importlib.util, sys, glob, hashlib, logging from collections import OrderedDict from .general import multisplit, sys_command from .exceptions import * from .networking import * -from .output import log, LOG_LEVELS +from .output import log from .storage import storage def grab_url_data(path): @@ -82,7 +82,7 @@ class Script(): self.examples = None self.namespace = os.path.splitext(os.path.basename(self.path))[0] self.original_namespace = self.namespace - log(f"Script {self} has been loaded with namespace '{self.namespace}'", level=LOG_LEVELS.Debug) + log(f"Script {self} has been loaded with namespace '{self.namespace}'", level=logging.DEBUG) def __enter__(self, *args, **kwargs): self.execute() diff --git a/archinstall/lib/user_interaction.py b/archinstall/lib/user_interaction.py index d8640a81..79b0e0b9 100644 --- a/archinstall/lib/user_interaction.py +++ b/archinstall/lib/user_interaction.py @@ -1,9 +1,9 @@ import getpass, pathlib, os, shutil, re -import sys, time, signal, ipaddress +import sys, time, signal, ipaddress, logging from .exceptions import * from .profiles import Profile from .locale_helpers import list_keyboard_languages, verify_keyboard_layout, search_keyboard_layout -from .output import log, LOG_LEVELS +from .output import log from .storage import storage from .networking import list_interfaces from .general import sys_command @@ -26,7 +26,7 @@ def check_for_correct_username(username): return True log( "The username you entered is invalid. Try again", - level=LOG_LEVELS.Warning, + level=logging.WARNING, fg='red' ) return False @@ -141,7 +141,7 @@ def ask_for_a_timezone(): else: log( f"Specified timezone {timezone} does not exist.", - level=LOG_LEVELS.Warning, + level=logging.WARNING, fg='red' ) @@ -198,7 +198,7 @@ def ask_to_configure_network(): except ValueError: log( "You need to enter a valid IP in IP-config mode.", - level=LOG_LEVELS.Warning, + level=logging.WARNING, fg='red' ) @@ -214,7 +214,7 @@ def ask_to_configure_network(): except ValueError: log( "You need to enter a valid gateway (router) IP address.", - level=LOG_LEVELS.Warning, + level=logging.WARNING, fg='red' ) diff --git a/examples/guided.py b/examples/guided.py index 43aaa788..0e6f2904 100644 --- a/examples/guided.py +++ b/examples/guided.py @@ -1,4 +1,4 @@ -import getpass, time, json, os +import getpass, time, json, os, logging import archinstall from archinstall.lib.hardware import hasUEFI from archinstall.lib.profiles import Profile @@ -237,8 +237,8 @@ def ask_user_questions(): def perform_installation_steps(): print() print('This is your chosen configuration:') - archinstall.log("-- Guided template chosen (with below config) --", level=archinstall.LOG_LEVELS.Debug) - archinstall.log(json.dumps(archinstall.arguments, indent=4, sort_keys=True, cls=archinstall.JSON), level=archinstall.LOG_LEVELS.Info) + archinstall.log("-- Guided template chosen (with below config) --", level=logging.DEBUG) + archinstall.log(json.dumps(archinstall.arguments, indent=4, sort_keys=True, cls=archinstall.JSON), level=logging.INFO) print() input('Press Enter to continue.') @@ -282,7 +282,7 @@ def perform_installation_steps(): else: partition.format() else: - archinstall.log(f"Did not format {partition} because .safe_to_format() returned False or .allow_formatting was False.", level=archinstall.LOG_LEVELS.Debug) + archinstall.log(f"Did not format {partition} because .safe_to_format() returned False or .allow_formatting was False.", level=logging.DEBUG) if hasUEFI(): fs.find_partition('/boot').format('vfat')# we don't have a boot partition in bios mode @@ -313,7 +313,7 @@ def perform_installation(mountpoint): # 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 # We need to wait for it before we continue since we opted in to use a custom mirror/region. - installation.log(f'Waiting for automatic mirror selection (reflector) to complete.', level=archinstall.LOG_LEVELS.Info) + installation.log(f'Waiting for automatic mirror selection (reflector) to complete.', level=logging.INFO) while archinstall.service_state('reflector') not in ('dead', 'failed'): time.sleep(1) # Set mirrors used by pacstrap (outside of installation) @@ -342,7 +342,7 @@ def perform_installation(mountpoint): installation.enable_service('systemd-resolved') if archinstall.arguments.get('audio', None) != None: - installation.log(f"This audio server will be used: {archinstall.arguments.get('audio', None)}", level=archinstall.LOG_LEVELS.Info) + installation.log(f"This audio server will be used: {archinstall.arguments.get('audio', None)}", level=logging.INFO) if archinstall.arguments.get('audio', None) == 'pipewire': print('Installing pipewire ...') @@ -351,7 +351,7 @@ def perform_installation(mountpoint): print('Installing pulseaudio ...') installation.add_additional_packages("pulseaudio") else: - installation.log("No audio server will be installed.", level=archinstall.LOG_LEVELS.Info) + installation.log("No audio server will be installed.", level=logging.INFO) if archinstall.arguments.get('packages', None) and archinstall.arguments.get('packages', None)[0] != '': installation.add_additional_packages(archinstall.arguments.get('packages', None)) -- cgit v1.2.3-70-g09d2 From a706a98151fcd80d414c5184c3e9325aaab475ec Mon Sep 17 00:00:00 2001 From: SecondThundeR Date: Tue, 27 Apr 2021 19:19:33 +0300 Subject: Revert some merge resolve changes --- archinstall/lib/installer.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 04fe44c8..577a2ae1 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -90,14 +90,14 @@ class Installer(): self.genfstab() if not (missing_steps := self.post_install_check()): - self.log('Installation completed without any errors. You may now reboot.', bg='black', fg='green', level=logging.INFO) + self.log('Installation completed without any errors. You may now reboot.', fg='green', level=logging.INFO) self.sync_log_to_install_medium() return True else: - self.log('Some required steps were not successfully installed/configured before leaving the installer:', bg='black', fg='red', level=logging.WARNING) + self.log('Some required steps were not successfully installed/configured before leaving the installer:', fg='red', level=logging.WARNING) for step in missing_steps: - self.log(f' - {step}', bg='black', fg='red', level=logging.WARNING) + self.log(f' - {step}', fg='red', level=logging.WARNING) self.log(f"Detailed error logs can be found at: {storage['LOG_PATH']}", level=logging.WARNING) self.log(f"Submit this zip file as an issue to https://github.com/archlinux/archinstall/issues", level=logging.WARNING) -- cgit v1.2.3-70-g09d2 From df86d2b80d9fcaa37f4ebef5de8d070017019ec0 Mon Sep 17 00:00:00 2001 From: advaithm Date: Wed, 28 Apr 2021 06:39:59 +0530 Subject: pdb traceing --- archinstall/lib/installer.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 577a2ae1..ddfd9018 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -1,6 +1,6 @@ import os, stat, time, shutil, pathlib import subprocess, logging - +import pdb from .exceptions import * from .disk import * from .general import * @@ -356,6 +356,7 @@ class Installer(): return True def add_bootloader(self, bootloader='systemd-bootctl'): + pdb.set_trace() boot_partition = None root_partition = None for partition in self.partitions: -- cgit v1.2.3-70-g09d2 From 464cee46ed961627c7c2503302d1de6ebc7872e1 Mon Sep 17 00:00:00 2001 From: advaithm Date: Wed, 28 Apr 2021 07:08:35 +0530 Subject: fixed kernel select --- archinstall/lib/installer.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index ddfd9018..94324238 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -40,8 +40,8 @@ class Installer(): :type hostname: str, optional """ - def __init__(self, target, *, base_packages='base base-devel linux linux-firmware', kernels='linux'): - base_packages = base_packages + kernels.replace(',', ' ') + def __init__(self, target, *, base_packages='base base-devel linux-firmware', kernels='linux'): + kernels = kernels.split(",") self.target = target self.init_time = time.strftime('%Y-%m-%d_%H-%M-%S') self.milliseconds = int(str(time.time()).split('.')[1]) @@ -52,6 +52,8 @@ class Installer(): } self.base_packages = base_packages.split(' ') if type(base_packages) is str else base_packages + for kernel in kernels: + self.base_packages.append(kernel) if hasUEFI(): self.base_packages.append("efibootmgr") else: -- cgit v1.2.3-70-g09d2 From 7922d82639f69f5b2761168f37173c7e639efa2a Mon Sep 17 00:00:00 2001 From: advaithm Date: Wed, 28 Apr 2021 07:41:34 +0530 Subject: trying to fix always failing bootloader install --- archinstall/lib/installer.py | 1 + 1 file changed, 1 insertion(+) (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 94324238..004a1743 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -442,6 +442,7 @@ class Installer(): root_device = f"{root_partition.path}" o = b''.join(sys_command(f'/usr/bin/arch-chroot {self.target} grub-install --target=i386-pc /dev/{root_device}')) sys_command('/usr/bin/arch-chroot /mnt grub-mkconfig -o /boot/grub/grub.cfg') + self.helper_flags['bootloader'] = bootloader return True else: raise RequirementError(f"Unknown (or not yet implemented) bootloader requested: {bootloader}") -- cgit v1.2.3-70-g09d2 From db7632f55ed7160f55e5c8160ff0be750a26e2cc Mon Sep 17 00:00:00 2001 From: advaithm Date: Wed, 28 Apr 2021 07:48:44 +0530 Subject: log diffrent values when in bios mode --- archinstall/lib/installer.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 004a1743..4fb3a337 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -366,8 +366,10 @@ class Installer(): boot_partition = partition elif partition.mountpoint == self.target: root_partition = partition - - self.log(f'Adding bootloader {bootloader} to {boot_partition}', level=logging.INFO) + if hasUEFI(): + self.log(f'Adding bootloader {bootloader} to {boot_partition}', level=logging.INFO) + else: + self.log(f'Adding bootloader {bootloader} to {root_partition}', level=logging.INFO) if bootloader == 'systemd-bootctl': if not hasUEFI(): -- cgit v1.2.3-70-g09d2 From 3bf7a9e7afe9a1a75f4026e3ff509b68d8f93287 Mon Sep 17 00:00:00 2001 From: advaithm Date: Wed, 28 Apr 2021 08:00:18 +0530 Subject: removed pdb --- archinstall/lib/installer.py | 2 -- 1 file changed, 2 deletions(-) (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 4fb3a337..a5449662 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -1,6 +1,5 @@ import os, stat, time, shutil, pathlib import subprocess, logging -import pdb from .exceptions import * from .disk import * from .general import * @@ -358,7 +357,6 @@ class Installer(): return True def add_bootloader(self, bootloader='systemd-bootctl'): - pdb.set_trace() boot_partition = None root_partition = None for partition in self.partitions: -- cgit v1.2.3-70-g09d2 From 2d02e806f2ae5341752a0ceb532e5c239a164ee7 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Thu, 29 Apr 2021 08:18:43 +0000 Subject: Cleaning up packages. (#374) * Cleaning up packages. installer now relies on __packages__ definition. Which will work with external libs to more easily gather packages used by installer and profiles. * Added back the logic for the log message, where we inform if we're adding the boot loader to root or boot. * Added __package__ definition to profiles and the installer. These packages can be used as an indication from outside libraries of what could *possibly* be installed. For instance an offline-tool could source these, it would source more than it needed to, but it would give a quick rundown of what might be needed. * Removed import of __base__packages__ as it's now just __packages__ after a lot of stream-lining. * Explosion misspelling. Co-authored-by: Anton Hvornum --- archinstall/__init__.py | 2 +- archinstall/lib/hardware.py | 4 +++- archinstall/lib/installer.py | 21 +++++++++------------ profiles/52-54-00-12-34-56.py | 14 ++++++-------- profiles/awesome.py | 2 +- profiles/i3.py | 8 ++++---- profiles/xorg.py | 4 +++- 7 files changed, 27 insertions(+), 28 deletions(-) (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/__init__.py b/archinstall/__init__.py index bc58af54..e2c7ea62 100644 --- a/archinstall/__init__.py +++ b/archinstall/__init__.py @@ -3,7 +3,7 @@ from .lib.general import * from .lib.disk import * from .lib.user_interaction import * from .lib.exceptions import * -from .lib.installer import __packages__, __base_packages__, Installer +from .lib.installer import __packages__, Installer from .lib.profiles import * from .lib.luks import * from .lib.mirrors import * diff --git a/archinstall/lib/hardware.py b/archinstall/lib/hardware.py index d6cf982c..e9c63e41 100644 --- a/archinstall/lib/hardware.py +++ b/archinstall/lib/hardware.py @@ -3,6 +3,8 @@ from .general import sys_command from .networking import list_interfaces, enrichIfaceTypes from typing import Optional +__packages__ = ['xf86-video-amdgpu', 'xf86-video-ati', 'xf86-video-intel', 'xf86-video-nouveau', 'xf86-video-fbdev', 'xf86-video-vesa', 'xf86-video-vmware', 'nvidia', 'mesa'] + AVAILABLE_GFX_DRIVERS = { # Sub-dicts are layer-2 options to be selected # and lists are a list of packages to be installed @@ -18,7 +20,7 @@ AVAILABLE_GFX_DRIVERS = { 'mesa' : ['mesa'], 'fbdev' : ['xf86-video-fbdev'], 'vesa' : ['xf86-video-vesa'], - 'vmware' : ['xf86-video-vmware'] + 'vmware / virtualbox' : ['xf86-video-vmware'] } def hasWifi()->bool: diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index a5449662..dbc6d1b4 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -12,8 +12,7 @@ from .storage import storage from .hardware import * # Any package that the Installer() is responsible for (optional and the default ones) -__packages__ = ["base", "base-devel", "linux", "linux-firmware", "efibootmgr", "nano", "ntp", "iwd"] -__base_packages__ = __packages__[:6] +__packages__ = ["base", "base-devel", "linux-firmware", "linux", "linux-lts", "linux-zen", "linux-hardened"] class Installer(): """ @@ -39,8 +38,7 @@ class Installer(): :type hostname: str, optional """ - def __init__(self, target, *, base_packages='base base-devel linux-firmware', kernels='linux'): - kernels = kernels.split(",") + def __init__(self, target, *, base_packages=__packages__[:3], kernels=['linux']): self.target = target self.init_time = time.strftime('%Y-%m-%d_%H-%M-%S') self.milliseconds = int(str(time.time()).split('.')[1]) @@ -53,10 +51,7 @@ class Installer(): self.base_packages = base_packages.split(' ') if type(base_packages) is str else base_packages for kernel in kernels: self.base_packages.append(kernel) - if hasUEFI(): - self.base_packages.append("efibootmgr") - else: - self.base_packages.append("grub") + self.post_base_install = [] storage['session'] = self @@ -364,12 +359,12 @@ class Installer(): boot_partition = partition elif partition.mountpoint == self.target: root_partition = partition - if hasUEFI(): - self.log(f'Adding bootloader {bootloader} to {boot_partition}', level=logging.INFO) - else: - self.log(f'Adding bootloader {bootloader} to {root_partition}', level=logging.INFO) + + self.log(f'Adding bootloader {bootloader} to {boot_partition if boot_partition else root_partition}', level=logging.INFO) if bootloader == 'systemd-bootctl': + self.pacstrap('efibootmgr') + if not hasUEFI(): raise HardwareIncompatibilityError # TODO: Ideally we would want to check if another config @@ -432,6 +427,8 @@ class Installer(): 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.") elif bootloader == "grub-install": + self.pacstrap('grub') + if hasUEFI(): o = b''.join(sys_command(f'/usr/bin/arch-chroot {self.target} grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB')) sys_command('/usr/bin/arch-chroot /mnt grub-mkconfig -o /boot/grub/grub.cfg') diff --git a/profiles/52-54-00-12-34-56.py b/profiles/52-54-00-12-34-56.py index ed2c9d78..442e053c 100644 --- a/profiles/52-54-00-12-34-56.py +++ b/profiles/52-54-00-12-34-56.py @@ -1,7 +1,8 @@ import archinstall import json import urllib.request -import git + +__packages__ = ['nano', 'wget', 'git'] # Unmount and close previous runs (Mainly only used for re-runs, but won't hurt.) archinstall.sys_command(f'umount -R /mnt', suppress_errors=True) @@ -30,22 +31,19 @@ with archinstall.Filesystem(harddrive) as fs: if installation.minimal_installation(): installation.add_bootloader() - installation.add_additional_packages(['nano', 'wget', 'git']) + installation.add_additional_packages(__packages__) installation.install_profile('awesome') - installation.user_create('anton', 'test') + installation.user_create('devel', 'devel') installation.user_set_pw('root', 'toor') - repo = git.Repo('./') - commit = repo.head.commit.hexsha[:7] - - print(f'Submitting {commit}: success') + print(f'Submitting {archinstall.__version__}: success') conditions = { "project": "archinstall", "profile": "52-54-00-12-34-56", "status": "success", - "commit": commit + "version": archinstall.__version__ } req = urllib.request.Request("https://api.archlinux.life/build/success", data=json.dumps(conditions).encode('utf8'), diff --git a/profiles/awesome.py b/profiles/awesome.py index cbd52a3c..01566d0f 100644 --- a/profiles/awesome.py +++ b/profiles/awesome.py @@ -6,7 +6,7 @@ is_top_level_profile = False # New way of defining packages for a profile, which is iterable and can be used out side # of the profile to get a list of "what packages will be installed". -__packages__ = ['nemo', 'gpicview-gtk3', 'scrot'] +__packages__ = ['nemo', 'gpicview-gtk3', 'maim'] def _prep_function(*args, **kwargs): """ diff --git a/profiles/i3.py b/profiles/i3.py index b82c03d6..148e591e 100644 --- a/profiles/i3.py +++ b/profiles/i3.py @@ -6,7 +6,7 @@ is_top_level_profile = False # New way of defining packages for a profile, which is iterable and can be used out side # of the profile to get a list of "what packages will be installed". -__packages__ = ['i3lock', 'i3status', 'i3blocks', 'xterm'] +__packages__ = ['i3lock', 'i3status', 'i3blocks', 'xterm', 'lightdm-gtk-greeter', 'lightdm'] def _prep_function(*args, **kwargs): """ @@ -48,13 +48,13 @@ if __name__ == 'i3': """ # Install common packages for all i3 configurations - installation.add_additional_packages(__packages__) + installation.add_additional_packages(__packages__[:4]) # Install dependency profiles installation.install_profile('xorg') - # gaps is installed by deafult so we are overriding it here - installation.add_additional_packages("lightdm-gtk-greeter lightdm") + # gaps is installed by deafult so we are overriding it here with lightdm + installation.add_additional_packages(__packages__[4:]) # Auto start lightdm for all users installation.enable_service('lightdm') diff --git a/profiles/xorg.py b/profiles/xorg.py index cd89668d..7546a01b 100644 --- a/profiles/xorg.py +++ b/profiles/xorg.py @@ -1,10 +1,12 @@ # A system with "xorg" installed import os -from archinstall import generic_select, sys_command, RequirementError import archinstall + is_top_level_profile = True +__packages__ = ['dkms', 'xorg-server', 'xorg-xinit', 'nvidia-dkms', 'xorg-server', *archinstall.lib.hardware.__packages__] + def _prep_function(*args, **kwargs): """ Magic function called by the importing installer -- cgit v1.2.3-70-g09d2 From 0ebc6be7ae3b153f2baad722a08a2019bb04c905 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Thu, 29 Apr 2021 11:32:21 +0000 Subject: Added a postgresql application profile. (#383) * Added a postgres application profile. Also introducing runas to the arch_chroot of the installation, to run commands as emulated users. This is highly WIP at the moment. * Fixing top-level-listing of profiles. As well as testing some postgres installation steps. * Removed dupe functions. * Added safety check in case a comment mentions the top level profile thing. * Patching namespace corruption. * Avoiding runtime collision due to installation not being initiated yet. * Allow for parameterization of filesystem in guided. Co-authored-by: Anton Hvornum --- archinstall/lib/disk.py | 1 - archinstall/lib/installer.py | 3 +++ archinstall/lib/profiles.py | 53 +++++++------------------------------ examples/guided.py | 6 +++-- profiles/52-54-00-12-34-56.py | 8 +++++- profiles/applications/postgresql.py | 11 ++++++++ 6 files changed, 34 insertions(+), 48 deletions(-) create mode 100644 profiles/applications/postgresql.py (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index ff924f62..49bef1be 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -471,7 +471,6 @@ class Filesystem(): def raw_parted(self, string:str): x = sys_command(f'/usr/bin/parted -s {string}') - log(f"'parted -s {string}' returned: {b''.join(x)}", level=logging.DEBUG) return x def parted(self, string:str): diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index dbc6d1b4..a7b36481 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -196,6 +196,9 @@ class Installer(): return sys_command(f'/usr/bin/arch-chroot {self.target} {cmd}') def arch_chroot(self, cmd, *args, **kwargs): + if 'runas' in kwargs: + cmd = f"su - {kwargs['runas']} -c \"{cmd}\"" + return self.run_command(cmd) def drop_to_shell(self): diff --git a/archinstall/lib/profiles.py b/archinstall/lib/profiles.py index ad5d3bac..06237c1c 100644 --- a/archinstall/lib/profiles.py +++ b/archinstall/lib/profiles.py @@ -92,6 +92,9 @@ class Script(): if len(args) >= 2 and args[1]: raise args[1] + if self.original_namespace: + self.namespace = self.original_namespace + def localize_path(self, profile_path): if (url := urllib.parse.urlparse(profile_path)).scheme and url.scheme in ('https', 'http'): if not self.converted_path: @@ -202,51 +205,14 @@ class Profile(Script): with open(self.path, 'r') as source: source_data = source.read() - # TODO: I imagine that there is probably a better way to write this. - return 'top_level_profile = True' in source_data - - @property - def packages(self) -> list: - """ - Returns a list of packages baked into the profile definition. - If no package definition has been done, .packages() will return None. - """ - with open(self.path, 'r') as source: - source_data = source.read() - - # Some crude safety checks, make sure the imported profile has - # a __name__ check before importing. - # - # If the requirements are met, import with .py in the namespace to not - # trigger a traditional: - # if __name__ == 'moduleName' - if '__name__' in source_data and '__packages__' in source_data: - with self.load_instructions(namespace=f"{self.namespace}.py") as imported: - if hasattr(imported, '__packages__'): - return imported.__packages__ - return None - - - def has_post_install(self): - with open(self.path, 'r') as source: - source_data = source.read() - - # Some crude safety checks, make sure the imported profile has - # a __name__ check and if so, check if it's got a _prep_function() - # we can call to ask for more user input. - # - # If the requirements are met, import with .py in the namespace to not - # trigger a traditional: - # if __name__ == 'moduleName' - if '__name__' in source_data and '_post_install' in source_data: + if '__name__' in source_data and 'is_top_level_profile' in source_data: with self.load_instructions(namespace=f"{self.namespace}.py") as imported: - if hasattr(imported, '_post_install'): - return True + if hasattr(imported, 'is_top_level_profile'): + return imported.is_top_level_profile - def is_top_level_profile(self): - with open(self.path, 'r') as source: - source_data = source.read() - return 'top_level_profile = True' in source_data + # Default to True if nothing is specified, + # since developers like less code - omitting it should assume they want to present it. + return True @property def packages(self) -> list: @@ -268,7 +234,6 @@ class Profile(Script): if hasattr(imported, '__packages__'): return imported.__packages__ return None - class Application(Profile): def __repr__(self, *args, **kwargs): diff --git a/examples/guided.py b/examples/guided.py index 2b8a06f5..c281d033 100644 --- a/examples/guided.py +++ b/examples/guided.py @@ -136,12 +136,14 @@ def ask_user_questions(): archinstall.log('Using existing partition table reported above.') elif option == 'format-all': - archinstall.arguments['filesystem'] = archinstall.ask_for_main_filesystem_format() + if not archinstall.arguments.get('filesystem', None): + archinstall.arguments['filesystem'] = archinstall.ask_for_main_filesystem_format() archinstall.arguments['harddrive'].keep_partitions = False 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() + if not archinstall.arguments.get('filesystem', None): + archinstall.arguments['filesystem'] = archinstall.ask_for_main_filesystem_format() archinstall.arguments['harddrive'].keep_partitions = False # Get disk encryption password (or skip if blank) diff --git a/profiles/52-54-00-12-34-56.py b/profiles/52-54-00-12-34-56.py index 442e053c..a3347760 100644 --- a/profiles/52-54-00-12-34-56.py +++ b/profiles/52-54-00-12-34-56.py @@ -4,6 +4,11 @@ import urllib.request __packages__ = ['nano', 'wget', 'git'] +if __name__ == '52-54-00-12-34-56': + awesome = archinstall.Application(installation, 'postgresql') + awesome.install() + +""" # Unmount and close previous runs (Mainly only used for re-runs, but won't hurt.) archinstall.sys_command(f'umount -R /mnt', suppress_errors=True) archinstall.sys_command(f'cryptsetup close /dev/mapper/luksloop', suppress_errors=True) @@ -51,4 +56,5 @@ with archinstall.Filesystem(harddrive) as fs: try: urllib.request.urlopen(req, timeout=5) except: - pass \ No newline at end of file + pass +""" \ No newline at end of file diff --git a/profiles/applications/postgresql.py b/profiles/applications/postgresql.py new file mode 100644 index 00000000..fcdce824 --- /dev/null +++ b/profiles/applications/postgresql.py @@ -0,0 +1,11 @@ +import archinstall + +# Define the package list in order for lib to source +# which packages will be installed by this profile +__packages__ = ["postgresql"] + +installation.add_additional_packages(__packages__) + +installation.arch_chroot("initdb -D /var/lib/postgres/data", runas='postgres') + +installation.enable_service('postgresql') \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 4ce97aaa8c395f24c96212471b32fb00987c0386 Mon Sep 17 00:00:00 2001 From: "Dylan M. Taylor" Date: Thu, 29 Apr 2021 16:59:43 -0400 Subject: Partially revert hasUEFI grub/efibootmgr change to fix GRUB --- archinstall/lib/installer.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index a7b36481..1443a0f9 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -51,6 +51,10 @@ class Installer(): self.base_packages = base_packages.split(' ') if type(base_packages) is str else base_packages for kernel in kernels: self.base_packages.append(kernel) + if hasUEFI(): + self.base_packages.append("efibootmgr") + else: + self.base_packages.append("grub") self.post_base_install = [] @@ -366,7 +370,6 @@ class Installer(): self.log(f'Adding bootloader {bootloader} to {boot_partition if boot_partition else root_partition}', level=logging.INFO) if bootloader == 'systemd-bootctl': - self.pacstrap('efibootmgr') if not hasUEFI(): raise HardwareIncompatibilityError @@ -430,7 +433,6 @@ class Installer(): 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.") elif bootloader == "grub-install": - self.pacstrap('grub') if hasUEFI(): o = b''.join(sys_command(f'/usr/bin/arch-chroot {self.target} grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB')) -- cgit v1.2.3-70-g09d2 From e488ad8ec40ab30ae6b5df83b5df64c123c701cc Mon Sep 17 00:00:00 2001 From: "Dylan M. Taylor" Date: Thu, 29 Apr 2021 20:03:25 -0400 Subject: Change how efibootmgr is installed Make changes suggested by Torxed --- archinstall/lib/installer.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 1443a0f9..61ac737c 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -51,10 +51,6 @@ class Installer(): self.base_packages = base_packages.split(' ') if type(base_packages) is str else base_packages for kernel in kernels: self.base_packages.append(kernel) - if hasUEFI(): - self.base_packages.append("efibootmgr") - else: - self.base_packages.append("grub") self.post_base_install = [] @@ -370,6 +366,7 @@ class Installer(): self.log(f'Adding bootloader {bootloader} to {boot_partition if boot_partition else root_partition}', level=logging.INFO) if bootloader == 'systemd-bootctl': + self.pacstrap('efibootmgr') if not hasUEFI(): raise HardwareIncompatibilityError @@ -433,8 +430,10 @@ class Installer(): 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.") elif bootloader == "grub-install": + self.pacstrap('grub') if hasUEFI(): + self.pacstrap('efibootmgr')` o = b''.join(sys_command(f'/usr/bin/arch-chroot {self.target} grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB')) sys_command('/usr/bin/arch-chroot /mnt grub-mkconfig -o /boot/grub/grub.cfg') return True -- cgit v1.2.3-70-g09d2 From 8f4b8fd5ffed54a4d1f7508d4ac6380ae8b84a29 Mon Sep 17 00:00:00 2001 From: builder_247 <14019974+builder-247@users.noreply.github.com> Date: Sat, 1 May 2021 00:36:40 +0300 Subject: Fix syntax error --- archinstall/lib/installer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 61ac737c..331762b4 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -433,7 +433,7 @@ class Installer(): self.pacstrap('grub') if hasUEFI(): - self.pacstrap('efibootmgr')` + self.pacstrap('efibootmgr') o = b''.join(sys_command(f'/usr/bin/arch-chroot {self.target} grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB')) sys_command('/usr/bin/arch-chroot /mnt grub-mkconfig -o /boot/grub/grub.cfg') return True -- cgit v1.2.3-70-g09d2