diff --git a/migration/vif53-pin-boot-disable b/migration/vif53-pin-boot-disable new file mode 100644 index 0000000..91c4614 --- /dev/null +++ b/migration/vif53-pin-boot-disable @@ -0,0 +1,111 @@ +#!/bin/sh +# Make config.boot carry `vif 53 disable` while the RUNNING config keeps the +# 10 gig up. Run on the master. Idempotent. +# +# WHY THIS IS AWKWARD +# +# The convention is that BOTH routers' config.boot hold `vif 53 disable`, so a +# reboot in any order comes up unable to claim the cloned MAC +# (f0:9f:c2:12:9b:4f) and vrrp-wan-reconcile then enables it on whichever box +# holds the VIP. The master's RUNNING config must have it enabled -- it is +# carrying the WAN -- so config.boot and the running config must deliberately +# disagree. +# +# VyOS gives no clean way to express that. `save` writes the RUNNING config, +# not the candidate: setting the node, saving, then discarding was tested in +# labsim and config.boot came back without `disable`, the WAN untouched. So the +# only route is to genuinely disable it, save that, and re-enable -- a real, +# brief interruption of the 10 gig. +# +# WHAT THE INTERRUPTION ACTUALLY COSTS +# +# Not the internet, on a healthy pair: pppoe0 is up on the master and the +# failover route falls to it while bond0.53 is down, which is exactly the +# behaviour T5 proves in labsim (LAN back in 5s). Traffic moves to the slower +# line and back. Expect a few seconds, plus however long the ISP takes to +# re-issue the DHCP lease afterwards. +# +# IF THIS SCRIPT DIES HALFWAY it leaves the master with bond0.53 disabled -- +# which vrrp-wan-reconcile repairs within 30s ("MASTER with bond0.53 disabled +# -> enabling"). The failure mode is bounded by design, not by luck. +# +# sudo /config/vif53-pin-boot-disable do it +# sudo /config/vif53-pin-boot-disable --check report only, change nothing + +VIF=53 +BOOT=/config/config.boot + +cfg() { /opt/vyatta/bin/vyatta-op-cmd-wrapper show configuration commands 2>/dev/null; } +boot_has() { awk "/vif ${VIF} {/,/^ }/" "$BOOT" 2>/dev/null | grep -qc disable 2>/dev/null; } +boot_disable_count() { awk "/vif ${VIF} {/,/^ }/" "$BOOT" 2>/dev/null | grep -c disable; } +run_disable_count() { cfg | grep -c "vif ${VIF} disable"; } + +report() { + printf ' running config disable : %s\n' "$(run_disable_count)" + printf ' config.boot disable : %s\n' "$(boot_disable_count)" + printf ' bond0.%s address : %s\n' "$VIF" \ + "$(ip -4 addr show "bond0.${VIF}" 2>/dev/null | sed -n 's/.*inet \([0-9.]*\).*/\1/p')" +} + +if [ "${1:-}" = "--check" ]; then report; exit 0; fi + +if [ "$(boot_disable_count)" -ge 1 ]; then + echo " config.boot already pins 'vif ${VIF} disable' -- nothing to do" + report + exit 0 +fi + +# Refuse on a box that is not carrying the WAN: there the running config should +# already have `disable`, and a plain `save` is all that is needed. Doing the +# dance here would be pointless downtime. +if [ "$(run_disable_count)" -ge 1 ]; then + echo " this box already has 'vif ${VIF} disable' in the running config;" + echo " a plain 'save' is enough and costs nothing. Not touching the WAN." + exit 0 +fi + +# Serialise against vrrp-wan-reconcile by taking ITS lock. Without this the two +# commit at the same time and VyOS refuses one of them with "Configuration +# system temporarily locked due to another commit in progress" -- observed in +# labsim, where the `save` landed but the RE-ENABLE did not, leaving the master +# with its 10 gig down. The reconciler uses `flock -n` and simply skips a tick +# it cannot get, so holding this is cheap and safe. +exec 9>/run/vrrp-wan.lock +if ! flock -w 60 9; then + echo " could not take /run/vrrp-wan.lock within 60s -- is a commit stuck?" + echo " refusing to race vrrp-wan-reconcile for the config lock." + exit 1 +fi + +logger -t vif53-pin "pinning 'vif ${VIF} disable' into config.boot -- bond0.${VIF} will bounce" +echo " bouncing bond0.${VIF} to get 'disable' into config.boot..." +t0=$(date +%s) + +# 9>&- so the config session's long-lived unionfs-fuse child does not inherit +# the lock fd and hold it for ever -- the same trap vrrp-wan-reconcile documents. +/bin/vbash 9>&- <