#!/bin/bash
# 网络切换看门狗:切换后若未确认连通性,自动还原物理网卡为普通 NM 管理网卡。
#
# 用法:
#   net-watchdog.sh [未确认等待秒数] [早期探测延迟秒数]
#   连通性验证通过后执行: touch /root/net-switch-OK   (阻止回滚)
#
# 可用环境变量覆盖(便于用 veth 做演练):
#   WD_DEV WD_IP WD_PREFIX WD_GW WD_BR WD_CONN WD_LOG WD_CONFIRM

set -u
DEV=${WD_DEV:-enp2s0}
IP=${WD_IP:-192.168.3.88}
PREFIX=${WD_PREFIX:-24}
GW=${WD_GW:-192.168.3.1}
BR=${WD_BR:-br-provider}
CONN=${WD_CONN:-$DEV}
LOG=${WD_LOG:-/root/net-watchdog.log}
CONFIRM=${WD_CONFIRM:-/root/net-switch-OK}

WAIT=${1:-300}           # 未确认等待时间
EARLY=${2:-40}           # 切换后早期网关探测延迟

log() { echo "$(date '+%F %T') $*" >>"$LOG"; logger -t net-watchdog "$*" 2>/dev/null; }

rm -f "$CONFIRM"
log "看门狗启动 dev=$DEV ip=$IP gw=$GW br=$BR wait=${WAIT}s early=${EARLY}s"

rollback() {
    log "开始回滚 ..."
    ovs-vsctl --if-exists del-port "$BR" "$DEV" >>"$LOG" 2>&1
    ip addr del "$IP/$PREFIX" dev "$BR" >>"$LOG" 2>&1
    ip route del default via "$GW" dev "$BR" >>"$LOG" 2>&1
    nmcli dev set "$DEV" managed yes >>"$LOG" 2>&1
    nmcli con mod "$CONN" connection.autoconnect yes >>"$LOG" 2>&1
    nmcli con up "$CONN" >>"$LOG" 2>&1 || nmcli dev connect "$DEV" >>"$LOG" 2>&1
    sleep 5
    if ! ip -4 addr show "$DEV" | grep -q "$IP"; then
        ip addr add "$IP/$PREFIX" dev "$DEV" >>"$LOG" 2>&1
        ip link set "$DEV" up >>"$LOG" 2>&1
        ip route replace default via "$GW" dev "$DEV" >>"$LOG" 2>&1
        log "NM 未恢复,已手工补回 IP/路由"
    fi
    local ok=不通
    timeout 6 ping -c 1 -W 2 "$GW" >/dev/null 2>&1 && ok=通
    log "回滚完成 dev=$DEV ip=$(ip -4 addr show "$DEV" 2>/dev/null | grep -o 'inet [0-9./]*' | head -1) 网关=$ok"
}

sleep "$EARLY"
if [ ! -f "$CONFIRM" ]; then
    if ! timeout 8 ping -c 2 -W 3 "$GW" >/dev/null 2>&1; then
        log "早期探测失败:网关 $GW 不可达,立即回滚"
        rollback; exit 1
    fi
    log "早期探测通过:网关可达"
fi

n=$WAIT
while [ "$n" -gt 0 ]; do
    [ -f "$CONFIRM" ] && { log "已确认,看门狗退出"; exit 0; }
    sleep 5; n=$((n - 5))
done
[ -f "$CONFIRM" ] && { log "已确认,看门狗退出"; exit 0; }

log "${WAIT}s 内未确认,执行自动回滚"
rollback