Replace old_installer.py with a curses TUI installer packaged as a one-file PyInstaller binary (python/installer/build.py, wrapped by python/installer/package.nix). The default .#installer is patched to run on foreign Linux live media; the new .#installer-nixos variant keeps its Nix store interpreter so it runs on NixOS. Add systems/iso, a minimal NixOS install CD with kernel 6.18 and ZFS 2.4 matching the deployed systems and the installer on PATH; build it with nix build .#iso. Shared logging and subprocess helpers move out of common.py into python/logging_config.py and python/process.py.
65 lines
1.7 KiB
Python
65 lines
1.7 KiB
Python
"""common."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
from datetime import UTC, datetime
|
|
from os import getenv
|
|
from subprocess import PIPE, Popen
|
|
|
|
from apprise import Apprise
|
|
|
|
from python.logging_config import configure_logger as _configure_logger
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def configure_logger(level: str = "INFO") -> None:
|
|
"""Configure the logger."""
|
|
_configure_logger(level)
|
|
|
|
|
|
def bash_wrapper(command: str) -> tuple[str, int]:
|
|
"""Execute a bash command and capture the output.
|
|
|
|
Args:
|
|
command (str): The bash command to be executed.
|
|
|
|
Returns:
|
|
Tuple[str, int]: A tuple containing the output of the command (stdout) as a string,
|
|
the error output (stderr) as a string (optional), and the return code as an integer.
|
|
"""
|
|
# This is a acceptable risk
|
|
process = Popen(command.split(), stdout=PIPE, stderr=PIPE)
|
|
output, error = process.communicate()
|
|
if error:
|
|
logger.error(f"{error=}")
|
|
return error.decode(), process.returncode
|
|
|
|
return output.decode(), process.returncode
|
|
|
|
|
|
def signal_alert(body: str, title: str = "") -> None:
|
|
"""Send a signal alert.
|
|
|
|
Args:
|
|
body (str): The body of the alert.
|
|
title (str, optional): The title of the alert. Defaults to "".
|
|
"""
|
|
apprise_client = Apprise()
|
|
|
|
from_phone = getenv("SIGNAL_ALERT_FROM_PHONE")
|
|
to_phone = getenv("SIGNAL_ALERT_TO_PHONE")
|
|
if not from_phone or not to_phone:
|
|
logger.info("SIGNAL_ALERT_FROM_PHONE or SIGNAL_ALERT_TO_PHONE not set")
|
|
return
|
|
|
|
apprise_client.add(f"signal://localhost:8989/{from_phone}/{to_phone}")
|
|
|
|
apprise_client.notify(title=title, body=body)
|
|
|
|
|
|
def utcnow() -> datetime:
|
|
"""Get the current UTC time."""
|
|
return datetime.now(tz=UTC)
|