From: Ian Kelling Date: Sat, 1 Mar 2025 18:06:00 +0000 (-0500) Subject: refactor, cleanup, add features to partitioning X-Git-Url: https://iankelling.org/git/?a=commitdiff_plain;h=c51e0c1967c0e59fc37add3b544f1e2a07047570;p=automated-distro-installer refactor, cleanup, add features to partitioning --- diff --git a/fai/config/hooks/partition.DEFAULT b/fai/config/hooks/partition.DEFAULT index 034a98c..95006f1 100755 --- a/fai/config/hooks/partition.DEFAULT +++ b/fai/config/hooks/partition.DEFAULT @@ -29,96 +29,139 @@ if [[ $EUID != 0 ]]; then exit 1 fi +usage() { + cat <<'EOF' +Example of calling outside of FAI: -# for calling outside of FAI. -# -# source /b/fai/fai-wrapper (note: this exports everything, including functions). -# - set any appropriate classes with: fai-setclass OPT1... which sets CLASS_OPT1=true... -# or run eval-fai-classfile FILE. -# - fai-setclass IANK|FSF (if not already set in 51-multiboot) -# /a/bin/fai/fai/config/hooks/partition.DEFAULT -# -## ARGS (only 0 or 1 is valid). All args are for use outside of fai. -# -# mkroot2: for setting up the root2/boot2 luks and btrfs and tab files -# -# mkroot2tab: for setting up the root2/boot2 tab files, in case luks and btrfs -# happen to already be setup. -# -# mktab: for generating a crypttab for the main root fs in -# /tmp/fai. Requires DISTRO be set, see below. -# -# Example use in a bootstrap distro: -# scp /b/fai/fai-wrapper /a/bin/fai/fai/config/{distro-install-common/devbyid,hooks/partition.DEFAULT} root@HOST: -# sl root@HOST -# . fai-wrapper # ignore error that FAI is not set, it is not needed for SPECIAL_DISK purposes. -# fai-setclass FSF -# export SPECIAL_DISK=/dev/sde -# export DISTRO=trisquelecne # not actually used -# . ./partition.DEFAULT -# -# ## cryptsetup wont take within a pipeline -# mapfile -t lines < <(awk '! /swap/ {print $2,$1}' /tmp/fai/crypttab ) -# for l in "${lines[@]}"; do cryptsetup luksOpen $l; done -# -# # or alternatively, to avoid typing it many times: -# read -r lukspw; for l in "${lines[@]}"; do yes "$lukspw" | cryptsetup luksOpen $l; done +Optionally: source /b/fai/fai-wrapper (note: this exports everything, including functions) and +set any appropriate classes with: fai-setclass OPT1... which sets CLASS_OPT1=true... +or run eval-fai-classfile FILE. -## potentially useful later: -# sed 's#/root/keyscript,#decrypt_keyctl,#;s/$/,noauto/' /tmp/fai/crypttab >/etc/crypttab -# -##### environment variables: -# -# HOSTNAME: if demohost, we set the luks password to just -# 'x'. Used in various other ways too. -# -# SPECIAL_DISK: For use outside of fai. A base disk name like -# /dev/sdk. If set, we just cryptsetup and partition this one disk then -# exit. It creates a single lvm pv/vg/lv called "data". If this is -# partitioning intended to go into a root filesystem, you can modify the -# script to change that, or run commands manually afterwards. This also -# sets REPARTITION. -# -# DISTRO: if not set, derived from VOL_... variable in a switch. -# Required except for mkroot2, mkroot2tab, or SPECIAL_DISK. -# -##### classes: -# -# FSF|IANK: what kind of partitioning we want to do. Required anytime we -# do partitioning. -# -# REPARTITION: forces repartitioning even if we detect the proper amount -# of partitions already exist. -# -# NOWIPE: use existing subvolumes if they exist -# -# REROOTFS: Don't reuse the root filesystem, even if we normally would -# -# ROTATIONAL: forces to install onto hdds instead of sdds. normally sdds -# are chosen if they exist. -# -# PARTITION_PROMPT: command line prompt before partitioning. This is good -# to set if we don't expect repartitioning to happen. -# -# ROTATIONAL: in a system with ssd and hdd, install to the hdd -# instead of the default ssd. -# -# RAID0: forces raid0 filesystem. Normally with 4+ devices, we use -# raid10. -# RAID1: forces raid1 filesystem. -# RAID1c3: forces raid1c3 filesystem (btrfs raid 1, 3 copies). +/a/bin/fai/fai/config/hooks/partition.DEFAULT + +Example use in a bootstrap distro: +scp /b/fai/fai-wrapper /a/bin/fai/fai/config/{distro-install-common/devbyid,hooks/partition.DEFAULT} root@HOST: +sl root@HOST +. fai-wrapper # ignore error that FAI is not set, it is not needed for SPECIAL_DISK purposes. +fai-setclass FSF +./partition.DEFAULT -s /dev/sde +cat /tmp/fai/crypttab >>/etc/crypttab +cat /tmp/fai/fstab >>/etc/fstab +# possibly edit fstab and do some mkfs.btrfs + +# cryptsetup wont take within a pipeline +mapfile -t lines < <(awk '! /swap/ {print $2,$1}' /tmp/fai/crypttab ) +for l in "${lines[@]}"; do cryptsetup luksOpen $l; done + +# or alternatively, to avoid typing it many times: +read -r lukspw; for l in "${lines[@]}"; do yes "$lukspw" | cryptsetup luksOpen $l; done + +potentially useful later: +sed 's#/root/keyscript,#decrypt_keyctl,#;s/$/,noauto/' /tmp/fai/crypttab >/etc/crypttab + +Options + +-c DISK_COUNT Meant for use with -s, the count of disks for doing swap size calculation. + +-d Create data partition instead of root partition. Meant for use with -s. + +-m Create root/data partition with maximum size instead of the 1tb limit. Meant for use with -s. + +-s SPECIAL_DISK For use outside of fai. A base disk name like +/dev/sdk. If set, we just cryptsetup and partition this one disk then +exit. It creates a single lvm pv/vg/lv called "data". If this is +partitioning intended to go into a root filesystem, you can modify the +script to change that, or run commands manually afterwards. This also +sets REPARTITION. + +ARGS (only 0 or 1 is valid). All args are for use outside of fai. + +mkroot2: for setting up the root2/boot2 luks and btrfs and tab files + +mkroot2tab: for setting up the root2/boot2 tab files, in case luks and btrfs +happen to already be setup. + +mktab: for generating a crypttab for the main root fs in +/tmp/fai. Requires DISTRO be set, see below. + + +environment variables: + +HOSTNAME: if demohost, we set the luks password to just +'x'. Used in various other ways too. + +DISTRO: if not set, derived from VOL_... variable in a switch. +Required except for mkroot2, mkroot2tab, or SPECIAL_DISK. + +classes: + +FSF: Use fsf partitioning logic rather than for iank systems. + +REPARTITION: forces repartitioning even if we detect the proper amount +of partitions already exist. + +NOWIPE: use existing subvolumes if they exist + +REROOTFS: Don't reuse the root filesystem, even if we normally would + +ROTATIONAL: forces to install onto hdds instead of sdds. normally sdds +are chosen if they exist. + +PARTITION_PROMPT: command line prompt before partitioning. This is good +to set if we don't expect repartitioning to happen. + +ROTATIONAL: in a system with ssd and hdd, install to the hdd +instead of the default ssd. + +RAID0: forces raid0 filesystem. Normally with 4+ devices, we use +raid10. +RAID1: forces raid1 filesystem. +RAID1c3: forces raid1c3 filesystem (btrfs raid 1, 3 copies). +EOF + exit $1 +} + + +## duplicates fai-wrapper, for convenience of not needing it +if ! type -t ifclass &>/dev/null; then + ifclass() { + local var=${1/#/CLASS_} + [[ $HOSTNAME == "$1" || ${!var} ]] + } +fi + + +##### begin command line parsing ######## + +data_part=false +max_size=false +temp=$(getopt -l help hc:dms: "$@") || usage 1 +eval set -- "$temp" +while true; do + case $1 in + -c) + devs_count=$2 + # note: i haven't had a need to run with -s on a system that + # should have a different devs_count and boot_devs_count, so + # setting them the same for simplicity. + boot_devs_count=$2 + shift + ;; + -d) data_part=true ;; + -m) max_size=true ;; + -s) special_disk="$2"; shift ;; + -h|--help) usage ;; + --) shift; break ;; + *) echo "$0: Internal error! unexpected args: $*" ; exit 1 ;; + esac + shift +done mkroot2tab=false mkroot2=false mktab=false + if (( $# >= 1 )); then - ## duplicates fai-wrapper, for convenience of not needing it - if ! type -t ifclass &>/dev/null; then - ifclass() { - local var=${1/#/CLASS_} - [[ $HOSTNAME == "$1" || ${!var} ]] - } - fi case $1 in mkroot2) @@ -137,13 +180,11 @@ if (( $# >= 1 )); then esac fi -if [[ ! $SPECIAL_DISK ]] && ! $mkroot2 && ! $mkroot2tab && ! $mktab \ - && ! ifclass IANK && ! ifclass FSF; then - echo $0: error: need class IANK or FSF or SPECIAL_DISK for running in fai -fi +##### end command line parsing ######## + -if [[ $SPECIAL_DISK ]]; then +if [[ $special_disk ]]; then export CLASS_REPARTITION=true fi @@ -287,9 +328,10 @@ luks-setup() { } mktab() { + fstabstd="x-systemd.device-timeout=30s,x-systemd.mount-timeout=30s" + mkdir -p /tmp/fai dev=${boot_devs[0]} - fstabstd="x-systemd.device-timeout=30s,x-systemd.mount-timeout=30s" if [[ $DISTRO == *_bootstrap ]]; then cat > /tmp/fai/fstab < /tmp/fai/fstab </tmp/fai/crypttab </tmp/fai/fstab < /tmp/fai/fstab <> /tmp/fai/fstab <> /tmp/fai/fstab <>/tmp/fai/crypttab <>/tmp/fai/crypttab <> /tmp/fai/fstab <> /tmp/fai/fstab <> /tmp/fai/fstab <> /tmp/fai/fstab </tmp/fai/disk_var.sh </tmp/fai/disk_var.sh <>/tmp/fai/crypttab <> /tmp/fai/fstab <>$target_etc/crypttab <>/tmp/fai/crypttab <> /tmp/fai/fstab <>$target_etc/crypttab <> $target_etc/fstab <> $target_etc/fstab < 0 )); then + read -ra short_devs<<<"${ssds[@]}" + else + read -ra short_devs<<<"${hdds[@]}" + fi -# Example of short_devs: (/dev/sda /dev/sdb /dev/sdc) -# Install all ssds, or if there are none, all hdds. -# Note, usb flash disks are seen as rotational, which is -# very odd, but convenient for ignoring them here. -if ! ifclass ROTATIONAL && (( ${#ssds[@]} > 0 )); then - read -ra short_devs<<<"${ssds[@]}" -else - read -ra short_devs<<<"${hdds[@]}" fi pvn=1 @@ -647,11 +712,7 @@ done if $partition && ifclass PARTITION_PROMPT; then echo "Press any key except ctrl-c to continue and partition these drives:" - if [[ $SPECIAL_DISK ]]; then - echo $SPECIAL_DISK - else - echo " ${short_devs[*]}" - fi + echo " ${short_devs[*]}" read -r fi @@ -686,7 +747,7 @@ for short_dev in ${short_devs[@]}; do fi done first_root_dev=${root_devs[0]} -if [[ ! $SPECIAL_DISK && ! ${devs[0]} ]]; then +if [[ ! $special_disk && ! ${devs[0]} ]]; then echo "$0: error: failed to detect devs" >&2 exit 1 fi @@ -748,24 +809,30 @@ for dev in ${devs[@]}; do done first_boot_dev=${boot_devs[0]} +if [[ ! $devs_count ]]; then + boot_devs_count=${#boot_devs[@]} + devs_count=${#devs[@]} +fi + even_raid=false -if (( ${#boot_devs[@]} == 1 )); then +if (( boot_devs_count == 1 )); then raid_level=0 raid_duplication=1 elif ifclass RAID0; then raid_level=0 - if (( ${#boot_devs[@]} >= 3 )); then + raid_duplication=1 + if (( boot_devs_count >= 3 )); then # Default is raid1 metadata for >=2 devices, but metadata is <.5% # data use, so lets increase that redundancy. raid_metadata_arg="-m raid1c3" fi -elif ifclass RAID1 || (( ${#boot_devs[@]} == 2 )); then - if (( ${#boot_devs[@]} == 2 )); then +elif ifclass RAID1 || (( boot_devs_count == 2 )); then + if (( boot_devs_count == 2 )); then even_raid=true fi raid_level=1 raid_duplication=2 -elif ifclass RAID1c3 || (( ${#boot_devs[@]} == 3 )); then +elif ifclass RAID1c3 || (( boot_devs_count == 3 )); then raid_level=1c3 raid_duplication=3 else @@ -804,16 +871,16 @@ else boot2_mib=100 fi -if [[ $SPECIAL_DISK ]]; then +if [[ $special_disk ]]; then # In this case, the number of detected boot_devs may not be what we # actually end up using if and when we use this disk's boot partition. boot_part_mib=$boot_mib else - boot_part_mib=$(( boot_mib * raid_duplication / ${#boot_devs[@]} )) + boot_part_mib=$(( boot_mib * raid_duplication / boot_devs_count )) fi if zilap; then - boot2_part_mib=$(( boot2_mib * raid_duplication / ${#boot_devs[@]} )) + boot2_part_mib=$(( boot2_mib * raid_duplication / boot_devs_count )) root2_part_mib=$(( root2_mib * raid_duplication / ${#root_devs[@]} )) else boot2_part_mib=0 @@ -857,7 +924,7 @@ if [[ ! $DISTRO ]]; then DISTRO=trisquelaramo elif ifclass VOL_ECNE; then DISTRO=trisquelecne - elif $mkroot2 || $mkroot2tab || [[ $SPECIAL_DISK ]]; then + elif $mkroot2 || $mkroot2tab || [[ $special_disk ]]; then : else echo "PARTITIONER ERROR: no distro class/var set" >&2 @@ -874,16 +941,24 @@ else fi -# -# for servers, a bit randomly picking 6gb per disk based on https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html/managing_storage_devices/getting-started-with-swap_managing-storage-devices#recommended-system-swap-space_getting-started-with-swap -# meh, i'll just do that * drives for machines with lots of ram. mem_kb=$(awk '$1 == "MemTotal:" {print $2}' /proc/meminfo) +mem_mib=$(( mem_kb / 1000 )) mem_gb=$(( mem_kb / 1024 / 1024 )) -if (( mem_gb < 64 )); then - # enable hibernate with 1.5x of ram, split per disk - swap_mib=$(( mem_gb * 3 / ${#devs[@]} )) + + +# somewhat random based on https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html/managing_storage_devices/getting-started-with-swap_managing-storage-devices#recommended-system-swap-space_getting-started-with-swap +if fsf; then + if (( mem_gb >= 64 )); then + swap_mib=6144 + else + swap_mib=$(( mem_mib * raid_duplication / devs_count )) + fi else - swap_mib=6144 + if [[ -e /sys/class/power_supply/BAT0/capacity ]]; then + swap_mib=$(( mem_mib * 15 * raid_duplication / ( devs_count * 10 ) )) + else + swap_mib=$(( mem_mib * raid_duplication / devs_count )) + fi fi shopt -s nullglob @@ -908,10 +983,10 @@ fi if $partition; then ### begin wipefs - if [[ $SPECIAL_DISK ]]; then - lvmwipe $SPECIAL_DISK + if [[ $special_disk ]]; then + lvmwipe $special_disk maybe-prompt sleep 10 - maybe-prompt wipefs --backup -a $SPECIAL_DISK* + maybe-prompt wipefs --backup -a $special_disk* echo "$0: execute the following?" for cmd in "${cmd_prompt[@]}"; do echo "$cmd" @@ -952,10 +1027,6 @@ if $partition; then fi fi - if [[ $SPECIAL_DISK ]]; then - tmps=$(devbyid $SPECIAL_DISK) - devs=("$tmps") - fi for dev in ${devs[@]}; do vg=vg${dev##*/} vg=${vg//:/} @@ -1004,16 +1075,24 @@ if $partition; then # so use fixed sizes to allow both to grow # 600 = uefi 512 + grubext 8 + bios grub 3 + some extra cuz this is lvm #root_mib=$(( disk_mib - root2_part_mib - swap_mib - boot_part_mib - boot2_part_mib - 600 )) - o_mib=$(( 180 * 1000 )) + + # If we have extra devices, give /o some overhead so that we can + # remove & then add a device if needed. + o_factor=$devs_count + if (( o_factor >= 2 )); then + o_factor=$(( o_factor - 1 )) + fi + # note: math operations are left to right, so divide at the end. + o_mib=$(( 180 * 1000 * raid_duplication / o_factor )) # max minus o, minus a gig just for some extra space max_root_mib=$(( disk_mib - root2_part_mib - swap_mib - boot_part_mib - boot2_part_mib - 600 - o_mib - 1000 )) root_mib=$(( 1700 * 1000 )) # * 1000 to make it in gb. - if (( max_root_mib < root_mib )); then + if $max_size || (( max_root_mib < root_mib )); then root_mib=$max_root_mib fi fi - if [[ $SPECIAL_DISK ]] && ! fsf; then + if [[ $special_disk ]] && $data_part; then lvcreate -y -L $root_mib $vg -n data else # -L unit default mebibyte @@ -1095,7 +1174,7 @@ if $partition; then # into ipxe which can't persist data, if we ever got that working. mkfs.ext2 $dev$grub_extsuf - if [[ $SPECIAL_DISK ]]; then + if [[ $special_disk ]] && $data_part; then if ! fsf; then luks-setup /dev/$vg/data crypt-$vg-data fi @@ -1109,6 +1188,10 @@ if $partition; then luks-setup /dev/$vg/o crypt-$vg-o fi + if [[ $special_disk ]]; then + exit 0 + fi + done ls -la /dev/btrfs-control # this was probably for debugging... sleep 1 @@ -1206,5 +1289,5 @@ umount /mnt # initial setup of extra data fs, mounted, # btrfs subvol create nocow # chattr +C nocow -# chown iank.iank nocow - +# mkdir nocow/{t,user} +# chown iank.iank nocow/{t,user}