pi_admin/main.py aktualisiert

This commit is contained in:
2026-03-03 21:12:32 +00:00
parent b94a23e4a3
commit b9c8d0eff3

View File

@@ -1,14 +1,20 @@
import json
import os import os
from fastapi import FastAPI, Request, WebSocket import subprocess
import pty
import select
import threading
import json
import paramiko
from fastapi import FastAPI, WebSocket, BackgroundTasks, Request
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates from fastapi.templating import Jinja2Templates
from fastapi.staticfiles import StaticFiles from fastapi.staticfiles import StaticFiles
import paramiko
from python_on_whales import DockerClient from python_on_whales import DockerClient
app = FastAPI() app = FastAPI()
templates = Jinja2Templates(directory="templates") templates = Jinja2Templates(directory="templates")
# Pfad zum SSH-Key
SSH_KEY = os.path.expanduser("~/.ssh/id_rsa")
# Speicher für Nodes (einfache JSON-Datei) # Speicher für Nodes (einfache JSON-Datei)
NODES_FILE = "nodes.json" NODES_FILE = "nodes.json"
@@ -112,6 +118,47 @@ async def chat_endpoint(websocket: WebSocket):
else: else:
await websocket.send_text("🤖 Auf welchem Pi soll ich Ollama installieren? (Nenne Name oder IP)") await websocket.send_text("🤖 Auf welchem Pi soll ich Ollama installieren? (Nenne Name oder IP)")
def ensure_ssh_key():
if not os.path.exists(SSH_KEY):
subprocess.run(["ssh-keygen", "-t", "rsa", "-N", "", "-f", SSH_KEY])
async def deploy_key_and_install(ip, user, password, ws: WebSocket):
ensure_ssh_key()
await ws.send_text(f"📦 Initialisiere Node {ip}...")
# 1. SSH-Key kopieren (automatisiert mit sshpass)
cmd_copy = f"sshpass -p '{password}' ssh-copy-id -o StrictHostKeyChecking=no {user}@{ip}"
process = subprocess.Popen(cmd_copy, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
for line in process.stdout:
await ws.send_text(f"🔑 SSH-Key: {line.strip()}")
# 2. Docker & Ollama Installation (Beispiel-Streaming)
await ws.send_text(f"🚀 Starte Setup auf {ip}...")
cmd_install = f"ssh {user}@{ip} 'curl -sSL https://get.docker.com | sh && curl -fsSL https://ollama.com/install.sh | sh'"
process = subprocess.Popen(cmd_install, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
for line in process.stdout:
await ws.send_text(f"🛠️ Install: {line.strip()}")
# --- WEB TERMINAL LOGIK (Vereinfacht) ---
@app.websocket("/ws/terminal/{ip}")
async def terminal_websocket(websocket: WebSocket, ip: str):
await websocket.accept()
# Öffne eine echte Shell-Sitzung zum Ziel-Node
(master_fd, slave_fd) = pty.openpty()
p = subprocess.Popen(["ssh", f"pi@{ip}"], stdin=slave_fd, stdout=slave_fd, stderr=slave_fd, text=True)
async def pty_to_ws():
while True:
await websocket.receive_text() # Input vom Browser empfangen (vereinfacht)
# Hier müsste xterm.js Input an master_fd geschrieben werden
# Hinweis: Ein volles Terminal braucht bidirektionales Streaming von Bytes.
await websocket.send_text(f"Verbunden mit {ip}. Terminal-Session gestartet.")
if __name__ == "__main__": if __name__ == "__main__":
import uvicorn import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000) uvicorn.run(app, host="0.0.0.0", port=8000)