Volver a la wiki

Comando rack_integrity_probe — calibración del Motor de Integridad

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:

  1. human (defecto): tabla de racks + avisos + equipos sin documentar
  2. json (flag --json): JSON completo para logging/auditoría programática
  3. save (flag --save): además de imprimir, persiste la foto en RackIntegritySnapshot

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:

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

FlagTypeDefaultDescripción
--orgintREQUERIDOID de la organización
--fresh-daysint7Máx antigüedad del perfil de discovery para considerarlo fresco
--target-fresh-minint30Máx antigüedad (minutos) del último check de monitorización
--saveflagFalseSi se pasa, persiste la foto en RackIntegritySnapshot
--jsonflagFalseSalida 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:

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:

  1. Drifts a revisar: hallazgos con clasificación matched_stale o ip_conflict
    • Formato: [CLASS] RackName UN · DeviceName · ip=... · Reason
    • Estos son los que el humano debe validar para el gate #202
  2. Undocumented: perfiles vivos sin plano
    • Formato: IP_ADDRESS HOSTNAME VENDOR DEVICE_TYPE

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:

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

Notas

Véase también

Subir