webapp: extract service layer (config.py + services/) from app.py
Phase 1a of a multi-session refactor toward a clean blueprint
structure. Pulls the helper code that lived alongside the routes in
the 1621-line app.py into focused modules. app.py is now 625 lines
of mostly routes plus a small Flask wiring header. Behaviour is
unchanged: smoke-tested against the 8 main GET routes (200 OK).
New modules:
- config.py env vars + IMAGE_TYPES + FRIENDLY_NAMES +
SHARED_DEPLOY_* taxonomy + unattend XML
namespaces.
- services/audit.py audit log file handler + audit() helper.
- services/csrf.py session CSRF token + before_request validator
wired via init_csrf(app).
- services/fs.py image_root / deploy_path / unattend_path /
control_path / tools_path + load_json /
save_json + resolve_destination.
- services/system.py service_status / find_usb_mounts /
find_upload_sources.
- services/images.py image_status + load_image_config.
- services/deploy.py import_deploy + _merge_tree +
_replace_with_symlink + allowed_import_source.
- services/unattend.py parse_unattend / build_unattend_xml /
extract_form_data and the qn / qwcm / settings
pass helpers.
- services/wim.py extract_startnet / update_startnet / list_files
wrapping wimextract / wimupdate / wimdir.
Endpoint names kept stable (dashboard, clonezilla_backups, etc.) so
existing url_for(...) calls in templates are unchanged. Phase 1b
(Flask blueprints with ".endpoint" naming) deferred to a future
session because it requires updating ~30 url_for sites in templates
and is mostly cosmetic.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
70
webapp/services/wim.py
Normal file
70
webapp/services/wim.py
Normal file
@@ -0,0 +1,70 @@
|
||||
"""boot.wim manipulation via wimtools (wimextract / wimupdate / wimdir).
|
||||
|
||||
Used by the startnet.cmd editor to extract + update the boot script
|
||||
that runs when WinPE boots from PXE.
|
||||
"""
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import tempfile
|
||||
|
||||
|
||||
def extract_startnet(wim_path):
|
||||
"""Extract startnet.cmd from a WIM file. Returns the contents or None."""
|
||||
tmpdir = tempfile.mkdtemp()
|
||||
try:
|
||||
result = subprocess.run(
|
||||
["wimextract", wim_path, "1",
|
||||
"/Windows/System32/startnet.cmd",
|
||||
"--dest-dir", tmpdir],
|
||||
capture_output=True, text=True, timeout=30,
|
||||
)
|
||||
startnet_path = os.path.join(tmpdir, "startnet.cmd")
|
||||
if result.returncode == 0 and os.path.isfile(startnet_path):
|
||||
with open(startnet_path, "r", encoding="utf-8", errors="replace") as fh:
|
||||
return fh.read()
|
||||
return None
|
||||
except Exception:
|
||||
return None
|
||||
finally:
|
||||
shutil.rmtree(tmpdir, ignore_errors=True)
|
||||
|
||||
|
||||
def update_startnet(wim_path, content):
|
||||
"""Update startnet.cmd inside a WIM file via wimupdate.
|
||||
|
||||
Returns (ok, error_message). Writes CRLF line endings.
|
||||
"""
|
||||
tmpdir = tempfile.mkdtemp()
|
||||
try:
|
||||
startnet_path = os.path.join(tmpdir, "startnet.cmd")
|
||||
with open(startnet_path, "w", encoding="utf-8", newline="\r\n") as fh:
|
||||
fh.write(content)
|
||||
update_cmd = f"add {startnet_path} /Windows/System32/startnet.cmd\n"
|
||||
result = subprocess.run(
|
||||
["wimupdate", wim_path, "1"],
|
||||
input=update_cmd,
|
||||
capture_output=True, text=True, timeout=60,
|
||||
)
|
||||
if result.returncode != 0:
|
||||
return False, result.stderr.strip()
|
||||
return True, ""
|
||||
except Exception as exc:
|
||||
return False, str(exc)
|
||||
finally:
|
||||
shutil.rmtree(tmpdir, ignore_errors=True)
|
||||
|
||||
|
||||
def list_files(wim_path, path="/"):
|
||||
"""List files inside a WIM at the given path."""
|
||||
try:
|
||||
result = subprocess.run(
|
||||
["wimdir", wim_path, "1", path],
|
||||
capture_output=True, text=True, timeout=30,
|
||||
)
|
||||
if result.returncode == 0:
|
||||
return [l.strip() for l in result.stdout.splitlines() if l.strip()]
|
||||
return []
|
||||
except Exception:
|
||||
return []
|
||||
Reference in New Issue
Block a user