diff --git a/scripts/config.sh b/scripts/config.sh index 72a4ef8..50798ac 100644 --- a/scripts/config.sh +++ b/scripts/config.sh @@ -10,13 +10,13 @@ create_default_disk_layout() { local device="$1" create_gpt new_id=gpt device="$device" - create_partition new_id=part_efi id=gpt size=128MiB type=efi - create_partition new_id=part_swap id=gpt size=8GiB type=raid - create_partition new_id=part_root id=gpt size=auto type=raid + create_partition new_id=part_efi id=gpt size=128MiB type=efi + create_partition new_id=part_swap id=gpt size=8GiB type=raid + create_partition new_id=part_root id=gpt size=remaining type=raid format id=part_efi type=efi label=efi format id=part_swap type=swap label=swap - format id=part_root type=ext4 label=ext4 + format id=part_root type=ext4 label=root DISK_ID_EFI=part_efi DISK_ID_SWAP=part_raid @@ -33,9 +33,9 @@ create_default_disk_layout /dev/sdX devices=(/dev/sd{X,Y}) for i in "${!devices[@]}"; do create_gpt new_id="gpt_dev${i}" device="${devices[$i]}" - create_partition new_id="part_efi_dev${i}" id="gpt_dev${i}" size=128MiB type=efi - create_partition new_id="part_swap_dev${i}" id="gpt_dev${i}" size=8GiB type=raid - create_partition new_id="part_root_dev${i}" id="gpt_dev${i}" size=auto type=raid + create_partition new_id="part_efi_dev${i}" id="gpt_dev${i}" size=128MiB type=efi + create_partition new_id="part_swap_dev${i}" id="gpt_dev${i}" size=8GiB type=raid + create_partition new_id="part_root_dev${i}" id="gpt_dev${i}" size=remaining type=raid done create_raid new_id=part_raid_swap level=0 ids="$(expand_ids '^part_swap_dev\d$')" @@ -44,7 +44,7 @@ create_luks new_id=part_luks_root id=part_raid_root format id=part_efi_dev0 type=efi label=efi format id=part_raid_swap type=swap label=swap -format id=part_luks_root type=ext4 label=ext4 +format id=part_luks_root type=ext4 label=root DISK_ID_EFI=part_efi_dev0 DISK_ID_SWAP=part_raid_swap diff --git a/scripts/functions.sh b/scripts/functions.sh index 7d71bf9..ee09bef 100644 --- a/scripts/functions.sh +++ b/scripts/functions.sh @@ -98,50 +98,174 @@ summary_color_args() { done } +resolve_id_to_device() { + local id="$1" + [[ -v disk_id_to_resolvable[$id] ]] \ + || die "Cannot resolve id='$id' to a block device (no table entry)" + + local type="${disk_id_to_resolvable[$id]%%:*}" + local arg="${disk_id_to_resolvable[$id]#*:}" + + case "$type" in + 'partuuid') get_device_by_partuuid "$arg" ;; + 'uuid') get_device_by_uuid "$arg" ;; + 'raw') echo -n "$arg" ;; + *) die "Cannot resolve '$type:$arg' to device (unkown type)" + esac +} + disk_create_gpt() { + local new_id="${arguments[new_id]}" if [[ $disk_action_summarize_only == true ]]; then if [[ -v arguments[id] ]]; then - add_summary_entry "${arguments[id]}" "${arguments[new_id]}" "gpt" "" "" + add_summary_entry "${arguments[id]}" "$new_id" "gpt" "" "" else - add_summary_entry __root__ "${arguments[new_id]}" "${arguments[device]}" "(gpt)" "" + add_summary_entry __root__ "$new_id" "${arguments[device]}" "(gpt)" "" fi return 0 fi + + local device + if [[ -v arguments[id] ]]; then + device="$(resolve_id_to_device "${arguments[id]}")" + else + device="${arguments[device]}" + fi + + disk_id_to_resolvable[$new_id]="raw:$device" + sgdisk -Z "$device" >/dev/null \ + || die "Could not create new gpt partition table ($new_id) on '$device'" + partprobe "$device" } disk_create_partition() { + local new_id="${arguments[new_id]}" + local id="${arguments[id]}" + local size="${arguments[size]}" + local type="${arguments[type]}" if [[ $disk_action_summarize_only == true ]]; then - add_summary_entry "${arguments[id]}" "${arguments[new_id]}" "part" "(${arguments[type]})" "$(summary_color_args size)" + add_summary_entry "$id" "$new_id" "part" "($type)" "$(summary_color_args size)" return 0 fi + + if [[ $size == "remaining" ]]; then + size=0 + else + size="+$size" + fi + + local device="$(resolve_id_to_device "$id")" + local partuuid="$(load_or_generate_uuid "$(base64 -w 0 <<< "$new_id")")" + case "$type" in + 'boot') type='ef02' ;; + 'efi') type='ef00' ;; + 'swap') type='8200' ;; + 'raid') type='fd00' ;; + 'luks') type='8309' ;; + 'linux') type='8300' ;; + *) ;; + esac + + disk_id_to_resolvable[$new_id]="partuuid:$partuuid" + sgdisk -n "0:0:$size" -t "0:$type" -u 0:"$partuuid" "$device" >/dev/null \ + || die "Could not create new gpt partition ($new_id) on '$device' ($id)" + partprobe "$device" } disk_create_raid() { + local new_id="${arguments[new_id]}" + local level="${arguments[level]}" + local ids="${arguments[ids]}" if [[ $disk_action_summarize_only == true ]]; then local id # Splitting is intentional here # shellcheck disable=SC2086 - for id in ${arguments[ids]//';'/ }; do - add_summary_entry "$id" "_${arguments[new_id]}" "raid${arguments[level]}" "" "" + for id in ${ids//';'/ }; do + add_summary_entry "$id" "_$new_id" "raid$level" "" "" done - add_summary_entry __root__ "${arguments[new_id]}" "raid${arguments[level]}" "" "" + add_summary_entry __root__ "$new_id" "raid$level" "" "" return 0 fi + + local devices=() + # Splitting is intentional here + # shellcheck disable=SC2086 + for id in ${ids//';'/ }; do + devices+=("$(resolve_id_to_device "$id")") + done + + local uuid="$(load_or_generate_uuid "$(base64 -w 0 <<< "$new_id")")" + disk_id_to_resolvable[$new_id]="uuid:$uuid" + + mdadm --create \ + --uuid="$uuid" \ + --level="$level" \ + "${devices[@]}" \ + || die "Could not format device '$device' ($id)" } disk_create_luks() { + local new_id="${arguments[new_id]}" + local id="${arguments[id]}" if [[ $disk_action_summarize_only == true ]]; then - add_summary_entry "${arguments[id]}" "${arguments[new_id]}" "luks" "" "" + add_summary_entry "$id" "$new_id" "luks" "" "" return 0 fi + + local device="$(resolve_id_to_device "$id")" + local uuid="$(load_or_generate_uuid "$(base64 -w 0 <<< "$new_id")")" + disk_id_to_resolvable[$new_id]="uuid:$uuid" + + cryptsetup luksFormat \ + --uuid="$uuid" \ + --type=luks2 \ + --cipher aes-xts-plain64 \ + --key-size 512 \ + --pbkdf argon2id \ + --iter-time=4000 "$device" \ + || die "Could not format device '$device' ($id)" } disk_format() { + local id="${arguments[id]}" + local type="${arguments[type]}" + local label="${arguments[label]}" if [[ $disk_action_summarize_only == true ]]; then add_summary_entry "${arguments[id]}" "__fs__${arguments[id]}" "${arguments[type]}" "(fs)" "$(summary_color_args label)" return 0 fi + + case "$type" in + 'boot'|'efi') + if [[ -v "arguments[label]" ]]; then + mkfs.fat -F 32 -n "$label" "$device" \ + || die "Could not format device '$device' ($id)" + else + mkfs.fat -F 32 "$device" \ + || die "Could not format device '$device' ($id)" + fi + ;; + 'swap') + if [[ -v "arguments[label]" ]]; then + mkswap -L "$label" "$device" \ + || die "Could not format device '$device' ($id)" + else + mkswap "$device" \ + || die "Could not format device '$device' ($id)" + fi + ;; + 'ext4') + if [[ -v "arguments[label]" ]]; then + mkfs.ext4 -q -L "$label" "$device" \ + || die "Could not format device '$device' ($id)" + else + mkfs.ext4 -q "$device" \ + || die "Could not format device '$device' ($id)" + fi + ;; + *) die "Unknown filesystem type" ;; + esac } apply_disk_action() { @@ -238,32 +362,9 @@ print_summary_tree() { fi } -summarize_disk_actions() { - elog "Current lsblk output" - for_line_in <(lsblk \ - || die "Error in lsblk") elog - - disk_action_summarize_only=true - declare -A summary_tree - declare -A summary_name - declare -A summary_hint - declare -A summary_ptr - declare -A summary_desc - declare -A summary_depth_continues - apply_disk_actions - unset disk_action_summarize_only - - local depth=-1 - elog - elog "Configured disk layout" - elog ──────────────────────────────────────────────────────────────────────────────── - elog "$(printf '%-26s %-28s %s' NODE ID OPTIONS)" - elog ──────────────────────────────────────────────────────────────────────────────── - print_summary_tree __root__ - elog ──────────────────────────────────────────────────────────────────────────────── -} - apply_disk_actions() { + declare -A disk_id_to_resolvable + local param local current_params=() for param in "${DISK_ACTIONS[@]}"; do @@ -276,112 +377,134 @@ apply_disk_actions() { done } -partition_device_print_config_summary() { - elog "-------- Partition configuration --------" - elog "Device: $PARTITION_DEVICE" - elog "Existing partition table:" - for_line_in <(lsblk -n "$PARTITION_DEVICE" \ +summarize_disk_actions() { + elog "Current lsblk output:" + for_line_in <(lsblk \ || die "Error in lsblk") elog - elog "New partition table:" - elog "$PARTITION_DEVICE" - elog "├─efi size=$PARTITION_EFI_SIZE" - if [[ $ENABLE_SWAP == true ]]; then - elog "├─swap size=$PARTITION_SWAP_SIZE" - fi - elog "└─linux size=[remaining]" - if [[ $ENABLE_SWAP != true ]]; then - elog "swap: disabled" - fi + + local disk_action_summarize_only=true + declare -A summary_tree + declare -A summary_name + declare -A summary_hint + declare -A summary_ptr + declare -A summary_desc + declare -A summary_depth_continues + apply_disk_actions + + local depth=-1 + elog + elog "Configured disk layout:" + elog ──────────────────────────────────────────────────────────────────────────────── + elog "$(printf '%-26s %-28s %s' NODE ID OPTIONS)" + elog ──────────────────────────────────────────────────────────────────────────────── + print_summary_tree __root__ + elog ──────────────────────────────────────────────────────────────────────────────── } -partition_device() { - [[ $ENABLE_PARTITIONING == true ]] \ - || return 0 +apply_disk_configuration() { + summarize_disk_actions - einfo "Preparing partitioning of device '$PARTITION_DEVICE'" + ask "Do you really want to apply this disk configuration?" \ + || die "Aborted" + countdown "Applying in " 5 - [[ -b $PARTITION_DEVICE ]] \ - || die "Selected device '$PARTITION_DEVICE' is not a block device" + einfo "Applying disk configuration" + apply_disk_actions - partition_device_print_config_summary - ask "Do you really want to apply this partitioning?" \ - || die "For manual partitioning formatting please set ENABLE_PARTITIONING=false in config.sh" - countdown "Partitioning in " 5 - - einfo "Partitioning device '$PARTITION_DEVICE'" - - # Delete any existing partition table - sgdisk -Z "$PARTITION_DEVICE" >/dev/null \ - || die "Could not delete existing partition table" - - # Create efi/boot partition - sgdisk -n "0:0:+$PARTITION_EFI_SIZE" -t 0:ef00 -c 0:"efi" -u 0:"$PARTITION_UUID_EFI" "$PARTITION_DEVICE" >/dev/null \ - || die "Could not create efi partition" - - # Create swap partition - if [[ $ENABLE_SWAP == true ]]; then - sgdisk -n "0:0:+$PARTITION_SWAP_SIZE" -t 0:8200 -c 0:"swap" -u 0:"$PARTITION_UUID_SWAP" "$PARTITION_DEVICE" >/dev/null \ - || die "Could not create swap partition" - fi - - # Create system partition - sgdisk -n 0:0:0 -t 0:8300 -c 0:"linux" -u 0:"$PARTITION_UUID_LINUX" "$PARTITION_DEVICE" >/dev/null \ - || die "Could not create linux partition" - - # Print partition table - einfo "Applied partition table" - sgdisk -p "$PARTITION_DEVICE" \ - || die "Could not print partition table" - - # Inform kernel of partition table changes - partprobe "$PARTITION_DEVICE" \ - || die "Could not probe partitions" + einfo "Disk configuration was applied successfully" + elog "New lsblk output:" + for_line_in <(lsblk \ + || die "Error in lsblk") elog } -format_partitions() { - [[ $ENABLE_FORMATTING == true ]] \ - || return 0 - - if [[ $ENABLE_PARTITIONING != true ]]; then - einfo "Preparing to format the following partitions:" - - blkid -t PARTUUID="$PARTITION_UUID_EFI" \ - || die "Error while listing efi partition" - if [[ $ENABLE_SWAP == true ]]; then - blkid -t PARTUUID="$PARTITION_UUID_SWAP" \ - || die "Error while listing swap partition" - fi - blkid -t PARTUUID="$PARTITION_UUID_LINUX" \ - || die "Error while listing linux partition" - - ask "Do you really want to format these partitions?" \ - || die "For manual formatting please set ENABLE_FORMATTING=false in config.sh" - countdown "Formatting in " 5 - fi - - einfo "Formatting partitions" - - local dev - dev="$(get_device_by_partuuid "$PARTITION_UUID_EFI")" \ - || die "Could not resolve partition UUID '$PARTITION_UUID_EFI'" - einfo " $dev (efi)" - mkfs.fat -F 32 -n "efi" "$dev" \ - || die "Could not format EFI partition" - - if [[ $ENABLE_SWAP == true ]]; then - dev="$(get_device_by_partuuid "$PARTITION_UUID_SWAP")" \ - || die "Could not resolve partition UUID '$PARTITION_UUID_SWAP'" - einfo " $dev (swap)" - mkswap -L "swap" "$dev" \ - || die "Could not create swap" - fi - - dev="$(get_device_by_partuuid "$PARTITION_UUID_LINUX")" \ - || die "Could not resolve partition UUID '$PARTITION_UUID_LINUX'" - einfo " $dev (linux)" - mkfs.ext4 -q -L "linux" "$dev" \ - || die "Could not create ext4 filesystem" -} +#partition_device() { +# [[ $ENABLE_PARTITIONING == true ]] \ +# || return 0 +# +# einfo "Preparing partitioning of device '$PARTITION_DEVICE'" +# +# [[ -b $PARTITION_DEVICE ]] \ +# || die "Selected device '$PARTITION_DEVICE' is not a block device" +# +# partition_device_print_config_summary +# ask "Do you really want to apply this partitioning?" \ +# || die "For manual partitioning formatting please set ENABLE_PARTITIONING=false in config.sh" +# countdown "Partitioning in " 5 +# +# einfo "Partitioning device '$PARTITION_DEVICE'" +# +# # Delete any existing partition table +# sgdisk -Z "$PARTITION_DEVICE" >/dev/null \ +# || die "Could not delete existing partition table" +# +# # Create efi/boot partition +# sgdisk -n "0:0:+$PARTITION_EFI_SIZE" -t 0:ef00 -c 0:"efi" -u 0:"$PARTITION_UUID_EFI" "$PARTITION_DEVICE" >/dev/null \ +# || die "Could not create efi partition" +# +# # Create swap partition +# if [[ $ENABLE_SWAP == true ]]; then +# sgdisk -n "0:0:+$PARTITION_SWAP_SIZE" -t 0:8200 -c 0:"swap" -u 0:"$PARTITION_UUID_SWAP" "$PARTITION_DEVICE" >/dev/null \ +# || die "Could not create swap partition" +# fi +# +# # Create system partition +# sgdisk -n 0:0:0 -t 0:8300 -c 0:"linux" -u 0:"$PARTITION_UUID_LINUX" "$PARTITION_DEVICE" >/dev/null \ +# || die "Could not create linux partition" +# +# # Print partition table +# einfo "Applied partition table" +# sgdisk -p "$PARTITION_DEVICE" \ +# || die "Could not print partition table" +# +# # Inform kernel of partition table changes +# partprobe "$PARTITION_DEVICE" \ +# || die "Could not probe partitions" +#} +# +#format_partitions() { +# [[ $ENABLE_FORMATTING == true ]] \ +# || return 0 +# +# if [[ $ENABLE_PARTITIONING != true ]]; then +# einfo "Preparing to format the following partitions:" +# +# blkid -t PARTUUID="$PARTITION_UUID_EFI" \ +# || die "Error while listing efi partition" +# if [[ $ENABLE_SWAP == true ]]; then +# blkid -t PARTUUID="$PARTITION_UUID_SWAP" \ +# || die "Error while listing swap partition" +# fi +# blkid -t PARTUUID="$PARTITION_UUID_LINUX" \ +# || die "Error while listing linux partition" +# +# ask "Do you really want to format these partitions?" \ +# || die "For manual formatting please set ENABLE_FORMATTING=false in config.sh" +# countdown "Formatting in " 5 +# fi +# +# einfo "Formatting partitions" +# +# local dev +# dev="$(get_device_by_partuuid "$PARTITION_UUID_EFI")" \ +# || die "Could not resolve partition UUID '$PARTITION_UUID_EFI'" +# einfo " $dev (efi)" +# mkfs.fat -F 32 -n "efi" "$dev" \ +# || die "Could not format EFI partition" +# +# if [[ $ENABLE_SWAP == true ]]; then +# dev="$(get_device_by_partuuid "$PARTITION_UUID_SWAP")" \ +# || die "Could not resolve partition UUID '$PARTITION_UUID_SWAP'" +# einfo " $dev (swap)" +# mkswap -L "swap" "$dev" \ +# || die "Could not create swap" +# fi +# +# dev="$(get_device_by_partuuid "$PARTITION_UUID_LINUX")" \ +# || die "Could not resolve partition UUID '$PARTITION_UUID_LINUX'" +# einfo " $dev (linux)" +# mkfs.ext4 -q -L "linux" "$dev" \ +# || die "Could not create ext4 filesystem" +#} mount_efivars() { # Skip if already mounted diff --git a/scripts/internal_config.sh b/scripts/internal_config.sh index 150c4a6..039cd73 100644 --- a/scripts/internal_config.sh +++ b/scripts/internal_config.sh @@ -26,6 +26,8 @@ USED_LUKS=false DISK_ACTIONS=() # An associative set to check for existing ids declare -A DISK_KNOWN_IDS +# An associative set to check for correct usage of size=remaining in gpt tables +declare -A DISK_GPT_HAD_SIZE_REMAINING only_one_of() { local previous="" @@ -90,18 +92,6 @@ verify_option() { die_trace 2 "Invalid option $opt='$arg', must be one of ($*)" } -#create_luks() { -# gpg --decrypt /tmp/efiboot/luks-key.gpg | \ -# cryptsetup --cipher serpent-xts-plain64 --key-size 512 --hash whirlpool --key-file - luksFormat /dev/sdZn -# local dev -# cryptsetup luksFormat \ -# --type=luks2 \ -# --cipher aes-xts-plain64 \ -# --key-size 512 \ -# --pbkdf argon2id \ -# --iter-time=4000 "$dev" -#} - # Named arguments: # new_id: Id for the new gpt table # device: The operand block device @@ -119,7 +109,7 @@ create_gpt() { # Named arguments: # new_id: Id for the new partition -# size: Size for the new partition, or auto to allocate the rest +# size: Size for the new partition, or 'remaining' to allocate the rest # type: The parition type, either (boot, efi, swap, raid, luks, linux) (or a 4 digit hex-code for gdisk). # id: The operand device id create_partition() { @@ -130,6 +120,12 @@ create_partition() { verify_existing_id id verify_option type boot efi swap raid luks linux + [[ -v "DISK_GPT_HAD_SIZE_REMAINING[${arguments[id]}]" ]] \ + && die_trace 1 "Cannot add another partition to table (${arguments[id]}) after size=remaining was used" + + [[ ${arguments[size]} == "remaining" ]] \ + && DISK_GPT_HAD_SIZE_REMAINING[${arguments[id]}]=true + DISK_ACTIONS+=("action=create_partition" "$@" ";") } diff --git a/scripts/main.sh b/scripts/main.sh index 6f26718..d0921e2 100755 --- a/scripts/main.sh +++ b/scripts/main.sh @@ -1,5 +1,5 @@ #!/bin/bash -set -uo pipefail +set -o pipefail ################################################ # Initialize script environment @@ -43,8 +43,7 @@ install_stage3() { [[ $# == 0 ]] || die "Too many arguments" prepare_installation_environment - partition_device - format_partitions + apply_disk_configuration download_stage3 extract_stage3 } diff --git a/scripts/main_chroot.sh b/scripts/main_chroot.sh index 74e52d2..8c6b74d 100755 --- a/scripts/main_chroot.sh +++ b/scripts/main_chroot.sh @@ -1,5 +1,5 @@ #!/bin/bash -set -uo pipefail +set -o pipefail [[ ${EXECUTED_IN_CHROOT} != true ]] \ && { echo "This script must not be executed directly!" >&2; exit 1; } diff --git a/scripts/utils.sh b/scripts/utils.sh index b73770f..45a20fa 100644 --- a/scripts/utils.sh +++ b/scripts/utils.sh @@ -128,6 +128,18 @@ get_device_by_partuuid() { echo -n "$dev" } +get_device_by_uuid() { + blkid -g \ + || die "Error while executing blkid" + local dev + dev="$(blkid -o export -t UUID="$1")" \ + || die "Error while executing blkid to find UUID=$1" + dev="$(grep DEVNAME <<< "$dev")" \ + || die "Could not find DEVNAME=... in blkid output" + dev="${dev:8}" + echo -n "$dev" +} + load_or_generate_uuid() { local uuid local uuid_file="$UUID_STORAGE_DIR/$1"