🎉 Refactor and optimize database files, enhance error handling with new utility scripts 📚, and update documentation on fault tolerance and unattended operation. 🚀
This commit is contained in:
270
backend/app.py
270
backend/app.py
@@ -1241,6 +1241,239 @@ def kiosk_restart_system():
|
||||
kiosk_logger.error(f"Fehler beim System-Neustart: {str(e)}")
|
||||
return jsonify({"error": "Fehler beim Neustart"}), 500
|
||||
|
||||
|
||||
# ===== ERWEITERTE SYSTEM-CONTROL API-ENDPUNKTE =====
|
||||
|
||||
@app.route('/api/admin/system/restart', methods=['POST'])
|
||||
@login_required
|
||||
@admin_required
|
||||
def api_admin_system_restart():
|
||||
"""Robuster System-Neustart mit Sicherheitsprüfungen."""
|
||||
try:
|
||||
from utils.system_control import schedule_system_restart
|
||||
|
||||
data = request.get_json() or {}
|
||||
delay_seconds = data.get('delay_seconds', 60)
|
||||
reason = data.get('reason', 'Manueller Admin-Neustart')
|
||||
force = data.get('force', False)
|
||||
|
||||
# Begrenze Verzögerung auf sinnvolle Werte
|
||||
delay_seconds = max(10, min(3600, delay_seconds)) # 10s bis 1h
|
||||
|
||||
result = schedule_system_restart(
|
||||
delay_seconds=delay_seconds,
|
||||
user_id=str(current_user.id),
|
||||
reason=reason,
|
||||
force=force
|
||||
)
|
||||
|
||||
if result.get('success'):
|
||||
app_logger.warning(f"System-Neustart geplant von Admin {current_user.username}: {reason}")
|
||||
return jsonify(result)
|
||||
else:
|
||||
return jsonify(result), 400
|
||||
|
||||
except Exception as e:
|
||||
app_logger.error(f"Fehler bei System-Neustart-Planung: {e}")
|
||||
return jsonify({"success": False, "error": str(e)}), 500
|
||||
|
||||
|
||||
@app.route('/api/admin/system/shutdown', methods=['POST'])
|
||||
@login_required
|
||||
@admin_required
|
||||
def api_admin_system_shutdown():
|
||||
"""Robuster System-Shutdown mit Sicherheitsprüfungen."""
|
||||
try:
|
||||
from utils.system_control import schedule_system_shutdown
|
||||
|
||||
data = request.get_json() or {}
|
||||
delay_seconds = data.get('delay_seconds', 30)
|
||||
reason = data.get('reason', 'Manueller Admin-Shutdown')
|
||||
force = data.get('force', False)
|
||||
|
||||
# Begrenze Verzögerung auf sinnvolle Werte
|
||||
delay_seconds = max(10, min(3600, delay_seconds)) # 10s bis 1h
|
||||
|
||||
result = schedule_system_shutdown(
|
||||
delay_seconds=delay_seconds,
|
||||
user_id=str(current_user.id),
|
||||
reason=reason,
|
||||
force=force
|
||||
)
|
||||
|
||||
if result.get('success'):
|
||||
app_logger.warning(f"System-Shutdown geplant von Admin {current_user.username}: {reason}")
|
||||
return jsonify(result)
|
||||
else:
|
||||
return jsonify(result), 400
|
||||
|
||||
except Exception as e:
|
||||
app_logger.error(f"Fehler bei System-Shutdown-Planung: {e}")
|
||||
return jsonify({"success": False, "error": str(e)}), 500
|
||||
|
||||
|
||||
@app.route('/api/admin/kiosk/restart', methods=['POST'])
|
||||
@login_required
|
||||
@admin_required
|
||||
def api_admin_kiosk_restart():
|
||||
"""Kiosk-Display neustarten ohne System-Neustart."""
|
||||
try:
|
||||
from utils.system_control import restart_kiosk
|
||||
|
||||
data = request.get_json() or {}
|
||||
delay_seconds = data.get('delay_seconds', 10)
|
||||
reason = data.get('reason', 'Manueller Kiosk-Neustart')
|
||||
|
||||
# Begrenze Verzögerung
|
||||
delay_seconds = max(0, min(300, delay_seconds)) # 0s bis 5min
|
||||
|
||||
result = restart_kiosk(
|
||||
delay_seconds=delay_seconds,
|
||||
user_id=str(current_user.id),
|
||||
reason=reason
|
||||
)
|
||||
|
||||
if result.get('success'):
|
||||
app_logger.info(f"Kiosk-Neustart geplant von Admin {current_user.username}: {reason}")
|
||||
return jsonify(result)
|
||||
else:
|
||||
return jsonify(result), 400
|
||||
|
||||
except Exception as e:
|
||||
app_logger.error(f"Fehler bei Kiosk-Neustart-Planung: {e}")
|
||||
return jsonify({"success": False, "error": str(e)}), 500
|
||||
|
||||
|
||||
@app.route('/api/admin/system/status', methods=['GET'])
|
||||
@login_required
|
||||
@admin_required
|
||||
def api_admin_system_status_extended():
|
||||
"""Erweiterte System-Status-Informationen."""
|
||||
try:
|
||||
from utils.system_control import get_system_status
|
||||
from utils.error_recovery import get_error_recovery_manager
|
||||
|
||||
# System-Control-Status
|
||||
system_status = get_system_status()
|
||||
|
||||
# Error-Recovery-Status
|
||||
error_manager = get_error_recovery_manager()
|
||||
error_stats = error_manager.get_error_statistics()
|
||||
|
||||
# Kombiniere alle Informationen
|
||||
combined_status = {
|
||||
**system_status,
|
||||
"error_recovery": error_stats,
|
||||
"resilience_features": {
|
||||
"auto_recovery_enabled": error_stats.get('auto_recovery_enabled', False),
|
||||
"monitoring_active": error_stats.get('monitoring_active', False),
|
||||
"recovery_success_rate": error_stats.get('recovery_success_rate', 0)
|
||||
}
|
||||
}
|
||||
|
||||
return jsonify(combined_status)
|
||||
|
||||
except Exception as e:
|
||||
app_logger.error(f"Fehler bei System-Status-Abfrage: {e}")
|
||||
return jsonify({"success": False, "error": str(e)}), 500
|
||||
|
||||
|
||||
@app.route('/api/admin/system/operations', methods=['GET'])
|
||||
@login_required
|
||||
@admin_required
|
||||
def api_admin_system_operations():
|
||||
"""Gibt geplante und vergangene System-Operationen zurück."""
|
||||
try:
|
||||
from utils.system_control import get_system_control_manager
|
||||
|
||||
manager = get_system_control_manager()
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"pending_operations": manager.get_pending_operations(),
|
||||
"operation_history": manager.get_operation_history(limit=50)
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
app_logger.error(f"Fehler bei Operations-Abfrage: {e}")
|
||||
return jsonify({"success": False, "error": str(e)}), 500
|
||||
|
||||
|
||||
@app.route('/api/admin/system/operations/<operation_id>/cancel', methods=['POST'])
|
||||
@login_required
|
||||
@admin_required
|
||||
def api_admin_cancel_operation(operation_id):
|
||||
"""Bricht geplante System-Operation ab."""
|
||||
try:
|
||||
from utils.system_control import get_system_control_manager
|
||||
|
||||
manager = get_system_control_manager()
|
||||
result = manager.cancel_operation(operation_id)
|
||||
|
||||
if result.get('success'):
|
||||
app_logger.info(f"Operation {operation_id} abgebrochen von Admin {current_user.username}")
|
||||
return jsonify(result)
|
||||
else:
|
||||
return jsonify(result), 400
|
||||
|
||||
except Exception as e:
|
||||
app_logger.error(f"Fehler beim Abbrechen von Operation {operation_id}: {e}")
|
||||
return jsonify({"success": False, "error": str(e)}), 500
|
||||
|
||||
|
||||
@app.route('/api/admin/error-recovery/status', methods=['GET'])
|
||||
@login_required
|
||||
@admin_required
|
||||
def api_admin_error_recovery_status():
|
||||
"""Gibt Error-Recovery-Status und -Statistiken zurück."""
|
||||
try:
|
||||
from utils.error_recovery import get_error_recovery_manager
|
||||
|
||||
manager = get_error_recovery_manager()
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"statistics": manager.get_error_statistics(),
|
||||
"recent_errors": manager.get_recent_errors(limit=20)
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
app_logger.error(f"Fehler bei Error-Recovery-Status-Abfrage: {e}")
|
||||
return jsonify({"success": False, "error": str(e)}), 500
|
||||
|
||||
|
||||
@app.route('/api/admin/error-recovery/toggle', methods=['POST'])
|
||||
@login_required
|
||||
@admin_required
|
||||
def api_admin_toggle_error_recovery():
|
||||
"""Aktiviert/Deaktiviert Error-Recovery-Monitoring."""
|
||||
try:
|
||||
from utils.error_recovery import get_error_recovery_manager
|
||||
|
||||
data = request.get_json() or {}
|
||||
enable = data.get('enable', True)
|
||||
|
||||
manager = get_error_recovery_manager()
|
||||
|
||||
if enable:
|
||||
manager.start_monitoring()
|
||||
message = "Error-Recovery-Monitoring aktiviert"
|
||||
else:
|
||||
manager.stop_monitoring()
|
||||
message = "Error-Recovery-Monitoring deaktiviert"
|
||||
|
||||
app_logger.info(f"{message} von Admin {current_user.username}")
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"message": message,
|
||||
"monitoring_active": manager.is_active
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
app_logger.error(f"Fehler beim Toggle von Error-Recovery: {e}")
|
||||
return jsonify({"success": False, "error": str(e)}), 500
|
||||
|
||||
# ===== BENUTZER-ROUTEN (ehemals user.py) =====
|
||||
|
||||
@app.route("/user/profile", methods=["GET"])
|
||||
@@ -8718,6 +8951,43 @@ if __name__ == "__main__":
|
||||
app_logger.error(f"❌ Shutdown-Manager konnte nicht geladen werden: {e}")
|
||||
# Fallback auf die alte Methode
|
||||
shutdown_manager = None
|
||||
|
||||
# ===== INITIALISIERE FEHLERRESILIENZ-SYSTEME =====
|
||||
try:
|
||||
from utils.error_recovery import start_error_monitoring, stop_error_monitoring
|
||||
from utils.system_control import get_system_control_manager
|
||||
|
||||
# Error-Recovery-Monitoring starten
|
||||
start_error_monitoring()
|
||||
app_logger.info("✅ Error-Recovery-Monitoring gestartet")
|
||||
|
||||
# System-Control-Manager initialisieren
|
||||
system_control_manager = get_system_control_manager()
|
||||
app_logger.info("✅ System-Control-Manager initialisiert")
|
||||
|
||||
# Integriere in Shutdown-Manager
|
||||
if shutdown_manager:
|
||||
shutdown_manager.register_cleanup_function(
|
||||
func=stop_error_monitoring,
|
||||
name="Error Recovery Monitoring",
|
||||
priority=2,
|
||||
timeout=10
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
app_logger.error(f"❌ Fehlerresilienz-Systeme konnten nicht initialisiert werden: {e}")
|
||||
|
||||
# ===== KIOSK-SERVICE-OPTIMIERUNG =====
|
||||
try:
|
||||
# Stelle sicher, dass der Kiosk-Service korrekt konfiguriert ist
|
||||
kiosk_service_exists = os.path.exists('/etc/systemd/system/myp-kiosk.service')
|
||||
if not kiosk_service_exists:
|
||||
app_logger.warning("⚠️ Kiosk-Service nicht gefunden - Kiosk-Funktionen eventuell eingeschränkt")
|
||||
else:
|
||||
app_logger.info("✅ Kiosk-Service-Konfiguration gefunden")
|
||||
|
||||
except Exception as e:
|
||||
app_logger.error(f"❌ Kiosk-Service-Check fehlgeschlagen: {e}")
|
||||
|
||||
# Windows-spezifisches Signal-Handling als Fallback
|
||||
def fallback_signal_handler(sig, frame):
|
||||
|
Reference in New Issue
Block a user