Arquitetura de Reconciliacao de VMs¶
Esta pagina documenta a arquitetura de reconciliacao do full-sync de VMs usada pelo proxbox-api quando o sync de VM roda no modo full-update (sync_vm_network=false).
O objetivo e maximizar throughput de leitura no Proxmox, mantendo a pressao de escrita no NetBox baixa e deterministica.
Motivacao¶
O modelo anterior misturava fetch/reconcile/write por VM e podia intercalar muitas escritas no NetBox durante a descoberta.
O novo modelo separa o fluxo em fases explicitas:
- Ler todos os dados necessarios do Proxmox em memoria (paralelo).
- Ler todo o estado necessario do NetBox em memoria (snapshot unico).
- Comparar desired vs current com payloads normalizados por Pydantic.
- Montar fila deterministica de operacoes (
GET,CREATE,UPDATE). - Despachar operacoes de forma sequencial em janelas de batch controladas por configuracao global.
Fases de Execucao¶
Fase 1: Preflight de Dependencias¶
Antes da reconciliacao de VMs, o sync garante objetos pai no NetBox:
- Manufacturer
- Device type
- Role de node Proxmox
- Cluster type
- Cluster
- Site
- Device do node
- Role de VM (QEMU/LXC)
Fase 2: Snapshot de Leitura Proxmox (Paralelo)¶
Para cada VM candidata, o sync prepara um estado em memoria contendo:
- Identidade de cluster + VM
- Resource da VM no Proxmox
- Config da VM no Proxmox
- Payload desired normalizado para NetBox
- Chaves de lookup no NetBox (cluster +
cf_proxmox_vm_id)
A preparacao roda com concorrencia limitada usando asyncio.gather + semaforo.
Fase 3: Snapshot de Leitura NetBox (Memoria)¶
O sync le todas as VMs do NetBox em paginas (limit/offset) e monta um indice em memoria com chave:
(cluster_id, proxmox_vm_id, proxmox_vm_type)
O segmento de tipo evita colisao entre uma VM QEMU 100 e um CT LXC 100 no mesmo cluster.
Registros legados sem custom_fields.proxmox_vm_type so sao reaproveitados quando a identidade
(cluster_id, proxmox_vm_id) e inequivoca.
Fase 4: Reconciliacao da Fila¶
O engine padrao de reconciliacao e Python. Para cada VM preparada:
- Validar payload desired com
NetBoxVirtualMachineCreateBody. - Normalizar registro current do NetBox com o mesmo schema.
- Calcular delta de campos.
Classificacao:
GET: objeto existe e nao ha delta.CREATE: objeto nao encontrado no indice.UPDATE: objeto existe e ha delta.
Existe uma implementacao Rust opcional atras de uma fronteira JSON pura:
Input : prepared_vms + netbox_snapshot + flags (JSON bytes)
Output : operation queue (CREATE | GET | UPDATE + patch_payload) (JSON bytes)
A funcao Rust nao executa HTTP, async, banco de dados, retry ou dispatch. Essas responsabilidades continuam no Python. Quando o pacote nativo esta instalado, a ponte Python serializa a entrada com Pydantic v2, chama a extensao PyO3 com o GIL liberado, decodifica o resultado e adapta as operacoes de volta para as dataclasses usadas pelo dispatch.
Selecao de engine usa runtime settings. A configuracao normal para operadores e
ProxboxPluginSettings.reconciliation_engine no plugin NetBox; PROXBOX_RECONCILIATION_ENGINE
continua sendo o override por variavel de ambiente.
| Variavel | Valor | Comportamento |
|---|---|---|
PROXBOX_RECONCILIATION_ENGINE |
python |
Padrao. Usa apenas a saida Python. |
PROXBOX_RECONCILIATION_ENGINE |
compare |
Roda Python e Rust quando Rust esta instalado, loga divergencias e retorna Python. |
PROXBOX_RECONCILIATION_ENGINE |
rust |
Retorna a saida Rust adaptada. |
PROXBOX_RECONCILIATION_COMPARE_STRICT |
true |
Falha em divergencia no compare mode. Uso previsto para CI. |
Se o pacote Rust nao estiver instalado, o modo python funciona normalmente e o modo compare
retorna a saida Python. O modo rust requer o pacote nativo e falha claramente quando ele nao esta
disponivel.
Divergencias em compare mode incrementam proxbox_reconcile_mismatch_total, exposto em:
/cache/metrics/cache/metrics/prometheus
Fase 5: Dispatch Sequencial para NetBox em Janelas de Batch¶
As operacoes sao executadas em ordem deterministica.
- Tamanho da janela de batch vem de
PROXBOX_NETBOX_WRITE_CONCURRENCY. - Dentro da janela, escritas continuam uma-a-uma (sequencial).
GETnao escreve no NetBox.CREATEexecuta POST no NetBox.UPDATEexecuta PATCH por ID no NetBox.
Diagramas Mermaid¶
Fluxo de Reconciliacao de Ponta a Ponta¶
flowchart TD
A[Inicio Full-Sync de VMs] --> B[Preflight de Dependencias]
B --> C[Preparar estados de VM no Proxmox em paralelo]
C --> D[Carregar snapshot de VMs NetBox em memoria]
D --> E[Comparar desired vs current com Pydantic]
E --> F[Montar fila ordenada: GET CREATE UPDATE]
F --> G[Despachar fila em janelas de batch]
G --> H[Executar escritas NetBox de forma sequencial]
H --> I[Sincronizar task history da VM]
I --> J[Retornar VMs reconciliadas]
Modelo de Leitura Paralela + Escrita Sequencial¶
sequenceDiagram
participant P1 as Proxmox Endpoint A
participant P2 as Proxmox Endpoint B
participant S as Sync Engine
participant N as NetBox API
par Leituras paralelas do Proxmox
S->>P1: Buscar resources/configs
P1-->>S: Snapshot de VM A
and
S->>P2: Buscar resources/configs
P2-->>S: Snapshot de VM B
end
S->>N: Buscar paginas de VM no NetBox
N-->>S: Snapshot NetBox em memoria
S->>S: Reconciliar com Python ou engine Rust opcional
S->>S: Montar fila ordenada de operacoes
loop Dispatch sequencial por batch
S->>N: CREATE ou UPDATE (uma por vez)
N-->>S: Resposta
end
Semantica das Operacoes¶
GET
- Nao requer escrita no NetBox.
- Reaproveita registro do snapshot em memoria.
CREATE
- Nao existe correspondencia por
(cluster_id, proxmox_vm_id, proxmox_vm_type). - Executa POST no NetBox durante o dispatch.
UPDATE
- Objeto existe, mas payload reconciliado difere.
- Executa PATCH apenas com campos alterados.
Configuracao¶
PROXBOX_VM_SYNC_MAX_CONCURRENCY: controla concorrencia de preparacao/fetch de VMs no Proxmox.PROXBOX_NETBOX_WRITE_CONCURRENCY: define tamanho da janela de batch no dispatch.reconciliation_engine/PROXBOX_RECONCILIATION_ENGINE: selecionapython,compareourust.PROXBOX_RECONCILIATION_COMPARE_STRICT: falha em drift no compare mode quandotrue.
Observacao: tamanho de batch nao implica escrita paralela; as escritas continuam sequenciais para proteger o NetBox em ambiente de instancia unica.
Politica de Rollout do Rust¶
Rust nao e o engine padrao. O rollout e conservador:
- Construir e testar wheels de
proxbox-reconcile-rsno CI. - Publicar
proxbox-reconcile-rsapenas pelo workflow de release do repositorio. - Manter
reconciliation_engine=pythoncomo padrao noproxbox-api. - Rodar
reconciliation_engine=compareem staging por pelo menos duas semanas. - Monitorar
proxbox_reconcile_mismatch_totale logs de mismatch. - Recomendar
PROXBOX_RECONCILIATION_ENGINE=rustapenas depois de zero divergencias em syncs reais diversos. - Considerar trocar o padrao apenas em uma release minor futura e somente se benchmarks de wall time do sync completo provarem ganho real.
Rollback e imediato: volte reconciliation_engine para python no NetBox ou remova PROXBOX_RECONCILIATION_ENGINE se um override de ambiente foi usado.
A evidencia atual de benchmark nao justifica tornar Rust o padrao. O caminho Rust completo ficou mais lento que Python no benchmark sintetico, e a medicao real mostrou que reconciliacao nao era o custo dominante do sync.