Files
pxe-server/playbook/sync-cmm.sh
cproudlock ce604adcda Renumber PXE LAN from 10.9.100.0/24 to 172.16.9.0/24
Single-site bay-stuck issue at WJ: GE Intune Report IP script filters
Get-NetIPAddress on StartsWith("10.") and posts everything matching
to the GE Tines webhook. Bays at WJ get the PXE LAN 10.9.100.x IP
captured and reported -> GE backend tags bays as on a non-corp 10.x
subnet -> dynamic group eligibility for SFLD policy never matches.
Other GE sites work because their PXE LANs aren't on 10.x at all.

Renumber PXE LAN to RFC1918 172.16.9.0/24 so the GE filter naturally
skips wired PXE addresses without any disable-NIC dance.

Server-side already in flight (netplan dual-bound, dnsmasq scope +
boot URL repointed, blancco preferences + grub.cfg + iPXE GetPxeScript
all sed'd to 172.16.9.1). This commit is the playbook / scripts /
docs side: 109 hits across 35 files sed'd in one shot.

After this lands + boot.wim is rebuilt + bays renumber off DHCP,
the 10.9.100.1 binding will be dropped from netplan as the final
cleanup step.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 16:30:32 -04:00

132 lines
4.0 KiB
Bash
Executable File

#!/bin/bash
# sync-cmm.sh - Push CMM bootstrap bundle to the PXE server enrollment share.
#
# Copies the Hexagon installers + cmm-manifest.json from the local workstation
# to /srv/samba/enrollment/cmm-installers on the PXE server. That directory
# becomes visible as \\172.16.9.1\enrollment\cmm-installers so startnet.cmd
# can xcopy it onto the target disk during WinPE phase.
#
# Run this on the workstation (not on the PXE server) any time:
# - You update cmm-manifest.json in playbook/shopfloor-setup/CMM/
# - You drop new/updated installers into /home/camp/pxe-images/cmm/hexagon/
#
# Same pattern as sync-preinstall.sh. The remote tree is updated in place and
# the next imaged CMM PC picks up the new files automatically.
#
# Usage:
# ./playbook/sync-cmm.sh
#
# Requires: sshpass (apt install sshpass), scp, ssh
set -euo pipefail
# --- Config ---
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
PXE_HOST="${PXE_HOST:-172.16.9.1}"
PXE_USER="${PXE_USER:-pxe}"
PXE_PASS="${PXE_PASS:-pxe}"
MANIFEST_SRC="$PROJECT_ROOT/playbook/shopfloor-setup/CMM/cmm-manifest.json"
INSTALLERS_SRC="${CMM_INSTALLERS_DIR:-/home/camp/pxe-images/cmm/hexagon}"
REMOTE_DIR="/srv/samba/enrollment/cmm-installers"
REMOTE_TEMP="/tmp/cmm-stage"
# --- Helpers ---
ssh_run() {
sshpass -p "$PXE_PASS" ssh -o StrictHostKeyChecking=no -o LogLevel=ERROR "$PXE_USER@$PXE_HOST" "$@"
}
scp_to() {
sshpass -p "$PXE_PASS" scp -o StrictHostKeyChecking=no -o LogLevel=ERROR "$1" "$PXE_USER@$PXE_HOST:'$2'"
}
# --- Validate sources ---
echo "Validating source files..."
if [ ! -f "$MANIFEST_SRC" ]; then
echo "ERROR: cmm-manifest.json not found at $MANIFEST_SRC" >&2
exit 1
fi
printf " OK %10d cmm-manifest.json\n" "$(stat -c %s "$MANIFEST_SRC")"
if [ ! -d "$INSTALLERS_SRC" ]; then
echo "ERROR: installers dir not found: $INSTALLERS_SRC" >&2
echo " Set CMM_INSTALLERS_DIR env var to override the default" >&2
exit 1
fi
installers=()
while IFS= read -r f; do
installers+=("$f")
done < <(find "$INSTALLERS_SRC" -maxdepth 1 -type f \( -name '*.exe' -o -name '*.msi' \) | sort)
if [ "${#installers[@]}" -eq 0 ]; then
echo "ERROR: no .exe or .msi files under $INSTALLERS_SRC" >&2
exit 1
fi
total_bytes=0
for f in "${installers[@]}"; do
size=$(stat -c %s "$f")
total_bytes=$((total_bytes + size))
printf " OK %10d %s\n" "$size" "$(basename "$f")"
done
printf " Total payload: %d bytes (%.1f GB)\n" "$total_bytes" "$(echo "scale=2; $total_bytes/1073741824" | bc)"
# --- Verify PXE server reachable ---
echo "Pinging PXE server $PXE_HOST..."
if ! ping -c 1 -W 2 "$PXE_HOST" >/dev/null 2>&1; then
echo "ERROR: PXE server $PXE_HOST not reachable" >&2
exit 1
fi
# --- Stage files to /tmp on PXE, then sudo install to enrollment share ---
echo "Staging files to $PXE_HOST:$REMOTE_TEMP..."
ssh_run "rm -rf $REMOTE_TEMP && mkdir -p $REMOTE_TEMP/files"
echo " -> cmm-manifest.json"
scp_to "$MANIFEST_SRC" "$REMOTE_TEMP/files/cmm-manifest.json"
for f in "${installers[@]}"; do
base="$(basename "$f")"
echo " -> $base"
scp_to "$f" "$REMOTE_TEMP/files/$base"
done
# --- Build remote install script (runs under sudo on PXE) ---
LOCAL_TEMP_SCRIPT="$(mktemp /tmp/sync-cmm-remote.XXXXXX.sh)"
trap 'rm -f "${LOCAL_TEMP_SCRIPT:-}"' EXIT
cat > "$LOCAL_TEMP_SCRIPT" <<REMOTE_SCRIPT
#!/bin/bash
set -e
mkdir -p "$REMOTE_DIR"
# Fresh deploy: remove stale files (old installer versions) so a shrinking
# manifest doesn't leave orphan binaries on the share.
find "$REMOTE_DIR" -maxdepth 1 -type f -delete
cp "$REMOTE_TEMP/files/"* "$REMOTE_DIR/"
chown -R root:root "$REMOTE_DIR"
find "$REMOTE_DIR" -type f -exec chmod 0644 {} +
find "$REMOTE_DIR" -type d -exec chmod 0755 {} +
rm -rf "$REMOTE_TEMP"
echo
echo "Final state of $REMOTE_DIR:"
ls -la "$REMOTE_DIR"
REMOTE_SCRIPT
scp_to "$LOCAL_TEMP_SCRIPT" "$REMOTE_TEMP/_install.sh"
echo "Installing files to $REMOTE_DIR (sudo)..."
ssh_run "echo '$PXE_PASS' | sudo -S bash $REMOTE_TEMP/_install.sh"
echo
echo "Done. CMM bootstrap synced to $PXE_HOST:$REMOTE_DIR"