Ruta y Método
POST /api/monitoring/profiles/{profile_id}/enable-monitoring
Router: monitoring.api.targets (Ninja)
Descripción Funcional
Habilita la monitorización de un DeviceProfile detectado por Auto-Provision, creando automáticamente un MonitoringTarget que reutiliza las credenciales SNMP guardadas del perfil.
Caso de uso: cuando un usuario abre un dispositivo detectado (wireless, UPS, cartelería, etc.) en el sidebar de Observatory y aún no se monitorizaba, este endpoint genera el target al vuelo, inyectando automáticamente las credenciales.
Parámetros
| Campo | Tipo | Ubicación | Requerido | Descripción |
|---|---|---|---|---|
profile_id | int | path | ✓ | ID del DeviceProfile a monitorizar |
Respuestas
200 OK
{
"id": 42,
"ip_address": "10.7.0.1",
"name": "wireless-ap-1",
"ping_enabled": true,
"snmp_enabled": true,
"http_enabled": false,
"enabled": true,
"config": {
"snmp_community": "s3cr3t",
"version": "v2c"
},
"device": null,
"organization": "org-abc123",
"created_at": "2026-06-08T16:20:00Z"
}
Esquema salida: MonitoringTargetOut
400 Bad Request
{
"error": "Profile has no IP address"
}
Se devuelve si el DeviceProfile no tiene IP configurada (caso anómalo).
404 Not Found
{
"error": "Profile not found"
}
El perfil no existe o pertenece a otra organización.
Lógica Interna
Función: enable_monitoring_for_profile(request, profile_id: int)
1. Validación de permisos
require_perm(request, "observatory", "edit")
org = require_org(request)
- Requiere permiso
observatory:editen la organización actual. - Operador o superior.
2. Lookup del ProfileTarget
profile = DeviceProfile.objects.select_related(
"linked_monitoring_target", "linked_device"
).get(id=profile_id, organization=org)
- Select_related optimiza queries (evita N+1 si ya hay target).
- Scope automático a la organización del usuario.
3. Idempotencia
if profile.linked_monitoring_target_id and profile.linked_monitoring_target:
return profile.linked_monitoring_target
Si ya existe un target vinculado, se devuelve tal cual (no se crea duplicado).
4. Validación de IP
if not profile.ip_address:
return 400, {"error": "Profile has no IP address"}
Sin IP, no hay nada que monitorizar.
5. get_or_create del MonitoringTarget
ip_str = str(profile.ip_address)
target, created = MonitoringTarget.objects.get_or_create(
organization=org,
ip_address=ip_str,
defaults={
"name": profile.hostname or ip_str,
"ping_enabled": True,
"snmp_enabled": bool(profile.snmp_community),
"http_enabled": False,
"enabled": True,
"config": build_snmp_config(profile),
"device": profile.linked_device,
}
)
Key point: build_snmp_config(profile) extrae automáticamente las credenciales SNMP del perfil (snmp_community, versión v2c/v3, etc.) e inyecta en el target. Sin intervención del usuario.
6. Vinculación bidireccional
profile.linked_monitoring_target = target
profile.save(update_fields=["linked_monitoring_target"])
Establece la FK inversa para que Observatory sepa que ya se monitorizaba.
7. Notificación de agentes
if created:
notify_agents(org.id)
Solo si el target es nuevo, avisa a los agentes de monitorización (polling, SNMP collection, etc.).
Integración con Observatory
Frontend (observatory.js):
async enableMonitoringForDevice(deviceId) {
const endpoint = deviceId < 0
? `/api/monitoring/profiles/${-deviceId}/enable-monitoring`
: `/api/monitoring/devices/${deviceId}/enable-monitoring`;
const target = await window.ApiService.post(endpoint);
await this.loadTargets();
this.renderDeviceList();
}
- ID negativo = DeviceProfile (convención en sidebar para distinguir fuentes).
- Carga targets actualizados y re-renderiza la lista.
Tests
Ubicación: tests/api/test_monitoring_enable_profile.py
4 casos de cobertura:
test_viewer_cannot_enable: viewer (sinobservatory:edit) → 403.test_creates_target_inheriting_snmp: crea target, heredasnmp_communityy credenciales.test_idempotent: llamadas múltiples devuelven el mismo target (no duplica).test_cross_org_is_404: intento de crear target en otra organización → 404.
Campos Tocados (DeviceProfile + MonitoringTarget)
Entrada (DeviceProfile):
ip_address(IP de monitorización)hostname(nombre para el target, fallback a IP)snmp_community(credencial v2c)snmp_version(v2c / v3)supports_snmp(booleano de capacidad)linked_device(FK opcional a Device si fue asignado a rack)
Salida (MonitoringTarget):
ip_addressnameping_enabled(siempre true)snmp_enabled(true si la credencial existe)config(JSON con SNMP settings)enabled(true)device(copia deprofile.linked_devicesi existe)
Véase también
- [[entity—monitoring—model—monitoring-target]]
- [[entity—network—model—device-profile]]
- [[feature—monitoring—observatory-unified-sidebar]]
- [[concept—network—snmp-configuration]]