CreaRack-SL

Incidente: Target de monitoreo "zombi" — Observable pero sin sondeo activo

Contexto

Incidente: s234 (detectado en vivo por Edu, 2026-07-23 18:00 UTC)

Un dispositivo de prueba temporal que compartió IP con un equipo de acceso inalámbrico (AP) real fue guardado con configuración de red inválida. Al guardarse, el hook de save_device_network_config apagó su MonitoringTarget (rama enabled=False) por validación fallida. Luego el device de prueba se eliminó, pero el target quedó en estado zombi:

  • ✅ Visible en Observatory con histórico y “Status UP” rancio
  • ❌ Fuera de la lista filtrada (enabled=True)
  • ❌ Sin sondeo del Agente (su push también filtra enabled=True)
  • ❌ Botones muertos — openTcpSettingsModal, openTargetTab, toggleMonitorType hacían return silencioso si el target no estaba en this.targets

Raíz: Invariante roto

La lógica implícita era: “si la gestión de red es válida, el monitoreo debe estar activo”. Pero esta invariante no estaba reforzada, solo asumida. Si un target se apagaba por arrastre y luego el device adquiría nueva config válida, nada lo re-encendía automáticamente.


Síntomas

  1. Usuario ve el equipo en Observatory con datos históricos y “UP”
  2. Intenta hacer clic en TCP Probe → botón no hace nada, sin log ni aviso
  3. Intenta abrir el modal de configuración → modal no abre, sin aviso
  4. Agente no sondea — el equipo está “desaparecido” para el polling
  5. Console limpia — ningún error visible, lo cual aumenta la ilusión de que “algo funciona”

Fix (v1.63.5)

Fix 1: Invariante “Gestión de red válida → Target activo” en DOS lugares

MonitoringTarget.get_or_create_for_device (monitoring/models.py)

Cuando se busca un target por FK al device:

  • Si existe pero enabled=False → re-encender (enabled=True)
  • Cuando se busca por IP (Ficha Central):
    • Si existe target anterior con otra IP → actualizar y re-encender

observatory_view (monitoring/views.py)

En el batch de reconciliación al abrir Observatory:

  • Si un device tiene gestión válida pero su target está enabled=False → re-encender en el bulk_update

Resultado: Un device cuya management_config es válida nunca puede quedarse con monitoreo apagado.

Fix 2: UI deja de callar

Modificados 3 handlers en frontend:

  • openTargetTab(targetId) — si target no existe en this.targets, mostrar toast + console.warn
  • openTcpSettingsModal(targetId) — ídem
  • toggleMonitorType(obs, targetId, ...) — ídem

Nuevo string traducido (djangojs.po):

msgid "Monitoring target not found — reload the page"
msgstr "El equipo no está en la lista de monitoreo — recarga la página"

Tests de regresión

TestZombieTargetReenable.test_get_or_create_reenables_zombie

  1. Crea un device con management_config válida
  2. Crea un target apagado manualmente (enabled=False)
  3. Llama get_or_create_for_device(device, org)
  4. Verifica que el target se re-encendió (enabled=True)

TestZombieTargetReenable.test_observatory_view_reenables_zombie

  1. Setup: target apagado + device con gestión válida
  2. GET /monitoring/ (vista de Observatory)
  3. Refresh del target de BD
  4. Verifica que enabled=True

Impacto

  • Usuarios: Equipos con gestión de red válida ya no pueden quedarse sin monitoreo “accidentalmente”
  • Observabilidad: Fallos en la UI se reportan explícitamente (toast + log)
  • Confianza: No hay más “targets invisibles” en el sistema

Véase también

  • [[decision—20260723—invariante-target-habilitado-con-gestion-red-valida]]
  • [[entity—monitoring—model—monitoring-target]]
  • [[concept—monitoring—observability]]
  • [[concept—saas—data-consistency]]
  • [[concept—saas—multi-tenancy]]