X-Git-Url: https://iankelling.org/git/?a=blobdiff_plain;f=fresize;fp=fresize;h=90f19982145fb15fd246f5f783108c6f54b7ac0b;hb=b16e4048672679b16223e55d768bee0d7d877ced;hp=0000000000000000000000000000000000000000;hpb=e8f685f09f4190d1afabf25d6d7ac2f7e5dec841;p=automated-distro-installer diff --git a/fresize b/fresize new file mode 100755 index 0000000..90f1998 --- /dev/null +++ b/fresize @@ -0,0 +1,240 @@ +#!/bin/bash + +shopt -s extdebug +bash-trace() { + # shows function args when: shopt -s extdebug + local -i argc_index=0 arg frame i start=${1:-1} max_indent=8 indent + local source + local extdebug=false + if [[ $(shopt -p extdebug) == *-s* ]]; then + extdebug=true + fi + + for ((frame=0; frame < ${#FUNCNAME[@]}-1; frame++)); do + argc=${BASH_ARGC[frame]} + argc_index+=$argc + ((frame < start)) && continue + if (( ${#BASH_SOURCE[@]} > 1 )); then + source="${BASH_SOURCE[frame+1]}:${BASH_LINENO[frame]}:" + fi + indent=$((frame-start+1)) + indent=$((indent < max_indent ? indent : max_indent)) + printf "%${indent}s↳%sin \`%s" '' "$source" "${FUNCNAME[frame]}" + if $extdebug; then + for ((i=argc_index-1; i >= argc_index-argc; i--)); do + printf " %s" "${BASH_ARGV[i]}" + done + fi + echo \' + done +} + + +errcatch() { + set -E; shopt -s extdebug + _err-trap() { + err=$? + exec >&2 + echo "${BASH_SOURCE[1]}:${BASH_LINENO[0]}:in \`$BASH_COMMAND' returned $err" + bash-trace 2 + echo "$0: exiting with code $err" + exit $err + } + trap _err-trap ERR + set -o pipefail +} + +errcatch + +[[ $EUID == 0 ]] || sudo "$BASH_SOURCE" "$@" + +usage() { + cat </dev/null; then + echo "$0: error: install parted" + exit 1 +fi + +case $2 in swap|boot) : ;; *) echo "$0: error: bad 2nd arg"; usage 1 ;; esac + +#### end arg error checking #### + + +boot=true +[[ $2 == boot ]] || boot=false + +#size=${x#[+-]} +op_size=$1 # operator plus size +[[ $op_size != *g ]] || op_size=$(( ${op_size%g} / 1024 )) +size=${op_size#[+-]} + +if [[ $op_size == +* ]]; then + op_size_rev=-$size # rev = reverse + grow=true +else + op_size_rev=+$size + grow=false +fi + +##### end command line parsing ######## + +rootn=1 +swapn=2 +bootn=3 +needs_reboot=false + +pmk() { + part=$1 + start_op=$2 + end_op=$3 + read start end < <(echo ${ptable[$part]}) + p mkpart primary "$4" $((start $start_op)) $((end $end_op)) +} + + +swapoff -a + +while read devid dev; do + if $dry_run; then + e() { echo "+ $@"; } + else + e() { echo "+ $@"; "$@"; } + fi + ptable=() + while IFS=: read id start end _; do + [[ $id == [0-9] ]] || continue + end=${end%MiB} + start=${start%MiB} + start=${start%.*} # small enough number that parted uses a decimal + ptable[$id]="$start $end" + done < <(parted -m /dev/$dev unit MiB print) + parted /dev/$dev unit MiB print | tee /root/backup_partition + p() { e parted -a optimal -s -- /dev/$dev unit MiB "$@"; } + e systemctl stop systemd-cryptsetup@crypt_swap_$dev$swapn + sleep 1 + # These partition comments seems a little verbose now, but I bet they + # will be helpfull if I read this in more than a week from now. + # <> = deleted partition, () = partition + p rm $swapn # ( root )< swap >( boot ) + + root_resize_cmd="e btrfs fi resize $devid:$op_size_rev /" + if $grow; then $root_resize_cmd; fi + # if $grow; then + # < root >< swap >( boot ) + # ( root ) >< swap >( boot ) + # else + # < root >< swap >( boot ) + # ( root >< ) swap >( boot ) + + out=$(p rm $rootn 2>&1) + echo "$out" + + pmk $rootn "" $op_size_rev + if ! $grow; then + if echo "$out" | \ + grep "but we have been unable to inform the kernel" &>/dev/null; then + e systemctl mask dev-mapper-crypt_swap_$dev$swapn.swap + e systemctl mask systemd-cryptsetup@crypt_swap_$dev$swapn.service + if ! $needs_reboot; then + needs_reboot=true + echo "$0: reboot and run /root/finish-resize to finish. +The following commands are what will be executed:" + rm -rf /root/finish-resize + cat >/root/finish-resize <<'EOF' +#!/bin/bash -x +set -eE -o pipefail +trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?"' ERR +EOF + chmod +x /root/finish-resize + fi + e() { echo "$@" | tee -a /root/finish-resize; } + e systemctl unmask systemd-cryptsetup@crypt_swap_$dev$swapn.service + e systemctl unmask dev-mapper-crypt_swap_$dev$swapn.swap + # todo, disable swap for the next boot. currently have to wait + # 1:30 for it to fail. + fi + $root_resize_cmd + fi + if $boot; then + boot_devid=$(btrfs fi show /boot | \ + sed -rn "s#^\s*devid\s+(\S+)\s.*$dev[0-9]#\1#p") + + if ! $grow; then + # shrink boot, move it to a temp file + e btrfs fi resize $boot_devid:$op_size /boot + temp_boot=/root/temp_boot_dd + e dd bs=1M if=/dev/$dev$bootn of=$temp_boot count=$size + fi + # if $grow; then + # ( root ) >< swap >< boot > + # ( root )( >< swap ) >< boot > + # ( root )( >< swap )( >< boot ) + # else + # ( root >< ) swap >< boot > + # ( root >< )( swap >< ) boot > + # ( root >< )( swap >< )( boot ) + e umount /boot + p rm $bootn + pmk $swapn $op_size_rev $op_size_rev "linux-swap" + pmk $bootn $op_size_rev "" + + if $grow; then + e dd bs=1M if=/dev/$dev$bootn of=/dev/$dev$bootn skip=$size + e btrfs fi resize $boot_devid:$op_size /boot + else + e dd bs=1M if=$temp_boot of=/dev/$dev$bootn + fi + e mount /boot + else + # if $grow; then ( root )( >< swap )( boot ) + # else ( root >< )( swap )( boot ) + pmk $swapn $op_size_rev "" "linux-swap" + fi +done < <(btrfs fi show / | \ + sed -nr 's#^\s*devid\s*(\S+)\s.*_([^_ ]+)[0-9]\s*$#\1 \2#p') + +if $boot; then + e rm -rf $temp_boot + e rm /root/finish-resize +fi + +if $needs_reboot; then + echo "$0: reminder, reboot then /root/finish-resize" +fi + +#for dev in ${devs[@]}; do