Fehlte bisher komplett - backends/mint/ enthielt nur handgepatchte WLAN-Test-Artefakte, kein backend.sh, sodass 40_backend.sh mit "Kein Backend für 'mint' gefunden" abbrach. Baut auf dem bereits real erprobten wlan-test.seed-Muster auf (Ubiquity/ Preseed, nicht Subiquity/Autoinstall - siehe ADR-0009), generalisiert zu einem echten Template mit denselben Platzhaltern wie Fedoras kickstart.tpl: - backends/mint/backend.sh: 5-Funktionen-Contract 1:1 wie Fedora (backend_init/validate/generate_config/launch/postinstall), backend_launch() bewusst als Stub (echte Parität mit Fedoras heutigem Stand, kein Vorgriff auf das noch nicht entschiedene Self-Service-Portal-Modell). - backends/mint/preseed.tpl + postinstall.sh: echter Agent-Bootstrap (curl agent.py, Bootstrap-POST, Credentials, systemd enable) im ubiquity/success_command, zweistufig envsubst+base64 gerendert (Debconf-Fallstrick bei mehrzeiligen Preseed-Werten, real erprobt). - scripts/build.sh: Backend-Argument (fedora|mint), Mint-Pfade real gegen die vorhandene Test-ISO verifiziert (/boot/grub/grub.cfg, /isolinux/live.cfg, /preseed/tuxflotte.seed - keine zweite ESP-Kopie wie bei Fedora), Test-Preseed-Bake mit Platzhalterwerten. - profiles/mint-desktop/profile.json: installer.type von "autoinstall" auf "preseed" korrigiert (ADR-0009 hatte den alten Wert als vermutlich falsch benannt markiert - jetzt bestätigt und korrigiert). End-to-end auf echter QEMU-Hardware verifiziert: automatisierte Installation, Reboot, Agent-Bootstrap, Check-in, ansible-pull-Zyklus (PLAY RECAP failed=0) - kompletter Kreislauf funktioniert. Dabei gefunden und gefixt: d-i pkgsel/include string ansible-core git fehlte (Pendant zu Fedoras kickstart.tpl %packages) - ohne das lief der Agent-Dienst in einer Restart-Fehlerschleife. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
166 lines
6.2 KiB
Bash
166 lines
6.2 KiB
Bash
#!/usr/bin/env bash
|
|
set -Eeuo pipefail
|
|
|
|
# Dieses Skript wird von einem Orchestrator-Modul (z.B. 40_backend.sh) per
|
|
# `source` in dessen Shell geladen. Variablen bleiben deshalb bewusst nicht
|
|
# readonly, um Namenskollisionen mit dem ladenden Modul zu vermeiden.
|
|
BACKEND_KEY="mint"
|
|
|
|
BACKEND_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PRESEED_TEMPLATE="${BACKEND_DIR}/preseed.tpl"
|
|
POSTINSTALL_SCRIPT="${BACKEND_DIR}/postinstall.sh"
|
|
|
|
RUNTIME_BLUEPRINT_FILE="/run/tuxflotte/runtime/runtime_blueprint.json"
|
|
SERVER_RESPONSE_FILE="/run/tuxflotte/server/response.json"
|
|
|
|
RUNTIME_DIR="/run/tuxflotte/backend"
|
|
CONFIG_FILE="${RUNTIME_DIR}/config"
|
|
|
|
backend_log() {
|
|
printf '[backend:%s] %s\n' "${BACKEND_KEY}" "$*" >&2
|
|
}
|
|
|
|
backend_fatal() {
|
|
printf '[backend:%s] FEHLER: %s\n' "${BACKEND_KEY}" "$*" >&2
|
|
return 1
|
|
}
|
|
|
|
backend_init() {
|
|
for cmd in jq envsubst base64; do
|
|
command -v "${cmd}" >/dev/null 2>&1 ||
|
|
{ backend_fatal "Benötigtes Werkzeug fehlt: ${cmd}"; return 1; }
|
|
done
|
|
|
|
[[ -r "${PRESEED_TEMPLATE}" ]] ||
|
|
{ backend_fatal "Preseed-Template nicht gefunden: ${PRESEED_TEMPLATE}"; return 1; }
|
|
|
|
[[ -r "${POSTINSTALL_SCRIPT}" ]] ||
|
|
{ backend_fatal "Postinstall-Skript nicht gefunden: ${POSTINSTALL_SCRIPT}"; return 1; }
|
|
|
|
install -d \
|
|
--mode=0700 \
|
|
--owner=root \
|
|
--group=root \
|
|
"${RUNTIME_DIR}"
|
|
|
|
rm -f -- "${CONFIG_FILE}"
|
|
|
|
backend_log "Initialisiert."
|
|
}
|
|
|
|
backend_validate() {
|
|
[[ -r "${RUNTIME_BLUEPRINT_FILE}" ]] ||
|
|
{ backend_fatal "Runtime Blueprint nicht gefunden: ${RUNTIME_BLUEPRINT_FILE}"; return 1; }
|
|
|
|
jq --exit-status \
|
|
--arg backend_key "${BACKEND_KEY}" \
|
|
'.runtime_blueprint.backend_id == $backend_key' \
|
|
"${RUNTIME_BLUEPRINT_FILE}" >/dev/null ||
|
|
{ backend_fatal "Runtime Blueprint ist nicht für Backend '${BACKEND_KEY}' aufgelöst."; return 1; }
|
|
|
|
jq --exit-status '
|
|
.runtime_blueprint.installation_directives
|
|
| (.disk_encryption | type == "boolean")
|
|
and (.partitioning | type == "string")
|
|
and (.secure_boot_required | type == "boolean")
|
|
' "${RUNTIME_BLUEPRINT_FILE}" >/dev/null ||
|
|
{ backend_fatal "Installationszeitliche Vorgaben fehlen oder sind ungültig."; return 1; }
|
|
|
|
# disk_encryption wird für Mint (noch) nicht unterstützt - kein getesteter
|
|
# LUKS-Preseed-Mechanismus (anders als Fedoras "autopart --encrypted").
|
|
if [[ "$(jq --raw-output '.runtime_blueprint.installation_directives.disk_encryption' "${RUNTIME_BLUEPRINT_FILE}")" == "true" ]]; then
|
|
backend_fatal "disk_encryption=true wird vom Mint-Backend derzeit nicht unterstützt."
|
|
return 1
|
|
fi
|
|
|
|
backend_log "Runtime Blueprint ist gültig für Backend '${BACKEND_KEY}'."
|
|
}
|
|
|
|
backend_generate_config() {
|
|
local hostname
|
|
local device_id
|
|
local partitioning
|
|
local secure_boot_required
|
|
local partman_recipe
|
|
local blueprints_json
|
|
local postinstall_rendered
|
|
local postinstall_b64
|
|
|
|
[[ -r "${SERVER_RESPONSE_FILE}" ]] ||
|
|
{ backend_fatal "Serverantwort nicht gefunden: ${SERVER_RESPONSE_FILE}"; return 1; }
|
|
|
|
hostname="$(jq --raw-output '.device.hostname // empty' "${SERVER_RESPONSE_FILE}")"
|
|
[[ -n "${hostname}" ]] ||
|
|
{ backend_fatal "Kein Hostname in der Serverantwort gefunden."; return 1; }
|
|
|
|
device_id="$(jq --raw-output '.device.id // empty' "${SERVER_RESPONSE_FILE}")"
|
|
[[ -n "${device_id}" ]] ||
|
|
{ backend_fatal "Keine Geräte-ID in der Serverantwort gefunden."; return 1; }
|
|
|
|
partitioning="$(jq --raw-output '.runtime_blueprint.installation_directives.partitioning' "${RUNTIME_BLUEPRINT_FILE}")"
|
|
secure_boot_required="$(jq --raw-output '.runtime_blueprint.installation_directives.secure_boot_required' "${RUNTIME_BLUEPRINT_FILE}")"
|
|
|
|
case "${partitioning}" in
|
|
default)
|
|
partman_recipe="atomic"
|
|
;;
|
|
*)
|
|
backend_fatal "Nicht unterstützte Partitionierungsvorgabe: ${partitioning}"
|
|
return 1
|
|
;;
|
|
esac
|
|
|
|
if [[ "${secure_boot_required}" == "true" ]]; then
|
|
backend_log "Hinweis: secure_boot_required=true wird derzeit nicht in der Preseed-Konfiguration durchgesetzt (Phase 1)."
|
|
fi
|
|
|
|
blueprints_json="$(jq --compact-output '.runtime_blueprint.blueprints' "${RUNTIME_BLUEPRINT_FILE}")"
|
|
|
|
# Erste Stufe: postinstall.sh-Platzhalter auflösen.
|
|
postinstall_rendered="$(
|
|
TUXFLOTTE_DEVICE_ID="${device_id}" \
|
|
TUXFLOTTE_BLUEPRINTS_JSON="${blueprints_json}" \
|
|
envsubst '${TUXFLOTTE_DEVICE_ID} ${TUXFLOTTE_BLUEPRINTS_JSON}' \
|
|
<"${POSTINSTALL_SCRIPT}"
|
|
)"
|
|
|
|
if grep -q '\${TUXFLOTTE_' <<<"${postinstall_rendered}"; then
|
|
backend_fatal "postinstall.sh enthält nach envsubst nicht aufgelöste Platzhalter."
|
|
return 1
|
|
fi
|
|
|
|
# base64-Kodierung: mehrzeilige/zitierte Preseed-Werte brechen unter
|
|
# Debconf lautlos (real erprobt, siehe backends/mint/wlan-test.seed) -
|
|
# als einzeiliger Base64-Blob besteht der success_command-Wert nur noch
|
|
# aus unkritischen Zeichen.
|
|
postinstall_b64="$(printf '%s' "${postinstall_rendered}" | base64 -w0)"
|
|
|
|
# Zweite Stufe: preseed.tpl mit allen Werten inkl. des fertigen Base64-Blobs auflösen.
|
|
TUXFLOTTE_HOSTNAME="${hostname}" \
|
|
TUXFLOTTE_PARTMAN_RECIPE="${partman_recipe}" \
|
|
TUXFLOTTE_POSTINSTALL_B64="${postinstall_b64}" \
|
|
envsubst '${TUXFLOTTE_HOSTNAME} ${TUXFLOTTE_PARTMAN_RECIPE} ${TUXFLOTTE_POSTINSTALL_B64}' \
|
|
<"${PRESEED_TEMPLATE}" >"${CONFIG_FILE}"
|
|
|
|
chmod 0600 "${CONFIG_FILE}"
|
|
|
|
[[ -s "${CONFIG_FILE}" ]] ||
|
|
{ backend_fatal "Erzeugte Konfigurationsdatei ist leer: ${CONFIG_FILE}"; return 1; }
|
|
|
|
if grep -q '\${TUXFLOTTE_' "${CONFIG_FILE}"; then
|
|
backend_fatal "Erzeugte Konfigurationsdatei enthält nicht aufgelöste Platzhalter."
|
|
return 1
|
|
fi
|
|
|
|
backend_log "Konfiguration erzeugt: ${CONFIG_FILE}"
|
|
}
|
|
|
|
backend_launch() {
|
|
backend_log "Phase 1: Start des nativen Installers ist noch nicht aktiv."
|
|
backend_log "Erzeugte Konfiguration liegt bereit unter: ${CONFIG_FILE}"
|
|
}
|
|
|
|
backend_postinstall() {
|
|
backend_log "Provisioning-Agent-Einrichtung erfolgt im ubiquity/success_command der Preseed-Konfiguration (Agent-Abruf, Bootstrap-Registrierung, systemd-Aktivierung)."
|
|
}
|