mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-11-13 15:29:12 +01:00
A Vector servers count in the Cluster card and a Vector Servers table after S3 Servers, from the engines the dashboard already discovers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011UpvafvK8JpagF94MHWqwK
110 lines
3.5 KiB
Go
110 lines
3.5 KiB
Go
package dash
|
|
|
|
import (
|
|
"context"
|
|
"sort"
|
|
"time"
|
|
|
|
adminplugin "github.com/seaweedfs/seaweedfs/weed/admin/plugin"
|
|
"github.com/seaweedfs/seaweedfs/weed/cluster"
|
|
"github.com/seaweedfs/seaweedfs/weed/pb"
|
|
"github.com/seaweedfs/seaweedfs/weed/pb/master_pb"
|
|
"golang.org/x/sync/errgroup"
|
|
"google.golang.org/grpc"
|
|
"google.golang.org/grpc/codes"
|
|
"google.golang.org/grpc/health/grpc_health_v1"
|
|
"google.golang.org/grpc/status"
|
|
)
|
|
|
|
type VectorNode struct {
|
|
Address string `json:"address"`
|
|
// Kind is "engine" for a weed-vector engine.
|
|
Kind string `json:"kind"`
|
|
Version string `json:"version"`
|
|
Status string `json:"status"`
|
|
}
|
|
|
|
type VectorOperationsData struct {
|
|
Engines []VectorNode `json:"engines"`
|
|
DiscoveryError string `json:"discovery_error,omitempty"`
|
|
MaintenanceWorkers int `json:"maintenance_workers"`
|
|
MaintenanceJobs []adminplugin.TrackedJob `json:"maintenance_jobs"`
|
|
}
|
|
|
|
func (s *AdminServer) getVectorNodesStatus(ctx context.Context) VectorOperationsData {
|
|
data := VectorOperationsData{Engines: []VectorNode{}}
|
|
if s.masterClient == nil {
|
|
data.DiscoveryError = "Master discovery unavailable"
|
|
return data
|
|
}
|
|
var discoveryErr error
|
|
for _, master := range s.masterClient.ListCachedMasters() {
|
|
discoveryCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
|
conn, err := pb.GrpcDial(discoveryCtx, master.ToGrpcAddress(), false, s.grpcDialOption)
|
|
if err == nil {
|
|
response, callErr := master_pb.NewSeaweedClient(conn).ListClusterNodes(discoveryCtx, s.listClusterNodesRequest(cluster.VectorType))
|
|
_ = conn.Close()
|
|
err = callErr
|
|
if err == nil {
|
|
for _, node := range response.ClusterNodes {
|
|
data.Engines = append(data.Engines, VectorNode{Address: node.Address, Kind: "engine", Version: node.Version, Status: "Registered"})
|
|
}
|
|
}
|
|
}
|
|
cancel()
|
|
if err != nil {
|
|
discoveryErr = err
|
|
}
|
|
if len(data.Engines) > 0 {
|
|
break
|
|
}
|
|
}
|
|
if len(data.Engines) == 0 && discoveryErr != nil {
|
|
data.DiscoveryError = discoveryErr.Error()
|
|
return data
|
|
}
|
|
var checks errgroup.Group
|
|
checks.SetLimit(8)
|
|
for i := range data.Engines {
|
|
checks.Go(func() error {
|
|
data.Engines[i].Status = vectorNodeStatus(ctx, data.Engines[i].Address, s.grpcDialOption)
|
|
return nil
|
|
})
|
|
}
|
|
_ = checks.Wait()
|
|
sort.Slice(data.Engines, func(i, j int) bool { return data.Engines[i].Address < data.Engines[j].Address })
|
|
return data
|
|
}
|
|
|
|
func vectorNodeStatus(ctx context.Context, address string, dialOption grpc.DialOption) string {
|
|
ctx, cancel := context.WithTimeout(ctx, time.Second)
|
|
defer cancel()
|
|
conn, err := pb.GrpcDial(ctx, address, false, dialOption)
|
|
if err != nil {
|
|
return "Unreachable"
|
|
}
|
|
defer conn.Close()
|
|
response, err := grpc_health_v1.NewHealthClient(conn).Check(ctx, &grpc_health_v1.HealthCheckRequest{Service: "vector_pb.VectorService"})
|
|
if status.Code(err) == codes.Unimplemented || status.Code(err) == codes.NotFound {
|
|
return "Registered (health unavailable)"
|
|
}
|
|
if err != nil {
|
|
return "Unreachable"
|
|
}
|
|
if response.Status == grpc_health_v1.HealthCheckResponse_SERVING {
|
|
return "Ready"
|
|
}
|
|
return "Not ready"
|
|
}
|
|
|
|
func (s *AdminServer) GetVectorOperationsData(ctx context.Context) VectorOperationsData {
|
|
data := s.getVectorNodesStatus(ctx)
|
|
for _, worker := range s.GetPluginWorkers() {
|
|
if capability := worker.Capabilities["lance_vector_index"]; capability != nil && capability.CanExecute {
|
|
data.MaintenanceWorkers++
|
|
}
|
|
}
|
|
data.MaintenanceJobs = s.ListPluginJobs("lance_vector_index", "", 5)
|
|
return data
|
|
}
|