#!/bin/bash
set -u
if [ "${FORCE_DEPRECATED:-no}" != "yes" ]; then
cat >&2 <<'EOF'
⛔ 本脚本已废弃,且拓扑与当前 br0+veth 方案互斥。
执行会写入 br-provider-mgmt.service,与 br0-provider-veth.service 争抢 enp2s0。
如确需使用(且已知风险),请显式覆盖:
FORCE_DEPRECATED=yes setsid /root/net-switch-egress.sh ...
当前方案请改用 deploy/install/60-network.sh(WITH_EGRESS_SWITCH=yes)。
EOF
exit 3
fi
IF=enp2s0
IP=192.168.3.88
PREFIX=24
GW=192.168.3.1
DNS=223.5.5.5
BR=br-provider
UNIT=/usr/lib/systemd/system/br-provider-mgmt.service
LOG=/root/net-switch.log
CONFIRM=/root/net-switch-OK
log() { echo "$(date '+%F %T') $*" | tee -a "$LOG"; }
[ "$(id -u)" = 0 ] || { echo "请以 root 运行"; exit 1; }
ip -4 addr show "$IF" | grep -q "$IP" || { log "!! $IF 上没有 $IP,可能已切换或配置不符,终止"; exit 1; }
rm -f "$CONFIRM"
log "=== 开始切换:$IF → OVS $BR(管理 IP $IP 迁移) ==="
log "启动看门狗(300s 内未确认则自动回滚)"
setsid /root/net-watchdog.sh 300 45 >/dev/null 2>&1 < /dev/null &
sleep 1
cat > "$UNIT" <<EOF
[Unit]
Description=Attach $IF to OVS $BR and restore management IP
After=network-online.target openvswitch.service
Wants=network-online.target
Requires=openvswitch.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/bash -c '\\
ovs-vsctl br-exists $BR || ovs-vsctl add-br $BR; \\
ovs-vsctl --may-exist add-port $BR $IF; \\
ip link set $IF up; ip link set $BR up; \\
ip addr add $IP/$PREFIX dev $BR 2>/dev/null || true; \\
ip route replace default via $GW dev $BR'
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload && log "持久化单元已写入:$UNIT"
log ">> 断网时刻开始"
ovs-vsctl --may-exist add-port "$BR" "$IF" || log "!! 挂端口失败"
ip addr flush dev "$IF" || log "!! 清空 $IF 地址失败"
ip link set "$IF" up
ip link set "$BR" up
ip addr add "$IP/$PREFIX" dev "$BR" || log "!! 桥上配 IP 失败"
ip route replace default via "$GW" dev "$BR" || log "!! 默认路由设置失败"
log ">> 切换动作完成,等待网络收敛"
sleep 8
if ! ip -4 addr show "$BR" | grep -q "$IP"; then
log "!! 桥上未出现 $IP,立即回滚"
/root/net-watchdog.sh 0 0 >/dev/null 2>&1 || true
exit 1
fi
log "桥上已持有 $IP"
OK=0
for i in $(seq 1 8); do
if ping -c 2 -W 3 "$GW" >/dev/null 2>&1; then OK=1; break; fi
log " 等待网关可达 ... ($i/8)"
sleep 4
done
if [ "$OK" = 1 ]; then
log "网关 $GW 可达 ✓"
else
log "!! 网关不可达,交由看门狗回滚(或立即手工会滚)"
fi
if [ "$OK" = 1 ]; then
for i in 1 2 3; do
code=$(curl -s -m 6 -o /dev/null -w '%{http_code}' "http://$IP:5000/v3/" 2>/dev/null)
log " keystone http://$IP:5000/v3/ -> $code"
[ "$code" = "200" ] && break
sleep 4
done
fi
cat <<EOF
================================================================
切换脚本执行完毕。请【另开新窗口】验证:
ip -4 addr show $BR | grep $IP
ip route show default
ping -c2 $GW
curl -s -o /dev/null -w '%{http_code}\n' http://$IP:5000/v3/ # 期望 200
若全部正常,务必执行确认(否则 300 秒后自动回滚):
touch $CONFIRM
systemctl enable --now br-provider-mgmt # 注册开机自愈
若异常,立即手工回滚:
systemctl disable --now br-provider-mgmt 2>/dev/null
ovs-vsctl --if-exists del-port $BR $IF
ip addr del $IP/$PREFIX dev $BR
ip route del default via $GW dev $BR
nmcli dev set $IF managed yes && nmcli con up $IF
================================================================
EOF
log "=== 脚本结束,等待人工确认 ==="