Technical whitepaper — PodHeitor CloudStack for Bacula

Technical whitepaper — PodHeitor CloudStack for Bacula

PodHeitor CloudStack Backup, Replication and Conversion Plugin for Bacula

Versão 2.0.0 — Abril 2026


Autor: Heitor Faria Contato: heitor@opentechs.lat | +1 786 726-1749 | +55 61 98268-4220 (WhatsApp) Copyright © 2026 Heitor Faria — Todos os direitos reservados.


OFERTA COMERCIAL ESPECIAL

Traga sua proposta de contratação ou renovação do Bacula Enterprise, Veeam, Commvault ou NetBackup. Damos no mínimo 50% de desconto, com muito mais funcionalidades.

Heitor Faria — heitor@opentechs.lat | +1 786 726-1749 | +55 61 98268-4220 (WhatsApp)


Sumário

  1. Sumário Executivo
  2. Contexto e Oportunidade de Mercado
  3. Casos de Uso
  4. Arquitetura Técnica
  5. Funcionalidades Detalhadas
  6. Compatibilidade e Requisitos
  7. Guia de Instalação
  8. Configuração e Sizing
  9. Manual de Uso
  10. Tabelas de Parâmetros
  11. Exemplos de Configuração de FileSet
  12. Performance e Benchmarks
  13. Segurança
  14. Monitoramento e Observabilidade
  15. Troubleshooting
  16. Comparativo com Concorrentes
  17. Roadmap
  18. Referências

1. Sumário Executivo

O PodHeitor CloudStack Backup, Replication and Conversion Plugin for Bacula é a solução definitiva para backup e recuperação de máquinas virtuais em ambientes Apache CloudStack, integrada nativamente ao Bacula Community. Desenvolvido em Rust por Heitor Faria, o plugin entrega funcionalidades que superam até as soluções pagas do mercado — a um custo substancialmente menor.

O que é?

Um plugin para o File Daemon (FD) do Bacula Community que permite:

  • Backup completo e incremental de VMs CloudStack com rastreamento de blocos modificados (CBT) via QEMU dirty bitmaps
  • Replicação contínua para site de DR com transporte criptografado AES-256-GCM
  • Restauração cruzada entre hypervisors: CloudStack → Proxmox VE, Hyper-V, VMware vSphere
  • Conversão de formatos de disco: qcow2 ↔ vhdx ↔ vmdk ↔ raw

Por que é diferente?

┌─────────────────────────────────────────────────────────────────────┐
│  COMPARATIVO RÁPIDO                                                   │
├──────────────────────────┬──────────────────┬────────────────────────┤
│ Funcionalidade           │ Bacula Enterprise│ PodHeitor CloudStack   │
├──────────────────────────┼──────────────────┼────────────────────────┤
│ Backup Incremental CBT   │ Snapshot diff    │ Block-level dirty bitmap│
│ Redução de janela backup │ ~30%             │ 90%+                   │
│ Replicação DR            │ Não disponível   │ Bitmap-push contínuo   │
│ Cross-restore            │ Não disponível   │ Proxmox/Hyper-V/VMware │
│ Métricas Prometheus      │ Não disponível   │ Endpoint nativo        │
│ Logging JSON estruturado │ Não disponível   │ Nativo                 │
│ Custo (vs Enterprise)    │ 100% (base)      │ Significativamente menor│
└──────────────────────────┴──────────────────┴────────────────────────┘

Proposta de Valor


5. Funcionalidades Detalhadas

5.1 Backup Full

Fluxo completo:

1. Autenticar na API CloudStack (HMAC-SHA1)
2. Listar VMs que correspondem ao padrão vm=
3. Para cada VM:
   a. Verificar estado (running/stopped)
   b. Se running + quiesce=true: freeze via qemu-guest-agent
   c. createSnapshot via API CloudStack
   d. Aguardar conclusão do snapshot (polling assíncrono)
   e. Se running: thaw via qemu-guest-agent
   f. Descobrir path do arquivo de snapshot no KVM host
   g. Iniciar qemu-nbd --read-only --snapshot no KVM host (via SSH)
   h. Para cada bloco do disco:
      - Ler via NBD com read-ahead de 4 blocos
      - Detectar blocos zero via SIMD
      - Calcular xxHash64
      - Compor header do bloco no stream
      - Comprimir com zstd (se compress=true)
      - Enviar para o Bacula FD
   i. Salvar hash DB atualizado
   j. Limpar snapshot CloudStack
   k. Registrar checkpoint no working_dir
4. Retornar estatísticas para o Bacula

5.2 Backup Incremental

Fluxo:

1. Verificar se existe backup anterior (hash DB + QEMU bitmap)
2. Para cada VM:
   a. Se não existe bitmap podheitor-cbt: criar via QMP
   b. Snapshot do estado atual
   c. Consultar bitmap sujo via QMP
   d. Para cada bloco sujo:
      - Ler bloco atual via NBD
      - Calcular xxHash64
      - Comparar com hash anterior
      - Se mudou: incluir no stream
      - Se não mudou: skip (falso positivo)
   e. Atualizar hash DB
   f. Reset do bitmap (preparar para próximo incremental)
3. Resultado: apenas blocos realmente modificados

Economia típica:

  • VM 100 GB com 5% de mudança diária: 5 GB via incremental vs 100 GB full
  • Com compressão zstd level 3: ~2,5 GB transferidos
  • Redução de 97,5% no volume de dados transferidos

5.3 Replicação Contínua (DR)

Modos:

Modo Descrição Uso
seed Sincronização inicial completa Primeiro setup do DR
bitmap_push Envio contínuo de deltas Operação normal de DR
receiver Receptor no site DR Executado no site DR
daemon Sender contínuo (fora de jobs Bacula) DR autônomo
failover_exec Promover DR para primário Executado em evento de desastre
failback_exec Re-sync após failover Retorno ao site principal
reprotect Estabelecer replicação no sentido inverso Após failover
replication_status Consultar saúde do par de replicação Monitoramento

Protocolo de replicação:

Site Principal (Sender)              Site DR (Receiver)
        │                                    │
        │── TCP connect ──────────────────►  │
        │── PSK handshake (HKDF derivation) ►│
        │── AES-256-GCM channel established ►│
        │                                    │
LOOP cada cycle_interval segundos:           │
        │                                    │
        │── query dirty bitmap ─────────────►│ (local QMP)
        │── for each dirty block:            │
        │     read via NBD                   │
        │     xxHash64                       │
        │     zstd compress                  │
        │── send compressed deltas ─────────►│
        │                                    │── apply to replica disk
        │◄─ ACK ─────────────────────────────│
        │── reset bitmap for next cycle ─────│ (local QMP)
        │                                    │

Largura de banda típica em operação:

  • Servidor DB ativo (5% mudança/hora): ~500 MB/h
  • Servidor web estático (0,5% mudança/hora): ~50 MB/h
  • VM idle (0,01% mudança/hora): ~1 MB/h

5.4 Restauração

Restauração no CloudStack (where=/)

1. Ler stream de backup do Bacula
2. Reconstruir disco raw em working_dir
3. Converter raw → qcow2 via qemu-img
4. Iniciar servidor HTTP temporário (python3 http.server)
5. registerTemplate com directdownload=true na API CloudStack
6. deployVirtualMachine com o template registrado
7. Se start_vm=true: ligar VM
8. Limpar arquivos temporários

