Files
BackItUp/app/app_runner.py
T
2026-08-11 23:33:40 +02:00

118 lines
4.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from pathlib import Path
from app.dependencies import DependencyManager
from app.paths import AppPaths
from app.ui import ConsoleUI
from app.venv_manager import VirtualEnvManager
class AppRunner:
def __init__(self, base_dir: Path, entry_script: Path) -> None:
self.paths = AppPaths(base_dir=base_dir)
self.entry_script = entry_script
def _bootstrap(self) -> None:
"""Ensure venv and dependencies are ready (re-execs into venv if needed)."""
venv = VirtualEnvManager(self.paths.venv_dir, self.entry_script)
if not venv.in_virtualenv():
ConsoleUI.info("Virtuelle Umgebung wird vorbereitet...")
venv.ensure_and_reexec_if_needed()
deps = DependencyManager(self.paths.requirements_path)
missing = deps.install_missing()
if missing:
ConsoleUI.success(f"Abhaengigkeiten installiert: {', '.join(missing)}")
else:
ConsoleUI.info("Alle Abhaengigkeiten sind bereits installiert.")
def setup(self) -> None:
ConsoleUI.headline("BackItUp Setup")
self._bootstrap()
ConsoleUI.success("System ist bereit.")
self._install_systemd_service()
def _install_systemd_service(self) -> None:
import shutil
import subprocess
if not shutil.which("systemctl"):
ConsoleUI.warn("systemctl nicht gefunden – kein systemd-System erkannt.")
ConsoleUI.info("Manuelle Installation: bash scripts/service.sh install")
return
service_name = "BackItUp.service"
user_systemd_dir = Path.home() / ".config" / "systemd" / "user"
user_systemd_dir.mkdir(parents=True, exist_ok=True)
if self.paths.venv_dir.name == "nt":
venv_python = self.paths.venv_dir / "Scripts" / "python.exe"
else:
venv_python = self.paths.venv_dir / "bin" / "python"
service_content = f"""[Unit]
Description=BackItUp Flask Service
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
WorkingDirectory={self.paths.base_dir}
ExecStart={venv_python} {self.entry_script.resolve()}
Restart=on-failure
RestartSec=3
Environment=PYTHONUNBUFFERED=1
[Install]
WantedBy=default.target
"""
target = user_systemd_dir / service_name
target.write_text(service_content)
ConsoleUI.success(f"Service-Datei geschrieben: {target}")
try:
subprocess.run(["systemctl", "--user", "daemon-reload"], check=True)
ConsoleUI.success("systemd daemon neu geladen.")
except subprocess.CalledProcessError as exc:
ConsoleUI.warn(f"daemon-reload fehlgeschlagen: {exc}")
ConsoleUI.info(f"Service aktivieren: systemctl --user enable {service_name}")
ConsoleUI.info(f"Service starten: systemctl --user start {service_name}")
ConsoleUI.info(f"Status pruefen: systemctl --user status {service_name}")
ConsoleUI.info(f"Logs verfolgen: journalctl --user -u {service_name} -f")
def run(self) -> None:
ConsoleUI.headline("BackItUp Bootstrap")
self._bootstrap()
from app.config_store import ConfigStore
from app.setup_wizard import SetupWizard
from app.web_server import FlaskServer
store = ConfigStore(self.paths.db_path)
store.ensure_schema()
config = store.load_config()
if config is None:
ConsoleUI.warn("Keine vollstaendige Konfiguration gefunden.")
setup_data = SetupWizard().collect_initial()
store.save_config(setup_data.config)
store.create_user(
setup_data.admin_username,
setup_data.admin_password_hash,
is_admin=True,
)
config = setup_data.config
ConsoleUI.success("Konfiguration und Admin-Benutzer wurden gespeichert.")
elif not store.has_any_user():
ConsoleUI.warn("Keine Benutzer gefunden.")
admin_username, admin_hash = SetupWizard().collect_admin_user()
store.create_user(admin_username, admin_hash, is_admin=True)
ConsoleUI.success("Admin-Benutzer wurde gespeichert.")
ConsoleUI.success("System ist bereit.")
ConsoleUI.info(
f"Flask startet auf http://{config.ip}:{config.port} (debug={config.debug})"
)
FlaskServer(config=config, store=store).run()