Преглед на файлове

Added BIOS-capable installer

master
Jan De Landtsheer преди 1 седмица
родител
ревизия
b593f1a54e
променени са 1 файла, в които са добавени 294 реда и са изтрити 0 реда
  1. +294
    -0
      zosinstallBIOSipxeondisk.sh

+ 294
- 0
zosinstallBIOSipxeondisk.sh Целия файл

@@ -0,0 +1,294 @@
#!/bin/bash

# Enable strict error handling
set -e

# Function to log messages with timestamps
log() {
echo "$(date '+%F %T') - $@"
}

# Function to display usage information
usage() {
echo "Usage: $0 [-d DEVICE] [-f FARM] [-e ENVIRONMENT]"
echo " -d, --device DEVICE Specify the block device to use (e.g., sda, sdb)."
echo " -f, --farm FARM Specify the FARM ID."
echo " -e, --environment ENV Specify the environment (dev, qa, test, prod)."
echo " -h, --help Display this help message."
exit 1
}

# Function to find suitable block devices
find_blockdev() {
# Minimum size in bytes, e.g., 10 GiB
MIN_SIZE=$((10 * 1024 * 1024 * 1024))

BLOCKDEVICES=()

# Exclude the boot disk
BOOT_DISK=$(findmnt -n -o SOURCE / | sed 's/[0-9]*$//;s|^/dev/||')
log "Boot disk detected: /dev/${BOOT_DISK}"

# Search for NVMe devices first
log "Searching for NVMe devices..."
for DEV in /dev/nvme*n1; do
DEV_BASE=$(basename "$DEV")
if [ -b "$DEV" ] && [ "$DEV_BASE" != "$BOOT_DISK" ]; then
SIZE_BYTES=$(blockdev --getsize64 "$DEV")
if [ "$SIZE_BYTES" -ge "$MIN_SIZE" ]; then
log "Found NVMe device: $DEV ($(numfmt --to=iec $SIZE_BYTES))"
BLOCKDEVICES+=("$DEV_BASE")
else
log "$DEV is smaller than $(numfmt --to=iec $MIN_SIZE). Skipping."
fi
else
[ "$DEV_BASE" == "$BOOT_DISK" ] && log "Skipping boot disk: $DEV"
fi
done

# Search for SSD devices
log "Searching for SSD devices..."
for DEV_PATH in /sys/block/*; do
DEV_NAME=$(basename "$DEV_PATH")
# Exclude unwanted devices and the boot disk
case "$DEV_NAME" in
loop* | ram* | sr* | fd* | md* | dm-*)
continue
;;
"$BOOT_DISK")
log "Skipping boot disk: /dev/$DEV_NAME"
continue
;;
esac
DEVICE="/dev/$DEV_NAME"
if [ -b "$DEVICE" ] && [ -e "/sys/block/$DEV_NAME/queue/rotational" ] && [ "$(cat /sys/block/$DEV_NAME/queue/rotational)" == "0" ]; then
SIZE_BYTES=$(blockdev --getsize64 "$DEVICE")
if [ "$SIZE_BYTES" -ge "$MIN_SIZE" ]; then
log "Found SSD device: $DEVICE ($(numfmt --to=iec $SIZE_BYTES))"
BLOCKDEVICES+=("$DEV_NAME")
else
log "$DEVICE is smaller than $(numfmt --to=iec $MIN_SIZE). Skipping."
fi
fi
done

if [ ${#BLOCKDEVICES[@]} -eq 0 ]; then
log "No suitable block devices found."
return 1
fi

log "List of block devices to be wiped:"
for DEV in "${BLOCKDEVICES[@]}"; do
log "/dev/$DEV"
done

# Select the first device as the block device to partition
BLOCKDEV="${BLOCKDEVICES[0]}"
}

# Main script execution
main() {
# Default values
BLOCKDEV_SPECIFIED=""
FARM="1234"
ENVIRONMENT="prod"

# Parse command-line arguments
while [[ $# -gt 0 ]]; do
case "$1" in
-d | --device)
shift
if [ -z "$1" ]; then
log "Error: '--device' requires a non-empty option argument."
usage
fi
BLOCKDEV_SPECIFIED="$1"
shift
;;
-f | --farm)
shift
if [ -z "$1" ]; then
log "Error: '--farm' requires a non-empty option argument."
usage
fi
FARM="$1"
shift
;;
-e | --environment)
shift
if [ -z "$1" ]; then
log "Error: '--environment' requires a non-empty option argument."
usage
fi
ENVIRONMENT="$1"
shift
;;
-h | --help)
usage
;;
*)
log "Error: Unknown option: $1"
usage
;;
esac
done

# Validate environment
case "$ENVIRONMENT" in
dev | qa | test | prod)
log "Using environment: $ENVIRONMENT"
;;
*)
log "Error: Invalid environment '$ENVIRONMENT'. Valid options are 'dev', 'qa', 'test', 'prod'."
exit 1
;;
esac

if [ -n "$BLOCKDEV_SPECIFIED" ]; then
# Use the specified block device
if [[ "$BLOCKDEV_SPECIFIED" != /dev/* ]]; then
BLOCKDEV_SPECIFIED="/dev/$BLOCKDEV_SPECIFIED"
fi
if [ ! -b "$BLOCKDEV_SPECIFIED" ]; then
log "Error: Specified device $BLOCKDEV_SPECIFIED does not exist or is not a block device."
exit 1
fi
BLOCKDEV="${BLOCKDEV_SPECIFIED##*/}"
BLOCKDEVICES=("$BLOCKDEV")
log "Using specified block device: $BLOCKDEV_SPECIFIED"
else
# Find suitable block devices
if ! find_blockdev; then
log "Error: No suitable block devices found."
exit 1
fi
fi

