Files
pxe-server/playbook/shopfloor-setup/gea-shopfloor-keyence/09-Setup-Keyence.ps1
cproudlock 9122b28c31 webapp: imaging progress dashboard + serial column on reports list
Adds end-to-end progress tracking for PXE imaging sessions and surfaces
each Blancco report's BIOS serial in the report list.

webapp:
  * services/imaging_status.py - JSON-per-serial state store under
    IMAGING_DIR (default /var/log/pxe-imaging). Atomic write via
    tempfile + rename. log_tail capped at 50 lines. Merges partial
    updates so clients can post just the current_stage tick.
  * config.py - new IMAGING_DIR env-overridable path.
  * services/csrf.py - explicit exempt list for machine-to-machine
    endpoints; /imaging/status is the first entry. Air-gapped LAN;
    trust-by-network for client posts.
  * app.py - four new routes:
      GET  /imaging               dashboard (renders all sessions)
      POST /imaging/status        client status push (JSON body)
      GET  /imaging/<serial>.json raw session JSON for ad-hoc polling
      POST /imaging/delete/<s>    clear a session from the dashboard
    Also parses each Blancco XML in the /reports list to surface
    system.serial + system.model columns.
  * templates/imaging.html - Bootstrap dashboard with per-session
    cards (state badge, progress bar, stage idx/total, mac, elapsed,
    log tail). meta http-equiv refresh=5 for auto-tick.
  * templates/base.html - new "Imaging Progress" nav entry.
  * templates/reports.html - Serial + Model columns added.

playbook:
  * shopfloor-setup/Shopfloor/lib/Send-PxeStatus.ps1 - new helper.
    Dot-source this then call Send-PxeStatus -Stage X -StageIndex N
    -StageTotal M from any stage script. BIOS serial via CIM, MAC via
    Get-NetAdapter, pctype + machinenumber from C:\Enrollment.
    Failures are swallowed to a local log so a network blip doesn't
    block imaging.
  * shopfloor-setup/Run-ShopfloorSetup.ps1 - dot-sources helper +
    posts at three coarse milestones (start, PPKG enrollment,
    handoff to Monitor-IntuneProgress).
  * shopfloor-setup/gea-shopfloor-keyence/09-Setup-Keyence.ps1 -
    posts at session start + after Install-FromManifest with
    succeeded/failed status derived from $rc. Other 09-Setup-*.ps1
    scripts can follow the same pattern.

ID is BIOS serial (stable across WinPE -> Windows transition and
across reboots, unlike hostname which is random pre-PPKG). Operator
already knows the serial of the bay they imaged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 10:07:18 -04:00

100 lines
4.5 KiB
PowerShell

