#!/usr/bin/env bash which sudo &>/dev/null && SUDO="sudo" || SUDO="" debrelease="buster" debmirror="http://debian.mirror.rafal.ca/debian" debpkglist="lvm2,parted,gdisk,grub-pg,linux-image-amd64,sudo,vim,gpg,gpg-agent,aptitude,openssh-server" clear titlestring_text="| Preparing to install a PVC node base system. |" titlestring_len="$( wc -c <<<"${titlestring_text}" )" for i in $( seq 2 ${titlestring_len} ); do echo -n "-"; done; echo echo "${titlestring_text}" for i in $( seq 2 ${titlestring_len} ); do echo -n "-"; done; echo echo echo "1) Please enter a fully-qualified hostname for the system." while [[ -z ${target_hostname} ]]; do echo echo -n "> " read target_hostname if [[ -z ${target_hostname} ]]; then echo echo "Please enter a hostname." continue fi echo done disks="$( for disk in /dev/sd?; do gdisk_data="$( $SUDO gdisk -l ${disk} )" echo -n "${disk}" echo -n "\t$( grep "^Model:" <<<"${gdisk_data}" | awk '{ $1=""; print $0 }' )" echo -n "\t$( grep "^Disk ${disk}:" <<<"${gdisk_data}" | awk '{ $1=$2=""; print $0 }' )" echo done )" echo "2) Please enter the disk to install the PVC base system to. This disk will be" echo "wiped, an LVM PV created on it, and the system installed to this LVM." echo echo "Available disks:" echo echo -e "$( sed 's/\(.*\)/ \1/' <<<"${disks[@]}" )" while [[ ! -b ${target_disk} ]]; do echo echo -n "> " read target_disk if [[ ! -b ${target_disk} ]]; then echo echo "Please enter a valid target disk." continue fi echo done for interface in $( ip address | grep '^[0-9]' | grep 'enp\|ens\|wlp' | awk '{ print $2 }' | tr -d ':' ); do $SUDO ip link set ${interface} up done sleep 2 interfaces="$( ip address | grep '^[0-9]' | grep 'enp\|ens\|wlp' | awk '{ print $2"\t"$3 }' | tr -d ':' )" echo "3a) Please enter the primary network interface for external connectivity." echo echo "Available interfaces:" echo echo -e "$( sed 's/\(.*\)/ \1/' <<<"${interfaces[@]}" )" while [[ -z ${target_interface} ]]; do echo echo -n "> " read target_interface if ! grep -qw "${target_interface}" <<<"${interfaces[@]}"; then echo echo "Please enter a valid interface." target_interface="" continue fi echo done echo "3b) Please enter the IP address, in CIDR format [X.X.X.X/YY], of the primary network interface." echo "Leave blank for DHCP configuration of the interface on boot." echo echo -n "> " read target_ipaddr if [[ -n ${target_ipaddr} ]]; then target_netformat="static" echo echo "3c) Please enter the default gateway IP address of the primary" echo "network interface." while [[ -z ${target_defgw} ]]; do echo echo -n "> " read target_defgw if [[ -z ${target_defgw} ]]; then echo echo "Please enter a default gateway; the installer requires Internet access." continue fi echo done else target_netformat="dhcp" echo fi echo "4) Please enter an HTTP URL containing a text list of SSH authorized keys to" echo "fetch. These keys will be allowed access to the 'deploy' user via SSH." echo "Leave blank to bypass this and use a password instead." echo echo -n "> " read target_keys_url if [[ -z ${target_keys_url} ]]; then echo echo "No SSH keys URL specified. Falling back to password configuration." echo echo "5) Please enter a password (hidden), twice, for the 'deploy' user." while [[ -z "${target_password}" ]]; do echo echo -n "> " read -s target_password_1 echo echo -n "> " read -s target_password_2 echo if [[ -n "${target_password_1}" && "${target_password_1}" -eq "${target_password_2}" ]]; then target_password="${target_password_1}" else echo echo "The specified passwords do not match or are empty." fi done fi echo titlestring_text="| Proceeding with installation of host '${target_hostname}' to disk '${target_disk}'. |" titlestring_len="$( wc -c <<<"${titlestring_text}" )" for i in $( seq 2 ${titlestring_len} ); do echo -n "-"; done; echo echo "${titlestring_text}" for i in $( seq 2 ${titlestring_len} ); do echo -n "-"; done; echo echo ### Script begins ### set -o errexit echo -n "Bringing up primary network interface in ${target_netformat} mode... " case mode in ${target_netformat} 'static') $SUDO ip link set ${target_interface} up &>/dev/null $SUDO ip address add ${target_ipaddr} dev ${target_interface} &>/dev/null $SUDO ip route add default via ${target_defgw} &>/dev/null formatted_ipaddr="$( sipcalc ${target_ipaddr} | grep -v '(' | awk '/Host address/{ print $NF }' )" formatted_netmask="$( sipcalc ${target_ipaddr} | grep -v '(' | awk '/Network mask/{ print $NF }' )" target_interfaces_block="auto ${target_interface}\niface ${target_interface} inet ${target_netformat}\n\taddress ${formatted_ipaddr}\n\tnetmask ${formatted_netmask}\n\tgateway ${target_defgw}" ;; 'dhcp') $SUDO dhclient ${target_interface} &>/dev/null target_interfaces_block="auto ${target_interface}\niface ${target_interface} inet ${target_netformat}" ;; esac echo "done." echo -n "Preparing block device... " # New GPT, part 1 64MB ESP, part 2 960MB BOOT, part 3 inf LVM PV echo -e "o\ny\nn\n1\n\n64M\nEF00\nn\n2\n\n960M\n8300\nn\n3\n\n\n8E00\nw\ny\n" | $SUDO gdisk ${target_disk} echo "done." echo -n "Rescanning disks... " $SUDO partprobe &>/dev/null echo "done." echo -n "Creating LVM PV... " $SUDO pvcreate ${target_disk}3 &>/dev/null echo "done." echo -n "Creating LVM VG named 'vgx'... " $SUDO vgcreate vgx ${target_disk}3 &>/dev/null echo "done." echo -n "Creating root logical volume (16GB, ext4)... " $SUDO lvcreate -L 16G -n root vgx &>/dev/null $SUDO mkfs.ext4 -f /dev/vgx/root &>/dev/null echo "done." echo -n "Creating ceph logical volume (16GB, ext4)... " $SUDO lvcreate -L 16G -n ceph vgx &>/dev/null $SUDO mkfs.ext4 -f /dev/vgx/ceph &>/dev/null echo "done." echo -n "Creating swap logical volume (8GB)... " $SUDO lvcreate -L 8G -n swap vgx &>/dev/null $SUDO mkswap -f /dev/vgx/swap &>/dev/null echo "done." echo -n "Mounting disks on temporary target... " target=$( mktemp -d ) $SUDO mount /dev/vgx/root ${target} &>/dev/null $SUDO mkdir -p ${target}/boot &>/dev/null $SUDO mount ${target_disk}2 ${target}/boot &>/dev/null $SUDO mkdir -p ${target}/boot/efi &>/dev/null $SUDO mount ${target_disk}1 ${target}/boot/efi &>/dev/null $SUDO mkdir -p ${target}/var/lib/ceph &>/dev/null $SUDO mount /dev/vgx/ceph ${target}/var/lib/ceph &>/dev/null echo "done." echo -n "Running debootstrap install... " $SUDO debootstrap --include=${debpkglist} ${debrelease} ${target}/ ${debmirror} &>/dev/null echo "done." # Determine the bypath name of the specified system disk for disk in /dev/disk/by-path/*; do bypathlink="$( readlink ${disk} | awk -F'/' '{ print $NF }' )" enteredname="$( awk -F'/' '{ print $NF }' <<<"${target_disk}" )" if [[ ${bypathlink} == ${enteredname} ]]; then bypath_disk="${disk}" fi done echo -n "Adding fstab entries... " echo "/dev/mapper/vgx-root / ext4 errors=remount-ro 0 1" | $SUDO tee -a ${target}/etc/fstab &>/dev/null echo "/dev/mapper/vgx-ceph /var/lib/ceph ext4 errors=remount-ro 0 2" | $SUDO tee -a ${target}/etc/fstab &>/dev/null echo "/dev/mapper/vgx-swap nonde swap sw 0 0" | $SUDO tee -a ${target}/etc/fstab &>/dev/null echo "${bypath_disk}2 /boot ext2 defaults 0 2" | $SUDO tee -a ${target}/etc/fstab &>/dev/null echo "${bypath_disk}1 /boot/efi vfat umask=0077 0 2" | $SUDO tee -a ${target}/etc/fstab &>/dev/null echo "done." echo -n "Adding interface segment... " echo -e "${target_interfaces_block}" | $SUDO tee -a ${target}/etc/network/interfaces &>/dev/null echo "done." echo -n "Adding 'deploy' user... " $SUDO mv ${target}/home ${target}/var/home &>/dev/null $SUDO chroot ${target} useradd -u 200 -d /var/home/deploy -m -s /bin/bash -g operator -G sudo deploy &>/dev/null $SUDO chroot ${target} mkdir -p /var/home/deploy/.ssh if [[ -n ${target_keys_url} ]]; then $SUDO wget -O ${target}/var/home/deploy/.ssh/authorized_keys ${target_keys_url} else echo "${target_password}" | $SUDO chroot ${target} passwd --stdin deploy &>/dev/null fi echo -n "Setting hostname... " echo "${target_hostname}" | sudo tee ${target}/etc/hostname &>/dev/null echo "done." echo -n "Installing GRUB bootloader... " $SUDO mount --bind /dev ${target}/dev &>/dev/null $SUDO mount --bind /dev/pts ${target}/dev/pts &>/dev/null $SUDO mount --bind /proc ${target}/proc &>/dev/null $SUDO mount --bind /sys ${target}/sys &>/dev/null $SUDO chroot ${target} grub-install --target=x86_64-efi ${target_disk} &>/dev/null $SUDO chroot ${target} update-grub &>/dev/null echo "done." echo -n "Cleaning up... " $SUDO umount ${target}/sys &>/dev/null $SUDO umount ${target}/proc &>/dev/null $SUDO umount ${target}/dev/pts &>/dev/null $SUDO umount ${target}/dev &>/dev/null $SUDO umount ${target}/var/lib/ceph &>/dev/null $SUDO umount ${target}/boot/efi &>/dev/null $SUDO umount ${target}/boot &>/dev/null $SUDO umount ${target} &>/dev/null echo "done." echo titlestring_text="| PVC node installation finished. Press to reboot into the installed system. |" titlestring_len="$( wc -c <<<"${titlestring_text}" )" for i in $( seq 2 ${titlestring_len} ); do echo -n "-"; done; echo echo "${titlestring_text}" echo "Verify the system is configured as you would expect, add any additional interfaces" echo "to the /etc/network/interfaces file, and then run the PVC Ansible role in" echo "'bootstrap=yes' mode to continue deploying the PVC system." for i in $( seq 2 ${titlestring_len} ); do echo -n "-"; done; echo echo read $SUDO reboot