Public repo to distribute scripts and config's
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

294 lignes
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 "$@"