Send patches - preferably formatted by git format-patch - to patches at archlinux32 dot org.
summaryrefslogtreecommitdiff
path: root/archinstall/lib/installer.py
diff options
context:
space:
mode:
Diffstat (limited to 'archinstall/lib/installer.py')
-rw-r--r--archinstall/lib/installer.py132
1 files changed, 78 insertions, 54 deletions
diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py
index 99d8f2b9..775de50a 100644
--- a/archinstall/lib/installer.py
+++ b/archinstall/lib/installer.py
@@ -1,4 +1,4 @@
-import os, stat
+import os, stat, time
from .exceptions import *
from .disk import *
@@ -6,6 +6,8 @@ from .general import *
from .user_interaction import *
from .profiles import Profile
from .mirrors import *
+from .output import log, LOG_LEVELS
+from .storage import storage
class Installer():
"""
@@ -35,6 +37,8 @@ class Installer():
self.profile = profile
self.hostname = hostname
self.mountpoint = mountpoint
+ self.init_time = time.strftime('%Y-%m-%d_%H-%M-%S')
+ self.milliseconds = int(str(time.time()).split('.')[1])
self.helper_flags = {
'bootloader' : False,
@@ -43,10 +47,24 @@ class Installer():
}
self.base_packages = base_packages.split(' ')
+ storage['session'] = self
self.partition = partition
self.boot_partition = boot_partition
+ def log(self, *args, level=LOG_LEVELS.Debug, file=None, **kwargs):
+ if not file:
+ if 'logfile' not in storage:
+ log_root = os.path.join(os.path.expanduser('~/'), '.cache/archinstall')
+ if not os.path.isdir(log_root):
+ os.makedirs(log_root)
+
+ storage['logfile'] = f"{log_root}/install-session_{self.init_time}.{self.milliseconds}.log"
+
+ file = storage['logfile']
+
+ log(*args, level=level, file=file, **kwargs)
+
def __enter__(self, *args, **kwargs):
self.partition.mount(self.mountpoint)
os.makedirs(f'{self.mountpoint}/boot', exist_ok=True)
@@ -60,12 +78,14 @@ class Installer():
raise args[1]
if not (missing_steps := self.post_install_check()):
- log('Installation completed without any errors. You may now reboot.', bg='black', fg='green')
+ self.log('Installation completed without any errors. You may now reboot.', bg='black', fg='green', level=LOG_LEVELS.Info)
return True
else:
- log('Some required steps were not successfully installed/configured before leaving the installer:', bg='black', fg='red')
+ self.log('Some required steps were not successfully installed/configured before leaving the installer:', bg='black', fg='red', level=LOG_LEVELS.Warning)
for step in missing_steps:
- log(f' - {step}', bg='black', fg='red')
+ self.log(f' - {step}', bg='black', fg='red', level=LOG_LEVELS.Warning)
+ self.log(f"Detailed error logs can be found at: {log_path}", level=LOG_LEVELS.Warning)
+ self.log(f"Submit this zip file as an issue to https://github.com/Torxed/archinstall/issues", level=LOG_LEVELS.Warning)
return False
def post_install_check(self, *args, **kwargs):
@@ -73,15 +93,15 @@ class Installer():
def pacstrap(self, *packages, **kwargs):
if type(packages[0]) in (list, tuple): packages = packages[0]
- log(f'Installing packages: {packages}')
+ 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:
return True
else:
- log(f'Could not strap in packages: {pacstrap.exit_code}')
+ self.log(f'Could not strap in packages: {pacstrap.exit_code}', level=LOG_LEVELS.Info)
else:
- log(f'Could not sync mirrors: {sync_mirrors.exit_code}')
+ self.log(f'Could not sync mirrors: {sync_mirrors.exit_code}', level=LOG_LEVELS.Info)
def set_mirrors(self, mirrors):
return use_mirrors(mirrors, destination=f'{self.mountpoint}/etc/pacman.d/mirrorlist')
@@ -114,13 +134,13 @@ class Installer():
return True
def activate_ntp(self):
- log(f'Installing and activating NTP.')
+ self.log(f'Installing and activating NTP.', level=LOG_LEVELS.Info)
if self.pacstrap('ntp'):
if self.enable_service('ntpd'):
return True
def enable_service(self, service):
- log(f'Enabling service {service}')
+ self.log(f'Enabling service {service}', level=LOG_LEVELS.Info)
return self.arch_chroot(f'systemctl enable {service}').exit_code == 0
def run_command(self, cmd, *args, **kwargs):
@@ -168,47 +188,51 @@ class Installer():
self.helper_flags['base'] = True
return True
- def add_bootloader(self):
- log(f'Adding bootloader to {self.boot_partition}')
- 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
-
- entry.write(f'options cryptdevice=UUID={uid}:luksdev root=/dev/mapper/luksdev rw intel_pstate=no_hwp\n')
-
- self.helper_flags['bootloader'] = True
- 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
-
- entry.write(f'options root=PARTUUID={uid} rw intel_pstate=no_hwp\n')
-
- self.helper_flags['bootloader'] = True
- 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.')
+ def add_bootloader(self, bootloader='systemd-bootctl'):
+ 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
+
+ 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
+
+ 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(f"Unknown (or not yet implemented) bootloader added to add_bootloader(): {bootloader}")
def add_additional_packages(self, *packages):
return self.pacstrap(*packages)
@@ -216,17 +240,17 @@ class Installer():
def install_profile(self, profile):
profile = Profile(self, profile)
- log(f'Installing network profile {profile}')
+ self.log(f'Installing network profile {profile}', level=LOG_LEVELS.Info)
return profile.install()
def enable_sudo(self, entity :str, group=False):
- log(f'Enabling sudo permissions for {entity}.')
+ self.log(f'Enabling sudo permissions for {entity}.', level=LOG_LEVELS.Info)
with open(f'{self.mountpoint}/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):
- log(f'Creating user {user}')
+ self.log(f'Creating user {user}', level=LOG_LEVELS.Info)
o = b''.join(sys_command(f'/usr/bin/arch-chroot {self.mountpoint} useradd -m -G wheel {user}'))
if password:
self.user_set_pw(user, password)
@@ -239,7 +263,7 @@ class Installer():
self.helper_flags['user'] = True
def user_set_pw(self, user, password):
- log(f'Setting password for {user}')
+ self.log(f'Setting password for {user}', level=LOG_LEVELS.Info)
if user == 'root':
# This means the root account isn't locked/disabled with * in /etc/passwd