Ubicación
racks/management/commands/rack_integrity_probe.py (124 LOC)
Comando Django management estándar registrado en manage.py.
Descripción General
Es la interfaz de calibración manual del Motor de Integridad para el gate de la task #202. Computa la clasificación plano↔realidad de una organización e imprime los resultados en tres formatos:
- human (defecto): tabla de racks + avisos + equipos sin documentar
- json (flag
--json): JSON completo para logging/auditoría programática - save (flag
--save): además de imprimir, persiste la foto enRackIntegritySnapshot
No modifica nada salvo si se pasa --save.
Uso
Forma Más Simple
python manage.py rack_integrity_probe --org 1
Salida human-readable:
Motor de Integridad · org 1 · 2026-07-17T12:30:00Z
Umbrales: perfil fresco <= 7 días · check monitorización <= 30 min
Rack fidelity coverage vivo stale confl no-obs
--------------------------------------...------...----...----...-----...-------
A01 95.2% 87.5% 38 1 0 5
A02 92.1% 90.0% 35 2 1 4
Rack-Temp — — 0 0 0 0
TOTAL · 3 racks · 127 equipos · fidelity 94.4% · coverage 95.3% · sin documentar en la LAN: 4
AVISOS A REVISAR A MANO (¿real o falsa alarma? — la cuenta del gate #202):
[matched_stale] A01 U2 · Router-Core-1 · ip=10.0.1.5 · El plano dice que está, pero la red no lo confirma (visto por última vez hace 15 días, umbral 7 días). Drift candidato: retirado, apagado o desconectado.
[ip_conflict] A02 U8 · Switch-Access-5 · ip=10.0.2.50 · La identidad enlazada al equipo vive ahora en otra IP (plano: 10.0.2.50 · perfil: 10.0.2.55). Posible sustitución o mudanza.
VIVOS EN LA LAN SIN PLANO (undocumented):
10.0.3.100 unknown-device-x Juniper switch
10.0.3.101 printer-floor-3 HP printer
...
Con Persistencia
python manage.py rack_integrity_probe --org 1 --save
Idem anterior, más al final:
Snapshot guardado (4 filas, fecha de hoy).
(3 racks + 1 fila-resumen)
JSON para Auditoría
python manage.py rack_integrity_probe --org 1 --json
Salida: la estructura completa del result de compute_integrity() en JSON formateado.
Ideal para:
- Capturar en log de auditoría
- Programar análisis post-mortem del gate #202
- Ingestar en sistema de reportes
Umbrales Personalizados
# Considerar frescos perfiles visto hace <= 14 días
python manage.py rack_integrity_probe --org 1 --fresh-days 14
# Considerar fresco si monitorización checó en últimos 60 min
python manage.py rack_integrity_probe --org 1 --target-fresh-min 60
# Combo
python manage.py rack_integrity_probe --org 1 --fresh-days 14 --target-fresh-min 60 --save
Argumentos
| Flag | Type | Default | Descripción |
|---|---|---|---|
--org | int | REQUERIDO | ID de la organización |
--fresh-days | int | 7 | Máx antigüedad del perfil de discovery para considerarlo fresco |
--target-fresh-min | int | 30 | Máx antigüedad (minutos) del último check de monitorización |
--save | flag | False | Si se pasa, persiste la foto en RackIntegritySnapshot |
--json | flag | False | Salida JSON en vez de human-readable |
Implementación
class Command(BaseCommand):
help = "Calibración del Motor de Integridad..."
def add_arguments(self, parser):
parser.add_argument("--org", type=int, required=True, ...)
parser.add_argument("--fresh-days", type=int, default=7, ...)
parser.add_argument("--target-fresh-min", type=int, default=30, ...)
parser.add_argument("--save", action="store_true", ...)
parser.add_argument("--json", action="store_true", ...)
def handle(self, *args, **opts):
# Resolver org
org = Organization.objects.get(id=opts["org"])
# Computar
result = integrity.compute_integrity(
org,
fresh_days=opts["fresh_days"],
target_fresh_minutes=opts["target_fresh_min"],
)
# Output
if opts["json"]:
self.stdout.write(json.dumps(result, ...))
else:
self._print_human(result)
# Persistencia opcional
if opts["save"]:
rows = integrity.persist_snapshots(org, result)
self.stdout.write(self.style.SUCCESS(f"Snapshot guardado ({rows} filas...)"))
Salida Human (_print_human)
Tabla formateada con:
- Rack name (30 chars max)
- fidelity_pct (%, o ”—” si NULL)
- coverage_pct (%, o ”—” si NULL)
- Conteos: matched_alive, matched_stale, ip_conflict, unobservable
Luego, agregados a nivel org:
TOTAL · 3 racks · 127 equipos · fidelity 94.4% · coverage 95.3% · sin documentar en la LAN: 4
Finalmente, dos secciones de avisos:
- Drifts a revisar: hallazgos con clasificación
matched_staleoip_conflict- Formato:
[CLASS] RackName UN · DeviceName · ip=... · Reason - Estos son los que el humano debe validar para el gate #202
- Formato:
- Undocumented: perfiles vivos sin plano
- Formato:
IP_ADDRESS HOSTNAME VENDOR DEVICE_TYPE
- Formato:
Contexto de Uso
Fase de Calibración (5 Días, Oficina Propia)
El equipo de infraestructura corre el comando una vez al día para detectar drifts en red conocida, confiable y con cambios lentos.
# Día 1
python manage.py rack_integrity_probe --org 1
# → "veo 2 matched_stale, 0 undocumented" → anotamos
# Día 2-5
python manage.py rack_integrity_probe --org 1
# → confirmamos consistencia de los avisos
Objetivo: validar que el motor NO genera falsos positivos en una red estable.
Validación de Señal/Ruido (Design Partner, Sept)
Se monta el probeador en una red ajena con cambios reales (design partner). Se corre diariamente durante X días, se recopilan snapshots, y se valida:
- Drift real encontrado: ✓ (true positive)
- Drift real NO encontrado: ✗ (false negative)
- Falso positivo: ✗ (ruido)
Métrica de gate: ≥80% de los drifts reportados son cambios reales.
Si ≥80%: GO a F2/F3 (UI + ITSM). Si 60-80%: rediseñar matching. Si <60%: KILL.
Exit Codes
0: Éxito (imprime, opcionalmente salva)NonZero: Fallo (org no existe, error interno, etc.)
Notas
- NO requiere permisos especiales: corre como usuario regular de management
- Solo lectura (salvo
--save): no modifica equipos ni perfiles - Idempotente con
--save: llamar 2 veces el mismo día sobrescribe el snapshot (merge lógico, no duplica) - Usado en task Huey:
compute_integrity_snapshots()llama apersist_snapshots()directamente (sin este comando)
Véase también
- [[feature—racks—motor-integridad-f1]]
- [[entity—racks—service—integrity]]
- [[entity—racks—model—rack-integrity-snapshot]]
- [[entity—racks—task—compute-integrity-snapshots]]