enrollment: auto-activate uploaded ppkg via ppkg.conf (no boot.wim edit)

startnet.cmd now sources SOURCE_PPKG/PPKG_VER/PPKG_EXP from \\<pxe>\enrollment\ppkg.conf (baked-in values kept as fallback if the file is missing). The webapp writes ppkg.conf on upload for standard GCCH_..._v<ver>.ppkg files: version parsed from the filename, optional expiry field (blank keeps current), so a new ppkg goes live at next boot with no startnet/boot.wim edit. Enrollment page shows the active ppkg. ppkg.conf seeded on the share (v4.16) and the ppkg.conf-aware startnet.cmd deployed into boot.wim.
This commit is contained in:
cproudlock
2026-07-23 11:02:43 -04:00
parent 3b63697176
commit 0ffdcc79ed
3 changed files with 82 additions and 5 deletions

View File

@@ -15,6 +15,7 @@ This file is the route surface; most logic lives in ``services/``:
import hashlib
import json
import os
import re
import shutil
import tempfile
import time
@@ -814,6 +815,37 @@ def imaging_set_laps(serial):
# Routes - Enrollment Packages
# ---------------------------------------------------------------------------
PPKG_CONF = os.path.join(config.ENROLLMENT_SHARE, "ppkg.conf")
def read_ppkg_conf():
"""Read the active-PPKG config (SOURCE_PPKG/PPKG_VER/PPKG_EXP) that
startnet.cmd sources at boot. Returns a dict (empty if unset)."""
data = {}
if os.path.isfile(PPKG_CONF):
try:
with open(PPKG_CONF, "r", errors="replace") as fh:
for line in fh:
if "=" in line:
k, _, v = line.strip().partition("=")
data[k.strip()] = v.strip()
except OSError:
pass
return data
def write_ppkg_conf(source_ppkg, ppkg_ver, ppkg_exp):
"""Write ppkg.conf (CRLF) so startnet.cmd picks up the active ppkg at
boot with no boot.wim edit."""
lines = [
f"SOURCE_PPKG={source_ppkg}",
f"PPKG_VER={ppkg_ver}",
f"PPKG_EXP={ppkg_exp}",
]
with open(PPKG_CONF, "w", newline="\r\n") as fh:
fh.write("\n".join(lines) + "\n")
@app.route("/enrollment")
def enrollment():
packages = []
@@ -830,6 +862,7 @@ def enrollment():
return render_template(
"enrollment.html",
packages=packages,
active_ppkg=read_ppkg_conf(),
image_types=config.IMAGE_TYPES,
friendly_names=config.FRIENDLY_NAMES,
)
@@ -856,6 +889,21 @@ def enrollment_upload():
f.save(dest)
audit("ENROLLMENT_UPLOAD", filename)
flash(f"Uploaded {filename} successfully.", "success")
# 2b: set this ppkg active for startnet.cmd by writing ppkg.conf on the
# share (no boot.wim edit). Only for the standard GCCH_..._v<ver>.ppkg name.
m = re.search(r"_(v\d+(?:\.\d+)*)\.ppkg$", filename, re.IGNORECASE)
if m:
ver = m.group(1)
expiry = (request.form.get("expiry") or "").strip()
if not expiry:
expiry = read_ppkg_conf().get("PPKG_EXP", "")
try:
write_ppkg_conf(filename, ver, expiry)
audit("PPKG_ACTIVATE", f"{filename} ver={ver} exp={expiry}")
flash(f"Set {filename} as the active PPKG - startnet.cmd will use it.", "success")
except OSError as exc:
flash(f"Uploaded, but could not update ppkg.conf: {exc}", "warning")
return redirect(url_for("enrollment"))