← Back to Blog

VMware to OpenStack Migration, Step by Step: virt-v2v, qemu-img and the Drivers That Break

Published · by RS Computers

VMware OpenStack Migration

A VMware to OpenStack migration comes down to four moves for each VM: export the powered-off machine from vCenter or ESXi, convert its VMDK disk to RAW or QCOW2 with qemu-img or virt-v2v, upload it to Glance or Cinder with the right image properties, and boot it on a Neutron network that matches its old port group. The disk conversion is the quick, predictable part. The guest is what breaks: Windows without VirtIO drivers stops with INACCESSIBLE_BOOT_DEVICE, and Linux comes up with its network card renamed from ens192 to ens3. This runbook walks through seven phases, each with a checklist, and we ran and timed every conversion command in our lab on Debian 13.

Key facts, checked on 11 October 2026:

This article is the how. For the why (Broadcom's licensing, and which OpenStack service replaces which vSphere feature), read why companies migrate from VMware to OpenStack. If your target is a few hosted servers rather than a private cloud, the VMware to KVM VPS migration guide is the shorter road.

Phase 0: inventory every VM

Most failed migrations were decided here, by a VM nobody knew was special. Export the VM list from vCenter and fill in one row per VM:

Sort the list into waves: stateless Linux first, ordinary Windows next, databases and clusters last. Consolidate snapshots before any export.

Phase 1: map vSphere objects to OpenStack objects

In vSphereIn OpenStackWhat to decide
Port group on a VLANNeutron provider network on the same VLAN IDCreate each port with its old fixed IP so the VM keeps its address.
NSX rulesSecurity groupsAdd virtual IPs as allowed address pairs, or Neutron drops their traffic.
Datastore tiersCinder volume types, usually on Ceph poolsOne volume type per tier. See Ceph RBD performance.
VM sizesFlavorsOne flavor per common size, created before wave one.
DRS affinity rulesServer groups (affinity or anti-affinity)A VM joins a server group only when it is created.
vAppHeat stack or Ansible playbookStart order moves into code.
Resource pools, foldersProjects with quotasOne project per team or application.
vSphere HAMasakari or Nova evacuatePull a host's power before you trust it.

For the network layer, our overview of SDN solutions in OpenStack compares Open vSwitch and OVN. Still choosing the platform? See KVM vs OpenStack vs Proxmox and OpenStack advantages and disadvantages in 2026.

Phase 2: prepare the guest while it still runs on VMware

On KVM the disk controller and the NIC become VirtIO devices, a family of virtual hardware built for virtual machines. The guest needs their drivers before it moves, because afterwards it cannot reach its own disk to load anything.

Linux guests

Linux loads its first drivers from the initramfs, a small file unpacked at boot. If the VirtIO disk driver is missing from it, the boot stops before the root file system is found.

# as root, on the Linux VM (Debian or Ubuntu)
lsinitramfs /boot/initrd.img-$(uname -r) | grep -E 'virtio_(blk|scsi|net)'
[ -d /sys/firmware/efi ] && echo UEFI || echo BIOS

On our Debian 13 VM the first command printed three lines ending in virtio_blk.ko.xz, virtio_net.ko.xz and virtio_scsi.ko.xz, and the second printed UEFI. Red Hat family systems often lack these modules; our KVM VPS migration guide has the dracut command that adds them. Also open /etc/fstab: UUID= and LABEL= lines survive the move, while /dev/sda1 may not, because a VirtIO disk shows up as /dev/vda. Write down the NIC name too. If it is ens192 or ens160, it will change. Then swap the guest tools:

# as root, on the Linux VM (Debian or Ubuntu)
apt purge open-vm-tools
apt install qemu-guest-agent

The install ends with qemu-guest-agent.service is a disabled or a static unit, not starting it. That is normal; the agent starts once the VM runs on KVM.

Windows guests and INACCESSIBLE_BOOT_DEVICE

Windows has no VirtIO drivers built in. Moved behind a VirtIO controller, it stops with stop code 0x7B, INACCESSIBLE_BOOT_DEVICE, meaning it lost access to its system partition during startup. We did not convert Windows in this lab, so these steps come from the official documentation:

  1. Mount the stable virtio-win ISO linked from the virtio-win project inside the running VM and run virtio-win-guest-tools.exe (disk, network and balloon drivers plus the QEMU guest agent).
  2. Uninstall VMware Tools while still on vSphere. The virt-v2v manual says VMware's uninstaller usually fails with error 1603 after conversion.
  3. Turn off Fast Startup and shut down from the Start menu; virt-v2v refuses hibernated guests.
  4. Save ipconfig /all, and suspend BitLocker or keep the recovery key.

Rescue route if a Windows VM lands without the driver: boot it once from an image with hw_disk_bus=ide, which Glance lists as valid for KVM, install virtio-win, then go back to virtio. IDE is slow, so use it only for the repair.

Phase 3: export from vCenter or ESXi

Shut the VM down cleanly, then export it with Actions, Template, Export OVF Template in the vSphere Client, or with OVF Tool. Broadcom's knowledge base article 340425 gives the pattern ovftool "vi://user@vcenter/Datacenter/vm/Folder/VM_Name" "VM_Name.ova". virt-v2v can also read straight from vCenter or from ESXi over SSH, shown in our VMware to OpenStack overview. We have no vSphere in our lab, so these export steps are from Broadcom's documentation, untested by us.

What you get is a VMDK in one of several layouts, which qemu-img shows as "create type". streamOptimized is the compressed kind inside OVA files. monolithicSparse is one growing file, as in VMware Workstation. Disks copied off an ESXi datastore come as a small descriptor plus a large -flat.vmdk: point the tools at the descriptor and keep both in one folder. The same goes for split -s001.vmdk pieces.

Phase 4: convert the disk (what our lab measured)

Our conversion host was a Debian 13 KVM virtual machine with 2 vCPUs, 3 GiB of RAM and NVMe storage:

# as root, on the Debian 13 conversion machine
apt update
apt install qemu-utils virt-v2v guestfs-tools qemu-system-x86
useradd -m -s /bin/bash -G kvm migrator

The install took 2 minutes 32 seconds. The kvm group lets the user run hardware-accelerated test VMs.

Rehearse on a disk you can throw away

We built a Debian 13 "VMware guest" with virt-builder: 6 GiB disk, open-vm-tools installed, and a static network setup on ens192, the usual vmxnet3 name on vSphere. Then we turned it into the two VMDK layouts you meet most:

# as the migrator user, in ~/lab
export LIBGUESTFS_BACKEND=direct
printf 'auto lo\niface lo inet loopback\n\nauto ens192\niface ens192 inet static\n    address 192.0.2.10/24\n    gateway 192.0.2.1\n' > interfaces.vmware
virt-builder debian-13 -o web01.raw --format raw --size 6G --hostname web01 \
  --root-password random --install open-vm-tools \
  --upload interfaces.vmware:/etc/network/interfaces \
  --run-command 'sed -i "s/^GRUB_CMDLINE_LINUX=.*/GRUB_CMDLINE_LINUX=\"console=ttyS0,115200\"/" /etc/default/grub && update-grub'
qemu-img convert -f raw -O vmdk -o subformat=streamOptimized,adapter_type=lsilogic web01.raw web01-stream.vmdk
qemu-img convert -f raw -O vmdk -o subformat=monolithicSparse,adapter_type=lsilogic web01.raw web01-sparse.vmdk
qemu-img info web01-stream.vmdk

qemu-img info showed virtual size: 6 GiB, disk size: 720 MiB and create type: streamOptimized. The virtual size is the disk the VM sees; your flavor or volume must be at least that big.

VMDK to QCOW2 or RAW with qemu-img

# as the migrator user, in ~/lab
qemu-img convert -p -f vmdk -O qcow2 web01-stream.vmdk back-stream.qcow2
qemu-img convert -p -f vmdk -O raw web01-sparse.vmdk back-sparse.raw
qemu-img check back-stream.qcow2
qemu-img compare web01.raw back-stream.qcow2

-f names the input format and -O the output. The check printed No errors were found on the image. and the compare printed Images are identical., so the round trip lost nothing.

Step (6 GiB disk, 1.57 GiB used)TimeResult size
RAW to streamOptimized VMDK (like an OVA export)66.1 s721 MiB
RAW to monolithicSparse VMDK11.2 s1,609 MiB
streamOptimized VMDK to QCOW212.6 s1,609 MiB
monolithicSparse VMDK to RAW7.6 s6 GiB apparent, 1.5 GiB on disk
VMDK to compressed QCOW2 (-c)62.3 s739 MiB
virt-v2v, VMDK to QCOW2 with guest conversion106.5 s1,300 MiB

Writing streamOptimized is slow because it compresses; reading it is fast. With 4 GiB of incompressible data, qemu-img read a streamOptimized VMDK into QCOW2 at about 234 MiB/s and a monolithicSparse one at about 182 MiB/s, but wrote streamOptimized at only 32 MiB/s. So an OVA costs time on the vSphere side, not on the conversion host.

RAW or QCOW2? If Glance and Cinder sit on Ceph, upload RAW: the Ceph documentation for OpenStack advises against QCOW2, because Ceph makes instant copy-on-write clones only from RAW. QCOW2 suits file-based storage and transfers.

The same job with virt-v2v

qemu-img changes only the container. virt-v2v also edits the guest: it checks VirtIO support, removes VMware Tools on Linux and writes a libvirt description of the VM.

# as the migrator user, in ~/lab
export LIBGUESTFS_BACKEND=direct
mkdir -p out
virt-v2v -i disk web01-stream.vmdk -o local -os out -of qcow2
virt-inspector -a out/web01-stream-sda | grep -E 'open-vm-tools|qemu-guest-agent'
virt-cat -a out/web01-stream-sda /etc/network/interfaces

virt-v2v printed Converting 13.1 (debian13) to run on KVM and This guest has virtio drivers installed., warned that it could not determine a way to update the configuration of Grub2 (harmless here), and ended with Finishing off. The output, out/web01-stream-sda, is a QCOW2 file without an extension, 309 MiB smaller than the qemu-img copy because virt-v2v skips unused blocks. virt-inspector found open-vm-tools gone. But /etc/network/interfaces still said ens192.

virt-v2v can also write straight into Cinder with -o openstack. Its manual says this must run inside an OpenStack instance, usually as root, with -oo server-id= naming that instance; each guest disk becomes one volume. We could not test it without a real cloud.

Phase 5: test-boot, fix, upload

A two-minute boot on the conversion host, with the same VirtIO hardware OpenStack uses, catches most problems:

# as the migrator user, in ~/lab
qemu-system-x86_64 -enable-kvm -cpu host -m 1024 -smp 2 -nographic \
  -drive file=out/web01-stream-sda,if=virtio,format=qcow2 \
  -nic user,model=virtio-net-pci

The guest reached web01 login: about 14 seconds after the kernel started. On the way the console showed virtio_blk virtio1: [vda] 12582912 512-byte logical blocks (disk driver fine), virtio_net virtio0 ens3: renamed from eth0 (new NIC name) and [FAILED] Failed to start networking.service (config still on ens192). The plain qemu-img copy booted the same way. Ctrl+A, then X, stops QEMU. Fix the network offline:

# as the migrator user, in ~/lab
virt-customize -a out/web01-stream-sda \
  --run-command "sed -i -e s/ens192/ens3/g -e 's/inet static/inet dhcp/' -e /address/d -e /gateway/d /etc/network/interfaces" \
  --run-command "ssh-keygen -A"

That took 7.5 seconds, and on the next boot networking and SSH both started. DHCP suits OpenStack, where Neutron hands each port its fixed IP. Ubuntu keeps this in /etc/netplan/ and Red Hat systems in NetworkManager files. Confirm the final name on the first cloud boot from the instance console.

Upload to Glance with the right properties

We could not run this step without a cloud account, so it is described from the OpenStack client documentation. openstack image create takes --disk-format (raw, qcow2, vmdk and others), --container-format bare, --file, --min-disk, --min-ram and a repeatable --property key=value. The properties choose the virtual hardware, per Glance's useful image properties:

PropertyValue after VMwareWhy
hw_disk_busvirtioThe disk controller; the main cause of boot failures when wrong.
hw_vif_modelvirtio (e1000 as a fallback)The NIC model.
hw_firmware_typebios or uefi, as on vSphereA UEFI guest booted with BIOS finds no boot device.
hw_qemu_guest_agentyesConnects the agent installed in Phase 2.
os_typewindows, for Windows guestsAdds Hyper-V enlightenments, which speed Windows up on KVM.

Declare the real format: Glance's 2025.1 design spec rejects uploads whose content does not match disk_format, and a VMDK labelled qcow2 is the first case it names. For large disks, boot from a Cinder volume created from the image, so the data lives on your chosen storage tier.

Phase 6: cutover and rollback

  1. A week before: lower DNS TTLs, freeze changes and agree a go or no-go time with each owner.
  2. Create ports with the old fixed IPs, security groups and server groups in advance.
  3. At the window: stop the application, shut down from inside the guest, export and convert.
  4. Test-boot, fix NIC names, upload, boot the instance on its prepared port.
  5. The owner tests, then switch DNS or the load balancer and watch the logs for an hour.

For rollback, never change the original. Leave the source VM powered off but registered in vCenter, with its NIC disconnected so nobody starts it with a duplicate IP. Rolling back means stopping the OpenStack instance, reconnecting that NIC and powering on. Data written on the new side after cutover is lost in a rollback unless you copy it back.

Downtime estimate by disk size

For a cold migration, the VM is off during export, conversion, upload and first-boot checks. This estimate uses a conversion rate of about 200 MB/s (our lab measured 182 to 241 MiB/s), an assumed 110 MB/s for export and upload over 1 Gb/s, and 15 minutes for boot and tests. Only used data counts.

Used dataExportConversionUploadTotal cold outage
20 GB3 min2 min3 minabout 25 min
100 GB15 min8 min15 minabout 1 hour
500 GB76 min42 min76 minabout 3.5 hours
1 TB2.5 hours1.4 hours2.5 hoursabout 7 hours
2 TB5 hours2.8 hours5 hoursabout 13 hours

virt-v2v with -o openstack removes the separate upload, and 10 Gb/s shrinks the transfer columns. Beyond roughly 500 GB, consider a warm-migration tool built on VMware's Changed Block Tracking: it copies the disk while the VM runs and stops it only for a final sync. The openstack.org page lists OS-Migrate, VEXXHOST MigrateKit and Coriolis among its tools.

Where RS Computers fits

RS Computers is not a VMware or OpenStack migration consultancy. We run KVM virtual servers, VPS and VDS, in Amsterdam (Netherlands), Dublin (Ireland) and Prishtina (Kosovo), and they help in two places. Phases 4 and 5 need a Linux machine with KVM and fast disks: a VDS Small (4 vCPU, 8 GB RAM, 240 GB NVMe) or VDS Medium (8 vCPU, 16 GB RAM, 480 GB NVMe) with a 10 Gb/s port is a good rehearsal and conversion box; our Linux and DevOps lab guide covers setting one up. And some VMs do not need a private cloud at all: a converted .qcow2 or .raw disk can run on a KVM VPS or VDS, and if you want us to do the setup work, we quote it per job via Telegram or email. Windows Server runs on VPS Mini and every VDS (see Windows VPS). Planning containers on the new cloud too? Read OKD on OpenStack.

Frequently asked questions

How do I convert a VMware VM to OpenStack?

Shut it down, export it as OVF or OVA, convert the VMDK with qemu-img convert -f vmdk -O raw (or -O qcow2) or with virt-v2v, upload it with openstack image create and properties such as hw_disk_bus=virtio, and boot it on a Neutron network matching the old port group.

Can OpenStack replace VMware?

For compute, networking and block storage, yes: Nova, Neutron and Cinder with Ceph cover what vSphere, NSX and vSAN do for most workloads. It does not replace a single vendor answering for the whole stack, so you need a platform team or a supported distribution.

Should I use virt-v2v or qemu-img?

virt-v2v when the guest needs changes, such as Windows driver injection or removing VMware Tools; it took 106 seconds on our 6 GiB test disk. qemu-img when the guest is already prepared; it took 12.6 seconds on the same disk. Neither rewrites the network configuration.

Why does Windows show INACCESSIBLE_BOOT_DEVICE after the move?

Windows has no built-in VirtIO storage driver, so it cannot read its own system disk. Install virtio-win while the VM still runs on VMware, or boot once with hw_disk_bus=ide, install the drivers and switch back to virtio.

Why does my Linux VM have no network after migrating?

The NIC gets a new name on KVM, such as ens3 instead of ens192, while the configuration still names the old one. Edit the interfaces, netplan or NetworkManager file to the new name, ideally with DHCP so Neutron assigns the fixed IP.

RAW or QCOW2 for OpenStack images?

RAW when Glance and Cinder use Ceph, which clones instantly only from RAW. QCOW2 for file-based storage and transfers; our compressed QCOW2 was 739 MiB for a disk with 1.57 GiB of data.

Before wave one

Run the whole chain on one boring Linux VM this week: inventory row, mapping, guest prep, export, conversion, test boot, upload, cutover and a deliberate rollback. Your own timings beat any estimate, ours included. If you need a KVM box with NVMe to rehearse on, or a home for the VMs that do not belong in the new cloud, see the VPS and VDS plans (availability by city is listed there) and message us on Telegram with what you are moving.

← All articles

Chat on Telegram