feat: personalisierte ISO-Volume-ID aus Organisationsname + Bau-Datum

compute_iso_volid() sanitisiert den Organisationsnamen ISO9660-konform
(Grossbuchstaben/Ziffern/Unterstrich, max. 32 Zeichen, NFKD-Fallback fuer
Umlaute, 'ORG'-Fallback falls kein ASCII-Zeichen uebrig bleibt) und haengt
das Bau-Datum (UTC) an. run_iso_build() reicht das Ergebnis als sechsten
Parameter an build_customer_iso.sh durch, statt des bisher fest codierten
'TUXFLOTTE'-Labels.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Thomas Stallinger 2026-08-25 09:01:53 +02:00
parent 34e5254984
commit c0877548ec

27
app.py
View File

@ -4,9 +4,11 @@ import hashlib
import hmac
import json
import os
import re
import secrets
import subprocess
import threading
import unicodedata
from uuid import UUID, uuid4
import psycopg
@ -2184,11 +2186,35 @@ def cleanup_old_iso_builds(organization_id: str, keep_build_id) -> None:
(organization_id, keep_build_id),
)
def compute_iso_volid(organization_name: str) -> str:
"""
ISO9660-Volume-ID fuer eine personalisierte Kunden-ISO: Organisationsname
+ Bau-Datum, damit ein gemountetes/im Dateimanager angezeigtes Medium
erkennbar ist, statt bei der festen generischen Bezeichnung zu bleiben.
ISO9660 erlaubt fuer die Primary-Volume-Descriptor-Volume-ID nur
Grossbuchstaben/Ziffern/Unterstrich und maximal 32 Zeichen - Umlaute
u.ae. werden per NFKD-Normalisierung auf ihr ASCII-Grundzeichen
reduziert (z.B. "Groesse" statt Wegfall), alles andere zu "_"
zusammengefasst. Faellt bei einem Namen ohne jedes ASCII-Zeichen (z.B.
rein kyrillisch/chinesisch) auf "ORG" zurueck statt eine leere
Volume-ID zu erzeugen.
"""
ascii_only = unicodedata.normalize("NFKD", organization_name).encode("ascii", "ignore").decode("ascii")
sanitized = re.sub(r"[^A-Za-z0-9]+", "_", ascii_only).strip("_").upper()
date_suffix = datetime.now(timezone.utc).strftime("%Y%m%d")
max_name_len = 32 - 1 - len(date_suffix) # 32 - "_" - "YYYYMMDD"
sanitized = sanitized[:max_name_len].rstrip("_") or "ORG"
return f"{sanitized}_{date_suffix}"
def run_iso_build(build_id, organization_id: str, activation_code: str, wifi_ssid: str | None, wifi_psk: str | None) -> None:
output_path = ISO_BUILD_OUTPUT_DIR / f"{build_id}.iso"
update_iso_build(build_id, status="running", mark_started=True)
organization = fetch_organization(organization_id)
volid = compute_iso_volid(organization["name"] if organization else "TUXFLOTTE")
try:
result = subprocess.run(
[
@ -2199,6 +2225,7 @@ def run_iso_build(build_id, organization_id: str, activation_code: str, wifi_ssi
activation_code,
wifi_ssid or "",
wifi_psk or "",
volid,
],
cwd=TUXFLOTTE_INSTALLER_DIR,
capture_output=True,