shopfloor: CMM PC-DMIS version gate, ShopDB reporter fixes, staging self-heal

- lib Install-FromManifest 2.5->2.6: add _CmmVersion per-entry filter (reads
  C:\Enrollment\cmm\version.txt). Lifted the version gate out of 09-Setup-CMM
  into the shared lib so imaging and GE-Enforce apply it identically and cannot
  drift (root cause of PC-DMIS 2016 installing on every CMM).
- Install-goCMMSettings: canonicalize the part-group share host to the FQDN in
  both the registry and ApplicationSettings.xml. Handles bare \\tsgwp00525\ and
  the legacy rd.ds.ge.com domain; idempotent. VM-tested.
- Report-AssetToShopDB: resolve the machine number eDNC registry first, then fall
  back to C:\Enrollment\machine-number.txt (matches the lib resolution order) so
  a freshly imaged PC still reports its number for the PC-machine relationship.
- Add Update-CMMEnforcer.ps1/.bat: update one CMM's local lib to the gated
  version and self-heal its PC-DMIS version.
- Add Debug-ShopDBReporting.ps1/.bat: one-shot reporter triage (preconditions,
  client log, live test POST, verdict).
- Add Verify-And-Heal-Staging.ps1/.bat: post-boot check that every imaging
  payload arrived and re-pull anything missing from the share, including the CMM
  bundle and the selected bay's backup (the payload that times out in WinPE).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
cproudlock
2026-06-14 09:14:54 -04:00
parent c2538a05c5
commit e97e5bd049
10 changed files with 735 additions and 45 deletions

View File

@@ -38,6 +38,25 @@ param(
$DefaultRewrites = @(
@{ From = 'rd.ds.ge.com'; To = 'wjs.geaerospace.net' } # WJ legacy domain -> new domain
)
# ----------------------------------------------------------------------------
# Part-group share host canonicalization. Bays were captured with three
# inconsistent forms of the share host in the goCMM 'Selected Part Group' /
# ApplicationSettings.xml <PartGroup FullName>:
# \\tsgwp00525\... (bare hostname - DNS-suffix dependent)
# \\tsgwp00525.rd.ds.ge.com\... (legacy GE corp domain - dead on the
# air-gapped shopfloor net)
# \\tsgwp00525.wjs.geaerospace.net\... (correct)
# The DefaultRewrites above only fix the middle form. goCMM DISPLAYS the part
# group from ApplicationSettings.xml, so the bare form survived into the UI.
# Pin every form to the FQDN in BOTH the registry and the XML. The regex
# matches the UNC host with an optional domain suffix and is idempotent (an
# already-correct FQDN maps to itself). Disabled by -NoDefaultRewrite.
$PartGroupHostShort = 'tsgwp00525'
$PartGroupHostFqdn = 'tsgwp00525.wjs.geaerospace.net'
# \\HOST or \\HOST.any.domain (followed by the next path backslash) -> \\FQDN
$PartGroupHostRx = '(?i)\\\\' + [regex]::Escape($PartGroupHostShort) + '(?:\.[A-Za-z0-9.\-]+)?(?=\\)'
$PartGroupHostTo = '\\' + $PartGroupHostFqdn
$ErrorActionPreference = 'Continue'
$ts = Get-Date -Format 'yyyyMMdd-HHmmss'
$logDir = 'C:\Logs\CMM'
@@ -148,6 +167,45 @@ if ($rewrites.Count -gt 0) {
}
}
# --- Canonicalize the part-group share host to the FQDN in reg + XML ---
# Runs AFTER the geaofi robocopy (so ApplicationSettings.xml is in place)
# and AFTER the literal rewrites above. Idempotent. This is what makes
# goCMM show the FQDN regardless of which form the bay was captured with.
if (-not $NoDefaultRewrite) {
# registry: every string value under the goCMM key
if (Test-Path $goCmmKey) {
try {
$props = Get-ItemProperty -Path $goCmmKey
foreach ($p in $props.PSObject.Properties) {
if ($p.Name -like 'PS*') { continue }
if (($p.Value -is [string]) -and ([regex]::IsMatch($p.Value, $PartGroupHostRx))) {
$new = [regex]::Replace($p.Value, $PartGroupHostRx, $PartGroupHostTo)
if ($new -ne $p.Value) {
Set-ItemProperty -Path $goCmmKey -Name $p.Name -Value $new
Log " host-canon reg [$($p.Name)] -> $new"
}
}
}
} catch { Log " WARN: host canonicalize (reg) failed: $($_.Exception.Message)" }
}
# files: every text file under the Shared Data Directory (incl ApplicationSettings.xml)
if (Test-Path $sharedDir) {
$utf8NoBomHost = New-Object System.Text.UTF8Encoding($false)
Get-ChildItem -Path $sharedDir -Recurse -File -Include *.xml,*.txt,*.csv,*.config,*.ini,*.bas -ErrorAction SilentlyContinue | ForEach-Object {
try {
$c = [System.IO.File]::ReadAllText($_.FullName)
if ([regex]::IsMatch($c, $PartGroupHostRx)) {
$nc = [regex]::Replace($c, $PartGroupHostRx, $PartGroupHostTo)
if ($nc -ne $c) {
[System.IO.File]::WriteAllText($_.FullName, $nc, $utf8NoBomHost)
Log " host-canon file [$($_.Name)] rewritten"
}
}
} catch { Log " WARN: host canonicalize $($_.FullName): $($_.Exception.Message)" }
}
}
}
# --- Grant BUILTIN\Users ReadKey+WriteKey on the reg key (goCMM opens it writable:true to read) ---
if (Test-Path $goCmmKey) {
try {