Files
proxmox/scripts/recreate-containers-from-configs.sh

224 lines
7.3 KiB
Bash
Raw Permalink Normal View History

#!/usr/bin/env bash
# Recreate containers from their configurations
# This script recreates containers that lost data during RAID expansion
set -euo pipefail
# Load IP configuration
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
source "${PROJECT_ROOT}/config/ip-addresses.conf" 2>/dev/null || true
NODE="r630-01"
NODE_IP="${PROXMOX_HOST_R630_01:-192.168.11.11}"
NODE_PASS="password"
# Colors
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m'
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
log_success() { echo -e "${GREEN}[✓]${NC} $1"; }
log_error() { echo -e "${RED}[✗]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[⚠]${NC} $1"; }
log_header() { echo -e "${CYAN}=== $1 ===${NC}"; }
ssh_node() {
sshpass -p "$NODE_PASS" ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10 root@"$NODE_IP" "$@" 2>&1
}
# Get container configuration
get_container_config() {
local vmid="$1"
ssh_node "pct config $vmid 2>/dev/null"
}
# Extract configuration values
extract_config_value() {
local config="$1"
local key="$2"
echo "$config" | grep "^$key:" | awk '{print $2}'
}
# Recreate container from template
recreate_container() {
local vmid="$1"
local config=$(get_container_config "$vmid")
if [ -z "$config" ]; then
log_error "Container $vmid configuration not found"
return 1
fi
log_header "Recreating Container $vmid"
# Extract configuration
local hostname=$(extract_config_value "$config" "hostname")
local rootfs=$(extract_config_value "$config" "rootfs")
local memory=$(extract_config_value "$config" "memory")
local swap=$(extract_config_value "$config" "swap" || echo "512")
local cores=$(extract_config_value "$config" "cores")
local net0=$(extract_config_value "$config" "net0")
# Parse rootfs
local storage=$(echo "$rootfs" | cut -d: -f1)
local volume=$(echo "$rootfs" | cut -d: -f2 | cut -d, -f1)
local size_raw=$(echo "$rootfs" | grep -oP 'size=\K[^,]+' || echo "10G")
# Extract numeric size (remove G/M suffix for pct create)
local size=$(echo "$size_raw" | sed 's/G$//' | sed 's/M$//')
local size_unit=$(echo "$size_raw" | grep -oE '[GM]$' || echo "G")
log_info "Hostname: $hostname"
log_info "Storage: $storage"
log_info "Size: $size"
log_info "Memory: ${memory}MB"
log_info "Cores: $cores"
# Check if container already exists
if ssh_node "pct list 2>/dev/null | grep -q '^$vmid'"; then
log_warn "Container $vmid already exists"
log_info "Checking if it's empty..."
local volume_usage=$(ssh_node "lvs pve | grep $volume | awk '{print \$6}'" | grep -oP '^\d+\.\d+' || echo "0")
if [ "$(echo "$volume_usage > 0" | bc 2>/dev/null || echo "0")" = "1" ]; then
log_warn "Container $vmid has data (${volume_usage}% used), skipping..."
return 0
else
log_info "Container $vmid is empty, will recreate..."
ssh_node "pct destroy $vmid --force" || log_warn "Failed to destroy container"
sleep 2
fi
fi
# Determine template (default to ubuntu-22.04)
local template="ubuntu-22.04-standard_22.04-1_amd64.tar.zst"
# Check if template exists
if ! ssh_node "test -f /var/lib/vz/template/cache/$template"; then
log_warn "Template $template not found, checking available templates..."
local available_template=$(ssh_node "ls /var/lib/vz/template/cache/*.tar.zst 2>/dev/null | head -1" | xargs basename)
if [ -n "$available_template" ]; then
template="$available_template"
log_info "Using template: $template"
else
log_error "No templates found. Please download a template first."
log_info "Download template: pveam download local ubuntu-22.04-standard_22.04-1_amd64.tar.zst"
return 1
fi
fi
# Map storage names (local-lvm maps to data pool)
local target_storage="$storage"
if [ "$storage" = "local-lvm" ]; then
target_storage="data"
fi
# Build pct create command
local create_cmd="pct create $vmid /var/lib/vz/template/cache/$template"
create_cmd="$create_cmd --storage $target_storage --rootfs $target_storage:$size"
create_cmd="$create_cmd --hostname $hostname"
create_cmd="$create_cmd --memory $memory --swap $swap --cores $cores"
# Add network configuration
if [ -n "$net0" ]; then
create_cmd="$create_cmd --net0 $net0"
else
create_cmd="$create_cmd --net0 name=eth0,bridge=vmbr0"
fi
# Add mount points if any
local mp_count=0
while echo "$config" | grep -q "^mp$mp_count:"; do
local mp=$(extract_config_value "$config" "mp$mp_count")
create_cmd="$create_cmd --mp$mp_count $mp"
mp_count=$((mp_count + 1))
done
log_info "Creating container with command:"
log_info "$create_cmd"
# Create container
if ssh_node "$create_cmd"; then
log_success "Container $vmid created successfully"
# Restore additional configuration
log_info "Restoring additional configuration..."
# Copy config file and restore non-standard settings
ssh_node "pct config $vmid > /tmp/vmid_${vmid}_new.conf" || true
# Restore any custom settings from old config
# (This would need to be customized based on specific needs)
log_success "Container $vmid recreation completed"
return 0
else
log_error "Failed to create container $vmid"
return 1
fi
}
# Main function
main() {
log_header "Container Recreation from Configurations"
echo ""
# Get list of containers to recreate (empty volumes)
log_info "Finding containers with empty volumes..."
local empty_containers=$(ssh_node "lvs pve | grep 'vm-.*-disk-0' | awk '\$6==\"0.00\" {print \$1}' | sed 's/vm-\([0-9]*\)-disk-0/\1/' | sort -n | head -20")
if [ -z "$empty_containers" ]; then
log_warn "No containers with empty volumes found"
log_info "You can specify VMIDs manually: $0 <vmid1> [vmid2] ..."
exit 0
fi
log_info "Found containers with empty volumes:"
echo "$empty_containers" | while read vmid; do
local name=$(ssh_node "pct config $vmid 2>/dev/null | grep '^hostname:' | awk '{print \$2}'" || echo "unknown")
echo " - $vmid: $name"
done
echo ""
# Confirm
log_warn "This will recreate containers from templates"
log_warn "All data in these containers will be lost (they're already empty)"
log_info "Press Enter to continue or Ctrl+C to cancel..."
read -r
# Recreate each container
local success=0
local failed=0
for vmid in $empty_containers; do
if recreate_container "$vmid"; then
success=$((success + 1))
else
failed=$((failed + 1))
fi
echo ""
done
# Summary
echo ""
log_header "Recreation Summary"
log_success "Successfully recreated: $success"
if [ $failed -gt 0 ]; then
log_error "Failed recreations: $failed"
fi
}
# If VMIDs provided as arguments, use those instead
if [ $# -gt 0 ]; then
for vmid in "$@"; do
recreate_container "$vmid"
echo ""
done
else
main "$@"
fi