Lasciare VMware dopo Broadcom: guida alla migrazione

Lasciare VMware dopo Broadcom: guida alla migrazione

Lasciare VMware dopo Broadcom: guida alla migrazione

Risposta breve (verificato il 2026-11-03): dopo l'acquisizione di VMware, Broadcom ha smesso di vendere licenze perpetue, ha accorpato il listino in due pacchetti in abbonamento, ha chiuso in Europa il vecchio programma per i partner cloud e, questo autunno, ha ritirato il download pubblico di VDDK, la libreria per i dischi che la maggior parte degli strumenti di migrazione usa per leggere i dischi VMware. Oggi The Register segnala un sostituto open source, in sola lettura, per questa libreria. Non tutte le vie d'uscita richiedono però VDDK: un export OVA seguito da una conversione del disco non usa alcun codice VMware. Di seguito: i cambiamenti con le date, destinazioni realistiche per un team europeo, la migrazione passo per passo e un convertitore che abbiamo eseguito su un vero export in formato VMware.

Fonte. "Architect creates open-source replacement for VM migration tool VMware has hidden" (Simon Sharwood, The Register, 2026-11-03). Gli altri fatti sono collegati dove compaiono. Il vostro contratto può differire dalle condizioni pubbliche, quindi fate confermare i dettagli della licenza dal vostro rivenditore.

Cosa ha cambiato Broadcom, con le date

Data Cambiamento Fonte
2023-12-11 Fine della vendita di licenze perpetue e dei rinnovi del supporto; offerta ridotta agli abbonamenti VMware Cloud Foundation (VCF) e vSphere Foundation (VVF) Notizie Broadcom, Krish Prasad
2025-03-28 Il distributore Arrow comunica ai partner che l'ordine minimo sale da 16 a 72 core per linea di prodotto dal 2025-04-10 The Register
2026-01-26 Contratti dei cloud provider (VCSP) nello SEE non rinnovati; trattative aperte da chiudere entro il 2026-03-31; in seguito programma solo su invito The Register, 2026-01-31
Ago-set 2026 VDDK rimosso dal download pubblico: "The VDDK is not a customer entitlement" (VDDK non è un diritto del cliente), accesso tramite alcuni partner TAP TechTarget, 2026-09-09
2026-11-03 OpenVDDK di Andrija Panić: sostituto diretto in sola lettura, con licenza Apache, di libvixDiskLib.so.8.0.3 che "contains no VMware code" (non contiene codice VMware) The Register, 2026-11-03

Due avvertenze. Il minimo di 72 core è stato riportato da un distributore, non da una pagina Broadcom che siamo riusciti a trovare: l'articolo di Broadcom sul conteggio dei core (KB 313548, verificato il 2026-11-03) dice "You must license a minimum of 16 physical cores for each CPU" (almeno 16 core fisici per ogni CPU), e alcuni rivenditori affermano che il minimo d'ordine di 72 core è stato di nuovo eliminato. Chiedete per iscritto il numero di core indicato nel vostro preventivo. E il fronte europeo è ancora aperto: l'associazione di settore del cloud CISPE ha chiesto nel luglio 2025 al Tribunale dell'Unione europea di annullare l'approvazione della fusione da parte della Commissione (causa T-503/25); non abbiamo ancora trovato una sentenza.

Perché VDDK conta e quali strade lo evitano

La libreria di VDDK, libvixDiskLib, permette a uno strumento di leggere i dischi delle VM che si trovano ancora in vSphere. The Register cita virt-v2v, nbdkit, gli importatori Forklift / MTV, Apache CloudStack e script interni tra gli strumenti che la caricano. L'estensione VM Conversion di Microsoft per Windows Admin Center (da vCenter a Hyper-V, con sincronizzazione a caldo tramite Change Block Tracking) è ancora indicata come anteprima nella sua documentazione (aggiornata il 2026-02-20), e gli articoli sul lancio elencano VDDK tra i prerequisiti. OpenVDDK è la nuova opzione per tutti questi strumenti, con l'avvertenza del suo stesso autore che i resoconti dei tester sono "not independently audited customer endorsements" (non referenze di clienti verificate in modo indipendente).

