212 lines
6.1 KiB
Bash
Executable File
212 lines
6.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Multi-node deployment script - distributes containers across available nodes
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
|
|
source "$PROJECT_ROOT/lib/common.sh"
|
|
source "$PROJECT_ROOT/lib/proxmox-api.sh"
|
|
|
|
# Load configuration
|
|
load_config
|
|
|
|
# Node assignment strategies
|
|
assign_node_auto() {
|
|
local memory="$1"
|
|
local disk="$2"
|
|
local storage="${3:-${PROXMOX_STORAGE}}"
|
|
|
|
proxmox_find_available_node "$memory" "$disk" "$storage"
|
|
}
|
|
|
|
assign_node_round_robin() {
|
|
local nodes
|
|
nodes=$(echo "${PROXMOX_NODES:-${PROXMOX_NODE}}" | tr ',' ' ')
|
|
local node_array=($nodes)
|
|
local index=$((RANDOM % ${#node_array[@]}))
|
|
echo "${node_array[$index]}"
|
|
}
|
|
|
|
assign_node_manual() {
|
|
# For manual assignment, use configuration file mapping
|
|
local vmid="$1"
|
|
local node_mapping="${NODE_MAPPING:-}"
|
|
|
|
if [[ -n "$node_mapping" && -f "$node_mapping" ]]; then
|
|
local assigned_node
|
|
assigned_node=$(grep "^${vmid}:" "$node_mapping" | cut -d: -f2 || echo "")
|
|
if [[ -n "$assigned_node" ]]; then
|
|
echo "$assigned_node"
|
|
return 0
|
|
fi
|
|
fi
|
|
|
|
# Fallback to default node
|
|
echo "${PROXMOX_NODE}"
|
|
}
|
|
|
|
# Get node for container based on strategy
|
|
get_assignment_node() {
|
|
local vmid="$1"
|
|
local memory="$2"
|
|
local disk="$3"
|
|
local storage="${4:-${PROXMOX_STORAGE}}"
|
|
|
|
local strategy="${NODE_ASSIGNMENT_STRATEGY:-auto}"
|
|
|
|
case "$strategy" in
|
|
auto)
|
|
assign_node_auto "$memory" "$disk" "$storage"
|
|
;;
|
|
round-robin)
|
|
assign_node_round_robin
|
|
;;
|
|
manual)
|
|
assign_node_manual "$vmid"
|
|
;;
|
|
*)
|
|
log_warn "Unknown strategy: $strategy, using default node"
|
|
echo "${PROXMOX_NODE}"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Function to create container on specific node
|
|
create_container_on_node() {
|
|
local vmid="$1"
|
|
local hostname="$2"
|
|
local ip_address="$3"
|
|
local memory="$4"
|
|
local cores="$5"
|
|
local disk="$6"
|
|
local network_config="$7"
|
|
local target_node="$8"
|
|
local storage="${9:-${PROXMOX_STORAGE}}"
|
|
|
|
log_info "Creating container $vmid ($hostname) on node $target_node..."
|
|
|
|
if pct list | grep -q "^\s*$vmid\s"; then
|
|
log_warn "Container $vmid already exists, skipping creation"
|
|
return 0
|
|
fi
|
|
|
|
# If on target node, create directly, otherwise use API
|
|
if [[ "$(hostname)" == "$target_node" ]] || [[ "${PROXMOX_HOST}" == "$target_node" ]]; then
|
|
pct create "$vmid" \
|
|
"${CONTAINER_OS_TEMPLATE:-local:vztmpl/ubuntu-22.04-standard_22.04-1_amd64.tar.zst}" \
|
|
--storage "$storage" \
|
|
--hostname "$hostname" \
|
|
--memory "$memory" \
|
|
--cores "$cores" \
|
|
--rootfs "${storage}:${disk}" \
|
|
--net0 "$network_config" \
|
|
--unprivileged 0 \
|
|
--features nesting=1,keyctl=1
|
|
|
|
log_success "Container $vmid created on node $target_node"
|
|
else
|
|
# Use API to create on remote node
|
|
proxmox_create_container "$vmid" \
|
|
"${CONTAINER_OS_TEMPLATE}" \
|
|
"$storage" \
|
|
"$hostname" \
|
|
"$memory" \
|
|
"$cores" \
|
|
"$disk" \
|
|
"$network_config" \
|
|
"$target_node"
|
|
fi
|
|
}
|
|
|
|
# Example: Deploy validators across nodes
|
|
deploy_validators_multi_node() {
|
|
local count="${1:-4}"
|
|
local start_vmid="${VMID_VALIDATORS_START:-1000}"
|
|
|
|
log_info "Deploying $count validators across available nodes..."
|
|
|
|
for i in $(seq 0 $((count - 1))); do
|
|
local vmid=$((start_vmid + i))
|
|
local hostname="validator-$((i + 1))"
|
|
local ip_octet=$((10 + i))
|
|
local ip_address="${SUBNET_BASE:-10.3.1}.${ip_octet}"
|
|
|
|
# Assign node
|
|
local target_node
|
|
target_node=$(get_assignment_node "$vmid" "${VALIDATOR_MEMORY:-8192}" "${VALIDATOR_DISK:-100}")
|
|
|
|
log_info "Validator $((i + 1)) will be deployed on node: $target_node"
|
|
|
|
# Network config
|
|
local vlan="${VLAN_VALIDATORS:-100}"
|
|
local network_config="bridge=${PROXMOX_BRIDGE:-vmbr0},tag=$vlan,name=eth0,ip=${ip_address}/${NETMASK:-24},gw=${GATEWAY:-10.3.1.1}"
|
|
|
|
# Create container
|
|
create_container_on_node \
|
|
"$vmid" \
|
|
"$hostname" \
|
|
"$ip_address" \
|
|
"${VALIDATOR_MEMORY:-8192}" \
|
|
"${VALIDATOR_CORES:-4}" \
|
|
"${VALIDATOR_DISK:-100}" \
|
|
"$network_config" \
|
|
"$target_node"
|
|
done
|
|
}
|
|
|
|
# Main
|
|
if [[ $# -eq 0 ]]; then
|
|
echo "Usage: $0 <command> [options]"
|
|
echo ""
|
|
echo "Commands:"
|
|
echo " validators [count] - Deploy validators across nodes"
|
|
echo " list-nodes - List available nodes"
|
|
echo " check-resources - Check resource availability on all nodes"
|
|
exit 1
|
|
fi
|
|
|
|
check_root
|
|
|
|
COMMAND="$1"
|
|
shift || true
|
|
|
|
case "$COMMAND" in
|
|
validators)
|
|
COUNT="${1:-4}"
|
|
deploy_validators_multi_node "$COUNT"
|
|
;;
|
|
list-nodes)
|
|
log_info "Available nodes:"
|
|
local nodes_output
|
|
nodes_output=$(proxmox_list_nodes 2>/dev/null)
|
|
if command_exists jq && [[ -n "$nodes_output" ]]; then
|
|
echo "$nodes_output" | jq -r '.data[] | " - \(.node): \(.status)"' 2>/dev/null
|
|
else
|
|
if [[ -n "${PROXMOX_NODES:-}" ]]; then
|
|
echo "$PROXMOX_NODES" | tr ',' '\n' | while read -r node; do
|
|
log_info " - $node"
|
|
done
|
|
else
|
|
log_info " - ${PROXMOX_NODE} (default node)"
|
|
fi
|
|
fi
|
|
;;
|
|
check-resources)
|
|
log_info "Checking resources on all nodes..."
|
|
local nodes
|
|
nodes=$(echo "${PROXMOX_NODES:-${PROXMOX_NODE}}" | tr ',' ' ')
|
|
for node in $nodes; do
|
|
log_info "Node: $node"
|
|
proxmox_get_storage_usage "$node" "${PROXMOX_STORAGE}"
|
|
done
|
|
;;
|
|
*)
|
|
error_exit "Unknown command: $COMMAND"
|
|
;;
|
|
esac
|
|
|
|
log_success "Multi-node deployment completed!"
|
|
|