Automating VDA Migration Between Catalogs in XenDesktop

Automating VDA Migration Between Catalogs in XenDesktop

September 17, 2021 0 By Amir Joseph Sayes

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 

$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 

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) 

$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

<#
 .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 
    }

}