Technical Documentation

Creating a Windows Server 2012 QCOW2 image (OpenStack/KVM)

By 14/08/2014 June 4th, 2019 2 Comments

Things are busy here in Aptiraville. One thing we have been working on recently is upgrading our business intelligence platform, ADAPT. We originally ran this platform for our customer, Mercurial, on our VMware backed OpenStack region but as part of the upgrade we wanted to increase its capability to run our own KVM backed region as well.

So I tried to convert the existing VMDK to a QCOW2 to file with:

qemu-img convert -f vmdk ws2012.vmdk -O qcow2 ws2012.qcow2

and a bunch of variations of that. Unfortunately, no matter what I did, WS2012 just wouldn’t work correctly! After wasting a very frustrating day, I decided to rebuild an identical image from scratch in QCOW2 format to bypass the issue completely. To my further frustration, the available documentation on the internet for doing so is actually quite sparse and in some cases nonexistent. I thought it would be useful to write up exactly what I did this time as a blogpost, so that others can hopefully use it as a resource and avoid the pain points that I had to go through (since Windows doesn’t use text based configuration files, making changes means booting the image, making the changes and reuploading, rather than simply mounting and modifying the image).

First thing you will need is a computer capable of running KVM, with VT extensions enabled in the BIOS. My advice is to use a CentOS 6 machine, as I found that images I created on newer distributions like Ubuntu 14.04 or CentOS 7 would not boot on RHEL/CentOS 6 machines due to changes in the version of QCOW2 used. Creating the image on CentOS 6 means that the image you create will be bootable everywhere.

Along with this, you will need to have a Windows Server 2012 ISO accessible on the computer and product key (Aptira is a Microsoft SPLA partner), and and the Fedora signed VirtIO drivers. Make sure you install virt-installer and virt-manager:

yum -y install virt-install virt-manager

Alternatively, if you don’t want to install the GUI virt-manager on to the computer, you can install that locally and connect to the computer over SSH with virt-manager.

Make sure you have enabled IP forwarding in sysctl so that the VM will be able to access the networks when it comes online (if you want to copy scripts or other files onto it for example):

echo 1 > /proc/sys/net/ipv4/ip_forward

Create a preallocated QCOW2 image in /tmp (I tried making a thin provisioned one and the Windows installer thought the disk size was zero) and set permissions so libvirt can access it:

cd /tmp
qemu-img create -f qcow2 -o preallocation=full ws2012.qcow2 15g
chmod o+wx ws2012.qcow2

The 15GB number chosen above as the disk size is arbitrary, the actual install only takes up just under 7GB so if you want to keep the image as small as possible then something close to that would be optimal.

Run virt-install to boot the VM with the WS2012 installer ISO and VirtIO driver ISO attached attached, the disk set as a VirtIO disk and NIC attached to the default created virbr0. Unfortunately the most recent “os-variant” available for MS Windows on the CentOS 6 version of virt-install is “win7” so that is what I chose here for better or worse:

virt-install --connect qemu:///system --arch=x86_64 -n ws2012 -r 2048 --vcpus=2 --disk path=/tmp/ws2012.qcow2,device=disk,bus=virtio,size=15 -c /mnt/Source/en_windows_server_2012_x64_dvd_915478.iso --vnc --noautoconsole --os-type windows --os-variant win7 --network=bridge:virbr0 --disk path=/mnt/Source/en_windows_server_2012_x64_dvd_915478.iso,device=cdrom,perms=ro -c /mnt/Source/virtio-win-0.1-81.iso

Once the virt-install command has started, you can view the GUI by either firing up virt-manager locally, remotely (and connect to the computer running virt-install via SSH) or simply connect directly to the VNC port running at (assuming no other KVM virtual machines are running on the same host).

Complete the Windows Server 2012 installation as you normally would. We prefer the headless mode. During the installation Windows will complain that it can’t find a disk to install to, and present a dialog to load drivers. The drivers should be in:


