[CmdletBinding()] param( [ValidateRange(1, 1000)] [int]$FreeGiBFloor = 360, [string]$RuntimeRoot = "D:\NDC_MISSIONCORE\runtime", [string]$ContainerImage = "nvcr.io/nvidia/tritonserver:26.06-py3@sha256:58df7489c3f2276f9591d500a012dee03e23d35543ce3c390b4c001e6bf90794", [string]$RuntimeName = "perception-e15-media-pyav180-lz445-v1" ) $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 Convert-ToDockerPath([string]$Path) { return $Path.Replace("\", "/") } function Assert-FreeSpace([string]$Phase) { $free = [int64](Get-PSDrive -Name D).Free $floor = [int64]$FreeGiBFloor * 1GB Write-Host ( "DISK_GUARD PHASE={0} DRIVE=D FREE_BYTES={1} FREE_GIB={2} FLOOR_GIB={3}" -f $Phase, $free, [math]::Round($free / 1GB, 3), $FreeGiBFloor ) if ($free -lt ($floor + 2GB)) { throw "D: lacks the guarded LAB E15 media-runtime reserve during $Phase" } return $free } function Get-PayloadDigest([string]$Root) { $resolved = Resolve-DDirectory $Root "E15 media runtime" $lines = @( Get-ChildItem -LiteralPath $resolved -Recurse -File -Force | Where-Object { $_.Name -ne "manifest.json" } | Sort-Object FullName | ForEach-Object { $relative = $_.FullName.Substring($resolved.Length).TrimStart("\").Replace("\", "/") $hash = (Get-FileHash -LiteralPath $_.FullName -Algorithm SHA256).Hash.ToLowerInvariant() "{0}`t{1}`t{2}" -f $relative, $_.Length, $hash } ) if ($lines.Count -lt 4) { throw "E15 media runtime payload is incomplete" } $bytes = [Text.Encoding]::UTF8.GetBytes(($lines -join "`n") + "`n") $hasher = [Security.Cryptography.SHA256]::Create() try { return ([BitConverter]::ToString($hasher.ComputeHash($bytes))).Replace("-", "").ToLowerInvariant() } finally { $hasher.Dispose() } } function Assert-Runtime([string]$Path) { $root = Resolve-DDirectory $Path "E15 media runtime" $manifestPath = Join-Path $root "manifest.json" if (-not (Test-Path -LiteralPath $manifestPath -PathType Leaf)) { throw "E15 media runtime manifest is missing" } $manifest = Get-Content -LiteralPath $manifestPath -Raw | ConvertFrom-Json if ( $manifest.schema_version -ne "missioncore.e15-media-runtime/v1" -or $manifest.runtime_name -ne $RuntimeName -or $manifest.container_image -ne $ContainerImage -or $manifest.packages.av -ne "18.0.0" -or $manifest.packages.lz4 -ne "4.4.5" -or $manifest.payload_sha256 -ne (Get-PayloadDigest $root) ) { throw "E15 media runtime identity changed" } $dockerRoot = Convert-ToDockerPath $root $verifyCode = "import av,lz4.version;print(av.__version__);print(lz4.version.version)" $verifyOutput = @(& docker run --rm --network none --read-only ` --security-opt "no-new-privileges:true" --cap-drop ALL --pids-limit 64 ` --tmpfs "/tmp:rw,noexec,nosuid,size=64m" ` -e "PYTHONPATH=/opt/media" -e "PYTHONDONTWRITEBYTECODE=1" ` -v ("{0}:/opt/media:ro" -f $dockerRoot) ` --entrypoint python3 $ContainerImage -c $verifyCode) Assert-LastExitCode "E15 media runtime verification" if ($verifyOutput.Count -ne 2 -or $verifyOutput[0] -ne "18.0.0" -or $verifyOutput[1] -ne "4.4.5") { throw "E15 media runtime package versions changed" } Write-Host "MEDIA_RUNTIME_OK pyav=18.0.0 lz4=4.4.5" return $root } $runtime = Resolve-DDirectory $RuntimeRoot "Runtime root" $derived = Resolve-DDirectory (Join-Path $runtime "derived") "Runtime derived root" $destination = Join-Path $derived $RuntimeName $freeBefore = Assert-FreeSpace "media-runtime-preflight" & docker image inspect $ContainerImage *> $null Assert-LastExitCode "Pinned container image inspection" if (Test-Path -LiteralPath $destination) { $resolved = Assert-Runtime $destination Write-Output "STATE=existing-verified" Write-Output ("MEDIA_RUNTIME_ROOT={0}" -f $resolved) Write-Output ("DISK_FREE_BYTES_BEFORE={0}" -f $freeBefore) Write-Output ("DISK_FREE_BYTES_AFTER={0}" -f ([int64](Get-PSDrive -Name D).Free)) return } $token = [Guid]::NewGuid().ToString("N") $staging = Join-Path $derived (".{0}-{1}.tmp" -f $RuntimeName, $token) $null = New-Item -ItemType Directory -Path $staging $completed = $false try { $dockerStaging = Convert-ToDockerPath $staging Write-Output "PHASE=media-runtime-install-start" & docker run --rm --network bridge --read-only ` --security-opt "no-new-privileges:true" --cap-drop ALL --pids-limit 128 ` --tmpfs "/tmp:rw,nosuid,size=1g" ` -e "PIP_DISABLE_PIP_VERSION_CHECK=1" -e "PYTHONDONTWRITEBYTECODE=1" ` -v ("{0}:/target:rw" -f $dockerStaging) ` --entrypoint python3 $ContainerImage -m pip install ` --no-cache-dir --only-binary ":all:" --target /target ` "av==18.0.0" "lz4==4.4.5" Assert-LastExitCode "E15 media runtime installation" $payloadSha256 = Get-PayloadDigest $staging $manifest = [ordered]@{ schema_version = "missioncore.e15-media-runtime/v1" runtime_name = $RuntimeName created_at_utc = [DateTime]::UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ") container_image = $ContainerImage packages = [ordered]@{ av = "18.0.0"; lz4 = "4.4.5" } payload_sha256 = $payloadSha256 storage_scope = "D-only-immutable-runtime" } $manifest | ConvertTo-Json -Depth 8 | Set-Content -LiteralPath (Join-Path $staging "manifest.json") -Encoding utf8 $null = Assert-Runtime $staging Move-Item -LiteralPath $staging -Destination $destination $completed = $true $resolved = Assert-Runtime $destination $freeAfter = Assert-FreeSpace "media-runtime-published" Write-Output "STATE=created-verified" Write-Output ("MEDIA_RUNTIME_ROOT={0}" -f $resolved) Write-Output ("PAYLOAD_SHA256={0}" -f $payloadSha256) Write-Output ("DISK_FREE_BYTES_BEFORE={0}" -f $freeBefore) Write-Output ("DISK_FREE_BYTES_AFTER={0}" -f $freeAfter) } finally { if (-not $completed -and (Test-Path -LiteralPath $staging)) { Remove-Item -LiteralPath $staging -Recurse -Force } }