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:
@@ -1648,8 +1648,6 @@ def startnet_editor():
|
||||
boot_menu=boot_menu,
|
||||
lint=lint,
|
||||
snapshots=snapshots,
|
||||
shopfloor_items=read_shopfloor_menu(),
|
||||
shopfloor_available=available_pctypes(),
|
||||
image_types=config.IMAGE_TYPES,
|
||||
friendly_names=config.FRIENDLY_NAMES,
|
||||
)
|
||||
@@ -1813,77 +1811,6 @@ def startnet_diff():
|
||||
return jsonify({"error": "provide snapshot_id or content"}), 400
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Routes - Shopfloor boot-menu (data-driven menu.json)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
SHOPFLOOR_SETUP_DIR = os.path.join(config.ENROLLMENT_SHARE, "shopfloor-setup")
|
||||
SHOPFLOOR_MENU_JSON = os.path.join(SHOPFLOOR_SETUP_DIR, "menu.json")
|
||||
|
||||
|
||||
def read_shopfloor_menu():
|
||||
"""The shopfloor PC-type menu items from menu.json (list; [] if absent)."""
|
||||
try:
|
||||
with open(SHOPFLOOR_MENU_JSON) as fh:
|
||||
return json.load(fh).get("shopfloor", [])
|
||||
except (OSError, json.JSONDecodeError):
|
||||
return []
|
||||
|
||||
|
||||
def available_pctypes():
|
||||
"""gea-shopfloor-* handler dirs on the share - the only valid menu keys."""
|
||||
try:
|
||||
return sorted(
|
||||
d for d in os.listdir(SHOPFLOOR_SETUP_DIR)
|
||||
if d.startswith("gea-shopfloor-")
|
||||
and os.path.isdir(os.path.join(SHOPFLOOR_SETUP_DIR, d))
|
||||
)
|
||||
except OSError:
|
||||
return []
|
||||
|
||||
|
||||
@app.route("/shopfloor-menu", methods=["GET", "POST"])
|
||||
def shopfloor_menu():
|
||||
if request.method == "POST":
|
||||
try:
|
||||
items = json.loads(request.form.get("items", "[]"))
|
||||
except json.JSONDecodeError:
|
||||
flash("Invalid menu payload.", "danger")
|
||||
return redirect(url_for("startnet_editor") + "#tab-shopfloor")
|
||||
valid = set(available_pctypes())
|
||||
clean = []
|
||||
for it in items:
|
||||
if not isinstance(it, dict):
|
||||
continue
|
||||
key = (it.get("key") or "").strip()
|
||||
label = (it.get("label") or "").strip()
|
||||
if not key or not label:
|
||||
continue
|
||||
if key not in valid:
|
||||
flash(f"Skipped '{label}': {key} has no shopfloor-setup handler.", "warning")
|
||||
continue
|
||||
clean.append({
|
||||
"key": key,
|
||||
"label": label,
|
||||
"hint": (it.get("hint") or "").strip(),
|
||||
"enabled": bool(it.get("enabled", True)),
|
||||
})
|
||||
if not clean:
|
||||
flash("Refused to save an empty menu.", "danger")
|
||||
return redirect(url_for("startnet_editor") + "#tab-shopfloor")
|
||||
try:
|
||||
os.makedirs(SHOPFLOOR_SETUP_DIR, exist_ok=True)
|
||||
with open(SHOPFLOOR_MENU_JSON, "w") as fh:
|
||||
json.dump({"shopfloor": clean}, fh, indent=2)
|
||||
audit("SHOPFLOOR_MENU_SAVE", f"{len(clean)} items")
|
||||
flash("Shopfloor boot menu saved - WinPE reads it at next boot.", "success")
|
||||
except OSError as exc:
|
||||
flash(f"Could not write menu.json: {exc}", "danger")
|
||||
return redirect(url_for("startnet_editor") + "#tab-shopfloor")
|
||||
|
||||
return redirect(url_for("startnet_editor") + "#tab-shopfloor")
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Routes - Audit Log
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -2064,6 +1991,7 @@ app.jinja_env.globals["blancco_failure_reason"] = blancco_report.failure_reason
|
||||
@app.context_processor
|
||||
def inject_globals():
|
||||
return {
|
||||
"site_name": config.BLANCCO_SITE,
|
||||
"all_image_types": config.IMAGE_TYPES,
|
||||
"all_friendly_names": config.FRIENDLY_NAMES,
|
||||
# image pages: tab table, header data, tab URLs (see _image_header.html)
|
||||
|
||||
Reference in New Issue
Block a user