Inspired by Marco Hofmann’s My First Time: Citrix Machine Creation Services (MCS) over at CUGC I decided to write a post about his concerns on how to upgrade the Master Image(s) automatically.
The frase Rolling Upgrades was created by Jarian Gibson and has been shared in many of his presentations at my #virtualexpo. During my work with Automation Framework 3.8 I decided it was about time to add support for Rolling Upgrades in my Image Factory.
According to the State of the End User Computing Union Survey 2018 more than 64.52% of the surveyed companies are running VMware vSphere so let’s focus on that.
First of you’ll need to stand up a Microsoft Deployment Server and configure it. The quick fix here is to use my free Automation Framework Community Edition which does all that automatically and even have a couple of hours of training videos.
From the build server (I usally use the MDT server) you’ll need to install VMware PowerCli and Citrix Studio to get the required Powershell snapins.
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 |
Write-Verbose "Setting Arguments" -Verbose $StartDTM = (Get-Date) $MyConfigFileloc = ("$env:Settings\Applications\Settings.xml") [xml]$MyConfigFile = (Get-Content $MyConfigFileLoc) $Vendor = "Citrix" $Product = "Studio" $PackageName = "Studio" $InstallerType = "exe" $Version = "7.18" $LogPS = "${env:SystemRoot}" + "\Temp\$Vendor $Product $Version PS Wrapper.log" $LogApp = "${env:SystemRoot}" + "\Temp\$PackageName.log" $UnattendedArgs = '/quiet /COMPONENTS DESKTOPSTUDIO' $Destination = "$Version\x64\XenDesktop Setup\" Start-Transcript $LogPS CD $Destination Write-Verbose "Starting Installation of $Vendor $Product $Version" -Verbose (Start-Process -FilePath "XenDesktopServerSetup.exe" -ArgumentList $unattendedArgs -Wait -Passthru).ExitCode Write-Verbose "Customization" -Verbose Write-Verbose "Stop logging" -Verbose $EndDTM = (Get-Date) Write-Verbose "Elapsed Time: $(($EndDTM-$StartDTM).TotalSeconds) Seconds" -Verbose Write-Verbose "Elapsed Time: $(($EndDTM-$StartDTM).TotalMinutes) Minutes" -Verbose Stop-Transcript |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
Write-Verbose "Setting Arguments" -Verbose $startDTM = (Get-Date) $Vendor = "VMware" $Product = "vSphere PowerCLI" $LogPS = "${env:SystemRoot}" + "\Temp\$Vendor $Product PS Wrapper.log" Start-Transcript $LogPS Write-Verbose "Starting Installation of $Vendor $Product" -Verbose Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force Set-PSRepository -Name "PSGallery" -InstallationPolicy Trusted Install-Module -Name VMware.PowerCLI -AllowClobber Write-Verbose "Get Installed $Vendor $Product Modules" -Verbose Get-Module -ListAvailable -Name VMware* Write-Verbose "Stop logging" -Verbose $EndDTM = (Get-Date) Write-Verbose "Elapsed Time: $(($EndDTM-$StartDTM).TotalSeconds) Seconds" -Verbose Write-Verbose "Elapsed Time: $(($EndDTM-$StartDTM).TotalMinutes) Minutes" -Verbose Stop-Transcript |
Then follow the instructions in the Image Factory blog post to configure a static MAC address in CustomSettings.ini to pick the Task Sequence you want for deploying the Master Image(s). This will work, but not optimal because there will be various Master Image VMs with the same MAC address (conflict). You can steal with pride from this Github project to use PSIni and RandomMAC instead.
The trick to get the rest configured is to use the Powershell tab in Citrix Studio. A great tip is to create only 1 machine to keep thing simple. After testing you can quickly add as many VMs as you want.
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 |
# # Create Delivery Group 'WS16MCS' # # 9/22/2018 5:28 PM # Get-LogSite -AdminAddress "xadc-01.ctxlab.local:80" -BearerToken ******** Start-LogHighLevelOperation -AdminAddress "xadc-01.ctxlab.local:80" -BearerToken ******** -Source "Studio" -StartTime "9/22/2018 10:28:49 PM" -Text "Create Delivery Group `'WS16MCS`'" New-BrokerDesktopGroup -AdminAddress "xadc-01.ctxlab.local:80" -BearerToken ******** -ColorDepth "TwentyFourBit" -DeliveryType "DesktopsAndApps" -DesktopKind "Shared" -InMaintenanceMode $False -IsRemotePC $False -LoggingId "6caa4ffe-6119-4589-a4b4-4974896e6222" -MinimumFunctionalLevel "L7_9" -Name "WS16MCS" -OffPeakBufferSizePercent 10 -PeakBufferSizePercent 10 -PublishedName "WS16MCS" -Scope @() -SecureIcaRequired $False -SessionSupport "MultiSession" -ShutdownDesktopsAfterUse $False -TimeZone "Central Standard Time" Set-BrokerDesktopGroup -AdminAddress "xadc-01.ctxlab.local:80" -BearerToken ******** -InputObject @(1) -LoggingId "6caa4ffe-6119-4589-a4b4-4974896e6222" -PassThru -ZonePreferences @("ApplicationHome","UserHome","UserLocation") Add-BrokerMachine -AdminAddress "xadc-01.ctxlab.local:80" -BearerToken ******** -DesktopGroup "WS16MCS" -InputObject @(2) -LoggingId "6caa4ffe-6119-4589-a4b4-4974896e6222" Test-BrokerAppEntitlementPolicyRuleNameAvailable -AdminAddress "xadc-01.ctxlab.local:80" -BearerToken ******** -Name @("WS16MCS") New-BrokerAppEntitlementPolicyRule -AdminAddress "xadc-01.ctxlab.local:80" -BearerToken ******** -DesktopGroupUid 1 -Enabled $True -IncludedUserFilterEnabled $False -LoggingId "6caa4ffe-6119-4589-a4b4-4974896e6222" -Name "WS16MCS" Test-BrokerAccessPolicyRuleNameAvailable -AdminAddress "xadc-01.ctxlab.local:80" -BearerToken ******** -Name @("WS16MCS_Direct") New-BrokerAccessPolicyRule -AdminAddress "xadc-01.ctxlab.local:80" -AllowedConnections "NotViaAG" -AllowedProtocols @("HDX","RDP") -AllowedUsers "AnyAuthenticated" -AllowRestart $True -BearerToken ******** -DesktopGroupUid 1 -Enabled $True -IncludedSmartAccessFilterEnabled $True -IncludedUserFilterEnabled $True -IncludedUsers @() -LoggingId "6caa4ffe-6119-4589-a4b4-4974896e6222" -Name "WS16MCS_Direct" Test-BrokerAccessPolicyRuleNameAvailable -AdminAddress "xadc-01.ctxlab.local:80" -BearerToken ******** -Name @("WS16MCS_AG") New-BrokerAccessPolicyRule -AdminAddress "xadc-01.ctxlab.local:80" -AllowedConnections "ViaAG" -AllowedProtocols @("HDX","RDP") -AllowedUsers "AnyAuthenticated" -AllowRestart $True -BearerToken ******** -DesktopGroupUid 1 -Enabled $True -IncludedSmartAccessFilterEnabled $True -IncludedSmartAccessTags @() -IncludedUserFilterEnabled $True -IncludedUsers @() -LoggingId "6caa4ffe-6119-4589-a4b4-4974896e6222" -Name "WS16MCS_AG" Stop-LogHighLevelOperation -AdminAddress "xadc-01.ctxlab.local:80" -BearerToken ******** -EndTime "9/22/2018 10:28:51 PM" -HighLevelOperationId "6caa4ffe-6119-4589-a4b4-4974896e6222" -IsSuccessful $True # Script completed successfully |
After running the script for a couple of times it will look like this.
So that’s it. It’s easy to do but if you want something out of the box then the paid version of the Automation Framework is your quick fix.
Hello,
I am trying to use the script in MDT and placed the Settings.xml file under %DeployRoot%\Applications and the script is located in %DeployRoot%\Applications\Scripts.
When the script is executed it is failing to find the XML file to read the variables.
Are you able to shed any light as to how the below is used.
$MyConfigFileloc = (“$env:Settings\Applications\Settings.xml”)
[xml]$MyConfigFile = (Get-Content $MyConfigFileLoc)
Thanks!
Remember to set the an environment variable called Settings to \\MDTSERVER\MDTProduction$. Check documentation.