VMware Horizon Community
visan35
Enthusiast
Enthusiast
Jump to solution

Script to look and add free vms in pool

I am looking for a script that will automatically add VM to pool when number of vms are less than the users entitled to pool.

Currently users are entitled thru a security group. Admins don't know if enough VMS are available in pool unless we manually go and check the pool size and free vms available.

We provision VM's in advance and not on demand as it usually takes 15 to 20 mins to provision a vm.

Visan.

1 Solution

Accepted Solutions
jrodsguitar
Enthusiast
Enthusiast
Jump to solution

For that just change this line:

$entitledusers = (Get-ADGroupMember $Poolentitlments.distinguishedName).count

To this:

$entitledusers = ($PoolEntitlments | foreach {Get-ADGroupMember $_.distinguishedName | where {$_.objectclass -eq 'user'}}).count

if I've been helpful please mark my answer as Correct Smiley Happy

Blog: https://powershell.house/

View solution in original post

10 Replies
BenFB
Virtuoso
Virtuoso
Jump to solution

I don't have a script to offer but instead a suggestion if you get one. I'd add some type of verification to the process before increasing the pool size. Just in case someone mistakenly adds a large amount of users to a AD group that could overwhelm your cluster and impact the performance of your users.

jrodsguitar
Enthusiast
Enthusiast
Jump to solution

So I couldn't find a way to do this via the Horizon API so we'll do it old school. I wrote a script that does what you need.

You'll need to run this from a server that has RSAT installed with the PowerShell AD modules. It creates an implicit connection to the View Server and imports the commands necessary to run.

https://get-cj.com/2018/04/02/auto-add-machines-to-vmware-horizon-pool-based-on-entitled-users/

The variables you need to change are at the top. $viewserver, $pooldisplayname, $machinebuffer, and $threshold. Here's the top section for reference.

#Change these settings to match your environment ###########################################################

$viewserver = "NAME_OF_SERVER" 

$poolDisplayName = 'DISPLAY_NAME_OF_POOL'

#Buffer number of machines to increase pool by. Change this based on your estimated needs.

#The script will increase the max number of machines by (Total Amount of entitled users - The difference of Total Machines in pool) + $machineBuffer

#So if the total amount of machines is 3 and the total number of entitled users is 5. We need 2 machines right? So the script will add 2 machines + $machineBuffer.

$machineBuffer = 1

#If totla machines to add is greater or equal to 50 don't do it. This is a precautionary measure in case someone adds too many users to the entitled AD group.

$threshold = 50

############################################################################################################

Blog: https://powershell.house/
jrodsguitar
Enthusiast
Enthusiast
Jump to solution

Good advice BenFB

My script takes this into account and has a $threshold variable to set the limit of new machines that can be created.

Blog: https://powershell.house/
0 Kudos
visan35
Enthusiast
Enthusiast
Jump to solution

I will try your script. It seems to do what I am looking for. Is it possible to include below conditions in the script:

1. I have around 18 full and linked clone pools. I like to query all the pools at same time once in a day and expand pool size if their are no VMS available.

2. In addition to entitling the pool to the AD groups their are some pools that have individual users entitled to it.

How can we modify script to include these 2 conditions?

Visan.

0 Kudos
jrodsguitar
Enthusiast
Enthusiast
Jump to solution

I suggest if possible to remove the individual users that are entitled to pools. Even though this works, I find it leads to clutter later on if not properly managed as users leave the company, etc.

You did say you have linked and full clones so you'll need to figure out a way to differentiate between al inked clone and a full clone pool because the command will be different. Maybe you can run this as 2 separate jobs. One for linked clones and one for full? Then you'd need a list of pools but you can do that easy enough. $pools = ('Pool1','Pool2','Pool3')

Linked CLones:

Update-VDIAutomaticLinkedClonePool -MaximumCount $newMaxMachines -MinimumCount $newMaxMachines -Pool_id $pool.pool_id

