add wipefs support for SPECIAL_DISK
authorIan Kelling <iank@fsf.org>
Wed, 11 Sep 2024 17:49:10 +0000 (13:49 -0400)
committerIan Kelling <iank@fsf.org>
Wed, 11 Sep 2024 19:24:51 +0000 (15:24 -0400)
fai/config/hooks/partition.DEFAULT

index a61653725b32de94eb1e7bd116b7437095ffb94f..b47b5ba747c8a7704feef549d57b940e85d2d2d0 100755 (executable)
@@ -73,7 +73,7 @@ fi
 # 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. This is useful for partitioning a disk in preparation to replace
-# a failed or failing disk from a raid10 array.
+# a failed or failing disk from a raid10 array. This also sets REPARTITION.
 #
 # DISTRO: if not set, derived from VOL_... variable in a switch below.
 #
@@ -105,7 +105,7 @@ fi
 mkroot2tab=false
 mkroot2=false
 mktab=false
-if [[ $1 ]]; then
+if (( $# >= 1 )); then
   ## duplicates fai-wrapper, for convenience of not needing it
   if ! type -t ifclass &>/dev/null; then
     ifclass() {
@@ -341,27 +341,28 @@ ROOT_PARTITION=\${ROOT_PARTITION:-$first_root_dev}
 SWAPLIST=\${SWAPLIST:-"${swap_devs[@]}"}
 EOF
 
-    if [[ $HOSTNAME == frodo ]]; then
-      big_disks=(
-        ata-Hitachi_HDS722020ALA330_JK1121YAG7SXWS-part1
-        ata-Hitachi_HDS722020ALA330_JK1121YAG7SY4S-part1
-        ata-Hitachi_HDS723030ALA640_MK0311YHG2WUSA-part1
-        ata-ST4000DM000-1F2168_Z300AZ6K-part1
-        ata-ST6000DM001-1XY17Z_Z4D2WMZK-part1
-        ata-TOSHIBA_MD04ACA500_8539K4TQFS9A-part1
-        ata-TOSHIBA_MD04ACA500_85NAK4T2FS9A-part1
-        ata-TOSHIBA_MD04ACA500_9551K615FS9A-part1
-        ata-TOSHIBA_MD04ACA500_Y5IFK6IJFS9A-part1
-      )
-      for d in ${big_disks[@]}; do
-        cat >>/tmp/fai/crypttab <<EOF
-crypt_dev_$d  /dev/disk/by-id/$d  /mnt/root/q/root/luks/iank  discard,luks
-EOF
-      done
-      cat >> /tmp/fai/fstab <<EOF
-/dev/mapper/crypt_dev_${big_disks[0]}  /mnt/i  btrfs  nofail,$fstabstd,noatime,subvolid=0  0 0
-EOF
-    fi
+    # now example if i add big disks.
+    #     if [[ $HOSTNAME == frodo ]]; then
+    #       big_disks=(
+    #         ata-Hitachi_HDS722020ALA330_JK1121YAG7SXWS-part1
+    #         ata-Hitachi_HDS722020ALA330_JK1121YAG7SY4S-part1
+    #         ata-Hitachi_HDS723030ALA640_MK0311YHG2WUSA-part1
+    #         ata-ST4000DM000-1F2168_Z300AZ6K-part1
+    #         ata-ST6000DM001-1XY17Z_Z4D2WMZK-part1
+    #         ata-TOSHIBA_MD04ACA500_8539K4TQFS9A-part1
+    #         ata-TOSHIBA_MD04ACA500_85NAK4T2FS9A-part1
+    #         ata-TOSHIBA_MD04ACA500_9551K615FS9A-part1
+    #         ata-TOSHIBA_MD04ACA500_Y5IFK6IJFS9A-part1
+    #       )
+    #       for d in ${big_disks[@]}; do
+    #         cat >>/tmp/fai/crypttab <<EOF
+    # crypt_dev_$d  /dev/disk/by-id/$d  /mnt/root/q/root/luks/iank  discard,luks
+    # EOF
+    #       done
+    #       cat >> /tmp/fai/fstab <<EOF
+    # /dev/mapper/crypt_dev_${big_disks[0]}  /mnt/i  btrfs  nofail,$fstabstd,noatime,subvolid=0  0 0
+    # EOF
+    #     fi
     if [[ $HOSTNAME == kd ]]; then
       # note, having these with keyscript and initramfs causes a luks error in fai.log,
       # but it is safely ignorable and gets us the ability to just type our password
@@ -425,6 +426,89 @@ EOF
   exit 0
 }
 
+d() {
+  if $dry_run; then
+    printf "%s\n" "$*"
+  else
+    "$@"
+  fi
+}
+
+# usage: lvmwipe [-n] SHORT_DEV_NAME...
+# -n   dry run.
+# example: lvmwipe /dev/sda /dev/sdb
+lvmwipe() {
+  local dry_run pv_dev short_dev vg lvs lv pv vgs_of_pv
+  local -a wipe_short_devs pv_wipes vg_wipes pv_devs
+  local -A vg_map
+  dry_run=false
+  case $1 in
+    -n)
+      dry_run=true
+      shift
+      ;;
+  esac
+  would_wipe=false
+  wipe_short_devs=("$@")
+  for short_dev in "${wipe_short_devs[@]}"; do
+    if [[ $short_dev != /dev/* ]]; then
+      echo "$0: error: lvmwipe: got unexpected argument: $short_dev" >&2
+      exit 1
+    fi
+  done
+  pv_wipes=()
+  vg_wipes=()
+  pv_devs=$(pvs --noheadings -o pvname)
+  for pv_dev in $pv_devs; do
+    for short_dev in ${wipe_short_devs[@]}; do
+      if [[ $pv_dev == $short_dev* ]]; then
+        pv_wipes+=($pv_dev)
+        vgs_of_pv=$(pvs --noheadings -o vgname $pv_dev)
+        for vg in $vgs_of_pv; do
+          if [[ ${vg_map[$vg]} ]]; then
+            continue
+          fi
+          vg_map[$vg]=t
+          vg_wipes+=($vg)
+          lvs=$(vgs --noheadings -o lv_path $vg)
+          for lv in $lvs; do
+            d wipefs -a $lv
+          done
+        done
+      fi
+    done
+  done
+
+  for vg in ${vg_wipes[@]}; do
+    d vgchange -an $vg
+    d vgremove -ff $vg
+  done
+
+  for pv in ${pv_wipes[@]}; do
+    would_wipe=true
+    d pvremove -ff $pv
+  done
+}
+
+devwipe() {
+  local count_down dev
+  local -a wipe_devs
+  wipe_devs=("$@")
+  for dev in ${wipe_devs[@]}; do
+    # if we repartition to the same as an old partition,
+    # we don't want any old fses hanging around.
+    count_down=10
+    # wipefs has failed, manual run works, google suggests timing issue
+    while ! wipefs -a $dev; do
+      sleep 2
+      count_down=$((count_down - 1))
+      if (( count_down <= 0 )); then
+        echo "$0: wipefs failed 10 times. exiting" >&2
+        exit 1
+      fi
+    done
+  done
+}
 
 ##### end function defs
 
@@ -467,7 +551,12 @@ fi
 
 hdds=()
 ssds=()
-# this excludes "usb". vda disk has empty tran (transport). This may need adjustment
+# Example output:
+# sda
+# sdb
+# sdc
+#
+# This excludes "usb". vda disk has empty tran (transport). This may need adjustment
 # for some new type we come across. cdrom has type "rom"
 for disk in $(lsblk -ndo name,type,tran | awk '$3 ~ "^(sata|nvme|sas|)$" && $2 == "disk" { print $1 }'); do
   if [[ ${disk_excludes[$disk]} ]]; then
@@ -491,7 +580,8 @@ $(cat $disk/queue/rotational)"; exit 1 ;;
   esac
 done
 
-# install all ssds, or if there are none, all hdds.
+# 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
@@ -790,56 +880,18 @@ fi
 
 if $partition; then
   ### begin wipefs
-  if [[ ! $SPECIAL_DISK ]]; then
-
+  if [[ $SPECIAL_DISK ]]; then
+    lvmwipe -n $SPECIAL_DISK
+    if $would_wipe; then
+      echo "wipefs -a $SPECIAL_DISK"
+      echo "$0: exiting. review and execute above wipefs commands manually"
+      exit 0
+    fi
+    devwipe $SPECIAL_DISK
+  else
     # we do lvm removals just for the disks we are using
-    pv_wipes=()
-    vg_wipes=()
-    declare -A vg_map
-    pv_devs=$(pvs --noheadings -o pvname)
-    for pv_dev in $pv_devs; do
-      for short_dev in ${short_devs[@]}; do
-        if [[ $pv_dev == $short_dev* ]]; then
-          pv_wipes+=($pv_dev)
-          vgs_of_pv=$(pvs --noheadings -o vgname $pv_dev)
-          for vg in $vgs_of_pv; do
-            if [[ ${vg_map[$vg]} ]]; then
-              continue
-            fi
-            vg_map[$vg]=t
-            vg_wipes+=($vg)
-            lvs=$(vgs --noheadings -o lv_path $vg)
-            for lv in $lvs; do
-              wipefs -a $lv
-            done
-          done
-        fi
-      done
-    done
-
-    for vg in ${vg_wipes[@]}; do
-      vgchange -an $vg
-      vgremove -ff $vg
-    done
-
-    for pv in ${pv_wipes[@]}; do
-      pvremove -ff $pv
-    done
-
-    for dev in ${devs[@]}; do
-      # if we repartition to the same as an old partition,
-      # we don't want any old fses hanging around.
-      count_down=10
-      # wipefs has failed, manual run works, google suggests timing issue
-      while ! wipefs -a $dev; do
-        sleep 2
-        count_down=$((count_down - 1))
-        if (( count_down <= 0 )); then
-          echo "$0: wipefs failed 10 times. exiting" >&2
-          exit 1
-        fi
-      done
-    done
+    lvmwipe "${short_devs[@]}"
+    devwipe "${devs[@]}"
   fi
   ### end wipefs
 
@@ -864,7 +916,8 @@ if $partition; then
   fi
 
   if [[ $SPECIAL_DISK ]]; then
-    devs=($(devbyid $SPECIAL_DISK))
+    tmps=$(devbyid $SPECIAL_DISK)
+    devs=("$tmps")
   fi
   for dev in ${devs[@]}; do
     vg=vg${dev##*/}