cgfixit

SCCM Patching Script for Proxies (Need to add custom hostname input and logging)

Oct 7th, 2025
372
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #Purpose: Gracefully drain selected VMware proxies, stop Veeam services for patching/reboot, then return them to #production.
  2. #Requirements
  3. # -Veeam Component: Veeam Backup & Replication 12.3.2 (Server & Console)
  4. # -Permissions:
  5. # Backup Administrator role in VBR
  6. # Local Administrator on each proxy (for remote Invoke-Command)
  7. # MFA: Disabled for the account launching PowerShell (MFA is not supported for Veeam PowerShell sessions ‑ KB4535)
  8. # PowerShell 5.1 on the jump host
  9. #Further Prerequisites for Success:
  10.  
  11. #Proxies 'F-1' and 'M-1' must exist in VBR configuration (if mismatch you will receive error but the script can be modified to accomodate
  12.  
  13. #WinRM enabled on both proxy servers
  14.  
  15. #Account has Backup Administrator role in VBR
  16.  
  17. #Account has local administrator rights on proxy servers
  18.  
  19. #PowerShell execution policy allows script execution
  20.  
  21. #Network connectivity between script host and proxies
  22.  
  23.  
  24.  
  25. <#
  26. Veeam Confidential - Internal Use Only
  27. Validated against Veeam Backup & Replication 12.3.2 (build 12.0.3.x) on 2025-07-24
  28.  
  29. Purpose  :  Gracefully drain selected VMware proxies, stop Veeam services for patching/reboot, then return them to production.
  30. Usage    : powershell.exe -ExecutionPolicy Bypass -File ProxyMaintenance.ps1 -Stage Pre|Post
  31. ExitCodes: 0  = Success
  32.            10 = Proxy objects not found
  33.            20 = Disable failed          (Pre)
  34.            30 = Task-drain timeout      (Pre)
  35.            40 = Stop-service failure    (Pre)
  36.            50 = Start-service failure   (Post)
  37.            60 = Re-enable failure       (Post)
  38.            90 = Invalid Stage argument
  39.            99 = Unhandled error
  40. NOTED Requirements:
  41.  
  42. Proxies 'F-1' and 'M-1' must exist in VBR configuration (if mismatch you will receive error but the script can be modified to accomodate
  43.  
  44. WinRM enabled on both proxy servers
  45.  
  46. Account has Backup Administrator role in VBR
  47.  
  48. Account has local administrator rights on proxy servers
  49.  
  50. PowerShell execution policy allows script execution (PowerShell 5.1 on jump ost)
  51.  
  52. MFA: Disabled for the account launching PowerShell (MFA is not supported for Veeam PowerShell sessions ‑ KB4535)
  53.  
  54. Network connectivity between script host and proxies
  55. --
  56. Troubleshooting:
  57.  
  58. Task Drain Delay:
  59. Use Suspend-VBRJob to pause jobs feeding these proxies.
  60. Check Instant Recovery sessions — they may hold proxy resources.
  61. Service Stop Failures
  62.  
  63. Misc:
  64. Run Get-Service Veeam* manually to confirm service names.
  65. Ensure no orphaned TCP connections (Get-NetTCPConnection).
  66. #>
  67.  
  68.  
  69. param(
  70.     [ValidateSet('Pre','Post')]
  71.     [string]$Stage = 'Pre'
  72. )
  73.  
  74. Write-Output "Process begins (Stage: $Stage)..."
  75.  
  76. $ProxyBatch           = @('F-1','M-1')      # proxies under maintenance
  77. $PollDelay            = 30                  # seconds between task-drain checks
  78. $DrainTimeoutMinutes  = 30                  # max wait time for drain
  79.  
  80. Import-Module Veeam.Backup.PowerShell -ErrorAction Stop
  81.  
  82. try {
  83.     #------------------------------------------------------------
  84.     # Common: get proxy objects
  85.     #------------------------------------------------------------
  86.     $ProxyObjs = Get-VBRViProxy -Name $ProxyBatch
  87.     if (-not $ProxyObjs) {
  88.         Write-Error "No matching proxies found!"
  89.         exit 10
  90.     }
  91.  
  92.     #------------------------------------------------------------
  93.     if ($Stage -eq 'Pre') {
  94.     #------------------------------------------------------------
  95.         # Disable proxies
  96.         try { $ProxyObjs | Disable-VBRViProxy }
  97.         catch { Write-Error "Failed to disable proxies: $_"; exit 20 }
  98.  
  99.         # Drain running tasks
  100.         Write-Host ">>> Waiting for active tasks to drain…" -ForegroundColor Cyan
  101.         $StartTime = Get-Date
  102.         do {
  103.             $Busy = Get-VBRTaskSession | Where-Object {
  104.                 $_.IsWorking -and ($ProxyBatch -contains $_.ProxyName)
  105.             }
  106.             if ($Busy) {
  107.                 if ((Get-Date) - $StartTime -gt (New-TimeSpan -Minutes $DrainTimeoutMinutes)) {
  108.                     Write-Error "Task drain timeout after $DrainTimeoutMinutes minutes"
  109.                     exit 30
  110.                 }
  111.                 Write-Host (" {0} task(s) still running – sleeping {1}s" -f $Busy.Count, $PollDelay)
  112.                 Start-Sleep -Seconds $PollDelay
  113.             }
  114.         } until (-not $Busy)
  115.         Write-Host ">>> No active tasks – stopping services." -ForegroundColor Green
  116.  
  117.         # Stop services on each proxy
  118.         foreach ($Node in $ProxyBatch) {
  119.             try {
  120.                 Write-Host " Stopping Veeam services on $Node …"
  121.                 Invoke-Command -ComputerName $Node -ScriptBlock {
  122.                     Get-Service Veeam* | Stop-Service -Force
  123.                 }
  124.             } catch {
  125.                 Write-Error "Failed to stop Veeam services on $Node: $_"
  126.                 exit 40
  127.             }
  128.         }
  129.  
  130.         Write-Output "Stage Pre completed successfully"
  131.         exit 0
  132.     }
  133.  
  134.     #------------------------------------------------------------
  135.     elseif ($Stage -eq 'Post') {
  136.     #------------------------------------------------------------
  137.         # Start services on each proxy
  138.         foreach ($Node in $ProxyBatch) {
  139.             try {
  140.                 Write-Host " Starting Veeam services on $Node …"
  141.                 Invoke-Command -ComputerName $Node -ScriptBlock {
  142.                     Get-Service Veeam* | Start-Service
  143.                 }
  144.             } catch {
  145.                 Write-Error "Failed to start Veeam services on $Node: $_"
  146.                 exit 50
  147.             }
  148.         }
  149.  
  150.         # Re-enable proxies
  151.         try { $ProxyObjs | Enable-VBRViProxy }
  152.         catch { Write-Error "Failed to re-enable proxies: $_"; exit 60 }
  153.  
  154.         Write-Output "Stage Post completed successfully"
  155.         exit 0
  156.     }
  157.  
  158.     #------------------------------------------------------------
  159.     else {
  160.         Write-Error "Invalid -Stage argument. Use Pre or Post."
  161.         exit 90
  162.     }
  163. }
  164. catch {
  165.     Write-Error "Unhandled error: $_"
  166.     exit 99
  167. }
Advertisement
Add Comment
Please, Sign In to add comment