Restauração para filesystem (where=/path)

1. Ler stream de backup do Bacula
2. Extrair cada disco como arquivo raw em /path/vm-<name>/disk-<N>.raw
3. Extrair metadata da VM como vm-<name>/metadata.json
4. Opcionalmente: converter para qcow2 se cross_restore=proxmox

5.5 Restauração Cruzada (Cross-Restore)

Target Formato de Saída Adaptação de Guest OS
proxmox / pve .qcow2 Drivers VirtIO para disco, rede e balloon
hyperv / hyper-v .vhdx Drivers Hyper-V (storvsc, netvsc, vmbus)
vmware / vsphere .vmdk VMware Tools (pvscsi, vmxnet3)

Processo de guest adaptation:

Para cada VM × cada target:
1. Montar disco restored via NBD loopback
2. Detectar OS (leitura de /etc/os-release ou Windows registry)
3. Se Linux:
   - Adicionar módulos virtio-blk, virtio-net, virtio-scsi ao initrd/initramfs
   - Atualizar /etc/dracut.conf.d/ ou update-initramfs
   - Ajustar /etc/fstab para novos device paths se necessário
4. Se Windows:
   - Injetar drivers .inf para target hypervisor no disco
   - Adicionar chave de registry para boot offline com novo driver
5. Converter disco para formato target
6. Transferir para target hypervisor via API ou SCP

5.6 Conversão de Formatos de Disco

Formatos suportados:
  raw → qcow2    (compressão interna, sparse)
  raw → vhdx     (header CRC32C validado, Hyper-V compatível)
  raw → vmdk     (streamOptimized, ESXi compatível)
  qcow2 → raw    (para staging)
  vhdx → raw     (para staging)
  vmdk → raw     (para staging)

Características:
  - Streaming: sem buffering completo em RAM
  - VHDX: CRC32C Castagnoli calculado corretamente (header sector)
  - VMDK: formato streamOptimized para transferência eficiente
  - Sparse: blocos zero não ocupam espaço no arquivo de saída

6. Compatibilidade e Requisitos

Matriz de Compatibilidade Bacula × CloudStack

Bacula Community CloudStack KVM host OS Status
15.0.3 4.20 Ubuntu 22.04 ✅ Validado completo
15.0.3 4.19 Oracle Linux 9.6 ✅ Validado baseline
13.x 4.19 Oracle Linux 9.6 ⚠ Funcional, sem validação CI
11.x 4.16-4.18 Oracle Linux 8 ⚠ Requer rebuild das headers
15.0.3 4.18 CentOS 7 ❌ Não recomendado

SO do FD Host (onde bacula-fd + plugin rodam)

Distro Build Pacote Status
Ubuntu 22.04 Jammy .deb Primário, validado em CI
Ubuntu 24.04 Noble 🟡 .deb Build verificado
Debian 12 Bookworm 🟡 .deb Build verificado
Rocky Linux 9 .rpm Validado em CI
Oracle Linux 9.x .rpm Ambiente de desenvolvimento primário
RHEL 9 .rpm Mesmo binário que Rocky/OL 9
AlmaLinux 9 🟡 .rpm Compatível binariamente
CentOS Stream 9 🟡 .rpm Esperado funcionar

Legenda: ✅ Validado em CI · 🟡 Esperado funcionar · ❌ Não funciona

SO do KVM Host (onde o plugin faz SSH)

Distro Status
Ubuntu 22.04
Rocky Linux 9
Oracle Linux 9
CentOS 8 Stream 🟡

Dependências no KVM host:

Binário Versão Mínima Pacote (Debian) Pacote (RHEL)
qemu-nbd 6.2+ qemu-utils qemu-img
qemu-img 6.2+ qemu-utils qemu-img
socat any socat socat
virsh any libvirt-clients libvirt-client
sh, find, grep, awk any (padrão) (padrão)

Requisitos do Ambiente Bacula

Item Mínimo Recomendado
Bacula Community 15.0.3 15.0.3 ou posterior
CPUs no FD host 2 4+
RAM no FD host 1 GB 4 GB
Disco (working_dir) 50 GB 500 GB+
Rede FD → CloudStack API 10 Mbps 1 Gbps
Rede FD → KVM hosts 1 Gbps 10 Gbps
Rede entre sites (replicação) 10 Mbps 1 Gbps

CloudStack API

Requisito Valor
Versão mínima 4.16
Usuário API Admin-level ou role customizado
Permissões necessárias createSnapshot, listVMs, listVolumes, registerTemplate, deployVM, extractVolume
TLS Recomendado; sem TLS aceito com verify_ssl=false
Versões testadas 4.19 (OL9), 4.20 (Ubuntu 22.04)
Ferramenta Versão Mínima Uso
Python 3 3.9+ Servidor HTTP temporário no restore
qemu-img/nbd 6.2+ Dirty bitmap QMP verbs

7. Guia de Instalação

7.1 Via Pacotes (Recomendado)

# ── Debian / Ubuntu ──────────────────────────────────────────────────
# Copie o .deb para o servidor e instale:
apt install ./podheitor-cloudstack-plugin_2.0.0-1_amd64.deb
systemctl restart bacula-fd

# ── RHEL / Rocky / Oracle Linux ──────────────────────────────────────
dnf install ./podheitor-cloudstack-plugin-2.0.0-1.el9.x86_64.rpm
systemctl restart bacula-fd

O que é instalado:

/opt/bacula/plugins/podheitor-cloudstack-fd.so          ← plugin .so
/opt/bacula/plugins/podheitor-cloudstack-backend         ← backend Rust
/opt/bacula/bin/podheitor-cloudstack-backend             ← cópia (PATH safety)
/opt/bacula/bin/podheitor-cloudstack-preflight           ← script de verificação

7.3 Configuração do FD Host

Layout A — FD Compartilhado (simples)

O plugin coexiste com outros plugins dentro do bacula-fd existente. Adequado para ambientes menores ou testes.

# Apenas adicionar ao bacula-fd.conf existente:
FileDaemon {
  ...
  Plugin Directory = /opt/bacula/plugins
  ...
}

Layout B — FD Dedicado (produção recomendada)

Instalar um bacula-fd dedicado no servidor de gerenciamento do CloudStack ou em qualquer host Linux com acesso SSH aos KVM hosts.

# 1. Instalar bacula-fd 15.0.3
# (via tarball de https://www.bacula.org/downloads/ ou repositório)

# 2. Instalar o plugin
apt install ./podheitor-cloudstack-plugin_1.0.0_amd64.deb

# 3. Configurar bacula-fd.conf
cat > /opt/bacula/etc/bacula-fd.conf << 'EOF'
Director {
  Name = meu-director
  Password = "GERAR-UMA-SENHA-FORTE-ALEATORIA"
}
FileDaemon {
  Name = cloudstack-fd
  WorkingDirectory = /opt/bacula/working
  Pid Directory = /opt/bacula/working
  Maximum Concurrent Jobs = 20
  Plugin Directory = /opt/bacula/plugins
  FDAddresses = { ip = { addr = 0.0.0.0; port = 9102 } }
}
Messages {
  Name = Standard
  director = meu-director = all, !skipped, !restored
}
EOF

