Local Agent v2.x
Local Agent
Nota (2026-07): el título original de esta página era “Local Agent v2.x” (snapshot de abril-2026). El número de versión NO se ancla aquí: la fuente de verdad es
terminal/agent/version.py(AGENT_VERSION). Actualizaciones de contexto respecto a aquel snapshot: (1) el auto-update desatendido está operativo (paquetes firmados Ed25519 + bootstrap onedir, sin Authenticode); (2) el Agente es “Full-Local” — TODA la I/O de red hacia dispositivos del cliente pasa por el Agente, no solo la monitorización. La arquitectura JWT/WS/Sentinel descrita abajo sigue vigente.
Qué es
Proceso Python autónomo que se instala en la red del cliente y mantiene WebSocket persistente con el SaaS. Es “Full-Local”: toda la I/O de red hacia dispositivos del cliente (SSH/SFTP, discovery/SNMP, monitorización, deploy de Signage) pasa por él. Ejecuta monitorización activa (ping, SNMP, HTTP) sobre dispositivos locales y envía métricas/alertas al SaaS en tiempo real. Cada tenant puede tener múltiples agentes: uno opera como Primary y el resto como Secondary, garantizando continuidad ante fallos.
Por qué existe
El SaaS no tiene acceso directo a redes privadas de clientes. El agente resuelve la brecha: vive dentro del segmento, alcanza IPs no enrutables desde internet y actúa como proxy de telemetría. Diseño Primary/Secondary permite HA sin coordinación manual: si el Primary cae, el Secondary más antiguo es promovido automáticamente.
Componentes
JWT Auth (3 capas): al registrarse, agent obtiene access_token (72h, HS256) y refresh_token (180d) vía terminal/api/auth.py. Verificación en AgentConsumer.connect(): si agent_id del token no coincide con URL, rechaza con código 4002. Cuando token tiene <2h de vida, SaaS lo renueva proactivamente via WS con mensaje token_refresh (capa 2). Capa 3: POST /api/agent/reauth-self usando solo agent_id+tenant_id, rate limit 5 intentos/hora.
SaaSConnector (WS cliente) (terminal/agent/saas_connector.py): conexión saliente a wss://<saas>/ws/agent/<agent_id>/?token=<jwt>. Heartbeat cada 30s (ping/pong), timeout recv 90s para detectar TCP muertas tras NAT. Reconexión con backoff exponencial: 1s inicio, 60s máx, 2×. Handlers por nombre de comando (update_targets, enable_sentinel, set_role).
AgentConsumer (WS servidor) (terminal/consumers.py): extremo SaaS por conexión. Diccionario memoria ACTIVE_AGENTS. Al conectar, agent se registra en AgentInstance y recibe rol. last_seen actualiza máx 1 vez/30s para no saturar BD. Métricas escritas a VictoriaMetrics via MetricsWriter; tipos snmp_fast_*, snmp_extras_*, snmp_bandwidth_* reenviados en tiempo real al navegador via Channel Layer.
Primary/Secondary: en modo auto (default), _register_and_assign_role() consulta si hay Primary activo para el tenant. Agent muerto: last_seen > 10 min. Agentes >24h offline eliminados como ghost. Si no hay Primary activo, agent entrante recibe primary; si no, secondary. Modo manual vía POST /api/agent/fleet/config (admins) congela roles.
SentinelScheduler (terminal/agent/sentinel/scheduler.py): orquesta 5 loops asíncronos: ping_loop, snmp_bandwidth_loop, extras_loop, fast_snmp_loop, purge_loop. Escalonado 3s entre arranques para evitar ráfagas tras reconexión/hibernación. Detección de suspensión: compara tiempo de reloj entre ticks con SLEEP_DETECTION_THRESHOLD; si salta, resetea circuit breakers y contadores base SNMP. Targets cargados desde SQLite local (TimeSeriesStore) para operación offline; al recibir update_targets del SaaS, persiste antes de actualizar memoria. Incluye CircuitBreaker por target y AnomalyDetector (CNS) que reporta via InsightReporter.
Cache offline: agent escribe métricas/alertas en SQLite cuando no hay conectividad. Al reconectar, pendientes se envían a POST /api/agent/metrics/bulk (hasta 5000/request), que escribe a VictoriaMetrics y reenvía al navegador.
Flujos
Register → Primary → targets → métricas → failover:
- Usuario descarga agent del SaaS; incluye
access_tokendePOST /api/agent/register. - Agent arranca
SaaSConnector.connect(), establece WS, envíaagent_statuscon version, hostname, sentinel state. _register_and_assign_role()evalúa fleet: si no hay Primary vivo, promueve al entrante y envíawelcomeconrole=primary.- Primary recibe
enable_sentinelyupdate_targetsconMonitoringTargetdel tenant + OIDs deVendorProfile. SentinelScheduler.update_targets()persiste en SQLite local e inicia loops.- Métricas: por WS (
type: metrics) o HTTP bulk offline (/api/agent/metrics/bulk). - Si Primary desconecta,
_handle_disconnect_failover()promueve Secondary más antiguo (porconnected_at), envíaset_role primary,enable_sentinel, targets.
Related
entity--terminal--model--agentinstance— modelo Django con estado, rol,last_seen.entity--monitoring--model--monitoringtarget— targets enviados al Primary.concept--monitoring--cns— detección de anomalías y reporting desde el agent.
Véase también
- [[entity—terminal—model—agentinstance]]
- [[entity—monitoring—model—monitoringtarget]]
- [[concept—monitoring—cns]]