Strade senza alcun VDDK, secondo la documentazione dell'input VMware di virt-v2v (verificata il 2026-11-03): un export OVA (-i ova), i file della VM su NFS o via SSH (-i vmx, -it ssh), NFC e il semplice percorso HTTPS di vCenter, che la documentazione definisce "the slowest method" (il metodo più lento). La procedura guidata di importazione ESXi di Proxmox VE, annunciata il 2024-03-27, legge i dischi tramite l'API ESXi con un proprio file system in spazio utente scritto in Rust ed è stata testata con ESXi da 6.5 a 8.0 (forum Proxmox).

Dove migrare: cinque destinazioni realistiche

Destinazione Adatta quando Attenzione a
Proxmox VE (KVM) sul vostro hardware 3+ host, un team che vuole una GUI e il clustering Aggiornamenti, storage (ZFS, Ceph) e supporto sono a vostro carico
OpenStack Molti tenant, tutto tramite API Pesante da gestire; conviene solo su larga scala
Hyper-V (Windows Server) Parco prevalentemente Windows, licenze Datacenter già pagate Lo strumento di Microsoft richiede prima i driver Hyper-V negli guest Linux
Server cloud (KVM) Da poche a qualche decina di VM, nessuna voglia di gestire un hypervisor Un'importazione per VM, nuovi indirizzi IP
Server dedicati + il vostro hypervisor Carico costante, volete l'intera macchina L'hypervisor lo gestite e aggiornate voi

Spostare una VM in cinque passi

  1. Inventario e pulizia. Annotate firmware (BIOS o EFI), controller del disco, tipo di scheda di rete, IP statici e ogni licenza legata a un indirizzo MAC. Eliminate o consolidate gli snapshot, così da esportare un solo disco aggiornato.
  2. Preparate il guest mentre gira ancora su VMware. Windows: installate subito i driver virtio (virtio-win); un guest Windows spostato su un disco virtio senza di essi non si avvia. Linux: i driver virtio sono nel kernel, ma un initramfs host-only può escluderli; controllate con lsinitramfs o lsinitrd e ricostruitelo se serve.
  3. Esportate o collegatevi. Spegnete la VM ed esportate un OVF / OVA (vSphere Client "Export OVF Template", oppure ovftool), oppure lasciate che sia virt-v2v o la procedura guidata di Proxmox a prelevarla.
  4. Convertite. Solo il disco con qemu-img, l'intero guest con virt-v2v (che adatta anche i driver), oppure direttamente in Proxmox a partire dall'OVF.
  5. Avviate dalla console, poi fate pulizia. Controllate il nome della scheda di rete e l'IP, rimuovete VMware Tools o open-vm-tools, installate qemu-guest-agent.
qemu-img convert -p -f vmdk -O qcow2 disk1.vmdk disk1.qcow2
virt-v2v -i ova VM.ova -o local -os /var/tmp -of qcow2
qm importovf 120 VM.ovf local-lvm

Queste sono le forme documentate nel manuale di ciascuno strumento; questi tre comandi non li abbiamo eseguiti qui. La conversione che abbiamo eseguito davvero è qui sotto.

Testato: cosa fa davvero una conversione (ova2raw.js)

Per mostrare gli ingranaggi, abbiamo scritto la conversione in circa 100 righe di Bun senza dipendenze. Lo script apre un OVA (un semplice archivio tar), verifica il manifest SHA-256, stampa l'hardware richiesto dall'OVF, decomprime il VMDK streamOptimized grain per grain in un'immagine raw sparsa e controlla la GPT. Gli abbiamo dato in pasto l'OVA ufficiale di Ubuntu 24.04, un vero export in formato VMware: noble-server-cloudimg-amd64.ova, build del 2026-10-17, il cui SHA-256 corrispondeva al SHA256SUMS di Ubuntu. Salvatelo come ova2raw.js:

// ova2raw.js - check a VMware OVA export and turn its disk into a raw image for KVM
// usage: bun ova2raw.js <export.ova> <out.raw>
import { openSync, readSync, writeSync, ftruncateSync, closeSync, fstatSync } from 'node:fs'
import { inflateSync } from 'node:zlib'
import { createHash } from 'node:crypto'

const [ova, out] = process.argv.slice(2)
const fd = openSync(ova, 'r')
const read = (pos, len) => {
  const b = Buffer.alloc(len)
  readSync(fd, b, 0, len, pos)
  return b
}

