feat: Auto-Modus + prozentuale Partitionierung für Mint (Phase 2)
Auto-Modus (TUXFLOTTE_AUTO_MODE=true, über config/installer.conf als
exportierte Env-Var vor 05_network.sh gesetzt) überspringt alle drei
interaktiven Gates, die bei genauerem Hinsehen existierten (nicht nur
das eine ursprünglich im Plan genannte):
- 05_network.sh: nicht-interaktiver WLAN-Pfad über TUXFLOTTE_WIFI_SSID/
TUXFLOTTE_WIFI_PSK, analog zum bestehenden TUXFLOTTE_ACTIVATION_CODE-
Muster in 12_enrollment_auth.sh (unverändert, unterstützte das schon).
- 17_device_status.sh: "Provisionierung fortsetzen?"-Prompt übersprungen.
- 20_profile_selection.sh: "Vorlage auswählen?"-Prompt übersprungen,
wählt automatisch die als is_default markierte Vorlage (echter
Server-Hinweis via Enrollment Session erst mit Phase 3 möglich).
- 25_installation_confirm.sh: eigentliches Commit-Gate übersprungen.
Alle drei Auto-Modus-Zweige lokal verifiziert (Skripte direkt mit
TUXFLOTTE_AUTO_MODE=true und präparierten Eingabedateien ausgeführt,
kein Hängenbleiben an read -p, korrekte state.env/template.json-Ausgabe).
Partitionierung: installation_directives.partitioning von einfachem
String auf strukturiertes Objekt umgestellt ({"scheme": "single"|
"custom", "root_filesystem", "extra_partitions": [{"mountpoint",
"filesystem", "percent"}]}) - Vertrag, an den sich provisioning-server
in Phase 3 halten muss. backend_generate_config() baut daraus ein
partman-auto/expert_recipe (ersetzt die bisherige choose_recipe-
Fallunterscheidung mit nur "default"/"atomic"), Prozentangaben werden
anhand der realen Zieldatenträgergröße (lsblk/blockdev, erst live auf
dem Zielgerät bekannt) in feste MB-Größen umgerechnet.
Auf UEFI-Systemen wird zusätzlich eine EFI-System-Partition ins Recipe
aufgenommen (sonst verweigert/warnt der Installer, "No EFI System
Partition was found") - exakte Stanza-Syntax nicht aus der Erinnerung
geraten, sondern aus /usr/lib/partman/recipes-amd64-efi/30atomic auf
dem echten Live-Medium ausgelesen ($reusemethod{ } war der fehlende
Teil in einem ersten, geparsten aber nicht erkannten Versuch).
backend_init() installiert jetzt auch jq/envsubst(gettext-base)/cpio
bei Bedarf nach (vorbestehende Lücke neben dem schon in Phase 1
behobenen kexec-tools).
Real per QEMU verifiziert: eigene Ein-Datenträger-Erkennung musste
gehärtet werden (nbd/zram-Geräte mit Größe 0 wurden fälschlich vor dem
echten Datenträger gewählt - auf einer sauberen VM allein wäre das nicht
aufgefallen). Custom-Recipe mit ext4-Root + ext4-/home (20%) +
btrfs-/var (10%) auf 40GB-Testplatte: vollständige unbeaufsichtigte
Installation inkl. Paketinstallation durchlaufen lassen, danach von der
Festplatte (nicht der Live-CD) gebootet - Login-Bildschirm mit korrektem
Hostname erscheint, System bootet einwandfrei per UEFI/ESP.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
d6a01462ef
commit
108444ecf7
@ -26,27 +26,35 @@ backend_fatal() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
backend_init() {
|
backend_init() {
|
||||||
for cmd in jq envsubst base64; do
|
# jq/envsubst(gettext-base)/cpio/kexec-tools sind auf dem Live-Medium
|
||||||
command -v "${cmd}" >/dev/null 2>&1 ||
|
# selbst (anders als im Zielsystem, siehe pkgsel/include in preseed.tpl)
|
||||||
{ backend_fatal "Benötigtes Werkzeug fehlt: ${cmd}"; return 1; }
|
# nicht vorinstalliert - real gegen das Live-Abbild verifiziert
|
||||||
done
|
# (Phase-1-Spike, zunächst nur für kexec-tools behoben, hier auf alle
|
||||||
|
# vier Live-only-Werkzeuge ausgeweitet). base64 kommt aus coreutils und
|
||||||
|
# ist auf jedem Debian-Derivat immer vorhanden, deshalb ohne Nachinstal-
|
||||||
|
# lationspfad.
|
||||||
|
local live_packages_needed=()
|
||||||
|
|
||||||
# kexec-tools ist auf dem Live-Medium selbst (anders als im Zielsystem,
|
command -v jq >/dev/null 2>&1 || live_packages_needed+=(jq)
|
||||||
# siehe pkgsel/include in preseed.tpl) nicht vorinstalliert - real gegen
|
command -v envsubst >/dev/null 2>&1 || live_packages_needed+=(gettext-base)
|
||||||
# das Live-Abbild verifiziert (Phase-1-Spike). Bis das Paket fest in die
|
command -v cpio >/dev/null 2>&1 || live_packages_needed+=(cpio)
|
||||||
# ISO gebacken wird (Folgeschritt), hier als Live-Nachinstallation.
|
command -v kexec >/dev/null 2>&1 || live_packages_needed+=(kexec-tools)
|
||||||
if ! command -v kexec >/dev/null 2>&1; then
|
|
||||||
backend_log "kexec-tools fehlt auf dem Live-Medium, installiere nach."
|
if [[ "${#live_packages_needed[@]}" -gt 0 ]]; then
|
||||||
|
backend_log "Werkzeuge fehlen auf dem Live-Medium, installiere nach: ${live_packages_needed[*]}"
|
||||||
|
|
||||||
sed -i '/^deb cdrom/d' /etc/apt/sources.list 2>/dev/null || true
|
sed -i '/^deb cdrom/d' /etc/apt/sources.list 2>/dev/null || true
|
||||||
rm -f /etc/apt/sources.list.d/*cdrom* 2>/dev/null || true
|
rm -f /etc/apt/sources.list.d/*cdrom* 2>/dev/null || true
|
||||||
|
|
||||||
apt-get update -qq ||
|
apt-get update -qq ||
|
||||||
{ backend_fatal "apt-get update fehlgeschlagen (kexec-tools)."; return 1; }
|
{ backend_fatal "apt-get update fehlgeschlagen."; return 1; }
|
||||||
DEBIAN_FRONTEND=noninteractive apt-get install -y kexec-tools ||
|
DEBIAN_FRONTEND=noninteractive apt-get install -y "${live_packages_needed[@]}" ||
|
||||||
{ backend_fatal "Installation von kexec-tools fehlgeschlagen."; return 1; }
|
{ backend_fatal "Installation fehlender Werkzeuge fehlgeschlagen."; return 1; }
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
command -v base64 >/dev/null 2>&1 ||
|
||||||
|
{ backend_fatal "Benötigtes Werkzeug fehlt: base64"; return 1; }
|
||||||
|
|
||||||
[[ -r "${PRESEED_TEMPLATE}" ]] ||
|
[[ -r "${PRESEED_TEMPLATE}" ]] ||
|
||||||
{ backend_fatal "Preseed-Template nicht gefunden: ${PRESEED_TEMPLATE}"; return 1; }
|
{ backend_fatal "Preseed-Template nicht gefunden: ${PRESEED_TEMPLATE}"; return 1; }
|
||||||
|
|
||||||
@ -77,7 +85,7 @@ backend_validate() {
|
|||||||
jq --exit-status '
|
jq --exit-status '
|
||||||
.runtime_blueprint.installation_directives
|
.runtime_blueprint.installation_directives
|
||||||
| (.disk_encryption | type == "boolean")
|
| (.disk_encryption | type == "boolean")
|
||||||
and (.partitioning | type == "string")
|
and (.partitioning | type == "object")
|
||||||
and (.secure_boot_required | type == "boolean")
|
and (.secure_boot_required | type == "boolean")
|
||||||
' "${RUNTIME_BLUEPRINT_FILE}" >/dev/null ||
|
' "${RUNTIME_BLUEPRINT_FILE}" >/dev/null ||
|
||||||
{ backend_fatal "Installationszeitliche Vorgaben fehlen oder sind ungültig."; return 1; }
|
{ backend_fatal "Installationszeitliche Vorgaben fehlen oder sind ungültig."; return 1; }
|
||||||
@ -92,10 +100,144 @@ backend_validate() {
|
|||||||
backend_log "Runtime Blueprint ist gültig für Backend '${BACKEND_KEY}'."
|
backend_log "Runtime Blueprint ist gültig für Backend '${BACKEND_KEY}'."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Baut einen einzelnen partman-auto/expert_recipe-Partitionsblock als
|
||||||
|
# EINZEILIGEN String (Felder durch Leerzeichen statt Zeilenumbrueche
|
||||||
|
# getrennt) - Debconf-Preseed-Werte mit eingebetteten Zeilenumbruechen
|
||||||
|
# brechen leicht lautlos (siehe base64-Kommentar bei success_command weiter
|
||||||
|
# unten fuer denselben Fallstrick an anderer Stelle), partmans Parser selbst
|
||||||
|
# ist bei Leerzeichen als Trenner tolerant.
|
||||||
|
_tuxflotte_partman_stanza() {
|
||||||
|
local size_mb="$1"
|
||||||
|
local filesystem="$2"
|
||||||
|
local mountpoint="$3"
|
||||||
|
local extra_flags="${4:-}"
|
||||||
|
|
||||||
|
printf '%s %s %s %s %s method{ format } format{ } use_filesystem{ } filesystem{ %s } mountpoint{ %s } . ' \
|
||||||
|
"${size_mb}" "${size_mb}" "${size_mb}" "${filesystem}" "${extra_flags}" "${filesystem}" "${mountpoint}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Ermittelt den ersten echten Datentraeger des Zielgeraets fuer die
|
||||||
|
# Groessenberechnung bei prozentualer Partitionierung (Fedoras autopart macht
|
||||||
|
# implizit dieselbe Ein-Datentraeger-Annahme, siehe fedora/backend.sh).
|
||||||
|
# Groessenfilter (>0) und Namensausschluss noetig - reale Systeme koennen
|
||||||
|
# nbd-/zram-/loop-Geraete mit type=="disk" aber ohne echte Speicherkapazitaet
|
||||||
|
# auflisten, die sonst faelschlich vor dem echten Zieldatentraeger gewaehlt
|
||||||
|
# wuerden (real beim Testen entdeckt).
|
||||||
|
_tuxflotte_detect_target_disk() {
|
||||||
|
lsblk --nodeps --noheadings --bytes --output NAME,TYPE,SIZE --paths |
|
||||||
|
awk '$2 == "disk" && $3 > 0 && $1 !~ /(nbd|zram|loop)[0-9]*$/ { print $1; exit }'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Baut den kompletten partman-auto/expert_recipe-Rezeptkoerper aus dem
|
||||||
|
# installation_directives.partitioning-Objekt. Prozentangaben werden anhand
|
||||||
|
# der realen Zieldatentraegergroesse (erst hier, live auf dem Zielgeraet,
|
||||||
|
# bekannt - nicht beim ISO-Bau) in feste MB-Groessen umgerechnet. Bewusst
|
||||||
|
# feste Groessen (min=priority=max) statt partmans eigener proportionaler
|
||||||
|
# Prioritaets-Verteilung - deterministischer und leichter zu verifizieren.
|
||||||
|
_tuxflotte_render_partman_recipe() {
|
||||||
|
local partitioning_json="$1"
|
||||||
|
local root_filesystem="$2"
|
||||||
|
local scheme
|
||||||
|
local disk_device
|
||||||
|
local disk_size_mb
|
||||||
|
local extra_count
|
||||||
|
local extra_percent_sum=0
|
||||||
|
local root_mb
|
||||||
|
local recipe_body=""
|
||||||
|
local i
|
||||||
|
local mountpoint
|
||||||
|
local filesystem
|
||||||
|
local percent
|
||||||
|
local size_mb
|
||||||
|
local esp_mb=0
|
||||||
|
|
||||||
|
scheme="$(jq --raw-output '.scheme // "single"' <<<"${partitioning_json}")"
|
||||||
|
|
||||||
|
disk_device="$(_tuxflotte_detect_target_disk)"
|
||||||
|
[[ -n "${disk_device}" ]] ||
|
||||||
|
{ backend_fatal "Zieldatenträger konnte nicht ermittelt werden."; return 1; }
|
||||||
|
disk_size_mb="$(( $(blockdev --getsize64 "${disk_device}") / 1024 / 1024 ))"
|
||||||
|
|
||||||
|
# Die eingebauten partman-Recipes ("atomic" etc.) legen auf UEFI-Systemen
|
||||||
|
# automatisch eine EFI-System-Partition an - ein eigenes expert_recipe
|
||||||
|
# muss das selbst tun, sonst warnt/verweigert der Installer (real beim
|
||||||
|
# Testen entdeckt: "No EFI System Partition was found"). 512 MB vorab
|
||||||
|
# reserviert, vor der Prozentaufteilung der restlichen Platte.
|
||||||
|
if [[ -d /sys/firmware/efi ]]; then
|
||||||
|
# Exakte Stanza-Form aus der eingebauten "atomic"-Recipe uebernommen
|
||||||
|
# (/usr/lib/partman/recipes-amd64-efi/30atomic auf dem Live-Medium
|
||||||
|
# ausgelesen) - eine erste eigene Vermutung ohne $reusemethod{ } und
|
||||||
|
# mit $bootable{ } wurde von partman zwar anstandslos geparst, aber
|
||||||
|
# nicht als gueltige EFI-System-Partition erkannt ("No EFI System
|
||||||
|
# Partition was found", real beim Testen entdeckt).
|
||||||
|
esp_mb=512
|
||||||
|
disk_size_mb="$(( disk_size_mb - esp_mb ))"
|
||||||
|
recipe_body="${esp_mb} ${esp_mb} ${esp_mb} fat32 \$reusemethod{ } \$primary{ } method{ efi } format{ } . "
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "${scheme}" in
|
||||||
|
single)
|
||||||
|
root_mb="$(( disk_size_mb - 1024 ))"
|
||||||
|
[[ "${root_mb}" -ge 2048 ]] ||
|
||||||
|
{ backend_fatal "Zieldatenträger ist zu klein (${disk_size_mb} MB)."; return 1; }
|
||||||
|
|
||||||
|
recipe_body="${recipe_body}$(_tuxflotte_partman_stanza "${root_mb}" "${root_filesystem}" "/" '$primary{ } $bootable{ }')"
|
||||||
|
;;
|
||||||
|
custom)
|
||||||
|
extra_count="$(jq '.extra_partitions | length' <<<"${partitioning_json}")"
|
||||||
|
[[ "${extra_count}" -gt 0 ]] ||
|
||||||
|
{ backend_fatal "scheme=custom ohne extra_partitions angegeben."; return 1; }
|
||||||
|
|
||||||
|
for ((i = 0; i < extra_count; i++)); do
|
||||||
|
mountpoint="$(jq --raw-output ".extra_partitions[${i}].mountpoint" <<<"${partitioning_json}")"
|
||||||
|
filesystem="$(jq --raw-output ".extra_partitions[${i}].filesystem" <<<"${partitioning_json}")"
|
||||||
|
percent="$(jq --raw-output ".extra_partitions[${i}].percent" <<<"${partitioning_json}")"
|
||||||
|
|
||||||
|
case "${mountpoint}" in
|
||||||
|
/home|/var) ;;
|
||||||
|
*) backend_fatal "Nicht unterstützter Einhängepunkt: ${mountpoint}"; return 1 ;;
|
||||||
|
esac
|
||||||
|
case "${filesystem}" in
|
||||||
|
ext4|btrfs) ;;
|
||||||
|
*) backend_fatal "Nicht unterstütztes Dateisystem: ${filesystem}"; return 1 ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
extra_percent_sum="$(( extra_percent_sum + percent ))"
|
||||||
|
done
|
||||||
|
|
||||||
|
[[ "${extra_percent_sum}" -gt 0 && "${extra_percent_sum}" -lt 90 ]] ||
|
||||||
|
{ backend_fatal "Summe der Partitions-Prozentangaben ist ungültig: ${extra_percent_sum}"; return 1; }
|
||||||
|
|
||||||
|
root_mb="$(( disk_size_mb * (100 - extra_percent_sum) / 100 - 1024 ))"
|
||||||
|
[[ "${root_mb}" -ge 2048 ]] ||
|
||||||
|
{ backend_fatal "Root-Partition wäre bei dieser Aufteilung zu klein."; return 1; }
|
||||||
|
|
||||||
|
recipe_body="${recipe_body}$(_tuxflotte_partman_stanza "${root_mb}" "${root_filesystem}" "/" '$primary{ } $bootable{ }')"
|
||||||
|
|
||||||
|
for ((i = 0; i < extra_count; i++)); do
|
||||||
|
mountpoint="$(jq --raw-output ".extra_partitions[${i}].mountpoint" <<<"${partitioning_json}")"
|
||||||
|
filesystem="$(jq --raw-output ".extra_partitions[${i}].filesystem" <<<"${partitioning_json}")"
|
||||||
|
percent="$(jq --raw-output ".extra_partitions[${i}].percent" <<<"${partitioning_json}")"
|
||||||
|
size_mb="$(( disk_size_mb * percent / 100 ))"
|
||||||
|
|
||||||
|
recipe_body="${recipe_body}$(_tuxflotte_partman_stanza "${size_mb}" "${filesystem}" "${mountpoint}")"
|
||||||
|
done
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
backend_fatal "Nicht unterstütztes Partitionierungsschema: ${scheme}"
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
printf 'tuxflotte :: %s' "${recipe_body}"
|
||||||
|
}
|
||||||
|
|
||||||
backend_generate_config() {
|
backend_generate_config() {
|
||||||
local hostname
|
local hostname
|
||||||
local device_id
|
local device_id
|
||||||
local partitioning
|
local partitioning_json
|
||||||
|
local root_filesystem
|
||||||
local secure_boot_required
|
local secure_boot_required
|
||||||
local partman_recipe
|
local partman_recipe
|
||||||
local blueprints_json
|
local blueprints_json
|
||||||
@ -113,19 +255,18 @@ backend_generate_config() {
|
|||||||
[[ -n "${device_id}" ]] ||
|
[[ -n "${device_id}" ]] ||
|
||||||
{ backend_fatal "Keine Geräte-ID in der Serverantwort gefunden."; return 1; }
|
{ backend_fatal "Keine Geräte-ID in der Serverantwort gefunden."; return 1; }
|
||||||
|
|
||||||
partitioning="$(jq --raw-output '.runtime_blueprint.installation_directives.partitioning' "${RUNTIME_BLUEPRINT_FILE}")"
|
partitioning_json="$(jq --compact-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}")"
|
secure_boot_required="$(jq --raw-output '.runtime_blueprint.installation_directives.secure_boot_required' "${RUNTIME_BLUEPRINT_FILE}")"
|
||||||
|
|
||||||
case "${partitioning}" in
|
root_filesystem="$(jq --raw-output '.root_filesystem // "ext4"' <<<"${partitioning_json}")"
|
||||||
default)
|
case "${root_filesystem}" in
|
||||||
partman_recipe="atomic"
|
ext4|btrfs) ;;
|
||||||
;;
|
*) backend_fatal "Nicht unterstütztes Root-Dateisystem: ${root_filesystem}"; return 1 ;;
|
||||||
*)
|
|
||||||
backend_fatal "Nicht unterstützte Partitionierungsvorgabe: ${partitioning}"
|
|
||||||
return 1
|
|
||||||
;;
|
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
partman_recipe="$(_tuxflotte_render_partman_recipe "${partitioning_json}" "${root_filesystem}")" ||
|
||||||
|
return 1
|
||||||
|
|
||||||
if [[ "${secure_boot_required}" == "true" ]]; then
|
if [[ "${secure_boot_required}" == "true" ]]; then
|
||||||
backend_log "Hinweis: secure_boot_required=true wird derzeit nicht in der Preseed-Konfiguration durchgesetzt (Phase 1)."
|
backend_log "Hinweis: secure_boot_required=true wird derzeit nicht in der Preseed-Konfiguration durchgesetzt (Phase 1)."
|
||||||
fi
|
fi
|
||||||
|
|||||||
@ -26,7 +26,8 @@ d-i time/zone string Europe/Berlin
|
|||||||
d-i clock-setup/ntp boolean true
|
d-i clock-setup/ntp boolean true
|
||||||
|
|
||||||
d-i partman-auto/method string regular
|
d-i partman-auto/method string regular
|
||||||
d-i partman-auto/choose_recipe select ${TUXFLOTTE_PARTMAN_RECIPE}
|
d-i partman-auto/expert_recipe string ${TUXFLOTTE_PARTMAN_RECIPE}
|
||||||
|
d-i partman-auto/choose_recipe select tuxflotte
|
||||||
d-i partman-partitioning/confirm_write_new_label boolean true
|
d-i partman-partitioning/confirm_write_new_label boolean true
|
||||||
d-i partman/choose_partition select finish
|
d-i partman/choose_partition select finish
|
||||||
d-i partman/confirm boolean true
|
d-i partman/confirm boolean true
|
||||||
|
|||||||
@ -124,7 +124,7 @@ bake_test_preseed() {
|
|||||||
"blueprints": [],
|
"blueprints": [],
|
||||||
"installation_directives": {
|
"installation_directives": {
|
||||||
"disk_encryption": false,
|
"disk_encryption": false,
|
||||||
"partitioning": "default",
|
"partitioning": {"scheme": "single", "root_filesystem": "ext4"},
|
||||||
"secure_boot_required": false
|
"secure_boot_required": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -377,6 +377,48 @@ connect_wifi() {
|
|||||||
log "Tuxflotte-Server ist über WLAN erreichbar."
|
log "Tuxflotte-Server ist über WLAN erreichbar."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
connect_wifi_noninteractive() {
|
||||||
|
local wifi_device="$1"
|
||||||
|
local ssid="${TUXFLOTTE_WIFI_SSID}"
|
||||||
|
|
||||||
|
log "Verbinde mit vorkonfiguriertem WLAN '${ssid}' (nicht-interaktiv)."
|
||||||
|
|
||||||
|
if [[ -n "${TUXFLOTTE_WIFI_PSK:-}" ]]; then
|
||||||
|
if ! "${NMCLI}" \
|
||||||
|
device wifi connect "${ssid}" \
|
||||||
|
password "${TUXFLOTTE_WIFI_PSK}" \
|
||||||
|
ifname "${wifi_device}" \
|
||||||
|
>/dev/null; then
|
||||||
|
|
||||||
|
warn "WLAN-Anmeldung mit vorkonfigurierten Zugangsdaten ist fehlgeschlagen."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if ! "${NMCLI}" \
|
||||||
|
device wifi connect "${ssid}" \
|
||||||
|
ifname "${wifi_device}" \
|
||||||
|
>/dev/null; then
|
||||||
|
|
||||||
|
warn "Verbindung mit dem offenen, vorkonfigurierten WLAN konnte nicht hergestellt werden."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! device_has_ipv4 "${wifi_device}"; then
|
||||||
|
warn "WLAN-Verbindung besitzt keine IPv4-Adresse."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "WLAN-Verbindung wurde hergestellt."
|
||||||
|
|
||||||
|
if ! server_is_reachable; then
|
||||||
|
warn "WLAN ist verbunden, aber der Tuxflotte-Server ist nicht erreichbar."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "Tuxflotte-Server ist über WLAN erreichbar."
|
||||||
|
}
|
||||||
|
|
||||||
store_network_state() {
|
store_network_state() {
|
||||||
local device
|
local device
|
||||||
local connection_name
|
local connection_name
|
||||||
@ -484,9 +526,14 @@ main() {
|
|||||||
|
|
||||||
log "Ethernet ist nicht verfügbar. WLAN-Initialisierung wird gestartet."
|
log "Ethernet ist nicht verfügbar. WLAN-Initialisierung wird gestartet."
|
||||||
|
|
||||||
|
if [[ -n "${TUXFLOTTE_WIFI_SSID:-}" ]]; then
|
||||||
|
connect_wifi_noninteractive "${wifi_device}" ||
|
||||||
|
fatal "Es konnte keine Verbindung zum Tuxflotte-Server hergestellt werden."
|
||||||
|
else
|
||||||
connect_wifi "${wifi_device}" ||
|
connect_wifi "${wifi_device}" ||
|
||||||
fatal "Es konnte keine Verbindung zum Tuxflotte-Server hergestellt werden."
|
fatal "Es konnte keine Verbindung zum Tuxflotte-Server hergestellt werden."
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
store_network_state
|
store_network_state
|
||||||
export_connection_profile
|
export_connection_profile
|
||||||
|
|||||||
@ -101,6 +101,12 @@ show_device_status() {
|
|||||||
confirm_provisioning() {
|
confirm_provisioning() {
|
||||||
local answer
|
local answer
|
||||||
|
|
||||||
|
if [[ "${TUXFLOTTE_AUTO_MODE:-false}" == "true" ]]; then
|
||||||
|
store_provisioning_state true
|
||||||
|
log "Auto-Modus: Provisionierung wird ohne Rückfrage fortgesetzt."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
printf '\n'
|
printf '\n'
|
||||||
read -r -p "Provisionierung fortsetzen? [j/N]: " answer
|
read -r -p "Provisionierung fortsetzen? [j/N]: " answer
|
||||||
|
|
||||||
|
|||||||
@ -72,7 +72,33 @@ show_templates() {
|
|||||||
done < <(jq -c '.templates[]' "${SERVER_RESPONSE_FILE}")
|
done < <(jq -c '.templates[]' "${SERVER_RESPONSE_FILE}")
|
||||||
}
|
}
|
||||||
|
|
||||||
select_template() {
|
select_template_auto() {
|
||||||
|
local default_index
|
||||||
|
|
||||||
|
# Kein spezifischer Server-Hinweis vorhanden (Enrollment Sessions legen
|
||||||
|
# serverseitig zwar schon eine Bereitstellungsvorlage fest, die
|
||||||
|
# Verbrauchslogik dafür existiert aber noch nicht - siehe Phase 3 im
|
||||||
|
# Plan) - bis dahin wird im Auto-Modus die als is_default markierte
|
||||||
|
# Vorlage gewählt.
|
||||||
|
default_index="$(
|
||||||
|
jq '[.templates[] | .is_default] | index(true)' "${SERVER_RESPONSE_FILE}"
|
||||||
|
)"
|
||||||
|
|
||||||
|
[[ "${default_index}" != "null" ]] ||
|
||||||
|
fatal "Auto-Modus: keine Standard-Bereitstellungsvorlage in der Serverantwort markiert."
|
||||||
|
|
||||||
|
jq \
|
||||||
|
--argjson index "${default_index}" \
|
||||||
|
'{
|
||||||
|
schema_version: 1,
|
||||||
|
template: .templates[$index]
|
||||||
|
}' \
|
||||||
|
"${SERVER_RESPONSE_FILE}" >"${TEMPLATE_FILE}"
|
||||||
|
|
||||||
|
log "Auto-Modus: Standard-Bereitstellungsvorlage automatisch gewählt."
|
||||||
|
}
|
||||||
|
|
||||||
|
select_template_interactive() {
|
||||||
local template_count
|
local template_count
|
||||||
local selection
|
local selection
|
||||||
|
|
||||||
@ -97,6 +123,14 @@ select_template() {
|
|||||||
template: .templates[$index]
|
template: .templates[$index]
|
||||||
}' \
|
}' \
|
||||||
"${SERVER_RESPONSE_FILE}" >"${TEMPLATE_FILE}"
|
"${SERVER_RESPONSE_FILE}" >"${TEMPLATE_FILE}"
|
||||||
|
}
|
||||||
|
|
||||||
|
select_template() {
|
||||||
|
if [[ "${TUXFLOTTE_AUTO_MODE:-false}" == "true" ]]; then
|
||||||
|
select_template_auto
|
||||||
|
else
|
||||||
|
select_template_interactive
|
||||||
|
fi
|
||||||
|
|
||||||
chmod 0600 "${TEMPLATE_FILE}"
|
chmod 0600 "${TEMPLATE_FILE}"
|
||||||
|
|
||||||
|
|||||||
@ -87,6 +87,12 @@ store_confirmation_state() {
|
|||||||
confirm_installation() {
|
confirm_installation() {
|
||||||
local answer
|
local answer
|
||||||
|
|
||||||
|
if [[ "${TUXFLOTTE_AUTO_MODE:-false}" == "true" ]]; then
|
||||||
|
store_confirmation_state true
|
||||||
|
log "Auto-Modus: Installation wird ohne Rückfrage gestartet."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
read -r -p "Installation jetzt starten? [j/N]: " answer
|
read -r -p "Installation jetzt starten? [j/N]: " answer
|
||||||
|
|
||||||
case "${answer}" in
|
case "${answer}" in
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user