Complete implementation of seed install
Some fixed decisions were made, namely that bond0 would be created by the installer from "all other interfaces" to facilitate easy provisioning.
This commit is contained in:
parent
8de0b4541a
commit
d8e08ac5ef
|
@ -63,7 +63,7 @@ while [ $# -gt 0 ]; do
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
PACKAGE_LIST_MAIN="live-tools linux-image-amd64 mdadm lvm2 parted gdisk dosfstools debootstrap grub-pc-bin grub-efi-amd64 sipcalc vim ca-certificates vlan tftp-hpa"
|
PACKAGE_LIST_MAIN="live-tools live-boot live-boot-initramfs-tools linux-image-amd64 mdadm lvm2 parted gdisk dosfstools debootstrap grub-pc-bin grub-efi-amd64 sipcalc vim ca-certificates vlan tftp-hpa curl ipmitool"
|
||||||
PACKAGE_LIST_NONFREE="firmware-bnx2 firmware-bnx2x"
|
PACKAGE_LIST_NONFREE="firmware-bnx2 firmware-bnx2x"
|
||||||
|
|
||||||
mkdir -p artifacts/lb
|
mkdir -p artifacts/lb
|
||||||
|
|
15
buildpxe.sh
15
buildpxe.sh
|
@ -114,7 +114,6 @@ build_pxe() {
|
||||||
|
|
||||||
# Set global variables
|
# Set global variables
|
||||||
set root-url tftp://\${next-server}
|
set root-url tftp://\${next-server}
|
||||||
set host-url tftp://\${next-server}/host
|
|
||||||
|
|
||||||
set menu-default pvc-installer
|
set menu-default pvc-installer
|
||||||
set submenu-default pvc-installer
|
set submenu-default pvc-installer
|
||||||
|
@ -122,12 +121,24 @@ set submenu-default pvc-installer
|
||||||
:pvc-installer
|
:pvc-installer
|
||||||
kernel \${root-url}/vmlinuz
|
kernel \${root-url}/vmlinuz
|
||||||
initrd \${root-url}/initrd.img
|
initrd \${root-url}/initrd.img
|
||||||
imgargs vmlinuz console=tty0 console=ttyS0,115200n8 boot=live components timezone=America/Toronto fetch=\${root-url}/filesystem.squashfs username=root pvcinstall.preseed=on pvcinstall.seed_host=\${next-server} pvcinstall.seed_file=/host/mac-\${mac:hexraw}.preseed
|
imgargs vmlinuz console=tty0 console=ttyS0,115200n8 vga=normal nomodeset boot=live components ethdevice-timeout=60 timezone=America/Toronto fetch=\${root-url}/filesystem.squashfs username=root pvcinstall.preseed=on pvcinstall.seed_host=\${next-server} pvcinstall.seed_file=/host/mac-\${mac:hexraw}.preseed
|
||||||
|
|
||||||
boot
|
boot
|
||||||
EOF
|
EOF
|
||||||
echo "done."
|
echo "done."
|
||||||
|
|
||||||
|
echo -n "Downloading iPXE binary undionly.kpxe (chainloads arbitrary PXE clients)... "
|
||||||
|
pushd ${outputdir} &>/dev/null
|
||||||
|
wget -O undionly.kpxe https://boot.ipxe.org/undionly.kpxe &>/dev/null || fail "failed to download undionly.kpxe."
|
||||||
|
popd &>/dev/null
|
||||||
|
echo "done."
|
||||||
|
|
||||||
|
echo -n "Downloading iPXE binary undionly.kpxe (chainloads UEFI clients)... "
|
||||||
|
pushd ${outputdir} &>/dev/null
|
||||||
|
wget -O ipxe.efi https://boot.ipxe.org/ipxe.efi &>/dev/null || fail "failed to download ipxe.efi."
|
||||||
|
popd &>/dev/null
|
||||||
|
echo "done."
|
||||||
|
|
||||||
sudo chown -R $(whoami) ${outputdir}
|
sudo chown -R $(whoami) ${outputdir}
|
||||||
sudo chmod -R u+w ${outputdir}
|
sudo chmod -R u+w ${outputdir}
|
||||||
|
|
||||||
|
|
350
install.sh
350
install.sh
|
@ -1,12 +1,26 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
logfile="/tmp/pvc-install.log"
|
||||||
|
lockfile="/run/pvc-install.lock"
|
||||||
|
|
||||||
if [[ $( whoami ) != "root" ]]; then
|
if [[ $( whoami ) != "root" ]]; then
|
||||||
echo "STOP! This script is designed to run as root within the installer only!"
|
echo "STOP! This script is designed to run as root within the installer only!"
|
||||||
echo "Do not run it on your system. To build a PVC installer ISO, use './buildiso.sh' instead!"
|
echo "Do not run it on your system. To build a PVC installer ISO, use './buildiso.sh' instead!"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
logfile="/tmp/pvc-install.log"
|
# Random delay to prevent overlaps
|
||||||
|
DELAY=$(( ${RANDOM} % 10 ))
|
||||||
|
echo -n "Waiting ${DELAY} seconds... "
|
||||||
|
sleep ${DELAY}
|
||||||
|
echo "done."
|
||||||
|
|
||||||
|
if [[ -f ${lockfile} ]]; then
|
||||||
|
echo "An instance of 'install.sh' is already running!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
touch ${lockfile}
|
||||||
|
|
||||||
iso_name="XXDATEXX"
|
iso_name="XXDATEXX"
|
||||||
target_deploy_user="XXDEPLOYUSERXX"
|
target_deploy_user="XXDEPLOYUSERXX"
|
||||||
|
|
||||||
|
@ -14,7 +28,7 @@ supported_debrelease="buster bullseye"
|
||||||
default_debrelease="buster"
|
default_debrelease="buster"
|
||||||
default_debmirror="http://debian.mirror.rafal.ca/debian"
|
default_debmirror="http://debian.mirror.rafal.ca/debian"
|
||||||
|
|
||||||
inclpkglist="lvm2,parted,gdisk,grub-pc,grub-efi-amd64,linux-image-amd64,sudo,vim,gpg,gpg-agent,aptitude,openssh-server,vlan,ifenslave,python2,python3,ca-certificates"
|
inclpkglist="lvm2,parted,gdisk,grub-pc,grub-efi-amd64,linux-image-amd64,sudo,vim,gpg,gpg-agent,aptitude,openssh-server,vlan,ifenslave,python3,ca-certificates,curl"
|
||||||
suppkglist="firmware-linux,firmware-linux-nonfree,firmware-bnx2,firmware-bnx2x,ntp"
|
suppkglist="firmware-linux,firmware-linux-nonfree,firmware-bnx2,firmware-bnx2x,ntp"
|
||||||
|
|
||||||
# DANGER - THIS PASSWORD IS PUBLIC
|
# DANGER - THIS PASSWORD IS PUBLIC
|
||||||
|
@ -24,36 +38,57 @@ suppkglist="firmware-linux,firmware-linux-nonfree,firmware-bnx2,firmware-bnx2x,n
|
||||||
# roles will overwrite it by default during configuration.
|
# roles will overwrite it by default during configuration.
|
||||||
root_password="hCb1y2PF"
|
root_password="hCb1y2PF"
|
||||||
|
|
||||||
# Obtain the mode from the kernel command line
|
# Respawn function
|
||||||
kernel_cmdline=$( cat /proc/cmdline )
|
respawn() (
|
||||||
install_option="$( awk '{
|
$0 & disown
|
||||||
for(i=1; i<=NF; i++) {
|
)
|
||||||
if($i ~ /pvcinstall.preseed/) {
|
|
||||||
print $i;
|
# Checkin function
|
||||||
}
|
seed_checkin() (
|
||||||
}
|
case ${1} in
|
||||||
}' <<<"${kernel_cmdline}" | awk -F'=' '{ print $NF }' )"
|
start)
|
||||||
|
action="install-start"
|
||||||
|
;;
|
||||||
|
end)
|
||||||
|
action="install-complete"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
macaddr=$( ip -br link show ${target_interface} | awk '{ print $3 }' )
|
||||||
|
ipaddr=$( ip -br address show ${target_interface} | awk '{ print $3 }' | awk -F '/' '{ print $1 }' )
|
||||||
|
curl -X POST \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "{\"action\":\"${action}\",\"macaddr\":\"${macaddr}\",\"ipaddr\":\"${ipaddr}\",\"hostname\":\"${target_hostname}\",\"bmc_macaddr\":\"${bmc_macaddr}\",\"bmc_ipaddr\":\"${bmc_ipaddr}\"}" \
|
||||||
|
${pvcbootstrapd_checkin_uri}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Obtain the preseed options from the kernel command line
|
||||||
|
install_option=""
|
||||||
|
seed_host=""
|
||||||
|
seed_file=""
|
||||||
|
kernel_cmdline=( $( cat /proc/cmdline ) )
|
||||||
|
for option in ${kernel_cmdline[@]}; do
|
||||||
|
case ${option} in
|
||||||
|
pvcinstall.preseed=*)
|
||||||
|
install_option=${option#pvcinstall.preseed=}
|
||||||
|
;;
|
||||||
|
pvcinstall.seed_host=*)
|
||||||
|
seed_host=${option#pvcinstall.seed_host=}
|
||||||
|
;;
|
||||||
|
pvcinstall.seed_file=*)
|
||||||
|
seed_file=${option#pvcinstall.seed_file=}
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
seed_config() {
|
seed_config() {
|
||||||
seed_host="$( awk '{
|
# Get IPMI BMC MAC for checkings
|
||||||
for(i=1; i<=NF; i++) {
|
bmc_macaddr="$( ipmitool lan print | grep 'MAC Address ' | awk '{ print $NF }' )"
|
||||||
if($i ~ /pvcinstall.seed_host=/) {
|
bmc_ipaddr="$( ipmitool lan print | grep 'IP Address ' | awk '{ print $NF }' )"
|
||||||
print $i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}' <<<"${kernel_cmdline}" | awk -F'=' '{ print $NF }' )"
|
|
||||||
seed_file="$( awk '{
|
|
||||||
for(i=1; i<=NF; i++) {
|
|
||||||
if($i ~ /pvcinstall.seed_file=/) {
|
|
||||||
print $i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}' <<<"${kernel_cmdline}" | awk -F'=' '{ print $NF }' )"
|
|
||||||
|
|
||||||
# Perform DHCP on all interfaces to come online
|
# Perform DHCP on all interfaces to come online
|
||||||
for interface in $( ip address | grep '^[0-9]' | grep 'eno\|enp\|ens\|wlp' | awk '{ print $2 }' | tr -d ':' ); do
|
for interface in $( ip address | grep '^[0-9]' | grep 'eno\|enp\|ens\|wlp' | awk '{ print $2 }' | tr -d ':' ); do
|
||||||
ip link set ${interface} up
|
ip link set ${interface} up
|
||||||
dhclient ${interface}
|
pgrep dhclient || dhclient ${interface}
|
||||||
done
|
done
|
||||||
|
|
||||||
# Fetch the seed config
|
# Fetch the seed config
|
||||||
|
@ -61,13 +96,13 @@ seed_config() {
|
||||||
|
|
||||||
. /tmp/install.seed || exit 1
|
. /tmp/install.seed || exit 1
|
||||||
|
|
||||||
|
# Handle the target interface
|
||||||
|
target_route="$( ip route show to match ${seed_host} | grep 'scope link' )"
|
||||||
|
target_interface="$( grep -E -o 'e[a-z]+[0-9]+[a-z0-9]*' <<<"${target_route}" )"
|
||||||
|
|
||||||
# Handle the target disk
|
# Handle the target disk
|
||||||
if [[ -n ${target_disk_path} ]]; then
|
if [[ -n ${target_disk_path} ]]; then
|
||||||
target_disk="$( realpath ${target_disk_path} )"
|
target_disk="$( realpath ${target_disk_path} )"
|
||||||
if [[ ! -b ${target_disk} ]]; then
|
|
||||||
echo "Invalid disk!"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
else
|
else
|
||||||
# Find the (first) disk with the given model
|
# Find the (first) disk with the given model
|
||||||
for disk in /dev/sd?; do
|
for disk in /dev/sd?; do
|
||||||
|
@ -78,11 +113,15 @@ seed_config() {
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
if [[ ! -b ${target_disk} ]]; then
|
||||||
|
echo "Invalid disk or disk not found!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
interactive_config() {
|
interactive_config() {
|
||||||
clear
|
clear
|
||||||
|
|
||||||
echo "--------------------------------------------------------"
|
echo "--------------------------------------------------------"
|
||||||
echo "| PVC Node installer (${iso_name}) |"
|
echo "| PVC Node installer (${iso_name}) |"
|
||||||
echo "--------------------------------------------------------"
|
echo "--------------------------------------------------------"
|
||||||
|
@ -93,7 +132,7 @@ interactive_config() {
|
||||||
echo " the questions below, you may do so by typing ^C to cancel the script,"
|
echo " the questions below, you may do so by typing ^C to cancel the script,"
|
||||||
echo " then re-running it by calling /install.sh in the resulting shell."
|
echo " then re-running it by calling /install.sh in the resulting shell."
|
||||||
echo
|
echo
|
||||||
|
|
||||||
echo "1) Please enter a fully-qualified hostname for the system. This should match the hostname"
|
echo "1) Please enter a fully-qualified hostname for the system. This should match the hostname"
|
||||||
echo "in the 'pvc-ansible' inventory."
|
echo "in the 'pvc-ansible' inventory."
|
||||||
while [[ -z ${target_hostname} ]]; do
|
while [[ -z ${target_hostname} ]]; do
|
||||||
|
@ -107,7 +146,7 @@ interactive_config() {
|
||||||
fi
|
fi
|
||||||
echo
|
echo
|
||||||
done
|
done
|
||||||
|
|
||||||
disks="$(
|
disks="$(
|
||||||
for disk in /dev/sd? /dev/nvme?n?; do
|
for disk in /dev/sd? /dev/nvme?n?; do
|
||||||
if [[ ! -b ${disk} ]]; then
|
if [[ ! -b ${disk} ]]; then
|
||||||
|
@ -120,7 +159,7 @@ interactive_config() {
|
||||||
echo
|
echo
|
||||||
done
|
done
|
||||||
)"
|
)"
|
||||||
|
|
||||||
echo "2) Please enter the disk to install the PVC base system to. This disk will be"
|
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 "wiped, an LVM PV created on it, and the system installed to this LVM."
|
||||||
echo "* NOTE: PVC requires a disk of at least 30GB to be installed to, and 100GB is the"
|
echo "* NOTE: PVC requires a disk of at least 30GB to be installed to, and 100GB is the"
|
||||||
|
@ -151,7 +190,7 @@ interactive_config() {
|
||||||
fi
|
fi
|
||||||
echo
|
echo
|
||||||
done
|
done
|
||||||
|
|
||||||
for interface in $( ip address | grep '^[0-9]' | grep 'eno\|enp\|ens\|wlp' | awk '{ print $2 }' | tr -d ':' ); do
|
for interface in $( ip address | grep '^[0-9]' | grep 'eno\|enp\|ens\|wlp' | awk '{ print $2 }' | tr -d ':' ); do
|
||||||
ip link set ${interface} up
|
ip link set ${interface} up
|
||||||
done
|
done
|
||||||
|
@ -183,7 +222,7 @@ interactive_config() {
|
||||||
fi
|
fi
|
||||||
echo
|
echo
|
||||||
done
|
done
|
||||||
|
|
||||||
echo -n "3b) Is a tagged vLAN required for the primary network interface? [y/N] "
|
echo -n "3b) Is a tagged vLAN required for the primary network interface? [y/N] "
|
||||||
read vlans_req
|
read vlans_req
|
||||||
if [[ ${vlans_req} == 'y' || ${vlans_req} == 'Y' ]]; then
|
if [[ ${vlans_req} == 'y' || ${vlans_req} == 'Y' ]]; then
|
||||||
|
@ -204,7 +243,7 @@ interactive_config() {
|
||||||
vlan_id=""
|
vlan_id=""
|
||||||
echo
|
echo
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "3c) Please enter the IP address, in CIDR format [X.X.X.X/YY], of the primary"
|
echo "3c) Please enter the IP address, in CIDR format [X.X.X.X/YY], of the primary"
|
||||||
echo "network interface. Leave blank for DHCP configuration of the interface on boot."
|
echo "network interface. Leave blank for DHCP configuration of the interface on boot."
|
||||||
echo
|
echo
|
||||||
|
@ -230,7 +269,7 @@ interactive_config() {
|
||||||
target_netformat="dhcp"
|
target_netformat="dhcp"
|
||||||
echo
|
echo
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo -n "Bringing up primary network interface in ${target_netformat} mode... "
|
echo -n "Bringing up primary network interface in ${target_netformat} mode... "
|
||||||
case ${target_netformat} in
|
case ${target_netformat} in
|
||||||
'static')
|
'static')
|
||||||
|
@ -244,16 +283,16 @@ interactive_config() {
|
||||||
ip route add default via ${target_defgw} >&2 || true
|
ip route add default via ${target_defgw} >&2 || true
|
||||||
formatted_ipaddr="$( sipcalc ${target_ipaddr} | grep -v '(' | awk '/Host address/{ print $NF }' )"
|
formatted_ipaddr="$( sipcalc ${target_ipaddr} | grep -v '(' | awk '/Host address/{ print $NF }' )"
|
||||||
formatted_netmask="$( sipcalc ${target_ipaddr} | grep -v '(' | awk '/Network mask/{ print $NF }' )"
|
formatted_netmask="$( sipcalc ${target_ipaddr} | grep -v '(' | awk '/Network mask/{ print $NF }' )"
|
||||||
target_interfaces_block="auto ${vlan_interface}\niface ${vlan_interface} inet ${target_netformat}\n\tvlan_raw_device ${target_interface}\n\taddress ${formatted_ipaddr}\n\tnetmask ${formatted_netmask}\n\tgateway ${target_defgw}"
|
|
||||||
real_interface="${vlan_interface}"
|
real_interface="${vlan_interface}"
|
||||||
|
target_interfaces_is="static-vlan"
|
||||||
else
|
else
|
||||||
ip link set ${target_interface} up >&2 || true
|
ip link set ${target_interface} up >&2 || true
|
||||||
ip address add ${target_ipaddr} dev ${target_interface} >&2 || true
|
ip address add ${target_ipaddr} dev ${target_interface} >&2 || true
|
||||||
ip route add default via ${target_defgw} >&2 || true
|
ip route add default via ${target_defgw} >&2 || true
|
||||||
formatted_ipaddr="$( sipcalc ${target_ipaddr} | grep -v '(' | awk '/Host address/{ print $NF }' )"
|
formatted_ipaddr="$( sipcalc ${target_ipaddr} | grep -v '(' | awk '/Host address/{ print $NF }' )"
|
||||||
formatted_netmask="$( sipcalc ${target_ipaddr} | grep -v '(' | awk '/Network mask/{ 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}"
|
|
||||||
real_interface="${target_interface}"
|
real_interface="${target_interface}"
|
||||||
|
target_interfaces_is="static-raw"
|
||||||
fi
|
fi
|
||||||
cat <<EOF >/etc/resolv.conf
|
cat <<EOF >/etc/resolv.conf
|
||||||
nameserver 8.8.8.8
|
nameserver 8.8.8.8
|
||||||
|
@ -264,26 +303,26 @@ EOF
|
||||||
modprobe 8021q >&2
|
modprobe 8021q >&2
|
||||||
vconfig add ${target_interface} ${vlan_id} &>/dev/null
|
vconfig add ${target_interface} ${vlan_id} &>/dev/null
|
||||||
vlan_interface=${target_interface}.${vlan_id}
|
vlan_interface=${target_interface}.${vlan_id}
|
||||||
target_interfaces_block="auto ${vlan_interface}\niface ${vlan_interface} inet ${target_netformat}\n\tvlan_raw_device${target_interface}"
|
|
||||||
dhclient ${vlan_interface} >&2
|
dhclient ${vlan_interface} >&2
|
||||||
real_interface="${vlan_interface}"
|
real_interface="${vlan_interface}"
|
||||||
|
target_interfaces_is="dhcp-vlan"
|
||||||
else
|
else
|
||||||
target_interfaces_block="auto ${target_interface}\niface ${target_interface} inet ${target_netformat}"
|
|
||||||
dhclient ${target_interface} >&2
|
dhclient ${target_interface} >&2
|
||||||
real_interface="${target_interface}"
|
real_interface="${target_interface}"
|
||||||
|
target_interfaces_is="dhcp-raw"
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
echo "done."
|
echo "done."
|
||||||
echo
|
echo
|
||||||
|
|
||||||
echo -n "Waiting for networking to become ready... "
|
echo -n "Waiting for networking to become ready... "
|
||||||
while ! ping -q -c 1 8.8.8.8 &>/dev/null; do
|
while ! ping -q -c 1 8.8.8.8 &>/dev/null; do
|
||||||
sleep 1
|
sleep 1
|
||||||
done
|
done
|
||||||
echo "done."
|
echo "done."
|
||||||
echo
|
echo
|
||||||
|
|
||||||
echo "4a) Please enter an alternate Debian release codename for the system if desired."
|
echo "4a) Please enter an alternate Debian release codename for the system if desired."
|
||||||
echo " Supported: ${supported_debrelease}"
|
echo " Supported: ${supported_debrelease}"
|
||||||
echo " Default: ${default_debrelease}"
|
echo " Default: ${default_debrelease}"
|
||||||
|
@ -302,7 +341,7 @@ EOF
|
||||||
fi
|
fi
|
||||||
echo
|
echo
|
||||||
done
|
done
|
||||||
|
|
||||||
echo "4b) Please enter an HTTP URL for an alternate Debian mirror if desired."
|
echo "4b) Please enter an HTTP URL for an alternate Debian mirror if desired."
|
||||||
echo " Default: ${default_debmirror}"
|
echo " Default: ${default_debmirror}"
|
||||||
while [[ -z ${debmirror} ]]; do
|
while [[ -z ${debmirror} ]]; do
|
||||||
|
@ -322,7 +361,7 @@ EOF
|
||||||
echo "Repository mirror '${debmirror}' successfully validated."
|
echo "Repository mirror '${debmirror}' successfully validated."
|
||||||
echo
|
echo
|
||||||
done
|
done
|
||||||
|
|
||||||
target_keys_method="wget"
|
target_keys_method="wget"
|
||||||
echo "5) Please enter an HTTP URL containing a text list of SSH authorized keys to"
|
echo "5) Please enter an HTTP URL containing a text list of SSH authorized keys to"
|
||||||
echo "fetch. These keys will be allowed access to the deployment user 'XXDEPLOYUSER'"
|
echo "fetch. These keys will be allowed access to the deployment user 'XXDEPLOYUSER'"
|
||||||
|
@ -375,12 +414,6 @@ case ${install_option} in
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
if [[ -f /tmp/pvc-install.lock ]]; then
|
|
||||||
echo "An instance of 'install.sh' is already running!"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
touch /tmp/pvc-install.lock
|
|
||||||
|
|
||||||
titlestring_text="| Proceeding with installation of host '${target_hostname}'. |"
|
titlestring_text="| Proceeding with installation of host '${target_hostname}'. |"
|
||||||
titlestring_len="$(( $( wc -c <<<"${titlestring_text}" ) - 2 ))"
|
titlestring_len="$(( $( wc -c <<<"${titlestring_text}" ) - 2 ))"
|
||||||
for i in $( seq 0 ${titlestring_len} ); do echo -n "-"; done; echo
|
for i in $( seq 0 ${titlestring_len} ); do echo -n "-"; done; echo
|
||||||
|
@ -392,9 +425,20 @@ echo
|
||||||
echo "LOGFILE: ${logfile}"
|
echo "LOGFILE: ${logfile}"
|
||||||
echo
|
echo
|
||||||
|
|
||||||
set -o errexit
|
|
||||||
exec 1> >( tee -ia ${logfile} )
|
exec 1> >( tee -ia ${logfile} )
|
||||||
exec 2> >( tee -ia ${logfile} >/dev/null )
|
exec 2> >( tee -ia ${logfile} >/dev/null )
|
||||||
|
set -o errexit
|
||||||
|
set -o xtrace
|
||||||
|
|
||||||
|
case ${install_option} in
|
||||||
|
on)
|
||||||
|
seed_checkin start
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
# noop
|
||||||
|
true
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
cleanup() {
|
cleanup() {
|
||||||
set +o errexit
|
set +o errexit
|
||||||
|
@ -412,9 +456,19 @@ cleanup() {
|
||||||
umount ${target} >&2
|
umount ${target} >&2
|
||||||
vgchange -an >&2
|
vgchange -an >&2
|
||||||
rmdir ${target} >&2
|
rmdir ${target} >&2
|
||||||
rm /tmp/pvc-install.lock
|
rm ${lockfile}
|
||||||
echo "done."
|
echo "done."
|
||||||
echo
|
echo
|
||||||
|
|
||||||
|
case ${install_option} in
|
||||||
|
on)
|
||||||
|
respawn
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
# noop
|
||||||
|
true
|
||||||
|
;;
|
||||||
|
esac
|
||||||
}
|
}
|
||||||
trap cleanup EXIT
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
@ -524,8 +578,10 @@ echo -n "Creating filesystem on ESP partition (vfat)... "
|
||||||
yes | mkdosfs -F32 ${target_disk}1 >&2
|
yes | mkdosfs -F32 ${target_disk}1 >&2
|
||||||
echo "done."
|
echo "done."
|
||||||
|
|
||||||
echo -n "Mounting disks on temporary target... "
|
vgchange -ay >&2
|
||||||
target=$( mktemp -d )
|
target="/tmp/target"
|
||||||
|
mkdir -p ${target} >&2
|
||||||
|
echo -n "Mounting disks on temporary target '${target}'... "
|
||||||
mount /dev/vgx/root ${target} >&2
|
mount /dev/vgx/root ${target} >&2
|
||||||
mkdir -p ${target}/boot >&2
|
mkdir -p ${target}/boot >&2
|
||||||
chattr +i ${target}/boot >&2
|
chattr +i ${target}/boot >&2
|
||||||
|
@ -578,8 +634,94 @@ echo "${bypath_disk}-part1 /boot/efi vfat umask=0077 0 2" | tee -a ${target}/etc
|
||||||
echo "tmpfs /tmp tmpfs defaults 0 0" | tee -a ${target}/etc/fstab >&2
|
echo "tmpfs /tmp tmpfs defaults 0 0" | tee -a ${target}/etc/fstab >&2
|
||||||
echo "done."
|
echo "done."
|
||||||
|
|
||||||
echo -n "Adding interface segment... "
|
seed_interfaces_segment() {
|
||||||
echo -e "${target_interfaces_block}" | tee -a ${target}/etc/network/interfaces >&2
|
# A seed install is always "dhcp-raw" since the provisioner is always a dedicated, access port
|
||||||
|
target_interfaces_block="auto ${target_interface}\niface ${target_interface} inet dhcp\npost-up /etc/network/pvcprovisionerd.checkin.sh \$IFACE"
|
||||||
|
}
|
||||||
|
|
||||||
|
interactive_interfaces_segment() {
|
||||||
|
case ${target_interfaces_is} in
|
||||||
|
static-vlan)
|
||||||
|
target_interfaces_block="auto ${vlan_interface}\niface ${vlan_interface} inet ${target_netformat}\n\tvlan_raw_device ${target_interface}\n\taddress ${formatted_ipaddr}\n\tnetmask ${formatted_netmask}\n\tgateway ${target_defgw}"
|
||||||
|
;;
|
||||||
|
static-raw)
|
||||||
|
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-vlan)
|
||||||
|
target_interfaces_block="auto ${vlan_interface}\niface ${vlan_interface} inet ${target_netformat}\n\tvlan_raw_device${target_interface}"
|
||||||
|
;;
|
||||||
|
dhcp-raw)
|
||||||
|
target_interfaces_block="auto ${target_interface}\niface ${target_interface} inet ${target_netformat}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
echo -n "Creating bootstrap interface segment... "
|
||||||
|
case ${install_option} in
|
||||||
|
on)
|
||||||
|
seed_interfaces_segment
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
interactive_interfaces_segment
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
echo "done."
|
||||||
|
|
||||||
|
echo -n "Adding bootstrap interface segment... "
|
||||||
|
echo -e "${target_interfaces_block}" | tee ${target}/etc/network/interfaces.d/${target_interface} >&2
|
||||||
|
echo "done."
|
||||||
|
|
||||||
|
case ${install_option} in
|
||||||
|
on)
|
||||||
|
echo -n "Creating bond interface segment... "
|
||||||
|
bond_interfaces="$( ip -br link show | grep -E -o '^e[a-z]+[0-9]+[a-z0-9]*' | grep -v "^${target_interface}$" | tr '\n' ' ' )"
|
||||||
|
bond_interfaces_block="auto bond0\niface bond0 inet manual\n\tbond-mode 802.3ad\n\tbond-slaves ${bond_interfaces}\n\tpost-up ip link set mtu 9000 dev \$IFACE"
|
||||||
|
echo "done."
|
||||||
|
|
||||||
|
echo -n "Adding bond interface segment... "
|
||||||
|
echo -e "${bond_interfaces_block}" | tee ${target}/etc/network/interfaces.d/bond0 >&2
|
||||||
|
echo "done."
|
||||||
|
|
||||||
|
echo -n "Adding bootstrap interface post-up checkin script... "
|
||||||
|
cat <<EOF | tee ${target}/etc/network/pvcprovisionerd.checkin.sh >&2
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
target_interface=\${1}
|
||||||
|
pvcbootstrapd_checkin_uri="${pvcbootstrapd_checkin_uri}"
|
||||||
|
macaddr=\$( ip -br link show \${target_interface} | awk '{ print \$3 }' )
|
||||||
|
ipaddr=\$( ip -br address show \${target_interface} | awk '{ print \$3 }' | awk -F '/' '{ print \$1 }' )
|
||||||
|
bmc_macaddr=\$( ipmitool lan print | grep 'MAC Address ' | awk '{ print $NF }' )
|
||||||
|
bmc_ipaddr=\$( ipmitool lan print | grep 'IP Address ' | awk '{ print $NF }' )
|
||||||
|
if [[ -f /etc/pvc-install.pvcbootstrapd_completed ]]; then
|
||||||
|
# The third boot, when all pvcprovisionerd plugins have been run (this script will henceforth do nothing)
|
||||||
|
action="system-boot_bootstrap-completed"
|
||||||
|
elif [[ -f /etc/pvc-install.base && -f /etc/pvc-install.pvc ]]; then
|
||||||
|
# The second boot, when Ansible has been run and plugins running
|
||||||
|
action="system-boot_ansible-completed"
|
||||||
|
touch /etc/pvc-install.pvcbootstrapd_completed
|
||||||
|
else
|
||||||
|
# The first boot, when Ansible has not been run yet
|
||||||
|
action="system-boot_initial"
|
||||||
|
fi
|
||||||
|
curl -X POST \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "{\"action\":\"\${action}\",\"macaddr\":\"\${macaddr}\",\"ipaddr\":\"\${ipaddr}\",\"hostname\":\"\$( hostname -s )\",\"bmc_macaddr\":\"\${bmc_macaddr}\",\"bmc_ipaddr\":\"\${bmc_ipaddr}\"}" \
|
||||||
|
\${pvcbootstrapd_checkin_uri}
|
||||||
|
|
||||||
|
if [[ -f /etc/pvc-install.pvcbootstrapd_completed ]]; then
|
||||||
|
# Clean up the bootstrap interface and this script
|
||||||
|
rm /etc/network/interfaces.d/\${target_interface}
|
||||||
|
rm \$0
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
EOF
|
||||||
|
chmod +x ${target}/etc/network/pvcprovisionerd.checkin.sh
|
||||||
|
echo "done."
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
# noop
|
||||||
|
true
|
||||||
|
;;
|
||||||
|
esac
|
||||||
echo "done."
|
echo "done."
|
||||||
|
|
||||||
echo -n "Setting temporary 'root' password... "
|
echo -n "Setting temporary 'root' password... "
|
||||||
|
@ -613,11 +755,11 @@ echo "done."
|
||||||
echo -n "Setting /etc/issue generator... "
|
echo -n "Setting /etc/issue generator... "
|
||||||
mkdir -p ${target}/etc/network/if-up.d >&2
|
mkdir -p ${target}/etc/network/if-up.d >&2
|
||||||
echo -e "#!/bin/sh
|
echo -e "#!/bin/sh
|
||||||
IP=\"\$( ip -4 addr show dev ${real_interface} | grep inet | awk '{ print \$2 }' | head -1 )\"
|
IP=\"\$( ip -4 addr show dev ${target_interface} | grep inet | awk '{ print \$2 }' | head -1 )\"
|
||||||
cat <<EOF >/etc/issue
|
cat <<EOF >/etc/issue
|
||||||
Debian GNU/Linux 10 \\\\n \\\\l
|
Debian GNU/Linux 10 \\\\n \\\\l
|
||||||
|
|
||||||
Primary interface IP address: \$IP
|
Bootstrap interface IP address: \$IP
|
||||||
|
|
||||||
EOF" | tee ${target}/etc/network/if-up.d/issue-gen >&2
|
EOF" | tee ${target}/etc/network/if-up.d/issue-gen >&2
|
||||||
chmod +x ${target}/etc/network/if-up.d/issue-gen 1>&2
|
chmod +x ${target}/etc/network/if-up.d/issue-gen 1>&2
|
||||||
|
@ -648,37 +790,73 @@ if [[ -d /sys/firmware/efi ]]; then
|
||||||
else
|
else
|
||||||
bios_target="i386-pc"
|
bios_target="i386-pc"
|
||||||
fi
|
fi
|
||||||
|
cat <<EOF | tee ${target}/etc/default/grub >&2
|
||||||
|
GRUB_DEFAULT=0
|
||||||
|
GRUB_TIMEOUT=5
|
||||||
|
GRUB_DISTRIBUTOR="Parallel Virtual Cluster (PVC) - Debian"
|
||||||
|
GRUB_CMDLINE_LINUX="console=hvc0 console=tty0 console=ttyS0,115200"
|
||||||
|
GRUB_TERMINAL_INPUT="console serial"
|
||||||
|
GRUB_TERMINAL_OUTPUT="gfxterm serial"
|
||||||
|
GRUB_SERIAL_COMMAND="serial --unit=0 --unit=1 --speed=115200"
|
||||||
|
EOF
|
||||||
chroot ${target} grub-install --force --target=${bios_target} ${target_disk} >&2
|
chroot ${target} grub-install --force --target=${bios_target} ${target_disk} >&2
|
||||||
chroot ${target} grub-mkconfig -o /boot/grub/grub.cfg >&2
|
chroot ${target} grub-mkconfig -o /boot/grub/grub.cfg >&2
|
||||||
echo "done."
|
echo "done."
|
||||||
|
|
||||||
set +o errexit
|
seed_postinst() {
|
||||||
echo
|
cleanup
|
||||||
echo -n "Edit the /etc/network/interfaces file in the target before completing setup? If you plan to use bonding, it is prudent to set this up in basic form now! [y/N] "
|
echo "Temporary root password: ${root_password}"
|
||||||
read edit_ifaces
|
seed_checkin end
|
||||||
if [[ ${edit_ifaces} == 'y' || ${edit_ifaces} == 'Y' ]]; then
|
|
||||||
vim ${target}/etc/network/interfaces
|
|
||||||
fi
|
|
||||||
echo
|
|
||||||
|
|
||||||
echo -n "Launch a chroot shell in the target environment? [y/N] "
|
echo -n "Rebooting in 10 seconds..."
|
||||||
read launch_chroot
|
i=10
|
||||||
if [[ ${launch_chroot} == 'y' || ${edit_ifaces} == 'Y' ]]; then
|
while [[ ${i} -gt 0 ]]; do
|
||||||
echo "Type 'exit' or Ctrl+D to exit chroot."
|
sleep 1
|
||||||
chroot ${target} /bin/bash
|
i=$(( ${1} - 1 ))
|
||||||
fi
|
echo -n "."
|
||||||
|
done
|
||||||
|
echo
|
||||||
|
reboot
|
||||||
|
}
|
||||||
|
|
||||||
cleanup
|
interactive_postinst() {
|
||||||
|
set +o errexit
|
||||||
|
echo
|
||||||
|
echo -n "Edit the /etc/network/interfaces file in the target before completing setup? If you plan to use bonding, it is prudent to set this up in basic form now! [y/N] "
|
||||||
|
read edit_ifaces
|
||||||
|
if [[ ${edit_ifaces} == 'y' || ${edit_ifaces} == 'Y' ]]; then
|
||||||
|
vim ${target}/etc/network/interfaces
|
||||||
|
fi
|
||||||
|
echo
|
||||||
|
|
||||||
echo "-------------------------------------------------------------------------------------"
|
echo -n "Launch a chroot shell in the target environment? [y/N] "
|
||||||
echo "| PVC node installation finished. Next steps: |"
|
read launch_chroot
|
||||||
echo "| 1. Press <enter> to reboot the system. |"
|
if [[ ${launch_chroot} == 'y' || ${edit_ifaces} == 'Y' ]]; then
|
||||||
echo "| 2. Boot the system verify SSH access (IP shown on login screen). |"
|
echo "Type 'exit' or Ctrl+D to exit chroot."
|
||||||
echo "| 3. Proceed with system deployment via PVC Ansible. |"
|
chroot ${target} /bin/bash
|
||||||
echo "| |"
|
fi
|
||||||
echo "| The INSECURE temporary root password if the system will not boot is: ${root_password} |"
|
|
||||||
echo "-------------------------------------------------------------------------------------"
|
|
||||||
echo
|
|
||||||
read
|
|
||||||
|
|
||||||
reboot
|
cleanup
|
||||||
|
|
||||||
|
echo "-------------------------------------------------------------------------------------"
|
||||||
|
echo "| PVC node installation finished. Next steps: |"
|
||||||
|
echo "| 1. Press <enter> to reboot the system. |"
|
||||||
|
echo "| 2. Boot the system verify SSH access (IP shown on login screen). |"
|
||||||
|
echo "| 3. Proceed with system deployment via PVC Ansible. |"
|
||||||
|
echo "| |"
|
||||||
|
echo "| The INSECURE temporary root password if the system will not boot is: ${root_password} |"
|
||||||
|
echo "-------------------------------------------------------------------------------------"
|
||||||
|
echo
|
||||||
|
read
|
||||||
|
|
||||||
|
reboot
|
||||||
|
}
|
||||||
|
|
||||||
|
case ${install_option} in
|
||||||
|
on)
|
||||||
|
seed_postinst
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
interactive_postinst
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
Loading…
Reference in New Issue