// 1. an OVA is a plain tar: list its members
const files = {}
for (let o = 0; o + 512 <= fstatSync(fd).size; ) {
  const h = read(o, 512)
  if (h.every(x => x === 0)) break
  const name = h.toString('utf8', 0, 100).replace(/\0.*$/s, '')
  const size = parseInt(h.toString('ascii', 124, 136).replace(/\0.*$/s, '').trim(), 8)
  files[name] = { pos: o + 512, size }
  o += 512 + Math.ceil(size / 512) * 512
}
const find = ext => Object.keys(files).find(n => n.endsWith(ext))
const text = n => read(files[n].pos, files[n].size).toString('utf8')
console.log('OVA members:', Object.entries(files).map(([n, f]) => `${n} (${f.size} B)`).join(', '))

// 2. the .mf manifest: every member's SHA-256 must match
const mf = find('.mf')
for (const line of mf ? text(mf).split('\n') : []) {
  const m = line.match(/^SHA(1|256)\((.+)\)\s*=\s*([0-9a-f]+)/i)
  if (!m || !files[m[2]]) continue
  const h = createHash('sha' + m[1])
  const f = files[m[2]]
  for (let p = 0; p < f.size; p += 1 << 24) h.update(read(f.pos + p, Math.min(1 << 24, f.size - p)))
  console.log(`  manifest ${m[2]}: ${h.digest('hex') === m[3].toLowerCase() ? 'OK' : 'MISMATCH'}`)
}

// 3. the .ovf descriptor: what the VM expects from its hardware
const ovf = text(find('.ovf'))
const items = [...ovf.matchAll(/<(?:ovf:)?Item\b[\s\S]*?<\/(?:ovf:)?Item>/g)].map(x => x[0])
const tag = (s, t) => s.match(new RegExp(`<(?:rasd:)?${t}>([^<]*)<`))?.[1]
const kind = { 3: 'CPU', 4: 'RAM', 5: 'IDE controller', 6: 'SCSI controller', 10: 'NIC', 17: 'disk', 20: 'SATA controller' }
console.log('OVF:', ovf.match(/vmw:osType="([^"]+)"/)?.[1] ?? '?', '| firmware',
  ovf.match(/key="firmware" ovf:value="([^"]+)"/)?.[1] ?? 'bios (default)')
for (const it of items) {
  const k = kind[tag(it, 'ResourceType')]
  if (k) console.log(`  ${k.padEnd(16)} ${tag(it, 'ElementName') ?? ''} ${tag(it, 'ResourceSubType') ?? ''} ${tag(it, 'VirtualQuantity') ?? ''}`.trimEnd())
}

// 4. the streamOptimized VMDK: a header, then compressed grains and markers
const vmdk = files[find('.vmdk')]
const hd = read(vmdk.pos, 512)
if (hd.readUInt32LE(0) !== 0x564d444b) throw new Error('not a sparse VMDK (no KDMV magic)')
const capacity = Number(hd.readBigUInt64LE(12)) * 512
const desc = read(vmdk.pos + Number(hd.readBigUInt64LE(28)) * 512, Number(hd.readBigUInt64LE(36)) * 512)
console.log(`VMDK ${desc.toString().match(/createType="([^"]+)"/)?.[1]}, virtual size ${capacity} B, grain ${Number(hd.readBigUInt64LE(20)) * 512} B`)

const ofd = openSync(out, 'w')
ftruncateSync(ofd, capacity) // sparse: unwritten grains stay holes = zeros
let pos = Number(hd.readBigUInt64LE(64)) * 512
let grains = 0
let written = 0
while (pos < vmdk.size) {
  const m = read(vmdk.pos + pos, 512)
  const val = Number(m.readBigUInt64LE(0))
  const size = m.readUInt32LE(8)
  if (size) { // compressed grain: lba, size, zlib data
    const raw = inflateSync(read(vmdk.pos + pos + 12, size))
    writeSync(ofd, raw, 0, raw.length, val * 512)
    grains++
    written += raw.length
    pos += Math.ceil((12 + size) / 512) * 512
  } else if (m.readUInt32LE(12) === 0) break // end-of-stream marker
  else pos += 512 + val * 512 // grain table / directory / footer: metadata only
}
closeSync(ofd)
console.log(`Wrote ${out}: ${grains} grains, ${written} B of data in ${capacity} B`)

