Wartung (B10): Restart-Allowlist vereinheitlichen
Der ServicesCard-"Anzeige- statt Unit-Name"-Bug ist behoben (Frontend nutzt durchgehend x.unit). Der echte Rest-Fehler lag in der ZWEITEN Restart-Wahrheit: /api/system/restart (system.py) + das MCP-Tool restart_service hatten eine veraltete Allowlist ohne llama-swap (Engine) und hermes-terminal, dafuer mit Geist-Eintrag hermes-webui. Ein Engine-Neustart per Sprache/MCP schlug daher mit "nicht erlaubt" fehl. Fix: /api/system/restart delegiert jetzt an services.maintenance.restart_service (EINE Allowlist-Wahrheit, kennt System- via sudo -n UND User-Dienste, wird auch von der UI genutzt). MCP-Tool-Docstring auf die echten Dienste korrigiert. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -9,13 +9,14 @@ import logging
|
|||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
from fastapi import APIRouter, HTTPException
|
from fastapi import APIRouter
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
|
|
||||||
from config import GATEWAY_URL, HERMES_API_URL, LLAMA_SWAP_URL, MEM0_SERVICE_URL, VOICE_SERVICE_URL
|
from config import GATEWAY_URL, HERMES_API_URL, LLAMA_SWAP_URL, MEM0_SERVICE_URL, VOICE_SERVICE_URL
|
||||||
from services import backup as backup_svc
|
from services import backup as backup_svc
|
||||||
|
from services import maintenance
|
||||||
from services.agent import agent_status
|
from services.agent import agent_status
|
||||||
from services.gateway import gateway_reachable
|
from services.gateway import gateway_reachable
|
||||||
from services.llamaswap import engine_reachable, list_models
|
from services.llamaswap import engine_reachable, list_models
|
||||||
@@ -27,8 +28,6 @@ log = logging.getLogger(__name__)
|
|||||||
|
|
||||||
router = APIRouter(prefix="/api")
|
router = APIRouter(prefix="/api")
|
||||||
|
|
||||||
# Nur diese User-Dienste dürfen neugestartet werden.
|
|
||||||
ALLOWED_SERVICES = {"mission-control-2", "hermes-gateway", "hermes-webui", "mem0-service", "voice-service"}
|
|
||||||
# Quelle für Self-Update (auf der Box ~/mission-control-v2).
|
# Quelle für Self-Update (auf der Box ~/mission-control-v2).
|
||||||
SOURCE_DIR = os.path.expanduser(os.environ.get("MC2_SOURCE_DIR", "~/mission-control-v2"))
|
SOURCE_DIR = os.path.expanduser(os.environ.get("MC2_SOURCE_DIR", "~/mission-control-v2"))
|
||||||
|
|
||||||
@@ -99,9 +98,12 @@ class RestartReq(BaseModel):
|
|||||||
|
|
||||||
@router.post("/system/restart")
|
@router.post("/system/restart")
|
||||||
def restart(req: RestartReq) -> dict:
|
def restart(req: RestartReq) -> dict:
|
||||||
if req.service not in ALLOWED_SERVICES:
|
"""Dienst neustarten. Delegiert an den Wartungs-Service (EINE Allowlist-Wahrheit):
|
||||||
raise HTTPException(400, f"Dienst '{req.service}' nicht erlaubt.")
|
der kennt System-Dienste (llama-swap, via sudo -n) UND User-Dienste und wird auch von
|
||||||
return _run(["systemctl", "--user", "restart", req.service])
|
der UI (/api/maintenance/restart) genutzt. Vorher lag hier eine zweite, veraltete Liste
|
||||||
|
(ohne llama-swap/hermes-terminal, mit Geist-Eintrag hermes-webui) → Engine-Neustart per
|
||||||
|
Sprache/MCP schlug fehl."""
|
||||||
|
return maintenance.restart_service(req.service)
|
||||||
|
|
||||||
|
|
||||||
@router.post("/system/self-update")
|
@router.post("/system/self-update")
|
||||||
|
|||||||
+3
-2
@@ -226,8 +226,9 @@ def list_services() -> str:
|
|||||||
|
|
||||||
@mcp.tool()
|
@mcp.tool()
|
||||||
def restart_service(service: str) -> str:
|
def restart_service(service: str) -> str:
|
||||||
"""Startet einen erlaubten Dienst neu
|
"""Startet einen erlaubten Dienst neu. Erlaubt: llama-swap (Engine) | mission-control-2 |
|
||||||
(mission-control-2 | hermes-gateway | hermes-webui | mem0-service | voice-service)."""
|
hermes-gateway | hermes-terminal | mem0-service | voice-service. Der Engine-Neustart
|
||||||
|
(llama-swap = System-Dienst) kann das Box-Passwort verlangen, wenn kein NOPASSWD gesetzt ist."""
|
||||||
res = _post("/api/system/restart", {"service": service})
|
res = _post("/api/system/restart", {"service": service})
|
||||||
return f"Restart {service}: {'ok' if res.get('ok') else 'Fehler — ' + res.get('err', '')}"
|
return f"Restart {service}: {'ok' if res.get('ok') else 'Fehler — ' + res.get('err', '')}"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user