Custom-Partitionierungsschema (extra_partitions) im Golden-Image-Deployment
image_deploy_partition_custom()/_format_custom()/_mount_custom() sowie eine um extra_partitions erweiterte image_deploy_write_fstab() ergaenzen das bisherige starre ESP+Root-Layout um eine variable Anzahl zusaetzlicher Partitionen (Mountpoint/Prozentanteil-der-Gesamtplatte/Dateisystem), ohne das bestehende scheme:"single" in irgendeiner Weise zu veraendern (eigene Funktionen statt Erweiterung der bestehenden). Alle drei Backends (mint/debian/ubuntu-image) verzweigen in backend_launch() auf das Schema aus der Bereitstellungsvorlage und validieren extra_partitions zusaetzlich defensiv in backend_validate() (Prozentsumme, doppelte Mountpoints, Dateisystem-Whitelist ext4/btrfs - zfs/Fedora bewusst nicht). Gegenstueck (API+GUI+DB) ist in provisioning-server/kundenplattform bereits committet. Teil von platform-docs/roadmap/e2e-testrunde-lokale- adressierung.md Phase 3. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DWKevK2QUK5tsGmqfSD6Yy
This commit is contained in:
1 parent
5bc8d108a6
commit
020aa66bfa
7 files changed
+534
-70
No files matched your search
@@ -152,10 +152,31 @@ backend_validate() {
|
||||
' "${RUNTIME_BLUEPRINT_FILE}" >/dev/null ||
|
||||
{ backend_fatal "Installationszeitliche Vorgaben fehlen oder sind ungültig."; return 1; }
|
||||
|
||||
# Phase 3 (siehe platform-docs/roadmap/e2e-testrunde-lokale-
|
||||
# adressierung.md) ergaenzt "custom" (extra_partitions fuer /home,
|
||||
# /var, /usr, ...) neben dem bisherigen "single"-Schema. zfs/Fedora
|
||||
# bewusst nicht abgedeckt.
|
||||
local scheme
|
||||
scheme="$(jq --raw-output '.runtime_blueprint.installation_directives.partitioning.scheme // "single"' "${RUNTIME_BLUEPRINT_FILE}")"
|
||||
[[ "${scheme}" == "single" ]] ||
|
||||
{ backend_fatal "Partitionierungsschema '${scheme}' wird von diesem Backend noch nicht unterstützt (nur 'single')."; return 1; }
|
||||
case "${scheme}" in
|
||||
single) ;;
|
||||
custom)
|
||||
jq --exit-status '
|
||||
.runtime_blueprint.installation_directives.partitioning.extra_partitions as $extra
|
||||
| ($extra | type == "array")
|
||||
and (($extra | map(.mountpoint) | length) == ($extra | map(.mountpoint) | unique | length))
|
||||
and (($extra | map(.percent) | add // 0) < 100)
|
||||
and all($extra[]; (.mountpoint | type == "string") and (.mountpoint | startswith("/")))
|
||||
and all($extra[]; (.percent | type == "number") and .percent > 0)
|
||||
and all($extra[]; .filesystem == "ext4" or .filesystem == "btrfs")
|
||||
' "${RUNTIME_BLUEPRINT_FILE}" >/dev/null ||
|
||||
{ backend_fatal "Partitionierungsschema 'custom': extra_partitions ist ungültig (Mountpoints/Prozente/Dateisystem prüfen)."; return 1; }
|
||||
;;
|
||||
*)
|
||||
backend_fatal "Partitionierungsschema '${scheme}' wird von diesem Backend nicht unterstützt (nur 'single'/'custom')."
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
local target_disk_rank
|
||||
target_disk_rank="$(jq --raw-output '.runtime_blueprint.installation_directives.partitioning.target_disk_rank // 1' "${RUNTIME_BLUEPRINT_FILE}")"
|
||||
@@ -173,6 +194,7 @@ backend_validate() {
|
||||
backend_generate_config() {
|
||||
local hostname device_id device_fingerprint
|
||||
local root_filesystem partitioning_json blueprints_json target_disk_rank
|
||||
local scheme extra_partitions_json
|
||||
|
||||
[[ -r "${SERVER_RESPONSE_FILE}" ]] ||
|
||||
{ backend_fatal "Serverantwort nicht gefunden: ${SERVER_RESPONSE_FILE}"; return 1; }
|
||||
@@ -202,6 +224,11 @@ backend_generate_config() {
|
||||
# hier nur noch reine Extraktion.
|
||||
target_disk_rank="$(jq --raw-output '.target_disk_rank // 1' <<<"${partitioning_json}")"
|
||||
|
||||
# Bereits in backend_validate() strukturell geprueft (bei scheme:"custom") -
|
||||
# hier nur noch reine Extraktion.
|
||||
scheme="$(jq --raw-output '.scheme // "single"' <<<"${partitioning_json}")"
|
||||
extra_partitions_json="$(jq --compact-output '.extra_partitions // []' <<<"${partitioning_json}")"
|
||||
|
||||
blueprints_json="$(jq --compact-output '.runtime_blueprint.blueprints' "${RUNTIME_BLUEPRINT_FILE}")"
|
||||
|
||||
jq --null-input \
|
||||
@@ -210,6 +237,8 @@ backend_generate_config() {
|
||||
--arg device_fingerprint "${device_fingerprint}" \
|
||||
--arg root_filesystem "${root_filesystem}" \
|
||||
--argjson target_disk_rank "${target_disk_rank}" \
|
||||
--arg scheme "${scheme}" \
|
||||
--argjson extra_partitions "${extra_partitions_json}" \
|
||||
--argjson blueprints "${blueprints_json}" \
|
||||
'{
|
||||
hostname: $hostname,
|
||||
@@ -217,6 +246,8 @@ backend_generate_config() {
|
||||
device_fingerprint: $device_fingerprint,
|
||||
root_filesystem: $root_filesystem,
|
||||
target_disk_rank: $target_disk_rank,
|
||||
scheme: $scheme,
|
||||
extra_partitions: $extra_partitions,
|
||||
blueprints: $blueprints
|
||||
}' > "${CONFIG_FILE}" ||
|
||||
{ backend_fatal "Konfigurationsdatei konnte nicht erzeugt werden."; return 1; }
|
||||
@@ -228,6 +259,7 @@ backend_generate_config() {
|
||||
|
||||
backend_launch() {
|
||||
local disk is_efi root_fs boot_part root_part target_disk_rank
|
||||
local scheme extra_partitions_json partition_result=""
|
||||
|
||||
target_disk_rank="$(jq --raw-output '.target_disk_rank // 1' "${CONFIG_FILE}")"
|
||||
disk="$(_debian_image_detect_target_disk "${target_disk_rank}")"
|
||||
@@ -238,18 +270,34 @@ backend_launch() {
|
||||
backend_log "Zieldatenträger: ${disk} (Firmware: $([ "${is_efi}" = true ] && echo UEFI || echo BIOS))"
|
||||
|
||||
root_fs="$(jq --raw-output '.root_filesystem' "${CONFIG_FILE}")"
|
||||
scheme="$(jq --raw-output '.scheme // "single"' "${CONFIG_FILE}")"
|
||||
extra_partitions_json="$(jq --compact-output '.extra_partitions // []' "${CONFIG_FILE}")"
|
||||
|
||||
backend_log "Partitioniere ${disk}"
|
||||
# Reihenfolge "root_part boot_part" (nicht umgekehrt) - siehe
|
||||
# image_deploy_partition() in image_deploy.sh fuer die Begruendung.
|
||||
read -r root_part boot_part <<<"$(image_deploy_partition "${disk}" "${is_efi}")" ||
|
||||
return 1
|
||||
backend_log "Partitioniere ${disk} (Schema: ${scheme})"
|
||||
if [[ "${scheme}" == "custom" ]]; then
|
||||
partition_result="$(image_deploy_partition_custom "${disk}" "${is_efi}" "${extra_partitions_json}")" || return 1
|
||||
boot_part="$(jq --raw-output '.boot_part' <<<"${partition_result}")"
|
||||
root_part="$(jq --raw-output '.root_part' <<<"${partition_result}")"
|
||||
else
|
||||
# Reihenfolge "root_part boot_part" (nicht umgekehrt) - siehe
|
||||
# image_deploy_partition() in image_deploy.sh fuer die Begruendung.
|
||||
read -r root_part boot_part <<<"$(image_deploy_partition "${disk}" "${is_efi}")" ||
|
||||
return 1
|
||||
fi
|
||||
|
||||
backend_log "Formatiere Partitionen"
|
||||
image_deploy_format "${boot_part}" "${root_part}" "${root_fs}" || return 1
|
||||
if [[ "${scheme}" == "custom" ]]; then
|
||||
image_deploy_format_custom "${boot_part}" "${root_part}" "${root_fs}" "${partition_result}" || return 1
|
||||
else
|
||||
image_deploy_format "${boot_part}" "${root_part}" "${root_fs}" || return 1
|
||||
fi
|
||||
|
||||
backend_log "Mounte unter ${TARGET_DIR}"
|
||||
image_deploy_mount "${TARGET_DIR}" "${boot_part}" "${root_part}" || return 1
|
||||
if [[ "${scheme}" == "custom" ]]; then
|
||||
image_deploy_mount_custom "${TARGET_DIR}" "${boot_part}" "${root_part}" "${partition_result}" || return 1
|
||||
else
|
||||
image_deploy_mount "${TARGET_DIR}" "${boot_part}" "${root_part}" || return 1
|
||||
fi
|
||||
|
||||
if [[ -f "${NETWORK_PROFILE_EXPORT}" ]]; then
|
||||
backend_log "Übernehme WLAN-/Netzwerkverbindungsprofil ins Zielsystem"
|
||||
@@ -267,7 +315,12 @@ backend_launch() {
|
||||
fi
|
||||
|
||||
backend_log "Schreibe fstab"
|
||||
image_deploy_write_fstab "${TARGET_DIR}" "${boot_part}" "${root_part}" "${root_fs}" || return 1
|
||||
if [[ "${scheme}" == "custom" ]]; then
|
||||
image_deploy_write_fstab "${TARGET_DIR}" "${boot_part}" "${root_part}" "${root_fs}" \
|
||||
"$(jq --compact-output '.extra_partitions' <<<"${partition_result}")" || return 1
|
||||
else
|
||||
image_deploy_write_fstab "${TARGET_DIR}" "${boot_part}" "${root_part}" "${root_fs}" || return 1
|
||||
fi
|
||||
|
||||
backend_log "Binde /dev, /proc, /sys ein"
|
||||
image_deploy_bind_mounts "${TARGET_DIR}" MOUNT_STACK || return 1
|
||||
|
||||
@@ -163,15 +163,31 @@ backend_validate() {
|
||||
' "${RUNTIME_BLUEPRINT_FILE}" >/dev/null ||
|
||||
{ backend_fatal "Installationszeitliche Vorgaben fehlen oder sind ungültig."; return 1; }
|
||||
|
||||
# Phase 2 deckt bewusst nur das einfache Schema ab (ESP/biosgrub +
|
||||
# eine Root-Partition, siehe image_deploy_partition()) - "custom" mit
|
||||
# extra_partitions (/home, /var) ist noch nicht auf die neue
|
||||
# parted-basierte Mechanik uebertragen. Klarer Fehler statt stiller
|
||||
# Fehlinterpretation.
|
||||
# Phase 3 (siehe platform-docs/roadmap/e2e-testrunde-lokale-
|
||||
# adressierung.md) ergaenzt "custom" (extra_partitions fuer /home,
|
||||
# /var, /usr, ...) neben dem bisherigen "single"-Schema. zfs/Fedora
|
||||
# bewusst nicht abgedeckt.
|
||||
local scheme
|
||||
scheme="$(jq --raw-output '.runtime_blueprint.installation_directives.partitioning.scheme // "single"' "${RUNTIME_BLUEPRINT_FILE}")"
|
||||
[[ "${scheme}" == "single" ]] ||
|
||||
{ backend_fatal "Partitionierungsschema '${scheme}' wird von diesem Backend noch nicht unterstützt (nur 'single')."; return 1; }
|
||||
case "${scheme}" in
|
||||
single) ;;
|
||||
custom)
|
||||
jq --exit-status '
|
||||
.runtime_blueprint.installation_directives.partitioning.extra_partitions as $extra
|
||||
| ($extra | type == "array")
|
||||
and (($extra | map(.mountpoint) | length) == ($extra | map(.mountpoint) | unique | length))
|
||||
and (($extra | map(.percent) | add // 0) < 100)
|
||||
and all($extra[]; (.mountpoint | type == "string") and (.mountpoint | startswith("/")))
|
||||
and all($extra[]; (.percent | type == "number") and .percent > 0)
|
||||
and all($extra[]; .filesystem == "ext4" or .filesystem == "btrfs")
|
||||
' "${RUNTIME_BLUEPRINT_FILE}" >/dev/null ||
|
||||
{ backend_fatal "Partitionierungsschema 'custom': extra_partitions ist ungültig (Mountpoints/Prozente/Dateisystem prüfen)."; return 1; }
|
||||
;;
|
||||
*)
|
||||
backend_fatal "Partitionierungsschema '${scheme}' wird von diesem Backend nicht unterstützt (nur 'single'/'custom')."
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
local target_disk_rank
|
||||
target_disk_rank="$(jq --raw-output '.runtime_blueprint.installation_directives.partitioning.target_disk_rank // 1' "${RUNTIME_BLUEPRINT_FILE}")"
|
||||
@@ -189,6 +205,7 @@ backend_validate() {
|
||||
backend_generate_config() {
|
||||
local hostname device_id device_fingerprint
|
||||
local root_filesystem partitioning_json blueprints_json target_disk_rank
|
||||
local scheme extra_partitions_json
|
||||
|
||||
[[ -r "${SERVER_RESPONSE_FILE}" ]] ||
|
||||
{ backend_fatal "Serverantwort nicht gefunden: ${SERVER_RESPONSE_FILE}"; return 1; }
|
||||
@@ -218,6 +235,11 @@ backend_generate_config() {
|
||||
# hier nur noch reine Extraktion.
|
||||
target_disk_rank="$(jq --raw-output '.target_disk_rank // 1' <<<"${partitioning_json}")"
|
||||
|
||||
# Bereits in backend_validate() strukturell geprueft (bei scheme:"custom") -
|
||||
# hier nur noch reine Extraktion.
|
||||
scheme="$(jq --raw-output '.scheme // "single"' <<<"${partitioning_json}")"
|
||||
extra_partitions_json="$(jq --compact-output '.extra_partitions // []' <<<"${partitioning_json}")"
|
||||
|
||||
blueprints_json="$(jq --compact-output '.runtime_blueprint.blueprints' "${RUNTIME_BLUEPRINT_FILE}")"
|
||||
|
||||
jq --null-input \
|
||||
@@ -226,6 +248,8 @@ backend_generate_config() {
|
||||
--arg device_fingerprint "${device_fingerprint}" \
|
||||
--arg root_filesystem "${root_filesystem}" \
|
||||
--argjson target_disk_rank "${target_disk_rank}" \
|
||||
--arg scheme "${scheme}" \
|
||||
--argjson extra_partitions "${extra_partitions_json}" \
|
||||
--argjson blueprints "${blueprints_json}" \
|
||||
'{
|
||||
hostname: $hostname,
|
||||
@@ -233,6 +257,8 @@ backend_generate_config() {
|
||||
device_fingerprint: $device_fingerprint,
|
||||
root_filesystem: $root_filesystem,
|
||||
target_disk_rank: $target_disk_rank,
|
||||
scheme: $scheme,
|
||||
extra_partitions: $extra_partitions,
|
||||
blueprints: $blueprints
|
||||
}' > "${CONFIG_FILE}" ||
|
||||
{ backend_fatal "Konfigurationsdatei konnte nicht erzeugt werden."; return 1; }
|
||||
@@ -244,6 +270,7 @@ backend_generate_config() {
|
||||
|
||||
backend_launch() {
|
||||
local disk is_efi root_fs boot_part root_part target_disk_rank
|
||||
local scheme extra_partitions_json partition_result=""
|
||||
|
||||
target_disk_rank="$(jq --raw-output '.target_disk_rank // 1' "${CONFIG_FILE}")"
|
||||
disk="$(_mint_image_detect_target_disk "${target_disk_rank}")"
|
||||
@@ -254,18 +281,34 @@ backend_launch() {
|
||||
backend_log "Zieldatenträger: ${disk} (Firmware: $([ "${is_efi}" = true ] && echo UEFI || echo BIOS))"
|
||||
|
||||
root_fs="$(jq --raw-output '.root_filesystem' "${CONFIG_FILE}")"
|
||||
scheme="$(jq --raw-output '.scheme // "single"' "${CONFIG_FILE}")"
|
||||
extra_partitions_json="$(jq --compact-output '.extra_partitions // []' "${CONFIG_FILE}")"
|
||||
|
||||
backend_log "Partitioniere ${disk}"
|
||||
# Reihenfolge "root_part boot_part" (nicht umgekehrt) - siehe
|
||||
# image_deploy_partition() in image_deploy.sh fuer die Begruendung.
|
||||
read -r root_part boot_part <<<"$(image_deploy_partition "${disk}" "${is_efi}")" ||
|
||||
return 1
|
||||
backend_log "Partitioniere ${disk} (Schema: ${scheme})"
|
||||
if [[ "${scheme}" == "custom" ]]; then
|
||||
partition_result="$(image_deploy_partition_custom "${disk}" "${is_efi}" "${extra_partitions_json}")" || return 1
|
||||
boot_part="$(jq --raw-output '.boot_part' <<<"${partition_result}")"
|
||||
root_part="$(jq --raw-output '.root_part' <<<"${partition_result}")"
|
||||
else
|
||||
# Reihenfolge "root_part boot_part" (nicht umgekehrt) - siehe
|
||||
# image_deploy_partition() in image_deploy.sh fuer die Begruendung.
|
||||
read -r root_part boot_part <<<"$(image_deploy_partition "${disk}" "${is_efi}")" ||
|
||||
return 1
|
||||
fi
|
||||
|
||||
backend_log "Formatiere Partitionen"
|
||||
image_deploy_format "${boot_part}" "${root_part}" "${root_fs}" || return 1
|
||||
if [[ "${scheme}" == "custom" ]]; then
|
||||
image_deploy_format_custom "${boot_part}" "${root_part}" "${root_fs}" "${partition_result}" || return 1
|
||||
else
|
||||
image_deploy_format "${boot_part}" "${root_part}" "${root_fs}" || return 1
|
||||
fi
|
||||
|
||||
backend_log "Mounte unter ${TARGET_DIR}"
|
||||
image_deploy_mount "${TARGET_DIR}" "${boot_part}" "${root_part}" || return 1
|
||||
if [[ "${scheme}" == "custom" ]]; then
|
||||
image_deploy_mount_custom "${TARGET_DIR}" "${boot_part}" "${root_part}" "${partition_result}" || return 1
|
||||
else
|
||||
image_deploy_mount "${TARGET_DIR}" "${boot_part}" "${root_part}" || return 1
|
||||
fi
|
||||
|
||||
# Live gefunden (01.09.2026, echter Hardware-Test): export_connection_profile()
|
||||
# in 05_network.sh legt das aktive WLAN-/Ethernet-Profil zwar geschuetzt unter
|
||||
@@ -295,7 +338,12 @@ backend_launch() {
|
||||
fi
|
||||
|
||||
backend_log "Schreibe fstab"
|
||||
image_deploy_write_fstab "${TARGET_DIR}" "${boot_part}" "${root_part}" "${root_fs}" || return 1
|
||||
if [[ "${scheme}" == "custom" ]]; then
|
||||
image_deploy_write_fstab "${TARGET_DIR}" "${boot_part}" "${root_part}" "${root_fs}" \
|
||||
"$(jq --compact-output '.extra_partitions' <<<"${partition_result}")" || return 1
|
||||
else
|
||||
image_deploy_write_fstab "${TARGET_DIR}" "${boot_part}" "${root_part}" "${root_fs}" || return 1
|
||||
fi
|
||||
|
||||
backend_log "Binde /dev, /proc, /sys ein"
|
||||
image_deploy_bind_mounts "${TARGET_DIR}" MOUNT_STACK || return 1
|
||||
|
||||
@@ -158,10 +158,31 @@ backend_validate() {
|
||||
' "${RUNTIME_BLUEPRINT_FILE}" >/dev/null ||
|
||||
{ backend_fatal "Installationszeitliche Vorgaben fehlen oder sind ungültig."; return 1; }
|
||||
|
||||
# Phase 3 (siehe platform-docs/roadmap/e2e-testrunde-lokale-
|
||||
# adressierung.md) ergaenzt "custom" (extra_partitions fuer /home,
|
||||
# /var, /usr, ...) neben dem bisherigen "single"-Schema. zfs/Fedora
|
||||
# bewusst nicht abgedeckt.
|
||||
local scheme
|
||||
scheme="$(jq --raw-output '.runtime_blueprint.installation_directives.partitioning.scheme // "single"' "${RUNTIME_BLUEPRINT_FILE}")"
|
||||
[[ "${scheme}" == "single" ]] ||
|
||||
{ backend_fatal "Partitionierungsschema '${scheme}' wird von diesem Backend noch nicht unterstützt (nur 'single')."; return 1; }
|
||||
case "${scheme}" in
|
||||
single) ;;
|
||||
custom)
|
||||
jq --exit-status '
|
||||
.runtime_blueprint.installation_directives.partitioning.extra_partitions as $extra
|
||||
| ($extra | type == "array")
|
||||
and (($extra | map(.mountpoint) | length) == ($extra | map(.mountpoint) | unique | length))
|
||||
and (($extra | map(.percent) | add // 0) < 100)
|
||||
and all($extra[]; (.mountpoint | type == "string") and (.mountpoint | startswith("/")))
|
||||
and all($extra[]; (.percent | type == "number") and .percent > 0)
|
||||
and all($extra[]; .filesystem == "ext4" or .filesystem == "btrfs")
|
||||
' "${RUNTIME_BLUEPRINT_FILE}" >/dev/null ||
|
||||
{ backend_fatal "Partitionierungsschema 'custom': extra_partitions ist ungültig (Mountpoints/Prozente/Dateisystem prüfen)."; return 1; }
|
||||
;;
|
||||
*)
|
||||
backend_fatal "Partitionierungsschema '${scheme}' wird von diesem Backend nicht unterstützt (nur 'single'/'custom')."
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
local target_disk_rank
|
||||
target_disk_rank="$(jq --raw-output '.runtime_blueprint.installation_directives.partitioning.target_disk_rank // 1' "${RUNTIME_BLUEPRINT_FILE}")"
|
||||
@@ -179,6 +200,7 @@ backend_validate() {
|
||||
backend_generate_config() {
|
||||
local hostname device_id device_fingerprint
|
||||
local root_filesystem partitioning_json blueprints_json target_disk_rank
|
||||
local scheme extra_partitions_json
|
||||
|
||||
[[ -r "${SERVER_RESPONSE_FILE}" ]] ||
|
||||
{ backend_fatal "Serverantwort nicht gefunden: ${SERVER_RESPONSE_FILE}"; return 1; }
|
||||
@@ -208,6 +230,11 @@ backend_generate_config() {
|
||||
# hier nur noch reine Extraktion.
|
||||
target_disk_rank="$(jq --raw-output '.target_disk_rank // 1' <<<"${partitioning_json}")"
|
||||
|
||||
# Bereits in backend_validate() strukturell geprueft (bei scheme:"custom") -
|
||||
# hier nur noch reine Extraktion.
|
||||
scheme="$(jq --raw-output '.scheme // "single"' <<<"${partitioning_json}")"
|
||||
extra_partitions_json="$(jq --compact-output '.extra_partitions // []' <<<"${partitioning_json}")"
|
||||
|
||||
blueprints_json="$(jq --compact-output '.runtime_blueprint.blueprints' "${RUNTIME_BLUEPRINT_FILE}")"
|
||||
|
||||
jq --null-input \
|
||||
@@ -216,6 +243,8 @@ backend_generate_config() {
|
||||
--arg device_fingerprint "${device_fingerprint}" \
|
||||
--arg root_filesystem "${root_filesystem}" \
|
||||
--argjson target_disk_rank "${target_disk_rank}" \
|
||||
--arg scheme "${scheme}" \
|
||||
--argjson extra_partitions "${extra_partitions_json}" \
|
||||
--argjson blueprints "${blueprints_json}" \
|
||||
'{
|
||||
hostname: $hostname,
|
||||
@@ -223,6 +252,8 @@ backend_generate_config() {
|
||||
device_fingerprint: $device_fingerprint,
|
||||
root_filesystem: $root_filesystem,
|
||||
target_disk_rank: $target_disk_rank,
|
||||
scheme: $scheme,
|
||||
extra_partitions: $extra_partitions,
|
||||
blueprints: $blueprints
|
||||
}' > "${CONFIG_FILE}" ||
|
||||
{ backend_fatal "Konfigurationsdatei konnte nicht erzeugt werden."; return 1; }
|
||||
@@ -234,6 +265,7 @@ backend_generate_config() {
|
||||
|
||||
backend_launch() {
|
||||
local disk is_efi root_fs boot_part root_part target_disk_rank
|
||||
local scheme extra_partitions_json partition_result=""
|
||||
|
||||
target_disk_rank="$(jq --raw-output '.target_disk_rank // 1' "${CONFIG_FILE}")"
|
||||
disk="$(_ubuntu_image_detect_target_disk "${target_disk_rank}")"
|
||||
@@ -244,18 +276,34 @@ backend_launch() {
|
||||
backend_log "Zieldatenträger: ${disk} (Firmware: $([ "${is_efi}" = true ] && echo UEFI || echo BIOS))"
|
||||
|
||||
root_fs="$(jq --raw-output '.root_filesystem' "${CONFIG_FILE}")"
|
||||
scheme="$(jq --raw-output '.scheme // "single"' "${CONFIG_FILE}")"
|
||||
extra_partitions_json="$(jq --compact-output '.extra_partitions // []' "${CONFIG_FILE}")"
|
||||
|
||||
backend_log "Partitioniere ${disk}"
|
||||
# Reihenfolge "root_part boot_part" (nicht umgekehrt) - siehe
|
||||
# image_deploy_partition() in image_deploy.sh fuer die Begruendung.
|
||||
read -r root_part boot_part <<<"$(image_deploy_partition "${disk}" "${is_efi}")" ||
|
||||
return 1
|
||||
backend_log "Partitioniere ${disk} (Schema: ${scheme})"
|
||||
if [[ "${scheme}" == "custom" ]]; then
|
||||
partition_result="$(image_deploy_partition_custom "${disk}" "${is_efi}" "${extra_partitions_json}")" || return 1
|
||||
boot_part="$(jq --raw-output '.boot_part' <<<"${partition_result}")"
|
||||
root_part="$(jq --raw-output '.root_part' <<<"${partition_result}")"
|
||||
else
|
||||
# Reihenfolge "root_part boot_part" (nicht umgekehrt) - siehe
|
||||
# image_deploy_partition() in image_deploy.sh fuer die Begruendung.
|
||||
read -r root_part boot_part <<<"$(image_deploy_partition "${disk}" "${is_efi}")" ||
|
||||
return 1
|
||||
fi
|
||||
|
||||
backend_log "Formatiere Partitionen"
|
||||
image_deploy_format "${boot_part}" "${root_part}" "${root_fs}" || return 1
|
||||
if [[ "${scheme}" == "custom" ]]; then
|
||||
image_deploy_format_custom "${boot_part}" "${root_part}" "${root_fs}" "${partition_result}" || return 1
|
||||
else
|
||||
image_deploy_format "${boot_part}" "${root_part}" "${root_fs}" || return 1
|
||||
fi
|
||||
|
||||
backend_log "Mounte unter ${TARGET_DIR}"
|
||||
image_deploy_mount "${TARGET_DIR}" "${boot_part}" "${root_part}" || return 1
|
||||
if [[ "${scheme}" == "custom" ]]; then
|
||||
image_deploy_mount_custom "${TARGET_DIR}" "${boot_part}" "${root_part}" "${partition_result}" || return 1
|
||||
else
|
||||
image_deploy_mount "${TARGET_DIR}" "${boot_part}" "${root_part}" || return 1
|
||||
fi
|
||||
|
||||
if [[ -f "${NETWORK_PROFILE_EXPORT}" ]]; then
|
||||
backend_log "Übernehme WLAN-/Netzwerkverbindungsprofil ins Zielsystem"
|
||||
@@ -273,7 +321,12 @@ backend_launch() {
|
||||
fi
|
||||
|
||||
backend_log "Schreibe fstab"
|
||||
image_deploy_write_fstab "${TARGET_DIR}" "${boot_part}" "${root_part}" "${root_fs}" || return 1
|
||||
if [[ "${scheme}" == "custom" ]]; then
|
||||
image_deploy_write_fstab "${TARGET_DIR}" "${boot_part}" "${root_part}" "${root_fs}" \
|
||||
"$(jq --compact-output '.extra_partitions' <<<"${partition_result}")" || return 1
|
||||
else
|
||||
image_deploy_write_fstab "${TARGET_DIR}" "${boot_part}" "${root_part}" "${root_fs}" || return 1
|
||||
fi
|
||||
|
||||
backend_log "Binde /dev, /proc, /sys ein"
|
||||
image_deploy_bind_mounts "${TARGET_DIR}" MOUNT_STACK || return 1
|
||||
|
||||
@@ -152,10 +152,31 @@ backend_validate() {
|
||||
' "${RUNTIME_BLUEPRINT_FILE}" >/dev/null ||
|
||||
{ backend_fatal "Installationszeitliche Vorgaben fehlen oder sind ungültig."; return 1; }
|
||||
|
||||
# Phase 3 (siehe platform-docs/roadmap/e2e-testrunde-lokale-
|
||||
# adressierung.md) ergaenzt "custom" (extra_partitions fuer /home,
|
||||
# /var, /usr, ...) neben dem bisherigen "single"-Schema. zfs/Fedora
|
||||
# bewusst nicht abgedeckt.
|
||||
local scheme
|
||||
scheme="$(jq --raw-output '.runtime_blueprint.installation_directives.partitioning.scheme // "single"' "${RUNTIME_BLUEPRINT_FILE}")"
|
||||
[[ "${scheme}" == "single" ]] ||
|
||||
{ backend_fatal "Partitionierungsschema '${scheme}' wird von diesem Backend noch nicht unterstützt (nur 'single')."; return 1; }
|
||||
case "${scheme}" in
|
||||
single) ;;
|
||||
custom)
|
||||
jq --exit-status '
|
||||
.runtime_blueprint.installation_directives.partitioning.extra_partitions as $extra
|
||||
| ($extra | type == "array")
|
||||
and (($extra | map(.mountpoint) | length) == ($extra | map(.mountpoint) | unique | length))
|
||||
and (($extra | map(.percent) | add // 0) < 100)
|
||||
and all($extra[]; (.mountpoint | type == "string") and (.mountpoint | startswith("/")))
|
||||
and all($extra[]; (.percent | type == "number") and .percent > 0)
|
||||
and all($extra[]; .filesystem == "ext4" or .filesystem == "btrfs")
|
||||
' "${RUNTIME_BLUEPRINT_FILE}" >/dev/null ||
|
||||
{ backend_fatal "Partitionierungsschema 'custom': extra_partitions ist ungültig (Mountpoints/Prozente/Dateisystem prüfen)."; return 1; }
|
||||
;;
|
||||
*)
|
||||
backend_fatal "Partitionierungsschema '${scheme}' wird von diesem Backend nicht unterstützt (nur 'single'/'custom')."
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
local target_disk_rank
|
||||
target_disk_rank="$(jq --raw-output '.runtime_blueprint.installation_directives.partitioning.target_disk_rank // 1' "${RUNTIME_BLUEPRINT_FILE}")"
|
||||
@@ -173,6 +194,7 @@ backend_validate() {
|
||||
backend_generate_config() {
|
||||
local hostname device_id device_fingerprint
|
||||
local root_filesystem partitioning_json blueprints_json target_disk_rank
|
||||
local scheme extra_partitions_json
|
||||
|
||||
[[ -r "${SERVER_RESPONSE_FILE}" ]] ||
|
||||
{ backend_fatal "Serverantwort nicht gefunden: ${SERVER_RESPONSE_FILE}"; return 1; }
|
||||
@@ -202,6 +224,11 @@ backend_generate_config() {
|
||||
# hier nur noch reine Extraktion.
|
||||
target_disk_rank="$(jq --raw-output '.target_disk_rank // 1' <<<"${partitioning_json}")"
|
||||
|
||||
# Bereits in backend_validate() strukturell geprueft (bei scheme:"custom") -
|
||||
# hier nur noch reine Extraktion.
|
||||
scheme="$(jq --raw-output '.scheme // "single"' <<<"${partitioning_json}")"
|
||||
extra_partitions_json="$(jq --compact-output '.extra_partitions // []' <<<"${partitioning_json}")"
|
||||
|
||||
blueprints_json="$(jq --compact-output '.runtime_blueprint.blueprints' "${RUNTIME_BLUEPRINT_FILE}")"
|
||||
|
||||
jq --null-input \
|
||||
@@ -210,6 +237,8 @@ backend_generate_config() {
|
||||
--arg device_fingerprint "${device_fingerprint}" \
|
||||
--arg root_filesystem "${root_filesystem}" \
|
||||
--argjson target_disk_rank "${target_disk_rank}" \
|
||||
--arg scheme "${scheme}" \
|
||||
--argjson extra_partitions "${extra_partitions_json}" \
|
||||
--argjson blueprints "${blueprints_json}" \
|
||||
'{
|
||||
hostname: $hostname,
|
||||
@@ -217,6 +246,8 @@ backend_generate_config() {
|
||||
device_fingerprint: $device_fingerprint,
|
||||
root_filesystem: $root_filesystem,
|
||||
target_disk_rank: $target_disk_rank,
|
||||
scheme: $scheme,
|
||||
extra_partitions: $extra_partitions,
|
||||
blueprints: $blueprints
|
||||
}' > "${CONFIG_FILE}" ||
|
||||
{ backend_fatal "Konfigurationsdatei konnte nicht erzeugt werden."; return 1; }
|
||||
@@ -228,6 +259,7 @@ backend_generate_config() {
|
||||
|
||||
backend_launch() {
|
||||
local disk is_efi root_fs boot_part root_part target_disk_rank
|
||||
local scheme extra_partitions_json partition_result=""
|
||||
|
||||
target_disk_rank="$(jq --raw-output '.target_disk_rank // 1' "${CONFIG_FILE}")"
|
||||
disk="$(_debian_image_detect_target_disk "${target_disk_rank}")"
|
||||
@@ -238,18 +270,34 @@ backend_launch() {
|
||||
backend_log "Zieldatenträger: ${disk} (Firmware: $([ "${is_efi}" = true ] && echo UEFI || echo BIOS))"
|
||||
|
||||
root_fs="$(jq --raw-output '.root_filesystem' "${CONFIG_FILE}")"
|
||||
scheme="$(jq --raw-output '.scheme // "single"' "${CONFIG_FILE}")"
|
||||
extra_partitions_json="$(jq --compact-output '.extra_partitions // []' "${CONFIG_FILE}")"
|
||||
|
||||
backend_log "Partitioniere ${disk}"
|
||||
# Reihenfolge "root_part boot_part" (nicht umgekehrt) - siehe
|
||||
# image_deploy_partition() in image_deploy.sh fuer die Begruendung.
|
||||
read -r root_part boot_part <<<"$(image_deploy_partition "${disk}" "${is_efi}")" ||
|
||||
return 1
|
||||
backend_log "Partitioniere ${disk} (Schema: ${scheme})"
|
||||
if [[ "${scheme}" == "custom" ]]; then
|
||||
partition_result="$(image_deploy_partition_custom "${disk}" "${is_efi}" "${extra_partitions_json}")" || return 1
|
||||
boot_part="$(jq --raw-output '.boot_part' <<<"${partition_result}")"
|
||||
root_part="$(jq --raw-output '.root_part' <<<"${partition_result}")"
|
||||
else
|
||||
# Reihenfolge "root_part boot_part" (nicht umgekehrt) - siehe
|
||||
# image_deploy_partition() in image_deploy.sh fuer die Begruendung.
|
||||
read -r root_part boot_part <<<"$(image_deploy_partition "${disk}" "${is_efi}")" ||
|
||||
return 1
|
||||
fi
|
||||
|
||||
backend_log "Formatiere Partitionen"
|
||||
image_deploy_format "${boot_part}" "${root_part}" "${root_fs}" || return 1
|
||||
if [[ "${scheme}" == "custom" ]]; then
|
||||
image_deploy_format_custom "${boot_part}" "${root_part}" "${root_fs}" "${partition_result}" || return 1
|
||||
else
|
||||
image_deploy_format "${boot_part}" "${root_part}" "${root_fs}" || return 1
|
||||
fi
|
||||
|
||||
backend_log "Mounte unter ${TARGET_DIR}"
|
||||
image_deploy_mount "${TARGET_DIR}" "${boot_part}" "${root_part}" || return 1
|
||||
if [[ "${scheme}" == "custom" ]]; then
|
||||
image_deploy_mount_custom "${TARGET_DIR}" "${boot_part}" "${root_part}" "${partition_result}" || return 1
|
||||
else
|
||||
image_deploy_mount "${TARGET_DIR}" "${boot_part}" "${root_part}" || return 1
|
||||
fi
|
||||
|
||||
if [[ -f "${NETWORK_PROFILE_EXPORT}" ]]; then
|
||||
backend_log "Übernehme WLAN-/Netzwerkverbindungsprofil ins Zielsystem"
|
||||
@@ -267,7 +315,12 @@ backend_launch() {
|
||||
fi
|
||||
|
||||
backend_log "Schreibe fstab"
|
||||
image_deploy_write_fstab "${TARGET_DIR}" "${boot_part}" "${root_part}" "${root_fs}" || return 1
|
||||
if [[ "${scheme}" == "custom" ]]; then
|
||||
image_deploy_write_fstab "${TARGET_DIR}" "${boot_part}" "${root_part}" "${root_fs}" \
|
||||
"$(jq --compact-output '.extra_partitions' <<<"${partition_result}")" || return 1
|
||||
else
|
||||
image_deploy_write_fstab "${TARGET_DIR}" "${boot_part}" "${root_part}" "${root_fs}" || return 1
|
||||
fi
|
||||
|
||||
backend_log "Binde /dev, /proc, /sys ein"
|
||||
image_deploy_bind_mounts "${TARGET_DIR}" MOUNT_STACK || return 1
|
||||
|
||||
@@ -163,15 +163,31 @@ backend_validate() {
|
||||
' "${RUNTIME_BLUEPRINT_FILE}" >/dev/null ||
|
||||
{ backend_fatal "Installationszeitliche Vorgaben fehlen oder sind ungültig."; return 1; }
|
||||
|
||||
# Phase 2 deckt bewusst nur das einfache Schema ab (ESP/biosgrub +
|
||||
# eine Root-Partition, siehe image_deploy_partition()) - "custom" mit
|
||||
# extra_partitions (/home, /var) ist noch nicht auf die neue
|
||||
# parted-basierte Mechanik uebertragen. Klarer Fehler statt stiller
|
||||
# Fehlinterpretation.
|
||||
# Phase 3 (siehe platform-docs/roadmap/e2e-testrunde-lokale-
|
||||
# adressierung.md) ergaenzt "custom" (extra_partitions fuer /home,
|
||||
# /var, /usr, ...) neben dem bisherigen "single"-Schema. zfs/Fedora
|
||||
# bewusst nicht abgedeckt.
|
||||
local scheme
|
||||
scheme="$(jq --raw-output '.runtime_blueprint.installation_directives.partitioning.scheme // "single"' "${RUNTIME_BLUEPRINT_FILE}")"
|
||||
[[ "${scheme}" == "single" ]] ||
|
||||
{ backend_fatal "Partitionierungsschema '${scheme}' wird von diesem Backend noch nicht unterstützt (nur 'single')."; return 1; }
|
||||
case "${scheme}" in
|
||||
single) ;;
|
||||
custom)
|
||||
jq --exit-status '
|
||||
.runtime_blueprint.installation_directives.partitioning.extra_partitions as $extra
|
||||
| ($extra | type == "array")
|
||||
and (($extra | map(.mountpoint) | length) == ($extra | map(.mountpoint) | unique | length))
|
||||
and (($extra | map(.percent) | add // 0) < 100)
|
||||
and all($extra[]; (.mountpoint | type == "string") and (.mountpoint | startswith("/")))
|
||||
and all($extra[]; (.percent | type == "number") and .percent > 0)
|
||||
and all($extra[]; .filesystem == "ext4" or .filesystem == "btrfs")
|
||||
' "${RUNTIME_BLUEPRINT_FILE}" >/dev/null ||
|
||||
{ backend_fatal "Partitionierungsschema 'custom': extra_partitions ist ungültig (Mountpoints/Prozente/Dateisystem prüfen)."; return 1; }
|
||||
;;
|
||||
*)
|
||||
backend_fatal "Partitionierungsschema '${scheme}' wird von diesem Backend nicht unterstützt (nur 'single'/'custom')."
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
local target_disk_rank
|
||||
target_disk_rank="$(jq --raw-output '.runtime_blueprint.installation_directives.partitioning.target_disk_rank // 1' "${RUNTIME_BLUEPRINT_FILE}")"
|
||||
@@ -189,6 +205,7 @@ backend_validate() {
|
||||
backend_generate_config() {
|
||||
local hostname device_id device_fingerprint
|
||||
local root_filesystem partitioning_json blueprints_json target_disk_rank
|
||||
local scheme extra_partitions_json
|
||||
|
||||
[[ -r "${SERVER_RESPONSE_FILE}" ]] ||
|
||||
{ backend_fatal "Serverantwort nicht gefunden: ${SERVER_RESPONSE_FILE}"; return 1; }
|
||||
@@ -218,6 +235,11 @@ backend_generate_config() {
|
||||
# hier nur noch reine Extraktion.
|
||||
target_disk_rank="$(jq --raw-output '.target_disk_rank // 1' <<<"${partitioning_json}")"
|
||||
|
||||
# Bereits in backend_validate() strukturell geprueft (bei scheme:"custom") -
|
||||
# hier nur noch reine Extraktion.
|
||||
scheme="$(jq --raw-output '.scheme // "single"' <<<"${partitioning_json}")"
|
||||
extra_partitions_json="$(jq --compact-output '.extra_partitions // []' <<<"${partitioning_json}")"
|
||||
|
||||
blueprints_json="$(jq --compact-output '.runtime_blueprint.blueprints' "${RUNTIME_BLUEPRINT_FILE}")"
|
||||
|
||||
jq --null-input \
|
||||
@@ -226,6 +248,8 @@ backend_generate_config() {
|
||||
--arg device_fingerprint "${device_fingerprint}" \
|
||||
--arg root_filesystem "${root_filesystem}" \
|
||||
--argjson target_disk_rank "${target_disk_rank}" \
|
||||
--arg scheme "${scheme}" \
|
||||
--argjson extra_partitions "${extra_partitions_json}" \
|
||||
--argjson blueprints "${blueprints_json}" \
|
||||
'{
|
||||
hostname: $hostname,
|
||||
@@ -233,6 +257,8 @@ backend_generate_config() {
|
||||
device_fingerprint: $device_fingerprint,
|
||||
root_filesystem: $root_filesystem,
|
||||
target_disk_rank: $target_disk_rank,
|
||||
scheme: $scheme,
|
||||
extra_partitions: $extra_partitions,
|
||||
blueprints: $blueprints
|
||||
}' > "${CONFIG_FILE}" ||
|
||||
{ backend_fatal "Konfigurationsdatei konnte nicht erzeugt werden."; return 1; }
|
||||
@@ -244,6 +270,7 @@ backend_generate_config() {
|
||||
|
||||
backend_launch() {
|
||||
local disk is_efi root_fs boot_part root_part target_disk_rank
|
||||
local scheme extra_partitions_json partition_result=""
|
||||
|
||||
target_disk_rank="$(jq --raw-output '.target_disk_rank // 1' "${CONFIG_FILE}")"
|
||||
disk="$(_mint_image_detect_target_disk "${target_disk_rank}")"
|
||||
@@ -254,18 +281,34 @@ backend_launch() {
|
||||
backend_log "Zieldatenträger: ${disk} (Firmware: $([ "${is_efi}" = true ] && echo UEFI || echo BIOS))"
|
||||
|
||||
root_fs="$(jq --raw-output '.root_filesystem' "${CONFIG_FILE}")"
|
||||
scheme="$(jq --raw-output '.scheme // "single"' "${CONFIG_FILE}")"
|
||||
extra_partitions_json="$(jq --compact-output '.extra_partitions // []' "${CONFIG_FILE}")"
|
||||
|
||||
backend_log "Partitioniere ${disk}"
|
||||
# Reihenfolge "root_part boot_part" (nicht umgekehrt) - siehe
|
||||
# image_deploy_partition() in image_deploy.sh fuer die Begruendung.
|
||||
read -r root_part boot_part <<<"$(image_deploy_partition "${disk}" "${is_efi}")" ||
|
||||
return 1
|
||||
backend_log "Partitioniere ${disk} (Schema: ${scheme})"
|
||||
if [[ "${scheme}" == "custom" ]]; then
|
||||
partition_result="$(image_deploy_partition_custom "${disk}" "${is_efi}" "${extra_partitions_json}")" || return 1
|
||||
boot_part="$(jq --raw-output '.boot_part' <<<"${partition_result}")"
|
||||
root_part="$(jq --raw-output '.root_part' <<<"${partition_result}")"
|
||||
else
|
||||
# Reihenfolge "root_part boot_part" (nicht umgekehrt) - siehe
|
||||
# image_deploy_partition() in image_deploy.sh fuer die Begruendung.
|
||||
read -r root_part boot_part <<<"$(image_deploy_partition "${disk}" "${is_efi}")" ||
|
||||
return 1
|
||||
fi
|
||||
|
||||
backend_log "Formatiere Partitionen"
|
||||
image_deploy_format "${boot_part}" "${root_part}" "${root_fs}" || return 1
|
||||
if [[ "${scheme}" == "custom" ]]; then
|
||||
image_deploy_format_custom "${boot_part}" "${root_part}" "${root_fs}" "${partition_result}" || return 1
|
||||
else
|
||||
image_deploy_format "${boot_part}" "${root_part}" "${root_fs}" || return 1
|
||||
fi
|
||||
|
||||
backend_log "Mounte unter ${TARGET_DIR}"
|
||||
image_deploy_mount "${TARGET_DIR}" "${boot_part}" "${root_part}" || return 1
|
||||
if [[ "${scheme}" == "custom" ]]; then
|
||||
image_deploy_mount_custom "${TARGET_DIR}" "${boot_part}" "${root_part}" "${partition_result}" || return 1
|
||||
else
|
||||
image_deploy_mount "${TARGET_DIR}" "${boot_part}" "${root_part}" || return 1
|
||||
fi
|
||||
|
||||
# Live gefunden (01.09.2026, echter Hardware-Test): export_connection_profile()
|
||||
# in 05_network.sh legt das aktive WLAN-/Ethernet-Profil zwar geschuetzt unter
|
||||
@@ -295,7 +338,12 @@ backend_launch() {
|
||||
fi
|
||||
|
||||
backend_log "Schreibe fstab"
|
||||
image_deploy_write_fstab "${TARGET_DIR}" "${boot_part}" "${root_part}" "${root_fs}" || return 1
|
||||
if [[ "${scheme}" == "custom" ]]; then
|
||||
image_deploy_write_fstab "${TARGET_DIR}" "${boot_part}" "${root_part}" "${root_fs}" \
|
||||
"$(jq --compact-output '.extra_partitions' <<<"${partition_result}")" || return 1
|
||||
else
|
||||
image_deploy_write_fstab "${TARGET_DIR}" "${boot_part}" "${root_part}" "${root_fs}" || return 1
|
||||
fi
|
||||
|
||||
backend_log "Binde /dev, /proc, /sys ein"
|
||||
image_deploy_bind_mounts "${TARGET_DIR}" MOUNT_STACK || return 1
|
||||
|
||||
@@ -158,10 +158,31 @@ backend_validate() {
|
||||
' "${RUNTIME_BLUEPRINT_FILE}" >/dev/null ||
|
||||
{ backend_fatal "Installationszeitliche Vorgaben fehlen oder sind ungültig."; return 1; }
|
||||
|
||||
# Phase 3 (siehe platform-docs/roadmap/e2e-testrunde-lokale-
|
||||
# adressierung.md) ergaenzt "custom" (extra_partitions fuer /home,
|
||||
# /var, /usr, ...) neben dem bisherigen "single"-Schema. zfs/Fedora
|
||||
# bewusst nicht abgedeckt.
|
||||
local scheme
|
||||
scheme="$(jq --raw-output '.runtime_blueprint.installation_directives.partitioning.scheme // "single"' "${RUNTIME_BLUEPRINT_FILE}")"
|
||||
[[ "${scheme}" == "single" ]] ||
|
||||
{ backend_fatal "Partitionierungsschema '${scheme}' wird von diesem Backend noch nicht unterstützt (nur 'single')."; return 1; }
|
||||
case "${scheme}" in
|
||||
single) ;;
|
||||
custom)
|
||||
jq --exit-status '
|
||||
.runtime_blueprint.installation_directives.partitioning.extra_partitions as $extra
|
||||
| ($extra | type == "array")
|
||||
and (($extra | map(.mountpoint) | length) == ($extra | map(.mountpoint) | unique | length))
|
||||
and (($extra | map(.percent) | add // 0) < 100)
|
||||
and all($extra[]; (.mountpoint | type == "string") and (.mountpoint | startswith("/")))
|
||||
and all($extra[]; (.percent | type == "number") and .percent > 0)
|
||||
and all($extra[]; .filesystem == "ext4" or .filesystem == "btrfs")
|
||||
' "${RUNTIME_BLUEPRINT_FILE}" >/dev/null ||
|
||||
{ backend_fatal "Partitionierungsschema 'custom': extra_partitions ist ungültig (Mountpoints/Prozente/Dateisystem prüfen)."; return 1; }
|
||||
;;
|
||||
*)
|
||||
backend_fatal "Partitionierungsschema '${scheme}' wird von diesem Backend nicht unterstützt (nur 'single'/'custom')."
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
local target_disk_rank
|
||||
target_disk_rank="$(jq --raw-output '.runtime_blueprint.installation_directives.partitioning.target_disk_rank // 1' "${RUNTIME_BLUEPRINT_FILE}")"
|
||||
@@ -179,6 +200,7 @@ backend_validate() {
|
||||
backend_generate_config() {
|
||||
local hostname device_id device_fingerprint
|
||||
local root_filesystem partitioning_json blueprints_json target_disk_rank
|
||||
local scheme extra_partitions_json
|
||||
|
||||
[[ -r "${SERVER_RESPONSE_FILE}" ]] ||
|
||||
{ backend_fatal "Serverantwort nicht gefunden: ${SERVER_RESPONSE_FILE}"; return 1; }
|
||||
@@ -208,6 +230,11 @@ backend_generate_config() {
|
||||
# hier nur noch reine Extraktion.
|
||||
target_disk_rank="$(jq --raw-output '.target_disk_rank // 1' <<<"${partitioning_json}")"
|
||||
|
||||
# Bereits in backend_validate() strukturell geprueft (bei scheme:"custom") -
|
||||
# hier nur noch reine Extraktion.
|
||||
scheme="$(jq --raw-output '.scheme // "single"' <<<"${partitioning_json}")"
|
||||
extra_partitions_json="$(jq --compact-output '.extra_partitions // []' <<<"${partitioning_json}")"
|
||||
|
||||
blueprints_json="$(jq --compact-output '.runtime_blueprint.blueprints' "${RUNTIME_BLUEPRINT_FILE}")"
|
||||
|
||||
jq --null-input \
|
||||
@@ -216,6 +243,8 @@ backend_generate_config() {
|
||||
--arg device_fingerprint "${device_fingerprint}" \
|
||||
--arg root_filesystem "${root_filesystem}" \
|
||||
--argjson target_disk_rank "${target_disk_rank}" \
|
||||
--arg scheme "${scheme}" \
|
||||
--argjson extra_partitions "${extra_partitions_json}" \
|
||||
--argjson blueprints "${blueprints_json}" \
|
||||
'{
|
||||
hostname: $hostname,
|
||||
@@ -223,6 +252,8 @@ backend_generate_config() {
|
||||
device_fingerprint: $device_fingerprint,
|
||||
root_filesystem: $root_filesystem,
|
||||
target_disk_rank: $target_disk_rank,
|
||||
scheme: $scheme,
|
||||
extra_partitions: $extra_partitions,
|
||||
blueprints: $blueprints
|
||||
}' > "${CONFIG_FILE}" ||
|
||||
{ backend_fatal "Konfigurationsdatei konnte nicht erzeugt werden."; return 1; }
|
||||
@@ -234,6 +265,7 @@ backend_generate_config() {
|
||||
|
||||
backend_launch() {
|
||||
local disk is_efi root_fs boot_part root_part target_disk_rank
|
||||
local scheme extra_partitions_json partition_result=""
|
||||
|
||||
target_disk_rank="$(jq --raw-output '.target_disk_rank // 1' "${CONFIG_FILE}")"
|
||||
disk="$(_ubuntu_image_detect_target_disk "${target_disk_rank}")"
|
||||
@@ -244,18 +276,34 @@ backend_launch() {
|
||||
backend_log "Zieldatenträger: ${disk} (Firmware: $([ "${is_efi}" = true ] && echo UEFI || echo BIOS))"
|
||||
|
||||
root_fs="$(jq --raw-output '.root_filesystem' "${CONFIG_FILE}")"
|
||||
scheme="$(jq --raw-output '.scheme // "single"' "${CONFIG_FILE}")"
|
||||
extra_partitions_json="$(jq --compact-output '.extra_partitions // []' "${CONFIG_FILE}")"
|
||||
|
||||
backend_log "Partitioniere ${disk}"
|
||||
# Reihenfolge "root_part boot_part" (nicht umgekehrt) - siehe
|
||||
# image_deploy_partition() in image_deploy.sh fuer die Begruendung.
|
||||
read -r root_part boot_part <<<"$(image_deploy_partition "${disk}" "${is_efi}")" ||
|
||||
return 1
|
||||
backend_log "Partitioniere ${disk} (Schema: ${scheme})"
|
||||
if [[ "${scheme}" == "custom" ]]; then
|
||||
partition_result="$(image_deploy_partition_custom "${disk}" "${is_efi}" "${extra_partitions_json}")" || return 1
|
||||
boot_part="$(jq --raw-output '.boot_part' <<<"${partition_result}")"
|
||||
root_part="$(jq --raw-output '.root_part' <<<"${partition_result}")"
|
||||
else
|
||||
# Reihenfolge "root_part boot_part" (nicht umgekehrt) - siehe
|
||||
# image_deploy_partition() in image_deploy.sh fuer die Begruendung.
|
||||
read -r root_part boot_part <<<"$(image_deploy_partition "${disk}" "${is_efi}")" ||
|
||||
return 1
|
||||
fi
|
||||
|
||||
backend_log "Formatiere Partitionen"
|
||||
image_deploy_format "${boot_part}" "${root_part}" "${root_fs}" || return 1
|
||||
if [[ "${scheme}" == "custom" ]]; then
|
||||
image_deploy_format_custom "${boot_part}" "${root_part}" "${root_fs}" "${partition_result}" || return 1
|
||||
else
|
||||
image_deploy_format "${boot_part}" "${root_part}" "${root_fs}" || return 1
|
||||
fi
|
||||
|
||||
backend_log "Mounte unter ${TARGET_DIR}"
|
||||
image_deploy_mount "${TARGET_DIR}" "${boot_part}" "${root_part}" || return 1
|
||||
if [[ "${scheme}" == "custom" ]]; then
|
||||
image_deploy_mount_custom "${TARGET_DIR}" "${boot_part}" "${root_part}" "${partition_result}" || return 1
|
||||
else
|
||||
image_deploy_mount "${TARGET_DIR}" "${boot_part}" "${root_part}" || return 1
|
||||
fi
|
||||
|
||||
if [[ -f "${NETWORK_PROFILE_EXPORT}" ]]; then
|
||||
backend_log "Übernehme WLAN-/Netzwerkverbindungsprofil ins Zielsystem"
|
||||
@@ -273,7 +321,12 @@ backend_launch() {
|
||||
fi
|
||||
|
||||
backend_log "Schreibe fstab"
|
||||
image_deploy_write_fstab "${TARGET_DIR}" "${boot_part}" "${root_part}" "${root_fs}" || return 1
|
||||
if [[ "${scheme}" == "custom" ]]; then
|
||||
image_deploy_write_fstab "${TARGET_DIR}" "${boot_part}" "${root_part}" "${root_fs}" \
|
||||
"$(jq --compact-output '.extra_partitions' <<<"${partition_result}")" || return 1
|
||||
else
|
||||
image_deploy_write_fstab "${TARGET_DIR}" "${boot_part}" "${root_part}" "${root_fs}" || return 1
|
||||
fi
|
||||
|
||||
backend_log "Binde /dev, /proc, /sys ein"
|
||||
image_deploy_bind_mounts "${TARGET_DIR}" MOUNT_STACK || return 1
|
||||
|
||||
@@ -145,6 +145,145 @@ image_deploy_partition() {
|
||||
fi
|
||||
}
|
||||
|
||||
# Partitionierung fuer scheme:"custom" (Bereitstellungsvorlage.partitioning,
|
||||
# siehe platform-docs/roadmap/e2e-testrunde-lokale-adressierung.md Phase 3):
|
||||
# ESP/biosgrub wie image_deploy_partition(), danach je einen "extra
|
||||
# partition"-Eintrag aus extra_partitions_json (kompaktes JSON-Array
|
||||
# [{"mountpoint":"/home","percent":20,"filesystem":"ext4"}, ...]), Root
|
||||
# nimmt den verbleibenden Rest. Prozentangaben sind bewusst Anteile der
|
||||
# GESAMTEN Platte (nicht des nach ESP verbleibenden Rests) - "20% fuer
|
||||
# /home" bedeutet 20% der Plattengroesse, parted interpretiert "X%" in
|
||||
# mkpart ohnehin relativ zur Gesamtgroesse des Datentraegers, nicht zum
|
||||
# vorherigen Partitionsende. Eigene Funktion statt Erweiterung von
|
||||
# image_deploy_partition() - komplett andere Partitionsanzahl/-logik,
|
||||
# und das bestehende (viel genutzte) single-Schema soll dadurch keinerlei
|
||||
# Verhaltensaenderung/Risiko erfahren.
|
||||
#
|
||||
# Gibt ein JSON-Objekt auf stdout aus:
|
||||
# {"boot_part": "...", "root_part": "...",
|
||||
# "extra_partitions": [{"mountpoint": "/home", "device": "...", "filesystem": "ext4"}, ...]}
|
||||
image_deploy_partition_custom() {
|
||||
local disk="$1"
|
||||
local is_efi="$2"
|
||||
local extra_partitions_json="$3"
|
||||
|
||||
_image_deploy_release_disk "${disk}"
|
||||
|
||||
if ! parted --script "${disk}" mklabel gpt; then
|
||||
image_deploy_log "parted meldete einen Fehler beim Anlegen der Partitionstabelle auf ${disk} (haeufig: eine alte Partition war noch belegt) - pruefe, ob der Kernel die neue Tabelle trotzdem uebernimmt."
|
||||
fi
|
||||
|
||||
_image_deploy_settle_partitions "${disk}" ||
|
||||
{ image_deploy_fatal "Kernel konnte die neue Partitionstabelle auf ${disk} auch nach mehreren Versuchen nicht uebernehmen."; return 1; }
|
||||
|
||||
parted --script "${disk}" print 2>/dev/null | grep -q "Partition Table: gpt" ||
|
||||
{ image_deploy_fatal "Nach dem Partitionieren liegt kein gueltiges GPT-Label auf ${disk} vor."; return 1; }
|
||||
|
||||
local part_num=1 cursor boot_part=""
|
||||
if [[ "${is_efi}" == "true" ]]; then
|
||||
parted --script "${disk}" mkpart ESP fat32 1MiB 513MiB &&
|
||||
parted --script "${disk}" set 1 esp on ||
|
||||
{ image_deploy_fatal "ESP-Partitionierung fehlgeschlagen auf ${disk}"; return 1; }
|
||||
boot_part="$(image_deploy_partition_path "${disk}" 1)"
|
||||
cursor="513MiB"
|
||||
else
|
||||
parted --script "${disk}" mkpart biosgrub 1MiB 2MiB &&
|
||||
parted --script "${disk}" set 1 bios_grub on ||
|
||||
{ image_deploy_fatal "biosgrub-Partitionierung fehlgeschlagen auf ${disk}"; return 1; }
|
||||
cursor="2MiB"
|
||||
fi
|
||||
|
||||
local extra_partitions_result="[]"
|
||||
local mountpoint percent filesystem name cumulative_percent=0 device entry
|
||||
while IFS= read -r entry; do
|
||||
[[ -n "${entry}" ]] || continue
|
||||
part_num=$((part_num + 1))
|
||||
mountpoint="$(jq --raw-output '.mountpoint' <<<"${entry}")"
|
||||
percent="$(jq --raw-output '.percent' <<<"${entry}")"
|
||||
filesystem="$(jq --raw-output '.filesystem' <<<"${entry}")"
|
||||
# Partitionsname aus Mountpoint ableiten ("/home" -> "home",
|
||||
# "/var/lib" -> "var-lib") - rein kosmetisch (parted-Label), hat
|
||||
# keine funktionale Bedeutung.
|
||||
name="$(sed -e 's#^/##' -e 's#/#-#g' <<<"${mountpoint}")"
|
||||
cumulative_percent=$((cumulative_percent + percent))
|
||||
|
||||
parted --script "${disk}" mkpart "${name}" "${filesystem}" "${cursor}" "${cumulative_percent}%" ||
|
||||
{ image_deploy_fatal "Partitionierung von ${mountpoint} (${percent}%) fehlgeschlagen auf ${disk}"; return 1; }
|
||||
|
||||
cursor="${cumulative_percent}%"
|
||||
device="$(image_deploy_partition_path "${disk}" "${part_num}")"
|
||||
extra_partitions_result="$(jq --compact-output \
|
||||
--arg mountpoint "${mountpoint}" --arg device "${device}" --arg filesystem "${filesystem}" \
|
||||
'. + [{mountpoint: $mountpoint, device: $device, filesystem: $filesystem}]' \
|
||||
<<<"${extra_partitions_result}")"
|
||||
done < <(jq --compact-output '.[]' <<<"${extra_partitions_json}")
|
||||
|
||||
part_num=$((part_num + 1))
|
||||
parted --script "${disk}" mkpart root ext4 "${cursor}" 100% ||
|
||||
{ image_deploy_fatal "Root-Partitionierung fehlgeschlagen auf ${disk}"; return 1; }
|
||||
local root_part
|
||||
root_part="$(image_deploy_partition_path "${disk}" "${part_num}")"
|
||||
|
||||
_image_deploy_settle_partitions "${disk}" ||
|
||||
{ image_deploy_fatal "Kernel konnte die neuen Partitionen auf ${disk} nicht uebernehmen."; return 1; }
|
||||
|
||||
[[ -z "${boot_part}" || -b "${boot_part}" ]] && [[ -b "${root_part}" ]] ||
|
||||
{ image_deploy_fatal "Partitionen nach partprobe nicht gefunden (${boot_part}, ${root_part})"; return 1; }
|
||||
|
||||
jq --null-input --compact-output \
|
||||
--arg boot_part "${boot_part}" --arg root_part "${root_part}" \
|
||||
--argjson extra_partitions "${extra_partitions_result}" \
|
||||
'{boot_part: $boot_part, root_part: $root_part, extra_partitions: $extra_partitions}'
|
||||
}
|
||||
|
||||
# Formatiert boot_part/root_part wie image_deploy_format(), zusaetzlich
|
||||
# jede Extra-Partition mit ihrem eigenen Dateisystem (aus dem stdout-JSON
|
||||
# von image_deploy_partition_custom()).
|
||||
image_deploy_format_custom() {
|
||||
local boot_part="$1"
|
||||
local root_part="$2"
|
||||
local root_fs="$3"
|
||||
local partition_result="$4"
|
||||
|
||||
image_deploy_format "${boot_part}" "${root_part}" "${root_fs}" || return 1
|
||||
|
||||
local device filesystem entry
|
||||
while IFS= read -r entry; do
|
||||
[[ -n "${entry}" ]] || continue
|
||||
device="$(jq --raw-output '.device' <<<"${entry}")"
|
||||
filesystem="$(jq --raw-output '.filesystem' <<<"${entry}")"
|
||||
case "${filesystem}" in
|
||||
ext4) mkfs.ext4 -F -L "$(basename "${device}")" "${device}" ;;
|
||||
btrfs) mkfs.btrfs -f -L "$(basename "${device}")" "${device}" ;;
|
||||
*) image_deploy_fatal "Nicht unterstuetztes Dateisystem: ${filesystem}"; return 1 ;;
|
||||
esac || { image_deploy_fatal "mkfs auf ${device} fehlgeschlagen"; return 1; }
|
||||
done < <(jq --compact-output '.extra_partitions[]' <<<"${partition_result}")
|
||||
}
|
||||
|
||||
# Mountet root/ESP wie image_deploy_mount(), zusaetzlich jede Extra-
|
||||
# Partition unter ihrem Mountpoint innerhalb von target - VOR dem Golden-
|
||||
# Image-Extract, damit das entpackte Archiv direkt auf den richtigen
|
||||
# Partitionen landet statt hinterher umkopiert werden zu muessen.
|
||||
image_deploy_mount_custom() {
|
||||
local target="$1"
|
||||
local boot_part="$2"
|
||||
local root_part="$3"
|
||||
local partition_result="$4"
|
||||
|
||||
image_deploy_mount "${target}" "${boot_part}" "${root_part}" || return 1
|
||||
|
||||
local device mountpoint entry
|
||||
while IFS= read -r entry; do
|
||||
[[ -n "${entry}" ]] || continue
|
||||
device="$(jq --raw-output '.device' <<<"${entry}")"
|
||||
mountpoint="$(jq --raw-output '.mountpoint' <<<"${entry}")"
|
||||
install -d "${target}${mountpoint}" ||
|
||||
{ image_deploy_fatal "Mountpunkt ${target}${mountpoint} konnte nicht angelegt werden"; return 1; }
|
||||
mount "${device}" "${target}${mountpoint}" ||
|
||||
{ image_deploy_fatal "${device} konnte nicht auf ${target}${mountpoint} gemountet werden"; return 1; }
|
||||
done < <(jq --compact-output '.extra_partitions[]' <<<"${partition_result}")
|
||||
}
|
||||
|
||||
image_deploy_format() {
|
||||
local boot_part="$1"
|
||||
local root_part="$2"
|
||||
@@ -354,11 +493,16 @@ image_deploy_install_network_profile() {
|
||||
{ image_deploy_fatal "Verbindungsprofil konnte nicht nach ${dest_dir} kopiert werden"; return 1; }
|
||||
}
|
||||
|
||||
# extra_partitions_json (5. Parameter, optional): kompaktes JSON-Array wie
|
||||
# von image_deploy_partition_custom() zurueckgegeben
|
||||
# ([{"mountpoint":...,"device":...,"filesystem":...}, ...]) - Default "[]",
|
||||
# damit bestehende Aufrufer (scheme:"single") unveraendert bleiben.
|
||||
image_deploy_write_fstab() {
|
||||
local target="$1"
|
||||
local boot_part="$2"
|
||||
local root_part="$3"
|
||||
local root_fs="$4"
|
||||
local extra_partitions_json="${5:-[]}"
|
||||
|
||||
local root_uuid
|
||||
root_uuid="$(blkid -s UUID -o value "${root_part}")"
|
||||
@@ -375,6 +519,18 @@ image_deploy_write_fstab() {
|
||||
{ image_deploy_fatal "Keine UUID fuer ${boot_part} gefunden"; return 1; }
|
||||
echo "UUID=${boot_uuid} /boot/efi vfat umask=0077 0 1"
|
||||
fi
|
||||
|
||||
local device mountpoint filesystem uuid entry
|
||||
while IFS= read -r entry; do
|
||||
[[ -n "${entry}" ]] || continue
|
||||
device="$(jq --raw-output '.device' <<<"${entry}")"
|
||||
mountpoint="$(jq --raw-output '.mountpoint' <<<"${entry}")"
|
||||
filesystem="$(jq --raw-output '.filesystem' <<<"${entry}")"
|
||||
uuid="$(blkid -s UUID -o value "${device}")"
|
||||
[[ -n "${uuid}" ]] ||
|
||||
{ image_deploy_fatal "Keine UUID fuer ${device} gefunden"; return 1; }
|
||||
echo "UUID=${uuid} ${mountpoint} ${filesystem} defaults 0 2"
|
||||
done < <(jq --compact-output '.[]' <<<"${extra_partitions_json}")
|
||||
} > "${target}/etc/fstab"
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user