Application Management – Underused Template Settings

This blog post marks the start of a new series on advanced features of Templates in Virtual Machine Manager. Most of the features I’ll be showing are lesser-known and scenario-specific, but I hope they will aid users in accomplishing tasks. In this first post, I’ll be discussing the use of Organization Units when deploying VMs to a domain.

OUs in VM Templates

A common best practice for simplification of VM deployments from VMM is to avoid the use of complicated GPOs. For an Active Directory environment that already has GPOs in place, it would be useful to have certain OU containers dedicated to VMs deployed by VMM. This way, the administrator can enforce the “no complicated GPOs” paradigm.image

Within VMM, a VM can be configured to join a domain upon creation by using a VM template. In the OS portion of the VM Template, there is a section for domain configuration, as depicted on the right.

During deployment, the VM will join the specified domain using the credentials provided. Under the covers, VMM generates an Answer File that contains certain information and attaches it to the VM during completion of the Windows installation (since the disk image containing the OS should have had the Sysprep tool run).

If we need more advanced options like a specific OU, there are PowerShell cmdlets for performing these operations.

The cmdlet we’ll need is Set-SCVMTemplate. I’ll assume we already have a VM template we want to adjust called “Domain” as depicted in the figure:

image Now, we’ll want an elevated console on which to run a few simple commands. First, we’ll import the module containing the necessary cmdlets:

Import-Module VirtualMachineManager;

Next, we’ll define the OU container which will contain the VM:

$ou = "OU=VMs,DC=contoso,DC=com";

Notice the formatting of the string. Although the string is not case-sensitive, ensure to use commas and not semi-colons to separate the fields. Next, we get the template object using the Get-SCVMTemplate cmdlet:

$template = Get-SCVMTemplate | where {$_.Name -eq "Domain"};

The string “Domain” is simply the name of the template. Now we set the OU:

Set-SCVMTemplate -VMTemplate $template -DomainJoinOrganizationalUnit $ou;

And that’s it. Obviously, these commands could be combined rather than using the temporary variables but I’m aiming for readability.

UI Visibility

The problem now is the lack of visibility for this setting in the UI. To fix this, we’ll use custom properties. First, we’ll create a new Custom Property in VMM. First, we’ll bring up the properties of the VM template and choose to Manage Custom Properties.



In the next window, we see a drop-down selector:


The concept of managing custom properties can be a bit confusing. When managing these properties, we’re not changing our VM Template, we’re adjusting the global settings for custom properties. By selecting Virtual Machine Template as the object type, I’m adding a custom property that will be available to all VM Templates. Next, I’m going to add a property called OU. Now I choose to create a property and name it:
image Now, I add this property to the VM Template object:

image And we’ll see this property appear in the list:


We could type something in the box if we wanted, but we’ll do that later. Back to the main screen, we can now add this property to the view by right-clicking the columns:

imageNow, we can populate this field for all VM templates in PowerShell using the Set-SCCustomPropertyValue cmdlet:

Get-SCVMTemplate | %{ Set-SCCustomPropertyValue -InputObject $_ -CustomProperty $(Get-SCCustomProperty -Name "OU") -Value $_.DomainJoinOrganizationalUnit };

Back in the UI, this value has now been populated:

image To keep this info always in sync, you might consider adding this line of PowerShell to an scheduled task queue on the VMM server.

OUs in Service Templates

Now, if you’re using service templates, you might wonder how this can be applied to a tier and how to parameterize it. It’s important to realize that VM templates placed into service templates are copied by value and no reference is made to the original. So, if you set a domain OU in the VM template and add it to a service template, the value of the OU will be copied but changing it proves a little more difficult (changes in the original VM template will not propagate to the service).

It’s important to understand that a VM tier in a service template corresponds to a VM template, although this relationship is not exactly exposed to the UI. So, let’s say we have a service template with two tiers and both tiers have VMs that need to join a domain with a particular OU. It might look something like this:

imageI created an empty service template and added the VM template we created earlier twice. Because these VM tiers are linked to VM templates, viewing the Custom Properties section of the tier properties shows the OU we set earlier. This value is purely aesthetic; we can’t change the OU by adjusting this custom property.

image If we added the earlier bit of PowerShell to the scheduled tasks, this custom property will be updated if we change the DomainJoinOrganizationUnit property for the VM template that’s linked by this tier. We’ll save this service template as “Demo” with a Release “V1” and we’ll adjust it in PowerShell:

$service_template = Get-SCServiceTemplate | where {$_.Name -eq "Demo" -and $_.Release –eq “V1”};

This service template will have a list of tiers and we’ll get the tier we want (although this could be done with a foreach clause):

$tier = $service_template.ComputerTierTemplates | where {$_.Name -like "*Tier 1"};

The VM template that is linked can now be retrieved:

$vm_template = $tier.VMTemplate;

Once you have the template object, the OU can be updated as before. You’ll have to rerun the script to propagate the custom property before you’ll see the change reflected in the UI. If you need even more flexibility (say, a service setting for the OU property), you’ll need to consider deploying service templates completely outside of the UI and setting this value at deployment time with a script as this property cannot be a service setting.

That’s all for now, stay tuned for upcoming posts in this series.