Tuesday, October 3, 2017

Using PowerShell To Create And Manage Instant Clone Pools With Horizon PowerCLI

With Horizon PowerCLI the sky's the limit for folks looking to automate their Horizon 7 environments with PowerShell.  Horizon PowerCLI entails leveraging a Horizon 7 module built right into PowerCLI 6.5 R1 and provides Horizon admins with full access to the same View API that's used by the Horizon Administrator console.  So, theoretically, any tasks accomplished through the administrator console can now be automated through PowerShell.  This is a vast improvement over the very limited capabilities of View PowerCLI, which has been officially deprecated as of Horizon 7.0.3.  Further, by leveraging the advanced functions developed by the VMware Horizon 7 team, administrators gain simplified and instant access to some of these new PowerShell capabilities.  Even better, with a completely documented View API, anything not achievable with these advanced functions out of the box can be achieved with determination and elbow grease.

(What we're working with.  For more details check out this blog by Graeme Gordon.)

My favorite new capability offered by Horizon PowerCLI is Instant Clone pool management.  Using the advanced functions mentioned above I plan to demonstrate how Instant Clone pools can be managed with zero understanding of the View API.   Then I'll demonstrate how you can further augment this capability with just a little digging into the View API documentation. 

The processes detailed below assumes you have PowerCLI 6.5 R1 installed with the Horizon 7 module and VMware.Hv.Helper module imported.   For an excellent tutorial on these preliminary steps check out this blog post by Ray Heffer.  Once you complete the setup detailed in that post you should be good to go.

To get connected to the View API on your connection servers you leverage the Connect-HVServer cmdlet that's part of the Horizon 7 module.  Here's an example:

Connect-HVServer -server view-connect.lab.local -user administrator -password YoMama -domain lab

Now that we're connected, we can take advantage of the New-HVPool advanced function:

New-HVPool -InstantClone -PoolName "Insta-Gimme" -PoolDisplayName "Gimme Desktop" -Description "Virtual desktops for important people" -UserAssignment FLOATING -ParentVM 'Parent' -SnapshotVM 'R25' -VmFolder 'temp' -HostOrCluster 'LabCluster' -ResourcePool 'LabCluster' -NamingMethod PATTERN -NamingPattern "Gimme{n}" -Datastores 'Clones' -NetBiosName 'lab' -DomainAdmin administrator 

Below are the result of the function executing successfully.   

For an explanation of the parameters we provided to New-HVPool, you can use the same old PowerShell help commands you're normally used to running, so commands like help New-HVPool or help New-HVPool -examples will work for you.   Also, if you're using the PowerShell ISE, you easily browse and look up parameters for all the VMware.Hv.Helper functions using the commands explorer.

Next, we can leverage the New-HVEntitlement function to entitle domain users to this new pool.  In this example, we entitle domain users for the "lab" domain:

New-HVEntitlement -ResourceName 'Insta-Gimme' -User 'lab\domain users' -ResourceType Desktop -Type Group

We can also go on to schedule an Instant Clone push for after hours.  To do that we use the Start-HVPool function:

Start-HVPool -Pool Insta-Gimme -LogoffSetting WAIT_FOR_LOGOFF -ParentVM 'Parent' -SchedulePushImage -SnapshotVM R25 -StartTime '23:30' -StopOnFirstError $true

When we go back and look at the pool we can see that the image push has been schedule.

Next, we can use Set-HVPool to enable or disable the pool:

Set-HVPool -PoolName Insta-Gimme -Disable

Digging In Deeper Into The View API

Using Set-HVPool and the View API documentation, we can compensate for some short comings of the New-HVPool function.  After exploring New-HVPool more thoroughly it came to my attention it supports way less parameters for Instant Clones than for Linked Clones.  For instance, when using New-HVPool to create an instant clone there's no option for setting a default display protocol or for enabling HTML access.  That's okay though.  We can look up specific objects and properties within the View API documentation and then use Set-HVPool to update these objects accordingly. 

To begin with, to get more information about the new Instant Clone pool and what type of object it is, we'll use the Get-HVPool function.

$MyNewPool = Get-HVPool -PoolName Insta-Gimme

We can then use Get-Member to get more information about this pool object type.   

Based on the output we can see that the pool is of the object type DesktopInfo and that it's properties in turn are other objects.  To get more information about this object and it's child objects, we can go to the View API documentation and look it up.

This entry for DesktopInfo includes links to the child objects that make up it's properties.   Poking around these different objects, I discovered that it's DesktopSettings object contains DisplayProtocolSettings object, which in turn has a property for defaultdisplayprotocol.  This certainly looks promising.   To confirm the current value of this setting, I can leverage the $MyNewPool object once again. 


This jives with what I see in the view administrator console.   Looking at the View API documentation for the DisplayProtocolSettings object, I can see that possible values for the DefaultDisplayProtocol property are RDP, PCOIP and BLAST.    With this info in hand I go on to leverage the Set-HVPool function to change the default protocol.    

Set-HVPool -PoolName Insta-Gimme -Key "desktopSettings.displayProtocolSettings.defaultDisplayProtocol" -Value "BLAST"

Examples of other pool properties we can set our using Set-HVPool are enabling HTML access or increasing the max number of machines.   

Set-HVPool -PoolName InstaGime2 -Key "desktopSettings.displayProtocolSettings.enableHTMLAccess" -Value $true

Set-HVPool -PoolName Insta-Gimme -Key "automatedDesktopData.vmNamingSettings.patternNamingSettings.maxNumberOfMachines" -Value 3

Note: At least in my own environment, the -Key parameter above is case sensitive, with every member name starting with a lowercase.   For example, if I were to try and run the above command with a capital A for the "AutomatedDesktopData" member, I get an error message about an invalid member name.  See the example below.


So, this has been an intro into how to get dangerous with Horizon PowerCLI.   In the future I plan to publish an additional post about using the View API Helper library to get more creative.  If you're looking for additional resources on what was covered in this post, here's the good stuff:

Automating VMware Horizon 7 with VMware PowerCLI 6.5 
Quick Guide To The Horizon 7 API With VMware PowerCL
View API 7.1.0
Horizon View API Review by Simon Long 


  1. This article was indispensable in preserving my sanity. Key names start with a lowerCASE character!!! ARRRRRRR!!!!!

    Happy Friday!

  2. Hello,
    I am trying to disable session collaboration setting in pool in horizon 7 but its giving the same error, no matter if I try lowercase or upper case. Please help me!!!!

    Set-HVPool -PoolName $PoolName -Key "$pool.DesktopSettings.DisplayProtocolSettings.EnableCollaboration" -Value $false

    Exception calling "Desktop_Update" with "3" argument(s): "ExceptionType : VMware.Hv.InvalidArgument
    ErrorMessage : Invalid member name.
    ParameterName : VMware.Hv.DesktopInfo.DesktopSettings.DisplayProtocolSettings.EnableCollaboration"
    At C:\Program Files\WindowsPowerShell\Modules\VMware.Hv.Helper\VMware.HV.Helper.psm1:6524 char:8
    + $desktop_helper.Desktop_Update($services,$item,$updates)
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : VimException