Probe hosts for health instead of risking the shared connection
The health check shares each host's libvirt connection with the reconciles, so it must not be able to take that connection away from them. - A timed-out check no longer drops the link. The check goes through the new hostPool.probe, which abandons its RPCs when the context ends and leaves the connection alone, so an image upload or a Create running on the same link is not cut off. A link that really died is closed by the keepalive. One abandoned probe per host may stay waiting; until it returns, the next check reports Timeout at once (errProbeBusy). - Waiting for a host's connection slot now ends with the caller's context. hostEntry used a mutex, so a check could wait out a reconcile redialing a dead host — minutes — past its own timeout. The slot is a one-slot channel and acquire bounds only the wait, never the uncontended take. - --provider-check-timeout defaults to 0 and derives min(15s, interval). The flat 15s default contradicted the validation that the timeout may not exceed the interval, so --provider-check-interval=12s alone failed to start. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -340,7 +340,8 @@ func TestValidateSchedule(t *testing.T) {
|
||||
{"shortest interval", 10 * time.Second, 10 * time.Second, false},
|
||||
{"too frequent", 5 * time.Second, time.Second, true},
|
||||
{"negative interval", -time.Minute, time.Second, true},
|
||||
{"no timeout", time.Minute, 0, true},
|
||||
{"timeout left to derive, short interval", 12 * time.Second, 0, false},
|
||||
{"negative timeout", time.Minute, -time.Second, true},
|
||||
{"timeout longer than interval", time.Minute, 2 * time.Minute, true},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
@@ -352,3 +353,25 @@ func TestValidateSchedule(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestMonitor_setDefaults_timeout(t *testing.T) {
|
||||
t.Parallel()
|
||||
tests := []struct {
|
||||
name string
|
||||
interval, timeout, want time.Duration
|
||||
}{
|
||||
{"default", time.Minute, 0, 15 * time.Second},
|
||||
{"interval shorter than the default", 12 * time.Second, 0, 12 * time.Second},
|
||||
{"explicit", time.Minute, 20 * time.Second, 20 * time.Second},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
m := &Monitor{Interval: tc.interval, Timeout: tc.timeout}
|
||||
m.setDefaults()
|
||||
if m.Timeout != tc.want {
|
||||
t.Errorf("Timeout = %s, want %s", m.Timeout, tc.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user