#!/bin/bash # finish-host.sh - applies ALL remaining changes to a host and verifies. # # Steps: # 1. Start all VMs (triggers NFS lazy-mount) # 2. Wait for NFS mounts to appear # 3. Verify NFS nconnect=4 + noatime # 4. Apply bond0 xmit_hash_policy=layer3+4 # 5. Full end-to-end verification # # Usage: bash finish-host.sh [--apply] # Default is dry-run (starts VMs + shows what bond change would do, but doesn't edit interfaces) set -uo pipefail HOST="${1:-}" MODE="${2:-dryrun}" [ "$MODE" = "--apply" ] && MODE="apply" || MODE="dryrun" if [ -z "$HOST" ]; then echo "Usage: $0 [--apply]" exit 1 fi SSH_OPTS=(-o BatchMode=yes -o ConnectTimeout=8 -o ServerAliveInterval=10 -o StrictHostKeyChecking=accept-new) SCRIPT_DIR="/home/reachableceo/projects/perfopt/scripts" echo "===================================================================" echo " finish-host.sh — $HOST (mode: $MODE)" echo "===================================================================" echo "" # ========================================================================= # STEP 1: Start all VMs # ========================================================================= echo "=== STEP 1: Start all VMs on $HOST ===" # Get list of all VMs (not just stopped — start is idempotent) vm_list=$(ssh "${SSH_OPTS[@]}" "root@$HOST" 'qm list 2>/dev/null | awk "NR>1{print \$1}"') for vmid in $vm_list; do status=$(ssh "${SSH_OPTS[@]}" "root@$HOST" "qm status $vmid 2>/dev/null | awk '{print \$2}'") if [ "$status" != "running" ]; then echo " Starting VM $vmid..." ssh "${SSH_OPTS[@]}" "root@$HOST" "qm start $vmid" 2>&1 | sed 's/^/ /' else echo " VM $vmid already running" fi done echo "" echo " Waiting 15s for VMs to boot and trigger NFS mounts..." sleep 15 echo "" echo "--- VM status after start ---" ssh "${SSH_OPTS[@]}" "root@$HOST" 'qm list 2>/dev/null' # ========================================================================= # STEP 2: Verify NFS mounts came back with nconnect=4 # ========================================================================= echo "" echo "=== STEP 2: Verify NFS mounts with nconnect=4 ===" ssh "${SSH_OPTS[@]}" "root@$HOST" 'nfsstat -m 2>/dev/null' | head -30 echo "" echo "--- NFS TCP connections to :2049 ---" ssh "${SSH_OPTS[@]}" "root@$HOST" 'ss -tn state established "( dport = :2049 )" 2>/dev/null' conn_count=$(ssh "${SSH_OPTS[@]}" "root@$HOST" 'ss -tn state established "( dport = :2049 )" 2>/dev/null | tail -n +2 | wc -l') echo " Total NFS TCP connections: $conn_count" # ========================================================================= # STEP 3: Apply bond0 hash policy # ========================================================================= echo "" echo "=== STEP 3: Apply bond0 xmit_hash_policy=layer3+4 (mode: $MODE) ===" # Upload the bond hash script scp "${SSH_OPTS[@]}" "$SCRIPT_DIR/apply-bond-hash.sh" "root@$HOST:/root/apply-bond-hash.sh" >/dev/null 2>&1 if [ "$MODE" = "apply" ]; then ssh "${SSH_OPTS[@]}" "root@$HOST" 'chmod +x /root/apply-bond-hash.sh && bash /root/apply-bond-hash.sh --apply' 2>&1 else ssh "${SSH_OPTS[@]}" "root@$HOST" 'chmod +x /root/apply-bond-hash.sh && bash /root/apply-bond-hash.sh' 2>&1 fi # ========================================================================= # STEP 4: Full verification # ========================================================================= echo "" echo "=== STEP 4: Full end-to-end verification ===" echo "" echo "--- Uptime ---" ssh "${SSH_OPTS[@]}" "root@$HOST" 'uptime' echo "" echo "--- CPU governor ---" ssh "${SSH_OPTS[@]}" "root@$HOST" 'cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor 2>/dev/null || echo "(no cpufreq driver)"' echo "" echo "--- vm.swappiness ---" ssh "${SSH_OPTS[@]}" "root@$HOST" 'sysctl vm.swappiness' echo "" echo "--- TCP BBR ---" ssh "${SSH_OPTS[@]}" "root@$HOST" 'sysctl net.ipv4.tcp_congestion_control net.core.default_qdisc' echo "" echo "--- tuned profile ---" ssh "${SSH_OPTS[@]}" "root@$HOST" 'tuned-adm active 2>/dev/null' echo "" echo "--- bond0 hash policy + LACP state ---" ssh "${SSH_OPTS[@]}" "root@$HOST" 'cat /proc/net/bonding/bond0 2>/dev/null | head -25' echo "" echo "--- NFS mount options (first 3 mounts) ---" ssh "${SSH_OPTS[@]}" "root@$HOST" 'nfsstat -m 2>/dev/null | head -24' echo "" echo "--- NFS TCP connections (expect 4 per server × 2 servers = 8) ---" ssh "${SSH_OPTS[@]}" "root@$HOST" 'ss -tn state established "( dport = :2049 )" 2>/dev/null' nfs_conns=$(ssh "${SSH_OPTS[@]}" "root@$HOST" 'ss -tn state established "( dport = :2049 )" 2>/dev/null | tail -n +2 | wc -l') echo " Count: $nfs_conns" echo "" echo "--- VMs running ---" ssh "${SSH_OPTS[@]}" "root@$HOST" 'qm list 2>/dev/null' echo "" echo "--- Failed services ---" ssh "${SSH_OPTS[@]}" "root@$HOST" 'systemctl --failed --no-legend 2>/dev/null | head -10' echo "" echo "--- Network interfaces (speed/duplex/mtu) ---" ssh "${SSH_OPTS[@]}" "root@$HOST" 'for ifc in bond0 nic0 nic1 nic2 vmbr0 datanet; do [ -d "/sys/class/net/$ifc" ] && printf "%-12s speed=%-8s duplex=%-8s mtu=%s\n" "$ifc" "$(cat /sys/class/net/$ifc/speed 2>/dev/null)" "$(cat /sys/class/net/$ifc/duplex 2>/dev/null)" "$(cat /sys/class/net/$ifc/mtu 2>/dev/null)"; done' echo "" echo "===================================================================" echo " COMPLETE — $HOST" echo "==================================================================="