103 lines
4.4 KiB
PowerShell
103 lines
4.4 KiB
PowerShell
[CmdletBinding()]
|
|
param(
|
|
[switch]$TokenStdin,
|
|
[ValidatePattern("^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$")]
|
|
[string]$RequestId = ("physical-k1-shadow-{0}" -f [Guid]::NewGuid().ToString("N")),
|
|
[string]$PersistentContainer = "mission-core-perception-worker",
|
|
[string]$PersistentOutputRoot = "D:\NDC_MISSIONCORE\runtime\derived\.perception-persistent-publish",
|
|
[ValidateRange(1024, 65535)] [int]$PersistentPort = 18020,
|
|
[ValidateRange(5, 3600)] [int]$MaximumDurationSeconds = 20,
|
|
[ValidateRange(1, 1000)] [int]$FreeGiBFloor = 360
|
|
)
|
|
|
|
$ErrorActionPreference = "Stop"
|
|
$ProgressPreference = "SilentlyContinue"
|
|
|
|
function Assert-LastExitCode([string]$Operation) {
|
|
if ($LASTEXITCODE -ne 0) { throw "$Operation failed with exit code $LASTEXITCODE" }
|
|
}
|
|
|
|
function Resolve-DDirectory([string]$Path, [string]$Label) {
|
|
$item = Get-Item -LiteralPath (Resolve-Path -LiteralPath $Path).Path -Force
|
|
$root = [IO.Path]::GetPathRoot($item.FullName).TrimEnd("\")
|
|
if (-not $item.PSIsContainer -or ($item.Attributes -band [IO.FileAttributes]::ReparsePoint) -or $root -ine "D:") {
|
|
throw "$Label must be a real D: directory"
|
|
}
|
|
return $item.FullName
|
|
}
|
|
|
|
function Get-DFreeBytes { return [int64](Get-PSDrive -Name D).Free }
|
|
|
|
if (-not $TokenStdin) { throw "Persistent shadow run requires the token through stdin" }
|
|
$token = [Console]::In.ReadLine()
|
|
if (-not $token -or $token.Length -lt 40 -or $token.Length -gt 512) {
|
|
throw "Persistent shadow token is missing or malformed"
|
|
}
|
|
|
|
$outputRoot = Resolve-DDirectory $PersistentOutputRoot "Persistent output root"
|
|
$freeBefore = Get-DFreeBytes
|
|
if ($freeBefore -lt ([int64]$FreeGiBFloor * 1GB + 512MB)) {
|
|
throw "D: lacks the guarded persistent-run reserve"
|
|
}
|
|
$containerRunning = docker inspect --format "{{.State.Running}}" $PersistentContainer
|
|
Assert-LastExitCode "Persistent worker inspection"
|
|
if ($containerRunning.Trim().ToLowerInvariant() -ne "true") {
|
|
throw "Persistent worker is not running"
|
|
}
|
|
$outputName = $RequestId
|
|
$request = @{
|
|
request_id = $RequestId
|
|
output_name = $outputName
|
|
token = $token
|
|
max_duration_seconds = $MaximumDurationSeconds
|
|
} | ConvertTo-Json -Compress
|
|
$token = $null
|
|
$client = (
|
|
"import sys,urllib.request,urllib.error;data=sys.stdin.buffer.read();" +
|
|
"request=urllib.request.Request('http://127.0.0.1:{0}/run',data=data," -f $PersistentPort
|
|
) + "headers={'Content-Type':'application/json'},method='POST');" +
|
|
"`ntry:`n response=urllib.request.urlopen(request,timeout=3600); body=response.read(); code=response.status" +
|
|
"`nexcept urllib.error.HTTPError as exc:`n body=exc.read(); code=exc.code" +
|
|
"`nsys.stdout.buffer.write(body);raise SystemExit(0 if code==200 else 22)"
|
|
try {
|
|
$responseJson = $request | & docker exec -i $PersistentContainer python3 -c $client
|
|
$request = $null
|
|
Assert-LastExitCode "Persistent worker request"
|
|
}
|
|
finally {
|
|
$token = $null
|
|
$request = $null
|
|
}
|
|
$response = $responseJson | ConvertFrom-Json
|
|
if ($response.request_id -ne $RequestId -or $response.models_reused -ne $true) {
|
|
throw "Persistent worker response contract changed"
|
|
}
|
|
$staging = Join-Path $outputRoot $outputName
|
|
$resultPath = Join-Path $staging "result.json"
|
|
if (-not (Test-Path -LiteralPath $resultPath -PathType Leaf)) {
|
|
throw "Persistent worker result manifest is missing"
|
|
}
|
|
$result = Get-Content -LiteralPath $resultPath -Raw | ConvertFrom-Json
|
|
if (
|
|
$result.schema_version -ne "missioncore.e15-shadow-inference-result/v1" -or
|
|
$result.result_id -notmatch "^e15-shadow-inference-[a-f0-9]{64}$" -or
|
|
$result.publication_scope -ne "live-shadow-diagnostic-only"
|
|
) { throw "Persistent worker result manifest is incompatible" }
|
|
$derivedRoot = Resolve-DDirectory (Split-Path $outputRoot -Parent) "Runtime derived root"
|
|
$finalRoot = Join-Path $derivedRoot ([string]$result.result_id)
|
|
if (Test-Path -LiteralPath $finalRoot) {
|
|
throw "Immutable persistent-worker result already exists"
|
|
}
|
|
Move-Item -LiteralPath $staging -Destination $finalRoot
|
|
$freeFinal = Get-DFreeBytes
|
|
if ($freeFinal -lt ([int64]$FreeGiBFloor * 1GB)) {
|
|
throw "D: crossed the guarded floor after persistent run"
|
|
}
|
|
Write-Output ("RESULT_ROOT={0}" -f $finalRoot)
|
|
Write-Output ("RESULT_ID={0}" -f $result.result_id)
|
|
Write-Output ("ACCEPTANCE_STATE={0}" -f $result.acceptance_state)
|
|
Write-Output ("RUNNER_EXIT_CODE={0}" -f $response.exit_code)
|
|
Write-Output "MODELS_REUSED=true"
|
|
Write-Output ("DISK_FREE_BYTES_BEFORE={0}" -f $freeBefore)
|
|
Write-Output ("DISK_FREE_BYTES_FINAL={0}" -f $freeFinal)
|