XenApp and XenDesktop PowerShell – Update MCS Image


If you need to automate the updating of a Machine Creation Services machine catalog, this script will be useful. It was created for a XenServer host.

The first part is to setup my parameters.

Function Update-MCSCatalog {
    param(
    [string] $xdControllers, #FQDN of a delivery controller
    [string] $MachineCatalogName, #Name of the MCS Machine Catalog
    [string] $MasterImage, #VM name for the master image
    [string] $storageResource, #The name of the host connection's resource from Citrix Studio
    [string] $HostResource, #The name of the host connection from Citrix Studio
    [string] $XSMaster, #The FQDN of the master XenServer host
    [string] $XenServerUsername, #XenServer host username
    [string] $XenServerPW #XenServer host password
    )

For the variables $StorageResource and $HostResource, you will use the names from Citrix Studio – Configuration – Hosting. I use “XenServer” for $HostResource and “XS_SharedStorage” for $StorageResource

StudioResources

 

First, make sure we load the Citrix PowerShell modules.

Write-Host (date -Format hh:mm:ss)   -   Updating machine catalog $machineCatalogName with the master VM $MasterImage -Foregroundcolor Green -Verbose

# Load the Citrix PowerShell modules
Write-Host (date -Format hh:mm:ss)   -   Loading Citrix XenDesktop modules. -Foregroundcolor Yellow -Verbose
Add-PSSnapin Citrix*

Next, we need to gather information about the XenDesktop infrastructure. We need storage and hypervisor information from Citrix Studio

# Get information from the hosting environment via the XD Controller
# Get the storage resource
Write-Host (date -Format hh:mm:ss)   -   Gathering storage and hypervisor connections from the XenDesktop infrastructure. -Foregroundcolor Yellow -Verbose
$hostingUnit = Get-ChildItem -AdminAddress $xdControllers "XDHyp:\HostingUnits" | Where-Object { $_.PSChildName -like $storageResource } | Select-Object PSChildName, PsPath

# Get the hypervisor management resources
$hostConnection = Get-ChildItem -AdminAddress $xdControllers "XDHyp:\Connections" | Where-Object { $_.PSChildName -like $hostResource }

# Get the broker connection to the hypervisor management
$brokerHypConnection = Get-BrokerHypervisorConnection -AdminAddress $xdControllers -HypHypervisorConnectionUid $hostConnection.HypervisorConnectionUid

Updates to an MCS catalog requires a VM snapshot. This section creates a new snapshot with the current date/time as the snapshot name.

# Get the master VM image from the storage resource
Write-Host (date -Format hh:mm:ss)   -   Getting the snapshot details for the catalog: $machineCatalogName  -Foregroundcolor Yellow -Verbose
$VM = Get-ChildItem "XDHyp:\HostingUnits\$storageResource" | Where-Object { $_.ObjectType -eq "VM" -and $_.Name -like $masterImage }
# Create snapshot.
$CurrentTime = Get-Timestamp
$Snapshot = New-HypVMSnapshot  -AdminAddress $XDControllers -LiteralPath $vm.FullPath -SnapshotName $CurrentTime
# Get the snapshot object
$VMSnapshots = Get-ChildItem -AdminAddress $xdControllers $VM.FullPath -Recurse -Include *.snapshot
$TargetSnapshot = $VMSnapshots | Where-Object { $_.FullPath -eq $snapshot }

This is the big part, update a machine catalog with the selected snapshot.

# Publish the image update to the machine catalog
$ProvScheme = Set-ProvSchemeMetadata -AdminAddress $xdControllers -Name 'ImageManagementPrep_DoImagePreparation' -ProvisioningSchemeName $machineCatalogName -Value 'True'
$PubTask = Publish-ProvMasterVmImage -AdminAddress $xdControllers -MasterImageVM $TargetSnapshot.FullPath -ProvisioningSchemeName $machineCatalogName -RunAsynchronously
$provTask = Get-ProvTask -AdminAddress $xdControllers -TaskId $PubTask

Would be nice to have a screen output showing the progress of the update process, as this can take some time.

# Track progress of the image update
Write-Host (date -Format hh:mm:ss)   -   Tracking progress of the machine creation task. -Foregroundcolor Yellow -Verbose
$totalPercent = 0
While ( $provTask.Active -eq $True ) {
    Try { $totalPercent = If ( $provTask.TaskProgress ) { $provTask.TaskProgress } Else {0} } Catch { }

    Write-Progress -Activity "Provisioning image update" -Status "$totalPercent% Complete:" -percentcomplete $totalPercent
    Sleep 15
    $provTask = Get-ProvTask -AdminAddress $xdControllers -TaskId $PubTask
}
Write-Progress -Activity "Provisioning image update"

Once the updates are master disk image are complete, we need to get these applied to all of the machines in the machine catalog. This section forces a reboot of all machines within the machine catalog.

# Start the desktop reboot cycle to get the update to the actual desktops
Write-Host (date -Format hh:mm:ss)   -   Initiating reboot of Machine Catalog $MachineCatalogName   -Foregroundcolor Yellow -Verbose
Get-brokerCatalog -Name $MachineCatalogName | Start-BrokerRebootCycle -AdminAddress $xdControllers -RebootDuration 1 -WarningDuration 0

This section is optional, but I like my VMs to have a description that says what VM was used as the master VM. Helps me remember.

# Change description for the VMs in the MachineCatalog to be the name of the master image VM
$XSSession = Connect-XenServer -server $XSMaster -UserName $XenServerUsername -Password $XenServerPW -SetDefaultSession -force
$CatalogVMs = Get-BrokerMachine | where { $_.CatalogName -eq $MachineCatalogName }
Foreach ( $catalogVM in $CatalogVMs) {
    set-xenvm -name $catalogvm.hostedmachinename -NameDescription $MasterImage
}
Disconnect-XenServer -session $XSSession
}
Advertisements