Full CLones:

Update-VDIAutomaticPool -MaximumCount $newMaxMachines -MinimumCount $newMaxMachines -Pool_id $pool.pool_id

To iterate through each pool you can do this. You just need to populate that $pools variable, either with a list then use get-vdipool on the list or as it is below for all pools if you can include logic to differentiate between linked and full clones.

$pools = get-vdipool

foreach($pool in $pools){

#Gather Pool data

#$pool = (Get-VDIPool -DisplayName $poolDisplayName)

$PoolEntitlments = Get-VDIPoolEntitlement -Pool_id $pool.pool_id

$maxmachines = $pool.maximumCount

Blog: https://powershell.house/
0 Kudos
visan35
Enthusiast
Enthusiast
Jump to solution

Thanks for your quick reply.

Will this cript work even when you have multiple AD groups entitled to same pool? Will it query the user count by adding members in all the AD groups to fund the total entitled users count?

0 Kudos
jrodsguitar
Enthusiast
Enthusiast
Jump to solution

For that just change this line:

$entitledusers = (Get-ADGroupMember $Poolentitlments.distinguishedName).count

To this:

$entitledusers = ($PoolEntitlments | foreach {Get-ADGroupMember $_.distinguishedName | where {$_.objectclass -eq 'user'}}).count

if I've been helpful please mark my answer as Correct Smiley Happy

Blog: https://powershell.house/
visan35
Enthusiast
Enthusiast
Jump to solution

Hi Jose

I got this below error

Get-ADGroupMember : Directory object not found

At line:1 char:30

+ ($PoolEntitlments | foreach {Get-ADGroupMember $_.distinguishedName})

+                              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : ObjectNotFound: (CN=ab test05,OU...ten,DC=co,DC=jp:ADGroup) [Get-ADGroupMember], ADIdentityNotFoundExcep

   tion

    + FullyQualifiedErrorId : ActiveDirectoryCmdlet:Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException,Microsoft.ActiveD

   irectory.Management.Commands.GetADGroupMember

After I run the below code

$entitledusers = ($PoolEntitlments | foreach {Get-ADGroupMember $_.distinguishedName | where {$_.objectclass -eq 'user'}}).count

I have installed the RSAT module.

0 Kudos
jrodsguitar
Enthusiast
Enthusiast
Jump to solution

So when I suggested to remove individual users from pool entitlement this is why. This means there is a user assigned to a pool. The script tries to do get-ADgroupmember on a user and returns that error.

I added some logic to it so that it handles that situation better. I'll repost the entire script so take the pieces that you need.

#This script will autamtically increaese the Maximum amount of Machines in a Linked CLone Pool based on the number of entitled users. It increases the total by a user specificied setting.

#Jose Rodriguez (jrodsguitar)

#https://get-cj.com

#Change these settings to match your environment ###########################################################

$viewserver = "NAME_OF_SERVER" 

#$poolDisplayName = 'DISPLAY_NAME_OF_POOL'

#Buffer number of machines to increase pool by. Change this based on your estimated needs.

#The script will increase the max number of machines by (Total Amount of entitled users - The difference of Total Machines in pool) + $machineBuffer

#So if the total amount of machines is 3 and the total number of entitled users is 5. We need 2 machines right? So the script will add 2 machines + $machineBuffer.

$machineBuffer = 1

#If totla machines to add is greater or equal to 50 don't do it. This is a precautionary measure in case someone adds too many users to the entitled AD group.

$threshold = 2

############################################################################################################

if($cred -eq $null){

$cred = Get-Credential

}

if($connect -eq $null){

$connect = Connect-HVServer -server $viewserver

}

$session = New-PSSession -Computername $viewserver

#Define a scriptblock to run - $computer is set to the first argument, $variable to the second 

$scriptBlock =

 

#Initialize variables and load modules for horizon on remote connection server.

Set-Variable product_name "VMware View PowerCLI" -scope Private

Set-Variable view_snapin_name "VMware.View.Broker" -scope Private

Set-Variable powercli_snapin_name "VMware.VimAutomation.Core" -scope Private

Set-Variable powercli_product_name "VI Toolkit / VSphere PowerCLI" -scope Private

# Load View Snapin

$ViewSnapinLoaded = Get-PSSnapin | Where { $_.Name -eq $view_snapin_name }

if(!$ViewSnapinLoaded){

write-host "Loading $product_name"

# Install or Re-register View Cmdlets

$installpath = (get-itemproperty "HKLM:\Software\VMware, Inc.\VMware VDM").ServerInstallPath

$NetFrameworkDirectory = $([System.Runtime.InteropServices.RuntimeEnvironment]::GetRuntimeDirectory())

set-alias installUtil (Join-Path $NetFrameworkDirectory "InstallUtil.exe")

$null = (installUtil ($installpath  + "\bin\PowershellServiceCmdlets.dll"))

add-PSSnapin $view_snapin_name

} else {

write-host "$product_name snapin already loaded."

}

# Load VI Toolkit/PowerCLI if available

$VimAutomationInstalled = Get-PSSnapin -Registered | Where { $_.Name -eq $powercli_snapin_name }

if($VimAutomationInstalled){

$VimAutomationLoaded = Get-PSSnapin | Where { $_.Name -eq $powercli_snapin_name }

if(!$VimAutomationLoaded){

write-host "Loading $powercli_product_name"

add-PSSnapin $powercli_snapin_name

} else {

write-host "$powercli_product_name already loaded"

}

}

Remove-Variable product_name -scope Private

Remove-Variable view_snapin_name -scope Private

Remove-Variable powercli_snapin_name -scope Private

Remove-Variable powercli_product_name -scope Private

Add-PSSnapin vmware.view.broker 

 

#Run script to intialize remote session

Invoke-Command -Session $session -ScriptBlock $scriptBlock

#Import remote session and prefix commands with 'VDI'

$importsession = Import-PSSession -Session $session -Prefix VDI -Module VMware*

$pools = get-vdipool

foreach($pool in $pools){

#Gather Pool data

#$pool = (Get-VDIPool -DisplayName $poolDisplayName)

$PoolEntitlments = Get-VDIPoolEntitlement -Pool_id $pool.pool_id

$maxmachines = $pool.maximumCount

$userGroupCheck = $null

$poolUsers = $null

$poolGroups = $null

$entitledusers = $null

#Counts the number of users in the AD group that is entitled to the pool

$userGroupCheck =  ($PoolEntitlments | foreach {Get-ADObject $_})

$poolUsers = @($userGroupCheck |   where {$_.objectclass -eq 'user'}).Count

$poolGroups =  @($userGroupCheck |   where {$_.objectclass -eq 'group'}).Count

$entitledusers = $poolUsers + $poolGroups

#If entitled users is greater than the amount of entitles users than increase the max machines in the pool by $newMaxIncrease

if($entitledusers -ge $maxmachines ){

$newMaxMachines = ($entitledusers - $maxmachines) + $machineBuffer

$total = $newMaxMachines + $maxmachines

If($total -le $threshold){

Update-VDIAutomaticLinkedClonePool -MaximumCount $newMaxMachines -MinimumCount $newMaxMachines -Pool_id $pool.pool_id

#Update-VDIAutomaticPool -MaximumCount $newMaxMachines -MinimumCount $newMaxMachines -Pool_id $pool.pool_id

Write-Output "Increasing Max machines $($pool.pool_id) from $maxmachines to $total machines"

}

else{

Write-output "$threshold is too big. Aborting the process"

}

}

}

Get-PSSession | Remove-PSSession

Blog: https://powershell.house/
visan35
Enthusiast
Enthusiast
Jump to solution

This script works perfectly fine. Thank for summarizing the various comments and redrafting the script. Appreciate your help.