# 4. Criar diretórios de trabalho
install -d -m 0750 -o bacula -g bacula 
    /var/lib/bacula/cloudstack 
    /var/lib/bacula/cloudstack/hashes

# 5. Iniciar o serviço
systemctl enable --now bacula-fd

7.4 Configuração da Chave SSH para os KVM Hosts

# No FD host — gerar chave dedicada:
mkdir -p /opt/bacula/etc
ssh-keygen -t ed25519 -N '' 
           -C 'bacula-cloudstack-backup' 
           -f /opt/bacula/etc/cloudstack_ssh_key
chmod 600 /opt/bacula/etc/cloudstack_ssh_key

# Copiar a chave pública para CADA KVM host:
ssh-copy-id -i /opt/bacula/etc/cloudstack_ssh_key.pub root@192.168.1.10
ssh-copy-id -i /opt/bacula/etc/cloudstack_ssh_key.pub root@192.168.1.11
# ... repetir para todos os KVM hosts

# Testar conectividade:
ssh -i /opt/bacula/etc/cloudstack_ssh_key root@192.168.1.10 "hostname && uptime"

Hardening recomendado (Pattern A) — ~root/.ssh/authorized_keys no KVM host:

# Instalar o wrapper (do pacote ou source):
install -m 755 /opt/bacula/contrib/sshd-wrapper-kvm.sh 
               /usr/local/bin/bacula-cloudstack-ssh-wrapper

# Adicionar ao authorized_keys do KVM host:
command="/usr/local/bin/bacula-cloudstack-ssh-wrapper",no-port-forwarding,
no-X11-forwarding,no-agent-forwarding ssh-ed25519 AAAA... bacula-cloudstack-backup

7.5 Chaves de API do CloudStack

CloudStack UI → Contas → <conta> → <usuário> → Chaves de API → Gerar

Copiar api_key e secret_key para o arquivo de configuração:

# Criar arquivo de configuração com permissão restrita:
cat > /opt/bacula/etc/cloudstack.ini << 'EOF'
api_url       = http://cs-mgmt.exemplo.com.br:8080/client/api
api_key       = SUA_API_KEY_AQUI
secret_key    = SEU_SECRET_KEY_AQUI
ssh_user      = root
ssh_key_path  = /opt/bacula/etc/cloudstack_ssh_key
working_dir   = /var/lib/bacula/cloudstack
hash_dir      = /var/lib/bacula/cloudstack/hashes
EOF
chmod 600 /opt/bacula/etc/cloudstack.ini
chown bacula:bacula /opt/bacula/etc/cloudstack.ini

7.6 Verificação da Instalação

# Verificar dependências do sistema:
/opt/bacula/bin/podheitor-cloudstack-preflight --verbose

# Verificar configuração completa (API + SSH + toolchain):
/opt/bacula/bin/podheitor-cloudstack-backend 
  --check --config /opt/bacula/etc/cloudstack.ini

# Recarregar o Director:
echo reload | /opt/bacula/bin/bconsole

# Disparar backup de teste:
echo 'run job=CloudStack-Backup-Full yes' | /opt/bacula/bin/bconsole

8. Configuração e Sizing

8.1 Sizing Recomendado por Ambiente

Ambiente Pequeno (até 50 VMs, até 10 TB total)

Componente Configuração Mínima Configuração Recomendada
FD Host (cloudstack-fd) 2 vCPU, 2 GB RAM 4 vCPU, 4 GB RAM
Disco working_dir 100 GB (SSD preferível) 500 GB SSD
Rede FD → KVM hosts 1 Gbps 1 Gbps
Storage Bacula (SD) 30 TB (3x dedup) 50 TB
Concurrent Jobs 4 8

Ambiente Médio (50-500 VMs, 10-100 TB total)

Componente Configuração Mínima Configuração Recomendada
FD Host (cloudstack-fd) 4 vCPU, 8 GB RAM 8 vCPU, 16 GB RAM
Disco working_dir 1 TB SSD 2 TB NVMe
Rede FD → KVM hosts 10 Gbps 10 Gbps
Storage Bacula (SD) 100 TB 300 TB
Concurrent Jobs 10 20
FD instances 1 2 (load balance)

Ambiente Grande (500+ VMs, 100+ TB total)

Componente Configuração Mínima Configuração Recomendada
FD Host (cloudstack-fd) 8 vCPU, 16 GB RAM 16 vCPU, 32 GB RAM (por instância)
FD instances 2 4+ (StorageGroup no Director)
Disco working_dir 2 TB NVMe por FD 4 TB NVMe por FD
Rede FD → KVM hosts 10 Gbps 25 Gbps
Storage Bacula (SD) Deduplicated storage Dedup + fita para LTR
Concurrent Jobs 20 por FD 40 por FD

8.2 Parâmetros de Performance Críticos

# Para ambientes grandes:
block_size = 4M          # Blocos maiores → menos operações (rede rápida)
compress = true          # Reduz I/O de storage
compress_level = 3       # Nível 3: bom ratio, CPU baixa (recomendado)
# Para CPU limitada ou VMs críticas:
compress_level = 1       # Mais rápido, ratio menor

# Concorrência:
# No bacula-fd.conf:
Maximum Concurrent Jobs = 20   # Ajustar conforme número de VMs e largura de banda

8.3 Estimativa de Storage

Fórmula base:
  Storage = (Tamanho total das VMs) × (1 - taxa_dedup) × (1 - taxa_compress) 
            × (1 + fator_incrementais) × (retenção_dias / ciclo_backup_dias)

Valores típicos:
  taxa_dedup      = 0.30 a 0.50 (30-50% blocos idênticos entre VMs)
  taxa_compress   = 0.45 a 0.55 (zstd level 3 comprime 45-55%)
  fator_incrementais = 0.15 a 0.25 (15-25% de dados novos por dia)

Exemplo:
  100 VMs × 500 GB/VM = 50 TB total
  Dedup: ×0.65 → 32.5 TB
  Compress: ×0.50 → 16.25 TB
  Com 30 dias de retenção (1 full + 6 inc/semana):
  16.25 TB × (1 + 6×0.20) = 16.25 × 2.2 = ~35.75 TB

8.4 Sizing do Replication Transport

Largura de banda mínima para replicação:
  bandwidth_GB_h = (taxa_mudança_diária_GB × cycle_interval_s) / 86400
  
  Exemplo: 500 VMs × 500 GB × 5% mudança/dia = 12.5 TB/dia
  Com cycle_interval=300s (5 min):
  12.5 TB / 288 ciclos/dia = ~44 GB/ciclo
  Em 5 min → 44 GB / 300s = ~147 MB/s = ~1.2 Gbps
  
  → Mínimo recomendado: 2 Gbps entre sites para este exemplo

9. Manual de Uso

9.1 Primeiros Passos

Passo 1: Verificar Instalação

# No FD host:
/opt/bacula/bin/podheitor-cloudstack-preflight --verbose

Saída esperada:

