Files
hpctools/pkgs/ks/dfmt.sh
2026-04-26 13:25:50 +08:00

255 lines
7.6 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/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