From f31d5e34cdfe9594678316dc100d8c381aac1f43 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 24 Jan 2021 22:42:07 +0100 Subject: Trying to centralize the configuration for logging. Phasing out some parameters which also affects the current ability to create multiple log files for multiple runs. This will be re-introduced when logging is made into a class object in a later version --- archinstall/lib/installer.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 8c22b51f..025c15cb 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -34,13 +34,19 @@ 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'): + 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): 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]) + + if logdir: + storage['LOG_PATH'] = logdir + if logfile: + storage['LOG_FILE'] = logfile + self.helper_flags = { 'bootloader' : False, 'base' : False, @@ -53,7 +59,7 @@ class Installer(): self.partition = partition self.boot_partition = boot_partition - def log(self, *args, level=LOG_LEVELS.Debug, file=None, **kwargs): + def log(self, *args, level=LOG_LEVELS.Debug, **kwargs): if not file: if 'logfile' not in storage: log_root = os.path.join(os.path.expanduser('~/'), '.cache/archinstall') @@ -64,7 +70,7 @@ class Installer(): file = storage['logfile'] - log(*args, level=level, file=file, **kwargs) + log(*args, level=level, **kwargs) def __enter__(self, *args, **kwargs): self.partition.mount(self.mountpoint) -- cgit v1.2.3-70-g09d2 From 828a09b9c8750dfb582ccd12d79fa7faa4512415 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 24 Jan 2021 22:57:16 +0100 Subject: Simpligied installer.log() to wrap output.log() with it's changes. --- archinstall/lib/installer.py | 15 ++++----------- archinstall/lib/output.py | 8 +++++++- 2 files changed, 11 insertions(+), 12 deletions(-) (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 025c15cb..1218b840 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -41,7 +41,6 @@ class Installer(): self.init_time = time.strftime('%Y-%m-%d_%H-%M-%S') self.milliseconds = int(str(time.time()).split('.')[1]) - if logdir: storage['LOG_PATH'] = logdir if logfile: @@ -60,16 +59,10 @@ class Installer(): self.boot_partition = boot_partition def log(self, *args, level=LOG_LEVELS.Debug, **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'] - + """ + 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. + """ log(*args, level=level, **kwargs) def __enter__(self, *args, **kwargs): diff --git a/archinstall/lib/output.py b/archinstall/lib/output.py index 267f2635..52b2ce2c 100644 --- a/archinstall/lib/output.py +++ b/archinstall/lib/output.py @@ -37,6 +37,11 @@ class journald(dict): # Fallback logger log_adapter.debug(message) +# TODO: Replace log() for session based logging. +class SessionLogging(): + def __init__(self): + pass + # Found first reference here: https://stackoverflow.com/questions/7445658/how-to-detect-if-the-console-does-support-ansi-escape-codes-in-python # And re-used this: https://github.com/django/django/blob/master/django/core/management/color.py#L12 def supports_color(): @@ -109,6 +114,7 @@ def log(*args, **kwargs): pass # Ignore writing to journald # Finally, print the log unless we skipped it based on level. - # And we print the string which may or may not contain color formatting. + # We use sys.stdout.write()+flush() instead of print() to try and + # fix issue #94 sys.stdout.write(string) sys.stdout.flush() \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 435d2f687eda1548e56270787b11f024e2a8e08d Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 25 Jan 2021 00:09:34 +0100 Subject: Added some more fields to the configuration output, as well as added a better fail safe for the logging output. Any exception during the installation will be caught by __exit__ in Installer(), hopefully. --- archinstall/lib/general.py | 6 +++--- archinstall/lib/installer.py | 1 + examples/guided.py | 5 +++++ 3 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 203f5fa9..dc94b063 100644 --- a/archinstall/lib/general.py +++ b/archinstall/lib/general.py @@ -245,9 +245,9 @@ class sys_command():#Thread): self.exit_code = 0 if self.exit_code != 0 and not self.kwargs['suppress_errors']: - 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=LOG_LEVELS.Debug) - raise SysCallError(f"'{self.raw_cmd}' did not exit gracefully, exit code {self.exit_code}.\n{self.trace_log.decode('UTF-8')}") + #self.log(self.trace_log.decode('UTF-8'), level=LOG_LEVELS.Debug) + #self.log(f"'{self.raw_cmd}' did not exit gracefully, exit code {self.exit_code}.", level=LOG_LEVELS.Error) + raise SysCallError(f"{self.trace_log.decode('UTF-8')}\n'{self.raw_cmd}' did not exit gracefully (trace log above), exit code: {self.exit_code}") self.ended = time.time() with open(f'{self.cwd}/trace.log', 'wb') as fh: diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 1218b840..48198635 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -75,6 +75,7 @@ class Installer(): # b''.join(sys_command(f'sync')) # No need to, since the underlaying fs() object will call sync. # 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(args[1], level=LOG_LEVELS.Error) raise args[1] self.genfstab() diff --git a/examples/guided.py b/examples/guided.py index 7726d5b9..f6c80969 100644 --- a/examples/guided.py +++ b/examples/guided.py @@ -85,6 +85,7 @@ archinstall.sys_command(f'cryptsetup close /dev/mapper/luksloop', suppress_error if len(keyboard_language := archinstall.select_language(archinstall.list_keyboard_languages()).strip()): archinstall.set_keyboard_language(keyboard_language) + archinstall.storage['_guided']['keyboard_layout'] = keyboard_language # Create a storage structure for all our information. # We'll print this right before the user gets informed about the formatting timer. @@ -102,6 +103,7 @@ while (disk_password := getpass.getpass(prompt='Enter disk encryption password ( if disk_password != disk_password_verification: archinstall.log(' * Passwords did not match * ', bg='black', fg='red') continue + archinstall.storage['_guided']['disk_encryption'] = True break archinstall.storage['_guided']['harddrive'] = harddrive @@ -118,7 +120,10 @@ while (root_pw := getpass.getpass(prompt='Enter root password (leave blank to le archinstall.log(' * Passwords did not match * ', bg='black', fg='red') continue + # Storing things in _guided_hidden helps us avoid printing it + # when echoing user configuration: archinstall.storage['_guided'] archinstall.storage['_guided_hidden']['root_pw'] = root_pw + archinstall.storage['_guided']['root_unlocked'] = True break # Ask for additional users (super-user if root pw was not set) -- cgit v1.2.3-70-g09d2 From 7eaee2cd4817c1aaca013f8baa267ddf4503f678 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 25 Jan 2021 00:25:15 +0100 Subject: Added a little print out to inform the user about where to find the log file on a crash. --- archinstall/lib/installer.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 48198635..2ea5c60e 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -75,7 +75,11 @@ class Installer(): # b''.join(sys_command(f'sync')) # No need to, since the underlaying fs() object will call sync. # 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) + + print(f"[!] A log file has been created here: {os.path.join(storage['LOG_PATH'], storage['LOG_FILE'])}") + print(f" Please submit this issue (and file) to https://github.com/Torxed/archinstall/issues") raise args[1] self.genfstab() -- cgit v1.2.3-70-g09d2 From 165d4ebc7f420d99eef453b785a86a51ceec8669 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Tue, 26 Jan 2021 00:44:34 +0100 Subject: Synced over the install log to the install medium upon Installer() __exit__. Default storage is /var/log/archinstall/install.log but can be configured in storage.py. This will include crash dumps and a identical copy is found in the ISO as well, in case the users starts looking in /var/log/archinstall in the ISO medium. --- archinstall/lib/installer.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'archinstall/lib/installer.py') diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 99c5506b..c4cdf857 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -75,10 +75,15 @@ class Installer(): def __exit__(self, *args, **kwargs): # b''.join(sys_command(f'sync')) # No need to, since the underlaying fs() object will call sync. # 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) + self.sync_log_to_install_medium() + + # We avoid printing /mnt/ because that might confuse people if they note it down + # and then reboot, and a identical log file will be found in the ISO medium anyway. print(f"[!] A log file has been created here: {os.path.join(storage['LOG_PATH'], storage['LOG_FILE'])}") print(f" Please submit this issue (and file) to https://github.com/Torxed/archinstall/issues") raise args[1] @@ -87,6 +92,7 @@ class Installer(): 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.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) @@ -94,8 +100,23 @@ class Installer(): 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) + self.sync_log_to_install_medium() return False + def sync_log_to_install_medium(self): + # Copy over the install log (if there is one) to the install medium if + # at least the base has been strapped in, otherwise we won't have a filesystem/structure to copy to. + if self.helper_flags.get('base-strapped', False) is True: + if (filename := storage.get('LOG_FILE', None)): + absolute_logfile = os.path.join(storage.get('LOG_PATH', './'), filename) + + if not os.path.isdir(f"{self.mountpoint}/{os.path.dirname(absolute_logfile)}"): + os.makedirs(f"{self.mountpoint}/{os.path.dirname(absolute_logfile)}") + + shutil.copy2(absolute_logfile, f"{self.mountpoint}/{absolute_logfile}") + + return True + def mount(self, partition, mountpoint, create_mountpoint=True): if create_mountpoint and not os.path.isdir(f'{self.mountpoint}{mountpoint}'): os.makedirs(f'{self.mountpoint}{mountpoint}') @@ -239,6 +260,7 @@ class Installer(): if self.partition.filesystem == 'xfs': self.base_packages.append('xfsprogs') self.pacstrap(self.base_packages) + self.helper_flags['base-strapped'] = True #self.genfstab() with open(f"{self.mountpoint}/etc/fstab", "a") as fstab: -- cgit v1.2.3-70-g09d2