From f36b72a5285c5dcf0a78c3167f28a86f63fafa3c Mon Sep 17 00:00:00 2001 From: "info@pi-farm.de" Date: Sat, 7 Mar 2026 00:02:08 +0000 Subject: [PATCH] main.py aktualisiert --- main.py | 91 +++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 56 insertions(+), 35 deletions(-) diff --git a/main.py b/main.py index 7fe3a27..4d225d6 100644 --- a/main.py +++ b/main.py @@ -174,6 +174,48 @@ class ConnectionManager: except: pass manager = ConnectionManager() +async def get_remote_info(ip, user): + """Versucht Linux/Mac-Infos zu lesen, falls fehlgeschlagen, dann Windows.""" + # 1. Versuch: Linux/Mac + linux_cmd = "uname -m && (sw_vers -productName 2>/dev/null || grep PRETTY_NAME /etc/os-release 2>/dev/null | cut -d= -f2 || uname -s) && (command -v docker >/dev/null 2>&1 && echo 1 || echo 0)" + ssh_cmd = f"ssh -o StrictHostKeyChecking=no -o ConnectTimeout=3 {user}@{ip} \"{linux_cmd}\"" + + try: + output = subprocess.check_output(ssh_cmd, shell=True, stderr=subprocess.DEVNULL).decode().strip().split('\n') + if len(output) >= 2: + return { + "arch": output[0], + "os": output[1].replace('"', ''), + "docker": int(output[2]) if len(output) > 2 else 0 + } + except: + pass # Linux-Versuch gescheitert, weiter zu Windows + + # 2. Versuch: Windows (CMD) + # ver = OS Version, echo %PROCESSOR_ARCHITECTURE% = Arch, where docker = Docker Check + win_cmd = 'ver && echo %PROCESSOR_ARCHITECTURE% && (where docker >nul 2>&1 && echo 1 || echo 0)' + ssh_cmd = f"ssh -o StrictHostKeyChecking=no -o ConnectTimeout=3 {user}@{ip} \"{win_cmd}\"" + + try: + output = subprocess.check_output(ssh_cmd, shell=True).decode().strip().split('\n') + # Windows Output sieht oft so aus: ["Microsoft Windows [Version 10.0...]", "AMD64", "1"] + raw_os = output[0] if len(output) > 0 else "Windows" + os_name = "Windows" + if "Version 10" in raw_os: os_name = "Windows 10/11" + elif "Version 11" in raw_os: os_name = "Windows 11" + + arch = output[1] if len(output) > 1 else "x86" + if "AMD64" in arch: arch = "x86-64" + + docker_val = int(output[2]) if len(output) > 2 else 0 + + return {"arch": arch, "os": os_name, "docker": docker_val} + except Exception as e: + print(f"Windows-Check fehlgeschlagen für {ip}: {e}") + return None + +# Nutze diese Funktion nun in bootstrap_node und refresh_status + # --- ERWEITERTES NODE BOOTSTRAPPING (Inventur) --- async def bootstrap_node(ip, user, password): await manager.broadcast(f"🔑 SSH-Handshake für {ip}...") @@ -186,36 +228,21 @@ async def bootstrap_node(ip, user, password): return # 2. System-Infos abrufen (Inventur) - await manager.broadcast(f"🔍 Inventur auf {ip} wird durchgeführt...") +await manager.broadcast(f"🔍 Inventur auf {ip} wird durchgeführt...") + info = await get_remote_info(ip, user) - # Befehlskette: Arch, OS-Name, Docker-Check - inspect_cmd = "uname -m && (sw_vers -productName 2>/dev/null || grep PRETTY_NAME /etc/os-release 2>/dev/null | cut -d= -f2 || uname -s) && (command -v docker >/dev/null 2>&1 && echo 1 || echo 0)" - ssh_cmd = f"ssh -o StrictHostKeyChecking=no {user}@{ip} \"{inspect_cmd}\"" - - try: - output = subprocess.check_output(ssh_cmd, shell=True).decode().strip().split('\n') - arch = output[0] if len(output) > 0 else "Unbekannt" - # Mapping für Architektur - if "aarch64" in arch.lower(): arch = "arm64" - elif "x86_64" in arch.lower(): arch = "x86-64" - - os_name = output[1].replace('"', '') if len(output) > 1 else "Linux" - docker_val = int(output[2]) if len(output) > 2 else 0 - - status = "Docker Aktiv" if docker_val else "Bereit (Kein Docker)" - - # Datenbank Update + if info: + status = "Docker Aktiv" if info['docker'] else "Bereit (Kein Docker)" conn = get_db() conn.execute(''' UPDATE nodes SET os = ?, arch = ?, docker_installed = ?, status = ? WHERE ip = ? - ''', (os_name, arch, docker_val, status, ip)) + ''', (info['os'], info['arch'], info['docker'], status, ip)) conn.commit() conn.close() - await manager.broadcast(f"✅ Node {ip} konfiguriert ({os_name}, {arch}).") - except Exception as e: - await manager.broadcast(f"⚠️ Inventur auf {ip} unvollständig: {e}") - + await manager.broadcast(f"✅ Node {ip} erkannt als {info['os']} ({info['arch']}).") + else: + await manager.broadcast(f"⚠️ Inventur auf {ip} fehlgeschlagen.") # --- ROUTES --- @app.get("/") @@ -305,21 +332,15 @@ async def refresh_status(node_id: int): node = conn.execute('SELECT * FROM nodes WHERE id = ?', (node_id,)).fetchone() if not node: return {"status": "Offline"} - inspect_cmd = "uname -m && (sw_vers -productName 2>/dev/null || grep PRETTY_NAME /etc/os-release 2>/dev/null | cut -d= -f2 || uname -s) && (command -v docker >/dev/null 2>&1 && echo 1 || echo 0)" - ssh_cmd = f"ssh -o StrictHostKeyChecking=no -o ConnectTimeout=3 {node['user']}@{node['ip']} \"{inspect_cmd}\"" + info = await get_remote_info(node['ip'], node['user']) - try: - output = subprocess.check_output(ssh_cmd, shell=True).decode().strip().split('\n') - arch = output[0]; os_name = output[1].replace('"', ''); docker_val = int(output[2]) - if "aarch64" in arch.lower(): arch = "arm64" - elif "x86_64" in arch.lower(): arch = "x86-64" - new_status = "Docker Aktiv" if docker_val else "Bereit (Kein Docker)" - + if info: + new_status = "Docker Aktiv" if info['docker'] else "Bereit (Kein Docker)" conn.execute('UPDATE nodes SET status=?, os=?, arch=?, docker_installed=? WHERE id=?', - (new_status, os_name, arch, docker_val, node_id)) + (new_status, info['os'], info['arch'], info['docker'], node_id)) conn.commit() - result = {"status": new_status, "os": os_name, "arch": arch, "docker": docker_val} - except: + result = {"status": new_status, "os": info['os'], "arch": info['arch'], "docker": info['docker']} + else: new_status = "Offline" conn.execute('UPDATE nodes SET status=? WHERE id=?', (new_status, node_id)) conn.commit()