Fix mirrorsetup function in homelab.sh

This commit is contained in:
myve 2026-10-04 07:46:03 +00:00
commit 59015d9d01

View file

@ -506,89 +506,126 @@ function initialSetup
# Customize mirrored zpools # Customize mirrored zpools
function mirrorsetup function mirrorsetup
{ {
local mirrorsetupArray=(${installation_drive_array[@]}) # Initialize with available drives from installation array
local mirror pair pairArray diskid pool local available_drives=("${installation_drive_array[@]}")
local index=1 local pool_count=0
declare -a pools=()
local prompt_index=1
while true while [[ ${#available_drives[@]} -gt 0 ]]
do do
# Exit only when all drives are assigned # Display available drives to user
if [[ $(wc -w <<<${mirrorsetupArray[@]}) -gt 0 ]] say in black bold "# System drives: ${available_drives[*]}"
# Prompt user for this mirror pool (this sets pool1, pool2, etc.)
ask for pool${prompt_index} in array "Enter mirror pool ${prompt_index}"
# Safely get the array content using a controlled approach
local pairArray=()
# Create variable name and access it safely
local var_name="pool${prompt_index}"
# Use eval in a controlled way to get array contents
# This is the minimal safe usage needed for bash array handling
if [[ -n "${!var_name}" ]]
then then
say in black bold "# System drives: $(echo ${mirrorsetupArray[@]})" eval "pairArray=(\"\${${var_name}[@]}\")"
ask for pool${index} in array "Enter mirror pool ${index}"
else else
break 1 # If no content, create empty array
pairArray=()
fi fi
# Temporary variables # Validate selections - check invalid drives first
pair=pool${index}[@] local valid=true
pairArray=($(printf '%s\n' ${!pair}))
# Escape only if selections are valid # Check each drive is available BEFORE checking minimum pool size
while true for drive in "${pairArray[@]}"
do do
# Ensure drive is chosen from installation drive pool local found=false
for drive in ${pairArray[@]} for available in "${available_drives[@]}"
do do
if ! [[ " ${mirrorsetupArray[*]} " =~ " ${drive} " ]] if [[ "$drive" == "$available" ]]
then then
say as warning "Invalid drive selected" found=true
echo break
break 2
fi fi
done done
# Reject mirrored pair if drives are entered more than once if [[ "$found" == false ]]
if [ $(printf '%s\n' ${!pair} | sort | uniq -d) ] then
say as warning "Invalid drive selected: $drive"
valid=false
break
fi
done
# Only continue with other validations if drives are valid
if [[ "$valid" == true ]]
then
# Check for duplicates
local unique_count=$(printf '%s\n' "${pairArray[@]}" | sort | uniq | wc -l)
local total_count=${#pairArray[@]}
if [[ $unique_count -lt $total_count ]]
then then
say as warning "Duplicate entries detected" say as warning "Duplicate entries detected"
echo valid=false
break 1 fi
# Need at least 2 drives per mirrored pool
elif [[ ${#pairArray[@]} -lt 2 ]] # Check minimum pool size (only after we know drives are valid)
if [[ ${#pairArray[@]} -lt 2 ]]
then then
say as warning 'Mirrored pairs must have at least two drives' say as warning 'Mirrored pairs must have at least two drives'
echo valid=false
break 1 fi
# Stray protection
elif [[ $((${#mirrorsetupArray[@]}-${#pairArray[@]})) -eq 1 ]] # Check for stray drives (only after we know drives are valid)
local remaining_after=$(( ${#available_drives[@]} - ${#pairArray[@]} ))
if [[ $remaining_after -eq 1 ]] && [[ ${#available_drives[@]} -gt ${#pairArray[@]} ]]
then then
say as warning 'Remaining drive does not have a mirror pair' say as warning 'Remaining drive does not have a mirror pair'
echo valid=false
break 1 fi
# Success: remove entries from remaining drive pool fi
else
for delete in ${pairArray[@]} # Process valid pool
if [[ "$valid" == true ]]
then
# Store this mirror pool configuration
pools[$pool_count]="${pairArray[*]}"
((pool_count++))
# Remove selected drives from available list
local new_available=()
for drive in "${available_drives[@]}"
do do
mirrorsetupArray=(${mirrorsetupArray[@]/${delete}}) local is_selected=false
done for selected in "${pairArray[@]}"
# Add an index if there are more drives remaining do
((index++)) if [[ "$drive" == "$selected" ]]
break 1 then
is_selected=true
break
fi fi
done done
if [[ "$is_selected" == false ]]
then
new_available+=("$drive")
fi
done
available_drives=("${new_available[@]}")
((prompt_index++))
else
echo
continue
fi
done done
# Convert drives to persistent disk/by-id naming
for pool in ${!pool*}
do
((mirror++))
local diskid=${pool}[@]
for drive in ${!diskid}
do
eval "mirrorpool${mirror}+=(${drive})"
done
done
# Export zroot layout
unset zrootlayout unset zrootlayout
pool=0 for ((i=0; i<pool_count; i++))
for mirrorpool in ${!mirrorpool*}
do do
((pool++)) local drives="${pools[$i]}"
zpool=${mirrorpool}[@] say as success "zroot mirror $((i+1)): ${drives}"
say as success "zroot mirror ${pool}: ${!zpool}" zrootlayout+=("mirror ${drives}")
zrootlayout+=($(echo "mirror ${!zpool}"))
done done
echo echo
} }