Generic build for other GE sites: no WJ data, one shopfloor type, Windows USB builder
Everything West Jefferson specific moved out to a separate repo (pxe-site-wj): NTLARS/UDC/heat-treat backups keyed by WJ machine numbers, CMM and Wax/Trace bay lists, WJ OpenText profiles, site-config.json, the WJ preinstall list, and the WJ shopfloor PC types (Collections, NoCollections, Common, Keyence, CMM, Genspect, HeatTreat, Wax/Trace, Display, PartMarker) with GE-Enforce, machine numbers and the desktop layout. The part-marker bench tools moved to their own repo. Dead scripts removed: build-proxmox-iso, deploy-bios, sync_hardware_models, mirror-from-gold, pull-bios, startnet-template.cmd. Shopfloor is one generic type, gea-shopfloor-standard, with today's timing: - PPKG at first logon (unattend Order 10, unchanged). - Install-AppList.ps1 runs C:\PreInstall\preinstall.json during setup. - A new SYSTEM task, GE Shopfloor Post-PPKG, runs postppkg.json once after the post-PPKG reboot. It also clears AutoLogonCount after the ShopFloor handover (the Users-level monitor can be denied that HKLM write) and removes the Intune Sync task when done. - Both lists ship empty. A site adds entries and installers. - WinPE choice 3 goes straight to the PPKG menu. Staging, fetch and heal carry only the generic payload. The webapp's shopfloor sub-menu editor is gone, and the imaging tiles name the new stages. - The playbook deploys the empty lists only if missing. It now deploys the PowerShell 7 MSI the shopfloor unattend installs, which it never did before. Blancco site settings move into the webapp (Updates > Blancco releases): business location, licensing Wi-Fi SSID and password. They are rendered into the served preferences.xml and applied to every staged release, and are seeded from site-vars (site_name, blancco_wifi_ssid, blancco_wifi_password) only while none exist. The repo XML carries no site values; the plaintext Wi-Fi password is gone from it. New site_name and site_timezone settings: report and evidence-pack site name, server clock and webapp time zone. No more West Jefferson defaults in webapp/config.py or the dashboard title. Sync-BPRT.ps1 gets the server address filled in at download instead of WJ's GE address. USB on Windows: - scripts/Build-PxeUsb.ps1 runs the same checks as build-usb.sh. It writes one FAT32 CIDATA partition (ISO files plus patched grub.cfg plus payload) with diskpart and reads every file back by SHA-256. - Tested with Windows PowerShell 5.1 in the win11 VM, and the layout installs and first-boots in the pxetest VM. - scripts/stage-usb-share.sh stages the build folder on a share. - site-content/ is optional for both builders. KB docs/kb/How_To_Deploy_PXE_Server_New_Site.html: new-site deployment, Windows only, with a site-vars.yml guide. Checks: webapp tests pass (5 suites); the unattend lint and playbook syntax checks pass; every .ps1 parses; there are no WJ hosts, IPs, names or PC types in playbook/, webapp/, scripts/ or autoinstall/.
This commit is contained in:
@@ -69,9 +69,8 @@
|
||||
# Zscaler Root CA: GE's Zscaler re-signs GitHub TLS, so the iPXE update
|
||||
# check fails without it. Repo copy first, else the copy on the image share.
|
||||
zscaler_ca_src: "{{ playbook_dir }}/certs/zscaler-root-ca.crt"
|
||||
# _media/<pctype> links the base image's entries, so also look in the
|
||||
# image roots (on a rebuild the _media views may not exist yet).
|
||||
zscaler_ca_share_glob: "{{ samba_share }}/_media/*/Deploy/Applications/ZscalerCommercialCertificate-2048-SHA256.crt {{ samba_share }}/gea-*/Deploy/Applications/ZscalerCommercialCertificate-2048-SHA256.crt"
|
||||
# The copy the playbook puts in every image (Deploy/Applications).
|
||||
zscaler_ca_share_glob: "{{ samba_share }}/gea-*/Deploy/Applications/ZscalerCommercialCertificate-2048-SHA256.crt"
|
||||
# --- The two NICs (site standard) ---
|
||||
# The imaging NIC (isolated imaging LAN, static pxe_server_ip, the ONLY
|
||||
# NIC that serves DHCP/TFTP/HTTP boot/SMB) is pinned by MAC. Leave
|
||||
@@ -119,7 +118,7 @@
|
||||
pxe_imaging_mac: "{{ pxe_nic_mac }}"
|
||||
pxe_ge_mac: "{{ corp_nic_mac }}"
|
||||
# A foreign DHCP server handing out one of these domains (whole labels:
|
||||
# wjs.geaerospace.net matches, notgeaerospace.net does not) = GE network.
|
||||
# site.geaerospace.net matches, notgeaerospace.net does not) = GE network.
|
||||
pxe_corp_domain_suffixes: "geaerospace.net, ge.com"
|
||||
# Only if the IMAGING switch is itself managed and sends LLDP/CDP: its
|
||||
# LLDP system name / CDP device id / chassis MAC, comma separated, so
|
||||
@@ -145,7 +144,7 @@
|
||||
# Who may reach SSH and the webapp (9009, no login, runs as root) on the
|
||||
# GE corporate NIC. Empty (the default) = all of GE, as before, with a
|
||||
# loud warning every run. Set to the admin subnets/hosts, e.g.
|
||||
# ["10.134.48.0/24", "3.12.34.56/32"]: UFW then allows 22 and 9009 on
|
||||
# ["10.12.34.0/24", "10.12.40.5/32"]: UFW then allows 22 and 9009 on
|
||||
# the corp NIC from these only. The play refuses to restrict if your own
|
||||
# SSH session is not inside one of them. See docs/SITE-CUSTOMIZATION.md.
|
||||
corp_admin_cidrs: []
|
||||
@@ -200,6 +199,19 @@
|
||||
# letters, digits . _ ~ - (it sits in a URI, a kernel command line and
|
||||
# a mount option list), 8 to 64 of them.
|
||||
clonezilla_smb_password: "clonezilla-backup"
|
||||
# The site, as stamped on Blancco erasure reports and the monthly CMMC
|
||||
# evidence packs (webapp BLANCCO_SITE). Empty: "Unnamed site", so a
|
||||
# missing name shows instead of another site's. Letters, digits, spaces
|
||||
# and . , - ( ) & / only (it goes into a systemd unit).
|
||||
site_name: ""
|
||||
# Time zone of the server clock and of every time the webapp shows
|
||||
# (evidence-pack month boundaries included). A tz database name.
|
||||
site_timezone: "America/New_York"
|
||||
# Wi-Fi Blancco joins to license erasures in the GE Blancco cloud (the
|
||||
# imaging LAN has no internet). The SSID is GE-wide; the password can
|
||||
# differ per site. Empty password: Blancco cannot license (warned).
|
||||
blancco_wifi_ssid: "INTERNETACCESS"
|
||||
blancco_wifi_password: ""
|
||||
image_types:
|
||||
- gea-standard
|
||||
- gea-engineer
|
||||
@@ -318,6 +330,32 @@
|
||||
Fix playbook/site-vars.yml and re-run.
|
||||
quiet: yes
|
||||
|
||||
- name: "Site: check site_name and site_timezone"
|
||||
assert:
|
||||
that:
|
||||
- site_name is string
|
||||
- site_name | length == 0 or site_name is match('^[A-Za-z0-9 .,()&/-]{1,60}$')
|
||||
- site_timezone is match('^[A-Za-z0-9_+/-]{1,64}$')
|
||||
- ('/usr/share/zoneinfo/' ~ site_timezone) is file
|
||||
fail_msg: >-
|
||||
site_name must be up to 60 characters from letters, digits, spaces
|
||||
and . , - ( ) & / (no quotes); site_timezone a time zone name such
|
||||
as America/New_York, Europe/London or Asia/Kolkata. Now:
|
||||
site_name='{{ site_name }}' site_timezone='{{ site_timezone }}'.
|
||||
quiet: yes
|
||||
|
||||
- name: "Site: WARNING, site_name is not set"
|
||||
debug:
|
||||
msg:
|
||||
- "!!! site_name is empty: Blancco erasure reports and the monthly evidence"
|
||||
- "!!! packs will say 'Unnamed site'. Set site_name in playbook/site-vars.yml."
|
||||
when: site_name | length == 0
|
||||
|
||||
- name: "Site: set the time zone"
|
||||
command: timedatectl set-timezone {{ site_timezone }}
|
||||
register: tz_set
|
||||
changed_when: false
|
||||
|
||||
- name: "Clonezilla: check the clonezilla Samba password"
|
||||
assert:
|
||||
that:
|
||||
@@ -1040,8 +1078,6 @@
|
||||
- pre-install
|
||||
- pre-install/bios
|
||||
- pre-install/installers
|
||||
- installers-post
|
||||
- installers-post/cmm
|
||||
- blancco
|
||||
- logs
|
||||
|
||||
@@ -1054,10 +1090,9 @@
|
||||
Single SMB share mounted by WinPE as Y: during imaging. Subdir layout:
|
||||
- ppkgs/ GCCH bulk-enrollment PPKGs
|
||||
- scripts/ run-enrollment.ps1, wait-for-internet.ps1, migrate-to-wifi.ps1
|
||||
- config/ site-config.json, FlatUnattendW10*.xml, per-site overrides
|
||||
- shopfloor-setup/ Per-PC-type post-imaging scripts
|
||||
- pre-install/ WinPE-phase content (bios/, installers/, preinstall.json)
|
||||
- installers-post/ Post-OOBE app installers (cmm/PCDMIS, etc.)
|
||||
- config/ FlatUnattendW10*.xml, per-site overrides
|
||||
- shopfloor-setup/ Shopfloor setup scripts (gea-shopfloor-standard)
|
||||
- pre-install/ preinstall.json + postppkg.json (site app lists) and installers/
|
||||
- blancco/ Blancco custom images / configs
|
||||
- logs/ Client log uploads
|
||||
|
||||
@@ -1089,13 +1124,6 @@
|
||||
- { src: "{{ usb_mount }}/winpe-status-push.ps1", dest: "winpe-status-push.ps1" }
|
||||
ignore_errors: yes
|
||||
|
||||
- name: "Deploy site-config.json to config/"
|
||||
copy:
|
||||
src: "{{ usb_mount }}/shopfloor-setup/site-config.json"
|
||||
dest: /srv/samba/enrollment/config/site-config.json
|
||||
mode: '0644'
|
||||
ignore_errors: yes
|
||||
|
||||
- name: "Deploy Dell driver packs to shared Out-of-box Drivers"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
@@ -1138,54 +1166,31 @@
|
||||
register: shopfloor_rsync
|
||||
changed_when: shopfloor_rsync.stdout | trim | length > 0 and 'SKIP:' not in shopfloor_rsync.stdout
|
||||
|
||||
- name: "Deploy preinstall.json to pre-install/"
|
||||
# The site app lists (both empty in the generic build). force: no - once
|
||||
# a site has filled in its lists on the share, a playbook re-run must not
|
||||
# put the empty templates back.
|
||||
- name: "Deploy the site app lists to pre-install/ (only if missing)"
|
||||
copy:
|
||||
src: "{{ usb_mount }}/preinstall/preinstall.json"
|
||||
dest: /srv/samba/enrollment/pre-install/preinstall.json
|
||||
src: "{{ usb_mount }}/preinstall/{{ item }}"
|
||||
dest: "/srv/samba/enrollment/pre-install/{{ item }}"
|
||||
mode: '0644'
|
||||
ignore_errors: yes
|
||||
force: no
|
||||
loop: [preinstall.json, postppkg.json]
|
||||
|
||||
# Oracle Client 11.2 is the first app the preinstall runner executes, so it
|
||||
# has to be present on-disk before the first client images. The 686 MB
|
||||
# Oracle_OracleDatabase_11r2_V03.zip doesn't belong in git; it rides on the
|
||||
# USB under oracle/ alongside the BIOS exes. Install-Oracle11r2.cmd is
|
||||
# tracked at playbook/preinstall/oracle/ and arrives via usb_mount.
|
||||
- name: "Create pre-install/installers/oracle/ staging dir"
|
||||
file:
|
||||
path: /srv/samba/enrollment/pre-install/installers/oracle
|
||||
state: directory
|
||||
mode: '0755'
|
||||
ignore_errors: yes
|
||||
|
||||
- name: "Deploy Install-Oracle11r2.cmd to pre-install/installers/oracle/"
|
||||
copy:
|
||||
src: "{{ usb_mount }}/preinstall/oracle/Install-Oracle11r2.cmd"
|
||||
dest: /srv/samba/enrollment/pre-install/installers/oracle/Install-Oracle11r2.cmd
|
||||
mode: '0755'
|
||||
ignore_errors: yes
|
||||
|
||||
# Per-file overrides for the .ora config dropped by the wrapper post-install.
|
||||
# The zip's client/ora/ contains dated defaults; shipping an updated
|
||||
# tnsnames.ora alongside the wrapper lets us refresh the DB catalog without
|
||||
# repackaging the 686 MB zip. sqlnet.ora and ldap.ora can be added here the
|
||||
# same way if they ever need to diverge from the zip's bundled copies.
|
||||
- name: "Deploy updated tnsnames.ora override to pre-install/installers/oracle/"
|
||||
copy:
|
||||
src: "{{ usb_mount }}/preinstall/oracle/tnsnames.ora"
|
||||
dest: /srv/samba/enrollment/pre-install/installers/oracle/tnsnames.ora
|
||||
mode: '0644'
|
||||
ignore_errors: yes
|
||||
|
||||
- name: "Deploy Oracle 11.2 zip (686 MB) from USB to pre-install/installers/oracle/"
|
||||
shell: >
|
||||
if [ -f "{{ usb_root }}/oracle/Oracle_OracleDatabase_11r2_V03.zip" ]; then
|
||||
cp -f "{{ usb_root }}/oracle/Oracle_OracleDatabase_11r2_V03.zip" \
|
||||
/srv/samba/enrollment/pre-install/installers/oracle/
|
||||
echo "Deployed Oracle 11.2 zip ($(stat -c %s /srv/samba/enrollment/pre-install/installers/oracle/Oracle_OracleDatabase_11r2_V03.zip) bytes)"
|
||||
else
|
||||
echo "WARNING: {{ usb_root }}/oracle/Oracle_OracleDatabase_11r2_V03.zip not on USB - preinstall runner will fail on Oracle step until this file is staged at /srv/samba/enrollment/pre-install/installers/oracle/"
|
||||
fi
|
||||
ignore_errors: yes
|
||||
# Installers the imaging flow needs (PowerShell 7, which the shopfloor
|
||||
# unattend installs before the PPKG) plus any the site adds. Merge, no
|
||||
# delete: a site's own installers on the share stay.
|
||||
- name: "Deploy pre-install installers (PowerShell 7 MSI)"
|
||||
shell: |
|
||||
set -e
|
||||
SRC="{{ usb_mount }}/preinstall/installers/"
|
||||
[ -d "$SRC" ] || { echo "SKIP: no preinstall/installers on the USB"; exit 0; }
|
||||
mkdir -p /srv/samba/enrollment/pre-install/installers
|
||||
rsync -rlt -i --chmod=D0755,F0644 "$SRC" /srv/samba/enrollment/pre-install/installers/
|
||||
args:
|
||||
executable: /bin/bash
|
||||
register: preinstall_rsync
|
||||
changed_when: preinstall_rsync.stdout | trim | length > 0 and 'SKIP:' not in preinstall_rsync.stdout
|
||||
|
||||
- name: "Ensure winpeapps/_shared/BIOS directory exists"
|
||||
file:
|
||||
@@ -1977,10 +1982,15 @@
|
||||
# Idempotent file copy (was bundled into the previous shell task with a
|
||||
# 'creates:' gate, so playbook re-runs never picked up edits to the
|
||||
# source XML - stale prefs survived deploys).
|
||||
- name: "Deploy Blancco preferences.xml from playbook source"
|
||||
# The repo's preferences carry no site values. They are installed as
|
||||
# preferences.repo.xml; the served preferences.xml is rendered from it
|
||||
# plus the site settings (business location, licensing Wi-Fi) by the
|
||||
# webapp's services/blancco_prefs.py, after the webapp is installed
|
||||
# below. The settings are edited on Updates > Blancco releases.
|
||||
- name: "Deploy Blancco preferences (repo copy, no site values)"
|
||||
copy:
|
||||
src: "{{ usb_root }}/playbook/blancco-preferences.xml"
|
||||
dest: "{{ web_root }}/blancco/preferences.xml"
|
||||
dest: "{{ web_root }}/blancco/preferences.repo.xml"
|
||||
mode: '0644'
|
||||
|
||||
# blancco-init.sh fetches this at boot and runs it as a service in the
|
||||
@@ -1991,18 +2001,6 @@
|
||||
dest: "{{ web_root }}/blancco/blancco-progress.py"
|
||||
mode: '0644'
|
||||
|
||||
# Hard gate: blancco-init.sh in initramfs drops to shell if the served
|
||||
# preferences.xml is malformed or missing the SMB target. Fail the
|
||||
# playbook here too so the problem surfaces at deploy time, not at the
|
||||
# next erasure attempt.
|
||||
- name: "Validate deployed preferences.xml is well-formed + targets the right SMB share"
|
||||
shell: |
|
||||
set -e
|
||||
python3 -c 'import xml.etree.ElementTree as ET; ET.parse("{{ web_root }}/blancco/preferences.xml")'
|
||||
grep -q '<hostname>{{ pxe_server_ip }}</hostname>' "{{ web_root }}/blancco/preferences.xml"
|
||||
grep -q '<path>blancco-reports</path>' "{{ web_root }}/blancco/preferences.xml"
|
||||
changed_when: false
|
||||
|
||||
- name: "Ensure Samba user for Blancco reports exists (idempotent)"
|
||||
shell: |
|
||||
id blancco >/dev/null 2>&1 || useradd -r -s /usr/sbin/nologin blancco
|
||||
@@ -2404,6 +2402,39 @@
|
||||
register: webapp_wheels
|
||||
changed_when: webapp_wheels.stdout_lines | last | default('') == 'CHANGED'
|
||||
|
||||
# Blancco site settings: seeded from site-vars only while none exist
|
||||
# (after that the webapp page owns them), then the served preferences.xml
|
||||
# is rendered from preferences.repo.xml. Password via env, not argv.
|
||||
- name: "Blancco: render preferences.xml with the site settings"
|
||||
command: python3 -m services.blancco_prefs render --seed
|
||||
args:
|
||||
chdir: /opt/pxe-webapp
|
||||
environment:
|
||||
WEB_ROOT: "{{ web_root }}"
|
||||
BLANCCO_SEED_LOCATION: "{{ site_name }}"
|
||||
BLANCCO_SEED_SSID: "{{ blancco_wifi_ssid }}"
|
||||
BLANCCO_SEED_PASSWORD: "{{ blancco_wifi_password }}"
|
||||
no_log: true
|
||||
register: blancco_render
|
||||
changed_when: "'CHANGED' in blancco_render.stdout_lines"
|
||||
|
||||
- name: "Blancco: render result"
|
||||
debug:
|
||||
msg: "{{ blancco_render.stdout_lines | select('search', 'CHANGED|WARNING|seeded') | list }}"
|
||||
|
||||
# Hard gate: blancco-init.sh in initramfs drops to shell if the served
|
||||
# preferences.xml is malformed or missing the SMB target. Fail the
|
||||
# playbook here too so the problem surfaces at deploy time, not at the
|
||||
# next erasure attempt.
|
||||
- name: "Validate deployed preferences.xml is well-formed + targets the right SMB share"
|
||||
shell: |
|
||||
set -e
|
||||
python3 -c 'import xml.etree.ElementTree as ET; ET.parse("{{ web_root }}/blancco/preferences.xml")'
|
||||
grep -q '<hostname>{{ pxe_server_ip }}</hostname>' "{{ web_root }}/blancco/preferences.xml"
|
||||
grep -q '<path>blancco-reports</path>' "{{ web_root }}/blancco/preferences.xml"
|
||||
grep -q '<business_location>[^<]' "{{ web_root }}/blancco/preferences.xml"
|
||||
changed_when: false
|
||||
|
||||
- name: "Create systemd service for PXE webapp"
|
||||
copy:
|
||||
dest: /etc/systemd/system/pxe-webapp.service
|
||||
@@ -2423,10 +2454,12 @@
|
||||
Environment=ENROLLMENT_SHARE=/srv/samba/enrollment
|
||||
Environment=AUDIT_LOG=/var/log/pxe-webapp-audit.log
|
||||
# Lock TZ so report/backup mtimes and audit-log timestamps render
|
||||
# in Eastern time regardless of how the host's /etc/localtime ends
|
||||
# up. Without this, a Python process started before timedatectl
|
||||
# finishes can cache UTC for its lifetime.
|
||||
Environment=TZ=America/New_York
|
||||
# in the site's time zone regardless of how the host's
|
||||
# /etc/localtime ends up. Without this, a Python process started
|
||||
# before timedatectl finishes can cache UTC for its lifetime.
|
||||
Environment=TZ={{ site_timezone }}
|
||||
Environment=DISPLAY_TZ={{ site_timezone }}
|
||||
Environment="BLANCCO_SITE={{ site_name if site_name else 'Unnamed site' }}"
|
||||
ExecStart=/usr/bin/python3 app.py
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
@@ -2470,7 +2503,9 @@
|
||||
Type=oneshot
|
||||
WorkingDirectory=/opt/pxe-webapp
|
||||
Environment=BLANCCO_REPORTS=/srv/samba/blancco-reports
|
||||
Environment=TZ=America/New_York
|
||||
Environment=TZ={{ site_timezone }}
|
||||
Environment=DISPLAY_TZ={{ site_timezone }}
|
||||
Environment="BLANCCO_SITE={{ site_name if site_name else 'Unnamed site' }}"
|
||||
ExecStart=/usr/bin/python3 /opt/pxe-webapp/blancco_evidence_monthly.py
|
||||
- name: pxe-blancco-evidence.timer
|
||||
content: |
|
||||
|
||||
Reference in New Issue
Block a user