Public repo to distribute scripts and config's
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

294 line
7.6 KiB

  1. #!/bin/bash
  2. # Enable strict error handling
  3. set -e
  4. # Function to log messages with timestamps
  5. log() {
  6. echo "$(date '+%F %T') - $@"
  7. }
  8. # Function to display usage information
  9. usage() {
  10. echo "Usage: $0 [-d DEVICE] [-f FARM] [-e ENVIRONMENT]"
  11. echo " -d, --device DEVICE Specify the block device to use (e.g., sda, sdb)."
  12. echo " -f, --farm FARM Specify the FARM ID."
  13. echo " -e, --environment ENV Specify the environment (dev, qa, test, prod)."
  14. echo " -h, --help Display this help message."
  15. exit 1
  16. }
  17. # Function to find suitable block devices
  18. find_blockdev() {
  19. # Minimum size in bytes, e.g., 10 GiB
  20. MIN_SIZE=$((10 * 1024 * 1024 * 1024))
  21. BLOCKDEVICES=()
  22. # Exclude the boot disk
  23. BOOT_DISK=$(findmnt -n -o SOURCE / | sed 's/[0-9]*$//;s|^/dev/||')
  24. log "Boot disk detected: /dev/${BOOT_DISK}"
  25. # Search for NVMe devices first
  26. log "Searching for NVMe devices..."
  27. for DEV in /dev/nvme*n1; do
  28. DEV_BASE=$(basename "$DEV")
  29. if [ -b "$DEV" ] && [ "$DEV_BASE" != "$BOOT_DISK" ]; then
  30. SIZE_BYTES=$(blockdev --getsize64 "$DEV")
  31. if [ "$SIZE_BYTES" -ge "$MIN_SIZE" ]; then
  32. log "Found NVMe device: $DEV ($(numfmt --to=iec $SIZE_BYTES))"
  33. BLOCKDEVICES+=("$DEV_BASE")
  34. else
  35. log "$DEV is smaller than $(numfmt --to=iec $MIN_SIZE). Skipping."
  36. fi
  37. else
  38. [ "$DEV_BASE" == "$BOOT_DISK" ] && log "Skipping boot disk: $DEV"
  39. fi
  40. done
  41. # Search for SSD devices
  42. log "Searching for SSD devices..."
  43. for DEV_PATH in /sys/block/*; do
  44. DEV_NAME=$(basename "$DEV_PATH")
  45. # Exclude unwanted devices and the boot disk
  46. case "$DEV_NAME" in
  47. loop* | ram* | sr* | fd* | md* | dm-*)
  48. continue
  49. ;;
  50. "$BOOT_DISK")
  51. log "Skipping boot disk: /dev/$DEV_NAME"
  52. continue
  53. ;;
  54. esac
  55. DEVICE="/dev/$DEV_NAME"
  56. if [ -b "$DEVICE" ] && [ -e "/sys/block/$DEV_NAME/queue/rotational" ] && [ "$(cat /sys/block/$DEV_NAME/queue/rotational)" == "0" ]; then
  57. SIZE_BYTES=$(blockdev --getsize64 "$DEVICE")
  58. if [ "$SIZE_BYTES" -ge "$MIN_SIZE" ]; then
  59. log "Found SSD device: $DEVICE ($(numfmt --to=iec $SIZE_BYTES))"
  60. BLOCKDEVICES+=("$DEV_NAME")
  61. else
  62. log "$DEVICE is smaller than $(numfmt --to=iec $MIN_SIZE). Skipping."
  63. fi
  64. fi
  65. done
  66. if [ ${#BLOCKDEVICES[@]} -eq 0 ]; then
  67. log "No suitable block devices found."
  68. return 1
  69. fi
  70. log "List of block devices to be wiped:"
  71. for DEV in "${BLOCKDEVICES[@]}"; do
  72. log "/dev/$DEV"
  73. done
  74. # Select the first device as the block device to partition
  75. BLOCKDEV="${BLOCKDEVICES[0]}"
  76. }
  77. # Main script execution
  78. main() {
  79. # Default values
  80. BLOCKDEV_SPECIFIED=""
  81. FARM="1234"
  82. ENVIRONMENT="prod"
  83. # Parse command-line arguments
  84. while [[ $# -gt 0 ]]; do
  85. case "$1" in
  86. -d | --device)
  87. shift
  88. if [ -z "$1" ]; then
  89. log "Error: '--device' requires a non-empty option argument."
  90. usage
  91. fi
  92. BLOCKDEV_SPECIFIED="$1"
  93. shift
  94. ;;
  95. -f | --farm)
  96. shift
  97. if [ -z "$1" ]; then
  98. log "Error: '--farm' requires a non-empty option argument."
  99. usage
  100. fi
  101. FARM="$1"
  102. shift
  103. ;;
  104. -e | --environment)
  105. shift
  106. if [ -z "$1" ]; then
  107. log "Error: '--environment' requires a non-empty option argument."
  108. usage
  109. fi
  110. ENVIRONMENT="$1"
  111. shift
  112. ;;
  113. -h | --help)
  114. usage
  115. ;;
  116. *)
  117. log "Error: Unknown option: $1"
  118. usage
  119. ;;
  120. esac
  121. done
  122. # Validate environment
  123. case "$ENVIRONMENT" in
  124. dev | qa | test | prod)
  125. log "Using environment: $ENVIRONMENT"
  126. ;;
  127. *)
  128. log "Error: Invalid environment '$ENVIRONMENT'. Valid options are 'dev', 'qa', 'test', 'prod'."
  129. exit 1
  130. ;;
  131. esac
  132. if [ -n "$BLOCKDEV_SPECIFIED" ]; then
  133. # Use the specified block device
  134. if [[ "$BLOCKDEV_SPECIFIED" != /dev/* ]]; then
  135. BLOCKDEV_SPECIFIED="/dev/$BLOCKDEV_SPECIFIED"
  136. fi
  137. if [ ! -b "$BLOCKDEV_SPECIFIED" ]; then
  138. log "Error: Specified device $BLOCKDEV_SPECIFIED does not exist or is not a block device."
  139. exit 1
  140. fi
  141. BLOCKDEV="${BLOCKDEV_SPECIFIED##*/}"
  142. BLOCKDEVICES=("$BLOCKDEV")
  143. log "Using specified block device: $BLOCKDEV_SPECIFIED"
  144. else
  145. # Find suitable block devices
  146. if ! find_blockdev; then
  147. log "Error: No suitable block devices found."
  148. exit 1
  149. fi
  150. fi
  151. # Confirm with the user before proceeding
  152. log "The following disks will be wiped:"
  153. for DEV in "${BLOCKDEVICES[@]}"; do
  154. log "/dev/$DEV"
  155. done
  156. read -p "This will erase all data on the above disks. Are you sure you want to proceed? Type 'WIPE ALL' to confirm: " CONFIRM
  157. if [ "$CONFIRM" != "WIPE ALL" ]; then
  158. log "Operation cancelled by user."
  159. exit 0
  160. fi
  161. # Wipe filesystem signatures on all disks
  162. log "Wiping filesystem signatures on all selected disks..."
  163. for DEV in "${BLOCKDEVICES[@]}"; do
  164. log "Wiping /dev/$DEV..."
  165. wipefs -a -f /dev/$DEV || {
  166. log "Failed to wipe /dev/$DEV"
  167. exit 1
  168. }
  169. done
  170. # Proceed with partitioning and formatting the first disk
  171. # Determine partition naming convention
  172. if [[ $BLOCKDEV =~ [0-9]$ ]]; then
  173. PARTPREFIX="${BLOCKDEV}p"
  174. else
  175. PARTPREFIX="${BLOCKDEV}"
  176. fi
  177. # Create GPT partition table on the selected block device
  178. log "Creating GPT partition table on /dev/${BLOCKDEV}..."
  179. parted -s /dev/${BLOCKDEV} mklabel gpt || {
  180. log "Failed to create GPT partition table."
  181. exit 1
  182. }
  183. # Create BIOS Boot Partition
  184. log "Creating BIOS Boot partition on /dev/${BLOCKDEV}..."
  185. parted -s /dev/${BLOCKDEV} mkpart primary 1MiB 2MiB || {
  186. log "Failed to create BIOS Boot partition."
  187. exit 1
  188. }
  189. parted -s /dev/${BLOCKDEV} set 1 bios_grub on
  190. # Create additional partitions as needed
  191. log "Creating data partitions on /dev/${BLOCKDEV}..."
  192. parted -s /dev/${BLOCKDEV} mkpart primary 2MiB 100MiB || {
  193. log "Failed to create partition."
  194. exit 1
  195. }
  196. parted -s /dev/${BLOCKDEV} mkpart primary 100MiB 100% || {
  197. log "Failed to create partition."
  198. exit 1
  199. }
  200. # Format partitions
  201. log "Formatting /dev/${PARTPREFIX}2 as FAT16..."
  202. if ! mkfs.vfat -F16 /dev/${PARTPREFIX}2; then
  203. log "Failed to format /dev/${PARTPREFIX}2 as FAT16."
  204. exit 1
  205. fi
  206. log "Formatting /dev/${PARTPREFIX}3 as BTRFS..."
  207. if ! mkfs.btrfs -f /dev/${PARTPREFIX}3; then
  208. log "Failed to format /dev/${PARTPREFIX}3 as BTRFS."
  209. exit 1
  210. fi
  211. # Install iPXE bootloader to MBR
  212. log "Installing iPXE bootloader to MBR of /dev/${BLOCKDEV}..."
  213. # Download the iPXE bootloader suitable for BIOS
  214. log "Downloading iPXE bootloader..."
  215. if ! wget -q -O ipxe.lkrn http://boot.ipxe.org/ipxe.lkrn; then
  216. log "Failed to download iPXE bootloader."
  217. exit 1
  218. fi
  219. # Write iPXE bootloader to the MBR
  220. log "Writing iPXE bootloader to MBR of /dev/${BLOCKDEV}..."
  221. dd if=ipxe.lkrn of=/dev/${BLOCKDEV} bs=440 count=1 conv=notrunc || {
  222. log "Failed to write iPXE to MBR."
  223. exit 1
  224. }
  225. # Clean up the downloaded file
  226. rm -f ipxe.lkrn
  227. # Prepare the iPXE script
  228. log "Preparing iPXE script..."
  229. # Mount the FAT16 partition to store the iPXE script
  230. MOUNT_POINT="zospxe"
  231. log "Creating and mounting directory ./${MOUNT_POINT}..."
  232. mkdir -p "${MOUNT_POINT}"
  233. if ! mount /dev/${PARTPREFIX}2 -t vfat "${MOUNT_POINT}"; then
  234. log "Failed to mount /dev/${PARTPREFIX}2 to ${MOUNT_POINT}."
  235. exit 1
  236. fi
  237. # Download the BOOTX64.EFI file (optional, depending on your setup)
  238. # Since this is a BIOS system, we might not need this step
  239. # However, if required, adjust the script accordingly
  240. # Alternatively, create an embedded iPXE script
  241. log "Creating iPXE script..."
  242. cat >"${MOUNT_POINT}/boot.ipxe" <<EOF
  243. #!ipxe
  244. dhcp
  245. set farm ${FARM}
  246. chain https://bootstrap.grid.tf/uefi/${ENVIRONMENT}/\${FARM}/debug/zero-os-development-zos-v4-debug-7d2de62033.efi?version=v4"
  247. # chain https://bootstrap.grid.tf/ipxe/${ENVIRONMENT}/\${farm}
  248. EOF
  249. log "iPXE script created at ${MOUNT_POINT}/boot.ipxe"
  250. # Unmount the partition
  251. log "Unmounting ${MOUNT_POINT}..."
  252. umount "${MOUNT_POINT}" || {
  253. log "Failed to unmount ${MOUNT_POINT}."
  254. exit 1
  255. }
  256. log "Operation completed successfully."
  257. }
  258. # Execute the main function
  259. main "$@"