How to Clean up VMware Horizon View pools without vCenter online and remove missing desktop pool from Global Entitlement using ADSI Edit

Recently I had to do a cleanup of a VMware Horizon 7 connection server, which involved removing all the existing desktop pools and recreating them. The trouble was, the old vCenter server had been removed, so when I tried to delete the pools using the Horizon Administrator Console, I got the error:

Server Error
Unable to connect to the vCenter Server

To fix this, I did the following:

Get the list of VM’s you want to remove

Using PowerCLI I was able to get a list of machines in the pool I wanted to remove. Install PowerCLI from the documentation here: https://docs.vmware.com/en/VMware-Horizon-7/7.6/horizon-integration/GUID-7C7C5239-6990-47E0-B9FB-29EC0EB0F5AC.html

Make sure to also install the VMware.Hv.Helper module from here https://github.com/vmware/PowerCLI-Example-Scripts by copying in to the C:\Program Files\WindowsPowerShell\Modules folder.

Then, after connecting to the Horizon View server, get a list of VM’s:

# Get all HV Machines
$ms = Get-HVMachine

# Show the HV Machine Names
$ms[0..2] | select -ExpandProperty Base | select Name

# Select just the machines you want
$to_remove = $ms | ?{$_.Base.Name -match '17a6-clst-p...'}

# And export the list to a csv
$to_remove | Export-Csv -NoTypeInformation ~\Downloads\to_remove.csv

Use SviConfig to delete machine records from the Horizon View Composer

This is from the documentation here: https://docs.vmware.com/en/VMware-Horizon-7/7.6/horizon-virtual-desktops/GUID-F0D595CB-4E7B-4DAE-B80B-DCDCE85E8DF2.html

Once you have copied the CSV to the composer server, you have to use the list to delete all the composer records for the machines.

# Run in an admin Powershell from path C:\Program Files (x86)\VMware\VMware View Composer
# Import the CSV
$to_delete = Import-Csv ~\Downloads\to_remove.csv

# Delete each item in the list
$to_delete | %{.\SviConfig.exe -operation=removesviclone -vmname="$($_.Name)" -AdminUser=<put admin account here> -AdminPassword="<put admin password here>"}

Remove the pool from any Global Entitlements

Important — This has to be done before removing the pool using ADSI Edit, in the next step. However, if you mess this up, as I did, I have a workaround as the last step.

To do this, just go into the global entitlements and remove the pool you are cleaning up from any of the global entitlements. If you don’t do this, you will see the global entitlement saying there are 2 pools in it, for example, but when you open the global entitlement to delete the pool you can’t see the local pool to remove.

Delete the pool using ADSI edit

To delete the actual pool and machine entries, follow the guide here: https://kb.vmware.com/s/article/2015112

The simple version is, you open ADSI edit to connect to server localhost and Distinguished Name/Naming Context dc=vdi,dc=vmware,dc=int.

You then create a query with the root of the search being OU=Servers,DC=vdi,DC=vmware,DC=int and the query string being (&(objectClass=pae-VM)(pae-displayname=17a6-clst-p*))

You can then check through the item the Applications and Server Groups OU’s to find the pool and delete it. However, make sure you have removed the pool from any global entitlements first.

Workaround – Delete Global Entitlement Local Pool member using ADSI edit

To do this, open ADSI edit on the connection server, and choose “Connect to”. Use localhost:22389 as the server, and DC=vdiglobal,DC=vmware,DC=int as the Distinguished Name/Naming Context.

Create a new query, as you did with deleting the pool using ADSI edit. This query should be in the new connection, and have the settings:

Name: Find global entitlement \
Root of search: OU=Entitlements,DC=vdiglobal,DC=vmware,DC=int \
Query String: (&(objectClass=pae-GlobalAssignment)(pae-LocalEntitlement=*17a6-clst-p*))

Note that the name of the local pool you haven’t removed from the global entitlement is in the query between the * characters.

This should give you one item, of type pae-GlobalAssignment. Open it up, and make sure the pae-LocalEntitlement attribute matches what you want to delete. If so, delete it.

You now shouldn’t have the incorrect number of local pools in your global entitlement.

Leave a Reply

Your email address will not be published. Required fields are marked *