feat: replace serial automation with resident TCP agent
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
param(
|
||||
[int] $ReadyTimeoutSeconds = 45
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$root = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
|
||||
function Stop-Listener([int] $Port) {
|
||||
$listeners = Get-NetTCPConnection -State Listen -LocalPort $Port -ErrorAction SilentlyContinue
|
||||
foreach ($listener in $listeners) {
|
||||
Stop-Process -Id $listener.OwningProcess -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
|
||||
# Quit through QEMU's monitor so qcow2/FAT writes are flushed. Forced VM
|
||||
# termination is deliberately forbidden because it previously lost files.
|
||||
$monitor = Get-NetTCPConnection -State Listen -LocalPort 4444 -ErrorAction SilentlyContinue
|
||||
if ($monitor) {
|
||||
& (Join-Path $root 'monitor.ps1') 'quit' | Out-Null
|
||||
$deadline = (Get-Date).AddSeconds(10)
|
||||
do {
|
||||
Start-Sleep -Milliseconds 250
|
||||
$monitor = Get-NetTCPConnection -State Listen -LocalPort 4444 -ErrorAction SilentlyContinue
|
||||
} while ($monitor -and (Get-Date) -lt $deadline)
|
||||
if ($monitor) { throw 'QEMU did not quit cleanly; refusing a forced reset.' }
|
||||
}
|
||||
Stop-Listener 5555
|
||||
Start-Sleep -Milliseconds 500
|
||||
|
||||
$runner = Join-Path $root 'run.ps1'
|
||||
Start-Process powershell -ArgumentList @('-NoProfile','-ExecutionPolicy','Bypass','-File',$runner) -WorkingDirectory $root
|
||||
$deadline = (Get-Date).AddSeconds(15)
|
||||
do {
|
||||
Start-Sleep -Milliseconds 250
|
||||
$monitor = Get-NetTCPConnection -State Listen -LocalPort 4444 -ErrorAction SilentlyContinue
|
||||
} while (-not $monitor -and (Get-Date) -lt $deadline)
|
||||
if (-not $monitor) { throw 'QEMU monitor did not start.' }
|
||||
|
||||
# Select the default boot entry. TCPAGENT is started by FDAUTO.BAT after the
|
||||
# packet driver, so readiness is the agent connection/PONG rather than sleep.
|
||||
Start-Sleep -Seconds 2
|
||||
& (Join-Path $root 'monitor.ps1') 'sendkey ret' | Out-Null
|
||||
$deadline = (Get-Date).AddSeconds($ReadyTimeoutSeconds)
|
||||
$ready = $false
|
||||
do {
|
||||
Start-Sleep -Milliseconds 500
|
||||
$connection = Get-NetTCPConnection -State Established -LocalPort 5558 -ErrorAction SilentlyContinue
|
||||
if ($connection) {
|
||||
try {
|
||||
$client = [Net.Sockets.TcpClient]::new('127.0.0.1',5555)
|
||||
$stream = $client.GetStream()
|
||||
$stream.ReadTimeout = 1500
|
||||
$bytes = [Text.Encoding]::ASCII.GetBytes("PING`n")
|
||||
$stream.Write($bytes,0,$bytes.Length)
|
||||
$buffer = New-Object byte[] 128
|
||||
$reply = ''
|
||||
while ($reply -notmatch "`n") {
|
||||
$count = $stream.Read($buffer,0,$buffer.Length)
|
||||
if ($count -le 0) { break }
|
||||
$reply += [Text.Encoding]::ASCII.GetString($buffer,0,$count)
|
||||
}
|
||||
$client.Dispose()
|
||||
$ready = $reply -match '^OK 504F4E47'
|
||||
} catch { $ready = $false }
|
||||
}
|
||||
} while (-not $ready -and (Get-Date) -lt $deadline)
|
||||
if (-not $ready) { throw 'TCPAGENT did not become ready.' }
|
||||
Write-Host 'QEMU reset complete; TCPAGENT answered PONG.'
|
||||
Reference in New Issue
Block a user