Feat: Node orchestration UX improvements (#6848)
* improve nginx playbook * improve configure-vm script * improve initialise-vm script * expand config naming options * provide args docs * syntax fix * address rabbitai comments * cleanup ansible * document ansible changes * fix review comments * update scraed data * fix max comment review
This commit is contained in:
@@ -1,36 +1,101 @@
|
||||
|
||||
#!/bin/bash
|
||||
|
||||
# detect active network interface
|
||||
INTERFACE=$(ip -o link show | awk -F': ' '{print $2}' | grep -v lo | head -n 1)
|
||||
usage() {
|
||||
local code="${1:-0}"
|
||||
cat <<EOF
|
||||
Usage: $0 [OPTIONS]
|
||||
|
||||
echo "Detected active network interface: $INTERFACE"
|
||||
read -p "Is this correct? (y/n): " CONFIRM
|
||||
if [[ "$CONFIRM" != "y" ]]; then
|
||||
echo "Exiting. Please manually specify the correct network interface."
|
||||
Options:
|
||||
-i, --interface Network interface (optional; auto-detected if omitted)
|
||||
-4, --ipv4 IPv4 address for the VM (optional)
|
||||
-6, --ipv6 IPv6 address for the VM (optional)
|
||||
-g, --gateway4 IPv4 gateway of the host server (optional)
|
||||
-G, --gateway6 IPv6 gateway of the host server (optional)
|
||||
-y, --yes Skip all confirmation prompts (auto-confirm)
|
||||
-h, --help Show this help message
|
||||
|
||||
Example:
|
||||
$0 --ipv4 192.168.1.100 --gateway4 192.168.1.1 --ipv6 2001:db8::1 --gateway6 2001:db8::fffe
|
||||
$0 --ipv4 192.168.1.100 --gateway4 192.168.1.1 --yes
|
||||
EOF
|
||||
exit "$code"
|
||||
}
|
||||
|
||||
# --- parse flags ---
|
||||
INTERFACE=""
|
||||
IPv4_VM=""
|
||||
IPv6_VM=""
|
||||
IPv4_GATEWAY_HOST_SERVER=""
|
||||
IPv6_GATEWAY_HOST_SERVER=""
|
||||
AUTO_YES=false
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
-i|--interface)
|
||||
[[ -n "${2:-}" && "${2:0:1}" != "-" ]] || { echo "Error: --interface requires a value."; exit 1; }
|
||||
INTERFACE="$2"; shift 2 ;;
|
||||
-4|--ipv4)
|
||||
[[ -n "${2:-}" && "${2:0:1}" != "-" ]] || { echo "Error: --ipv4 requires a value."; exit 1; }
|
||||
IPv4_VM="$2"; shift 2 ;;
|
||||
-6|--ipv6)
|
||||
[[ -n "${2:-}" && "${2:0:1}" != "-" ]] || { echo "Error: --ipv6 requires a value."; exit 1; }
|
||||
IPv6_VM="$2"; shift 2 ;;
|
||||
-g|--gateway4)
|
||||
[[ -n "${2:-}" && "${2:0:1}" != "-" ]] || { echo "Error: --gateway4 requires a value."; exit 1; }
|
||||
IPv4_GATEWAY_HOST_SERVER="$2"; shift 2 ;;
|
||||
-G|--gateway6)
|
||||
[[ -n "${2:-}" && "${2:0:1}" != "-" ]] || { echo "Error: --gateway6 requires a value."; exit 1; }
|
||||
IPv6_GATEWAY_HOST_SERVER="$2"; shift 2 ;;
|
||||
-y|--yes) AUTO_YES=true; shift ;;
|
||||
-h|--help) usage ;;
|
||||
*)
|
||||
echo "Error: Unknown option: $1"
|
||||
usage 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# at least one of IPv4 or IPv6 must be provided
|
||||
if [[ -z "$IPv4_VM" && -z "$IPv6_VM" ]]; then
|
||||
echo "Error: At least one of --ipv4 or --ipv6 must be provided."
|
||||
echo "Run '$0 --help' for usage."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# prompt for network settings
|
||||
read -p "Enter IPv4 address for VM (leave blank if not used): " IPv4_VM
|
||||
read -p "Enter IPv6 address for VM (leave blank if not used): " IPv6_VM
|
||||
read -p "Enter IPv4 gateway (host server, leave blank if not used): " IPv4_GATEWAY_HOST_SERVER
|
||||
read -p "Enter IPv6 gateway (host server, leave blank if not used): " IPv6_GATEWAY_HOST_SERVER
|
||||
confirm() {
|
||||
local prompt="$1"
|
||||
if $AUTO_YES; then
|
||||
echo "${prompt} [Y/n] (auto-confirmed)"
|
||||
return 0
|
||||
fi
|
||||
read -p "${prompt} [Y/n]: " REPLY
|
||||
[[ -z "$REPLY" || "$REPLY" == "y" || "$REPLY" == "Y" ]]
|
||||
}
|
||||
|
||||
# resize partition
|
||||
# --- detect or validate interface ---
|
||||
if [[ -z "$INTERFACE" ]]; then
|
||||
INTERFACE=$(ip -o link show | awk -F': ' '{print $2}' | grep -v lo | head -n 1)
|
||||
echo "Detected active network interface: $INTERFACE"
|
||||
if ! confirm "Is this correct?"; then
|
||||
echo "Exiting. Re-run with --interface <name> to specify one manually."
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "Using network interface: $INTERFACE"
|
||||
fi
|
||||
|
||||
# --- resize partition ---
|
||||
echo "Expanding partition and resizing filesystem..."
|
||||
growpart /dev/vda 1
|
||||
resize2fs /dev/vda1
|
||||
df -h
|
||||
|
||||
# ask before continuing
|
||||
read -p "Continue with network configuration? (y/n): " CONTINUE
|
||||
if [[ "$CONTINUE" != "y" ]]; then
|
||||
if ! confirm "Continue with network configuration?"; then
|
||||
echo "Exiting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# generate Netplan config
|
||||
# --- generate Netplan config ---
|
||||
NETPLAN_CONFIG="/etc/netplan/01-network-config.yaml"
|
||||
echo "Creating Netplan configuration at $NETPLAN_CONFIG..."
|
||||
|
||||
@@ -45,28 +110,19 @@ network:
|
||||
addresses:
|
||||
EOF
|
||||
|
||||
# append IPv4 address if provided
|
||||
if [[ -n "$IPv4_VM" ]]; then
|
||||
echo " - $IPv4_VM/24" >> $NETPLAN_CONFIG
|
||||
fi
|
||||
[[ -n "$IPv4_VM" ]] && echo " - $IPv4_VM/24" >> $NETPLAN_CONFIG
|
||||
[[ -n "$IPv6_VM" ]] && echo " - $IPv6_VM/64" >> $NETPLAN_CONFIG
|
||||
|
||||
# append IPv6 address if provided
|
||||
if [[ -n "$IPv6_VM" ]]; then
|
||||
echo " - $IPv6_VM/64" >> $NETPLAN_CONFIG
|
||||
fi
|
||||
|
||||
echo " routes:" >> $NETPLAN_CONFIG
|
||||
|
||||
# append IPv4 route if provided
|
||||
if [[ -n "$IPv4_GATEWAY_HOST_SERVER" ]]; then
|
||||
echo " - to: default" >> $NETPLAN_CONFIG
|
||||
echo " via: $IPv4_GATEWAY_HOST_SERVER" >> $NETPLAN_CONFIG
|
||||
fi
|
||||
|
||||
# append IPv6 route if provided
|
||||
if [[ -n "$IPv6_GATEWAY_HOST_SERVER" ]]; then
|
||||
echo " - to: default" >> $NETPLAN_CONFIG
|
||||
echo " via: $IPv6_GATEWAY_HOST_SERVER" >> $NETPLAN_CONFIG
|
||||
if [[ -n "$IPv4_GATEWAY_HOST_SERVER" || -n "$IPv6_GATEWAY_HOST_SERVER" ]]; then
|
||||
echo " routes:" >> $NETPLAN_CONFIG
|
||||
if [[ -n "$IPv4_GATEWAY_HOST_SERVER" ]]; then
|
||||
echo " - to: default" >> $NETPLAN_CONFIG
|
||||
echo " via: $IPv4_GATEWAY_HOST_SERVER" >> $NETPLAN_CONFIG
|
||||
fi
|
||||
if [[ -n "$IPv6_GATEWAY_HOST_SERVER" ]]; then
|
||||
echo " - to: default" >> $NETPLAN_CONFIG
|
||||
echo " via: $IPv6_GATEWAY_HOST_SERVER" >> $NETPLAN_CONFIG
|
||||
fi
|
||||
fi
|
||||
|
||||
cat <<EOF >> $NETPLAN_CONFIG
|
||||
@@ -78,58 +134,43 @@ cat <<EOF >> $NETPLAN_CONFIG
|
||||
- 2001:4860:4860::8888 # Google IPv6 DNS
|
||||
EOF
|
||||
|
||||
# secure Netplan config
|
||||
chmod 600 $NETPLAN_CONFIG
|
||||
|
||||
# generate Netplan configuration
|
||||
netplan generate
|
||||
|
||||
# ask before applying Netplan
|
||||
read -p "Apply Netplan changes? (y/n): " CONTINUE
|
||||
if [[ "$CONTINUE" != "y" ]]; then
|
||||
if ! confirm "Apply Netplan changes?"; then
|
||||
echo "Exiting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# apply Netplan and verify settings
|
||||
netplan --debug apply
|
||||
|
||||
# show IP configurations
|
||||
ip -4 a
|
||||
ip -6 a
|
||||
ip -4 r
|
||||
ip -6 r
|
||||
|
||||
# test network connectivity
|
||||
echo "Testing IPv4 connectivity for 10 seconds..."
|
||||
timeout 10 ping -4 google.com
|
||||
|
||||
echo "Testing IPv6 connectivity for 10 seconds..."
|
||||
timeout 10 ping -6 google.com
|
||||
|
||||
# ask before updating system
|
||||
read -p "Proceed with system update and upgrade? (y/n): " CONTINUE
|
||||
if [[ "$CONTINUE" != "y" ]]; then
|
||||
echo "Skipping updates."
|
||||
else
|
||||
if confirm "Proceed with system update and upgrade?"; then
|
||||
apt update && apt upgrade -y
|
||||
else
|
||||
echo "Skipping updates."
|
||||
fi
|
||||
|
||||
# generate SSH host keys without password
|
||||
# --- SSH setup ---
|
||||
echo "Generating SSH host keys..."
|
||||
ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -N ""
|
||||
ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key -N ""
|
||||
ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key -N ""
|
||||
ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -N ""
|
||||
ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key -N ""
|
||||
ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key -N ""
|
||||
ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N ""
|
||||
|
||||
# restart SSH service
|
||||
systemctl restart ssh.service
|
||||
|
||||
# ensure ~/.ssh directory exists
|
||||
mkdir -p ~/.ssh
|
||||
|
||||
# Open authorized_keys file for user input
|
||||
echo "# Add your admin SSH keys here, save and exit!" > ~/.ssh/authorized_keys
|
||||
nano ~/.ssh/authorized_keys
|
||||
|
||||
echo "Setup complete! Try to ping and ssh from the outside before killing this console"
|
||||
echo "Setup complete! Try to ping and ssh from the outside before killing this console"
|
||||
@@ -1,6 +1,86 @@
|
||||
#!/bin/bash
|
||||
|
||||
# check if noble-server-cloudimg-amd64.img is in working dir - if not, wget it
|
||||
usage() {
|
||||
local code="${1:-0}"
|
||||
cat <<EOF
|
||||
Usage: $0 [OPTIONS]
|
||||
|
||||
Options:
|
||||
-n, --name VM name (required)
|
||||
-p, --password Root password (required)
|
||||
-c, --cpus Number of vCPUs (required)
|
||||
-r, --ram RAM in MB (required); e.g. 2048, 4096, 8192
|
||||
-s, --size Disk size to add in GB (required); e.g. 50, 100, 200
|
||||
-h, --help Show this help message
|
||||
|
||||
Example:
|
||||
$0 --name myvm --password secret --cpus 4 --ram 8192 --size 100
|
||||
EOF
|
||||
exit "$code"
|
||||
}
|
||||
|
||||
# --- parse flags ---
|
||||
VM_NAME=""
|
||||
PASSWORD=""
|
||||
VCPUS=""
|
||||
RAM=""
|
||||
SIZE=""
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
-n|--name)
|
||||
[[ -n "${2:-}" && "${2:0:1}" != "-" ]] || { echo "Error: --name requires a value."; exit 1; }
|
||||
VM_NAME="$2"; shift 2 ;;
|
||||
-p|--password)
|
||||
[[ -n "${2:-}" && "${2:0:1}" != "-" ]] || { echo "Error: --password requires a value."; exit 1; }
|
||||
PASSWORD="$2"; shift 2 ;;
|
||||
-c|--cpus)
|
||||
[[ -n "${2:-}" && "${2:0:1}" != "-" ]] || { echo "Error: --cpus requires a value."; exit 1; }
|
||||
VCPUS="$2"; shift 2 ;;
|
||||
-r|--ram)
|
||||
[[ -n "${2:-}" && "${2:0:1}" != "-" ]] || { echo "Error: --ram requires a value."; exit 1; }
|
||||
RAM="$2"; shift 2 ;;
|
||||
-s|--size)
|
||||
[[ -n "${2:-}" && "${2:0:1}" != "-" ]] || { echo "Error: --size requires a value."; exit 1; }
|
||||
SIZE="$2"; shift 2 ;;
|
||||
-h|--help) usage ;;
|
||||
*)
|
||||
echo "Error: Unknown option: $1"
|
||||
usage 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# --- validate required flags ---
|
||||
MISSING=()
|
||||
[[ -z "$VM_NAME" ]] && MISSING+=("--name")
|
||||
[[ -z "$PASSWORD" ]] && MISSING+=("--password")
|
||||
[[ -z "$VCPUS" ]] && MISSING+=("--cpus")
|
||||
[[ -z "$RAM" ]] && MISSING+=("--ram")
|
||||
[[ -z "$SIZE" ]] && MISSING+=("--size")
|
||||
|
||||
if [[ ${#MISSING[@]} -gt 0 ]]; then
|
||||
echo "Error: Missing required flags: ${MISSING[*]}"
|
||||
echo "Run '$0 --help' for usage."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! "$VCPUS" =~ ^[0-9]+$ || "$VCPUS" -lt 1 ]]; then
|
||||
echo "Error: --cpus must be a positive integer."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! "$RAM" =~ ^[0-9]+$ || "$RAM" -lt 256 ]]; then
|
||||
echo "Error: --ram must be a positive integer (minimum 256 MB)."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! "$SIZE" =~ ^[0-9]+$ || "$SIZE" -lt 1 ]]; then
|
||||
echo "Error: --size must be a positive integer in GB."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- check / download base image ---
|
||||
if [[ ! -f noble-server-cloudimg-amd64.img ]]; then
|
||||
echo "Base image not found. Downloading noble-server-cloudimg-amd64.img..."
|
||||
wget https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img
|
||||
@@ -10,99 +90,40 @@ if [[ ! -f noble-server-cloudimg-amd64.img ]]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
# prompt for VM_NAME
|
||||
read -p "Enter VM name: " VM_NAME
|
||||
if [[ -z "$VM_NAME" ]]; then
|
||||
echo "Error: VM_NAME cannot be empty. Exiting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# prompt for PASSWORD w silent input
|
||||
read -s -p "Enter password for the VM: " PASSWORD
|
||||
echo
|
||||
if [[ -z "$PASSWORD" ]]; then
|
||||
echo "Error: PASSWORD cannot be empty. Exiting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# prompt for number of vCPUs
|
||||
read -p "Enter the number of vCPUs for the VM: " VCPUS
|
||||
if [[ -z "$VCPUS" || ! "$VCPUS" =~ ^[0-9]+$ ]]; then
|
||||
echo "Error: Invalid number of vCPUs. Exiting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# prompt for RAM size with suggestions
|
||||
DEFAULT_RAM=4096
|
||||
HALF_RAM=$((DEFAULT_RAM / 2))
|
||||
DOUBLE_RAM=$((DEFAULT_RAM * 2))
|
||||
TRIPLE_RAM=$((DEFAULT_RAM * 3))
|
||||
FOUR_TIMES_RAM=$((DEFAULT_RAM * 4))
|
||||
SIX_TIMES_RAM=$((DEFAULT_RAM * 6))
|
||||
EIGHT_TIMES_RAM=$((DEFAULT_RAM * 8))
|
||||
|
||||
echo "Choose the amount of RAM for the VM:"
|
||||
echo "1) $HALF_RAM MB"
|
||||
echo "2) $DEFAULT_RAM MB (recommended)"
|
||||
echo "3) $DOUBLE_RAM MB"
|
||||
echo "4) $TRIPLE_RAM MB"
|
||||
echo "5) $FOUR_TIMES_RAM MB"
|
||||
echo "6) $SIX_TIMES_RAM MB"
|
||||
echo "7) $EIGHT_TIMES_RAM MB"
|
||||
read -p "Enter your choice (1-7) or specify a custom amount in MB: " RAM_CHOICE
|
||||
|
||||
case $RAM_CHOICE in
|
||||
1) RAM=$HALF_RAM ;;
|
||||
2) RAM=$DEFAULT_RAM ;;
|
||||
3) RAM=$DOUBLE_RAM ;;
|
||||
4) RAM=$TRIPLE_RAM ;;
|
||||
5) RAM=$FOUR_TIMES_RAM ;;
|
||||
6) RAM=$SIX_TIMES_RAM ;;
|
||||
7) RAM=$EIGHT_TIMES_RAM ;;
|
||||
*)
|
||||
if [[ "$RAM_CHOICE" =~ ^[0-9]+$ ]]; then
|
||||
RAM=$RAM_CHOICE
|
||||
else
|
||||
echo "Invalid choice. Exiting."
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# define image path
|
||||
IMAGE_PATH="/var/lib/libvirt/images/${VM_NAME}.img"
|
||||
|
||||
# copy the base image
|
||||
|
||||
if [[ -e "$IMAGE_PATH" ]]; then
|
||||
echo "Error: $IMAGE_PATH already exists. Choose a different --name or remove the old image first."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Copying the base image to $IMAGE_PATH..."
|
||||
cp noble-server-cloudimg-amd64.img "$IMAGE_PATH"
|
||||
|
||||
# install guestfs-tools if missing
|
||||
echo "Checking and installing guestfs-tools if needed..."
|
||||
if ! dpkg -l | grep -q guestfs-tools; then
|
||||
sudo apt update && sudo apt install guestfs-tools -y
|
||||
fi
|
||||
|
||||
# set root password inside the image
|
||||
echo "Setting root password inside the VM image..."
|
||||
virt-customize -a "$IMAGE_PATH" --root-password password:"$PASSWORD"
|
||||
|
||||
# resize the image
|
||||
echo "Resizing the image by +100G..."
|
||||
qemu-img resize "$IMAGE_PATH" +100G
|
||||
echo "Resizing the image by +${SIZE}G..."
|
||||
qemu-img resize "$IMAGE_PATH" +${SIZE}G
|
||||
|
||||
# install the VM and run log in prompt
|
||||
echo "Starting VM installation..."
|
||||
virt-install \
|
||||
--name "$VM_NAME" \
|
||||
--ram="$RAM" \
|
||||
--vcpus="$VCPUS" \
|
||||
--cpu host \
|
||||
--hvm \
|
||||
--disk bus=virtio,path="$IMAGE_PATH" \
|
||||
--network bridge=br0 \
|
||||
--graphics none \
|
||||
--console pty,target_type=serial \
|
||||
--osinfo ubuntunoble \
|
||||
--import
|
||||
--name "$VM_NAME" \
|
||||
--ram="$RAM" \
|
||||
--vcpus="$VCPUS" \
|
||||
--cpu host \
|
||||
--hvm \
|
||||
--disk bus=virtio,path="$IMAGE_PATH" \
|
||||
--network bridge=br0 \
|
||||
--graphics none \
|
||||
--console pty,target_type=serial \
|
||||
--osinfo ubuntunoble \
|
||||
--import
|
||||
|
||||
echo "VM $VM_NAME has been successfully installed!"
|
||||
echo "VM $VM_NAME has been successfully installed!"
|
||||
Reference in New Issue
Block a user