13 thoughts on “XenApp and XenDesktop PowerShell – Update MCS Image

Add yours

  1. Hello Could you help me i cant see to get this to work i keep getting error with the string can you show me where to put them. : [string] $xdControllers, #FQDN of a delivery controller

    Like

    1. I’m just calling this function like this:
      update-MCSCatalog -XDControllers “ddc-test.snpp.local” -MachineCatalogName “TestCatalog” -MasterImage “Win10-1809” -StorageResource “XS_SharedStorage” -HostResource “XenServer” -XSMaster “XS1.snpp.local”

      What error do you get?

      Like

  2. Hello Daniel,
    Thank you for sharing the script. I hope to use it our environment to update the VMs in Machine Catalog. Question on
    on the script parameters. I am new Citrix SDK. Not sure how to get value of the $storageResource, $HostResource?
    Is $XSMaster variable would be a vCenter server? Thank you in advance.

    Like

    1. I added a screen shot on where to get the $STorageResource and $hostResource items. It comes from Studio.

      For a vSphere environment, I believe you will use the vCenter server FQDN. Don’t have vSphere handy to test it out. You will also want to remove the last section “# Change description for the VMs in the MachineCatalog to be the name of the master image VM” as this is using XenServer powershell. I believe the rest of the function uses Virtual Apps/Desktops Powershell functions.

      Like

  3. getting a issue issue with : $brokerHypConnection = Get-BrokerHypervisorConnection -AdminAddress $xdControllers -HypHypervisorConnectionUid $hostConnection.HypervisorConnectionUid

    Get-BrokerHypervisorConnection : Cannot bind parameter ‘HypHypervisorConnectionUid’ to the target. Exception setting “HypHypervisorConnectionUid”: “Object reference not set to an instance
    of an object.”
    At line:1 char:112
    + … rConnectionUid $hostConnection.HypervisorConnectionUid
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : WriteError: (:) [Get-BrokerHypervisorConnection], ParameterBindingException
    + FullyQualifiedErrorId : ParameterBindingFailed,Citrix.Broker.Admin.SDK.GetBrokerHypervisorConnectionCommand

    Like

    1. Will need to track down which item before that fails. When it fails, do you have info for the variable $HostConnection?

      I added a screenshot to the blog identifying where to get the $StorageResource and $HostResource variable names.

      Like

      1. Look in Citrix Studio under Configuration – Hosting. In the image in the blog, you can see mine is called “XenServer”. I use that for the $HostConnection. Within that host connection is XS_SharedStorage. I use that for my $StorageResource

        Like

  4. $VM = Get-ChildItem “XDHyp:\HostingUnits\$storageResource” | Where-Object { $_.ObjectType -eq “VM” -and $_.Name -like $masterImage }. $VM is blank, unfortunately my W10 master images are in a vSphere resource pool under Citrix/Master, not at the root level. So the required VM object is not retrieved

    Small point, I guess
    PS I always enjoy your Citrix presentations

    Like

    1. It’s a function that you have to call…
      update-MCSCatalog -XDControllers “ddc-test.snpp.local” -MachineCatalogName “TestCatalog” -MasterImage “Win10-1809” -StorageResource “XS_SharedStorage” -HostResource “XenServer” -XSMaster “XS1.snpp.local”

      Like

  5. thank you so much i was able to kick it off and everything went fine but today keep getting the following error:

    New-HypVMSnapshot : Cannot validate argument on parameter ‘LiteralPath’. The argument is null. Provide a valid value for
    the argument, and then try running the command again.

    Like

  6. This is *almost* what I’ve been hunting around for since Citrix has mysteriously not given us scheduling options in the GUI. Before i get started making this work with vmware, has anyone already done that yet? If not, I’ll reply back here with an updated version that’ll work with vmware.

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Create a free website or blog at WordPress.com.

Up ↑

%d bloggers like this: