Backup VM-level de Nutanix AHV via Prism v3+v4 com Changed Regions Tracking nativo, replicação vendor-neutral PHCBT01, cross-hypervisor inbound a partir de Proxmox/vSphere/Hyper-V e disk-only / alternate-cluster restore — todos ausentes do plugin AHV do Bacula Enterprise 18.2.3.
Documento técnico complementar à página do plugin PodHeitor Nutanix.
1. Lacunas do plugin Nutanix do Bacula Enterprise
O Bacula Enterprise 18.2.3 ships um plugin Nutanix AHV — em JVM, baseado em Prism v2/v3, sem CRT v4, sem cross-restore, sem replicação vendor-neutral, sem disk-only restore, sem alternate-cluster restore. Para clientes que rodam pc.2024.3+ e querem DR multi-vendor, isso deixa quatro lacunas operacionais grandes:
- Sem CRT v4. A API
compute-changed-regionsem pc.2024.3+ é mais rápida e granular que o legado v3changed_regions. O BEE não a consome. - Sem cross-restore. Backup AHV restaura só em AHV. Sair do Nutanix exige V2V manual.
- Replicação acoplada ao Nutanix Protection Policies. Não funciona cross-vendor.
- Latência JVM. Pausas GC durante streaming de disco grande são mensuráveis.
O PodHeitor Nutanix Plugin é um sibling Rust dos plugins podheitor-proxmox, podheitor-vsphere e podheitor-hyperv — reusando seus formatos on-wire byte-a-byte para que restores sejam totalmente cross-compatíveis.
2. Modelo arquitetural — two-process Rust
O plugin segue o padrão PodHeitor: cdylib (na verdade um shim C++ de ~120 LOC, constants-only, linkado contra a metaplugin framework) + backend Rust standalone, comunicando-se via PTCOMM length-tagged framing em stdin/stdout.
┌──────────────────────────────────────────────────────────────────────────┐
│ Bacula File Daemon (bacula-fd) │
│ ┌──────────────────────────────────────────────────────────────────┐ │
│ │ podheitor-nutanix-fd.so (metaplugin C++ shim, ~120 LOC) │ │
│ │ - PLUGINNAMESPACE="@nutanix" │ │
│ └──────────────────────────────────────────────────────────────────┘ │
│ │ PTCOMM over pipe (stdin/stdout) │
└──────────────────────────────┼────────────────────────────────────────────┘
▼
┌──────────────────────────────────────────────────────────────────────────┐
│ podheitor-nutanix-backend (Rust binary) │
│ ┌──────────────┬──────────────┬──────────────┬──────────────────────┐ │
│ │ prism v3/v4 │ snapshot │ iscsi │ disk_reader │ │
│ │ REST client │ RAII guard │ attach/detach│ (O_DIRECT /dev/sdX) │ │
│ ├──────────────┼──────────────┼──────────────┼──────────────────────┤ │
│ │ crt (CBT) │ backup.rs │ restore.rs │ replication.rs │ │
│ └──────────────┴──────────────┴──────────────┴──────────────────────┘ │
└────┬─────────────────────────┬────────────────────────┬───────────────────┘
│ HTTPS (9440) │ iSCSI (DSIP:3260) │ TLS (9848)
▼ ▼ ▼
┌──────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ Prism Central│ │ Nutanix CVMs │ │ DR Receiver │
└──────────────┘ └──────────────────┘ └──────────────────┘
2.1 Dois deployment modes, um binário
| Mode | Onde roda o backend | Quando escolher |
|---|---|---|
proxy_mode=external |
FD host fora do cluster AHV | Default — exige rota de rede para Prism:9440 + DSIP:3260 e open-iscsi no FD host |
proxy_mode=in_cluster |
Linux VM dentro do cluster AHV | Throughput máximo: data plane é virtual-NIC local para DSIP |
3. Backup full — fluxo passo a passo
- PTCOMM handshake; recebe JobInfo + Plugin params.
- Cluster discovery: PC v4 com fallback v3, retorna PE IP + JWT 15-min (cookie
NTNX_IGW_SESSION). POST /api/nutanix/v3/vms/{uuid}/snapshot(ou v4 equivalente). RAIISnapshotGuardgarante delete on drop.- Clone snapshot disks para um Volume Group temporário (Prism API).
- Attach VG ao proxy/FD via iSCSI:
iscsiadm -m discovery+iscsiadm -m node --login. - Enumera
/dev/disk/by-path/...via sysfs scan; mapeia disk ↔ block device por LUN. - Emite FNAME packets:
@nutanix/<cluster>/<vm-uuid>/vm-metadata.json,@nutanix/.../disks/disk-<idx>-<id>.raw. - Stream bytes em reads O_DIRECT 1 MiB / 4 KiB-aligned → D-packets.
- Logout iSCSI, delete VG, delete snapshot (a menos que seja a CBT reference).
- Persiste estado CBT:
reference_recovery_point_ext_id(v4) ousnapshot_uuid(v3) em/var/lib/podheitor-nutanix/bitmap/<cluster>/<vm-uuid>.json. - PTCOMM F (end-of-data), wait FD ack, T (terminate).
4. Backup incremental — CRT v4 com fallback v3
O passo 5 do fluxo full vira:
- Cria novo snapshot (current). Mantém o reference snapshot anterior.
- Para cada disk: chama
compute-changed-regions(v4) ou/data/changed_regions(v3) com(reference, current). - Pagina: até 10.000 regiões por response, segue
nextOffsetaté exaurir. - Emite extents modificados em formato PHCBT01 (magic + original_size + region_count + {offset, length, data} × N) sobre D-packets.
- Hybrid path: dense extents → iSCSI attach + read; sparse extents → REST range-GET. Heurística por densidade.
- Em sucesso: rotate. Delete old reference, promote current a new reference.
5. RAII guards — limpeza determinística
Snapshot Nutanix orfã = capacity leak no cluster. VG órfã = LUN target zumbi. iSCSI session aberta = device file zumbi no FD. O backend resolve via Rust Drop chain reverso:
| Guard | Recurso | Drop action |
|---|---|---|
SnapshotGuard |
Recovery point Prism | Delete via API |
VolumeGroupGuard |
VG temporário | Delete via API |
IscsiSessionGuard |
iSCSI session | iscsiadm -m node --logout |
CleanupGuard |
Catch-all | Catches Drop panics; loga errors mas nunca propaga |
Drop ordering é load-bearing: iSCSI logout → VG delete → snapshot delete. Reverse-declaration drop order do Rust dá isso de graça, mas inserir guards entre os existentes silenciosamente troca a ordem — convenção é encoded em comment no back_up_vm.
6. Cross-restore inbound — Proxmox/vSphere/Hyper-V → AHV
Detecção no scan de FNAME (primeiro file do job):
| Prefixo FNAME | Pipeline |
|---|---|
@proxmox/<vmid>/disks/*.raw |
raw → qcow2 (qemu-img convert) → Image Service upload |
@vsphere/<vm>/disks/*.vmdk |
vmdk → qcow2 → Image Service upload |
@hyperv/<vm>/disks/*.vhdx |
vhdx → qcow2 → Image Service upload |
VM config (.conf / .vmx / .vmcx XML) é traduzida para AHV vm_spec_v3:
| Source field | AHV target |
|---|---|
| Memory (MB) | resources.memory_size_mib |
| vCPUs | num_sockets × num_vcpus_per_socket |
| Firmware BIOS/UEFI | resources.boot_config.boot_type |
| SCSI/IDE disks | disk_list[].device_properties.device_type=DISK, adapter_type=SCSI |
| NIC MAC+VLAN | nic_list[].mac_address + subnet_reference via network_map |
7. Replicação vendor-neutral (PHCBT01 over TLS)
Diferentemente das Nutanix Protection Policies, que exigem Nutanix nas duas pontas, a replicação PodHeitor opera sobre PHCBT01-over-TLS na porta 9848 — mesmo formato dos plugins Proxmox/vSphere/Hyper-V. Receiver pode ser Nutanix, Proxmox, ou qualquer host com peer FD PodHeitor.
- Seed: full inicial via mesmo caminho de backup, marcado como reference.
- Bitmap-push: ciclos periódicos lêem CRT delta, enviam via TLS para receiver.
- Failover modes: planned, unplanned, test, undo, permanent.
8. Disk-only e alternate-cluster restore
Dois modos absent do BEE AHV v18:
- Disk-only restore: restaura apenas
disk-N.rawpara um device path arbitrário no FD host (sem upload ao Image Service, sem criação de VM). Caso de uso: forense, recuperação de arquivo específico via mount manual. - Alternate-cluster restore: parâmetro
target_clusterredireciona o restore para PE diferente do origem. Combina comrestore_vm_name=enetwork_map=para evitar IP collision.
9. Anti-patterns documentados
- Não use
prism_insecure=trueem produção. Existe para Nutanix CE (cert self-signed default). Importe a CA do PC no trust store do FD em vez de bypass. - Não inverta a ordem de Drop dos guards. Delete de snapshot antes de logout iSCSI deixa device files zumbis no FD.
- Não rode
proxy_mode=externalsemdsip=explícito. O fallback paracluster_namefunciona em lab mas é frágil em produção (DNS, multi-DSIP). - Não rode replicação contra cluster com Protection Policies ativas no mesmo VM. Conflito de snapshots; fluxo atual não detecta automaticamente.
10. License posture
O plugin distribui sob LicenseRef-PodHeitor-Proprietary. O backend é binário Rust standalone — não vincula estaticamente nenhum source AGPLv3 do Bacula. O shim C++ é minimalista (~120 LOC, constants-only) e linka contra a Bacula metaplugin framework dynamically.
Pronto para avaliar?
Trial gratuito de 30 dias para clusters Nutanix AHV (Prism Central pc.2024.3+ recomendado, pc.2023.x suportado via fallback v3). Garantimos no mínimo 50% de desconto vs Bacula Enterprise, Veeam ou Commvault, com cross-restore e replicação vendor-neutral inclusos.
Heitor Faria — Fundador, PodHeitor International
✉ [email protected]
☎ +1 (789) 726-1749 · +55 (61) 98268-4220 (WhatsApp)
🔗 Página do plugin PodHeitor Nutanix
Disponível em:
Português
English (Inglês)
Español (Espanhol)