Rework install log (#3550)
This commit is contained in:
parent
a5d995b546
commit
1dccfe6c33
|
|
@ -22,9 +22,8 @@ from archinstall.lib.models.network_configuration import NetworkConfiguration
|
|||
from archinstall.lib.models.packages import Repository
|
||||
from archinstall.lib.models.profile_model import ProfileConfiguration
|
||||
from archinstall.lib.models.users import Password, User
|
||||
from archinstall.lib.output import debug, error, warn
|
||||
from archinstall.lib.output import debug, error, logger, warn
|
||||
from archinstall.lib.plugins import load_plugin
|
||||
from archinstall.lib.storage import storage
|
||||
from archinstall.lib.translationhandler import Language, tr, translation_handler
|
||||
from archinstall.lib.utils.util import get_password
|
||||
from archinstall.tui.curses_menu import Tui
|
||||
|
|
@ -389,7 +388,7 @@ class ArchConfigHandler:
|
|||
args.silent = False
|
||||
|
||||
if args.debug:
|
||||
warn(f'Warning: --debug mode will write certain credentials to {storage["LOG_PATH"]}/{storage["LOG_FILE"]}!')
|
||||
warn(f'Warning: --debug mode will write certain credentials to {logger.path}!')
|
||||
|
||||
if args.plugin:
|
||||
plugin_path = Path(args.plugin)
|
||||
|
|
|
|||
|
|
@ -12,8 +12,7 @@ from archinstall.tui.types import Alignment, FrameProperties, Orientation, Previ
|
|||
from .args import ArchConfig
|
||||
from .crypt import encrypt
|
||||
from .general import JSON, UNSAFE_JSON
|
||||
from .output import debug, warn
|
||||
from .storage import storage
|
||||
from .output import debug, logger, warn
|
||||
from .utils.util import get_password, prompt_dir
|
||||
|
||||
|
||||
|
|
@ -29,7 +28,7 @@ class ConfigurationOutput:
|
|||
"""
|
||||
|
||||
self._config = config
|
||||
self._default_save_path = storage.get('LOG_PATH', Path('.'))
|
||||
self._default_save_path = logger.directory
|
||||
self._user_config_file = Path('user_configuration.json')
|
||||
self._user_creds_file = Path('user_credentials.json')
|
||||
|
||||
|
|
|
|||
|
|
@ -19,8 +19,7 @@ from shutil import which
|
|||
from typing import Any, override
|
||||
|
||||
from .exceptions import RequirementError, SysCallError
|
||||
from .output import debug, error
|
||||
from .storage import storage
|
||||
from .output import debug, error, logger
|
||||
|
||||
# https://stackoverflow.com/a/43627833/929999
|
||||
_VT100_ESCAPE_REGEX = r'\x1B\[[?0-9;]*[a-zA-Z]'
|
||||
|
|
@ -415,7 +414,7 @@ class SysCommand:
|
|||
|
||||
|
||||
def _append_log(file: str, content: str) -> None:
|
||||
path = Path(f'{storage["LOG_PATH"]}/{file}')
|
||||
path = logger.directory / file
|
||||
|
||||
change_perm = not path.exists()
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ from .models.locale import LocaleConfiguration
|
|||
from .models.mirrors import MirrorConfiguration
|
||||
from .models.network_configuration import Nic
|
||||
from .models.users import User
|
||||
from .output import debug, error, info, log, warn
|
||||
from .output import debug, error, info, log, logger, warn
|
||||
from .pacman import Pacman
|
||||
from .pacman.config import PacmanConfig
|
||||
from .plugins import plugins
|
||||
|
|
@ -132,13 +132,12 @@ class Installer:
|
|||
|
||||
# We avoid printing /mnt/<log path> 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.
|
||||
log_file = os.path.join(storage['LOG_PATH'], storage['LOG_FILE'])
|
||||
Tui.print(str(tr('[!] A log file has been created here: {}').format(log_file)))
|
||||
Tui.print(str(tr('[!] A log file has been created here: {}').format(logger.path)))
|
||||
Tui.print(tr('Please submit this issue (and file) to https://github.com/archlinux/archinstall/issues'))
|
||||
raise exc_val
|
||||
|
||||
if not (missing_steps := self.post_install_check()):
|
||||
msg = f'Installation completed without any errors.\nLog files temporarily available at {storage["LOG_PATH"]}.\nYou may reboot when ready.\n'
|
||||
msg = f'Installation completed without any errors.\nLog files temporarily available at {logger.directory}.\nYou may reboot when ready.\n'
|
||||
log(msg, fg='green')
|
||||
self.sync_log_to_install_medium()
|
||||
return True
|
||||
|
|
@ -148,7 +147,7 @@ class Installer:
|
|||
for step in missing_steps:
|
||||
warn(f' - {step}')
|
||||
|
||||
warn(f'Detailed error logs can be found at: {storage["LOG_PATH"]}')
|
||||
warn(f'Detailed error logs can be found at: {logger.directory}')
|
||||
warn('Submit this zip file as an issue to https://github.com/archlinux/archinstall/issues')
|
||||
|
||||
self.sync_log_to_install_medium()
|
||||
|
|
@ -456,13 +455,12 @@ class Installer:
|
|||
# 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)
|
||||
absolute_logfile = logger.path
|
||||
|
||||
if not os.path.isdir(f'{self.target}/{os.path.dirname(absolute_logfile)}'):
|
||||
os.makedirs(f'{self.target}/{os.path.dirname(absolute_logfile)}')
|
||||
if not os.path.isdir(f'{self.target}/{os.path.dirname(absolute_logfile)}'):
|
||||
os.makedirs(f'{self.target}/{os.path.dirname(absolute_logfile)}')
|
||||
|
||||
shutil.copy2(absolute_logfile, f'{self.target}/{absolute_logfile}')
|
||||
shutil.copy2(absolute_logfile, f'{self.target}/{absolute_logfile}')
|
||||
|
||||
return True
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ from enum import Enum
|
|||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from .storage import storage
|
||||
from .utils.unicode import unicode_ljust, unicode_rjust
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
|
@ -147,30 +146,46 @@ class Journald:
|
|||
log_adapter.log(level, message)
|
||||
|
||||
|
||||
def _check_log_permissions() -> None:
|
||||
filename = storage.get('LOG_FILE', None)
|
||||
log_dir = storage.get('LOG_PATH', Path('./'))
|
||||
class Logger:
|
||||
def __init__(self, path: Path = Path('/var/log/archinstall')) -> None:
|
||||
self._path = path
|
||||
|
||||
if not filename:
|
||||
raise ValueError('No log file name defined')
|
||||
@property
|
||||
def path(self) -> Path:
|
||||
return self._path / 'install.log'
|
||||
|
||||
log_file = log_dir / filename
|
||||
@property
|
||||
def directory(self) -> Path:
|
||||
return self._path
|
||||
|
||||
try:
|
||||
log_dir.mkdir(exist_ok=True, parents=True)
|
||||
log_file.touch(exist_ok=True)
|
||||
def _check_permissions(self) -> None:
|
||||
log_file = self.path
|
||||
|
||||
with log_file.open('a') as fp:
|
||||
fp.write('')
|
||||
except PermissionError:
|
||||
# Fallback to creating the log file in the current folder
|
||||
fallback_dir = Path('./').absolute()
|
||||
fallback_log_file = fallback_dir / filename
|
||||
try:
|
||||
self._path.mkdir(exist_ok=True, parents=True)
|
||||
log_file.touch(exist_ok=True)
|
||||
|
||||
fallback_log_file.touch(exist_ok=True)
|
||||
with log_file.open('a') as f:
|
||||
f.write('')
|
||||
except PermissionError:
|
||||
# Fallback to creating the log file in the current folder
|
||||
logger._path = Path('./').absolute()
|
||||
|
||||
storage['LOG_PATH'] = fallback_dir
|
||||
warn(f'Not enough permission to place log file at {log_file}, creating it in {fallback_log_file} instead')
|
||||
warn(
|
||||
f'Not enough permission to place log file at {log_file},',
|
||||
'creating it in {logger.path} instead'
|
||||
)
|
||||
|
||||
def log(self, level: int, content: str) -> None:
|
||||
self._check_permissions()
|
||||
|
||||
with self.path.open('a') as f:
|
||||
ts = _timestamp()
|
||||
level_name = logging.getLevelName(level)
|
||||
f.write(f'[{ts}] - {level_name} - {content}\n')
|
||||
|
||||
|
||||
logger = Logger()
|
||||
|
||||
|
||||
def _supports_color() -> bool:
|
||||
|
|
@ -309,25 +324,15 @@ def log(
|
|||
reset: bool = False,
|
||||
font: list[Font] = [],
|
||||
) -> None:
|
||||
# leave this check here as we need to setup the logging
|
||||
# right from the beginning when the modules are loaded
|
||||
_check_log_permissions()
|
||||
text = ' '.join([str(x) for x in msgs])
|
||||
|
||||
text = orig_string = ' '.join([str(x) for x in msgs])
|
||||
logger.log(level, text)
|
||||
|
||||
# Attempt to colorize the output if supported
|
||||
# Insert default colors and override with **kwargs
|
||||
if _supports_color():
|
||||
text = _stylize_output(text, fg, bg, reset, font)
|
||||
|
||||
log_file = storage['LOG_PATH'] / storage['LOG_FILE']
|
||||
|
||||
with log_file.open('a') as fp:
|
||||
ts = _timestamp()
|
||||
level_name = logging.getLevelName(level)
|
||||
out = f'[{ts}] - {level_name} - {orig_string}\n'
|
||||
fp.write(out)
|
||||
|
||||
Journald.log(text, level=level)
|
||||
|
||||
if level != logging.DEBUG:
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
# (4. Added the ~/.config directory as an additional option for future reasons)
|
||||
#
|
||||
# And Keeping this in dict ensures that variables are shared across imports.
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING, NotRequired, TypedDict
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
|
@ -14,13 +13,8 @@ if TYPE_CHECKING:
|
|||
|
||||
|
||||
class _StorageDict(TypedDict):
|
||||
LOG_FILE: Path
|
||||
LOG_PATH: Path
|
||||
active_boot: NotRequired['Boot | None']
|
||||
installation_session: NotRequired['Installer']
|
||||
|
||||
|
||||
storage: _StorageDict = {
|
||||
'LOG_FILE': Path('install.log'),
|
||||
'LOG_PATH': Path('/var/log/archinstall'),
|
||||
}
|
||||
storage: _StorageDict = {}
|
||||
|
|
|
|||
Loading…
Reference in New Issue