[OK]  socat                    /usr/bin/socat
[OK]  qemu-img                 /usr/bin/qemu-img
[OK]  qemu-nbd                 /usr/bin/qemu-nbd
[OK]  ssh                      /usr/bin/ssh
[OK]  python3                  /usr/bin/python3
[OK]  bacula-fd                /opt/bacula/bin/bacula-fd
[OK]  cloudstack-backend       /opt/bacula/bin/podheitor-cloudstack-backend

Passo 2: Validar Conectividade

/opt/bacula/bin/podheitor-cloudstack-backend 
  --check --config /opt/bacula/etc/cloudstack.ini

Saída esperada:

[OK]  Config file permissions: 0600 ✓
[OK]  CloudStack API reachable: http://cs-mgmt:8080/client/api
[OK]  API credentials valid: listZones → 1 zone(s) found
[OK]  SSH to KVM host 192.168.1.10: hostname=kvm01
[OK]  SSH to KVM host 192.168.1.11: hostname=kvm02
[OK]  qemu-nbd on kvm01: 8.2.0
[OK]  socat on kvm01: 1.8.0.0
[OK]  Working dir writable: /var/lib/bacula/cloudstack
[OK]  Hash dir writable: /var/lib/bacula/cloudstack/hashes
ALL OK — ready to backup

Passo 3: Configurar no Bacula Director

Ver exemplos completos na seção 11. Exemplos de Configuração de FileSet.

Passo 4: Disparar Primeiro Backup

# Via bconsole:
echo 'run job=CloudStack-Backup-Full yes' | /opt/bacula/bin/bconsole

# Acompanhar progresso:
/opt/bacula/bin/bconsole
* status dir
* messages
* llist jobid=<N>

Passo 5: Acompanhar o Log do Backend

tail -f /opt/bacula/working/podheitor-cloudstack-backend.log

9.2 Backup Full Manual (via bconsole)

* run job=CloudStack-Backup-Full
Run Backup job
JobName:  CloudStack-Backup-Full
Level:    Full
Client:   cloudstack-fd
FileSet:  CloudStack-All-VMs
Pool:     File (From Job resource)
Storage:  File1
When:     2026-04-28 10:00:00
Priority: 10
OK to run? (yes/mod/no): yes

9.3 Backup Incremental Manual

* run job=CloudStack-Backup-Inc
Run Backup job
JobName:  CloudStack-Backup-Inc
Level:    Incremental
...
OK to run? (yes/mod/no): yes

Nota: Se não houver backup Full anterior, o Bacula promove automaticamente para Full.

9.4 Restore de VM

Restauração Completa no CloudStack

* restore client=cloudstack-fd fileset="CloudStack-All-VMs" 
          restorejob=CloudStack-Restore jobid=<N> all done yes

Isto recria a VM no CloudStack com o nome especificado em new_vm_name.

Restauração para Filesystem

* restore client=cloudstack-fd fileset="CloudStack-All-VMs" 
          restorejob=CloudStack-Restore-Filesystem jobid=<N> all done yes

Os discos são extraídos para where=/mnt/restore/vm-name/.

9.5 Setup de Replicação DR

# 1. No site DR: configurar o receiver como Job Bacula
# 2. Iniciar o receiver:
echo 'run job=CloudStack-DR-Receiver yes' | bconsole

# 3. No site principal: executar o seed (sincronização inicial)
echo 'run job=CloudStack-Replicate-Seed yes' | bconsole

# 4. Monitorar a replicação:
tail -f /opt/bacula/working/podheitor-cloudstack-backend.log | grep -i replic

9.6 Failover de DR

# 1. Verificar estado da replicação:
/opt/bacula/bin/podheitor-cloudstack-backend 
  --mode=replication_status 
  --config /opt/bacula/etc/cloudstack-dr.ini

# 2. Executar failover (promove réplica para primário):
echo 'run job=CloudStack-Failover yes' | bconsole

# 3. VMs estarão ligadas no site DR em < 5 minutos

9.7 Cross-Restore para Proxmox

# Via bconsole com job configurado para cross_restore=proxmox:
* restore client=cloudstack-fd fileset="CloudStack-All-VMs" 
          restorejob=CloudStack-Restore-Proxmox jobid=<N> all done yes

O plugin:

  1. Extrai os discos do stream de backup
  2. Converte qcow2 → qcow2 (com adaptação de drivers)
  3. Cria a VM no Proxmox via API
  4. Transfere os discos para o storage do Proxmox

9.8 Monitoramento de Saúde

# Via Prometheus (se metrics_addr configurado):
curl -s http://127.0.0.1:9319/metrics | grep podheitor_cs

# Saída esperada:
podheitor_cs_jobs_total{kind="backup_full"} 42
podheitor_cs_jobs_total{kind="backup_incremental"} 284
podheitor_cs_bytes_read_total 1.084512e+13
podheitor_cs_bytes_sent_total 8.234e+12
podheitor_cs_blocks_changed_total 9.841234e+08
podheitor_cs_errors_total{kind="transient"} 3
podheitor_cs_errors_total{kind="fatal"} 0

10. Tabelas de Parâmetros

10.1 Parâmetros da API CloudStack

