Stage 2a: unified GE-Enforce framework + share-root mirror
Consolidates per-type enforcers (CMM, Keyence, Machine, Common, Acrobat)
into one dispatcher driven by pc-type.txt + site-config and a share-side
manifest layout. Same share is now the single source of truth for routine
software updates without re-imaging.
Runtime:
common/GE-Enforce.ps1 SYSTEM scheduled task. Reads
common/manifest.json plus optional
<pcType>/manifest.json and
<pcType-subType>/manifest.json.
Dispatches each entry through the lib.
Writes _outputs/logs/<hostname>/status.json
on the share after each cycle for fleet
monitoring.
common/Register-GEEnforce.ps1 Task registration. Triggers: AtLogOn +
every 5 min (jittered per-PC from
hostname hash) + daily at 05:45,
13:45, 21:45 EST shift windows.
Unregisters legacy per-type tasks on
install so the two coexist at most for
the duration of a single enforce cycle.
common/Deploy-GEEnforce.ps1 Retrofit helper for already-imaged PCs
(admin-run; copies runtime + registers
task + optional immediate trigger).
Library (common/lib/Install-FromManifest.ps1):
- New Type values: PS1, BAT, File, Registry, INF
- New DetectionMethod values: Always, MarkerFile, ValueMatches, pnputil
- TargetHostnames filter (exact + -like wildcards, ANDed with PCTypes)
- Schema version check (logs WARN on manifest newer than lib MAJOR)
- Auto-writes MarkerFile on successful one-shot PS1/BAT/CMD runs
- MSI log scan on failure surfaces meaningful install errors
- Lib version bumped 2.0 -> 2.1 for TargetHostnames
Observability:
common/monitor-fleet-status.py Scans _outputs/logs/*/status.json for
stale check-ins, failed scopes, and
version drift. Respects scope (dir-name),
PCTypes, and TargetHostnames filters so
entries excluded from a PC do not
false-flag as drift.
Regression harness:
common/test/ Parameterized VM harness + README
covering every action type plus
rollback, bad/missing SFLD creds, and
schema versioning.
Imaging integration:
Run-ShopfloorSetup.ps1 now stages GE-Enforce.ps1 and lib to
C:\Program Files\GE\Shopfloor\ and invokes Register-GEEnforce.ps1
at the end of setup. Legacy Register-CommonEnforce invocation is
kept for the transition; it and the legacy per-type enforcer files
are dead code once Register-GEEnforce runs and will be removed in a
dedicated cleanup pass.
Standard-Machine manifest:
eDNC entry bumped 6.4.3 -> 6.4.5. DetectionValue pinned to the
4-part FileVersion 6.4.5.0 verified against a fresh install in the
Win11 analyzer VM. UDC DetectionValue pinned to 1.0.34 (registry
stores 3-part for UDC; verified live).
scripts/mirror-from-gold.sh:
Restructured around share-root rsyncs (one pass per Samba share)
to close gaps in the prior per-subdir layout: winpeapps/_shared/
Applications (7.5 GB of Adobe + fonts + Java + Office + OpenText
+ printdrivers + wireless + Zscaler), additional winpeapps image
types, and enrollment flat-layout root files. Adds
--skip-clonezilla and --skip-reports.
Verified end-to-end in the Win11 analyzer VM:
- Every action Type and DetectionMethod round-tripped
- PCTypes filter (Oracle excluded on Shopfloor, Firefox included
on Shopfloor and DESKTOP-*, excluded elsewhere)
- TargetHostnames filter (exact, wildcard, no-match)
- Upgrade path: XML hash bump + fleet re-copy
- Rollback path: history-archive restore propagates via enforcer,
fleet converges back without per-PC intervention
- Status writeback + monitor script drift detection
- Graceful degradation on bad creds, missing creds, share
unreachable (all exit 0, log clearly, retry next cycle)
Not in this commit (follow-ups):
- Retire legacy per-type *-Enforce.ps1 files and simplify
09-Setup-*.ps1 scripts (coordinated multi-file cleanup)
- Stage 2b: InUseCheck close-and-reopen, ApplyMode gating,
UpdateWindow, .apply-now.txt sentinel, BITS pre-staging,
1618 mutex retry, PostInstallCheck, Uninstall action
- Management app (manifest CRUD + deploy + rollback + fleet view)
- ShopFloor autologon persistence bug (deferred for next imaging
attempt with live registry evidence)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,24 +1,23 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# mirror-from-gold.sh - Replicate content from an existing PXE server (GOLD)
|
||||
# onto a freshly-installed PXE server.
|
||||
# mirror-from-gold.sh - Byte-identical mirror of /srv/samba/ from an existing
|
||||
# PXE server (GOLD) onto a freshly-installed PXE server.
|
||||
#
|
||||
# Run this ON THE NEW PXE SERVER, pointing at the GOLD server's IP.
|
||||
# It pulls Operating Systems, drivers, packages, custom installers, and
|
||||
# Blancco assets that are NOT bundled on the USB installer.
|
||||
#
|
||||
# GOLD is on the taxonomy layout (pre-install/, installers-post/, blancco/,
|
||||
# config/, ppkgs/, scripts/, shopfloor-setup/). Source and destination paths
|
||||
# are identical per section, so sections can be added trivially as GOLD grows.
|
||||
# It pulls every Samba share (winpeapps, enrollment, blancco-reports,
|
||||
# clonezilla) wholesale so the new box matches GOLD regardless of whether
|
||||
# content lives in the flat layout or the new taxonomy layout.
|
||||
#
|
||||
# Usage:
|
||||
# sudo ./mirror-from-gold.sh <GOLD_IP> [options]
|
||||
#
|
||||
# Options:
|
||||
# --skip-drivers Do not mirror Dell driver tree (saves ~178G).
|
||||
# --skip-drivers Do not mirror Out-of-box Drivers trees (saves ~178G).
|
||||
# --skip-dell10 Do not mirror Dell_10 drivers (saves ~179G).
|
||||
# --skip-latitude Do not mirror Latitude drivers (saves ~48G).
|
||||
# --skip-os Do not mirror Operating Systems (saves ~22G).
|
||||
# --skip-os Do not mirror shared Operating Systems (saves ~22G).
|
||||
# --skip-clonezilla Do not mirror clonezilla backup images (can be huge).
|
||||
# --skip-reports Do not mirror blancco-reports history.
|
||||
# --dry-run Show what would transfer without doing it.
|
||||
#
|
||||
# Prereqs:
|
||||
@@ -49,15 +48,19 @@ SKIP_DRIVERS=0
|
||||
SKIP_DELL10=0
|
||||
SKIP_LATITUDE=0
|
||||
SKIP_OS=0
|
||||
SKIP_CLONEZILLA=0
|
||||
SKIP_REPORTS=0
|
||||
DRY_RUN=""
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--skip-drivers) SKIP_DRIVERS=1 ;;
|
||||
--skip-dell10) SKIP_DELL10=1 ;;
|
||||
--skip-latitude) SKIP_LATITUDE=1 ;;
|
||||
--skip-os) SKIP_OS=1 ;;
|
||||
--dry-run) DRY_RUN="--dry-run" ;;
|
||||
--skip-drivers) SKIP_DRIVERS=1 ;;
|
||||
--skip-dell10) SKIP_DELL10=1 ;;
|
||||
--skip-latitude) SKIP_LATITUDE=1 ;;
|
||||
--skip-os) SKIP_OS=1 ;;
|
||||
--skip-clonezilla) SKIP_CLONEZILLA=1 ;;
|
||||
--skip-reports) SKIP_REPORTS=1 ;;
|
||||
--dry-run) DRY_RUN="--dry-run" ;;
|
||||
*) echo "Unknown option: $1"; exit 1 ;;
|
||||
esac
|
||||
shift
|
||||
@@ -104,84 +107,42 @@ mirror() {
|
||||
echo " WARNING: rsync exited rc=$? (likely a permissions issue on source); continuing"
|
||||
}
|
||||
|
||||
# ---------- Shared imaging content (winpeapps/_shared) ----------
|
||||
DRIVER_EXCLUDES=()
|
||||
[ "$SKIP_DELL10" = "1" ] && DRIVER_EXCLUDES+=(--exclude='Dell_10')
|
||||
[ "$SKIP_LATITUDE" = "1" ] && DRIVER_EXCLUDES+=(--exclude='Latitude')
|
||||
# ---------- winpeapps share (all image types + _shared) ----------
|
||||
WINPE_EXCLUDES=()
|
||||
[ "$SKIP_OS" = "1" ] && WINPE_EXCLUDES+=(--exclude='_shared/gea-Operating Systems')
|
||||
[ "$SKIP_DRIVERS" = "1" ] && WINPE_EXCLUDES+=(--exclude='_shared/Out-of-box Drivers' --exclude='Out-of-box Drivers')
|
||||
[ "$SKIP_DELL10" = "1" ] && WINPE_EXCLUDES+=(--exclude='Dell_10')
|
||||
[ "$SKIP_LATITUDE" = "1" ] && WINPE_EXCLUDES+=(--exclude='Latitude')
|
||||
|
||||
if [ "$SKIP_OS" = "0" ]; then
|
||||
mirror "Operating Systems (gea-Operating Systems)" \
|
||||
"/srv/samba/winpeapps/_shared/gea-Operating Systems/" \
|
||||
"/srv/samba/winpeapps/_shared/gea-Operating Systems/"
|
||||
mirror "winpeapps (all image types, _shared, tools)" \
|
||||
"/srv/samba/winpeapps/" \
|
||||
"/srv/samba/winpeapps/" \
|
||||
"${WINPE_EXCLUDES[@]}"
|
||||
|
||||
# ---------- enrollment share (flat-layout root + taxonomy subdirs) ----------
|
||||
mirror "enrollment (taxonomy + flat-layout content)" \
|
||||
"/srv/samba/enrollment/" \
|
||||
"/srv/samba/enrollment/"
|
||||
|
||||
# ---------- blancco-reports share (historical XML reports) ----------
|
||||
if [ "$SKIP_REPORTS" = "0" ]; then
|
||||
mirror "blancco-reports (erasure report history)" \
|
||||
"/srv/samba/blancco-reports/" \
|
||||
"/srv/samba/blancco-reports/"
|
||||
fi
|
||||
|
||||
mirror "Packages (gea-Packages)" \
|
||||
"/srv/samba/winpeapps/_shared/gea-Packages/" \
|
||||
"/srv/samba/winpeapps/_shared/gea-Packages/"
|
||||
|
||||
mirror "Sources (gea-Sources)" \
|
||||
"/srv/samba/winpeapps/_shared/gea-Sources/" \
|
||||
"/srv/samba/winpeapps/_shared/gea-Sources/"
|
||||
|
||||
if [ "$SKIP_DRIVERS" = "0" ]; then
|
||||
mirror "Out-of-box Drivers" \
|
||||
"/srv/samba/winpeapps/_shared/Out-of-box Drivers/" \
|
||||
"/srv/samba/winpeapps/_shared/Out-of-box Drivers/" \
|
||||
"${DRIVER_EXCLUDES[@]}"
|
||||
# ---------- clonezilla share (disk backup images, can be very large) ----------
|
||||
if [ "$SKIP_CLONEZILLA" = "0" ]; then
|
||||
mirror "clonezilla (disk backup images)" \
|
||||
"/srv/samba/clonezilla/" \
|
||||
"/srv/samba/clonezilla/"
|
||||
fi
|
||||
|
||||
# ---------- Per-image-type Deploy/ trees (mostly symlinks to _shared) ----------
|
||||
for img in gea-standard gea-engineer gea-shopfloor; do
|
||||
mirror "Image dir: $img" \
|
||||
"/srv/samba/winpeapps/$img/" \
|
||||
"/srv/samba/winpeapps/$img/" \
|
||||
--exclude=backup --exclude=logs --exclude='New folder' --exclude=ProMax
|
||||
done
|
||||
|
||||
# ---------- Enrollment-share content (GOLD is on taxonomy layout, src == dest) ----------
|
||||
|
||||
# Pre-install: installers + bios + preinstall.json + udc-backups
|
||||
mirror "Pre-install tree" \
|
||||
"/srv/samba/enrollment/pre-install/" \
|
||||
"/srv/samba/enrollment/pre-install/" \
|
||||
--exclude='*.old'
|
||||
|
||||
# Post-install installers (CMM PC-DMIS, etc.)
|
||||
mirror "Post-install installers" \
|
||||
"/srv/samba/enrollment/installers-post/" \
|
||||
"/srv/samba/enrollment/installers-post/"
|
||||
|
||||
# Blancco custom image
|
||||
mirror "Blancco images" \
|
||||
"/srv/samba/enrollment/blancco/" \
|
||||
"/srv/samba/enrollment/blancco/"
|
||||
|
||||
# Site config (site-config.json, etc.)
|
||||
mirror "Enrollment config" \
|
||||
"/srv/samba/enrollment/config/" \
|
||||
"/srv/samba/enrollment/config/"
|
||||
|
||||
# Provisioning packages
|
||||
mirror "PPKGs" \
|
||||
"/srv/samba/enrollment/ppkgs/" \
|
||||
"/srv/samba/enrollment/ppkgs/"
|
||||
|
||||
# Enrollment scripts (run-enrollment.ps1, startnet.cmd, etc.)
|
||||
mirror "Enrollment scripts" \
|
||||
"/srv/samba/enrollment/scripts/" \
|
||||
"/srv/samba/enrollment/scripts/" \
|
||||
--exclude='*.pre-*'
|
||||
|
||||
# Shopfloor-setup tree (per-PC-type scripts + site-config)
|
||||
mirror "Shopfloor-setup tree" \
|
||||
"/srv/samba/enrollment/shopfloor-setup/" \
|
||||
"/srv/samba/enrollment/shopfloor-setup/"
|
||||
|
||||
# Permissions: anything we just created should be readable by the share
|
||||
chown -R root:root /srv/samba/enrollment /srv/samba/winpeapps
|
||||
# Permissions: make sure everything we pulled is readable by the share
|
||||
chown -R root:root /srv/samba/enrollment /srv/samba/winpeapps /srv/samba/blancco-reports /srv/samba/clonezilla 2>/dev/null || true
|
||||
find /srv/samba/enrollment /srv/samba/winpeapps -type d -exec chmod 0755 {} \; 2>/dev/null || true
|
||||
find /srv/samba/enrollment /srv/samba/winpeapps -type f -exec chmod 0644 {} \; 2>/dev/null || true
|
||||
find /srv/samba/enrollment/ppkgs -name '*.ppkg' -exec chmod 0755 {} \; 2>/dev/null || true
|
||||
find /srv/samba/enrollment -name '*.ppkg' -exec chmod 0755 {} \; 2>/dev/null || true
|
||||
|
||||
echo
|
||||
echo "============================================"
|
||||
|
||||
Reference in New Issue
Block a user