Add ARCHITECTURE.md, SITE-CUSTOMIZATION.md, mirror-from-gold.sh
Two new docs cover what the system is (boot chain, services, shares, enrollment layout, data flow) and what to change per site (every hardcoded value, where it lives, secrets handling). scripts/mirror-from-gold.sh replicates content from an existing PXE server (Operating Systems, drivers, packages, custom installers, BIOS, PCDMIS, Blancco custom image, site-config) onto a freshly-installed PXE server. Translates the legacy flat enrollment layout on the source into the reorganized taxonomy (ppkgs/, pre-install/installers/, installers- post/cmm/, blancco/, config/) on the destination. Tolerates rsync exit 23 (permission-denied subdirs like the OpenText W10shortcuts dir that is pxe-upload-group-only on legacy servers).
This commit is contained in:
203
docs/ARCHITECTURE.md
Normal file
203
docs/ARCHITECTURE.md
Normal file
@@ -0,0 +1,203 @@
|
||||
# PXE Server Architecture
|
||||
|
||||
This document describes the moving parts of the PXE server, the boot chain a
|
||||
client follows, and how data flows between the server, clients, and external
|
||||
systems.
|
||||
|
||||
## Hardware and host OS
|
||||
|
||||
- Single physical host (or VM) with at minimum 4 GB RAM, 4 CPU cores, and one
|
||||
network interface attached to the isolated PXE LAN.
|
||||
- Disk: 232 GB minimum if you stay slim (Dell_11 only, no Latitude); 500 GB
|
||||
recommended for a full mirror; 2 TB+ recommended for headroom across all
|
||||
driver sets and OS image variants.
|
||||
- OS: Ubuntu Server 24.04 LTS (Noble), installed unattended via the autoinstall
|
||||
USB built by `scripts/build-usb.sh`.
|
||||
|
||||
## Network layout
|
||||
|
||||
- PXE server static IP: `10.9.100.1/24` on an isolated subnet.
|
||||
- DHCP range served by dnsmasq: `10.9.100.10 - 10.9.100.100`, 12h leases.
|
||||
- Default gateway and DNS handed out via DHCP point at the PXE server itself.
|
||||
- The subnet has no route to the corporate LAN. Client traffic (Blancco BMC
|
||||
cloud, Intune enrollment) goes out via WiFi after Windows boots; PXE-time
|
||||
traffic stays on the isolated LAN.
|
||||
|
||||
## Services on the PXE server
|
||||
|
||||
| Service | Port | Role |
|
||||
|---------------|-----------|------------------------------------------------------|
|
||||
| dnsmasq | 67/udp | DHCP. Hands out IPs and the next-server (TFTP) info. |
|
||||
| dnsmasq | 69/udp | TFTP. Serves `ipxe.efi` to firmware PXE clients. |
|
||||
| Apache | 80/tcp | HTTP. Serves wimboot, boot.wim, Blancco binaries, Clonezilla, memtest, and proxies the webapp on /. |
|
||||
| Apache | 4433/tcp | HTTP. Serves `Altiris/iPXE/GetPxeScript.aspx` (the iPXE menu script). |
|
||||
| Samba | 445/tcp | SMB shares. WinPE mounts these to fetch image content during deployment. |
|
||||
| Flask webapp | 9009/tcp | Browser UI for image import, unattend editing, log/report viewing. |
|
||||
|
||||
`/etc/cron.d/dnsmasq-restart` restarts dnsmasq 15 seconds after every reboot to
|
||||
work around a systemd-resolved race condition that can prevent dnsmasq from
|
||||
binding to the PXE interface on cold boot.
|
||||
|
||||
`/etc/cron.d/media-tag-refresh` touches `Media.tag` in every image's
|
||||
`Deploy/Control/` directory daily and on reboot. Without this, the WinPE
|
||||
deployment loader stops finding the image after 30 days.
|
||||
|
||||
## Samba shares
|
||||
|
||||
| Share | Filesystem path | Purpose |
|
||||
|------------------|-----------------------------|--------------------------------------------------------------|
|
||||
| winpeapps | /srv/samba/winpeapps | Per-image-type Deploy/ trees (gea-standard, gea-shopfloor, etc.) and the deduped `_shared/` content (Operating Systems, Out-of-box Drivers, Packages). |
|
||||
| clonezilla | /srv/samba/clonezilla | Clonezilla disk backup images (uploaded by clients running Clonezilla Live). |
|
||||
| blancco-reports | /srv/samba/blancco-reports | XML erasure reports, written automatically by Blancco Drive Eraser at the end of each wipe. |
|
||||
| enrollment | /srv/samba/enrollment | Single share that WinPE mounts as Y: during imaging. See "Enrollment share layout" below. |
|
||||
| image-upload | /home/pxe/image-upload | Staging area for new image content uploaded from a Windows PC running `Upload-Image.ps1`. |
|
||||
|
||||
All shares are accessible to `pxe-upload` (password `pxe`) and the public-side
|
||||
ones also allow guest access. The `blancco` user (password `blancco`) writes to
|
||||
`blancco-reports` only.
|
||||
|
||||
## Enrollment share layout
|
||||
|
||||
The `enrollment` share is the catchall WinPE pulls from during imaging. New
|
||||
fresh installs (built from this repo) deploy this layout:
|
||||
|
||||
```
|
||||
/srv/samba/enrollment/
|
||||
README.md
|
||||
ppkgs/ GCCH bulk-enrollment PPKGs (.ppkg)
|
||||
scripts/ run-enrollment.ps1, wait-for-internet.ps1, migrate-to-wifi.ps1
|
||||
config/ site-config.json, FlatUnattendW10*.xml, per-site overrides
|
||||
shopfloor-setup/ PC-type post-imaging scripts (CMM, Display, Standard, Lab, etc.)
|
||||
pre-install/ WinPE-phase content
|
||||
bios/ Dell BIOS update binaries + check-bios.cmd + models.txt
|
||||
installers/ UDC, OpenText, etc. staged on client during preinstall
|
||||
preinstall.json Preinstall manifest read by the WinPE preinstall stage
|
||||
installers-post/ Post-OOBE app installers
|
||||
cmm/ PC-DMIS patched MSIs
|
||||
blancco/ Blancco custom images / configs (BDE715_GEAE_INTERNET.img.gz)
|
||||
logs/ Client-uploaded logs and diagnostic bundles
|
||||
```
|
||||
|
||||
Older servers (built before this repo's reorganization) use a flat layout
|
||||
(everything at the share root). Both layouts work; the `startnet.cmd` baked
|
||||
into each server's `boot.wim` matches its own layout.
|
||||
|
||||
## Boot chain (client perspective)
|
||||
|
||||
A client PXE-boots from the isolated LAN. UEFI Secure Boot is supported for
|
||||
WinPE; the Blancco and Clonezilla utilities require Secure Boot disabled.
|
||||
|
||||
```
|
||||
1. Client UEFI firmware sends DHCP DISCOVER on the isolated LAN.
|
||||
2. dnsmasq replies with IP, next-server (PXE server IP), and bootfile=ipxe.efi.
|
||||
3. Firmware fetches /srv/tftp/ipxe.efi via TFTP.
|
||||
4. ipxe.efi (Broadcom-signed for Secure Boot) starts, gets DHCP, fetches the
|
||||
iPXE menu script from http://<server>:4433/Altiris/iPXE/GetPxeScript.aspx.
|
||||
5. Client picks an option:
|
||||
|
||||
a. Windows PE:
|
||||
iPXE -> wimboot -> boot.wim
|
||||
boot.wim runs startnet.cmd which mounts SMB shares (Y: enrollment,
|
||||
Z: chosen winpeapps), kicks off FlatSetupLoader.exe -> PESetup.exe
|
||||
to deploy the OS, then handles per-PC-type setup before reboot.
|
||||
|
||||
b. Blancco Drive Eraser:
|
||||
iPXE chains http://<server>/blancco/grubx64.efi
|
||||
GRUB loads vmlinuz-bde-linux + initramfs over TFTP (HTTP times out on
|
||||
large files inside GRUB)
|
||||
Blancco boot uses copytoram=y to load the rootfs into memory, mounts
|
||||
the customized airootfs.sfs over HTTP, connects to BMC cloud over WiFi
|
||||
for license validation, then runs the configured erasure profile.
|
||||
Reports are written back to \\<server>\blancco-reports.
|
||||
|
||||
c. Clonezilla Live:
|
||||
iPXE loads vmlinuz + initrd over HTTP, fetches filesystem.squashfs.
|
||||
|
||||
d. Memtest86+:
|
||||
iPXE loads memtest.efi.
|
||||
```
|
||||
|
||||
## Windows imaging lifecycle (gea-* images)
|
||||
|
||||
```
|
||||
1. Boot to WinPE via PXE.
|
||||
2. startnet.cmd mounts Y: \\server\enrollment and presents an interactive
|
||||
image type and PC type menu.
|
||||
3. Optionally checks BIOS firmware version against a manifest; if outdated,
|
||||
stages the new firmware to the disk and reboots so it flashes on POST.
|
||||
4. PESetup.exe runs the chosen image (image type determines OS, drivers,
|
||||
apps to deploy).
|
||||
5. After WinPE finishes, the system reboots into Windows OOBE.
|
||||
6. During OOBE, the staged PPKG runs (GCCH bulk-enrollment, joins AAD, sets
|
||||
up Intune enrollment).
|
||||
7. After OOBE, the per-PC-type Run-ShopfloorSetup.ps1 runs from C:\Enrollment.
|
||||
It installs the apps for that PC type (eDNC, OpenText, UDC, Dashboard,
|
||||
etc. depending on the type), configures the desktop, and triggers Intune
|
||||
sync.
|
||||
```
|
||||
|
||||
## Webapp
|
||||
|
||||
`/opt/pxe-webapp/` runs as a systemd service, reverse-proxied by Apache on
|
||||
port 80 (`/`) and accessible directly on port 9009. Built with Flask. Pages:
|
||||
|
||||
- Dashboard: service status, disk usage, recent activity.
|
||||
- Images: import wizard for new content (from `image-upload` SMB share into
|
||||
per-image Deploy/ trees), per-image driver and hardware config editing.
|
||||
- Unattend editor: in-place editing of FlatUnattendW10.xml for each image.
|
||||
- Startnet editor: edit and re-inject `Windows/System32/startnet.cmd` inside
|
||||
the deployed `boot.wim` via wimupdate.
|
||||
- Enrollment: PPKG inventory and upload.
|
||||
- Backups: Clonezilla backup management.
|
||||
- Reports: Blancco erasure report viewer.
|
||||
- Audit: action log.
|
||||
|
||||
## Data flow summary
|
||||
|
||||
```
|
||||
Build workstation (this repo)
|
||||
|
|
||||
| scripts/build-usb.sh /dev/sdX ubuntu-24.04.iso
|
||||
v
|
||||
USB installer (2 partitions: ISO + CIDATA)
|
||||
|
|
||||
| inserted into target server, boot from USB
|
||||
v
|
||||
Ubuntu auto-install + first-boot Ansible playbook
|
||||
|
|
||||
v
|
||||
Configured PXE server (10.9.100.1) ----+
|
||||
|
|
||||
Windows PCs running Upload-Image.ps1 --+--> Image content (SMB, webapp import)
|
||||
|
|
||||
PXE clients (UEFI -> iPXE -> WinPE) ---+--> Image deployment (SMB, HTTP)
|
||||
PXE clients (UEFI -> iPXE -> Blancco) -+--> Drive erasure + report upload
|
||||
|
|
||||
+--> Clonezilla backups (SMB)
|
||||
```
|
||||
|
||||
## Where things live
|
||||
|
||||
- Ansible playbook: `playbook/pxe_server_setup.yml`. Single file, idempotent.
|
||||
- WinPE startup script (template): `playbook/startnet.cmd` (canonical) and
|
||||
`startnet-template.cmd` (mirror copy at repo root for editor convenience).
|
||||
The playbook injects this into `Windows/System32/startnet.cmd` inside the
|
||||
`boot.wim` it deploys to `/var/www/html/win11/sources/`.
|
||||
- iPXE menu script source: embedded in the playbook (`Create GetPxeScript.aspx`
|
||||
task); deployed to `/var/www/html/Altiris/iPXE/GetPxeScript.aspx`.
|
||||
- Per-PC-type setup scripts: `playbook/shopfloor-setup/`. The playbook copies
|
||||
the whole tree to the enrollment share so WinPE can fetch them.
|
||||
- Blancco assets: `boot-tools/blancco/` in the repo, deployed to
|
||||
`/var/www/html/blancco/` plus TFTP symlinks in `/srv/tftp/blancco/`.
|
||||
- Site-specific values (IPs, SSIDs, BMC creds, hostnames): currently
|
||||
hardcoded in multiple files; see SITE-CUSTOMIZATION.md for the migration
|
||||
plan to consolidate these in `config/`.
|
||||
|
||||
## See also
|
||||
|
||||
- SETUP.md: build process and target server install
|
||||
- SITE-CUSTOMIZATION.md: what to change when bringing up a new site
|
||||
- TROUBLESHOOTING.md: known failure modes and fixes
|
||||
- BLANCCO.md: erasure boot chain details, custom config.img, BMC licensing
|
||||
- GEA-IMAGING.md: WinPE deployment internals, PPKGs, per-type setup
|
||||
- OPERATIONS.md: day 2 procedures (PPKG bumps, BIOS updates, image upload)
|
||||
199
docs/SITE-CUSTOMIZATION.md
Normal file
199
docs/SITE-CUSTOMIZATION.md
Normal file
@@ -0,0 +1,199 @@
|
||||
# Site Customization
|
||||
|
||||
The PXE server in this repo was built for the GE Aerospace West Jefferson site.
|
||||
To stand it up at another site, several values need to change. This document
|
||||
lists every site-specific value, where it lives today, and the recommended
|
||||
forward state.
|
||||
|
||||
## Status
|
||||
|
||||
The repo has not yet been parameterized. As of 2026-04-14 the site-specific
|
||||
values below are hardcoded in multiple files. The `config/` directory at the
|
||||
repo root is a placeholder for the future state where one YAML file drives
|
||||
substitution at build time. Until that exists, customizing for a new site
|
||||
means editing the source files directly.
|
||||
|
||||
If you are bringing up the first non-WJ site, expect to do this manually and
|
||||
contribute a `config/sites/<sitename>.yaml` template back to the repo.
|
||||
|
||||
## Values to change
|
||||
|
||||
### Network
|
||||
|
||||
| Value | Default | Where it lives |
|
||||
|-------------------|----------------------|--------------------------------------------------------------------------------|
|
||||
| PXE server IP | 10.9.100.1 | `playbook/pxe_server_setup.yml` (dnsmasq config, iPXE script, samba conf, webapp env), `playbook/startnet.cmd` (mount paths), `boot-tools/blancco/grub-blancco.cfg` (TFTP/HTTP URLs) |
|
||||
| PXE subnet | 10.9.100.0/24 | Same as above, plus `playbook/pxe_server_setup.yml` (UFW rules) |
|
||||
| DHCP range | 10.9.100.10-100 | `playbook/pxe_server_setup.yml` (dnsmasq config) |
|
||||
| Hostname | pxeserver | `autoinstall/user-data` (identity.hostname) |
|
||||
|
||||
### Identity and credentials
|
||||
|
||||
| Value | Default | Where it lives |
|
||||
|-----------------------------|---------------------------------------|---------------------------------------------------------|
|
||||
| Linux user | pxe / pxe | `autoinstall/user-data` (identity.username, password hash) |
|
||||
| Samba upload user | pxe-upload / pxe | `playbook/pxe_server_setup.yml` (Samba user creation) |
|
||||
| Samba blancco user | blancco / blancco | `playbook/pxe_server_setup.yml` |
|
||||
| Sudo password | pxe | autoinstall password hash; also referenced in scripts that ssh + sudo |
|
||||
|
||||
### WiFi and BMC (Blancco licensing)
|
||||
|
||||
The Blancco custom `config.img` carries WiFi credentials and BMC cloud
|
||||
credentials in plaintext. These are GE-Aerospace specific.
|
||||
|
||||
| Value | Default | Where it lives |
|
||||
|---------------|----------------------|-------------------------------------------------------------------------|
|
||||
| WiFi SSID | INTERNETACCESS | `boot-tools/blancco/config.img` (inside the cpio archive: preferences.xml) |
|
||||
| WiFi password | Acc3ssGr@nted22 | Same |
|
||||
| BMC endpoint | classic.eu-west-1.blancco.cloud:443 | Same; encrypted credentials inside config.img |
|
||||
|
||||
To rebuild `config.img` for a different site, see BLANCCO.md ("Rebuilding
|
||||
config.img").
|
||||
|
||||
### Image types
|
||||
|
||||
The repo defines seven image types (see `playbook/pxe_server_setup.yml`,
|
||||
`image_types`). Most sites likely only need a subset. The current set:
|
||||
- gea-standard
|
||||
- gea-engineer
|
||||
- gea-shopfloor
|
||||
- ge-standard
|
||||
- ge-engineer
|
||||
- ge-shopfloor-lockdown
|
||||
- ge-shopfloor-mce
|
||||
|
||||
Trim or extend this list and the matching `shopfloor_types` filter as needed.
|
||||
|
||||
### PC types (shopfloor sub-types)
|
||||
|
||||
`playbook/shopfloor-setup/` contains per-PC-type install logic. The current
|
||||
types reflect WJ shopfloor needs:
|
||||
- CMM (PC-DMIS)
|
||||
- WaxAndTrace
|
||||
- Keyence
|
||||
- Genspect
|
||||
- Display (Lobby and Dashboard variants)
|
||||
- Standard (Timeclock and Machine variants)
|
||||
- Lab
|
||||
|
||||
A site without CMMs can drop the CMM type and its installers entirely.
|
||||
|
||||
### GCCH bulk-enrollment PPKGs
|
||||
|
||||
PPKG filenames are baked into `playbook/startnet.cmd` and
|
||||
`startnet-template.cmd`. They are tied to the GE Aerospace tenant. Other
|
||||
sites/tenants will have their own PPKGs with different filenames.
|
||||
|
||||
| PPKG enrollment menu choice | Default filename |
|
||||
|-----------------------------|---------------------------------------------------------------|
|
||||
| 1 NoOffice | GCCH_Prod_SFLD_NoOffice_US_Exp_20260430_v4.10.ppkg |
|
||||
| 2 StdOffice x86 | GCCH_Prod_SFLD_StdOffice-x86_US_Exp_20260430_v4.10.ppkg |
|
||||
| 3 StdOffice x64 | GCCH_Prod_SFLD_StdOffice-x64_US_Exp_20260430_v4.10.ppkg |
|
||||
| 4 ProPlusOffice x86 | GCCH_Prod_SFLD_ProPlusOffice-x86_US_Exp_20260430_v4.10.ppkg |
|
||||
| 5 ProPlusOffice x64 | GCCH_Prod_SFLD_ProPlusOffice-x64_US_Exp_20260430_v4.10.ppkg |
|
||||
|
||||
When you bump PPKG versions, update the filenames in startnet.cmd, drop the
|
||||
new PPKGs in `enrollment/` on the workstation, and rebuild the USB.
|
||||
|
||||
### Site-specific shopfloor config
|
||||
|
||||
`playbook/shopfloor-setup/site-config.json` has site-specific values like
|
||||
default machine number ranges, share paths for software, and more. Inspect
|
||||
that file for site name strings, share UNC paths, and machine number ranges.
|
||||
|
||||
### Branding
|
||||
|
||||
The Flask webapp uses GE Aerospace branding:
|
||||
- Logo: `webapp/static/ge-aerospace-logo.svg`
|
||||
- Favicon: `webapp/static/favicon.ico`
|
||||
- Page titles and templates reference "GE Aerospace" in `webapp/templates/*.html`
|
||||
- iPXE menu title: "GE Aerospace PXE Boot Menu" in `playbook/pxe_server_setup.yml`
|
||||
|
||||
### Drivers (Dell)
|
||||
|
||||
Driver content is hardware-specific, not strictly site-specific, but the set
|
||||
of driver families to bundle changes by what hardware the site deploys:
|
||||
- `Dell_11/Pro` and `Dell_11/ProMax`: Dell Pro Micro PCs (most common shopfloor)
|
||||
- `Dell_11/Optiplex`: traditional desktops
|
||||
- `Dell_11/Precision`: workstations
|
||||
- `Dell_11/Latitude`: laptops (large, often excluded if site has none)
|
||||
|
||||
The `scripts/download-drivers.py` and `scripts/Download-Drivers.ps1` scripts
|
||||
populate `drivers-staging/` from upstream sources. Edit these to target the
|
||||
relevant hardware lists.
|
||||
|
||||
### BIOS update manifest
|
||||
|
||||
`playbook/shopfloor-setup/BIOS/models.txt` maps Dell model strings to the
|
||||
BIOS .exe to flash. Update this whenever new hardware arrives or Dell
|
||||
publishes a new firmware release for a model already in the fleet.
|
||||
|
||||
### Intune DSC categories
|
||||
|
||||
The post-enrollment Intune DSC delivery (per `intune-dsc.md` memory) pulls
|
||||
per-category YAML from Azure Blob:
|
||||
- main
|
||||
- cmm
|
||||
- displaypcs
|
||||
- waxtrace
|
||||
|
||||
Different sites/tenants will need their own categories and their own Azure
|
||||
Blob storage account.
|
||||
|
||||
### Image-upload paths on Windows
|
||||
|
||||
`scripts/Upload-Image.ps1` defaults to:
|
||||
- `\\10.9.100.1\image-upload` as the destination
|
||||
- `C:\ProgramData\GEAerospace\MediaCreator\Cache\` as the source
|
||||
|
||||
Update both for a different site.
|
||||
|
||||
## Recommended forward state
|
||||
|
||||
A site config file should drive substitution at build time. Proposed schema:
|
||||
|
||||
```yaml
|
||||
# config/sites/<sitename>.yaml
|
||||
site:
|
||||
name: westjeff
|
||||
pxe_server_ip: 10.9.100.1
|
||||
pxe_subnet: 10.9.100.0/24
|
||||
dhcp_range_start: 10.9.100.10
|
||||
dhcp_range_end: 10.9.100.100
|
||||
hostname: pxeserver
|
||||
|
||||
credentials:
|
||||
pxe_user: pxe
|
||||
pxe_password: pxe
|
||||
pxe_upload_password: pxe
|
||||
blancco_password: blancco
|
||||
|
||||
blancco:
|
||||
wifi_ssid: INTERNETACCESS
|
||||
wifi_password: Acc3ssGr@nted22
|
||||
bmc_endpoint: classic.eu-west-1.blancco.cloud:443
|
||||
|
||||
ppkg_versions:
|
||||
current: v4.10
|
||||
expiry: 20260430
|
||||
|
||||
intune_dsc_categories: [main, cmm, displaypcs, waxtrace]
|
||||
|
||||
image_types: [gea-standard, gea-engineer, gea-shopfloor]
|
||||
shopfloor_types: [gea-shopfloor]
|
||||
```
|
||||
|
||||
`scripts/build-usb.sh` and the playbook would consume this and substitute
|
||||
into the templated config files. Implementing this is a separate piece of
|
||||
work; until then, edit source files directly.
|
||||
|
||||
## Secrets handling
|
||||
|
||||
Some values above are sensitive (WiFi passwords, BMC credentials, Samba
|
||||
passwords). Today these sit in plain text in the repo. For a multi-site
|
||||
deployment, treat them as per-site secrets:
|
||||
- Keep `config/sites/<sitename>.secrets.yaml` out of git (gitignore).
|
||||
- Distribute via secure channel (1Password, Vault, etc.) when standing up
|
||||
a new site.
|
||||
- The `eMxInfo.txt` precedent (see `feedback_emxinfo_secret.md`) is a good
|
||||
template: never commit, document where the canonical copy lives.
|
||||
184
scripts/mirror-from-gold.sh
Executable file
184
scripts/mirror-from-gold.sh
Executable file
@@ -0,0 +1,184 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# mirror-from-gold.sh - Replicate content 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.
|
||||
#
|
||||
# Source paths on GOLD use the legacy flat enrollment layout. Destination
|
||||
# paths on the new server use the reorganized layout (ppkgs/, scripts/,
|
||||
# config/, pre-install/, installers-post/, blancco/, etc).
|
||||
#
|
||||
# Usage:
|
||||
# sudo ./mirror-from-gold.sh <GOLD_IP> [options]
|
||||
#
|
||||
# Options:
|
||||
# --skip-drivers Do not mirror Dell driver tree (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).
|
||||
# --dry-run Show what would transfer without doing it.
|
||||
#
|
||||
# Prereqs:
|
||||
# - GOLD's pxe user accepts the SSH key this script generates.
|
||||
# - GOLD's filesystem is world-readable for the paths involved
|
||||
# (it is, by default).
|
||||
|
||||
# Note: not using `set -e`. rsync legitimately exits non-zero (e.g. 23
|
||||
# "some files/attrs were not transferred") when source dirs have files
|
||||
# the rsync user cannot read (the OpenText W10shortcuts dir on GOLD is
|
||||
# pxe-upload-group-only). We log and continue instead of aborting.
|
||||
set -uo pipefail
|
||||
|
||||
GOLD="${1:-}"
|
||||
shift || true
|
||||
|
||||
if [ -z "$GOLD" ]; then
|
||||
echo "Usage: $0 <GOLD_IP> [--skip-drivers|--skip-dell10|--skip-latitude|--skip-os|--dry-run]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
echo "ERROR: must run as root (sudo)."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SKIP_DRIVERS=0
|
||||
SKIP_DELL10=0
|
||||
SKIP_LATITUDE=0
|
||||
SKIP_OS=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" ;;
|
||||
*) echo "Unknown option: $1"; exit 1 ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
KEY=/root/.ssh/pxe-mirror-key
|
||||
if [ ! -f "$KEY" ]; then
|
||||
echo "[setup] Generating mirror SSH key at $KEY"
|
||||
mkdir -p /root/.ssh && chmod 700 /root/.ssh
|
||||
ssh-keygen -t ed25519 -N '' -f "$KEY" -q
|
||||
echo
|
||||
echo "Copy the following public key into pxe@$GOLD's ~/.ssh/authorized_keys"
|
||||
echo "(easiest: ssh pxe@$GOLD 'mkdir -p ~/.ssh && chmod 700 ~/.ssh' and then"
|
||||
echo " scp '$KEY.pub' pxe@$GOLD:~/.ssh/authorized_keys, then chmod 600 there)"
|
||||
echo
|
||||
cat "$KEY.pub"
|
||||
echo
|
||||
read -rp "Press enter once the key is installed on GOLD..."
|
||||
fi
|
||||
|
||||
RSH="ssh -i $KEY -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"
|
||||
|
||||
# Quick connectivity check
|
||||
echo "[check] Testing key-based SSH to pxe@$GOLD..."
|
||||
$RSH "pxe@$GOLD" "whoami" >/dev/null || {
|
||||
echo "ERROR: SSH to pxe@$GOLD failed. Install $KEY.pub on GOLD first."
|
||||
exit 1
|
||||
}
|
||||
echo " OK"
|
||||
|
||||
mirror() {
|
||||
local label="$1"
|
||||
local src="$2"
|
||||
local dest="$3"
|
||||
shift 3
|
||||
echo
|
||||
echo "==== $label ===="
|
||||
echo " src: pxe@$GOLD:$src"
|
||||
echo " dest: $dest"
|
||||
mkdir -p "$dest"
|
||||
rsync -aHl --info=progress2 --no-inc-recursive $DRY_RUN "$@" \
|
||||
-e "$RSH" \
|
||||
"pxe@$GOLD:$src" "$dest" || \
|
||||
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')
|
||||
|
||||
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/"
|
||||
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[@]}"
|
||||
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 with path translation (flat -> taxonomy) ----------
|
||||
|
||||
# Preinstall installers (adobe, opentext, drivers, display, vcredist, UDC, Oracle, etc.)
|
||||
mirror "Pre-install installers" \
|
||||
"/srv/samba/enrollment/preinstall/installers/" \
|
||||
"/srv/samba/enrollment/pre-install/installers/" \
|
||||
--exclude='*.old'
|
||||
|
||||
# CMM installers (PCDMIS) - flat dir on GOLD becomes installers-post/cmm/
|
||||
mirror "CMM installers (PCDMIS)" \
|
||||
"/srv/samba/enrollment/cmm-installers/" \
|
||||
"/srv/samba/enrollment/installers-post/cmm/"
|
||||
|
||||
# Blancco custom image - flat file on GOLD becomes blancco/<file>
|
||||
echo
|
||||
echo "==== Blancco custom image ===="
|
||||
mkdir -p /srv/samba/enrollment/blancco
|
||||
rsync -aHl --info=progress2 $DRY_RUN \
|
||||
-e "$RSH" \
|
||||
"pxe@$GOLD:/srv/samba/enrollment/BDE715_GEAE_INTERNET.img.gz" \
|
||||
"/srv/samba/enrollment/blancco/"
|
||||
|
||||
# Site-specific config file
|
||||
echo
|
||||
echo "==== Site config (site-config.json) ===="
|
||||
echo " Verifying GOLD's copy is more recent than playbook default..."
|
||||
rsync -avhl $DRY_RUN -e "$RSH" \
|
||||
"pxe@$GOLD:/srv/samba/enrollment/site-config.json" \
|
||||
"/srv/samba/enrollment/config/site-config.json" 2>/dev/null || \
|
||||
echo " (no site-config.json at flat path on GOLD - skipping)"
|
||||
|
||||
# Permissions: anything we just created should be readable by the share
|
||||
chown -R root:root /srv/samba/enrollment /srv/samba/winpeapps
|
||||
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
|
||||
|
||||
echo
|
||||
echo "============================================"
|
||||
echo "Mirror complete. Verify with:"
|
||||
echo " du -sh /srv/samba/winpeapps/_shared/*"
|
||||
echo " du -sh /srv/samba/enrollment/*"
|
||||
echo " df -h /srv"
|
||||
echo "============================================"
|
||||
Reference in New Issue
Block a user