Migrate VMware virtual machines to OpenStack: virt-v2v and OVF export
These are the two migration paths we industrialize most often. virt-v2v connects to vCenter, converts the guest, injects VirtIO drivers and writes Cinder volumes directly. The export path keeps every intermediate artefact under control: OVF export, qemu-img conversion, Glance import. Commands are illustrative: each engagement adapts them to your releases, storage backend and security constraints.
1. Qualify the VM before converting it
Most failed conversions are decided before the first command. For every VM, record the guest OS and version, firmware type (BIOS or UEFI), number and size of disks, snapshot chain, network interfaces with their MAC and fixed IPs, and any licence bound to hardware identifiers. This inventory feeds the eligibility matrix: direct migration, remediation first, rebuild on the target or retirement.
# Inventory with govc (read-only against vCenter)
export GOVC_URL='https://<VCENTER_HOST>' GOVC_USERNAME='<VCENTER_USER>' GOVC_INSECURE=1
govc vm.info -json <VM_NAME> | jq '.virtualMachines[0] | {guest: .config.guestFullName, firmware: .config.firmware, cpu: .config.hardware.numCPU, memMB: .config.hardware.memoryMB}'
govc device.info -vm <VM_NAME> disk-* ethernet-*
govc snapshot.tree -vm <VM_NAME> # must be empty (or consolidated) before export
2. Path A: direct conversion with virt-v2v
virt-v2v runs on a Linux conversion server that is itself an OpenStack instance, with network access to both vCenter and the OpenStack APIs. The -o openstack output creates one Cinder volume per disk (named VM_NAME-sda, VM_NAME-sdb, and so on), attaching them temporarily to the conversion server identified by -oo server-id.
2.1 Prerequisites on the conversion node
# Install virt-v2v and guestfs tools on the Linux conversion node (Debian/Ubuntu)
apt-get install virt-v2v libguestfs-tools -y
# Windows guests: virt-v2v needs the virtio-win drivers (ISO from the Fedora virtio-win project)
export VIRTIO_WIN=/opt/virtio-win.iso
# OpenStack credentials for the -o openstack output (tenant API endpoints are enough)
source /etc/kolla/admin-openrc.sh # or the tenant project's openrc
2.2 Convert straight from ESXi into Cinder volumes
# Power off the source VM first, then run virt-v2v against vCenter.
# Must run as root (Cinder volumes appear as /dev devices); sudo -E keeps the OS_* variables.
export LIBGUESTFS_BACKEND=direct
sudo -E virt-v2v -ic 'vpx://<VCENTER_USER>@<VCENTER_HOST>/<DATACENTER>/<ESXI_HOST>' \
-ip /root/vcenter-password <VM_NAME> \
-o openstack -oo server-id=<CONVERSION_SERVER_ID> \
-os <VOLUME_TYPE> -oo guest-id=<VM_NAME>
# -os sets the Cinder volume type; -oo guest-id tags every created volume (virt_v2v_guest_id).
# Keep TLS certificate verification enabled; reserve ?no_verify=1 for controlled diagnostics only.
# -of and -oa are not supported with -o openstack: volumes are always written raw into Cinder.
2.3 Boot the instance from the converted system volume
# UEFI guests: pin the firmware and machine types on the boot volume before first boot
openstack volume set --image-property hw_firmware_type=uefi --image-property hw_machine_type=q35 "<VM_NAME>-sda"
# Boot from the system volume, attach data volumes afterwards
openstack server create --volume "<VM_NAME>-sda" \
--flavor <FLAVOR_NAME> \
--network <TENANT_NET_ID> \
"<VM_NAME>_migrated"
openstack server add volume "<VM_NAME>_migrated" "<VM_NAME>-sdb"
3. Path B: OVF export, conversion and Glance import
The standard, fully controllable procedure: export the ESXi disks, convert them offline, then ingest them into Glance and Cinder. Ideal for air-gapped environments and scripted bulk migrations, at the cost of intermediate storage and a longer window per VM.
3.1 Export the VM from ESXi / vCenter
# Export the powered-off VM as an OVA package (password is prompted interactively)
ovftool vi://<VCENTER_USER>@<VCENTER_HOST>/<DATACENTER>/vm/<VM_NAME> /tmp/<VM_NAME>.ova
# Extract the VMDK file(s) from the OVA archive
mkdir -p /tmp/export && tar -xvf /tmp/<VM_NAME>.ova -C /tmp/export/
3.2 Convert VMDK to RAW
# RAW is optimal for Ceph RBD (native thin provisioning, no format translation on boot)
qemu-img convert -f vmdk -O raw -p /tmp/export/<VM_NAME>-disk1.vmdk /tmp/<VM_NAME>.raw
qemu-img info /tmp/<VM_NAME>.raw
# Optional: adapt the guest offline; local output is named <VM_NAME>-sda, -sdb, and so on
mkdir -p /tmp/converted
virt-v2v -i disk /tmp/<VM_NAME>.raw -o local -os /tmp/converted/ -of raw
3.3 Upload to Glance and boot from a Cinder volume
# Upload the raw image to Glance with VirtIO properties (private to the project)
openstack image create "<VM_NAME>_migrated" \
--file /tmp/converted/<VM_NAME>-sda \
--disk-format raw --container-format bare \
--property hw_disk_bus=virtio --property hw_vif_model=virtio
# add --property hw_firmware_type=uefi --property hw_machine_type=q35 for UEFI guests
# add --property os_type=windows for Windows guests (RTC and timer handling)
# Create a volume from the image and boot the Nova instance
openstack volume create --image "<VM_NAME>_migrated" --size <SIZE_GB> "<VM_NAME>_vol"
openstack server create --volume "<VM_NAME>_vol" --flavor <FLAVOR> --network <NET_ID> "<VM_NAME>"
4. Which path for which fleet
Prefer virt-v2v when
Windows guests need VirtIO driver injection, guests run standard Linux distributions, a direct network path exists between vCenter and the conversion node, and the team wants maximum automation per VM.
Prefer export and convert when
Environments are air-gapped or strictly segmented, guests are non-standard, every intermediate artefact must be kept and checked, or bulk migrations are scripted into a repeatable migration factory.
5. Pitfalls we neutralize before they occur
- ■Windows VirtIO drivers: without VirtIO storage drivers injected before first boot, Windows guests crash on startup. Inject and verify them during conversion, not after.
- ■IP and MAC preservation: application licences, firewall rules and hardcoded configurations depend on addresses. Create the Neutron port with a fixed IP and MAC (openstack port create --fixed-ip ip-address=… --mac-address …) when continuity requires it.
- ■VMware Tools removal: leftover VMware Tools degrade the migrated guest. virt-v2v removes them; on the export path, uninstall them before export and install qemu-guest-agent on the target.
- ■UEFI versus BIOS: a UEFI guest booted in BIOS mode simply fails. Inventory the firmware type per VM and pin hw_firmware_type on the Glance image or boot volume.
- ■Multi-terabyte volumes: large disks stretch export windows considerably. Stream conversions directly into Ceph RBD (qemu-img convert … rbd:pool/volume-…) and size cutover windows on measured throughput, not estimates.
- ■Snapshots and CBT chains: unconsolidated snapshot chains corrupt or bloat exports. Consolidate snapshots and pause backup integrations before any disk leaves vSphere.
6. Acceptance and rollback
The source VM stays powered off but intact on vSphere until acceptance is signed. Rollback is a documented, tested runbook: power the source back on, reconnect flows, log the deviation and feed it back into the eligibility matrix. Only then is the vSphere VM deleted and its storage reclaimed.
# Post-migration checks on the OpenStack side
openstack server show "<VM_NAME>" -c status -c addresses -c "OS-EXT-SRV-ATTR:hypervisor_hostname"
openstack console log show "<VM_NAME>" | tail -n 50 # kernel/boot messages, driver detection
openstack console url show "<VM_NAME>" # interactive check through the VNC/SPICE console
# Rollback (vSphere side): the source VM was never deleted
govc vm.power -on <VM_NAME>
Reverse direction: export an OpenStack VM to VMware →