281 lines
9.7 KiB
Bash
281 lines
9.7 KiB
Bash
|
#!/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 <Enter> 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
|