
Background
Customers using Citrix XenDesktop with dedicated catalog may want to relocate the desktops to another catalog for various reasons such as wanting to change the datastore behind it or simply to change the catalog from Un-managed to Power Managed.
Doing this manually would be painful as you will have to remove the machines from their Delivery Groups, catalogs, lose their assigned users, then re-add them to the new catalog and reconfigure them.
In this scenario, the solution provided can automate all of those actions with Powershell so the whole process can take minutes instead of days.
Problem
The existing catalogs were not power managed, which wasn’t handy when users wanted to reboot their own machines and made management more difficult for System Administrators. So new Power Managed catalogs were needed without changing the existing user assignments nor the Delivery Groups.
Environment
CVAD 7+ or later
VMware vSphere as a Virtualization Hypervisor
Requirements
- Admin Access to the Citrix DDC and Powershell
- XenDesktop SDK (Installed by default on the Desktop Delivery Controller) or can be found on CVAD media ISO under Drive:\x64\Citrix Desktop Delivery Controller
- VMware PowerCLI Module using Powershell
- Create your new Catalog(s) (with one machine only) and give it a new name/configuration e.g. Power Managed etc.. then use the following command to grab
To the script!
Using your favourite editor (VSCode, PoSH ISE, etc) open up Powershell as Admin
Providing you installed the SDKs above on the machine you are running the code from, add all the snap-ins to your PoSH session
Add-PSSnapin * -ErrorAction SilentlyContinue
Set your variables for the Hypervisor Connection ID and the New Catalog ID – those are needed for the script to work
In Studio, go to Hosting and find the connection name that connects your machines to the Hypervisor then feed that name into the following command
$HypervisorConnectionUid = (Get-BrokerHypervisorConnection -Name <Replace with connection Name>).Uid
Also, grab the name of the new catalog(s) you just created and feed it into the following command
$CatalogUID = (Get-BrokerCatalog -Name "Replace with new Catalog Name").Uid
If you have more than one geo location and want to separate your catalogs accordingly you may grab the UID of each Catalog you create – in my case I needed to create 2 catalogs, one for each data center site
1 2 3 4 |
$CatalogUID_C = (Get-BrokerCatalog -Name "Replace with new Catalog Name").Uid $CatalogUID_Z = (Get-BrokerCatalog -Name "Replace with new Catalog Name").Uid |
Connect to Vmware if not already
Connect-VIServer -Server <vCenter_FQDN> -User <username>
In order to stage the migration, a tag can be created and assigned to the machines that are ready to be migrate. In Studio, create a new tag e.g. Migrate_MC and assign as needed to machines
Next the script will grab a random Delivery Controller (or Cloud Connector) and choose it as the principle AdminAddress – in the following function, replace with your DDC or CC accordingly
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
Function Get-a-XAbroker { Add-PSSnapin * -ErrorAction SilentlyContinue #List of XML brokers $DDCs = "DDC1","DDC2","DDC3","DDC4" foreach ($controller in $DDCs | Sort-Object {Get-Random}) { $Error.Clear() Get-BrokerController -AdminAddress $controller | Out-Null if ($Error.Count -eq 0) { break } } if ($error.Count -gt 0) {continue}; $SelectedDDC = $controller return $SelectedDDC } $adminaddress = Get-a-XAbroker |
Next, we grab the list of machines that has been tagged by you with “Migrate_MC” tag (to indicate that they are ready for migration)
1 2 3 |
$ListOfMachines = Get-brokermachine -AdminAddress $adminaddress -MaxRecordCount 5000 -Tag "Migrate_MC" |
Now, the magic happens! We loop into the list of machines and do the following for each machine:
- Grab the currently assigned user, the current delivery group name, current catalog and the machine name without domain
- Get the hostedmachineID and the VMHost from Vmware
- Remove the machine from the current delivery group
- Remove the machine from the current machine catalog
- In case you have more than hosting geographical locations, you may want to have a separate catalog for each and hence want to make sure that Machine A hosted on Host B goes to Catalog C while Machine X hosted on host Y goes to catalog Z etc..
- Re-add the machine to the old Delivery Group
- Re-add the user(s) to the machine
The code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
<# .Synopsis Script to migrate Citrix XenDesktop VDAs Between Catalogs on the fly with Powershell .DESCRIPTION The script gather several variables and pass them to the logic to complete the work .NOTES =========================================================================== Created on: 17/09/2021 Created by: Amir Joseph Sayes - Twitter @amirjsa Organization: Ninaronline.co.uk #> #Add snapins Add-PSSnapin * -ErrorAction SilentlyContinue #Variables $HypervisorConnectionUid = (Get-BrokerHypervisorConnection -Name <Replace with connection Name>).Uid $CatalogUID_C = (Get-BrokerCatalog -Name "Replace with new Catalog Name").Uid $CatalogUID_Z = (Get-BrokerCatalog -Name "Replace with new Catalog Name").Uid Connect-VIServer -Server <vCenter_FQDN> -User <username> Function Get-a-XAbroker { Add-PSSnapin * -ErrorAction SilentlyContinue #List of XML brokers $DDCs = "DDC1","DDC2","DDC3","DDC4" foreach ($controller in $DDCs | Sort-Object {Get-Random}) { $Error.Clear() Get-BrokerController -AdminAddress $controller | Out-Null if ($Error.Count -eq 0) { break } } if ($error.Count -gt 0) {continue}; $SelectedDDC = $controller return $SelectedDDC } $adminaddress = Get-a-XAbroker $ListOfMachines = Get-brokermachine -AdminAddress $adminaddress -MaxRecordCount 5000 -Tag "Migrate_MC" $ListOfMachines |% { #Grab the currently assigned user, the current delivery group name, current catalog and the machine name without domain $AssignedUser = @($($_.AssociatedUserNames)) $CurrentDeliveryGroupName = $($_.DesktopGroupName) $currentCatalogUID = $($_.CatalogUid) $HostedMachineName = ($_.machinename -split "\\")[1] $machinename = $_.machinename ###Get the hostedmachineID and the VMHost from Vmware $HostedmachineID = (Get-View -id (get-vm $HostedMachineName).id).config.uuid $VMHost = (get-vm $HostedMachineName).VMHost ######Remove the machine from the current delivery group Remove-BrokerMachine $_.MachineName -DesktopGroup $CurrentDeliveryGroupName -ErrorAction SilentlyContinue -Force #####Remove the machine from the current machine catalog Remove-BrokerMachine -MachineName $_.MachineName -ErrorAction SilentlyContinue -Force #In case you have more than hosting geographical locations, #you may want to have a separate catalog for each and hence want to make #sure that Machine A hosted on Host B goes to Catalog C while Machine X hosted on host Y goes to catalog Z etc.. if ($VMHost -like "*HostC*") { New-BrokerMachine -CatalogUid $CatalogUID_C -MachineName $_.MachineName -HypervisorConnectionUid $HypervisorConnectionUid -HostedMachineId $HostedmachineID } else { New-BrokerMachine -CatalogUid $CatalogUID_Z -MachineName $_.MachineName -HypervisorConnectionUid $HypervisorConnectionUid -HostedMachineId $HostedmachineID } #Re-add the machine to the old Delivery Group Add-BrokerMachine -MachineName $_.MachineName -DesktopGroup $CurrentDeliveryGroupName #Re-add the user(s) to the machine $AssignedUser | % { New-BrokerUser -Name $($_) | Add-BrokerUser -PrivateDesktop $machinename } } |