diff --git a/boot-medium/config/includes.chroot/opt/tuxflotte/scripts/lib/image_deploy.sh b/boot-medium/config/includes.chroot/opt/tuxflotte/scripts/lib/image_deploy.sh index efc732e..7ac8498 100644 --- a/boot-medium/config/includes.chroot/opt/tuxflotte/scripts/lib/image_deploy.sh +++ b/boot-medium/config/includes.chroot/opt/tuxflotte/scripts/lib/image_deploy.sh @@ -46,12 +46,61 @@ image_deploy_partition_path() { # an, siehe dortiger Kommentar zu bios_grub). Gibt "BOOT_PART ROOT_PART" # auf stdout aus - BOOT_PART ist bei BIOS leer (die biosgrub-Partition # braucht kein Dateisystem/keinen Mountpunkt). +# Vorhandene Partitionen der Zielplatte vor dem Neupartitionieren freigeben +# (unmounten, Swap deaktivieren) - live auf echter Hardware gefunden +# (01.09.2026): parted schreibt eine neue Partitionstabelle zwar trotzdem +# auf die Platte, meldet aber einen Fehler ("...have been unable to inform +# the Kernel of the change... probably because it/they are in use"), wenn +# eine alte Partition (z.B. Swap oder ein gemountetes Dateisystem vom +# vorherigen Betriebssystem auf dieser Platte) noch belegt ist. In QEMU mit +# stets frischen Testplatten nie aufgetreten - reale Kundenhardware hat +# aber fast immer schon ein Vorleben auf der Platte. +_image_deploy_release_disk() { + local disk="$1" + local part + + for part in "${disk}"?*; do + [[ -b "${part}" ]] || continue + swapoff "${part}" 2>/dev/null || true + umount --recursive "${part}" 2>/dev/null || true + done +} + +# Manche Kernel-/Platten-Kombinationen brauchen mehrere Anlaeufe, bis das +# Neueinlesen der Partitionstabelle (BLKRRPART) greift, gerade direkt nach +# einem mklabel auf einer zuvor belegten Platte - deshalb mehrfach +# probieren statt nach einem einzigen partprobe-Aufruf aufzugeben. +_image_deploy_settle_partitions() { + local disk="$1" + local attempt + + for attempt in 1 2 3 4 5; do + if partprobe "${disk}" 2>/dev/null; then + udevadm settle + return 0 + fi + sleep 1 + done + + udevadm settle + return 1 +} + image_deploy_partition() { local disk="$1" local is_efi="$2" - parted --script "${disk}" mklabel gpt || - { image_deploy_fatal "mklabel gpt fehlgeschlagen auf ${disk}"; return 1; } + _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; } if [[ "${is_efi}" == "true" ]]; then parted --script "${disk}" mkpart ESP fat32 1MiB 513MiB && @@ -65,8 +114,8 @@ image_deploy_partition() { { image_deploy_fatal "Partitionierung (BIOS) fehlgeschlagen auf ${disk}"; return 1; } fi - partprobe "${disk}" 2>/dev/null || true - udevadm settle + _image_deploy_settle_partitions "${disk}" || + { image_deploy_fatal "Kernel konnte die neuen Partitionen auf ${disk} nicht uebernehmen."; return 1; } local part1 part2 part1="$(image_deploy_partition_path "${disk}" 1)" diff --git a/scripts/lib/image_deploy.sh b/scripts/lib/image_deploy.sh index efc732e..7ac8498 100644 --- a/scripts/lib/image_deploy.sh +++ b/scripts/lib/image_deploy.sh @@ -46,12 +46,61 @@ image_deploy_partition_path() { # an, siehe dortiger Kommentar zu bios_grub). Gibt "BOOT_PART ROOT_PART" # auf stdout aus - BOOT_PART ist bei BIOS leer (die biosgrub-Partition # braucht kein Dateisystem/keinen Mountpunkt). +# Vorhandene Partitionen der Zielplatte vor dem Neupartitionieren freigeben +# (unmounten, Swap deaktivieren) - live auf echter Hardware gefunden +# (01.09.2026): parted schreibt eine neue Partitionstabelle zwar trotzdem +# auf die Platte, meldet aber einen Fehler ("...have been unable to inform +# the Kernel of the change... probably because it/they are in use"), wenn +# eine alte Partition (z.B. Swap oder ein gemountetes Dateisystem vom +# vorherigen Betriebssystem auf dieser Platte) noch belegt ist. In QEMU mit +# stets frischen Testplatten nie aufgetreten - reale Kundenhardware hat +# aber fast immer schon ein Vorleben auf der Platte. +_image_deploy_release_disk() { + local disk="$1" + local part + + for part in "${disk}"?*; do + [[ -b "${part}" ]] || continue + swapoff "${part}" 2>/dev/null || true + umount --recursive "${part}" 2>/dev/null || true + done +} + +# Manche Kernel-/Platten-Kombinationen brauchen mehrere Anlaeufe, bis das +# Neueinlesen der Partitionstabelle (BLKRRPART) greift, gerade direkt nach +# einem mklabel auf einer zuvor belegten Platte - deshalb mehrfach +# probieren statt nach einem einzigen partprobe-Aufruf aufzugeben. +_image_deploy_settle_partitions() { + local disk="$1" + local attempt + + for attempt in 1 2 3 4 5; do + if partprobe "${disk}" 2>/dev/null; then + udevadm settle + return 0 + fi + sleep 1 + done + + udevadm settle + return 1 +} + image_deploy_partition() { local disk="$1" local is_efi="$2" - parted --script "${disk}" mklabel gpt || - { image_deploy_fatal "mklabel gpt fehlgeschlagen auf ${disk}"; return 1; } + _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; } if [[ "${is_efi}" == "true" ]]; then parted --script "${disk}" mkpart ESP fat32 1MiB 513MiB && @@ -65,8 +114,8 @@ image_deploy_partition() { { image_deploy_fatal "Partitionierung (BIOS) fehlgeschlagen auf ${disk}"; return 1; } fi - partprobe "${disk}" 2>/dev/null || true - udevadm settle + _image_deploy_settle_partitions "${disk}" || + { image_deploy_fatal "Kernel konnte die neuen Partitionen auf ${disk} nicht uebernehmen."; return 1; } local part1 part2 part1="$(image_deploy_partition_path "${disk}" 1)"