# Confirm with the user before proceeding
log "The following disks will be wiped:"
for DEV in "${BLOCKDEVICES[@]}"; do
log "/dev/$DEV"
done
read -p "This will erase all data on the above disks. Are you sure you want to proceed? Type 'WIPE ALL' to confirm: " CONFIRM
if [ "$CONFIRM" != "WIPE ALL" ]; then
log "Operation cancelled by user."
exit 0
fi

# Wipe filesystem signatures on all disks
log "Wiping filesystem signatures on all selected disks..."
for DEV in "${BLOCKDEVICES[@]}"; do
log "Wiping /dev/$DEV..."
wipefs -a -f /dev/$DEV || {
log "Failed to wipe /dev/$DEV"
exit 1
}
done

# Proceed with partitioning and formatting the first disk
# Determine partition naming convention
if [[ $BLOCKDEV =~ [0-9]$ ]]; then
PARTPREFIX="${BLOCKDEV}p"
else
PARTPREFIX="${BLOCKDEV}"
fi

# Create GPT partition table on the selected block device
log "Creating GPT partition table on /dev/${BLOCKDEV}..."
parted -s /dev/${BLOCKDEV} mklabel gpt || {
log "Failed to create GPT partition table."
exit 1
}

# Create BIOS Boot Partition
log "Creating BIOS Boot partition on /dev/${BLOCKDEV}..."
parted -s /dev/${BLOCKDEV} mkpart primary 1MiB 2MiB || {
log "Failed to create BIOS Boot partition."
exit 1
}
parted -s /dev/${BLOCKDEV} set 1 bios_grub on

# Create additional partitions as needed
log "Creating data partitions on /dev/${BLOCKDEV}..."
parted -s /dev/${BLOCKDEV} mkpart primary 2MiB 100MiB || {
log "Failed to create partition."
exit 1
}
parted -s /dev/${BLOCKDEV} mkpart primary 100MiB 100% || {
log "Failed to create partition."
exit 1
}

# Format partitions
log "Formatting /dev/${PARTPREFIX}2 as FAT16..."
if ! mkfs.vfat -F16 /dev/${PARTPREFIX}2; then
log "Failed to format /dev/${PARTPREFIX}2 as FAT16."
exit 1
fi

log "Formatting /dev/${PARTPREFIX}3 as BTRFS..."
if ! mkfs.btrfs -f /dev/${PARTPREFIX}3; then
log "Failed to format /dev/${PARTPREFIX}3 as BTRFS."
exit 1
fi

# Install iPXE bootloader to MBR
log "Installing iPXE bootloader to MBR of /dev/${BLOCKDEV}..."

# Download the iPXE bootloader suitable for BIOS
log "Downloading iPXE bootloader..."
if ! wget -q -O ipxe.lkrn http://boot.ipxe.org/ipxe.lkrn; then
log "Failed to download iPXE bootloader."
exit 1
fi

# Write iPXE bootloader to the MBR
log "Writing iPXE bootloader to MBR of /dev/${BLOCKDEV}..."
dd if=ipxe.lkrn of=/dev/${BLOCKDEV} bs=440 count=1 conv=notrunc || {
log "Failed to write iPXE to MBR."
exit 1
}

# Clean up the downloaded file
rm -f ipxe.lkrn

# Prepare the iPXE script
log "Preparing iPXE script..."

# Mount the FAT16 partition to store the iPXE script
MOUNT_POINT="zospxe"
log "Creating and mounting directory ./${MOUNT_POINT}..."
mkdir -p "${MOUNT_POINT}"
if ! mount /dev/${PARTPREFIX}2 -t vfat "${MOUNT_POINT}"; then
log "Failed to mount /dev/${PARTPREFIX}2 to ${MOUNT_POINT}."
exit 1
fi

# Download the BOOTX64.EFI file (optional, depending on your setup)
# Since this is a BIOS system, we might not need this step
# However, if required, adjust the script accordingly

# Alternatively, create an embedded iPXE script
log "Creating iPXE script..."
cat >"${MOUNT_POINT}/boot.ipxe" <<EOF
#!ipxe
dhcp
set farm ${FARM}
chain https://bootstrap.grid.tf/uefi/${ENVIRONMENT}/\${FARM}/debug/zero-os-development-zos-v4-debug-7d2de62033.efi?version=v4"
# chain https://bootstrap.grid.tf/ipxe/${ENVIRONMENT}/\${farm}
EOF

log "iPXE script created at ${MOUNT_POINT}/boot.ipxe"

# Unmount the partition
log "Unmounting ${MOUNT_POINT}..."
umount "${MOUNT_POINT}" || {
log "Failed to unmount ${MOUNT_POINT}."
exit 1
}

log "Operation completed successfully."
}

# Execute the main function
main "$@"

Зареждане…
Отказ
Запис