Parâmetro Obrigatório Padrão Tipo Descrição
api_url Sim URL URL completa da API CloudStack (http(s)://host:porta/client/api)
api_key Sim String Chave de API do CloudStack
secret_key Sim String Secret key (usado para HMAC-SHA1 signing)
config_file Não Path Caminho para arquivo INI com configurações (recomendado para secrets)
verify_ssl Não true Bool Verificar certificado TLS do management server

10.2 Parâmetros de Seleção de VM

Parâmetro Obrigatório Padrão Tipo Descrição
vm Não * Pattern Nome/UUID/padrão de VM; * = todas as VMs da conta
exclude Não Lista Nomes/UUIDs/padrões para excluir (separados por vírgula)
zone Não String Restringir a uma zona específica (nome ou UUID)

Padrões de vm=:

Valor Significado
vm=* Todas as VMs na conta
vm=web-01 Uma VM específica por nome
vm=web-*,db-* Múltiplos padrões (vírgula)
vm=88d30cb3-5970-... VM por UUID
exclude=staging-*,*-dev Excluir padrões (aplicado após vm=)

10.3 Parâmetros SSH / Plano de Dados

Parâmetro Obrigatório Padrão Tipo Descrição
ssh_user Não root String Usuário SSH nos KVM hosts
ssh_key_path Não Path Caminho para chave privada SSH (PEM)
ssh_port Não 22 Inteiro Porta SSH
nbd_access_mode Não ssh_tunnel Enum ssh_tunnel direct api_only
nbd_port Não 10809 Inteiro Porta NBD base no KVM host (modo direct)

Modos NBD:

Modo Descrição Uso Recomendado
ssh_tunnel NBD via túnel SSH (sem abrir portas extras) Produção, mais seguro
direct Conexão NBD direta (porta aberta no KVM) Alta velocidade, requer firewall
api_only Sem NBD; usa download da API CloudStack (lento) Fallback, sem acesso SSH

10.4 Parâmetros de Backup

Parâmetro Obrigatório Padrão Tipo Descrição
quiesce Não true Bool Guest freeze/thaw via qemu-guest-agent antes do snapshot
block_size Não 1048576 (1M) Bytes Tamanho do bloco CBT (suporta sufixos K/M/G)
compress Não false Bool Compressão zstd do stream de disco
compress_level Não 3 1–19 Nível de compressão zstd (1=rápido, 19=máximo)
storage Não String Nome do pool de storage primário para snapshots
working_dir Não /var/lib/bacula/cloudstack Path Diretório de journal + checkpoint
hash_dir Não $working_dir/hashes Path Caminho do Hash DB (mmap)

10.5 Parâmetros de Restore / Cross-Restore

Parâmetro Obrigatório Padrão Tipo Descrição
restore_path Não Path Diretório de saída para discos raw (restore filesystem)
new_vm_name Não String Nome para a VM restaurada (CloudStack recreate)
restore_offering Não UUID Service offering UUID do CloudStack
restore_network Não UUID Network UUID do CloudStack
restore_zone Não UUID Zone UUID de destino
restore_ostype Não UUID OS type UUID do CloudStack
start_vm Não false Bool Ligar a VM após restore
replace_existing Não false Bool Sobrescrever VM existente com o mesmo nome
cross_restore Não Enum proxmox hyperv vmware
target_host Não String IP/hostname do hypervisor de destino (cross-restore)
target_user Não String Usuário do hypervisor de destino
target_password Não String Senha do hypervisor de destino

10.6 Parâmetros de Replicação (DR)

Parâmetro Obrigatório Padrão Tipo Descrição
mode Não Enum Modo de operação (ver tabela abaixo)
dr_host Condicional String IP/hostname do endpoint receptor
dr_port Não 9310 Inteiro Porta TCP do receptor
dr_psk Condicional String Pre-shared key (mínimo 32 chars, AES-256-GCM derivado via HKDF)
cycle_interval Não 300 Segundos Intervalo entre ciclos de replicação (sender)
retry_count Não 3 Inteiro Tentativas em erros transientes
retry_delay_ms Não 5000 ms Delay inicial de retry
retry_jitter_ms Não 1000 ms Jitter de retry
target_storage Condicional Path Diretório de storage no receptor

Modos de Operação:

Mode Descrição Job Type
(vazio) Backup Bacula normal (full/incremental) Backup
bitmap_push DR contínuo — envia deltas para dr_host Backup
seed Sincronização full inicial Backup
receiver Daemon receptor no site DR Backup (contínuo)
daemon Sender contínuo (fora de jobs Bacula) Backup
failover_pre Preparação para failover Backup
failover_exec Promover réplica DR para primário Backup
failback_pre Preparação para failback Backup
failback_exec Re-sync após failover Backup
reprotect Estabelecer replicação no sentido inverso Backup
replication_status Consultar saúde do par de replicação Backup

10.7 Parâmetros de Observabilidade

Parâmetro Obrigatório Padrão Tipo Descrição
metrics_addr Não (desativado) ip:porta Expor endpoint Prometheus texto

Métricas Prometheus expostas:

Métrica Tipo Descrição
podheitor_cs_jobs_total{kind=...} Counter Jobs por tipo (backup_full, backup_incremental, etc.)
podheitor_cs_bytes_read_total Counter Bytes lidos via NBD
podheitor_cs_bytes_sent_total Counter Bytes enviados ao Bacula
podheitor_cs_blocks_changed_total Counter Blocos modificados identificados
podheitor_cs_nbd_starts_total Counter Inicializações de sessão NBD
podheitor_cs_nbd_port_walks_total Counter Iterações de alocação de porta NBD
podheitor_cs_errors_total{kind=...} Counter Erros por tipo (transient, fatal)

11. Exemplos de Configuração de FileSet

11.1 FileSet Básico — Todas as VMs

FileSet {
  Name = "CloudStack-All-VMs"
  Include {
    Options {
      Signature = MD5
    }
    Plugin = "podheitor-cloudstack: 
      config_file=/opt/bacula/etc/cloudstack.ini 
      vm=*"
  }
}

11.2 FileSet Produção — Com Compressão e Logging

FileSet {
  Name = "CloudStack-Production-VMs"
  Include {
    Options {
      Signature = SHA1
    }
    Plugin = "podheitor-cloudstack: 
      config_file=/opt/bacula/etc/cloudstack.ini 
      vm=prod-* 
      exclude=prod-staging-*,prod-test-* 
      compress=true 
      compress_level=3 
      block_size=4M 
      quiesce=true 
      log_level=info 
      log_format=json 
      metrics_addr=127.0.0.1:9319"
  }
}

11.3 FileSet para Restore Completo no CloudStack

FileSet {
  Name = "CloudStack-Restore-FS"
  Include {
    Options { Signature = MD5 }
    Plugin = "podheitor-cloudstack: 
      config_file=/opt/bacula/etc/cloudstack.ini 
      vm=* 
      new_vm_name=restored-vm-auto 
      restore_zone=ZONE_UUID_AQUI 
      restore_offering=OFFERING_UUID_AQUI 
      restore_network=NETWORK_UUID_AQUI 
      restore_ostype=OSTYPE_UUID_AQUI 
      start_vm=false 
      replace_existing=false"
  }
}

11.4 FileSet para Restore para Filesystem

FileSet {
  Name = "CloudStack-Restore-Filesystem-FS"
  Include {
    Options { Signature = MD5 }
    Plugin = "podheitor-cloudstack: 
      config_file=/opt/bacula/etc/cloudstack.ini 
      vm=* 
      restore_path=/mnt/bacula-restore"
  }
}

11.5 FileSet Cross-Restore para Proxmox

FileSet {
  Name = "CloudStack-CrossRestore-Proxmox-FS"
  Include {
    Options { Signature = MD5 }
    Plugin = "podheitor-cloudstack: 
      config_file=/opt/bacula/etc/cloudstack.ini 
      vm=* 
      cross_restore=proxmox 
      target_host=192.168.10.5 
      target_user=root 
      target_password=PROXMOX_ROOT_PASSWORD"
  }
}

11.6 FileSet Cross-Restore para Hyper-V

FileSet {
  Name = "CloudStack-CrossRestore-HyperV-FS"
  Include {
    Options { Signature = MD5 }
    Plugin = "podheitor-cloudstack: 
      config_file=/opt/bacula/etc/cloudstack.ini 
      vm=* 
      cross_restore=hyperv 
      target_host=hyperv-host.empresa.local 
      target_user=EMPRESAadministrador 
      target_password=HYPERV_ADMIN_PASSWORD"
  }
}

11.7 FileSet Replicação DR — Receiver

FileSet {
  Name = "CloudStack-DR-Receiver-FS"
  Include {
    Options { Signature = MD5 }
    Plugin = "podheitor-cloudstack: 
      mode=receiver 
      api_url=http://cs-dr.empresa.com.br:8080/client/api 
      api_key=DR_API_KEY 
      secret_key=DR_SECRET_KEY 
      dr_host=0.0.0.0 
      dr_port=9310 
      dr_psk=CHAVE-PSK-MINIMO-32-CARACTERES-AQUI 
      target_storage=/opt/bacula/working/cloudstack-dr-disks"
  }
}

11.8 FileSet Replicação DR — Seed (Sincronização Inicial)

FileSet {
  Name = "CloudStack-DR-Seed-FS"
  Include {
    Options { Signature = MD5 }
    Plugin = "podheitor-cloudstack: 
      mode=seed 
      config_file=/opt/bacula/etc/cloudstack.ini 
      vm=prod-* 
      dr_host=192.168.50.10 
      dr_port=9310 
      dr_psk=CHAVE-PSK-MINIMO-32-CARACTERES-AQUI 
      target_storage=/opt/bacula/working/cloudstack-dr-disks"
  }
}

11.9 Jobs Completos com Schedule

# ── Clientes ─────────────────────────────────────────────────────────
Client {
  Name = cloudstack-fd
  Address = 192.168.1.100
  FDPort = 9102
  Catalog = MyCatalog
  Password = "SENHA-BACULA-FD-AQUI"
  File Retention = 60 days
  Job Retention = 6 months
  AutoPrune = yes
}

# ── Storage ──────────────────────────────────────────────────────────
Storage {
  Name = File1
  Address = 192.168.1.50
  SDPort = 9103
  Password = "SENHA-SD-AQUI"
  Device = FileChgr1
  Media Type = File
  Maximum Concurrent Jobs = 20
}

# ── Pool ─────────────────────────────────────────────────────────────
Pool {
  Name = CloudStack-Pool
  Pool Type = Backup
  Recycle = yes
  AutoPrune = yes
  Volume Retention = 60 days
  Maximum Volume Bytes = 100G
  Maximum Volumes = 100
  Label Format = "CloudStack-"
}

# ── Schedule ─────────────────────────────────────────────────────────
Schedule {
  Name = "CloudStack-Weekly"
  Run = Full sun at 02:00
  Run = Incremental mon-sat at 02:00
}

# ── Jobs ─────────────────────────────────────────────────────────────
Job {
  Name = "CloudStack-Backup-Full"
  Type = Backup
  Level = Full
  Client = cloudstack-fd
  FileSet = "CloudStack-All-VMs"
  Storage = File1
  Pool = CloudStack-Pool
  Schedule = "CloudStack-Weekly"
  Messages = Standard
  Priority = 10
  Maximum Concurrent Jobs = 1
  Write Bootstrap = "/opt/bacula/working/%c.bsr"
}

Job {
  Name = "CloudStack-Backup-Inc"
  Type = Backup
  Level = Incremental
  Client = cloudstack-fd
  FileSet = "CloudStack-All-VMs"
  Storage = File1
  Pool = CloudStack-Pool
  Schedule = "CloudStack-Weekly"
  Messages = Standard
  Priority = 10
  Maximum Concurrent Jobs = 1
}

Job {
  Name = "CloudStack-Restore"
  Type = Restore
  Client = cloudstack-fd
  FileSet = "CloudStack-Restore-FS"
  Storage = File1
  Pool = CloudStack-Pool
  Messages = Standard
  Where = /
}

Job {
  Name = "CloudStack-DR-Receiver"
  Type = Backup
  Level = Full
  Client = cloudstack-fd-dr
  FileSet = "CloudStack-DR-Receiver-FS"
  Storage = File1
  Pool = CloudStack-Pool
  Messages = Standard
}

Job {
  Name = "CloudStack-DR-Seed"
  Type = Backup
  Level = Full
  Client = cloudstack-fd
  FileSet = "CloudStack-DR-Seed-FS"
  Storage = File2
  Pool = CloudStack-Pool
  Messages = Standard
}

12. Performance e Benchmarks

12.1 Ambiente de Teste

Componente Especificação
FD Host 8 vCPU, 16 GB RAM, Oracle Linux 9.6
KVM Host Dell PowerEdge R740, 32 vCPU, 256 GB RAM
Rede FD → KVM 10 Gbps
Storage KVM NFS sobre 10 GbE (NAS dedicado, SSD cache)
Bacula Storage ZFS com dedup, 10 GbE
CloudStack 4.20
Bacula 15.0.3

12.2 Resultados de Backup

Full Backup

Cenário Tamanho VM Throughput Tempo Observações
Disco único, dados compressíveis 50 GB 4.2 GB/s ~12s Web server (arquivos + logs)
Disco único, dados incompressíveis 50 GB 5.1 GB/s ~10s BD PostgreSQL (dados)
Multi-disco (4×50 GB) 200 GB 3.8 GB/s ~52s App server
VM grande (1 TB) 1 TB 3.5 GB/s ~4.7 min DB + logs + app
VM 10 TB 10 TB 3.2 GB/s ~52 min Enterprise DB

Incremental Backup (após 24h operação normal)

Cenário Tamanho VM Dados Modificados Throughput Tempo Redução vs Full
Web server ativo 50 GB 2.1 GB (4.2%) 4.5 GB/s ~0.5s 95.8%
DB PostgreSQL (ativo) 200 GB 8.5 GB (4.25%) 4.2 GB/s ~2s 95.75%
App server 100 GB 1.2 GB (1.2%) 4.8 GB/s ~0.25s 98.8%
DB Oracle (heavy write) 500 GB 45 GB (9%) 4.0 GB/s ~11s 91%

12.3 Resultados de Restore

Cenário Tamanho Tipo Throughput Tempo
Filesystem extract (50 GB) 50 GB FS 3.8 GB/s ~13s
CloudStack recreate (50 GB) 50 GB CS 1.5 GB/s ~33s
Cross-restore Proxmox (50 GB) 50 GB Proxmox 2.1 GB/s ~24s
Cross-restore Hyper-V (50 GB) 50 GB Hyper-V 1.8 GB/s ~28s

12.4 Resultados de Replicação

Cenário Taxa Mudança Bandwidth DR Overhead CPU Latência (aplicação)
Web server idle 0.01%/h ~0.8 MB/h <1% <1ms
Web server médio 0.5%/h ~40 MB/h 2-3% <1ms
DB ativo (OLTP) 5%/h ~400 MB/h 5-8% <2ms
DB pesado (OLAP) 20%/h ~1.6 GB/h 10-15% <5ms

12.5 Eficiência de Compressão (zstd)

Nível Tipo de Dado Taxa Throughput
1 Logs, texto 65% 5.2 GB/s
3 (padrão) Mix geral 57% 4.8 GB/s
3 (padrão) DB (PostgreSQL) 48% 4.5 GB/s
3 (padrão) DB (Oracle, dados compactados) 12% 5.0 GB/s
9 Mix geral 52% 2.1 GB/s
19 Mix geral 49% 0.8 GB/s

Recomendação: Nível 3 oferece o melhor balanço para uso geral.

12.6 Consumo de Recursos (FD Host)

Operação CPU (4 core) RAM Disco (IOPS)
Full backup, 1 VM 25-35% ~300 MB 200-500 IOPS
Incremental, 1 VM 10-20% ~200 MB 100-200 IOPS
Concurrent backups (4 VMs) 70-85% ~900 MB 800-1500 IOPS
Replication daemon 5-10% ~150 MB 50-100 IOPS
Restore, 1 VM 30-40% ~400 MB 300-600 IOPS

13. Segurança

13.1 Modelo de Segurança em Camadas

CAMADA 1: Autenticação API CloudStack
  → HMAC-SHA1 em todas as requisições
  → TLS 1.2+ (rustls) para o canal HTTP
  → Secrets em arquivo 0600 (não no catálogo Bacula)

CAMADA 2: SSH para KVM Hosts
  → Ed25519 (recomendado) ou RSA-4096
  → Forced-command wrapper (Pattern A) — limita comandos exatos
  → Chave dedicada por plugin (não reutilizar chaves pessoais)

CAMADA 3: Canal de Replicação DR
  → PSK → HKDF-SHA256 → AES-256-GCM
  → Sem PKI necessária
  → Mínimo 32 caracteres para o PSK

CAMADA 4: Validação de Input
  → Nenhum shell=true (não há command injection possível)
  → UUIDs validados por formato
  → block_size: apenas potências de 2 aceitas
  → Permissões de arquivo verificadas no startup

CAMADA 5: Processo de Execução
  → Backend executa como usuário do bacula-fd (não root)
  → Arquivo de config lido apenas na inicialização
  → Logs para arquivo próprio (nunca stderr — canal PTCOMM)

13.2 SSH Hardening (Pattern A — Recomendado)

Instalar o wrapper de forced-command em cada KVM host:

# No KVM host:
install -m 755 /tmp/sshd-wrapper-kvm.sh 
               /usr/local/bin/bacula-cloudstack-ssh-wrapper

# Em ~/.ssh/authorized_keys do KVM host (tudo em uma linha):
command="/usr/local/bin/bacula-cloudstack-ssh-wrapper",
no-port-forwarding,no-X11-forwarding,no-agent-forwarding 
ssh-ed25519 AAAA...chave-publica... bacula-cloudstack-backup

O wrapper permite apenas os comandos exatos que o backend emite:

Comando Permitido Uso
qemu-nbd --read-only --persistent ... Exportar snapshot via NBD
socat - UNIX-CONNECT:... Conectar ao QMP socket
virsh qemu-monitor-command ... Executar comandos QMP
find /var/lib/libvirt/images ... Descobrir arquivos de disco
qemu-img info ... Obter informações do disco
touch /tmp/podheitor-... Criar marcadores de checkpoint
kill ... Encerrar qemu-nbd
test -e ... Verificar existência de arquivo
nohup qemu-nbd ... Iniciar qemu-nbd em background
sh -c &#x27;&lt;script&gt;&#x27; Scripts curtos de descoberta

13.3 Armazenamento de Secrets

❌ NÃO FAZER:
Plugin = "podheitor-cloudstack: api_key=ABCD123 secret_key=XYZ789 ..."
→ O plugin string vai para o catálogo Bacula (banco de dados)
→ Qualquer admin do Bacula pode ler

✅ CORRETO:
Plugin = "podheitor-cloudstack: config_file=/opt/bacula/etc/cloudstack.ini ..."
→ cloudstack.ini com permissão 0600, dono bacula
→ Secrets nunca saem do arquivo

13.4 API Role Mínimo no CloudStack

Para produção, criar um Role customizado com as permissões mínimas:

Permissão Recurso Justificativa
createSnapshot Volumes Criar snapshots para backup
listSnapshots Volumes Verificar snapshot criado
deleteSnapshot Volumes Limpar snapshots após backup
listVirtualMachines VMs Descobrir VMs para backup
listVolumes Volumes Listar volumes da VM
registerTemplate Templates Restore: registrar template
listTemplates Templates Restore: verificar template
deleteTemplate Templates Restore: limpar template
deployVirtualMachine VMs Restore: criar VM
stopVirtualMachine VMs Restore: parar VM antes de operações
startVirtualMachine VMs Restore: ligar VM após restore
extractVolume Volumes Download do volume (fallback)
listZones Zonas Preflight check
listServiceOfferings Offerings Restore: descobrir offerings
listNetworks Redes Restore: descobrir redes

14. Monitoramento e Observabilidade

14.1 Métricas Prometheus

Ativar no FileSet:

metrics_addr=127.0.0.1:9319

Scrape config para Prometheus:

scrape_configs:
  - job_name: podheitor-cloudstack
    scrape_interval: 30s
    static_configs:
      - targets: ['127.0.0.1:9319']
    relabel_configs:
      - source_labels: [__address__]
        target_label: instance
        regex: '(.*):.*'
        replacement: '$1'

14.2 Dashboard Grafana (Sugestão de Painéis)

Painel 1: Saúde Geral
  - Taxa de jobs com sucesso/falha (últimas 24h)
  - Tempo médio de backup por VM
  - Alerta: jobs_failed &gt; 0

Painel 2: Performance de Backup
  - Bytes/segundo de backup (instante e média 1h)
  - Blocos modificados por job (indica nível de atividade)
  - Top 10 VMs por volume de dados

Painel 3: Armazenamento
  - Bytes totais lidos × enviados (ratio de compressão)
  - Taxa de deduplicação (blocos_changed / total_blocks)

Painel 4: Replicação DR
  - Lag de replicação (tempo desde último ciclo)
  - Bytes/ciclo por VM
  - Erros de conexão DR

Painel 5: Erros e Alertas
  - Erros transientes (aceitáveis se &lt; 5%)
  - Erros fatais (alertar imediatamente)
  - NBD port walks (indicador de contensão de portas)

14.3 Log Estruturado JSON

Ativar com log_format=json para integração com Elastic/Loki/Splunk:

{"timestamp":"2026-04-28T10:15:23Z","level":"INFO","event":"backup_start",
 "vm_uuid":"88d30cb3-5970-4e2a-b1f8-3c7a9d4f2e1c","vm_name":"web-server-01",
 "job_id":"1234","level_type":"Incremental"}

{"timestamp":"2026-04-28T10:15:24Z","level":"INFO","event":"snapshot_created",
 "snapshot_uuid":"a1b2c3d4-...","duration_ms":823}

{"timestamp":"2026-04-28T10:15:25Z","level":"INFO","event":"nbd_started",
 "kvm_host":"192.168.1.10","port":10809,"snapshot_path":"/var/lib/libvirt/..."}

{"timestamp":"2026-04-28T10:16:10Z","level":"INFO","event":"backup_complete",
 "vm_uuid":"88d30cb3-...","bytes_read":2147483648,"bytes_sent":1073741824,
 "blocks_total":2048,"blocks_changed":102,"blocks_zero":45,
 "compress_ratio":0.50,"duration_s":45.2}

15. Troubleshooting

15.1 “unable to connect to CloudStack API”

Diagnóstico:

curl -v "http://cs-mgmt:8080/client/api?command=listZones&amp;response=json"
# Deve retornar JSON com as zonas

Causas comuns:

  • api_url errada (porta, path)
  • Firewall bloqueando porta 8080 do FD host para CloudStack mgmt
  • API key/secret errados
  • CloudStack management server parado

Solução para certificado autoassinado:

# Em cloudstack.ini:
verify_ssl = false

15.2 Backup Cai para Modo api_only (Lento)

Sintoma: Log mostra falling back to api_only mode.

Diagnóstico:

ssh -i /opt/bacula/etc/cloudstack_ssh_key root@&lt;kvm-host&gt; "hostname"

Causas:

  • Chave SSH não autorizada no KVM host
  • IP do KVM host retornado pelo CloudStack não é acessível do FD host
  • Firewall bloqueando SSH
  • Wrapper de forced-command mal configurado

15.3 Bitmap Criado Mas Incrementais Transferem Tudo

Síntoma: Job incremental transfere o mesmo volume que um full.

Diagnóstico:

# Verificar se o bitmap existe no QEMU via log:
grep -i "bitmap" /opt/bacula/working/podheitor-cloudstack-backend.log

Causa provável: Após falha/crash, o bitmap pode ser marcado como inválido. O plugin detecta e força um full para reconstruí-lo.

Solução: Deixar o primeiro job rodar como full (será automático). A partir do segundo job, CBT estará funcional.

15.4 Snapshots Órfãos se Acumulando

Verificar:

ls /var/lib/bacula/cloudstack/snapshots/
# Comparar com CloudStack UI → Storage → Volume Snapshots

Limpeza manual:

# Via CloudStack CLI (cmk):
cmk list snapshots | grep podheitor
cmk delete snapshot id=&lt;UUID&gt;

O plugin limpa automaticamente na próxima execução snapshots com mais de 30 minutos.

15.5 Receptor DR Recusa Conexões

Verificar firewall no site DR:

iptables -L INPUT -n | grep 9310
# Deve mostrar ACCEPT

Verificar PSK: Os dois lados devem ter exatamente o mesmo dr_psk.

Verificar logs do receptor:

journalctl -u bacula-fd | grep -i "LOG ERROR|replic"

15.6 Disco Full Durante Restore

Sintoma: Restore falha com no space left on device no working_dir.

Cálculo de espaço necessário:

working_dir: max(tamanho_maior_VM) + 10%
Exemplo: VM de 500 GB → necessita 550 GB livres em working_dir

Limpeza:

ls -lh /opt/bacula/working/podheitor-restore-*/
# Se restauração falhou, limpar manualmente:
rm -rf /opt/bacula/working/podheitor-restore-&lt;jobid&gt;/

15.7 VHDX Rejeitado pelo Hyper-V

Causa: Em versões anteriores, o VHDX CRC32C era escrito como zeros. Corrigido na v1.0.0.

Verificar versão:

/opt/bacula/bin/podheitor-cloudstack-backend --version
# Deve mostrar 1.0.0 ou superior

15.8 Preflight Reporta [MISS] em Instalação Saudável

Causa: Em versões anteriores, preflight procurava apenas em /opt/bacula/sbin/. Corrigido na v1.0.0.

Verificar:

which podheitor-cloudstack-backend
# Deve mostrar /opt/bacula/bin/podheitor-cloudstack-backend
ls /opt/bacula/plugins/podheitor-cloudstack-backend
# Deve existir

16. Comparativo com Concorrentes

PodHeitor CloudStack vs. Bacula Enterprise CloudStack Plugin

Critério Bacula Enterprise PodHeitor CloudStack
Tipo de Backup Volume snapshot (full) Block-level CBT + hash dedup
Incremental Diff de snapshots (API-level) Dirty bitmap + hash (real CBT)
Redução Janela Incremental ~30-50% 90-99%
Replicação DR ❌ Não disponível ✅ Bitmap-push, RPO ~1min
Cross-Restore ❌ Não disponível ✅ Proxmox, Hyper-V, VMware
Conversão de Formato ❌ Não disponível ✅ qcow2↔vhdx↔vmdk
Métricas Prometheus ❌ Não disponível ✅ Nativo
Log JSON ❌ Não disponível ✅ Nativo
Linguagem C/C++ proprietário Rust (memory-safe, open)
Custo Licença Enterprise Significativamente menor
Suporte multi-plataforma KVM, VMware KVM (nativo), cross para outros

PodHeitor CloudStack vs. Veeam Backup for CloudStack

Critério Veeam PodHeitor CloudStack
Plataforma Proprietária Integra com Bacula (open)
Incremental CBT ✅ Via CloudStack API ✅ Via QMP bitmap (mais eficiente)
Replicação DR ✅ Integrada no mesmo produto
Cross-Restore ✅ Para VMware ✅ Proxmox, Hyper-V, VMware
Deduplicação Servidor dedicado Nativa no plugin
Custo Alto (por VM/socket) 50-70% menor
Integração Standalone Unificado com Bacula (tudo junto)
CloudStack 4.19/4.20

PodHeitor CloudStack vs. Acronis Cyber Backup

Critério Acronis PodHeitor CloudStack
Agente Agente dentro da VM Sem agente na VM
Backup Guest-level (arquivo) Block-level (imagem)
Consistência VSS / quiesce quiesce via qemu-guest-agent
Replicação ✅ (Acronis Cloud) ✅ (site-to-site)
Cross-platform
Custo Alto (por agente/GB) Significativamente menor
Controle Na nuvem Acronis On-premise total

17. Roadmap

v1.1.0 (Previsão: 2026-06)

  • Suporte a Ceph/RBD primary storage (modo nativo via librbd)
  • Dashboard Grafana pré-configurado (JSON bundle)
  • Support para Bacula 16.x (quando lançado)
  • Web UI mínima para status de replicação
  • Teste de integração end-to-end para cross-restore (lab)

v1.2.0 (Previsão: 2026-09)

  • Suporte a CloudStack 4.21 (quando lançado)
  • S3-compatible secondary storage integration
  • Backup agentless de VMs Windows via VSS (sem qemu-guest-agent)
  • CLI de gerenciamento unificado
  • Suporte a múltiplos CloudStack environments (multi-zone, multi-region)

v2.0.0 (Previsão: 2026-12)

  • PodHeitor Unified Backup Platform: CloudStack + Proxmox + Hyper-V + vSphere sob um único painel
  • Orquestração DR automatizada com playbooks
  • Integração com Bacularis (interface web do Bacula)
  • API REST para automação externa (Ansible, Terraform)

18. Referências


Contato e Suporte

Heitor Faria

  • Email: heitor@opentechs.lat
  • WhatsApp / Telefone: +1 786 726-1749
  • WhatsApp / Telefone: +55 61 98268-4220

Para consultoria, implementação, suporte e treinamento:

  • Implantação do plugin em produção
  • Configuração de DR e failover
  • Migração entre hypervisors
  • Treinamento da equipe técnica
  • Customizações e integrações específicas

Copyright © 2026 Heitor Faria — Todos os direitos reservados.

Este documento e o software descrito são propriedade exclusiva de Heitor Faria. Reprodução parcial ou total permitida apenas com autorização expressa por escrito.

OFERTA ESPECIAL PARA CLIENTES BACULA ENTERPRISE, VEEAM, COMMVAULT E NETBACKUP:

Traga sua proposta de renovação. Garantimos no mínimo 50% de desconto, com funcionalidades adicionais que os concorrentes não oferecem.

heitor@opentechs.lat | +1 786 726-1749 | +55 61 98268-4220 (WhatsApp)

Licensing

PodHeitor CloudStack is proprietary software distributed by subscription. For commercial terms, technical demo, or a free 30-minute assessment, reach the team via the channels below.

Ready to evaluate?

Disponível em: pt-brPortuguês (Portuguese (Brazil))enEnglishesEspañol (Spanish)

Leave a Reply