diff --git a/spinifex/daemon/daemon_handlers.go b/spinifex/daemon/daemon_handlers.go index 01a15335c..525d7daca 100644 --- a/spinifex/daemon/daemon_handlers.go +++ b/spinifex/daemon/daemon_handlers.go @@ -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) { diff --git a/spinifex/daemon/roles_test.go b/spinifex/daemon/roles_test.go index 62cc91d6e..6b8c90ec3 100644 --- a/spinifex/daemon/roles_test.go +++ b/spinifex/daemon/roles_test.go @@ -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) -} diff --git a/spinifex/types/node.go b/spinifex/types/node.go index 0e1a15247..d778946f2 100644 --- a/spinifex/types/node.go +++ b/spinifex/types/node.go @@ -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.