Ask tenant + PC purpose at the PXE menu; add the missing 3D kiosk display option
PC PURPOSE / TENANT FOR STANDARD AND ENGINEER
The capability was already there - the media carries all six MCL packages
(PERS/SH/LOAN x GCCH/RoW) and Start-BulkEnrollOrchestrator.ps1 picks one from
whatever Select-PCConfig.ps1 returns. The problem was WHEN it asks: a GUI at
first logon, so an otherwise unattended build stops at a dialog until someone
walks over.
Now startnet asks after Standard/Engineer is chosen, while the tech who knows
what the machine is for is standing at it, and writes {Tenant}_{Purpose} to
C:\Enrollment\pc-config.txt. A shim at the path the orchestrator already calls
returns that value and falls through to the vendor dialog when it is absent or
malformed - so "ask at first logon" stays available and bays imaged before this
are unaffected. The vendor script is preserved as Select-PCConfig-vendor.ps1;
replace THAT when the vendor ships a new one.
The tenant is not cosmetic. Insert-BPRTToPPKG.ps1 matches the bulk token on
Tenant AND Purpose, so this selects which token gets injected.
ONLY THE CHOICE IS PRE-SEEDED, deliberately. Injection stays at first logon
because it fetches an encrypted token table from mcl.dwcdn.geaerospace.com,
unreachable from the isolated imaging LAN - which is also why routing MCL
packages through run-enrollment.ps1 would not work: provtool would get a package
whose token is still the Exp_XXXXXXXX placeholder and join nothing.
Standard/engineer previously skipped staging entirely (no ppkg, no PCTYPE), so
the staging gate now also admits PCCONFIG.
3D PARTS KIOSK
The display submenu offered Dashboard and Lobby only. The GE-Enforce display
scope has always had a third entry - 3DPrintRoom -> /shopdb/parts-kiosk - so a
parts kiosk could only be set by editing display-type.txt by hand after imaging.
Added as option 3. The value is a KEY into that map, so the spelling matches
exactly.
Verified: startnet parens balance, every goto resolves, 994 CRLF lines with no
bare LF; shim parses clean. Deployed - boot.wim 4d16c946, shim staged with the
vendor dialog preserved.
This commit is contained in:
84
playbook/shopfloor-setup/BPRT/Select-PCConfig.ps1
Normal file
84
playbook/shopfloor-setup/BPRT/Select-PCConfig.ps1
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Return the tenant + PC purpose, pre-seeded if WinPE already asked.
|
||||||
|
|
||||||
|
.DESCRIPTION
|
||||||
|
Start-BulkEnrollOrchestrator.ps1 calls this at first logon and captures
|
||||||
|
stdout:
|
||||||
|
|
||||||
|
$pcType = powershell.exe -File 'C:\Deploy\Applications\BPRT\Select-PCConfig.ps1' -LogoPath '...'
|
||||||
|
|
||||||
|
It uses the answer twice - to pick which MCL package to apply, and to select
|
||||||
|
which bulk token Insert-BPRTToPPKG.ps1 injects (it matches on Tenant AND
|
||||||
|
Purpose). The vendor's version asks with a GUI, which means an otherwise
|
||||||
|
unattended build stops at a dialog until somebody walks over.
|
||||||
|
|
||||||
|
startnet.cmd now asks the same question at the PXE menu, while the tech who
|
||||||
|
knows what the machine is for is standing at it, and writes the answer to
|
||||||
|
C:\Enrollment\pc-config.txt. This shim returns that value when present and
|
||||||
|
falls through to the vendor dialog when it is not - so nothing is lost if the
|
||||||
|
tech picks "ask at first logon", or on a bay imaged before this existed.
|
||||||
|
|
||||||
|
ONLY the choice is pre-seeded. Token injection still happens at first logon:
|
||||||
|
Insert-BPRTToPPKG.ps1 fetches an encrypted token table from
|
||||||
|
mcl.dwcdn.geaerospace.com, which is unreachable from the isolated imaging
|
||||||
|
LAN.
|
||||||
|
|
||||||
|
.OUTPUTS
|
||||||
|
"{Tenant}_{PCType}" - Tenant GCCH|RoW, PCType PERS|SH|LOAN.
|
||||||
|
Identical contract to the vendor script.
|
||||||
|
|
||||||
|
.NOTES
|
||||||
|
The vendor script is kept alongside as Select-PCConfig-vendor.ps1. Replace
|
||||||
|
THAT file when the vendor ships a new one; this shim only needs changing if
|
||||||
|
the return contract changes.
|
||||||
|
#>
|
||||||
|
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $false)]
|
||||||
|
[string]$LogoPath
|
||||||
|
)
|
||||||
|
|
||||||
|
$seedFile = 'C:\Enrollment\pc-config.txt'
|
||||||
|
$vendor = Join-Path $PSScriptRoot 'Select-PCConfig-vendor.ps1'
|
||||||
|
$logDir = 'C:\Logs\BPRT\Orchestrator'
|
||||||
|
$shimLog = Join-Path $logDir 'Select-PCConfig-shim.log'
|
||||||
|
|
||||||
|
function Log {
|
||||||
|
param([string]$Message)
|
||||||
|
try {
|
||||||
|
New-Item -ItemType Directory -Path $logDir -Force -ErrorAction SilentlyContinue | Out-Null
|
||||||
|
Add-Content -Path $shimLog -Value ("{0} {1}" -f (Get-Date -Format 'yyyy-MM-dd HH:mm:ss'), $Message)
|
||||||
|
} catch { }
|
||||||
|
}
|
||||||
|
|
||||||
|
# Valid values, so a typo in the seed file falls back to the dialog instead of
|
||||||
|
# handing the orchestrator a string that matches no token and no package.
|
||||||
|
$validTenants = @('GCCH', 'RoW')
|
||||||
|
$validPurposes = @('PERS', 'SH', 'LOAN')
|
||||||
|
|
||||||
|
if (Test-Path $seedFile) {
|
||||||
|
$seed = (Get-Content $seedFile -First 1 -ErrorAction SilentlyContinue)
|
||||||
|
if ($seed) { $seed = $seed.Trim() }
|
||||||
|
$parts = if ($seed) { $seed.Split('_') } else { @() }
|
||||||
|
|
||||||
|
if ($parts.Count -eq 2 -and $validTenants -contains $parts[0] -and $validPurposes -contains $parts[1]) {
|
||||||
|
Log "Pre-seeded value '$seed' from $seedFile - dialog skipped."
|
||||||
|
Write-Output $seed
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
Log "Ignoring malformed pre-seed '$seed' in $seedFile; falling back to the dialog."
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Test-Path $vendor) {
|
||||||
|
Log "No usable pre-seed; showing the vendor dialog."
|
||||||
|
if ($LogoPath) { & $vendor -LogoPath $LogoPath }
|
||||||
|
else { & $vendor }
|
||||||
|
exit $LASTEXITCODE
|
||||||
|
}
|
||||||
|
|
||||||
|
# Neither a seed nor the vendor dialog. Say so in the log rather than returning
|
||||||
|
# something invented - the orchestrator would inject the wrong token.
|
||||||
|
Log "ERROR: no pre-seed at $seedFile and no vendor script at $vendor."
|
||||||
|
exit 1
|
||||||
@@ -47,9 +47,59 @@ REM --- Shopfloor images (3,6,7) need GCCH enrollment + (for 3) PC-type sub-menu
|
|||||||
REM Choice 3 = GEA Shopfloor: drill into sub-menu first to pick the gea-shopfloor-*
|
REM Choice 3 = GEA Shopfloor: drill into sub-menu first to pick the gea-shopfloor-*
|
||||||
REM sub-category, THEN the office menu, THEN machine number for collections+nocollections.
|
REM sub-category, THEN the office menu, THEN machine number for collections+nocollections.
|
||||||
set PPKG=
|
set PPKG=
|
||||||
|
set PCCONFIG=
|
||||||
if "%choice%"=="3" goto gea_shopfloor_submenu
|
if "%choice%"=="3" goto gea_shopfloor_submenu
|
||||||
if "%choice%"=="6" goto enroll_menu
|
if "%choice%"=="6" goto enroll_menu
|
||||||
if "%choice%"=="7" goto enroll_menu
|
if "%choice%"=="7" goto enroll_menu
|
||||||
|
REM Standard and engineer enrol through the vendor orchestrator, which asks for
|
||||||
|
REM tenant + PC purpose with a GUI at first logon. Ask here instead, while the
|
||||||
|
REM tech who knows what the machine is for is standing at it, and pre-seed the
|
||||||
|
REM answer so the dialog never appears. See :gea_purpose_submenu.
|
||||||
|
if "%choice%"=="1" goto gea_purpose_submenu
|
||||||
|
if "%choice%"=="2" goto gea_purpose_submenu
|
||||||
|
goto enroll_staged
|
||||||
|
|
||||||
|
:gea_purpose_submenu
|
||||||
|
cls
|
||||||
|
echo.
|
||||||
|
echo ========================================
|
||||||
|
echo PC Purpose - Entra enrollment
|
||||||
|
echo ========================================
|
||||||
|
echo.
|
||||||
|
echo 1. Single-User PC (one assigned person)
|
||||||
|
echo 2. Shared PC (multiple users)
|
||||||
|
echo 3. Loaner PC (temporary assignment)
|
||||||
|
echo.
|
||||||
|
echo 4. Ask at first logon (show the vendor dialog instead)
|
||||||
|
echo.
|
||||||
|
set PCPURPOSE=
|
||||||
|
set /p purp_choice=Enter your choice (1-4):
|
||||||
|
if "%purp_choice%"=="1" set PCPURPOSE=PERS
|
||||||
|
if "%purp_choice%"=="2" set PCPURPOSE=SH
|
||||||
|
if "%purp_choice%"=="3" set PCPURPOSE=LOAN
|
||||||
|
if "%purp_choice%"=="4" goto enroll_staged
|
||||||
|
if "%PCPURPOSE%"=="" goto gea_purpose_submenu
|
||||||
|
|
||||||
|
:gea_tenant_submenu
|
||||||
|
cls
|
||||||
|
echo.
|
||||||
|
echo ========================================
|
||||||
|
echo Entra Tenant
|
||||||
|
echo ========================================
|
||||||
|
echo.
|
||||||
|
echo 1. GCC High (GCCH - US)
|
||||||
|
echo 2. Rest of World (RoW)
|
||||||
|
echo.
|
||||||
|
REM The tenant is not cosmetic: Insert-BPRTToPPKG.ps1 matches the bulk token by
|
||||||
|
REM Tenant AND Purpose, so this picks which token gets injected.
|
||||||
|
set PCTENANT=
|
||||||
|
set /p ten_choice=Enter your choice (1-2):
|
||||||
|
if "%ten_choice%"=="1" set PCTENANT=GCCH
|
||||||
|
if "%ten_choice%"=="2" set PCTENANT=RoW
|
||||||
|
if "%PCTENANT%"=="" goto gea_tenant_submenu
|
||||||
|
set PCCONFIG=%PCTENANT%_%PCPURPOSE%
|
||||||
|
echo.
|
||||||
|
echo PC config: %PCCONFIG%
|
||||||
goto enroll_staged
|
goto enroll_staged
|
||||||
|
|
||||||
:gea_shopfloor_submenu
|
:gea_shopfloor_submenu
|
||||||
@@ -163,11 +213,21 @@ echo ========================================
|
|||||||
echo.
|
echo.
|
||||||
echo 1. Dashboard (shop floor metrics dashboard)
|
echo 1. Dashboard (shop floor metrics dashboard)
|
||||||
echo 2. Lobby Display (lobby information screen)
|
echo 2. Lobby Display (lobby information screen)
|
||||||
|
echo 3. 3D Parts Kiosk (printed-parts kiosk)
|
||||||
echo.
|
echo.
|
||||||
|
REM These values are KEYS into the GE-Enforce display scope
|
||||||
|
REM (shopdb-flask plugins/geenforce/seed_display_scope.py):
|
||||||
|
REM Dashboard -> /shopdb/shopfloor, Lobby -> /shopdb/tv,
|
||||||
|
REM 3DPrintRoom -> /shopdb/parts-kiosk
|
||||||
|
REM They are written to C:\Enrollment\display-type.txt and the dispatcher reads
|
||||||
|
REM that as its fallback when the server has no IP-based role for the device, so
|
||||||
|
REM the spelling must match the map exactly. 3DPrintRoom was in the map but had
|
||||||
|
REM no menu entry, so a parts kiosk could only be set by hand after imaging.
|
||||||
set DISPLAYTYPE=
|
set DISPLAYTYPE=
|
||||||
set /p disp_choice=Enter your choice (1-2):
|
set /p disp_choice=Enter your choice (1-3):
|
||||||
if "%disp_choice%"=="1" set DISPLAYTYPE=Dashboard
|
if "%disp_choice%"=="1" set DISPLAYTYPE=Dashboard
|
||||||
if "%disp_choice%"=="2" set DISPLAYTYPE=Lobby
|
if "%disp_choice%"=="2" set DISPLAYTYPE=Lobby
|
||||||
|
if "%disp_choice%"=="3" set DISPLAYTYPE=3DPrintRoom
|
||||||
if "%DISPLAYTYPE%"=="" goto display_submenu
|
if "%DISPLAYTYPE%"=="" goto display_submenu
|
||||||
goto enroll_menu
|
goto enroll_menu
|
||||||
|
|
||||||
@@ -410,7 +470,9 @@ if errorlevel 1 goto wait_start
|
|||||||
echo PESetup.exe is running. Waiting for imaging to complete...
|
echo PESetup.exe is running. Waiting for imaging to complete...
|
||||||
|
|
||||||
REM --- Copy enrollment package and shopfloor setup as soon as Windows partition appears ---
|
REM --- Copy enrollment package and shopfloor setup as soon as Windows partition appears ---
|
||||||
if "%PPKG%"=="" if "%PCTYPE%"=="" goto wait_finish
|
REM PCCONFIG is here so standard/engineer builds still reach the volume wait:
|
||||||
|
REM they select no ppkg and no PCTYPE, but they do need pc-config.txt written.
|
||||||
|
if "%PPKG%"=="" if "%PCTYPE%"=="" if "%PCCONFIG%"=="" goto wait_finish
|
||||||
REM --- Wait for the volume PESetup applies Windows to -----------------------
|
REM --- Wait for the volume PESetup applies Windows to -----------------------
|
||||||
REM PESetup hardcodes W: in nine places - every copy destination, both DISM
|
REM PESetup hardcodes W: in nine places - every copy destination, both DISM
|
||||||
REM offline sessions, bcdboot and reagentc - and CREATES it during its own disk
|
REM offline sessions, bcdboot and reagentc - and CREATES it during its own disk
|
||||||
@@ -472,7 +534,24 @@ REM the >> redirect after the screen echo. robocopy /LOG+ appends its
|
|||||||
REM own output directly.
|
REM own output directly.
|
||||||
set STAGELOG=%OSDRIVE%\Enrollment\winpe-staging.log
|
set STAGELOG=%OSDRIVE%\Enrollment\winpe-staging.log
|
||||||
echo [%DATE% %TIME%] WinPE staging started >> "%STAGELOG%"
|
echo [%DATE% %TIME%] WinPE staging started >> "%STAGELOG%"
|
||||||
echo PCTYPE=%PCTYPE% PPKG=%PPKG% MACHINENUM=%MACHINENUM% CMMID=%CMMID% >> "%STAGELOG%"
|
echo PCTYPE=%PCTYPE% PPKG=%PPKG% MACHINENUM=%MACHINENUM% CMMID=%CMMID% PCCONFIG=%PCCONFIG% >> "%STAGELOG%"
|
||||||
|
|
||||||
|
REM --- Pre-seed the tenant + PC purpose for the enrollment orchestrator -----
|
||||||
|
REM Start-BulkEnrollOrchestrator.ps1 asks for this with a GUI at first logon
|
||||||
|
REM (Select-PCConfig.ps1) and uses the answer twice: to pick which MCL package
|
||||||
|
REM to apply, and to select which bulk token Insert-BPRTToPPKG.ps1 injects -
|
||||||
|
REM it matches on Tenant AND Purpose. Writing the answer here lets the shim
|
||||||
|
REM return it non-interactively, so an unattended build never stops on a dialog.
|
||||||
|
REM Format is exactly what the vendor dialog returns: {Tenant}_{Purpose},
|
||||||
|
REM e.g. GCCH_PERS, GCCH_SH, RoW_LOAN.
|
||||||
|
REM Only the CHOICE is pre-seeded. Token injection still happens at first logon
|
||||||
|
REM because it fetches an encrypted token table from mcl.dwcdn.geaerospace.com,
|
||||||
|
REM which is unreachable from this isolated imaging LAN.
|
||||||
|
if not "%PCCONFIG%"=="" (
|
||||||
|
echo %PCCONFIG%> %OSDRIVE%\Enrollment\pc-config.txt
|
||||||
|
echo Pre-seeded PC config %PCCONFIG% for the enrollment orchestrator.
|
||||||
|
echo [%TIME%] Wrote pc-config.txt=%PCCONFIG% >> "%STAGELOG%"
|
||||||
|
)
|
||||||
|
|
||||||
REM --- Copy site config (drives site-specific values in all setup scripts) ---
|
REM --- Copy site config (drives site-specific values in all setup scripts) ---
|
||||||
if exist "Y:\config\site-config.json" (
|
if exist "Y:\config\site-config.json" (
|
||||||
|
|||||||
Reference in New Issue
Block a user