and you are looking to install the VirtIO SCSI device driver (we will install the remaining VirtIO drivers after the operating system installation is complete and the virtual machine is running).
Once the installation is completed, the machine will restart and you can set an administrator password and login. The first step after successful installation is to run a command prompt (if using headless mode one will be presented as soon as you login) and use pnputil to insert the remaining VirtIO drivers:

pnputil -i -a D:\WIN8\AMD64\*.INF

We also want to enable .NET 2.0 and .NET 3.0/3.5 frameworks (E:\SOURCES\SXS is a directory on the WS2012 installer ISO):

DISM /Online /Enable-Feature /FeatureName:NetFx3 /All /LimitAccess /Source:E:\SOURCES\SXS

At this point, we want to copy over the installer for the latest .NET 4.5, any patches, scripts, etc as well as Cloudbase-Init (we recommend the automated Jenkins gated build) so we will create a directory for these files to go, map a CIFS network share, copy the files and then delete the share when we have completed the copy:

net use x: \\APTIRAFILESERVER01\
mkdir c:\source
copy x:\OpenStack\ADAPT\setup\* c:\source\
net use x: /DELETE

and then install Cloudbase-Init. If you are not familiar with this tool, it’s a port of the popular Ubuntu Linux tool that configures cloud virtual machines when they boot up based on a variety of configuration sources (we use ConfigDrive but also supported is the EC2 style metadata server, MaaS and others):


During the installation process you should set the user that Cloudbase-Init will manage from the default “Admin” to “Administrator”, unless you have (or plan to) create a special user for cloud-init purposes.

On the last dialog of the Cloudbase-Init installation you should select the option to run Sysprep and “generify” the virtual machine image. Don’t select the option to shutdown the virtual machine, as we still have one thing left to do.

After the Sysprep has finished running, to ensure that any scripts the user runs on boot through the OpenStack nova –user-data flag (referred to as “Post-Creation” in the OpenStack dashboard) we will need to set the PowerShell execution policy to be unrestricted:

Set-ExecutionPolicy Unrestricted

During testing we noticed that unfortunately line-breaks don’t translate correctly when using the “Post-Creation” textbox in the “Launch Instance” dialog in OpenStack dashboard and ConfigDrive (works fine with metadata servers) so that a Post-Creation entry of:

net user Administrator test123!

will appear in the user_data file as

#ps1_sysnativenet user Administrator test123!

so we recommend booting instances from the commandline python-novaclient with the –user-data=userdata.txt flag set when running “nova boot”, where userdata.txt is a file written with an editor like Vi that supports writing files in DOS format (:set ff=dos).

Once this is completed you can shut down the virtual machine immediately with:

shutdown -s -t 0

Now your image is ready to upload to the closest glance server for a test run (exciting!):

glance image-create --name WS2012 --disk-format=raw --container-format=bare --is-public --progress --file /tmp/ws2012.qcow2

Now you can enjoy Windows Server 2012 as a first class instance citizen on your KVM based OpenStack cloud like Aptira does! If you need more information on how you can do this yourself, check out our Training courses. Alternatively, we can do the hard work for you with our range of OpenStack services. Get in touch with our Solutionauts today for more information.

How can we make OpenStack work for you?
Find out what else we can do with OpenStack.

Find Out Here

Join the discussion 2 Comments

  • Tyler says:

    I’m working through your walk through and I am stuck at

    “virt-install –connect qemu:///system –arch=x86_64 -n ws2012 -r 2048 –vcpus=2 –disk path=/tmp/ws2012.qcow2,device=disk,bus=virtio,size=15 -c /mnt/Source/en_windows_server_2012_x64_dvd_915478.iso –vnc –noautoconsole –os-type windows –os-variant win7 –network=bridge:virbr0 –disk path=/mnt/Source/en_windows_server_2012_x64_dvd_915478.iso,device=cdrom,perms=ro -c /mnt/Source/virtio-win-0.1-81.iso”

    I get: ERROR Unknown argument ‘-connect’

    I cannot find any online support for this and I’ve been googling for hours now, I’m wondering if you had an idea how I can get past this step?

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.