Blog ·
Cuando NetBox es la fuente de la verdad
Conectar un DCIM externo no es una sincronización. Es una decisión campo a campo sobre quién decide, más una lista de lo que se rechaza importar y se dice.
Por Provibr
Un cliente con un NetBox que funciona no quiere un segundo inventario. Quiere que sus racks y sus máquinas aparezcan en la plataforma desde la que opera, y quiere seguir editándolos en el sitio que su equipo ya conoce.
La palabra que se le suele poner a eso es «sincronización», y la palabra es el problema. Sincronizar implica dos sistemas convergiendo en una sola verdad. Lo que hay en realidad es una pregunta campo a campo que hay que responder por adelantado y dejar escrita: para esta columna, en este objeto, ¿quién decide? Responderla una vez encogiéndose de hombros y ya se ha construido un sistema que sobrescribe una edición local deliberada a las tres de la madrugada, o uno que ignora en silencio un cambio que el cliente hizo hace una hora y cree que ha llegado.
Así la respondimos, incluidos los campos donde la respuesta es que no.
Cuatro valores, y no son grados de confianza
Cada columna de cada objeto vinculado lleva uno de cuatro valores de propiedad, y dicen cuatro cosas distintas sobre quién decide, no cuatro niveles de confianza.
Externo. Decide el otro lado. El campo es de solo lectura aquí y una importación lo sobrescribe sin preguntar. Eso no es una pérdida de control, es el acuerdo en el que entró el administrador cuando conectó el sistema.
Nuestro. Decidimos nosotros, y una importación no lo toca. Ese es el estado de todos los campos de un objeto que no está vinculado en absoluto, y de todos los campos para los que el sistema externo no tiene equivalente.
Bloqueado manualmente. El otro lado sí tiene un valor, y un administrador lo ha anulado aquí deliberadamente, con un motivo. Una diferencia es entonces un conflicto que se saca a la superficie, nunca una sobrescritura silenciosa. Es el único de los cuatro que no puede surgir por defecto: alguien lo pone.
Derivado. No decide nadie. Se sigue de otra cosa: si una máquina está montada en un rack, si está vinculada a un servicio, si está lista, la capacidad de un rack, la contabilidad de la propia fila. Estos son estructuralmente no importables, y una prueba afirma que no aparecen jamás en ningún mapeo.
Ese último merece una nota. Los campos de contabilidad, quién creó una fila y cuándo, son derivados y no nuestros. Nadie elige esos valores, se siguen de la acción. Un camino de importación al que se le permite escribir una marca de tiempo de creación es un camino de importación que puede reescribir la historia.
La propiedad cuelga del vínculo y no del objeto. Un objeto sin vínculo es enteramente nuestro, lo que significa que desvincular es un solo borrado y no una migración de estado a lo largo de cada columna.
El registro es por columna, y la lista de columnas sale del esquema
Cada columna de los cuatro tipos de objeto admitidos, sitios, ubicaciones, racks y máquinas, tiene una entrada en un registro. Incluidas las que no tienen absolutamente nada que ver con el sistema externo.
Esa exhaustividad se impone en vez de pretenderse. Una prueba deriva la lista de columnas del esquema de la base de datos y exige una decisión para cada una. Una columna nueva añadida en alguna ronda posterior es por tanto una prueba en rojo y no un hueco silencioso, que es la misma construcción que usamos en otros sitios: una prueba por caso no puede, por su naturaleza, encontrar un caso que falta.
Algunas de las decisiones son la parte interesante.
El presupuesto de potencia de un rack sigue siendo nuestro. NetBox modela la potencia como acometidas, no como una única cifra de presupuesto. Derivar un número de varias acometidas sería una afirmación de capacidad montada con datos incompletos, que es precisamente lo que el diseño de capacidad prohíbe. Así que el campo no se importa, con esa frase anotada al lado como motivo.
El estado de proceso de una máquina sigue siendo nuestro. El estado de dispositivo de NetBox mezcla ciclo de vida y operación en un solo campo. Un dispositivo marcado como averiado empujaría, con un mapeo ingenuo, a una máquina hacia un estado de mantenimiento y la sacaría del conjunto vendible. Son dos vocabularios distintos que dan la casualidad de compartir un nombre.
La clase de una máquina sigue siendo nuestra. El rol de dispositivo de NetBox es texto libre. Adivinar mal ahí no produce un error cosmético, cambia lo que la plataforma deja hacer con una máquina.
Cada una de esas se guarda con un motivo escrito, en la misma estructura que la decisión. Una regla con un motivo adjunto sobrevive a la siguiente persona; una regla sin él la relaja alguien que da por hecho que era arbitraria.
Solo inicial, porque hay pegatinas en una caja
Dos campos se importan una vez, al crearse, y no se actualizan nunca: el código de un sitio, una ubicación o un rack, y la etiqueta de activo de una máquina.
La razón es física. Esos valores están impresos en etiquetas, y las etiquetas están en una caja en un armario. Un slug renombrado en NetBox la primavera que viene no debe mandar un escaneo al sitio equivocado. Solo inicial no es un tercer valor de propiedad, es una propiedad de la importación: cogerlo al añadir, dejarlo en paz después.
Esos mismos campos son con los que se empareja un objeto no vinculado cuando se establece la conexión por primera vez: el código para los otros tres, la etiqueta de activo para las máquinas. Deliberadamente no el nombre, porque un código es estable y único sin distinguir mayúsculas, y un nombre no es ni una cosa ni la otra.
La colocación no se importa nunca, y no hay ningún campo que lleve ahí
NetBox conoce, de cada dispositivo, su rack, su posición y su cara. Esos tres se rechazan.
No se ignoran. Se rechazan, por su nombre, con un código de motivo, y se muestran en la vista previa.
El razonamiento se sigue directamente del diseño de ocupación: el único límite real a la ocupación de un rack es un índice único parcial sobre la tabla de slots, y ese índice solo lo toca una función. Un camino de importación que escribe un rack y un número de unidad en una máquina es un segundo camino de escritura que no sabe nada de ese índice, y entonces un día una máquina queda registrada en dos racks con un sistema externo confirmando que eso es correcto.
La especificación de esta parte dice que una colocación local o una asignación activa nunca deben quedar borradas por una importación. Hay dos maneras de que eso sea cierto. Una es escribir la importación de modo que deje las asignaciones en paz. La otra es hacer imposible que la importación llegue a escribir una asignación, y esa es la que tomamos: no hay ningún campo que lleve ahí.
Imponerlo es una guarda sobre el árbol de sintaxis abstracta y no un caso de prueba. Lee el código fuente del módulo de importación y exige que las cuatro tablas protegidas, las asignaciones, los slots, los vínculos de servicio y las etiquetas, aparezcan únicamente dentro de un select. Un insert, un update o un delete sobre cualquiera de ellas es rojo aunque ningún camino de código llegue nunca hasta ahí, porque la garantía tiene que valer para código que todavía no existe. El recorredor falla de forma ruidosa ante una forma que no reconoce, que es una lección aprendida por la vía cara en una guarda anterior que se saltaba en silencio lo que no sabía analizar.
Los rechazos se listan en la vista previa por su nombre. La omisión silenciosa es aquí la versión peligrosa: alguien conecta su NetBox, lee «142 máquinas actualizadas» y da por hecho que su distribución de racks vino con ellas.
Un borrado externo es un tombstone
Un objeto vinculado que el otro lado deja de mencionar se convierte en un tombstone con una revisión de impacto, no en un borrado.
Eso no es mera cortesía. Una lista que vuelve corta por un error de filtro, por un cambio de permisos o por una página traída a medias vaciaría si no el inventario de un cliente. El tombstone pone el objeto delante de una persona, junto con lo que depende de él: un objeto con una asignación activa no se puede quitar en absoluto, y una vez liberada la asignación el resultado es una retirada y no un borrado.
Y si se sabe que la obtención quedó truncada, no ocurre nada en absoluto. No se propone ningún tombstone para nada. De lo que no se ha visto no se puede concluir que falte. Eso es una condición de dos líneas y es la diferencia entre un conector y un incidente.
Lo que apuntaríamos
- Decidir la propiedad por columna, no por objeto, y hacer que la lista de columnas venga del esquema para que no se pueda olvidar una nueva.
- Guardar el motivo junto con la decisión. Un campo que no se importa necesita una frase, o alguien lo importará más adelante.
- Hacer imposible la importación peligrosa en lugar de cuidadosa. Ningún campo que lleve hasta ella, más una guarda que lea el código fuente.
- Nombrar en la vista previa lo que se rechaza, porque un número de objetos actualizados se lee como exhaustividad.
- Tratar la ausencia como una pregunta, nunca como un borrado, y tratar una obtención truncada como ninguna información en absoluto.
Sobre nuestro propio estado: esto está detrás de un interruptor de despliegue apagado por defecto con un ajuste por organización por encima, así que no es algo que se pueda comprar hoy, y no se ha ejecutado contra un NetBox real. Lo que se dice más arriba sobre cómo modela NetBox la potencia, el estado y los roles procede de su documentación y de la forma de su interfaz, no de una instancia suya en producción. Todo lo anterior se midió contra un stub que reproduce el comportamiento de paginación, la cabecera de versión y los objetos anidados de la interfaz real, fijado a la versión de la API que envía el código de producción. El stub ofrece de verdad un rack, una posición y una cara en sus cargas de dispositivo, y se escriben cero asignaciones: la negativa está medida y no supuesta. La pregunta relacionada de por qué un sistema externo que informa de éxito no es un resultado por sí mismo está en por qué un 200 de Proxmox no es un resultado.
Del trabajo de centro de datos en Provibr. La frontera de ocupación de la que se mantiene apartada esta importación se describe en el único límite real a la ocupación de un rack, y las etiquetas cuyos códigos deben permanecer estables en una etiqueta que sobrevive a un cambio de nombre de host.