#!/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 \\10.9.100.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:-10.9.100.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" <