We get regularly a lot of requests about how to generate Windows OpenStack images, especially for KVM, where the proper VirtIO drivers need to be installed.
This article provides all the step required to build one, as we did for the official OpenStack Windows Server 2012 R2 Evaluation images
All the scripts are publicly available on Github.
For people familiar with Linux unattended deployment solutions like kickstart or preseed files, Windows has a roughly similar model based on XML files which can be automatically generated with a freely available tool currently called Windows Assessment and Deployment Kit (ADK in short). The ADK is not necessary if you’re fine with tweaking XML files manually as we usually do.
Kickstart and Preseed files in Linux provide a “post” script where you can do some more advanced provisioning by running your own scripts. That’s also what we do here. The difference is that we split the work in 3 specific areas:
- SynchronousCommands during the Specialize step. This is the earliest moment in which we can run some custom actions. Scripts will be executed with the SYSTEM credentials and won’t be able to access some OS features that are not yet available, for example WMI. This is the best place where to place your script, especially if you expect a reboot to load your features.
- SynchronousCommands during the first logon. These commands get executed when the setup is basically done with the Administrator’s credentials (or whatever is specified in the XML file), just before the user can log in. As a comparison, this is the closest thing to a “post” script in a Kickstart file.
- AsysncronousCommands during logon. These commands are executed after the setup and are really useful if you need to execute work that requires an unspecified number of additional reboots. We use it mainly to execute Windows updates.
To make things simpler, during each of the above steps we download and execute a Powershell script from the Github repository instead of adding every single action that we want to run into the XML file. This way we have a lot more flexibility and troubleshooting issues while writing those scripts becomes a cakewalk, especially using virtual machine snapshots.
Here are the actions that are performed in detail:
Specialize
- The most important feature: setting the Cloudbase Solutions wallpaper. 🙂
- Enabling ping response in the firewall (Note: RDP access is enabled in the XML file).
- Downloading the FirstLogon script.
FirstLogon
- Detecting what platform we are running on (KVM, Hyper-V, ESXi, etc). This requires WMI and is the reason why this and the next step are not executed during the Specialize phase.
- Installing the relevant platform drivers and tools: VirtIO drivers on KVM and VMWare tools on ESXi. Nothing is needed on Hyper-V, as the relevant tools are already included starting with Windows Server 2008. Note: the VirtIO drivers are unsigned, so we use a trick to get the job done in a fully unattended way. 😉
Important note: The Fedora VirtIO drivers version 0.1-65 generate a blue screen when you attach a volume. Use the stable version instead.
- Downloading the logon script.
Logon
- Installing PSWindowsUpdate, a Powershell module to handle, well, Windows Updates.
- Installing the updates. At the end of each updates round a reboot is performed if needed and after reboot the same step is repeated until the system is up to date. Please note that this might take a while, mostly depending on your Internet connection speed.
- Downloading and installing the latest Cloudbase-Init version.
- Finally running Sysprep, using Cloudbase-Init’s Unattended.xml and rebooting.
All you have to do to prepare an image, is to start a VM with the Autounattend.xml file on a virtual floppy, the Windows Server ISO connected on the first DVDRom drive and the optional platform tools (VirtIO drivers, VMWare tools, etc) on the second DVDRom drive.
When the image is done, it will shut down automatically, ready to be put in Glance.
Fairly easy, no?
How to automate the image creation on KVM
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
IMAGE=windows-server-2012-r2.qcow2 FLOPPY=Autounattend.vfd VIRTIO_ISO=virtio-win-0.1-52.iso ISO=9600.16384.WINBLUE_RTM.130821-1623_X64FRE_SERVER_EVAL_EN-US-IRM_SSS_X64FREE_EN-US_DV5.ISO KVM=/usr/libexec/qemu-kvm if [ ! -f "$KVM" ]; then KVM=/usr/bin/kvm fi qemu-img create -f qcow2 -o preallocation=metadata $IMAGE 16G $KVM -m 2048 -smp 2 -cdrom $ISO -drive file=$VIRTIO_ISO,index=3,media=cdrom -fda $FLOPPY $IMAGE \ -boot d -vga std -k en-us -vnc :1 |
Note: don’t forget to open the VNC port on the hypervisor’s firewall if you want to check of things are going (5901 in the example). It’s very important not to interact with the OS while the scripts run, but it’s a great way to see how things progress.
How to automate the image creation on Hyper-V
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
$vmname = "OpenStack WS 2012 R2 Standard Evaluation" # Set the extension to VHD instead of VHDX only if you plan to deploy # this image on Grizzly or on Windows / Hyper-V Server 2008 R2 $vhdpath = "C:\VM\windows-server-2012-r2.vhdx" $isoPath = "C:\your\path\9600.16384.WINBLUE_RTM.130821-1623_X64FRE_SERVER_EVAL_EN-US-IRM_SSS_X64FREE_EN-US_DV5.ISO" $floppyPath = "C:\your\path\Autounattend.vfd" # Set the vswitch accordingly with your configuration $vmSwitch = "external" New-VHD $vhdpath -Dynamic -SizeBytes (16 * 1024 * 1024 * 1024) $vm = New-VM $vmname -MemoryStartupBytes (2048 * 1024 *1024) $vm | Set-VM -ProcessorCount 2 $vm.NetworkAdapters | Connect-VMNetworkAdapter -SwitchName $vmSwitch $vm | Add-VMHardDiskDrive -ControllerType IDE -Path $vhdpath $vm | Add-VMDvdDrive -Path $isopath $vm | Set-VMFloppyDiskDrive -Path $floppyPath $vm | Start-Vm |
Check the README file of the project for updates, we’re definitely going to add more hypervisor options!
Thanks a lot for sharing your knowledge ! Very much appreciated !
Thanks Jordan!
Tried this with Windows 7 Enterprise. Getting the following error:
“Windows could not parse or process unattended answer file
[C:\Windows\Panther\unattend.xml] for pass [oobeSystem]. A
component or setting specified in the answer file does not exist.”
Any ideas?
Thanks,
Kevin
Hi Kevin,
Solved: you have to comment the following two options.
<HideOnlineAccountScreens>true</HideOnlineAccountScreens>
<HideLocalAccountScreen>true</HideLocalAccountScreen>
The github repository has been updated to match this update, so I suggest do a git pull to get the latest version.
Thanks
It now gets stuck at a new dialog after installing:
Set Up Windows:
Windows 7 Enterprise N
Choose a user name for your account. Your computer’s name is managed by your organization’s system administrator.
Type a user name (for example, John):
I’m guessing thats what one of those options was intended to surpress.
Creating a user gets to a desktop but I think the install didn’t finish. I see no trace of cloud init.
Thanks,
Kevin
On client OSs (Windows7, 8, 81, etc) you need to uncomment the section.
It’s in the Autounattend.xml comments, but we also added it in the README to make it more explicit:
https://github.com/cloudbase/windows-openstack-imaging-tools/blob/master/README.md
Yeah, that fixed it. Thanks.
A couple of other things:
I had to use “Windows 7 ENTERPRISEN” to get it to autoinstall for me. The lack of a space there threw me for a while. Could you add a comment for that for others?
The other thing I’m still working through. Its doing all of its updates, but being an ENTERPRISE varient, its trying to install a ton of language packs. I edited Logon.ps1 and added the following to the end of the Get-WUInstall line:
-NotCategory “Language packs”
It kept confusing me though since editing the files didn’t seem to have any effect until I relaized the local Autounattended.xml is the only file used. It points back to github for the other files. Two possible options to make this better:
* Can the extra files be placed in the floppy image instead? Then they can be referenced directly.
* If the installer can’t handle that, at very least, can the Autounattended.xml file be changed to set the baseurl in one place, and download all of the files at once, so you only need to change the one file to point it at a different url?
Thanks,
Kevin
Hi Kevin,
Added Win7 Enterprise (not N) to the list. We should thing about an utility that extracts the possible image names from the install DVD, like the AIK tools do.
Good point. Testing and adding it!
The reason why we keep those scripts online and not in the floppy image is that updates are automatically reflected in the next boot without having to generate a floppy image.
Being an open source project, the idea is that anybody can fork the repository, download the scripts and tweak them based on personal requirements (for example by putting the scripts in the floppy image). We’re trying to make them as generic as possible to suit most needs (hence the support for various Windows versions and not only WS 2012 R2) but we obviously cannot cover every possible requirement.
The problem with the forking this way though is it does not go as you’d expect.
When you git checkout or git fork, you expect that changes in the repository you used initially do not automatically get applied each time you instantiate the software. That should only happen on a git pull. As it is now, you git clone the repo and it might work for a few days, and then it might suddenly stop working once someone checks in a change to trunk.
In fact, that was the case just a few minutes ago once FirstLogin got updated to use a command that isn’t in 7.
The idea is that along with the fork, you should update the links in Autounattend.xml to point to your repo (not the original one)
Found another issue. You need to tweak FirstLogon.ps1 to point to E:\Win7 not Win8. Nothing failed, but performance was terible. Maybe a readme comment about this too please?
BTW, is there a better place to discuss issues?
Thanks,
Kevin
We just updated FirstLogon.ps1 to dynamically select the path (Win7, WIn8, etc) based on the OS.
This was not an issue, the scripts have been created for WS2012R2 and we progressively added automated support of other OS versions (see also the Autounattend.xml various options).
Just tried that. It fails due to:
System.Management.Automation.CommandNotFoundException: The term ‘get-Volume’ is not recognized as the name of a cmdlet, function, script file, or operable program…
I’ll try and tweak that part back to a hard coded E: and see if the rest works.
Thanks,
Kevin
This is due to the fact that Get-Volume has been introduced with Powershell 3.0. We definitely need to find an alternative for 2.0
Powershell 2.0 (Windows 7 / WIndows Server 2008 R2) added by replacing Get-Volume with a WMI query.
Hi,
We are behind a proxy here and it seems that the scripts downloads a lot of stuff. Do you know a way of adding the proxy in the Autounattend.xml file.
we tried adding this section :
<component name="Microsoft-Windows-IE-ClientNetworkProtocolImplementation" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" ve$
true
http://xxx.xxx.xxx.xxx:8080
But it didn’t work.
thanks for the help.
Hi, there are a few options:
1) Instance System.Net.WebProxy, configure it and assign it to the System.Net.WebClient instances used.
We’re going to add an example ASAP.
2) Put the scripts in an internal web server
3) Put the scripts on the attached floppy image
Looks like after Microsoft last update in PSWindowsUpdate (December 24) I’m facing problems to install 2008 R2, after reboot I’m getting the error below:
System.Management.Automation.ActionPreferenceStopException: Command execution stopped because the preference variable “ErrorActionPreference” or common parameter is set to Stop: The term ‘Unblock-File’
is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name,
or if a path was included, verify that the path is correct and try again. at System.Management.Automation.Internal.PipelineProcessor.SynchronousExecute
Enumerate(Object input, Hashtable errorResults, Boolean enumerate)
at System.Management.Automation.PipelineNode.Execute(Array input, Pipe output
Pipe, ArrayList& resultList, ExecutionContext context)
at System.Management.Automation.StatementListNode.ExecuteStatement(ParseTreeN
ode statement, Array input, Pipe outputPipe, ArrayList& resultList, ExecutionCon
text context)
Thanks for the update, we’re looking into it.
Hi,
Thanks for the wonderful work.I’m facing the problem after Instance launch for windows 7 professional.i I created the windows 7 professional qcow2 image and install the OS using KVM VNC console using the virtio-win-0.1-74.iso driver and generated Autounattend.vfd. I’m getting blue screen error. in System recovery window I’m seeing Operating System Unknown on (unknown) Local Disk.. i don’t know where I’m doing wrong here.please guide me.
Thanks,
Tulasiram
We also noticed issues with the 0.1.74 stable version of the VirtIO drivers on Windows 7 and Windows Server 2008 R2. By our preliminary tests the previous version works.
Can you please attach a link to a snapshot of the blue screen? Is your Windows 7 architecture x86 or x64?
Hi,
Thanks for the great work!!!
I am facing the same problem mentioned above for 2008r2 server:
System.Management.Automation.ActionPreferenceStopException: Command execution stopped because the preference variable “ErrorActionPreference” or common parameter is set to Stop: The term ‘Unblock-File’
is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name,
or if a path was included, verify that the path is correct and try again. at System.Management.Automation.Internal.PipelineProcessor.SynchronousExecute
Enumerate(Object input, Hashtable errorResults, Boolean enumerate)
at System.Management.Automation.PipelineNode.Execute(Array input, Pipe output
Pipe, ArrayList& resultList, ExecutionContext context)
at System.Management.Automation.StatementListNode.ExecuteStatement(ParseTreeN
ode statement, Array input, Pipe outputPipe, ArrayList& resultList, ExecutionCon
text context)
Could you please advise what could be wrong here?
thanks,
Vin
Hi, it’s a bug in PSWindowsUpdate, we just committed a workaround for it, please let me know if it works for you.
Hello,
We experiment some issue with the network on OpenStack we only get 70 to 80 Mbit/sec with some image made with your script but but don’t experiment any issue with the evaluation version you directly proivide.
Is there anything we have to do except installing the virtIO network driver ?
regards,
Xavier
Hi Xavier, we use the same scripts to generate the evaluation images. What version of the VirtIO tools are you using?
Hello,
Following the instructions above I was able to create an image and watch it install via vnc just fine. However, when I migrated it into openstack I get a blue screen with *** STOP: 0x0000005D (0x000000000FCBFBF9, 0x0000 … ) etc . This is windows 2008 R2.
any help apprec .
Hi, this error happens when deploying the image on QEMU instead of KVM. Can you please confirm that your Nova compute nodes are configured accordingly?
Thanks