feat(sprint3): Invoke-VmrunBounded, Get-GuestIPAddress, transport and concurrency hardening
H4: Invoke-VmrunBounded added to _Common.psm1 (Start-Process + Wait-Process + taskkill on
timeout, returns {ExitCode;Output;TimedOut;ElapsedSeconds}). Wired in Invoke-CIJob.ps1
for vmrun start (180s) and Remove-BuildVM.ps1 for stop/deleteVM (60s/90s).
H5: Cleanup-OrphanedBuildVMs.ps1 removes stale vm-start.lock (>30 min). ValidateRange
lowered to 0 to allow emergency -MaxAgeHours 0. Invoke-RetentionPolicy.ps1 same.
H8: _Transport.psm1 SSH hardening: StrictHostKeyChecking=accept-new, F:\CI\State\known_hosts.
H9: Validate-DeployState.ps1 Linux branch added: checks ci-report-ip.service enabled,
ci-report-ip.sh executable via SSH. New params: -GuestOS, -SshKeyPath, -SshUser.
H12: Get-GuestIPAddress extracted into _Common.psm1 (guestinfo.ci-ip primary, getGuestIPAddress
fallback). Invoke-CIJob.ps1 Phase 3b replaced with single call. Measure-CIBenchmark.ps1
updated to match.
Also: _Common.psm1 adds Write-CIRedactedCommand and ConvertTo-SafeShellSingleQuotedString.
Pester suite updated: 30/30 pass.
This commit is contained in:
@@ -1,35 +1,130 @@
|
||||
#Requires -Version 5.1
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Validates that Deploy-WinBuild2025.ps1 has correctly configured a guest VM.
|
||||
Validates that a guest VM has been correctly configured.
|
||||
|
||||
.DESCRIPTION
|
||||
Connects to the VM via WinRM (HTTP/Basic) and runs all checks that
|
||||
Install-CIToolchain-WinBuild2025.ps1 Steps 1/2/3/4b/5b/5c assert as validation-only.
|
||||
Use this after Deploy completes and before running Prepare/Install-CIToolchain.
|
||||
For Windows guests: connects via WinRM (HTTPS/Basic) and runs all checks
|
||||
that Install-CIToolchain-WinBuild2025.ps1 asserts as validation-only.
|
||||
|
||||
For Linux guests: connects via SSH and verifies that ci-report-ip.service
|
||||
is enabled and that the ci-report-ip.sh script is executable.
|
||||
|
||||
Use this after Deploy completes and before taking the BaseClean snapshot.
|
||||
|
||||
.PARAMETER VMIPAddress
|
||||
IP address of the guest VM on VMnet8 (e.g. 192.168.79.129).
|
||||
|
||||
.PARAMETER GuestOS
|
||||
Target OS: Windows (default) or Linux.
|
||||
|
||||
.PARAMETER AdminUsername
|
||||
Admin account inside the VM (default: Administrator).
|
||||
Windows only — admin account inside the VM (default: Administrator).
|
||||
Prompted if -GuestOS Windows and -AdminPassword is not provided.
|
||||
|
||||
.PARAMETER AdminPassword
|
||||
Password for the admin account. Prompted if omitted.
|
||||
Windows only — password for the admin account.
|
||||
|
||||
.PARAMETER SshKeyPath
|
||||
Linux only — path to the SSH private key (no passphrase).
|
||||
Default: F:\CI\keys\ci_linux
|
||||
|
||||
.PARAMETER SshUser
|
||||
Linux only — SSH login user inside the VM.
|
||||
Default: ci_build
|
||||
|
||||
.EXAMPLE
|
||||
# Windows
|
||||
.\Validate-DeployState.ps1 -VMIPAddress 192.168.79.129
|
||||
|
||||
.EXAMPLE
|
||||
# Linux
|
||||
.\Validate-DeployState.ps1 -VMIPAddress 192.168.79.200 -GuestOS Linux
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory)] [string] $VMIPAddress,
|
||||
|
||||
[ValidateSet('Windows', 'Linux')]
|
||||
[string] $GuestOS = 'Windows',
|
||||
|
||||
# Windows params
|
||||
[string] $AdminUsername = 'Administrator',
|
||||
[string] $AdminPassword
|
||||
[string] $AdminPassword,
|
||||
|
||||
# Linux params
|
||||
[string] $SshKeyPath = 'F:\CI\keys\ci_linux',
|
||||
[string] $SshUser = 'ci_build'
|
||||
)
|
||||
|
||||
Set-StrictMode -Version Latest
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
# ── Linux branch ──────────────────────────────────────────────────────────────
|
||||
if ($GuestOS -eq 'Linux') {
|
||||
if (-not (Test-Path $SshKeyPath -PathType Leaf)) {
|
||||
Write-Error "SSH key not found: $SshKeyPath"
|
||||
exit 1
|
||||
}
|
||||
|
||||
$sshBase = @(
|
||||
'-i', $SshKeyPath,
|
||||
'-o', 'StrictHostKeyChecking=no',
|
||||
'-o', 'UserKnownHostsFile=NUL',
|
||||
'-o', 'ConnectTimeout=10',
|
||||
'-o', 'BatchMode=yes',
|
||||
"$SshUser@$VMIPAddress"
|
||||
)
|
||||
|
||||
Write-Host "`nValidating Linux Deploy state on $VMIPAddress..." -ForegroundColor Cyan
|
||||
|
||||
$checks = [System.Collections.Generic.List[pscustomobject]]::new()
|
||||
|
||||
function Add-LinuxCheck {
|
||||
param([string]$Name, [string]$SshCommand, [scriptblock]$Validator)
|
||||
$savedEap = $ErrorActionPreference; $ErrorActionPreference = 'Continue'
|
||||
$out = (& ssh.exe @sshBase $SshCommand 2>&1)
|
||||
$rc = $LASTEXITCODE
|
||||
$ErrorActionPreference = $savedEap
|
||||
$pass = [bool](& $Validator $out $rc)
|
||||
$checks.Add([pscustomobject]@{ Name = $Name; Pass = $pass; Err = if (-not $pass) { "rc=$rc out=$out" } else { '' } })
|
||||
}
|
||||
|
||||
# ci-report-ip.service must be enabled
|
||||
Add-LinuxCheck `
|
||||
-Name 'ci-report-ip.service enabled' `
|
||||
-SshCommand 'systemctl is-enabled ci-report-ip.service 2>/dev/null' `
|
||||
-Validator { param($out, $rc) $rc -eq 0 -and "$out".Trim() -eq 'enabled' }
|
||||
|
||||
# ci-report-ip.sh must be executable
|
||||
Add-LinuxCheck `
|
||||
-Name '/usr/local/bin/ci-report-ip.sh executable' `
|
||||
-SshCommand 'test -x /usr/local/bin/ci-report-ip.sh && echo ok' `
|
||||
-Validator { param($out, $rc) $rc -eq 0 }
|
||||
|
||||
Write-Host ''
|
||||
$failed = 0
|
||||
foreach ($r in $checks) {
|
||||
if ($r.Pass) {
|
||||
Write-Host " [OK] $($r.Name)" -ForegroundColor Green
|
||||
} else {
|
||||
$detail = if ($r.Err) { " ($($r.Err))" } else { '' }
|
||||
Write-Host " [FAIL] $($r.Name)$detail" -ForegroundColor Red
|
||||
$failed++
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host ''
|
||||
if ($failed -eq 0) {
|
||||
Write-Host "All $($checks.Count) Linux Deploy checks passed." -ForegroundColor Green
|
||||
exit 0
|
||||
} else {
|
||||
Write-Host "$failed / $($checks.Count) Linux Deploy checks FAILED." -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
# ── Windows branch (WinRM HTTPS) ──────────────────────────────────────────────
|
||||
if (-not $AdminPassword) {
|
||||
$secure = Read-Host "Password for $AdminUsername@$VMIPAddress" -AsSecureString
|
||||
$AdminPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto(
|
||||
|
||||
Reference in New Issue
Block a user