// 5. check the result: a valid GPT, and the file systems where the partitions say they are
const rfd = openSync(out, 'r')
const at = (p, l) => { const b = Buffer.alloc(l); readSync(rfd, b, 0, l, p); return b }
const gpt = at(512, 92)
const crc = Buffer.from(gpt)
crc.writeUInt32LE(0, 16)
console.log(`GPT "${gpt.toString('ascii', 0, 8)}", header CRC ${(Bun.hash.crc32(crc) >>> 0) === gpt.readUInt32LE(16) ? 'OK' : 'BAD'}`)
const n = gpt.readUInt32LE(80)
const es = gpt.readUInt32LE(84)
const ents = at(Number(gpt.readBigUInt64LE(72)) * 512, n * es)
console.log(`  partition array CRC ${(Bun.hash.crc32(ents) >>> 0) === gpt.readUInt32LE(88) ? 'OK' : 'BAD'}`)
for (let i = 0; i < n; i++) {
  const e = ents.subarray(i * es, (i + 1) * es)
  if (e.subarray(0, 16).every(x => x === 0)) continue
  const first = Number(e.readBigUInt64LE(32))
  const last = Number(e.readBigUInt64LE(40))
  const sb = at(first * 512 + 1024, 136)
  const fs = sb.readUInt16LE(56) === 0xef53 ? `ext4 label "${sb.toString('ascii', 120, 136).replace(/\0.*$/s, '')}"`
    : at(first * 512, 512).toString('ascii', 82, 87) === 'FAT32' ? 'FAT32 (EFI system partition)'
    : e.toString('ascii', 0, 16) === 'Hah!IdontNeedEFI' ? 'BIOS boot (GRUB for legacy BIOS)' : 'unknown'
  console.log(`  p${i + 1} ${String((last - first + 1) * 512 / 2 ** 20 | 0).padStart(5)} MiB  ${fs}`)
}
bun ova2raw.js noble-server-cloudimg-amd64.ova noble.raw

Output, eseguito su un server DCXV Cloud con Bun 1.4.4 il 2026-11-03:

OVA members: ubuntu-noble-24.04-cloudimg.ovf (11186 B), ubuntu-noble-24.04-cloudimg.mf (213 B), ubuntu-noble-24.04-cloudimg.vmdk (590749696 B)
  manifest ubuntu-noble-24.04-cloudimg.vmdk: OK
  manifest ubuntu-noble-24.04-cloudimg.ovf: OK
OVF: ubuntu64Guest | firmware bios (default)
  CPU              2 virtual CPU(s)  2
  RAM              1024MB of memory  1024
  SCSI controller  SCSI Controller 0 VirtualSCSI
  IDE controller   VirtualIDEController 1
  IDE controller   VirtualIDEController 0
  disk             Hard Disk 1
  NIC              Ethernet 1 VmxNet3
VMDK streamOptimized, virtual size 10737418240 B, grain 65536 B
Wrote noble.raw: 28663 grains, 1878458368 B of data in 10737418240 B
GPT "EFI PART", header CRC OK
  partition array CRC OK
  p1  2558 MiB  ext4 label "cloudimg-rootfs"
  p14     4 MiB  BIOS boot (GRUB for legacy BIOS)
  p15   106 MiB  FAT32 (EFI system partition)
  p16   913 MiB  ext4 label "BOOT"

Tre esecuzioni hanno richiesto da 14.6 a 16.2 s di tempo reale su quel server. Il file raw ha una dimensione di 10 GiB e occupa 1.8 GB su disco.

Cosa vi dice l'output prima del passaggio

  1. VmxNet3 e VirtualSCSI sono dispositivi VMware. Su KVM diventano virtio-net e virtio-blk o virtio-scsi. Il guest ha bisogno dei driver per entrambi prima del primo avvio, e l'interfaccia di rete di solito cambia nome, quindi un IP statico legato al vecchio nome non si attiverà. Usate la console per il primo avvio.
  2. Il firmware deve coincidere. Questo OVF non imposta nulla, quindi è BIOS; il disco contiene sia una partizione di avvio BIOS sia una partizione di sistema EFI, quindi si avvia in entrambi i casi. Una VM esportata con firmware=efi richiede UEFI (OVMF) sulla destinazione, altrimenti non trova alcun boot loader.
  3. Il thin resta thin solo se lo mantenete tale. 10 GiB virtuali, 1.8 GB di dati. Copiate con strumenti che gestiscono i file sparsi (cp --sparse=always, rsync -S) oppure usate qcow2, altrimenti trasferite e archiviate zeri.
  4. Il manifest è il vostro controllo del trasferimento. Verificate lo SHA-256 dopo ogni copia tra siti: un upload interrotto si converte senza errori in un disco che fallirà più avanti.

