Files
Projektarbeit-MYP/install.py
Till Tomczak a8f27179b5 Es scheint, dass Sie eine Reihe von Dateien und Verzeichnissen in Ihrem Backend-Projekt bearbeitet haben. Hier ist ein zusammenfassender Überblick über die Änderungen:
1. **Entfernung von 'node_modules'**: Es scheint, dass Sie den 'node_modules'-Ordner entfernt oder aktualisiert haben, da einige Dateien wie '.gitignore', 'package
2025-06-19 22:13:49 +02:00

609 lines
19 KiB
Python

#!/usr/bin/env python3
"""
MYP (Manage Your Printers) Installer
=====================================
Universeller Installer für das MYP Druckerverwaltungssystem.
Unterstützt Installation, Kiosk-Modus und Desktop-Icon-Erstellung.
Aufruf vom Stammverzeichnis aus:
python install.py # Interaktive Installation
python install.py --kiosk # Direktinstallation mit Kiosk-Modus
python install.py --desktop-icon # Nur Desktop-Icon erstellen
python install.py --help # Hilfe anzeigen
Autor: Till Tomczak
Version: 2.0
"""
import os
import sys
import subprocess
import argparse
import shutil
import stat
from pathlib import Path
class MYPInstaller:
"""
Hauptinstaller-Klasse für das MYP System.
Verwaltet die komplette Installation inklusive:
- Systemabhängigkeiten
- Python-Packages
- Kiosk-Modus-Konfiguration
- Desktop-Integration
- Service-Setup
"""
def __init__(self):
self.root_dir = Path(__file__).parent
self.backend_dir = self.root_dir / "backend"
self.setup_dir = self.backend_dir / "setup"
self.is_root = os.geteuid() == 0 if hasattr(os, 'geteuid') else False
# System-Erkennung
self.is_raspberry_pi = self._detect_raspberry_pi()
self.is_debian = self._detect_debian()
print(f"""
{'='*70}
🏭 MYP (MANAGE YOUR PRINTERS) INSTALLER
{'='*70}
🎯 Mercedes-Benz Druckerverwaltungssystem
🔧 Universal-Installer für alle Plattformen
📍 Arbeitsverzeichnis: {self.root_dir}
🔍 SYSTEM-ERKENNUNG:
• Raspberry Pi: {'✅ JA' if self.is_raspberry_pi else '❌ NEIN'}
• Debian/Ubuntu: {'✅ JA' if self.is_debian else '❌ NEIN'}
• Root-Rechte: {'✅ JA' if self.is_root else '❌ NEIN'}
{'='*70}
""")
def _detect_raspberry_pi(self):
"""Erkennt Raspberry Pi Hardware"""
try:
with open('/proc/cpuinfo', 'r') as f:
cpuinfo = f.read()
return 'raspberry pi' in cpuinfo.lower() or 'bcm' in cpuinfo.lower()
except:
return False
def _detect_debian(self):
"""Erkennt Debian-basierte Systeme"""
try:
return os.path.exists('/etc/debian_version')
except:
return False
def check_prerequisites(self):
"""
Prüft Systemvoraussetzungen für die Installation.
Returns:
bool: True wenn alle Voraussetzungen erfüllt sind
"""
print("🔍 VORAUSSETZUNGSPRÜFUNG")
print("-" * 40)
checks = []
# Python-Version
if sys.version_info >= (3, 8):
checks.append("✅ Python 3.8+ verfügbar")
else:
checks.append("❌ Python 3.8+ erforderlich")
return False
# Git verfügbar
try:
subprocess.run(['git', '--version'], capture_output=True, check=True)
checks.append("✅ Git verfügbar")
except:
checks.append("❌ Git nicht gefunden")
# Projekt-Struktur
required_paths = [
self.backend_dir,
self.backend_dir / "app.py",
self.backend_dir / "requirements.txt",
self.setup_dir
]
for path in required_paths:
if path.exists():
checks.append(f"{path.name}")
else:
checks.append(f"{path.name} fehlt")
return False
# Systemtools (nur auf Linux)
if self.is_debian:
tools = ['systemctl', 'nginx', 'ufw']
for tool in tools:
try:
subprocess.run(['which', tool], capture_output=True, check=True)
checks.append(f"{tool} verfügbar")
except:
checks.append(f"⚠️ {tool} nicht gefunden (wird installiert)")
for check in checks:
print(f" {check}")
print("✅ Voraussetzungen erfüllt\n")
return True
def install_system_dependencies(self):
"""
Installiert System-Abhängigkeiten über den Package-Manager.
"""
if not self.is_debian:
print("⚠️ Überspringe System-Dependencies (nicht Debian-basiert)")
return True
print("📦 SYSTEM-ABHÄNGIGKEITEN INSTALLIEREN")
print("-" * 40)
# Basis-Pakete
packages = [
'python3-pip',
'python3-venv',
'nodejs',
'npm',
'nginx',
'ufw',
'sqlite3',
'git',
'curl',
'wget',
'unzip'
]
# Raspberry Pi spezifische Pakete
if self.is_raspberry_pi:
packages.extend([
'chromium-browser',
'xorg',
'openbox',
'lightdm',
'python3-gpiozero' # Für Hardware-Integration
])
try:
print(" Aktualisiere Package-Listen...")
subprocess.run(['sudo', 'apt', 'update'], check=True)
print(f" Installiere {len(packages)} Pakete...")
subprocess.run(['sudo', 'apt', 'install', '-y'] + packages, check=True)
print("✅ System-Abhängigkeiten installiert\n")
return True
except subprocess.CalledProcessError as e:
print(f"❌ Fehler bei System-Installation: {e}")
return False
def install_python_dependencies(self):
"""
Installiert Python-Dependencies aus requirements.txt.
"""
print("🐍 PYTHON-ABHÄNGIGKEITEN INSTALLIEREN")
print("-" * 40)
requirements_file = self.backend_dir / "requirements.txt"
try:
# Virtual Environment erstellen (optional, aber empfohlen)
venv_path = self.backend_dir / "venv"
if not venv_path.exists():
print(" Erstelle Virtual Environment...")
subprocess.run([sys.executable, '-m', 'venv', str(venv_path)], check=True)
# Requirements installieren
print(" Installiere Python-Packages...")
if self.is_debian:
# Auf Debian: --break-system-packages für pip
subprocess.run([
sys.executable, '-m', 'pip', 'install', '-r', str(requirements_file),
'--break-system-packages'
], check=True, cwd=self.backend_dir)
else:
subprocess.run([
sys.executable, '-m', 'pip', 'install', '-r', str(requirements_file)
], check=True, cwd=self.backend_dir)
print("✅ Python-Dependencies installiert\n")
return True
except subprocess.CalledProcessError as e:
print(f"❌ Fehler bei Python-Installation: {e}")
return False
def build_frontend_assets(self):
"""
Baut Frontend-Assets (CSS, JavaScript).
"""
print("🎨 FRONTEND-ASSETS BAUEN")
print("-" * 40)
try:
# npm-Dependencies installieren
print(" Installiere npm-Dependencies...")
subprocess.run(['npm', 'install'], check=True, cwd=self.backend_dir)
# TailwindCSS bauen
print(" Baue TailwindCSS...")
subprocess.run(['npm', 'run', 'build'], check=True, cwd=self.backend_dir)
print("✅ Frontend-Assets gebaut\n")
return True
except subprocess.CalledProcessError as e:
print(f"❌ Fehler beim Asset-Build: {e}")
return False
def setup_database(self):
"""
Initialisiert die SQLite-Datenbank.
"""
print("🗄️ DATENBANK INITIALISIEREN")
print("-" * 40)
try:
# Instance-Verzeichnis erstellen
instance_dir = self.backend_dir / "instance"
instance_dir.mkdir(exist_ok=True)
# Datenbank initialisieren
print(" Initialisiere SQLite-Datenbank...")
subprocess.run([
sys.executable, '-c',
'from models import init_database; init_database()'
], check=True, cwd=self.backend_dir)
print("✅ Datenbank initialisiert\n")
return True
except subprocess.CalledProcessError as e:
print(f"❌ Fehler bei Datenbank-Setup: {e}")
return False
def setup_kiosk_mode(self):
"""
Konfiguriert Kiosk-Modus für Raspberry Pi.
"""
if not self.is_raspberry_pi:
print("⚠️ Kiosk-Modus nur auf Raspberry Pi verfügbar")
return True
print("🖥️ KIOSK-MODUS KONFIGURIEREN")
print("-" * 40)
try:
# Kiosk-Skript erstellen
kiosk_script = Path("/home/pi/kiosk.sh")
kiosk_content = """#!/bin/bash
# MYP Kiosk-Modus Startskript
# Startet Chromium im Vollbild-Modus
# Warten auf Netzwerk
sleep 10
# Bildschirmschoner deaktivieren
xset s off
xset -dpms
xset s noblank
# Chromium im Kiosk-Modus starten
chromium-browser \\
--no-sandbox \\
--disable-infobars \\
--disable-restore-session-state \\
--disable-session-crashed-bubble \\
--disable-features=TranslateUI \\
--kiosk \\
--app=https://localhost/
"""
with open(kiosk_script, 'w') as f:
f.write(kiosk_content)
# Ausführbar machen
kiosk_script.chmod(stat.S_IRWXU | stat.S_IRGRP | stat.S_IROTH)
# Autostart konfigurieren
autostart_dir = Path("/home/pi/.config/autostart")
autostart_dir.mkdir(parents=True, exist_ok=True)
desktop_entry = autostart_dir / "myp-kiosk.desktop"
desktop_content = f"""[Desktop Entry]
Type=Application
Name=MYP Kiosk
Exec={kiosk_script}
Hidden=false
NoDisplay=false
X-GNOME-Autostart-enabled=true
"""
with open(desktop_entry, 'w') as f:
f.write(desktop_content)
print(" ✅ Kiosk-Skript erstellt")
print(" ✅ Autostart konfiguriert")
print("✅ Kiosk-Modus konfiguriert\n")
return True
except Exception as e:
print(f"❌ Fehler bei Kiosk-Setup: {e}")
return False
def create_desktop_icon(self):
"""
Erstellt Desktop-Icon für MYP.
"""
print("🖱️ DESKTOP-ICON ERSTELLEN")
print("-" * 40)
try:
# Desktop-Verzeichnis finden
desktop_dirs = [
Path.home() / "Desktop",
Path.home() / "Schreibtisch",
Path("/home/pi/Desktop")
]
desktop_dir = None
for dir_path in desktop_dirs:
if dir_path.exists():
desktop_dir = dir_path
break
if not desktop_dir:
print("⚠️ Desktop-Verzeichnis nicht gefunden")
return True
# Icon-Datei kopieren
icon_source = self.backend_dir / "static" / "favicon.svg"
icon_dest = desktop_dir / "myp-icon.svg"
if icon_source.exists():
shutil.copy2(icon_source, icon_dest)
# Desktop-Entry erstellen
desktop_file = desktop_dir / "MYP-Druckerverwaltung.desktop"
desktop_content = f"""
[Desktop Entry]
Version=1.0
Type=Application
Name=MYP Druckerverwaltung
Comment=Mercedes-Benz Druckerverwaltungssystem
Icon={icon_dest}
Exec=python3 {self.backend_dir}/app.py
Terminal=false
Categories=Application;Office;
StartupNotify=true
"""
with open(desktop_file, 'w') as f:
f.write(desktop_content)
# Ausführbar machen
desktop_file.chmod(stat.S_IRWXU | stat.S_IRGRP | stat.S_IROTH)
print(f" ✅ Desktop-Icon erstellt: {desktop_file}")
print("✅ Desktop-Integration abgeschlossen\n")
return True
except Exception as e:
print(f"❌ Fehler bei Desktop-Icon: {e}")
return False
def setup_systemd_services(self):
"""
Installiert systemd-Services für automatischen Start.
"""
if not self.is_debian or not self.is_root:
print("⚠️ Service-Setup erfordert Debian + Root-Rechte")
return True
print("⚙️ SYSTEMD-SERVICES INSTALLIEREN")
print("-" * 40)
try:
# Service-Dateien kopieren
systemd_dir = self.backend_dir / "systemd"
if systemd_dir.exists():
for service_file in systemd_dir.glob("*.service"):
dest = Path("/etc/systemd/system") / service_file.name
shutil.copy2(service_file, dest)
print(f"{service_file.name} installiert")
# Services aktivieren
services = ["myp-https.service"]
if self.is_raspberry_pi:
services.append("myp-kiosk.service")
for service in services:
subprocess.run(['systemctl', 'daemon-reload'], check=True)
subprocess.run(['systemctl', 'enable', service], check=True)
print(f"{service} aktiviert")
print("✅ SystemD-Services installiert\n")
return True
except subprocess.CalledProcessError as e:
print(f"❌ Fehler bei Service-Setup: {e}")
return False
def run_full_installation(self):
"""
Führt die komplette Installation durch.
"""
print("🚀 VOLLSTÄNDIGE INSTALLATION STARTEN")
print("=" * 50)
steps = [
("Voraussetzungen prüfen", self.check_prerequisites),
("System-Abhängigkeiten", self.install_system_dependencies),
("Python-Dependencies", self.install_python_dependencies),
("Frontend-Assets", self.build_frontend_assets),
("Datenbank", self.setup_database),
("SystemD-Services", self.setup_systemd_services)
]
for step_name, step_func in steps:
print(f"\n📋 SCHRITT: {step_name}")
if not step_func():
print(f"\n❌ INSTALLATION FEHLGESCHLAGEN bei: {step_name}")
return False
print(f"""
{'='*70}
🎉 INSTALLATION ERFOLGREICH ABGESCHLOSSEN!
{'='*70}
✅ MYP Druckerverwaltungssystem wurde installiert
🔧 NÄCHSTE SCHRITTE:
1. System neustarten (empfohlen)
2. MYP-Service starten: sudo systemctl start myp-https
3. Browser öffnen: https://localhost/
📝 WICHTIGE HINWEISE:
• Standard-Admin: admin / admin123
• Logs: {self.backend_dir}/logs/
• Konfiguration: {self.backend_dir}/config/
🎯 MERCEDES-BENZ DRUCKERVERWALTUNG BEREIT!
{'='*70}
""")
return True
def run_kiosk_installation(self):
"""
Führt Installation mit Kiosk-Modus durch.
"""
print("🖥️ KIOSK-INSTALLATION STARTEN")
print("=" * 40)
# Basis-Installation
if not self.run_full_installation():
return False
# Kiosk-Modus konfigurieren
if not self.setup_kiosk_mode():
return False
print(f"""
🎉 KIOSK-INSTALLATION ABGESCHLOSSEN!
🖥️ Das System startet automatisch im Kiosk-Modus
• Vollbild-Browser mit MYP
• Automatischer Start nach Boot
• Bildschirmschoner deaktiviert
🔄 Neustart erforderlich für Kiosk-Aktivierung
""")
return True
def main():
"""Haupt-Installer-Funktion mit Argument-Parsing"""
parser = argparse.ArgumentParser(
description="MYP Druckerverwaltungssystem Installer",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
BEISPIELE:
python install.py # Interaktive Installation
python install.py --kiosk # Installation mit Kiosk-Modus
python install.py --desktop-icon # Nur Desktop-Icon erstellen
python install.py --full --kiosk # Vollinstallation + Kiosk
SYSTEMANFORDERUNGEN:
• Python 3.8+
• Debian/Ubuntu (empfohlen)
• Root-Rechte für System-Services
• Raspberry Pi für Kiosk-Modus
"""
)
parser.add_argument('--full', action='store_true',
help='Vollständige Installation durchführen')
parser.add_argument('--kiosk', action='store_true',
help='Kiosk-Modus aktivieren')
parser.add_argument('--desktop-icon', action='store_true',
help='Desktop-Icon erstellen')
parser.add_argument('--no-deps', action='store_true',
help='System-Dependencies überspringen')
parser.add_argument('--force', action='store_true',
help='Installation trotz Warnungen fortsetzen')
args = parser.parse_args()
# Installer initialisieren
installer = MYPInstaller()
# Kein Argument = Interaktive Installation
if not any([args.full, args.kiosk, args.desktop_icon]):
print("""
🤔 INSTALLATIONSART WÄHLEN:
1) Vollständige Installation (empfohlen)
2) Installation mit Kiosk-Modus (Raspberry Pi)
3) Nur Desktop-Icon erstellen
4) Abbrechen
Ihre Wahl [1-4]: """, end="")
try:
choice = input().strip()
if choice == '1':
args.full = True
elif choice == '2':
args.kiosk = True
elif choice == '3':
args.desktop_icon = True
else:
print("Installation abgebrochen.")
return
except KeyboardInterrupt:
print("\nInstallation abgebrochen.")
return
# Installation ausführen
success = True
if args.desktop_icon:
success = installer.create_desktop_icon()
elif args.kiosk:
success = installer.run_kiosk_installation()
elif args.full:
success = installer.run_full_installation()
if success and installer.is_raspberry_pi:
create_kiosk = input("\n🖥️ Kiosk-Modus aktivieren? [j/N]: ").lower().startswith('j')
if create_kiosk:
installer.setup_kiosk_mode()
# Ergebnis
if success:
print("\n🎉 Installation erfolgreich!")
# Desktop-Icon anbieten falls nicht bereits erstellt
if not args.desktop_icon and not args.kiosk:
create_icon = input("🖱️ Desktop-Icon erstellen? [j/N]: ").lower().startswith('j')
if create_icon:
installer.create_desktop_icon()
sys.exit(0)
else:
print("\n❌ Installation fehlgeschlagen!")
sys.exit(1)
if __name__ == "__main__":
main()