From 594213138e6d412b8eb9e92d5862b2ba988a477e Mon Sep 17 00:00:00 2001 From: Andreas Wrede Date: Wed, 23 Sep 2026 21:04:33 -0400 Subject: [PATCH] apply-network fix round 1: reload networkd after the NM reload on rollback; harden post-check tests Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01KqhjP7nud5gdBg25zCiRk9 --- deploy.sh | 4 ++-- tests/check-templates.sh | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/deploy.sh b/deploy.sh index b86cf61..cfaf7f8 100755 --- a/deploy.sh +++ b/deploy.sh @@ -390,7 +390,7 @@ PY # configured/configuring holds a stale in-memory claim (cured by networkctl reload). # Before the apply networkd legitimately owns it: say nothing. if [ "$f" = matches ] && [ -e "$sysnet/$STARLINK_IFACE" ] && command -v networkctl >/dev/null 2>&1; then - out=$(networkctl --no-pager --no-legend list 2>/dev/null | awk -v i="$STARLINK_IFACE" '$2 == i { print $5; exit }') || out= + out=$(networkctl --no-pager --no-legend list 2>/dev/null | awk -v i="$STARLINK_IFACE" '$2 == i { s = $5 } END { print s }') case "$out" in configured|configuring) warn "post-deploy: networkd still manages $STARLINK_IFACE although NetworkManager owns it — run: networkctl reload" ;; unmanaged) echo " ok networkd leaves $STARLINK_IFACE to NetworkManager" ;; @@ -545,8 +545,8 @@ restore() { # restore : put the pre-run netplan back, re-check connecti [ ! -f "\$nd/10-dhcp-all-interfaces.yaml.vanlink-disabled" ] || mv "\$nd/10-dhcp-all-interfaces.yaml.vanlink-disabled" "\$nd/10-dhcp-all-interfaces.yaml" fi timeout -k $AN_KILL_T $AN_GEN_T netplan generate && timeout -k $AN_KILL_T $AN_APPLY_T netplan apply || { [ "\$rb" != ok ] || rb=APPLY-FAILED; } - nd_reload # the old config is back: networkd's in-memory state changes the other way [ ! -f "\$ncd/$pc" ] || timeout $AN_NM_T nmcli general reload conf || echo "nmcli general reload conf failed" + nd_reload # NM has let go of the port; now networkd, with the old config back, claims it (after the NM reload, not before) # the re-apply restarted networkd too, which can drop br0's members (as on the forward path; not gating) if timeout $AN_NM_T systemctl cat van-br0-setup >/dev/null 2>&1; then timeout $AN_RESTART_T systemctl restart van-br0-setup || echo "van-br0-setup restart failed (continuing)" diff --git a/tests/check-templates.sh b/tests/check-templates.sh index 68d3c92..fb5f0b1 100755 --- a/tests/check-templates.sh +++ b/tests/check-templates.sh @@ -415,6 +415,9 @@ STUB l_ap2=$(grep -n '^netplan apply' "$sb/calls" | sed -n 2p | cut -d: -f1 || true); l_rl2=$(grep -n '^nmcli general reload conf$' "$sb/calls" | sed -n 2p | cut -d: -f1 || true) [ -n "$l_ap2" ] && [ -n "$l_rl2" ] && [ "$l_ap2" -lt "$l_rl2" ] && ok "apply helper stage1: NM conf reloaded after the rollback apply" || bad "apply helper stage1: no NM conf reload after the rollback apply (apply '$l_ap2', reload '$l_rl2')" l_nr2=$(grep -n '^networkctl reload$' "$sb/calls" | sed -n 2p | cut -d: -f1 || true) + [ -n "$l_rl2" ] && [ -n "$l_nr2" ] && [ "$l_rl2" -lt "$l_nr2" ] && ok "apply helper stage1: NM conf reload before the networkd reload on rollback" || bad "apply helper stage1: networkd reload not after the NM conf reload (nm '$l_rl2', networkd '$l_nr2')" + l_b2=$(grep -n '^systemctl restart van-br0-setup$' "$sb/calls" | sed -n 2p | cut -d: -f1 || true) + [ -n "$l_b2" ] && [ "$l_nr2" -lt "$l_b2" ] && ok "apply helper stage1: networkd reload before the van-br0-setup restart" || bad "apply helper stage1: networkd reload after van-br0-setup restart" [ -n "$l_ap2" ] && [ -n "$l_nr2" ] && [ "$l_ap2" -lt "$l_nr2" ] && ok "apply helper stage1: networkctl reload after the rollback apply" || bad "apply helper stage1: no networkctl reload after the rollback apply (apply '$l_ap2', reload '$l_nr2')" sed -n '/restoring/,$p' "$sb/log" | grep -q '^networkd still manages' && bad "apply helper rollback: 'still manages' note belongs to the forward path only" || ok "apply helper rollback: no 'still manages' note" for m in '--- diagnostics: stage 1' 'STUB-DIAG-NM' 'routers = 192.168.100.1' 'STUB-NETWORKCTL-STATUS' 'STUB-ADDR inet' 'default via 192.168.100.1 dev enP2p33s0'; do @@ -614,7 +617,7 @@ chmod +x "$tc/stub/networkctl" for x in /usr/bin/* /bin/*; do [ "${x##*/}" = networkctl ] || ln -sf "$x" "$tc/nostub/${x##*/}" 2>/dev/null || true; done nd() { # nd [netplan-state: matches|missing] [ "${3:-matches}" = matches ] && cp "$tc/np-ok.yaml" "$tc/np.yaml" || rm -f "$tc/np.yaml" - PATH="$1:/usr/bin:/bin" STUB_STAR="$STAR" STUB_SETUP="$2" STUB_DEV="$tc/dev" STUB_CONN="$tc/conn" VANLINK_NM_DIR="$tc/nm" VANLINK_SYSNET="$tc/sys3" \ + PATH="${4:-$1:/usr/bin:/bin}" STUB_STAR="$STAR" STUB_SETUP="$2" STUB_DEV="$tc/dev" STUB_CONN="$tc/conn" VANLINK_NM_DIR="$tc/nm" VANLINK_SYSNET="$tc/sys3" \ VANLINK_WAN_NETPLAN="$tc/np.yaml" VANLINK_APPLY_STATUS="$tc/none" POSTCHECK_WAIT=0 ./deploy.sh --post-check hosts/van.conf 2>&1 | sed '/^== warnings ==$/,$d' || true } VANLINK_CONF=hosts/van.conf ./deploy.sh --render-wan-netplan > "$tc/np-ok.yaml" @@ -624,7 +627,7 @@ nd "$tc/stub" configuring | grep -qF -- "$W" && ok "19h: matches + configuring - o=$(nd "$tc/stub" unmanaged) echo "$o" | grep -qF " ok networkd leaves $STAR to NetworkManager" && ! echo "$o" | grep -q 'networkd still manages' && ok "19h: matches + unmanaged -> ok" || bad "19h: matches + unmanaged ok line missing" nd "$tc/stub" configured missing | grep -qE 'networkd (still manages|leaves)' && bad "19h: netplan not matching must print nothing about networkd" || ok "19h: netplan missing + configured -> nothing" -nd "$tc/nostub" configured | grep -qE 'networkd (still manages|leaves)' && bad "19h: no networkctl must print nothing" || ok "19h: no networkctl -> nothing" +nd "$tc/nostub" configured matches "$tc/nostub" | grep -qE 'networkd (still manages|leaves)' && bad "19h: no networkctl must print nothing" || ok "19h: no networkctl -> nothing" rmdir "$tc/sys3/$STAR" nd "$tc/stub" configured | grep -qE 'networkd (still manages|leaves)' && bad "19h: absent port must print nothing" || ok "19h: uplink port absent -> nothing" # 19g. an installed WAN netplan this user cannot read (the helper installs it 0600) is "unreadable", not "differs"