refactor: stop probing predastore for a raft role

The daemon dialled a /status endpoint on each meta node to report which held
raft leadership. That endpoint lived in predastore's s3db package; after the
transport collapse the meta nodes speak rpc over QUIC and the in-process pipe
and expose no HTTP surface, so the probe dialled a dead port.

NodeStatusResponse.PredastoreRole is retained and left empty. Every consumer
already guards on the empty string, so the CLI and the UI simply omit the
badge, and restoring the probe later needs no contract change.
This commit is contained in:
brynmailer-mdc
2026-08-11 14:45:45 +10:00
committed by Bryn Mailer
parent 96dc1af568
commit 94db344556
3 changed files with 7 additions and 78 deletions
+2 -41
View File
@@ -347,9 +347,8 @@ func (d *Daemon) handleNodeStatus(msg *nats.Msg) {
// OVN roles are probed only on DB quorum members; compute-only nodes skip
// the shell-out entirely.
var wg sync.WaitGroup
wg.Add(2)
wg.Add(1)
go func() { defer wg.Done(); resp.NATSRole = d.queryNATSRole() }()
go func() { defer wg.Done(); resp.PredastoreRole = d.queryPredastoreRole() }()
if d.isOVNDBQuorumMember() {
wg.Add(2)
go func() { defer wg.Done(); resp.OVNNBRole = host.OVNDBRole(host.OVNNBTarget, host.OVNNBSchema) }()
@@ -364,8 +363,7 @@ const (
roleLeader = "leader"
roleFollower = "follower"
natsMonitorPort = 8222
predastoreDBPort = 6660
natsMonitorPort = 8222
)
// queryNATSRole queries the local NATS monitoring endpoint to determine this
@@ -378,16 +376,6 @@ func (d *Daemon) queryNATSRole() string {
return fetchNATSRole(url, roleHTTPClient)
}
// queryPredastoreRole queries the local Predastore DB status endpoint to
// determine this node's Raft role. Returns "leader", "follower", or "".
func (d *Daemon) queryPredastoreRole() string {
if !d.config.HasService("predastore") {
return ""
}
url := "https://" + net.JoinHostPort(d.daemonIP(), strconv.Itoa(predastoreDBPort)) + "/status"
return fetchPredastoreRole(url, roleTLSHTTPClient)
}
// isOVNDBQuorumMember reports whether this node hosts the clustered OVN NB/SB
// databases. Compute-only nodes short-circuit OVN role probes to "" without
// shelling out to ovn-appctl.
@@ -401,10 +389,6 @@ func (d *Daemon) isOVNDBQuorumMember() bool {
var roleHTTPClient = &http.Client{Timeout: 500 * time.Millisecond}
var roleTLSHTTPClient = &http.Client{
Timeout: 500 * time.Millisecond,
}
// fetchNATSRole queries a NATS /varz endpoint and returns "leader", "follower", or "".
func fetchNATSRole(url string, client *http.Client) string {
resp, err := client.Get(url) //nolint:noctx // internal monitoring call
@@ -525,29 +509,6 @@ func resolveVMGPU(att gpu.GPUAttachment, byMdev, byPCI map[string]gpu.PoolEntry)
return nil
}
// fetchPredastoreRole queries a Predastore /status endpoint and returns "leader", "follower", or "".
func fetchPredastoreRole(url string, client *http.Client) string {
resp, err := client.Get(url) //nolint:noctx // internal monitoring call
if err != nil {
slog.Debug("Failed to query Predastore status", "err", err)
return ""
}
defer resp.Body.Close()
var status struct {
IsLeader bool `json:"is_leader"`
}
if err := json.NewDecoder(resp.Body).Decode(&status); err != nil {
slog.Debug("Failed to decode Predastore status", "err", err)
return ""
}
if status.IsLeader {
return roleLeader
}
return roleFollower
}
// handleNodeVMs responds with the list of VMs running on this node.
// Used by the CLI: spx get vms.
func (d *Daemon) handleNodeVMs(msg *nats.Msg) {
-35
View File
@@ -76,38 +76,3 @@ func TestFetchNATSRole_BadJSON(t *testing.T) {
role := fetchNATSRole(srv.URL, srv.Client())
assert.Empty(t, role)
}
func TestFetchPredastoreRole_Leader(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(`{"node_id":"1","state":"Leader","is_leader":true}`))
}))
defer srv.Close()
role := fetchPredastoreRole(srv.URL, srv.Client())
assert.Equal(t, "leader", role)
}
func TestFetchPredastoreRole_Follower(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(`{"node_id":"2","state":"Follower","is_leader":false}`))
}))
defer srv.Close()
role := fetchPredastoreRole(srv.URL, srv.Client())
assert.Equal(t, "follower", role)
}
func TestFetchPredastoreRole_Unreachable(t *testing.T) {
role := fetchPredastoreRole("https://127.0.0.1:1/status", &http.Client{})
assert.Empty(t, role)
}
func TestFetchPredastoreRole_BadJSON(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(`not json`))
}))
defer srv.Close()
role := fetchPredastoreRole(srv.URL, srv.Client())
assert.Empty(t, role)
}
+5 -2
View File
@@ -62,8 +62,11 @@ type NodeStatusResponse struct {
InstanceTypes []InstanceTypeCap `json:"instance_types"`
// Leader roles for clustered services (empty string = service not running or not clustered)
NATSRole string `json:"nats_role,omitempty"` // "leader" or "follower"
PredastoreRole string `json:"predastore_role,omitempty"` // "leader" or "follower"
NATSRole string `json:"nats_role,omitempty"` // "leader" or "follower"
// Never populated: predastore's meta nodes expose no status surface. Kept so
// the JSON contract and the UI are unchanged when the probe is restored.
PredastoreRole string `json:"predastore_role,omitempty"`
// OVN DB Raft roles ("leader"/"follower"/""); empty when the node is not an
// OVN DB cluster member or OVN is standalone.