To conclude this three-part blog series, we are now going take a look at reference implementation for building your own Microsoft Windows Virtual Appliance (VA). Similar to the Linux VA build, the Windows OVA will also support the ability to customize basic networking configuration including the use of a static or DHCP option.

In addition, to demonstrate the endless possibilities for building your own VA, I have also included an option to automatically join a Microsoft Active Directory Domain as part of the OVA deployment, which is a fairly common operation after deploying a Windows-based system. In the example below, I am using Windows Server 2016 and PowerShell to perform all the required automation.

Step 1 - Create a new VM in vCenter Server and then install Window Server 2016 using the ISO. Once you have completed the OS installation, you may want to apply any patches or packages that you want included as part of your VA. Once that is done, go ahead and shut down the VM.

Step 2 - Select the VM in the vSphere Inventory and then click on Configure->vApp and then check the Enable vApp Options. Once enabled, select OVF environment for the IP allocation scheme. In the OVF Details tab, select VMware Tools for the OVF environment transport. (Optionally) You can specify some additional metadata including appliance name and URLs to help others who maybe consuming your VA once it has been exported to an OVF/OVA.

Step 3 - Next, add the following 9 OVF properties which will be used as input to configure networking within PhotonOS. Click Add and provide a Label, Key and optional Category.



Label Key Category Hostname guestinfo.hostname Networking IP Address guestinfo.ipaddress Networking Netmask guestinfo.netmask Networking Gateway guestinfo.gateway Networking DNS Server guestinfo.dns Networking DNS Domain guestinfo.domain Networking AD Domain guestinfo.ad_domain Active Directory AD Username guestinfo.ad_username Active Directory AD Password guestinfo.ad_password Active Directory



Step 3 - Power back on the VM and once it is available on the network (assuming DHCP), download and copy the sample first boot script customize-guest.ps1 to C:\Users\Administrator\Desktop. This script is where all the magic happens and will process the OVF property input and then configure the network settings and if specified, it will also perform the Active Directory domain join. Right now it assumes the networking fields are optional, meaning if they are left blank, it will default the system to DHCP. If you provide all input properties, then it will go ahead and configure a static network address.

Step 4 - Using a Local Group Policy, we can have Windows run our startup script on boot up. Open the Local Group Policy Editor and navigate to Windows Settings->Scripts and under the PowerShell Scripts tab, add our script and then click OK to save.



Step 5 - At this point, the OS is now prepared and you can shut it down so we can export it to an OVF. To do so, you can either use OVFTool or simply use the vSphere UI by right clicking on the VM and select Template->Export OVF Template and download the respective files to your local desktop. Once you have the OVF, you can then convert it to an OVA using OVFTool which will give you a single image that you can easily distribute amongst your organization rather than a collection of files.

One limitation that I have found when exporting to an OVF is that the ordering of the OVF Properties is no longer maintained. If you want a particular ordering, especially for logical purposes, you will need to manually edit the OVF file prior to conversion. Here is a sample Windows2016-Template.ovf file that you can use as a reference and if you decide to edit the OVF file, you will need to delete the .mf file which contains a hash of the originally generated OVF or the conversion will fail.

Step 6 - Next, run the following OVFTool command to convert your OVF to an OVA:

ovftool <OVF File> <OVA File>

Step 7 - Finally, the last thing to do is to try out our new Windows Server OVA! Go ahead and run through the Import OVF wizard and you should now be prompted to input OVF properties. As mentioned earlier, the script is designed to handle zero input which means it will default to DHCP or if you specify all the properties, it will go ahead and configure a static network address. You can also use various CLIs like OVFTool or govc to import the OVA, but for testing purposes, the vSphere UI is ideal to ensure there are no issues.

Note: When configuring the netmask address using PowerShell, it no longer uses the traditional netmask value (e.g 255.255.255.0), it expects the input to be CIDR notation (e.g. 24)



Once the VM starts up, the first boot script will automatically execute and once it has completed, it will create a file in %TEMP%\ran_customization which is checked by script to ensure it only runs once. For testing or debugging purposes, you can remove the file and the customization script will re-run again. In addition, I also create a log file stored in %TEMP%\customization-log.txt which can be used for development and testing purposes.

Hopefully you enjoyed this short blog series and that it helps demystify how Virtual Appliances actually work in-conjunction with OVF Properties which is nothing more than custom key/values that are defined as part of an OVF/OVA and those key/values mean nothing without a GuestOS script which actually process and does the actual customization, which can range from basic networking to automating other OS settings or even application deployment.