webapp/imaging: rewind detection + WinPE-phase status push
services/imaging_status.py - if a new POST arrives with stage_index <= 1 that is lower than the cached stage_index, OR the previous run already finished (status=succeeded|failed), reset the session: clear log_tail, mint a fresh started_at, drop the status field so the in_progress default re-applies. Preserves serial + records the previous run's last_updated under previous_run_at for audit. Without this, a reimage on the same bay would leave a stale 6/8 "succeeded" card visible until the new run progressed past that index. playbook/startnet.cmd - one-line PowerShell POST after the PXE menu choice + enrollment-share mount, before PESetup.exe waits to start. Captures BIOS serial via wmic, MAC via Get-NetAdapter, and posts: stage_index=2, current_stage="WinPE: PESetup / WIM apply". Best-effort; try/catch swallows any network failure so a missing webapp never blocks imaging. PXE clients will now appear on the /imaging dashboard during WinPE phase instead of only post-PPKG. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -85,6 +85,24 @@ if "%ges_choice%"=="7" set PCTYPE=gea-shopfloor-heattreat
|
||||
if "%ges_choice%"=="8" set PCTYPE=gea-shopfloor-waxtrace
|
||||
if "%ges_choice%"=="9" set PCTYPE=gea-shopfloor-display
|
||||
if "%PCTYPE%"=="" goto gea_shopfloor_submenu
|
||||
if "%PCTYPE%"=="gea-shopfloor-display" goto display_submenu
|
||||
goto enroll_menu
|
||||
|
||||
:display_submenu
|
||||
cls
|
||||
echo.
|
||||
echo ========================================
|
||||
echo Display Kiosk Sub-Type
|
||||
echo ========================================
|
||||
echo.
|
||||
echo 1. Dashboard (shop floor metrics dashboard)
|
||||
echo 2. Lobby Display (lobby information screen)
|
||||
echo.
|
||||
set DISPLAYTYPE=
|
||||
set /p disp_choice=Enter your choice (1-2):
|
||||
if "%disp_choice%"=="1" set DISPLAYTYPE=Dashboard
|
||||
if "%disp_choice%"=="2" set DISPLAYTYPE=Lobby
|
||||
if "%DISPLAYTYPE%"=="" goto display_submenu
|
||||
goto enroll_menu
|
||||
|
||||
:enroll_menu
|
||||
@@ -107,8 +125,8 @@ REM --- PPKG configuration (constructed at menu time, see docs) ---
|
||||
REM Vendor ships one source PPKG; we construct the BPRT-tagged filename
|
||||
REM by filling in Office, Region, Expiry, Version on the target copy.
|
||||
REM Update SOURCE_PPKG + PPKG_VER when a new PPKG is released.
|
||||
set SOURCE_PPKG=GCCH_Prod_SFLD_v4.12.ppkg
|
||||
set PPKG_VER=v4.12
|
||||
set SOURCE_PPKG=GCCH_Prod_SFLD_v4.14.ppkg
|
||||
set PPKG_VER=v4.14
|
||||
set PPKG_EXP=20260831
|
||||
set REGION=US
|
||||
|
||||
@@ -125,13 +143,12 @@ set PPKG=
|
||||
if not "%OFFICE%"=="" set PPKG=GCCH_Prod_SFLD_%OFFICE%_%REGION%_Exp_%PPKG_EXP%_%PPKG_VER%.ppkg
|
||||
|
||||
REM --- 2026-05-04 rename reorg: PCTYPE is set by gea_shopfloor_submenu above
|
||||
REM (single string, e.g. gea-shopfloor-collections). Old per-type submenus
|
||||
REM (Standard sub-type, Display sub-type) are gone - flatten via the new
|
||||
REM gea-shopfloor-* names. PCSUBTYPE / DISPLAYTYPE are no longer written
|
||||
REM (pc-subtype.txt / display-type.txt deprecated). Configure-PC.ps1 still
|
||||
REM looks up site-config.json profiles via the single full string.
|
||||
REM (single string, e.g. gea-shopfloor-collections). pc-subtype.txt is no
|
||||
REM longer written. DISPLAYTYPE IS still written (display-type.txt) when
|
||||
REM PCTYPE=gea-shopfloor-display because Install-KioskApp.cmd needs Lobby
|
||||
REM vs Dashboard to choose installer + Get-PCProfile builds Display-{type}
|
||||
REM profile key.
|
||||
set PCSUBTYPE=
|
||||
set DISPLAYTYPE=
|
||||
|
||||
REM --- Machine number (collections + nocollections only; other variants don't use one) ---
|
||||
set MACHINENUM=9999
|
||||
@@ -228,6 +245,15 @@ goto end
|
||||
|
||||
:end
|
||||
echo.
|
||||
|
||||
REM --- Push initial "WinPE staging" status to PXE webapp ---
|
||||
REM Best-effort POST so the imaging dashboard shows this bay during the
|
||||
REM WinPE / WIM-apply phase, BEFORE Run-ShopfloorSetup.ps1 takes over the
|
||||
REM status updates post-PPKG. Identifies the session by BIOS serial.
|
||||
REM Errors are swallowed - never block imaging on a status push.
|
||||
for /f "tokens=2 delims==" %%S in ('wmic bios get serialnumber /value 2^>nul ^| find "="') do set BIOS_SERIAL=%%S
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -Command "try { $body = @{ serial=$env:BIOS_SERIAL; mac=((Get-NetAdapter -Physical | Where-Object { $_.Status -eq 'Up' } | Select-Object -First 1).MacAddress -replace '-',':'); pctype=$env:PCTYPE; current_stage='WinPE: PESetup / WIM apply'; stage_index=2; stage_total=8; status='in_progress' } | ConvertTo-Json -Compress; Invoke-WebRequest -Uri 'http://10.9.100.1:9009/imaging/status' -Method POST -Body $body -ContentType 'application/json' -UseBasicParsing -TimeoutSec 5 | Out-Null } catch { }"
|
||||
|
||||
echo Waiting for PESetup.exe to start...
|
||||
:wait_start
|
||||
ping -n 3 127.0.0.1 >NUL
|
||||
@@ -279,10 +305,11 @@ echo Manual fallback created at W:\enroll.cmd
|
||||
REM --- Copy shopfloor PC type setup scripts ---
|
||||
if "%PCTYPE%"=="" goto cleanup_enroll
|
||||
echo %PCTYPE%> W:\Enrollment\pc-type.txt
|
||||
REM 2026-05-04 rename reorg: pc-subtype.txt and display-type.txt no longer
|
||||
REM written. PCTYPE is a single full string ("gea-shopfloor-collections",
|
||||
REM "gea-shopfloor-display", etc.). pcSubType-aware code paths fall back
|
||||
REM to empty string and are handled as alias-resolution-only.
|
||||
REM 2026-05-04 rename reorg: pc-subtype.txt no longer written.
|
||||
REM display-type.txt IS still written for gea-shopfloor-display because
|
||||
REM Install-KioskApp.cmd reads it to pick Lobby vs Dashboard installer
|
||||
REM and Get-PCProfile.ps1 reads it to build the Display-{type} profile key.
|
||||
if not "%DISPLAYTYPE%"=="" echo %DISPLAYTYPE%> W:\Enrollment\display-type.txt
|
||||
if not "%MACHINENUM%"=="" echo %MACHINENUM%> W:\Enrollment\machine-number.txt
|
||||
copy /Y "Y:\shopfloor-setup\Run-ShopfloorSetup.ps1" "W:\Enrollment\Run-ShopfloorSetup.ps1"
|
||||
REM --- Always copy Shopfloor baseline scripts ---
|
||||
@@ -299,6 +326,13 @@ if exist "Y:\shopfloor-setup\common" (
|
||||
xcopy /E /Y /I "Y:\shopfloor-setup\common" "W:\Enrollment\shopfloor-setup\common\"
|
||||
echo Copied common setup files.
|
||||
)
|
||||
REM --- Copy _ntlars-backups (147 per-bay .reg files restored by gea-shopfloor-{collections,nocollections}\03-RestoreEDncConfig.ps1) ---
|
||||
REM Same root level as common/, referenced by 03-RestoreEDncConfig.ps1 via Join-Path $PSScriptRoot '..\_ntlars-backups'.
|
||||
if exist "Y:\shopfloor-setup\_ntlars-backups" (
|
||||
mkdir W:\Enrollment\shopfloor-setup\_ntlars-backups 2>NUL
|
||||
xcopy /E /Y /I "Y:\shopfloor-setup\_ntlars-backups" "W:\Enrollment\shopfloor-setup\_ntlars-backups\"
|
||||
echo Copied _ntlars-backups.
|
||||
)
|
||||
REM --- Copy type-specific scripts on top of baseline ---
|
||||
if exist "Y:\shopfloor-setup\%PCTYPE%" (
|
||||
mkdir "W:\Enrollment\shopfloor-setup\%PCTYPE%" 2>NUL
|
||||
|
||||
@@ -66,12 +66,31 @@ def update_session(payload: dict) -> dict:
|
||||
except (json.JSONDecodeError, OSError):
|
||||
state = {}
|
||||
|
||||
# Reimage detection: if the new payload's stage_index is <= 1 and we have
|
||||
# an existing session that was further along, treat this as a fresh run.
|
||||
# Clear log_tail + reset started_at; preserve serial. Without this, a
|
||||
# reimage on the same bay leaves stale "succeeded" / high-idx state on
|
||||
# the dashboard until the new run progresses past idx 1.
|
||||
if state:
|
||||
try:
|
||||
old_idx = int(state.get("stage_index") or 0)
|
||||
new_idx = int(payload.get("stage_index") or 0)
|
||||
except (TypeError, ValueError):
|
||||
old_idx, new_idx = 0, 0
|
||||
rewind = new_idx > 0 and new_idx < old_idx and new_idx <= 1
|
||||
prev_done = state.get("status") in ("succeeded", "failed")
|
||||
if rewind or (prev_done and new_idx > 0 and new_idx <= 1):
|
||||
state = {"serial": serial, "previous_run_at": state.get("last_updated"), "log_tail": []}
|
||||
|
||||
if not state:
|
||||
state = {
|
||||
"serial": serial,
|
||||
"started_at": _now_iso(),
|
||||
"log_tail": [],
|
||||
}
|
||||
elif "started_at" not in state:
|
||||
# Fresh state after a rewind - mint a new started_at.
|
||||
state["started_at"] = _now_iso()
|
||||
|
||||
# Append any new log lines (preserve old; cap to LOG_TAIL_MAX).
|
||||
new_lines = payload.pop("log_lines", None)
|
||||
|
||||
Reference in New Issue
Block a user