255 lines
7.6 KiB
Bash
255 lines
7.6 KiB
Bash
#!/bin/bash
|
||
|
||
get_disk_priority() {
|
||
local disk=$1
|
||
local disk_name=$(basename $disk)
|
||
|
||
if [[ $disk_name == nvme* ]]; then
|
||
echo 1
|
||
return
|
||
fi
|
||
|
||
local rotational=$(cat /sys/block/$disk/queue/rotational 2>/dev/null)
|
||
if [[ $rotational -eq 0 ]]; then
|
||
echo 2
|
||
return
|
||
fi
|
||
|
||
local transport=$(lsblk -d -o NAME,TRAN /dev/$disk 2>/dev/null | grep $disk | awk '{print $2}')
|
||
if [[ $transport == "sas" ]]; then
|
||
echo 3
|
||
else
|
||
echo 4 # SATA OR OTHER
|
||
fi
|
||
}
|
||
|
||
get_disk_size() {
|
||
local disk=$1
|
||
cat /sys/block/$disk/size 2>/dev/null
|
||
}
|
||
|
||
is_installed_node() {
|
||
local disks=$(lsblk -d -n -o NAME,TYPE | grep disk | awk '{print $1}')
|
||
|
||
for disk in $disks; do
|
||
local partitions=$(lsblk -n -o NAME /dev/$disk | grep -E "^${disk}p?[0-9]+" || true)
|
||
|
||
for part in $partitions; do
|
||
local mount_point="/mnt/tmp_${part}"
|
||
mkdir -p $mount_point 2>/dev/null
|
||
|
||
if mount -t ext4 -o ro /dev/$part $mount_point 2>/dev/null || \
|
||
mount -t xfs -o ro /dev/$part $mount_point 2>/dev/null; then
|
||
|
||
if [[ -f $mount_point/.sunhpc-release ]]; then
|
||
umount $mount_point
|
||
rmdir $mount_point 2>/dev/null
|
||
echo "yes"
|
||
return 0
|
||
fi
|
||
umount $mount_point
|
||
fi
|
||
rmdir $mount_point 2>/dev/null
|
||
done
|
||
done
|
||
|
||
echo "no"
|
||
}
|
||
|
||
select_best_disk() {
|
||
local disks=()
|
||
|
||
for disk in /sys/block/*; do
|
||
local disk_name=$(basename $disk)
|
||
if [[ $disk_name =~ ^(loop|zram|ram|sr|fd|dm-) ]]; then
|
||
continue
|
||
fi
|
||
if [[ -e /dev/$disk_name ]] && [[ $(cat /sys/block/$disk_name/removable 2>/dev/null) -eq 0 ]]; then
|
||
disks+=($disk_name)
|
||
fi
|
||
done
|
||
|
||
if [[ ${#disks[@]} -eq 0 ]]; then
|
||
echo ""
|
||
return 1
|
||
fi
|
||
|
||
declare -A disk_priority
|
||
declare -A disk_size
|
||
|
||
for disk in "${disks[@]}"; do
|
||
disk_priority[$disk]=$(get_disk_priority $disk)
|
||
disk_size[$disk]=$(get_disk_size $disk)
|
||
done
|
||
|
||
local sorted_disks=($(for disk in "${disks[@]}"; do
|
||
echo "${disk_priority[$disk]}:${disk_size[$disk]}:$disk"
|
||
done | sort -n -t: -k1,1 -k2,2rn | cut -d: -f3))
|
||
|
||
echo "${sorted_disks[0]}"
|
||
}
|
||
|
||
# 智能计算 Root 分区大小
|
||
# 参数: $1 = 磁盘总大小(GB), $2 = 期望的默认大小(GB)
|
||
# 返回: 合适的 root 分区大小(GB)
|
||
calculate_root_size() {
|
||
local disk_total_gb=$1
|
||
local default_root_gb=${2:-70}
|
||
local min_root_gb=30
|
||
local max_root_gb=100
|
||
|
||
# 如果磁盘总容量小于最小要求(70GB + boot + swap = 约75GB)
|
||
if [[ $disk_total_gb -lt 75 ]]; then
|
||
# 磁盘太小,使用最小 root 分区
|
||
echo $min_root_gb
|
||
elif [[ $disk_total_gb -lt 100 ]]; then
|
||
# 磁盘在 75-100GB 之间,使用 40-50GB
|
||
echo $((disk_total_gb - 45)) # 预留 boot+swap+state 空间
|
||
elif [[ $disk_total_gb -lt 150 ]]; then
|
||
# 磁盘在 100-150GB 之间,使用 60GB
|
||
echo 60
|
||
elif [[ $disk_total_gb -lt 250 ]]; then
|
||
# 磁盘在 150-250GB 之间,使用默认 70GB
|
||
echo $default_root_gb
|
||
else
|
||
# 大磁盘,限制最大 100GB
|
||
echo $max_root_gb
|
||
fi
|
||
}
|
||
|
||
calculate_state_size() {
|
||
local disk_total_sectors=$1
|
||
local root_size_sectors=$2
|
||
echo $((disk_total_sectors - root_size_sectors))
|
||
}
|
||
|
||
get_disk_size_gb() {
|
||
local disk=$1
|
||
local total_sectors=$(cat /sys/block/$disk/size 2>/dev/null)
|
||
local total_gb=$((total_sectors * 512 / 1024 / 1024 / 1024))
|
||
echo $total_gb
|
||
}
|
||
|
||
get_disk_type() {
|
||
local disk=$1
|
||
|
||
if [[ $disk == nvme* ]]; then
|
||
echo "NVMe"
|
||
elif [[ $(cat /sys/block/$disk/queue/rotational 2>/dev/null) -eq 0 ]]; then
|
||
echo "SSD"
|
||
else
|
||
local transport=$(lsblk -d -o NAME,TRAN /dev/$disk 2>/dev/null | grep $disk | awk '{print $2}')
|
||
if [[ $transport == "sas" ]]; then
|
||
echo "SAS"
|
||
else
|
||
echo "SATA"
|
||
fi
|
||
fi
|
||
}
|
||
|
||
generate_ks_partition() {
|
||
local disk=$1
|
||
local is_upgrade=$2
|
||
|
||
# 获取磁盘总容量(扇区和GB)
|
||
local total_sectors=$(cat /sys/block/$disk/size)
|
||
local total_gb=$(get_disk_size_gb $disk)
|
||
local disk_type=$(get_disk_type $disk)
|
||
|
||
# 智能计算 root 分区大小
|
||
local root_gb=$(calculate_root_size $total_gb 70)
|
||
local root_size_sectors=$((root_gb * 1024 * 1024 * 1024 / 512))
|
||
|
||
# 计算剩余空间给 state 分区
|
||
local remaining_sectors=$((total_sectors - root_size_sectors))
|
||
local remaining_gb=$((remaining_sectors * 512 / 1024 / 1024 / 1024))
|
||
|
||
# 计算 boot 和 swap 预留空间
|
||
local boot_gb=1
|
||
local swap_gb=4
|
||
local reserved_gb=$((boot_gb + swap_gb))
|
||
|
||
cat << EOF
|
||
# ==================================================
|
||
# Disk Partition Information
|
||
# ==================================================
|
||
# Installation Type : $([ "$is_upgrade" == "yes" ] && echo "Upgrade" || echo "Fresh") Installation
|
||
# Disk Device : /dev/$disk
|
||
# Disk Type : $disk_type
|
||
# Disk Total : $total_gb GB ($total_sectors sectors)
|
||
#
|
||
# Partition Plan:
|
||
# - /boot : ${boot_gb}GB (reserved)
|
||
# - swap : ${swap_gb}GB (reserved)
|
||
# - / : ${root_gb}GB ($root_size_sectors sectors)
|
||
# - /state : ${remaining_gb}GB ($remaining_sectors sectors)
|
||
# ==================================================
|
||
EOF
|
||
|
||
cat << EOF
|
||
zerombr
|
||
ignoredisk --only-use=$disk
|
||
clearpart --all --initlabel
|
||
part /boot --fstype="xfs" --size=1024 --ondisk=$disk
|
||
part swap --fstype="swap" --size=4096 --ondisk=$disk
|
||
part / --fstype="xfs" --size=$((root_gb * 1024)) --ondisk=$disk
|
||
EOF
|
||
|
||
if [[ $is_upgrade == "yes" ]]; then
|
||
cat << EOF
|
||
part /state/partition1 --fstype=xfs --size=1 --grow --ondisk=$disk
|
||
EOF
|
||
fi
|
||
}
|
||
|
||
main() {
|
||
local is_installed=$(is_installed_node)
|
||
|
||
if [[ $is_installed == "yes" ]]; then
|
||
echo "# Detected: Already installed node (found .sunhpc-release)"
|
||
local found_disk=""
|
||
local disks=$(lsblk -d -n -o NAME,TYPE | grep disk | awk '{print $1}')
|
||
|
||
for disk in $disks; do
|
||
local partitions=$(lsblk -n -o NAME /dev/$disk | grep -E "^${disk}p?[0-9]+" || true)
|
||
for part in $partitions; do
|
||
local mount_point="/mnt/tmp_${part}"
|
||
mkdir -p $mount_point 2>/dev/null
|
||
if mount -t ext4 -o ro /dev/$part $mount_point 2>/dev/null || \
|
||
mount -t xfs -o ro /dev/$part $mount_point 2>/dev/null; then
|
||
if [[ -f $mount_point/.sunhpc-release ]]; then
|
||
found_disk=$disk
|
||
umount $mount_point
|
||
rmdir $mount_point 2>/dev/null
|
||
break 2
|
||
fi
|
||
umount $mount_point
|
||
fi
|
||
rmdir $mount_point 2>/dev/null
|
||
done
|
||
done
|
||
|
||
if [[ -n $found_disk ]]; then
|
||
echo "# Found existing installation on disk: /dev/$found_disk"
|
||
generate_ks_partition $found_disk "yes"
|
||
else
|
||
echo "# ERROR: Cannot find disk with .sunhpc-release, using default"
|
||
local best_disk=$(select_best_disk)
|
||
generate_ks_partition $best_disk "yes"
|
||
fi
|
||
else
|
||
echo "# Detected: Fresh installation"
|
||
local best_disk=$(select_best_disk)
|
||
|
||
if [[ -z $best_disk ]]; then
|
||
echo "# ERROR: No disk found"
|
||
exit 1
|
||
fi
|
||
|
||
echo "# Selected best disk: /dev/$best_disk"
|
||
generate_ks_partition $best_disk "no"
|
||
fi
|
||
}
|
||
|
||
main
|