Files
local-ci-cd-system/scripts/Wait-VMReady.ps1
T
Simone 34b33c5011 fix(winrm-https): PS 5.1 Test-WSMan has no -SessionOption — remove from all call sites
Test-WSMan in Windows PowerShell 5.1 does not support -SessionOption (WSManSessionOption),
causing "Cannot find a parameter matching the name 'SessionOption'" at runtime.

Prepare-WinBuild2025.ps1:
  - Remove Test-WSMan connectivity check step entirely
  - Open New-PSSession directly (handles -SkipCACheck via PSSessionOption)
  - Wrap New-PSSession in try/catch with the same actionable error message
  - Remove $wsmOpt (WSManSessionOption) — no longer needed
  Wait-GuestWinRMReady: replace Test-WSMan probe with New-PSSession probe + Remove-PSSession

Wait-VMReady.ps1:
  - Remove $wsmOpt entirely
  - Replace Test-WSMan -UseSSL -SessionOption with Test-NetConnection -Port 5986
    (TCP open on 5986 = HTTPS listener up = VM ready; credentials not available here)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-10 15:58:57 +02:00

132 lines
4.5 KiB
PowerShell

#Requires -Version 5.1
<#
.SYNOPSIS
Waits until a build VM is fully ready to accept WinRM connections.
.DESCRIPTION
Performs a three-phase readiness check in a polling loop:
1. vmrun getState returns "running"
2. ICMP ping succeeds
3. Test-WSMan (WinRM) responds without error
Throws if the VM does not become ready within the timeout period.
.PARAMETER VMPath
Full path to the clone VM's .vmx file.
.PARAMETER IPAddress
IP address of the VM on the build network (e.g. 192.168.11.101).
.PARAMETER TimeoutSeconds
Maximum seconds to wait for the VM to become ready.
Default: 300 (5 minutes)
.PARAMETER PollIntervalSeconds
Seconds between readiness checks.
Default: 5
.PARAMETER VmrunPath
Full path to vmrun.exe.
Default: C:\Program Files (x86)\VMware\VMware Workstation\vmrun.exe
.EXAMPLE
.\Wait-VMReady.ps1 `
-VMPath "F:\CI\BuildVMs\Clone_run-42_20260508_143022\Clone_run-42_20260508_143022.vmx" `
-IPAddress "192.168.11.101"
#>
[CmdletBinding()]
param(
[Parameter(Mandatory)]
[string] $VMPath,
[Parameter(Mandatory)]
[ValidatePattern('^((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$')]
[string] $IPAddress,
[ValidateRange(30, 600)]
[int] $TimeoutSeconds = 300,
[ValidateRange(3, 30)]
[int] $PollIntervalSeconds = 5,
[string] $VmrunPath = 'C:\Program Files (x86)\VMware\VMware Workstation\vmrun.exe',
# Skip ICMP ping phase (phase 2). Useful when the guest firewall blocks ICMP
# but WinRM (TCP 5986) is open. Phase 1 (vmrun state) and phase 3 (WinRM)
# are still checked.
[switch] $SkipPing
)
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
if (-not (Test-Path $VmrunPath -PathType Leaf)) {
throw "vmrun.exe not found at: $VmrunPath"
}
$deadline = (Get-Date).AddSeconds($TimeoutSeconds)
$attempt = 0
$phase = 'vmrun-state' # tracks current phase for informative output
$lastPhase = ''
Write-Host "[Wait-VMReady] Waiting for VM ready (timeout: ${TimeoutSeconds}s, IP: $IPAddress)..."
while ((Get-Date) -lt $deadline) {
$attempt++
# ── Phase 1: VM must be running ─────────────────────────────────────
# vmrun has no getState; getGuestIPAddress exits non-zero when the VM
# is not powered on. Native commands don't throw — check exit code only.
& $VmrunPath getGuestIPAddress $VMPath 2>&1 | Out-Null
$isRunning = ($LASTEXITCODE -eq 0)
if (-not $isRunning) {
if ($phase -ne 'vmrun-state') {
$phase = 'vmrun-state'
}
if ($lastPhase -ne $phase) {
Write-Host "[Wait-VMReady] Phase 1/3: waiting for VM to enter running state..."
$lastPhase = $phase
}
Start-Sleep -Seconds $PollIntervalSeconds
continue
}
# ── Phase 2: Network ping (optional) ───────────────────────────────
if (-not $SkipPing) {
$pingOk = Test-Connection -ComputerName $IPAddress -Count 1 -Quiet -ErrorAction SilentlyContinue
if (-not $pingOk) {
$phase = 'ping'
if ($lastPhase -ne $phase) {
Write-Host "[Wait-VMReady] Phase 2/3: VM running, waiting for network (ping $IPAddress)..."
$lastPhase = $phase
}
Start-Sleep -Seconds $PollIntervalSeconds
continue
}
}
# ── Phase 3: WinRM port 5986 accepting TCP connections ───────────────
# Test-WSMan has no -SessionOption in PS 5.1 and fails cert validation for
# self-signed certs. TCP open on 5986 = HTTPS listener up = VM ready.
$winrmUp = Test-NetConnection -ComputerName $IPAddress -Port 5986 `
-InformationLevel Quiet -WarningAction SilentlyContinue `
-ErrorAction SilentlyContinue
if ($winrmUp) {
Write-Host "[Wait-VMReady] VM ready after ~$([int]($attempt * $PollIntervalSeconds))s (attempt $attempt)."
return
}
else {
$phase = 'winrm'
if ($lastPhase -ne $phase) {
Write-Host "[Wait-VMReady] Phase 3/3: ping OK, waiting for WinRM on port 5986 (HTTPS)..."
$lastPhase = $phase
}
Start-Sleep -Seconds $PollIntervalSeconds
continue
}
}
throw "[Wait-VMReady] Timed out after ${TimeoutSeconds}s waiting for VM at $IPAddress to become ready. Last phase: $phase"