#!/usr/bin/env bash # Migrate containers 1504, 2503, 2504, 6201 from ml110 to r630-01 using thin1 storage 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 # Configuration PROXMOX_HOST_ML110="${PROXMOX_HOST_ML110}" ML110_PASS="L@kers2010" SOURCE_NODE="ml110" TARGET_NODE="r630-01" TARGET_STORAGE="thin1" # Containers to migrate CONTAINERS=(1504 2503 2504 6201) # Colors RED='\033[0;31m' GREEN='\033[0;32m' 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_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } log_error() { echo -e "${RED}[ERROR]${NC} $1"; } log_header() { echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"; } # SSH helper ssh_ml110() { sshpass -p "$ML110_PASS" ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=accept-new root@"$PROXMOX_HOST_ML110" "$@" 2>&1 } # Check if container exists check_container() { local vmid=$1 ssh_ml110 "pct list | grep -q '^$vmid'" && return 0 || return 1 } # Get container status get_container_status() { local vmid=$1 ssh_ml110 "pct status $vmid 2>/dev/null | awk '{print \$2}'" || echo "unknown" } # Check if container is on target node is_on_target() { local vmid=$1 if ssh_ml110 "pvesh get /nodes/$TARGET_NODE/lxc/$vmid/status/current 2>/dev/null | grep -q 'status'"; then return 0 else return 1 fi } # Migrate a single container migrate_container() { local vmid=$1 log_info "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" log_info "Migrating container $vmid" log_info "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" # Check if already on target if is_on_target "$vmid"; then log_success "Container $vmid is already on $TARGET_NODE" return 0 fi # Check if container exists if ! check_container "$vmid"; then log_error "Container $vmid not found on $SOURCE_NODE" return 1 fi # Get container name local name=$(ssh_ml110 "pct list | grep '^$vmid' | awk '{print \$4}'") log_info "Container name: $name" # Get current status local status=$(get_container_status "$vmid") log_info "Current status: $status" # Stop container if running if [ "$status" == "running" ]; then log_info "Stopping container $vmid..." ssh_ml110 "pct stop $vmid" || { log_warn "pct stop failed, trying graceful shutdown..." ssh_ml110 "pvesh create /nodes/$SOURCE_NODE/lxc/$vmid/status/shutdown --timeout 30" || true } # Wait for stop log_info "Waiting for container to stop..." for i in {1..12}; do sleep 2 status=$(get_container_status "$vmid") if [ "$status" == "stopped" ]; then log_success "Container stopped" break fi if [ $i -lt 12 ]; then log_info "Still stopping... (attempt $i/12)" fi done if [ "$status" != "stopped" ]; then log_warn "Container may still be running, proceeding anyway..." fi fi # Perform migration log_info "Migrating container $vmid from $SOURCE_NODE to $TARGET_NODE..." log_info "Target storage: $TARGET_STORAGE" # Use pvesh API to migrate with storage specification # pct migrate doesn't support --storage, so we use the API log_info "Starting migration (this may take several minutes)..." local migrate_output=$(ssh_ml110 "pvesh create /nodes/$SOURCE_NODE/lxc/$vmid/migrate --target $TARGET_NODE --storage $TARGET_STORAGE --online 0" 2>&1) local migrate_exit=$? if [ $migrate_exit -eq 0 ]; then log_success "Migration command completed for container $vmid" # Wait and verify log_info "Waiting for migration to complete..." local migrated=false for i in {1..30}; do sleep 5 # Check if container is now on target node if is_on_target "$vmid"; then local target_status=$(ssh_ml110 "pvesh get /nodes/$TARGET_NODE/lxc/$vmid/status/current 2>/dev/null | jq -r '.status' 2>/dev/null" || echo "unknown") log_success "Container $vmid is now on $TARGET_NODE (status: $target_status)" migrated=true break fi if [ $i -lt 30 ]; then log_info "Still migrating... (attempt $i/30, ~$((i*5)) seconds)" fi done if [ "$migrated" == "false" ]; then log_warn "Migration may still be in progress or failed" log_info "Check migration status manually:" log_info " ssh root@$PROXMOX_HOST_ML110 'pvesh get /nodes/$TARGET_NODE/lxc/$vmid/status/current'" return 1 fi return 0 else log_error "Migration failed for container $vmid" log_info "Error output: $migrate_output" return 1 fi } # Main execution main() { echo "" log_header log_info "Proxmox Container Migration to r630-01" log_info "Source: $SOURCE_NODE -> Target: $TARGET_NODE" log_info "Target Storage: $TARGET_STORAGE" log_header echo "" log_info "Containers to migrate: ${CONTAINERS[*]}" echo "" # Check connectivity log_info "Checking connectivity to $SOURCE_NODE..." if ! sshpass -p "$ML110_PASS" ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=accept-new root@"$PROXMOX_HOST_ML110" "echo 'connected'" 2>/dev/null; then log_error "Cannot connect to $SOURCE_NODE" exit 1 fi log_success "Connected to $SOURCE_NODE" echo "" # Verify containers exist log_info "Verifying containers exist..." local found=0 for vmid in "${CONTAINERS[@]}"; do if check_container "$vmid"; then local name=$(ssh_ml110 "pct list | grep '^$vmid' | awk '{print \$4}'") local status=$(get_container_status "$vmid") log_success "Container $vmid found: $name (status: $status)" found=$((found + 1)) else log_warn "Container $vmid not found, skipping..." fi done if [ $found -eq 0 ]; then log_error "No containers found to migrate" exit 1 fi echo "" # Check for non-interactive mode if [[ "${NON_INTERACTIVE:-}" != "1" ]] && [[ -t 0 ]]; then read -p "Continue with migration? (y/N): " -n 1 -r echo "" if [[ ! $REPLY =~ ^[Yy]$ ]]; then log_info "Operation cancelled" exit 0 fi fi echo "" # Migrate each container local failed=0 local succeeded=0 for vmid in "${CONTAINERS[@]}"; do if migrate_container "$vmid"; then succeeded=$((succeeded + 1)) else failed=$((failed + 1)) fi echo "" done # Summary log_header log_info "Migration Summary" log_header echo "" log_info "Succeeded: $succeeded" log_info "Failed: $failed" echo "" # Final verification log_info "Final container locations:" for vmid in "${CONTAINERS[@]}"; do if is_on_target "$vmid"; then local target_status=$(ssh_ml110 "pvesh get /nodes/$TARGET_NODE/lxc/$vmid/status/current 2>/dev/null | jq -r '.status' 2>/dev/null" || echo "unknown") log_success "Container $vmid: $TARGET_NODE (status: $target_status)" else log_warn "Container $vmid: not on $TARGET_NODE" fi done echo "" if [ $failed -eq 0 ]; then log_success "All containers migrated successfully!" log_info "" log_info "Next steps:" log_info " 1. Verify containers on pve: ssh root@$PROXMOX_HOST_ML110 'pvesh get /nodes/$TARGET_NODE/lxc'" log_info " 2. Start containers if needed: ssh root@${PROXMOX_HOST_R630_01:-192.168.11.11} 'pct start '" exit 0 else log_warn "Some containers failed to migrate" exit 1 fi } main "$@"