Cloudbase.it provides tools for creating OpenStack-ready cloud images. They've created a Windows Server 2012R2 images, which is ready for use (download and instructions here). This image is already imported into our environment.
If you need an another Windows Version, you must build the image yourself, with good help from the automated cloudbase-scripts. The example script given in this article will only work on Hyper-V enabled physical host (Windows 10 or a Server variant). The following examples is a list of what we did to create a cloud ready Windows Server 2019 image.
UnattendTemplate.xml: Change InputLocale and UserLocale from en-US to nb-NO
We provide Windows Server images with the KMS activiation key injected. To make that work, we need to set the DNS Search Suffix. This will only run on servers, as we are not allowed to use KMS for Client SKUs
# Set DNS Search Suffix to NTNUs windows domain
# This is a requirement in order to do KMS activation in the images
# This should only run on Server SKUs and on non-eval versions!
if ((Get-ComputerInfo).OsProductType -eq 'Server') {
if( -Not ((Get-WindowsEdition -Online).Edition).Contains('Eval') ) {
Set-DnsClientGlobalSetting -SuffixSearchList @('win.ntnu.no')
}
} |
Openstack Neutron expects all instances to use EUI-64 for IPv6 auto configuration. EUI-64 is not the default in Windows, so we need to enable it (and disable the other magic stuff)
# Enable EUI-64 and disable all other trickery Write-Host "Enabling EUI-64" Set-NetIPv6Protocol -RandomizeIdentifiers Disabled -UseTemporaryAddresses Disabled |
Import-Module C:\dev\windows-imaging-tools-master\WinImageBuilder.psm1
Import-Module C:\dev\windows-imaging-tools-master\Config.psm1
Import-Module C:\dev\windows-imaging-tools-master\UnattendResources\ini.psm1
function Set-Config {
param($file, $section, $key, $value)
Set-IniFileValue -Path (Resolve-Path $file) -Section $section `
-Key $key `
-Value $value
}
$date = Get-Date -UFormat "%Y%m%d"
$virtualDiskPath = "C:\dev\images\w11_24h2_eval_uefi_$date.qcow2"
$virtIOISOPath = "C:\iso\virtio-win-0.1.266.iso"
$winISOPath = "C:\iso\w11_24h2_eval.iso"
$mountResult = Mount-DiskImage -ImagePath $winISOPath -StorageType ISO -PassThru
$imageDrive = ($mountResult | Get-Volume).DriveLetter
$wimFilePath = "${imageDrive}:\sources\install.wim"
$diskSize = 40GB
$ramSize = 4GB
$cpuCount = 2
# Check which SKU from the WimFile you want, and specify the corresponding index to $image
$images = Get-WimFileImagesInfo -WimFilePath $wimFilePath
#Dismount-DiskImage -InputObject $mountResult
$image = $images[0]
$configfile = '.\config.ini'
New-WindowsImageConfig -ConfigFilePath $configfile
if ( ! (Test-Path C:\dev\images) ) { New-Item C:\dev\images -Type Directory }
Set-Config -file $configfile -section "DEFAULT" -key "wim_file_path" -value $wimFilePath
Set-Config -file $configfile -section "DEFAULT" -key "image_name" -value $image.ImageName
Set-Config -file $configfile -section "DEFAULT" -key "image_path" -value $virtualDiskPath
Set-Config -file $configfile -section "DEFAULT" -key "virtual_disk_format" -value "QCOW2"
Set-Config -file $configfile -section "DEFAULT" -key "image_type" -value "KVM"
#Set-Config -file $configfile -section "DEFAULT" -key "disk_layout" -value "BIOS"
Set-Config -file $configfile -section "DEFAULT" -key "disk_layout" -value "UEFI"
Set-Config -file $configfile -section "DEFAULT" -key "custom_scripts_path" -value "C:\dev\custom"
Set-Config -file $configfile -section "DEFAULT" -key "wallpaper_solid_color" -value "0 0 0"
Set-Config -file $configfile -section "DEFAULT" -key "enable_ping_requests" -value "True"
Set-Config -file $configfile -section "DEFAULT" -key "enable_ipv6_eui64" -value "True"
Set-Config -file $configfile -section "DEFAULT" -key "enable_active_mode" -value "True"
# This is the KMS key config. 'default_kms_key' will grab the correct key automatically
#Set-Config -file $configfile -section "DEFAULT" -key "product_key" -value "default_kms_key"
#Set-Config -file $configfile -section "DEFAULT" -key "extra_packages" -value "C:\dev\custom\Windows6.1-KB2506143-x64.msu"
Set-Config -file $configfile -section "vm" -key "external_switch" -value "ext-net"
Set-Config -file $configfile -section "vm" -key "cpu_count" -value $cpuCount
Set-Config -file $configfile -section "vm" -key "ram_size" -value $ramSize
Set-Config -file $configfile -section "vm" -key "disk_size" -value $diskSize
Set-Config -file $configfile -section "drivers" -key "virtio_iso_path" -value $virtIOISOPath
Set-Config -file $configfile -section "updates" -key "install_updates" -value "True"
Set-Config -file $configfile -section "updates" -key "purge_updates" -value "True"
Set-Config -file $configfile -section "cloudbase_init" -key "beta_release" -value "False"
Set-Config -file $configfile -section "custom" -key "time_zone" -value "W. Europe Standard Time"
# Check if we are on a Hyper-V enabled host
if ( $(Get-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V).State -eq "Enabled" ) {
New-WindowsOnlineImage -ConfigFilePath $configfile
} else {
Write-Host "This script only works on Hyper-V enabled hosts"
}
Dismount-DiskImage -InputObject $mountResult
|
You now have a .qcow2 diskfile, which contains an updated and sysprepped Windows-installation with cloud-init installed
Convert the qcow2 disk to raw
qemu-img convert -f qcow2 -O raw disk.qcow2 disk.raw |
The raw image can now be imported to glance.
When you spawn a Windows instance, be sure to attach a keypair. Cloudbase-init will generate a random password for the user Admin, which can be retrieved with:
nova get-password <instance-id> <private-key-file> |
The password can also be retrieved in Horizon through the "Retrieve password" action on the instance.
NOTE: There is a known issue with Windows 10 - the hostname will not be set to wahtever you chose for instance name. This might be fixed in the future... (Link)
We are allowed to provide Windows Server images which will use KMS for automatic activation. The KMS keys are global, and here is a list of the SKUs we care about:
| SKU | KMS key |
|---|---|
| Windows Server 2012 R2 Standard | D2N9P-3P6X9-2R39C-7RTCD-MDVJX |
| Windows Server 2016 Standard | WC2BQ-8NRM3-FDDYY-2BFGV-KHKQY |
| Windows Server 2019 Standard | N69G4-B89J2-4G8F4-WWYCC-J464C |
| Windows Server 2022 Standard | VDYBN-27WPP-V4HQT-9VMD4-VMK7H |
| Windows Server 2025 Standard | TVRH6-WHNXV-R9WG3-9XRFY-MY832 |