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,toggleMonitorTypehacíanreturnsilencioso si el target no estaba enthis.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
- Usuario ve el equipo en Observatory con datos históricos y “UP”
- Intenta hacer clic en TCP Probe → botón no hace nada, sin log ni aviso
- Intenta abrir el modal de configuración → modal no abre, sin aviso
- Agente no sondea — el equipo está “desaparecido” para el polling
- 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 enthis.targets, mostrar toast + console.warnopenTcpSettingsModal(targetId)— ídemtoggleMonitorType(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
- Crea un device con
management_configválida - Crea un target apagado manualmente (
enabled=False) - Llama
get_or_create_for_device(device, org) - Verifica que el target se re-encendió (
enabled=True)
TestZombieTargetReenable.test_observatory_view_reenables_zombie
- Setup: target apagado + device con gestión válida
- GET
/monitoring/(vista de Observatory) - Refresh del target de BD
- 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]]