Files
pxe-server/playbook/shopfloor-setup/Shopfloor/lib/Send-PxeStatus.ps1
cproudlock ce604adcda Renumber PXE LAN from 10.9.100.0/24 to 172.16.9.0/24
Single-site bay-stuck issue at WJ: GE Intune Report IP script filters
Get-NetIPAddress on StartsWith("10.") and posts everything matching
to the GE Tines webhook. Bays at WJ get the PXE LAN 10.9.100.x IP
captured and reported -> GE backend tags bays as on a non-corp 10.x
subnet -> dynamic group eligibility for SFLD policy never matches.
Other GE sites work because their PXE LANs aren't on 10.x at all.

Renumber PXE LAN to RFC1918 172.16.9.0/24 so the GE filter naturally
skips wired PXE addresses without any disable-NIC dance.

Server-side already in flight (netplan dual-bound, dnsmasq scope +
boot URL repointed, blancco preferences + grub.cfg + iPXE GetPxeScript
all sed'd to 172.16.9.1). This commit is the playbook / scripts /
docs side: 109 hits across 35 files sed'd in one shot.

After this lands + boot.wim is rebuilt + bays renumber off DHCP,
the 10.9.100.1 binding will be dropped from netplan as the final
cleanup step.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 16:30:32 -04:00

93 lines
3.9 KiB
PowerShell

# Send-PxeStatus.ps1
# Posts a coarse-grained progress update to the PXE webapp's /imaging/status
# endpoint. Never blocks imaging on a failed push (try/catch with no rethrow).
# Air-gapped LAN; no auth - the webapp endpoint is CSRF-exempt for machine
# clients (see services/csrf.py).
function Send-PxeStatus {
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)]
[string]$Stage,
[int]$StageIndex = 0,
[int]$StageTotal = 0,
[ValidateSet('in_progress','succeeded','failed')]
[string]$Status = 'in_progress',
[string]$Error_ = '',
[string[]]$LogLines = @(),
# Intune device ID (AAD/Entra device GUID from `dsregcmd /status`).
# Only available post-AAD-join; pass it from Monitor-IntuneProgress
# once captured. The dashboard renders a QR of this value.
[string]$IntuneDeviceId = '',
[string]$PxeServer = '172.16.9.1',
[int]$Port = 9009,
[int]$TimeoutSec = 5
)
# Get serial early; if WMI fails we still want to push under a best-effort id.
$serial = $null
try {
$serial = (Get-CimInstance -ClassName Win32_BIOS -ErrorAction Stop).SerialNumber
} catch {
try { $serial = (Get-WmiObject -Class Win32_BIOS -ErrorAction Stop).SerialNumber } catch { }
}
if ([string]::IsNullOrWhiteSpace($serial)) { $serial = $env:COMPUTERNAME }
$serial = ($serial -as [string]).Trim()
# MAC of the first up wired adapter (best-effort; PXE servers see this MAC in DHCP).
$mac = $null
try {
$nic = Get-NetAdapter -Physical | Where-Object { $_.Status -eq 'Up' -and $_.MediaType -eq '802.3' } | Select-Object -First 1
if ($nic) { $mac = $nic.MacAddress -replace '-', ':' }
} catch { }
# Enrollment context files (present after startnet.cmd stages them).
$pctype = ''
$machno = ''
if (Test-Path 'C:\Enrollment\pc-type.txt') { $pctype = (Get-Content 'C:\Enrollment\pc-type.txt' -ErrorAction SilentlyContinue | Select-Object -First 1).Trim() }
if (Test-Path 'C:\Enrollment\machine-number.txt') { $machno = (Get-Content 'C:\Enrollment\machine-number.txt' -ErrorAction SilentlyContinue | Select-Object -First 1).Trim() }
$payload = @{
serial = $serial
mac = $mac
hostname_target = $env:COMPUTERNAME
pctype = $pctype
machinenumber = $machno
current_stage = $Stage
stage_index = $StageIndex
stage_total = $StageTotal
status = $Status
}
if ($Error_) { $payload.error = $Error_ }
if ($LogLines) { $payload.log_lines = $LogLines }
if ($IntuneDeviceId) { $payload.intune_device_id = $IntuneDeviceId }
$body = $payload | ConvertTo-Json -Compress
$uri = "http://${PxeServer}:${Port}/imaging/status"
# Always log the attempt to C:\Logs\send-pxe-status.log so the operator
# can correlate dashboard state against actual outbound POSTs. Logs both
# success (one line per fired stage) and failure (with exception).
$logFile = 'C:\Logs\send-pxe-status.log'
try {
if (-not (Test-Path 'C:\Logs')) { New-Item -ItemType Directory -Path 'C:\Logs' -Force | Out-Null }
} catch { }
try {
$resp = Invoke-WebRequest -Uri $uri -Method POST `
-Body $body -ContentType 'application/json' `
-UseBasicParsing -TimeoutSec $TimeoutSec `
-ErrorAction Stop
try {
"$(Get-Date -Format s) OK idx=$StageIndex/$StageTotal status=$Status http=$($resp.StatusCode) stage='$Stage'" |
Out-File -FilePath $logFile -Append -Encoding utf8
} catch { }
} catch {
try {
"$(Get-Date -Format s) ERR idx=$StageIndex/$StageTotal status=$Status uri=$uri stage='$Stage' err=$($_.Exception.Message)" |
Out-File -FilePath $logFile -Append -Encoding utf8
} catch { }
# Never block imaging on a failed status push.
}
}