Some checks failed
Test / test (push) Has been cancelled
Co-authored-by: Cursor <cursoragent@cursor.com>
287 lines
8.2 KiB
Bash
Executable File
287 lines
8.2 KiB
Bash
Executable File
#!/bin/bash
|
|
# Validate Proxmox Network Setup Prerequisites
|
|
# Checks system readiness for network configuration
|
|
|
|
# Don't use set -e since we handle errors manually with pass/fail system
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m' # No Color
|
|
|
|
PASS_COUNT=0
|
|
FAIL_COUNT=0
|
|
WARN_COUNT=0
|
|
|
|
pass() {
|
|
echo -e "${GREEN}[PASS]${NC} $1"
|
|
((PASS_COUNT++))
|
|
}
|
|
|
|
fail() {
|
|
echo -e "${RED}[FAIL]${NC} $1"
|
|
((FAIL_COUNT++))
|
|
}
|
|
|
|
warn() {
|
|
echo -e "${YELLOW}[WARN]${NC} $1"
|
|
((WARN_COUNT++))
|
|
}
|
|
|
|
info() {
|
|
echo -e "${BLUE}[INFO]${NC} $1"
|
|
}
|
|
|
|
check_root() {
|
|
info "Checking root access..."
|
|
if [ "$EUID" -eq 0 ]; then
|
|
pass "Running as root"
|
|
else
|
|
fail "Not running as root (required for network configuration)"
|
|
fi
|
|
}
|
|
|
|
check_proxmox() {
|
|
info "Checking Proxmox VE installation..."
|
|
if command -v pveversion &> /dev/null; then
|
|
PVE_VERSION=$(pveversion 2>&1 || echo "unknown")
|
|
pass "Proxmox VE installed: $PVE_VERSION"
|
|
else
|
|
fail "Proxmox VE not found (pveversion command not available)"
|
|
fi
|
|
}
|
|
|
|
get_interface_speed() {
|
|
local iface=$1
|
|
if command -v ethtool &>/dev/null; then
|
|
local speed=$(ethtool "$iface" 2>/dev/null | grep -i "Speed:" | awk '{print $2}' | sed 's/[^0-9]//g')
|
|
if [ -n "$speed" ]; then
|
|
echo "$speed"
|
|
return
|
|
fi
|
|
fi
|
|
local speed=$(cat "/sys/class/net/$iface/speed" 2>/dev/null)
|
|
if [ -n "$speed" ] && [ "$speed" != "-1" ]; then
|
|
echo "$speed"
|
|
return
|
|
fi
|
|
echo "unknown"
|
|
}
|
|
|
|
check_interfaces() {
|
|
info "Checking physical network interfaces..."
|
|
|
|
PHYSICAL_IFACES=()
|
|
declare -A IFACE_SPEEDS
|
|
|
|
for iface in /sys/class/net/*; do
|
|
iface_name=$(basename "$iface")
|
|
|
|
# Skip loopback, virtual interfaces, bridges, bonds, and VLANs
|
|
if [[ "$iface_name" == "lo" ]] || \
|
|
[[ -L "$iface/device" ]] && [[ ! -d "$iface/device" ]] || \
|
|
[[ -d "$iface/bridge" ]] || \
|
|
[[ -d "$iface/bonding" ]] || \
|
|
[[ "$iface_name" =~ \. ]]; then
|
|
continue
|
|
fi
|
|
|
|
if [ -d "$iface/device" ] || [ -L "$iface/device" ]; then
|
|
PHYSICAL_IFACES+=("$iface_name")
|
|
IFACE_SPEEDS["$iface_name"]=$(get_interface_speed "$iface_name")
|
|
fi
|
|
done
|
|
|
|
IFS=$'\n' PHYSICAL_IFACES=($(sort <<<"${PHYSICAL_IFACES[*]}"))
|
|
unset IFS
|
|
|
|
if [ ${#PHYSICAL_IFACES[@]} -eq 0 ]; then
|
|
fail "No physical interfaces detected"
|
|
elif [ ${#PHYSICAL_IFACES[@]} -eq 1 ]; then
|
|
fail "Only 1 physical interface detected (need at least 2)"
|
|
info " Found: ${PHYSICAL_IFACES[*]}"
|
|
else
|
|
pass "Found ${#PHYSICAL_IFACES[@]} physical interface(s)"
|
|
info " All interfaces and speeds:"
|
|
for iface in "${PHYSICAL_IFACES[@]}"; do
|
|
speed="${IFACE_SPEEDS[$iface]}"
|
|
if [ "$speed" = "1000" ]; then
|
|
info " $iface: 1 Gbps ⭐ (1 Gbps port)"
|
|
elif [ "$speed" != "unknown" ] && [ -n "$speed" ]; then
|
|
info " $iface: ${speed} Mbps"
|
|
else
|
|
info " $iface: speed unknown"
|
|
fi
|
|
done
|
|
|
|
# Check for 1 Gbps interfaces
|
|
GIGABIT_COUNT=0
|
|
for iface in "${PHYSICAL_IFACES[@]}"; do
|
|
if [ "${IFACE_SPEEDS[$iface]}" = "1000" ]; then
|
|
((GIGABIT_COUNT++))
|
|
fi
|
|
done
|
|
|
|
if [ $GIGABIT_COUNT -ge 2 ]; then
|
|
pass "Found $GIGABIT_COUNT 1 Gbps interface(s) - will use these for vmbr0 and vmbr1"
|
|
elif [ $GIGABIT_COUNT -eq 1 ]; then
|
|
warn "Found only 1 1 Gbps interface - may need manual specification"
|
|
else
|
|
warn "No 1 Gbps interfaces detected (may need link for speed detection)"
|
|
info " Script will use first two interfaces by default"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
check_existing_bridges() {
|
|
info "Checking existing bridges..."
|
|
|
|
EXISTING_BRIDGES=$(ip link show type bridge 2>/dev/null | grep -oP '^\d+: \K[^:]+' || echo "")
|
|
|
|
if [ -z "$EXISTING_BRIDGES" ]; then
|
|
pass "No existing bridges found (clean setup)"
|
|
else
|
|
warn "Existing bridges detected:"
|
|
echo "$EXISTING_BRIDGES" | while read bridge; do
|
|
info " - $bridge"
|
|
done
|
|
|
|
if echo "$EXISTING_BRIDGES" | grep -q "vmbr0\|vmbr1"; then
|
|
warn "vmbr0 or vmbr1 already exists - configuration will modify them"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
check_dhcp_clients() {
|
|
info "Checking DHCP client availability..."
|
|
|
|
if command -v dhclient &> /dev/null; then
|
|
pass "dhclient found: $(dhclient --version 2>&1 | head -1)"
|
|
elif command -v dhcpcd &> /dev/null; then
|
|
pass "dhcpcd found: $(dhcpcd --version 2>&1 | head -1)"
|
|
else
|
|
warn "No DHCP client found (dhclient or dhcpcd) - DHCP may not work"
|
|
fi
|
|
}
|
|
|
|
check_network_tools() {
|
|
info "Checking network management tools..."
|
|
|
|
if command -v ifup &> /dev/null && command -v ifdown &> /dev/null; then
|
|
pass "ifupdown tools available"
|
|
else
|
|
fail "ifupdown tools not found (required for network configuration)"
|
|
fi
|
|
|
|
if command -v ifreload &> /dev/null; then
|
|
pass "ifreload command available"
|
|
else
|
|
warn "ifreload command not found (may need to use ifup/ifdown instead)"
|
|
fi
|
|
}
|
|
|
|
check_network_service() {
|
|
info "Checking network service status..."
|
|
|
|
if systemctl is-active --quiet networking 2>/dev/null; then
|
|
pass "Networking service is active"
|
|
elif systemctl is-active --quiet NetworkManager 2>/dev/null; then
|
|
warn "NetworkManager is active (may conflict with ifupdown configuration)"
|
|
else
|
|
warn "Network service status unclear"
|
|
fi
|
|
}
|
|
|
|
check_config_backup() {
|
|
info "Checking if configuration backup exists..."
|
|
|
|
BACKUP_COUNT=$(ls -1 /etc/network/interfaces.backup.* 2>/dev/null | wc -l)
|
|
|
|
if [ "$BACKUP_COUNT" -gt 0 ]; then
|
|
info " Found $BACKUP_COUNT backup file(s)"
|
|
pass "Backup files exist"
|
|
else
|
|
info " No existing backups found (will be created during configuration)"
|
|
pass "Ready to create backups"
|
|
fi
|
|
}
|
|
|
|
show_system_info() {
|
|
info "System Information:"
|
|
echo " Hostname: $(hostname)"
|
|
echo " OS: $(lsb_release -d 2>/dev/null | cut -f2 || cat /etc/os-release | grep PRETTY_NAME | cut -d'"' -f2)"
|
|
echo " Kernel: $(uname -r)"
|
|
|
|
# Try to detect server model
|
|
if [ -f /sys/class/dmi/id/product_name ]; then
|
|
VENDOR=$(cat /sys/class/dmi/id/sys_vendor 2>/dev/null || echo "Unknown")
|
|
PRODUCT=$(cat /sys/class/dmi/id/product_name 2>/dev/null || echo "Unknown")
|
|
echo " Server: $VENDOR $PRODUCT"
|
|
fi
|
|
}
|
|
|
|
show_current_network() {
|
|
info "Current Network Configuration:"
|
|
echo ""
|
|
echo "=== Interfaces ==="
|
|
ip link show | grep -E "^[0-9]+:" | sed 's/^/ /'
|
|
echo ""
|
|
echo "=== IP Addresses ==="
|
|
ip addr show | grep -E "^[0-9]+:|inet " | sed 's/^/ /'
|
|
echo ""
|
|
echo "=== Routes ==="
|
|
ip route show | sed 's/^/ /'
|
|
}
|
|
|
|
main() {
|
|
echo "========================================="
|
|
echo "Proxmox Network Setup Validation"
|
|
echo "========================================="
|
|
echo ""
|
|
|
|
show_system_info
|
|
echo ""
|
|
|
|
check_root
|
|
check_proxmox
|
|
check_interfaces
|
|
check_existing_bridges
|
|
check_dhcp_clients
|
|
check_network_tools
|
|
check_network_service
|
|
check_config_backup
|
|
|
|
echo ""
|
|
echo "========================================="
|
|
echo "Validation Summary"
|
|
echo "========================================="
|
|
echo -e "${GREEN}Passed:${NC} $PASS_COUNT"
|
|
echo -e "${YELLOW}Warnings:${NC} $WARN_COUNT"
|
|
echo -e "${RED}Failed:${NC} $FAIL_COUNT"
|
|
echo ""
|
|
|
|
if [ $FAIL_COUNT -eq 0 ]; then
|
|
if [ $WARN_COUNT -eq 0 ]; then
|
|
echo -e "${GREEN}✓ System is ready for network configuration${NC}"
|
|
exit 0
|
|
else
|
|
echo -e "${YELLOW}⚠ System is ready but has warnings (review above)${NC}"
|
|
exit 0
|
|
fi
|
|
else
|
|
echo -e "${RED}✗ System is not ready (fix failures above)${NC}"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# If --show-network flag is provided, show current network config
|
|
if [[ "$1" == "--show-network" ]]; then
|
|
show_current_network
|
|
exit 0
|
|
fi
|
|
|
|
main "$@"
|
|
|