First get the virtual disk (vhdx) from the Hyper-V platform.
Use a Linux machine with libvirt installed.
Do not forget to install the UEFI firmware:
sudo apt install ovmf
We need to convert the disk to the native format used by OpenStack:
qemu-img check -r all windows-disk.vhdx
qemu-img convert -O qcow2 windows-disk.vhdx windows-disk.qcow2
OpenStack (and KVM) use para-virtualized (virtio) drivers for the disk and the network. Although most modern Linux distributions have these drivers pre-loaded, Windows does not.
The best way to inject the drivers will be to do the following:
Get the virtio drivers for Windows:
curl -LO https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/stable-virtio/virtio-win.iso
Create a dummy disk that will make Windows detect the virtio disk driver:
qemu-img create -f qcow2 dummy.qcow2 5G
Create a temporary Virtual Machine:
virt-install --connect qemu:///system \
--ram 2048 \
--vcpus 2 --cpu host \
--network network=default,model=virtio \
--disk path=windows-disk.qcow2,device=disk,format=qcow2,bus=ide \
--disk path=dummy.qcow2,format=qcow2,device=disk,bus=virtio \
--disk path=./iso/virtio-win.iso,device=cdrom,perms=ro \
--graphics vnc,listen=0.0.0.0,password=1234 --noautoconsole \
--boot uefi \
--os-type windows --os-variant win2k12 \
--import \
--name myvm
Note: if the virtual disk is not an UEFI image, the --boot uefi
should not be used.
Once the Virtual Machine has booted, log in and install the drivers:
d:
cd \balloon\2k12R2\amd64
pnputil -i -a *.inf
cd \NetKVM\2k12R2\amd64
pnputil -i -a *.inf
cd \viostor\2k12R2\amd64
pnputil -i -a *.inf
Then, stop the virtual machine from inside (Powershell: Stop-Computer
).
And undefine it in KVM:
virsh undefine --nvram myvm
Finally, start the Virtual Machine again with the virtio bus:
virt-install --connect qemu:///system \
--ram 2048 \
--vcpus 2 --cpu host \
--network network=default,model=virtio \
--disk path=windows-disk.qcow2,device=disk,format=qcow2,bus=virtio \
--graphics vnc,listen=0.0.0.0,password=1234 --noautoconsole \
--boot uefi \
--os-type windows --os-variant win2k12 \
--import \
--name myvm
Note: if the virtual disk is not an UEFI image, the --boot uefi
should not be used.
Check the Virtual Machine to see if it is working fine.
First Import the virtual disk into an Openstack Image:
openstack image create \
--container-format bare \
--disk-format qcow2 \
--file windows-disk.qcow2 \
myvm-disk
And, create a volume from that image:
openstack volume create \
--image myvm-disk \
--size 60G \
myvm-disk
Check the progress with the Horizon web server or with: openstack volume list
. Once the volume is ready, you can start the instance:
openstack server create
--volume myvm-disk \
--flavor w1.small \
--security-group xxx \
--property hw_firmware_type=uefi \
myvm
Notes:
- if the virtual disk is not an UEFI image, do not add the propery
hw_firmware_type=uefi
. - Don't forget to choose the appropriate security group!
Unfortunately, nova reads the UEFI settings only from the image of the instance. And, in our case, there is no base image as the instance is directly attached to a volume.
There might be ways to read the image from the volume, but I have not found it in nova's source code.
The best was to patch the source code to read the firmware type from the instance metadata.
Here is the patch to apply in /usr/lib/python2.7/dist-packages/nova/virt/libvirt
:
--- driver.py 2020-10-08 19:45:10.847239335 +0900
+++ driver.py.new 2020-10-08 19:45:18.935288598 +0900
@@ -4895,6 +4895,8 @@
guest.sysinfo = self._get_guest_config_sysinfo(instance)
guest.os_smbios = vconfig.LibvirtConfigGuestSMBIOS()
hw_firmware_type = image_meta.properties.get('hw_firmware_type')
+ if not hw_firmware_type:
+ hw_firmware_type = instance.get('metadata').get('hw_firmware_type')
if caps.host.cpu.arch == fields.Architecture.AARCH64:
if not hw_firmware_type:
hw_firmware_type = fields.FirmwareType.UEFI
You apply it like this:
cd /usr/lib/python2.7/dist-packages/nova/virt/libvirt
sudo patch driver.py < driver.py.patch
sudo python -m compileall driver.py
sudo systemctl restart nova-compute.service
I also used this method to insert drivers
Downloaded and Mounted https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/stable-virtio/virtio-win.iso
Installed virtio-win-x64.msi and virtio-win-guest-tools.exe before exporting VHD off my hyperv
unsure if this will work for a core install but worked for my windows 10 veeam server