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.
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
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.
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
############################################################################################################
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.
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.
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
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?
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
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.
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)
#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
This script works perfectly fine. Thank for summarizing the various comments and redrafting the script. Appreciate your help.