Public/Restart-CitrixMachinesByTag.ps1
|
function Restart-CitrixMachinesByTag { <# .SYNOPSIS Restarts machines that carry a given tag, in staggered batches. Supports -WhatIf/-Confirm. .DESCRIPTION Selects machines with Get-BrokerMachine -Tag and queues restart power actions with New-BrokerHostingPowerAction in batches, waiting between batches. By default machines with active sessions are skipped. Power actions are queued and executed by the Broker's hosting connection throttling; this script only controls queuing pace. Maintenance mode is not changed; use Set-CitrixMaintenanceMode.ps1 separately if you need to drain first. .PARAMETER AdminAddress Delivery Controller FQDN. Omit for Citrix DaaS. .PARAMETER Tag Broker tag name (Get-BrokerTag). .PARAMETER BatchSize Machines per batch (default 5). .PARAMETER DelaySeconds Wait between batches (default 300). .PARAMETER IncludeMachinesWithSessions Also restart machines that have sessions (users will be disconnected - use with care). .PARAMETER Action Restart (graceful, default) or Reset (hard). .EXAMPLE Restart-CitrixMachinesByTag -AdminAddress ddc01 -Tag 'Reboot-Sunday' -BatchSize 10 -WhatIf .NOTES Author : Anthony Buhnerkemper License: MIT Requires the Citrix Virtual Apps and Desktops PowerShell SDK (on-prem) or the Citrix DaaS Remote PowerShell SDK. Tested for syntax only - validate in a lab first. #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'High')] param( [Parameter()] [string]$AdminAddress, [Parameter(Mandatory)] [string]$Tag, [Parameter()] [ValidateRange(1, 500)] [int]$BatchSize = 5, [Parameter()] [ValidateRange(0, 86400)] [int]$DelaySeconds = 300, [Parameter()] [switch]$IncludeMachinesWithSessions, [Parameter()] [ValidateSet('Restart', 'Reset')] [string]$Action = 'Restart' ) function Import-CitrixSdk { <# Loads the Citrix SDK: modules (CVAD 2203+ / Remote PowerShell SDK) first, snap-ins as fallback. #> if (Get-Command -Name Get-BrokerSite -ErrorAction SilentlyContinue) { return } $mod = Get-Module -ListAvailable -Name Citrix.Broker.Admin.V2 | Select-Object -First 1 if ($mod) { Import-Module $mod -ErrorAction Stop; return } if (Get-Command -Name Add-PSSnapin -ErrorAction SilentlyContinue) { Add-PSSnapin -Name Citrix* -ErrorAction SilentlyContinue } if (-not (Get-Command -Name Get-BrokerSite -ErrorAction SilentlyContinue)) { throw "Citrix Broker SDK not found. Run on a Delivery Controller, a machine with Studio/the SDK installed, or with the DaaS Remote PowerShell SDK." } } Import-CitrixSdk $ap = @{} if ($AdminAddress) { $ap.AdminAddress = $AdminAddress } $machines = @(Get-BrokerMachine -Tag $Tag -MaxRecordCount 10000 @ap | Where-Object { $_.HypervisorConnectionUid -and $_.PowerState -eq 'On' }) if (-not $IncludeMachinesWithSessions) { $skipped = $machines | Where-Object { $_.SessionCount -gt 0 } foreach ($s in $skipped) { Write-Warning "Skipping $($s.MachineName): $($s.SessionCount) session(s)" } $machines = @($machines | Where-Object { $_.SessionCount -eq 0 }) } if ($machines.Count -eq 0) { Write-Host "No eligible power-managed machines tagged '$Tag'."; return } Write-Host ("{0} machine(s) eligible, batch size {1}, delay {2}s" -f $machines.Count, $BatchSize, $DelaySeconds) for ($i = 0; $i -lt $machines.Count; $i += $BatchSize) { $batch = $machines[$i..([math]::Min($i + $BatchSize, $machines.Count) - 1)] foreach ($m in $batch) { if ($PSCmdlet.ShouldProcess($m.MachineName, "$Action (power action)")) { try { $pa = New-BrokerHostingPowerAction -MachineName $m.MachineName -Action $Action @ap -ErrorAction Stop [pscustomobject]@{ MachineName = $m.MachineName; Action = $Action; PowerActionUid = $pa.Uid; State = $pa.State } } catch { Write-Warning "Failed to queue $Action for $($m.MachineName): $($_.Exception.Message)" } } } $more = ($i + $BatchSize) -lt $machines.Count if ($more -and $DelaySeconds -gt 0 -and -not $WhatIfPreference) { Write-Verbose "Waiting $DelaySeconds seconds before next batch" Start-Sleep -Seconds $DelaySeconds } } Write-Host "Track progress with: Get-BrokerHostingPowerAction -State Pending,Started" } |