Pianificare il fermo

Uno spostamento a freddo costa export + trasferimento + conversione + primo avvio. Cronometrate ogni fase su una VM di prova, poi moltiplicate. Calcolo del trasferimento (nostro, al netto dell'overhead di protocollo): 1.8 GB a 1 Gbit/s sono circa 15 s, 1 TB circa 2.2 ore. Gli strumenti a caldo copiano mentre la VM è in funzione e alla fine inviano solo i blocchi modificati; i tester citati da The Register riportano esecuzioni a freddo e a caldo con Forklift e MTV. Per database e applicazioni molto usate, replica più cambio DNS batte qualsiasi copia del disco: abbassate prima il TTL (vedi propagazione DNS e TTL) e seguite le checklist di come migrare su un server cloud.

Quando sono adatti i server cloud o dedicati DCXV

  • Poche VM, nessun team per l'hypervisor: i nostri server cloud girano su KVM con dischi virtio. Nel pannello, Reinstalla -> "Immagine personalizzata (URL)" accetta un file qcow2, raw o vmdk via https; un'immagine più grande del disco del piano aumenta il disco e viene fatturata come upgrade del disco, e le impostazioni di rete vengono applicate solo se l'immagine include cloud-init. I piani partono da EUR 15.00/mese (2 vCPU, 4 GB RAM, 40 GB; verificato il 2026-11-03, IVA esclusa).
  • Decine di VM o un vostro cluster Proxmox: server dedicati da EUR 210/mese, con l'hypervisor che preferite.
  • Guest Windows: rivendiamo licenze Windows Server; chiedete prima dello spostamento, così la licenza è pronta dal primo giorno.

Entrambi funzionano nei nostri data center Tier III di Praga e Covilha.

Pianificate la migrazione con noi

Eseguite ova2raw.js su una VM esportata e inviate le righe sull'hardware del suo output a sales@dcxv.com, oppure avviate un server cloud e provate voi stessi l'importazione.

Lasciare VMware dopo Broadcom: guida alla migrazione
clouddedicatedinfrastructure

Lasciare VMware dopo Broadcom: guida alla migrazione

Broadcom ha chiuso le licenze perpetue, tagliato i partner e nascosto VDDK. Come spostare VM su KVM, Proxmox o Hyper-V: date e un convertitore OVA già testato.

Propagazione DNS: 3 secondi di Cloudflare contro il tuo TTL
networkingcloudinfrastructure

Propagazione DNS: 3 secondi di Cloudflare contro il tuo TTL

Cloudflare ha ridotto il ritardo di build DNS a 3,3 s. Il passaggio di server però attende TTL, cache negativa e 2 giorni di delega .com. Misurato su due zone.

10.000 commenti nei consigli USA: cosa cambia per i clienti
clouddedicatedinfrastructure

10.000 commenti nei consigli USA: cosa cambia per i clienti

Un dataset codifica 10.202 interventi sui data center negli USA: 90,5% contrari, l'acqua al primo posto. Lo ricontiamo e spieghiamo cosa cambierà per i clienti.

Supporto e fatturazione AWS: guida verificata per team UE
cloudpricingcompare

Supporto e fatturazione AWS: guida verificata per team UE

Piani di supporto AWS e prezzi, ritardi nei dati di fatturazione, egress, uno script per controllare i costi e quando è più adatto un provider UE a prezzo fisso

Latenza di memoria su un server cloud: misurata, non stimata
clouddedicatedinfrastructure

Latenza di memoria su un server cloud: misurata, non stimata

Un post virale dice che una CPU occupata spesso aspetta solo la RAM. Abbiamo misurato la latenza da L1 a DRAM sul nostro server cloud e spieghiamo perché conta.