# 09-Setup-Keyence.ps1 - Keyence type setup (runs during shopfloor-setup phase).
#
# Performs the imaging-time install of Keyence VR-6000 Series Software MSI +
# KEYENCE VR Series USB driver from the staged bundle. Ongoing enforcement
# is handled by GE-Enforce (registered separately in Run-ShopfloorSetup.ps1)
# reading keyence/manifest.json from the tsgwp00525 share.
#
# Layout at $PSScriptRoot (xcopied by startnet.cmd only for PCTYPE=Keyence):
# keyence-manifest.json
# 09-Setup-Keyence.ps1 (this file)
# installers\VR-6000 Series Software.msi
# drivers\keyence_vr_series.inf (+ cat + amd64\{Wdf,WinUsb}CoInstaller*.dll)
#
# Library lookup: the imaging-time install uses the common Install-FromManifest
# library at ..\common\lib\Install-FromManifest.ps1 (relative to $PSScriptRoot).
#
# Log: C:\Logs\Keyence\09-Setup-Keyence.log
# C:\Logs\Keyence\install.log (written by Install-FromManifest)
$ErrorActionPreference = 'Continue'
$manifestPath = Join-Path $PSScriptRoot 'keyence-manifest.json'
$libSource = Join-Path $PSScriptRoot '..\common\lib\Install-FromManifest.ps1'
$logDir = 'C:\Logs\Keyence'
$installLog = Join-Path $logDir 'install.log'
$transcriptLog = Join-Path $logDir '09-Setup-Keyence.log'
if (-not (Test-Path $logDir)) {
New-Item -Path $logDir -ItemType Directory -Force | Out-Null
}
try { Start-Transcript -Path $transcriptLog -Append -Force | Out-Null } catch {}
function Write-KeyenceLog {
param([string]$Message, [string]$Level = 'INFO')
$stamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
Write-Host "[$stamp] [$Level] $Message"
}
Write-KeyenceLog "================================================================"
Write-KeyenceLog "=== Keyence Setup (imaging-time) session start (PID $PID) ==="
Write-KeyenceLog "Running as: $([System.Security.Principal.WindowsIdentity]::GetCurrent().Name)"
Write-KeyenceLog "Script root: $PSScriptRoot"
Write-KeyenceLog "================================================================"
# Status push to PXE webapp - best-effort, never blocks imaging.
$pxeStatusLib = Join-Path $PSScriptRoot '..\Shopfloor\lib\Send-PxeStatus.ps1'
if (Test-Path $pxeStatusLib) {
try { . $pxeStatusLib; Send-PxeStatus -Stage '09-Setup-Keyence: starting' -StageIndex 5 -StageTotal 8 } catch { }
}
# Diagnostic dump
foreach ($file in @('pc-type.txt','pc-subtype.txt','machine-number.txt')) {
$path = "C:\Enrollment\$file"
if (Test-Path -LiteralPath $path) {
$content = (Get-Content -LiteralPath $path -First 1 -ErrorAction SilentlyContinue).Trim()
Write-KeyenceLog " $file = $content"
} else {
Write-KeyenceLog " $file = (not present)"
}
}
# ============================================================================
# Step 1: Install via manifest (imaging-time)
# ============================================================================
if (-not (Test-Path $manifestPath)) {
Write-KeyenceLog "keyence-manifest.json not found at $manifestPath" "ERROR"
} elseif (-not (Test-Path $libSource)) {
Write-KeyenceLog "Install-FromManifest.ps1 not found at $libSource" "ERROR"
} else {
Write-KeyenceLog "Running Install-FromManifest (InstallerRoot=$PSScriptRoot)"
& $libSource -ManifestPath $manifestPath -InstallerRoot $PSScriptRoot -LogFile $installLog
$rc = $LASTEXITCODE
Write-KeyenceLog "Install-FromManifest returned $rc"
}
# ============================================================================
# Step 2: OpenText auto-start at login (HostExplorer "WJ Shopfloor" session)
# ============================================================================
$autoStartLib = Join-Path $PSScriptRoot '..\Shopfloor\lib\Set-OpenTextAutoStart.ps1'
if (Test-Path -LiteralPath $autoStartLib) {
Write-KeyenceLog "Calling $autoStartLib"
& $autoStartLib
} else {
Write-KeyenceLog "Set-OpenTextAutoStart.ps1 not found at $autoStartLib - OpenText auto-start NOT configured" 'WARN'
}
if (Get-Command Send-PxeStatus -ErrorAction SilentlyContinue) {
$finalStatus = if ($rc -eq 0) { 'in_progress' } else { 'failed' }
$finalErr = if ($rc -ne 0) { "Install-FromManifest exit $rc" } else { '' }
Send-PxeStatus -Stage '09-Setup-Keyence: complete' -StageIndex 6 -StageTotal 8 -Status $finalStatus -Error_ $finalErr
}
Write-KeyenceLog "================================================================"
Write-KeyenceLog "=== Keyence Setup session end ==="
Write-KeyenceLog "================================================================"
try { Stop-Transcript | Out-Null } catch {}