Files
proxmox/smom-dbis-138-proxmox/scripts/manage/deploy-multi-node.sh

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!"