#!/usr/bin/env bash # Comprehensive IP audit and hostname migration preparation # Audits all VMs/containers across all Proxmox hosts for IP conflicts 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 SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$SCRIPT_DIR/load-physical-inventory.sh" 2>/dev/null || true 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}[⚠]${NC} $1"; } log_error() { echo -e "${RED}[✗]${NC} $1"; } log_section() { echo -e "\n${CYAN}=== $1 ===${NC}\n"; } declare -A HOSTS HOSTS[ml110]="${PROXMOX_HOST_ML110:-192.168.11.10}:${PROXMOX_PASS_ML110:-L@kers2010}" HOSTS[ml110]="${PROXMOX_HOST_ML110:-192.168.11.10}:${PROXMOX_PASS_ML110:-password}" HOSTS[r630-01]="${PROXMOX_HOST_R630_01:-192.168.11.11}:${PROXMOX_PASS_R630_01:-password}" HOSTS[r630-02]="${PROXMOX_HOST_R630_02:-192.168.11.12}:${PROXMOX_PASS_R630_02:-password}" TMPFILE=$(mktemp) trap "rm -f $TMPFILE" EXIT log_section "Comprehensive IP Address Audit" # Collect all VM/container IPs for hostname in "${!HOSTS[@]}"; do ip="${HOSTS[$hostname]%%:*}" password="${HOSTS[$hostname]#*:}" log_info "Scanning ${hostname} (${ip})..." sshpass -p "$password" ssh -o StrictHostKeyChecking=no -o ConnectTimeout=5 root@"$ip" bash <<'ENDSSH' 2>/dev/null || { log_warn "Could not connect to ${hostname}" continue } pct list 2>/dev/null | awk 'NR>1 {print $1, $3}' | while read vmid status; do ip=$(pct config "$vmid" 2>/dev/null | sed -n 's/.*ip=\([^,]*\).*/\1/p' | head -1 || echo "N/A") hostname_vm=$(pct config "$vmid" 2>/dev/null | sed -n 's/.*hostname=\([^,]*\).*/\1/p' | head -1 || echo "N/A") if [[ "$ip" != "N/A" ]] && [[ "$ip" != "dhcp" ]] && [[ -n "$ip" ]]; then ip_base="${ip%/*}" echo "${hostname}:CT:${vmid}:${ip_base}:${hostname_vm}:${status}" elif [[ "$ip" == "dhcp" ]]; then echo "${hostname}:CT:${vmid}:DHCP:${hostname_vm}:${status}" fi done ENDSSH done > "$TMPFILE" log_section "IP Address Summary" printf "%-15s %-8s %-6s %-20s %-15s %-10s\n" "IP Address" "Type" "VMID" "Hostname" "Proxmox Host" "Status" echo "--------------------------------------------------------------------------------" sort -t: -k4 -V "$TMPFILE" | while IFS=: read -r proxmox_host type vmid ip_addr hostname_vm status; do if [[ "$ip_addr" != "DHCP" ]]; then printf "%-15s %-8s %-6s %-20s %-15s %-10s\n" "$ip_addr" "$type" "$vmid" "$hostname_vm" "$proxmox_host" "$status" fi done # Check for conflicts log_section "Conflict Detection" declare -A IP_USAGE conflict_count=0 while IFS=: read -r proxmox_host type vmid ip_addr hostname_vm status; do if [[ "$ip_addr" != "DHCP" ]] && [[ -n "$ip_addr" ]]; then key="${proxmox_host}:${type}:${vmid}" if [[ -n "${IP_USAGE[$ip_addr]:-}" ]]; then IP_USAGE[$ip_addr]="${IP_USAGE[$ip_addr]},$key" conflict_count=$((conflict_count + 1)) else IP_USAGE[$ip_addr]="$key" fi fi done < "$TMPFILE" if [[ $conflict_count -gt 0 ]]; then log_error "Found $conflict_count IP conflict(s):" for ip in "${!IP_USAGE[@]}"; do usage="${IP_USAGE[$ip]}" if [[ "$usage" == *","* ]]; then log_error " IP $ip used by: $usage" fi done else log_success "No IP conflicts detected!" fi # Check for invalid IPs log_section "Invalid IP Detection" invalid_count=0 while IFS=: read -r proxmox_host type vmid ip_addr hostname_vm status; do if [[ "$ip_addr" =~ ^192\.168\.11\.(0|255)$ ]]; then invalid_count=$((invalid_count + 1)) log_error "INVALID: $ip_addr (network/broadcast) - VMID $vmid on $proxmox_host" fi done < "$TMPFILE" if [[ $invalid_count -eq 0 ]]; then log_success "No invalid IPs detected!" fi # Summary log_section "Audit Summary" total_vms=$(grep -v "DHCP" "$TMPFILE" | wc -l) dhcp_vms=$(grep "DHCP" "$TMPFILE" | wc -l) echo "Total VMs/Containers with static IPs: $total_vms" echo "Total VMs/Containers with DHCP: $dhcp_vms" echo "IP Conflicts: $conflict_count" echo "Invalid IPs: $invalid_count" echo "" if [[ $conflict_count -eq 0 ]] && [[ $invalid_count -eq 0 ]]; then log_success "✅ IP audit passed!" exit 0 else log_error "❌ IP audit found issues!" exit 1 fi