mirror of
https://github.com/juanfont/headscale.git
synced 2026-09-23 16:54:53 +09:00
state: preserve previous primary when all HA advertisers unhealthy
electPrimaryRoutes' all-unhealthy fallback picked candidates[0] (lowest NodeID) regardless of who was prev. Under cable-pull semantics IsOnline lags reality (long-poll TCP half-open), so both routers stay in candidates and both go Unhealthy via the prober — the fallback then churned primary to a node that was itself unreachable. Prefer prev when still in candidates; fall through to candidates[0] only when prev is gone. Anti-blackhole holds. Update the property test reference model and split the unit test into existence (KeepsAPrimary) and identity (PreservesPrevious) cases. Fixes #3203
This commit is contained in:
@@ -620,9 +620,12 @@ func snapshotFromNodes(
|
||||
// electPrimaryRoutes picks the primary advertiser for each non-exit
|
||||
// prefix. The previous primary is preserved when it is still online
|
||||
// and healthy (anti-flap); otherwise the lowest-NodeID healthy
|
||||
// advertiser wins, falling back to the lowest-NodeID candidate when
|
||||
// every advertiser is unhealthy so peers see *some* primary instead
|
||||
// of none.
|
||||
// advertiser wins. When every advertiser is unhealthy the previous
|
||||
// primary is preserved if still a candidate, falling back to the
|
||||
// lowest-NodeID candidate so peers see *some* primary instead of
|
||||
// none. Anti-flap in the all-unhealthy case matters under cable-pull
|
||||
// where IsOnline lags reality and a naive lowest-ID fallback churns
|
||||
// primaries to a node that is itself unreachable (issue #3203).
|
||||
func electPrimaryRoutes(
|
||||
nodes map[types.NodeID]types.Node,
|
||||
prev map[netip.Prefix]types.NodeID,
|
||||
@@ -675,7 +678,12 @@ func electPrimaryRoutes(
|
||||
}
|
||||
|
||||
if !found && len(candidates) >= 1 {
|
||||
selected = candidates[0]
|
||||
if cur, ok := prev[prefix]; ok && slices.Contains(candidates, cur) {
|
||||
selected = cur
|
||||
} else {
|
||||
selected = candidates[0]
|
||||
}
|
||||
|
||||
found = true
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user