Converting Windows Guests From VMWare ESX to KVM With Virtio Drivers

Tags: , , , , , , , , , , , , , , , , , , , , , , ,

The below steps were tested while pulling my hair out trying to migrate a Windows 2k3 guest from VMWare ESX to KVM managed by libvirt, hopefully this will save you from much windows related pain and suffering.

Prep the VM while it’s still running in VMware

Download MergeIDE.zip and run MergeIDE.bat. This is a really important step that will prepare the system to boot using an IDE driver when we bring it up in KVM. Skipping this step will likely result in blue screen errors and much frustration.

MergeIDE can be downloaded at
http://www.virtualbox.org/attachment/wiki/Migrate_Windows/MergeIDE.zip

Also, ensure that you know the local administrator password. This seems rather obvious but networking may not come up, so best to be prepared.

Now you’re ready to shut down and copy the vm.

Shutdown the VM and copy it’s vmdk

Gracefully shut down the VM. Once it’s down, ssh into your ESX server and navigate to the appropriate VMFS volume containing your VM.

[root@esx1 example-vm]# pwd
/vmfs/volumes/VMFS1/example-vm
[root@esx1 example-vm]# ls
example-vm-flat.vmdk    example-vm.vmdk  example-vm.vmx   
example-vm.nvram      example-vm.vmsd  example-vm.vmxf 
vmware-0.log  vmware-2.log  vmware-7.log  vmware.log
vmware-1.log  vmware-6.log  vmware-8.log

SCP the “flat” .vmdk file (or files if your machine has multiple virtual disks) from your ESX host to your KVM host.

[root@esx1 example-vm]# scp -pr example-vm-flat.vmdk kvm1:/etc/libvirt/images/
root@kvm1 password: 
example-vm-flat.vmdk           100%   20GB  14.6MB/s   23:20

Prepare the libvirt/KVM instance

Create an XML file to define the attributes of the virtual machine. You’ll likely want to copy things like the memory size, number of CPUs and MAC address from the vmware vmx file, in our case this is /vmfs/volumes/VMFS1/example-vm/example-vm.vmx.

In order to set up virtio we first set our primry disk as bus type ide and create a secondary disk with a bus type of virtio. This will allow us to boot from the existing OS without special drivers. From there windows will detect the secondary virtio SCSI adapter and prompt for driver installation. We’ll also attach a virtio guest drivers floppy while we’re at it.

Virtio guest driver iso and floppy images can be downloaded at
http://alt.fedoraproject.org/pub/alt/virtio-win/latest/images/bin/

<domain type='kvm'>
  <name>example-vm</name>
  <uuid>5de881b6-7738-4c30-8f14-da203c1b09f5</uuid>
  <memory>2097152</memory>
  <currentMemory>2097152</currentMemory>
  <vcpu>1</vcpu>
  <os>
    <type arch='x86_64' machine='rhel5.4.0'>hvm</type>
    <boot dev='hd'/>
  </os>
  <features>
    <acpi/>
    <apic/>
    <pae/>
  </features>
  <clock offset='utc'/>
  <on_poweroff>destroy</on_poweroff>
  <on_reboot>restart</on_reboot>
  <on_crash>restart</on_crash>
  <devices>
    <emulator>/usr/libexec/qemu-kvm</emulator>
    <disk type='file' device='disk'>
      <driver name='qemu' cache='none'/>
      <source file='/etc/libvirt/images/example-vm/example-vm-flat.vmdk'/>
      <target dev='hda' bus='ide'/>
      <driver name='qemu' cache='none'/>
      <source file='/etc/libvirt/images/example-vm/virtio-temp.raw'/>
      <target dev='vdb' bus='virtio'/>
    </disk>
    <disk type='file' device='floppy'>
      <source file='/root/virtio-win-1.1.16.vfd'/>
      <target dev='fda' bus='fdc'/>
    </disk>
      <readonly/>
    </disk>
    <interface type='bridge'>
      <mac address='00:50:56:b9:4e:50'/>
      <source bridge='virbr0'/>
      <model type='virtio'/>
    </interface>
    <serial type='pty'>
      <target port='0'/>
    </serial>
    <console type='pty'>
      <target port='0'/>
    </console>
    <input type='mouse' bus='ps2'/>
    <graphics type='vnc' port='-1' autoport='yes' keymap='en-us'/>
  </devices>
</domain>

Note: if you need to generate a new uuid simply run uuidgen

Now you’re ready to “Define” the new virtual machine in libvirt.

[root@kvm1 ~]# virsh define /etc/libvirt/qemu/example-vm.xml 
Domain example-vm defined from /etc/libvirt/qemu/example-vm.xml

Boot the KVM guest

Using virt-manager, start the virtual machine. It should boot up and allow you to log in as a local administrator or with cached credentials. If you are seeing a bsod (blue screen) with error 0x000007b boot errors, verify that the MergeIDE step was successful. This resolved my 0x7b errors.

Install the windows virtio guest drivers

Upon logging in, windows should detect the new virtio SCSI and network hardware and prompt you for drivers. You’ll want to point it at the floppy drive we attached to the guest.

A very detailed description of what to do is available at
http://www.linux-kvm.org/page/WindowsGuestDrivers/viostor/installation#Non-System_disk_installation_procedure.

Change the primary disk from ide to virtio

Finally, once the virtio drivers have been successfully installed you’re ready to change your boot disk to a bus type of virtio and can remove the temporary second drive. This can be done by executing virsh edit example-vm while the host is running and changing the disk dev= and bus= as follows:

    <disk type='file' device='disk'>
      <driver name='qemu' cache='none'/>
      <source file='/etc/libvirt/images/example-vm/example-vm-flat.vmdk'/>
      <target dev='vda' bus='virtio'/>
    </disk>

You can also remove the driver floppy at this time.

Perform a full reboot of the guest

To make the above change take effect simply shut the machine down completely and then re-start it with virt-manager. Don’t simply issue a reboot from within the VM, we need to apply the changes to the libvirt domain definition.

You’re done!

Your VM should now be up and running, free from vmware and benefiting from the performance gains of virtio.