Big work on the disk selection. Improved efficiency and clarity. Have to continue working on it.

This commit is contained in:
Raphael Numbus
2025-12-07 19:22:38 +01:00
parent 75144767b4
commit 1f8c6c50d7
2 changed files with 100 additions and 54 deletions
-1
View File
@@ -41,4 +41,3 @@
type = "xfs";
label = "data-storage";
mountpoint = "/mnt/data-storage";
+100 -53
View File
@@ -282,46 +282,93 @@ disk_config_generation() {
echo -e "\n\n 🔎 Fetching and analyzing disks from target host... (This may take a moment)"
declare -A DISK_INFO_MAP
declare -A DISK_SIZE_MAP
declare -A DISK_BY_ID_MAP
declare -A DISK_LABEL_MAP
DISK_OPTIONS=()
DISK_NAMES=$(ssh_to_host "lsblk -d -n -o NAME,TYPE | awk '\$2==\"disk\" {print \$1}'")
# --> Get disks info
for name in $DISK_NAMES; do
details=$(echo "$REMOTE_PASS" | ssh_to_host "
set -e
devpath=/dev/$name
rota=1 # Default to rotational (HDD)
[ -f /sys/block/$name/queue/rotational ] && rota=\$(cat /sys/block/$name/queue/rotational)
tran=\$(lsblk -d -n -o TRAN \"\$devpath\" || echo 'unknown')
health=\$(sudo -S smartctl -H \"\$devpath\" 2>/dev/null | grep 'self-assessment' | awk '{print \$6}')
by_id=\$(ls -l /dev/disk/by-id | grep -m 1 \"../../$name\$\" | awk '{print \"/dev/disk/by-id/\"\$9}')
# Determine type
if [[ \"\$name\" == nvme* ]]; then type=\"NVMe\"; # Check for NVMe first
elif [[ \"\$rota\" == \"0\" ]]; then type=\"SSD\";
elif [[ \"\$tran\" == \"usb\" ]]; then type=\"USB\";
else type=\"HDD\"; fi
### --> Get disk information
DISK_DETAILS=$(ssh_to_host "
# Declare arrays and variables
DISK_DEVPATH=()
DISK_NAME=()
DISK_TYPE=()
DISK_HEALTH=()
DISK_ID=()
DISK_SIZE=()
HDD=1
# Fallback for health and by-id
[[ -z \"\$health\" || \"\$health\" == \"\" ]] && health=\"N/A\"
[ -z \"\$by_id\" ] && by_id=\"\$devpath\"
for DISK in \$(lsblk -d -n -o NAME); do
# Disk name and simple path
DISK_DEVPATH+=(\"/dev/\$DISK\")
DISK_NAME+=(\"\$DISK\")
# Get size last, after other commands that might fail
size=\$(lsblk -b -d -n -o SIZE \"\$devpath\")
echo \"\$size:::\$type:::\$health:::\$by_id\"
")
# Get disks info <--
# Disk type
HDD=\$(cat /sys/block/\$DISK/queue/rotational)
TRANSPORT_PROTOCOL=\$(lsblk -d -n -o TRAN /dev/\$DISK)
if [[ \"\$DISK\" == \"nvme*\" ]]; then DISK_TYPE+=(\"NVMe\");
elif [[ \"\$TRANSPORT_PROTOCOL\" == \"usb\" ]]; then DISK_TYPE+=(\"USB\");
elif [[ \"\$HDD\" == \"1\" ]]; then DISK_TYPE+=(\"HDD\");
elif [[ \"\$HDD\" == \"0\" ]]; then DISK_TYPE+=(\"SSD\");
else DISK_TYPE+=(\"Other\")
fi
mapfile -t parts < <(echo "$details" | tr ':' '\n')
size="${parts[0]}"
disk_type="${parts[3]}"
health="${parts[6]}"
by_id="${parts[9]}"
# Disk health
if [[ \$(echo "$REMOTE_PASS" | sudo -S smartctl -H /dev/\$DISK 2>/dev/null | grep 'self-assessment' | awk '{print \$6}') == \"PASSED\" ]]; then
DISK_HEALTH+=(\"PASSED\")
else
DISK_HEALTH+=(\"N/A\")
fi
# Disk ID
DISK_ID+=(\$(ls -l /dev/disk/by-id | grep -m1 \"../../\$DISK\" | awk '{print \"/dev/disk/by-id/\" \$9}'))
# Disk size
DISK_SIZE+=(\"\$(lsblk -d -n -o SIZE /dev/\$DISK)\")
done
# Print elements
echo \"\${DISK_DEVPATH[@]}\"
echo \"\${DISK_NAME[@]}\"
echo \"\${DISK_TYPE[@]}\"
echo \"\${DISK_HEALTH[@]}\"
echo \"\${DISK_ID[@]}\"
echo \"\${DISK_SIZE[@]}\"
"
)
# Get arrays back
readarray -t LINES <<<"$DISK_DETAILS"
read -r -a DISK_DEVPATH <<<"${LINES[0]}"
read -r -a DISK_NAME <<<"${LINES[1]}"
read -r -a DISK_TYPE <<<"${LINES[2]}"
read -r -a DISK_HEALTH <<<"${LINES[3]}"
read -r -a DISK_ID <<<"${LINES[4]}"
read -r -a DISK_SIZE <<<"${LINES[5]}"
### Get disk information <--
### --> Disk selection
NUMBER_OF_DISKS=${#DISK_NAME[@]}
if [ "$NUMBER_OF_DISKS" -eq 0 ]; then
echo " ❌ No disks found on the target host. Aborting."
exit 1
fi
HEADER=$(printf " %-12s %-12s %-12s %-12s %s" "Device" "Type" "Size" "SMART" "Path")
i=0
for DISK in $(seq 1 $NUMBER_OF_DISKS); do
PRINTED_ELEMENT=$(printf "%-12s %-12s %-12s %-12s %s" "${DISK_NAME[$i]}" "${DISK_TYPE[$i]}" "${DISK_SIZE[$i]}" "${DISK_HEALTH[$i]}" "${DISK_DEVPATH[$i]}")
PRINTED_ELEMENTS+=("$PRINTED_ELEMENT")
i=$i+1
done
gum style --foreground 212 " ➡️ Please choose one (stripe) or two (mirror) disks for your NixOS boot installation:"
echo -e ""
mapfile -t SELECTED_BOOT_LABELS < <(gum choose --limit 2 --header "$HEADER" "${PRINTED_ELEMENTS[@]}")
### Disk selection <--
## Now you have to look at associative arrays to define clear variable for the following logic (i.e. BOOT_DISK_1, BOOT_DISK_2, etc)
human_size=$(numfmt --to=iec-i --suffix=B "$size")
label=$(printf "%-12s %-12s %-12s %-12s %s" "$name" "$disk_type" "$human_size" "$health" "$by_id")
@@ -333,10 +380,6 @@ disk_config_generation() {
DISK_LABEL_MAP["$name"]="$label"
done
if [ ${#DISK_OPTIONS[@]} -eq 0 ]; then
echo " ❌ No disks found on the target host. Aborting."
exit 1
fi
HEADER=$(printf " %-12s %-12s %-12s %-12s %s" "Device" "Type" "Size" "SMART" "ID")
gum style --foreground 212 " ➡️ Please choose one (stripe) or two (mirror) disks for your NixOS boot installation:"
@@ -442,7 +485,7 @@ The mirror will be created using the size of the smaller disk, and any extra spa
echo -e "\n\n ⚠️ No remaining disks to select for data."
fi
# --> Final recap
### --> Final recap
NUMBER_OF_BOOT_DISKS=0
[[ -n "$BOOT_DISK_1" ]] && NUMBER_OF_BOOT_DISKS=$((NUMBER_OF_BOOT_DISKS + 1)) && export BOOT_DISK_1
[[ -n "$BOOT_DISK_2" ]] && NUMBER_OF_BOOT_DISKS=$((NUMBER_OF_BOOT_DISKS + 1)) && export BOOT_DISK_2
@@ -468,35 +511,36 @@ EOF
gum style --border normal --margin "1" --padding "1 2" --border-foreground 212 "$(gum format <<< "$RECAP_CONTENT")"
gum confirm "Proceed with this disk configuration?" || { echo " ❌ Aborting as requested."; exit 1; }
# Final recap <--
### Final recap <--
### --> Disko file generation
echo -e "\n\n ✅ Generating disko configuration from templates..."
template_file="config-files/disks/boot-${NUMBER_OF_BOOT_DISKS}.nix"
(envsubst < "$template_file") > ./nix-config/disks/disko.nix
echo -e "\n ✅ Generated boot disk configuration."
if (( NUMBER_OF_CONTENT_DISKS == 1 && NUMBER_OF_PARITY_DISKS == 1 )); then
# Mirror configuration
if [[ "$NUMBER_OF_CONTENT_DISKS" == 1 && "$NUMBER_OF_PARITY_DISKS" == 1 ]]; then
(envsubst < "config-files/disks/mirror.nix") >> ./nix-config/disks/disko.nix
fi
if (( NUMBER_OF_CONTENT_DISKS != 2 )); then
# SnapRAID configuration
elif [[ "$NUMBER_OF_CONTENT_DISKS" -gt 0 ]]; then
for i in $(seq 1 $NUMBER_OF_CONTENT_DISKS); do
disk_var="CONTENT_DISK_$i"
LOOP_DISK="CONTENT_DISK_$i"
export DISK_NUMBER=$i
export DISK_PATH=${!disk_var}
export DISK_PATH=${!LOOP_DISK}
(envsubst < "config-files/disks/content.nix") >> ./nix-config/disks/disko.nix
done
[[ "$NUMBER_OF_CONTENT_DISKS" -gt 0 ]] && echo -e "\n ✅ Generated $NUMBER_OF_CONTENT_DISKS data disk configuration(s)."
echo -e "\n ✅ Generated $NUMBER_OF_CONTENT_DISKS data disk configuration(s)."
for i in $(seq 1 $NUMBER_OF_PARITY_DISKS); do
disk_var="PARITY_DISK_$i"
LOOP_DISK="PARITY_DISK_$i"
export DISK_NUMBER=$i
export DISK_PATH=${!disk_var}
export DISK_PATH=${!LOOP_DISK}
(envsubst < "config-files/disks/parity.nix") >> ./nix-config/disks/disko.nix
done
[[ "$NUMBER_OF_PARITY_DISKS" -gt 0 ]] && echo -e "\n ✅ Generated $NUMBER_OF_PARITY_DISKS parity disk configuration(s)."
echo -e "\n ✅ Generated $NUMBER_OF_PARITY_DISKS parity disk configuration(s)."
fi
# Close the disko.nix block
cat <<'EOF' >> ./nix-config/disks/disko.nix
};
@@ -504,6 +548,9 @@ EOF
}
EOF
echo -e "\n ✅ Final disko configuration created."
### Disko file generation <--
# --> Generate automatic unlock configuration in ./nix-config/disks/snapraid.nix
if [[ "$NUMBER_OF_CONTENT_DISKS" -gt 1 && "$NUMBER_OF_PARITY_DISKS" -gt 0 ]]; then