import os import json import socket import subprocess import platform import netifaces import requests from datetime import datetime import logging class NetworkConfig: """Verwaltet die Netzwerkkonfiguration für das MYP-System.""" CONFIG_FILE = 'instance/network_config.json' DEFAULT_CONFIG = { 'backend_hostname': '192.168.0.5', 'backend_port': 5000, 'frontend_hostname': '192.168.0.106', 'frontend_port': 3000 } def __init__(self, app=None): """Initialisierung der Netzwerkkonfiguration.""" self.logger = logging.getLogger('myp.network') self.config = self.DEFAULT_CONFIG.copy() self.last_check = None self.backend_status = "Nicht überprüft" self.frontend_status = "Nicht überprüft" # Stelle sicher, dass das Verzeichnis existiert os.makedirs(os.path.dirname(self.CONFIG_FILE), exist_ok=True) # Lade gespeicherte Konfiguration, falls vorhanden self.load_config() if app: self.init_app(app) def init_app(self, app): """Initialisiert die Anwendung mit dieser Konfiguration.""" app.network_config = self # Registriere Route für Netzwerkkonfiguration @app.route('/admin/network-config', methods=['GET', 'POST']) def network_config(): from flask import request, render_template, flash, redirect, url_for # Prüfe aktuelle Status self.check_connection_statuses() if request.method == 'POST': # Aktualisiere Konfiguration self.config['backend_hostname'] = request.form.get('backend_hostname', self.DEFAULT_CONFIG['backend_hostname']) self.config['backend_port'] = int(request.form.get('backend_port', self.DEFAULT_CONFIG['backend_port'])) self.config['frontend_hostname'] = request.form.get('frontend_hostname', self.DEFAULT_CONFIG['frontend_hostname']) self.config['frontend_port'] = int(request.form.get('frontend_port', self.DEFAULT_CONFIG['frontend_port'])) # Speichere Konfiguration self.save_config() # Teste die neue Konfiguration self.check_connection_statuses() flash('Netzwerkkonfiguration erfolgreich gespeichert!', 'success') return redirect(url_for('network_config')) # Ermittle Netzwerkschnittstellen network_interfaces = self.get_network_interfaces() return render_template('network_config.html', config=self.config, backend_status=self.backend_status, frontend_status=self.frontend_status, last_check=self.last_check, network_interfaces=network_interfaces, message=request.args.get('message'), message_type=request.args.get('message_type', 'info')) def load_config(self): """Lädt die gespeicherte Konfiguration.""" try: if os.path.exists(self.CONFIG_FILE): with open(self.CONFIG_FILE, 'r') as f: saved_config = json.load(f) self.config.update(saved_config) self.logger.info(f"Netzwerkkonfiguration geladen: {self.config}") else: self.logger.info(f"Keine gespeicherte Konfiguration gefunden, verwende Standardwerte: {self.config}") except Exception as e: self.logger.error(f"Fehler beim Laden der Netzwerkkonfiguration: {e}") def save_config(self): """Speichert die aktuelle Konfiguration.""" try: with open(self.CONFIG_FILE, 'w') as f: json.dump(self.config, f, indent=4) self.logger.info(f"Netzwerkkonfiguration gespeichert: {self.config}") return True except Exception as e: self.logger.error(f"Fehler beim Speichern der Netzwerkkonfiguration: {e}") return False def get_backend_url(self): """Gibt die Backend-URL zurück.""" return f"http://{self.config['backend_hostname']}:{self.config['backend_port']}" def get_frontend_url(self): """Gibt die Frontend-URL zurück.""" return f"http://{self.config['frontend_hostname']}:{self.config['frontend_port']}" def check_connection_statuses(self): """Überprüft den Verbindungsstatus zu Backend und Frontend.""" self.last_check = datetime.now().strftime("%d.%m.%Y %H:%M:%S") # Prüfe Backend-Verbindung backend_url = self.get_backend_url() try: response = requests.get(f"{backend_url}/api/test", timeout=3) if response.status_code == 200: self.backend_status = "Verbunden" else: self.backend_status = f"Fehler: HTTP {response.status_code}" except requests.exceptions.RequestException as e: self.backend_status = f"Nicht erreichbar: {str(e)}" # Prüfe Frontend-Verbindung frontend_url = self.get_frontend_url() try: response = requests.get(frontend_url, timeout=3) if response.status_code == 200: self.frontend_status = "Verbunden" else: self.frontend_status = f"Fehler: HTTP {response.status_code}" except requests.exceptions.RequestException as e: self.frontend_status = f"Nicht erreichbar: {str(e)}" self.logger.info(f"Verbindungsstatus - Backend: {self.backend_status}, Frontend: {self.frontend_status}") def get_network_interfaces(self): """Gibt Informationen zu allen Netzwerkschnittstellen zurück.""" interfaces = [] try: for interface in netifaces.interfaces(): if interface.startswith(('lo', 'docker', 'br-')): continue # Ignoriere Loopback und Docker-Interfaces addresses = [] try: addrs = netifaces.ifaddresses(interface) if netifaces.AF_INET in addrs: for addr in addrs[netifaces.AF_INET]: if 'addr' in addr: addresses.append(addr['addr']) except Exception as e: self.logger.error(f"Fehler beim Ermitteln der Adresse für Interface {interface}: {e}") if addresses: interfaces.append({ 'name': interface, 'address': ', '.join(addresses) }) except Exception as e: self.logger.error(f"Fehler beim Ermitteln der Netzwerkschnittstellen: {e}") return interfaces # Helper-Funktion zum Testen von Netzwerkverbindungen def test_connection(host, port, timeout=2): """Testet eine TCP-Verbindung zu einem Host und Port.""" try: socket.setdefaulttimeout(timeout) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((host, port)) s.close() return True except Exception as e: return False # Helper-Funktion zum Ping eines Hosts def ping_host(host, count=1): """Pingt einen Host an.""" param = '-n' if platform.system().lower() == 'windows' else '-c' command = ['ping', param, str(count), host] return subprocess.call(command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) == 0