dashboard-nanobot/backend/api/platform_node_probe_router.py

120 lines
5.4 KiB
Python
Raw Permalink Normal View History

2026-03-26 16:12:46 +00:00
import httpx
from fastapi import APIRouter, Depends, HTTPException, Request
from sqlmodel import Session
from clients.edge.http import HttpEdgeClient
from core.database import get_session
from schemas.platform import ManagedNodePayload
from api.platform_node_support import (
managed_node_from_payload,
normalize_node_payload,
test_edge_connectivity,
test_edge_native_preflight,
)
from api.platform_shared import invalidate_platform_nodes_cache
router = APIRouter()
@router.post("/api/platform/nodes/test")
def test_platform_node(payload: ManagedNodePayload, request: Request):
normalized = normalize_node_payload(payload)
temp_node = managed_node_from_payload(normalized)
result = test_edge_connectivity(
lambda _target: HttpEdgeClient(
node=temp_node,
http_client_factory=lambda: httpx.Client(timeout=10.0, trust_env=False),
async_http_client_factory=lambda: httpx.AsyncClient(timeout=10.0, trust_env=False),
),
temp_node,
)
return result.model_dump()
@router.post("/api/platform/nodes/native/preflight")
def test_platform_node_native_preflight(payload: ManagedNodePayload, request: Request):
normalized = normalize_node_payload(payload)
temp_node = managed_node_from_payload(normalized)
result = test_edge_native_preflight(
lambda _target: HttpEdgeClient(
node=temp_node,
http_client_factory=lambda: httpx.Client(timeout=10.0, trust_env=False),
async_http_client_factory=lambda: httpx.AsyncClient(timeout=10.0, trust_env=False),
),
temp_node,
native_command=str(normalized.native_command or "").strip() or None,
native_workdir=str(normalized.native_workdir or "").strip() or None,
)
return result.model_dump()
@router.post("/api/platform/nodes/{node_id}/test")
def test_saved_platform_node(node_id: str, request: Request, session: Session = Depends(get_session)):
normalized_node_id = str(node_id or "").strip().lower()
node_registry = getattr(request.app.state, "node_registry_service", None)
if node_registry is None or not hasattr(node_registry, "get_node"):
raise HTTPException(status_code=500, detail="node registry is unavailable")
node = node_registry.get_node(normalized_node_id)
if node is None:
raise HTTPException(status_code=404, detail=f"Managed node not found: {normalized_node_id}")
transport_kind = str((node.metadata or {}).get("transport_kind") or "edge").strip().lower()
if transport_kind != "edge":
invalidate_platform_nodes_cache()
raise HTTPException(status_code=400, detail="Only edge transport is supported")
result = test_edge_connectivity(
lambda _target: HttpEdgeClient(
node=node,
http_client_factory=lambda: httpx.Client(timeout=10.0, trust_env=False),
async_http_client_factory=lambda: httpx.AsyncClient(timeout=10.0, trust_env=False),
),
node,
)
if result.ok:
node_registry.mark_node_seen(
session,
node_id=node.node_id,
display_name=str(node.display_name or result.node_self.get("display_name") or node.node_id) if result.node_self else node.display_name,
capabilities=dict(result.node_self.get("capabilities") or {}) if result.node_self else dict(node.capabilities or {}),
resources=dict(result.node_self.get("resources") or {}) if result.node_self else dict(getattr(node, "resources", {}) or {}),
)
invalidate_platform_nodes_cache()
return result.model_dump()
@router.post("/api/platform/nodes/{node_id}/native/preflight")
def test_saved_platform_node_native_preflight(node_id: str, request: Request, session: Session = Depends(get_session)):
normalized_node_id = str(node_id or "").strip().lower()
node_registry = getattr(request.app.state, "node_registry_service", None)
if node_registry is None or not hasattr(node_registry, "get_node"):
raise HTTPException(status_code=500, detail="node registry is unavailable")
node = node_registry.get_node(normalized_node_id)
if node is None:
raise HTTPException(status_code=404, detail=f"Managed node not found: {normalized_node_id}")
transport_kind = str((node.metadata or {}).get("transport_kind") or "edge").strip().lower()
if transport_kind != "edge":
invalidate_platform_nodes_cache()
raise HTTPException(status_code=400, detail="Only edge transport is supported")
metadata = dict(node.metadata or {})
result = test_edge_native_preflight(
lambda _target: HttpEdgeClient(
node=node,
http_client_factory=lambda: httpx.Client(timeout=10.0, trust_env=False),
async_http_client_factory=lambda: httpx.AsyncClient(timeout=10.0, trust_env=False),
),
node,
native_command=str(metadata.get("native_command") or "").strip() or None,
native_workdir=str(metadata.get("native_workdir") or "").strip() or None,
)
if result.status == "online" and result.node_self:
node_registry.mark_node_seen(
session,
node_id=node.node_id,
display_name=str(node.display_name or result.node_self.get("display_name") or node.node_id),
capabilities=dict(result.node_self.get("capabilities") or {}),
resources=dict(result.node_self.get("resources") or {}),
)
invalidate_platform_nodes_cache()
return result.model_dump()