diff --git a/weed/admin/dash/admin_data.go b/weed/admin/dash/admin_data.go index 9c93af2534..286613e954 100644 --- a/weed/admin/dash/admin_data.go +++ b/weed/admin/dash/admin_data.go @@ -311,9 +311,7 @@ func (s *AdminServer) getFilerNodesStatus() []FilerNode { // Get filer nodes from master using ListClusterNodes err := s.WithMasterClient(func(client master_pb.SeaweedClient) error { - resp, err := client.ListClusterNodes(context.Background(), &master_pb.ListClusterNodesRequest{ - ClientType: cluster.FilerType, - }) + resp, err := client.ListClusterNodes(context.Background(), s.listClusterNodesRequest(cluster.FilerType)) if err != nil { return err } @@ -352,9 +350,7 @@ func (s *AdminServer) getMessageBrokerNodesStatus() []MessageBrokerNode { // Get message broker nodes from master using ListClusterNodes err := s.WithMasterClient(func(client master_pb.SeaweedClient) error { - resp, err := client.ListClusterNodes(context.Background(), &master_pb.ListClusterNodesRequest{ - ClientType: cluster.BrokerType, - }) + resp, err := client.ListClusterNodes(context.Background(), s.listClusterNodesRequest(cluster.BrokerType)) if err != nil { return err } @@ -393,9 +389,7 @@ func (s *AdminServer) getS3NodesStatus() []S3Node { // Get S3 nodes from master using ListClusterNodes err := s.WithMasterClient(func(client master_pb.SeaweedClient) error { - resp, err := client.ListClusterNodes(context.Background(), &master_pb.ListClusterNodesRequest{ - ClientType: cluster.S3Type, - }) + resp, err := client.ListClusterNodes(context.Background(), s.listClusterNodesRequest(cluster.S3Type)) if err != nil { return err } diff --git a/weed/admin/dash/admin_server.go b/weed/admin/dash/admin_server.go index a3e90b663b..282d30647c 100644 --- a/weed/admin/dash/admin_server.go +++ b/weed/admin/dash/admin_server.go @@ -85,6 +85,7 @@ type AdminServer struct { masterClient *wdclient.MasterClient templateFS http.FileSystem dataDir string + filerGroup string grpcDialOption grpc.DialOption cacheExpiration time.Duration lastCacheUpdate time.Time @@ -134,13 +135,13 @@ type AdminServer struct { // Type definitions moved to types.go -func NewAdminServer(masters string, templateFS http.FileSystem, dataDir string, icebergPort int) *AdminServer { +func NewAdminServer(masters string, filerGroup string, templateFS http.FileSystem, dataDir string, icebergPort int) *AdminServer { grpcDialOption := security.LoadClientTLS(util.GetViper(), "grpc.admin") // Create master client with multiple master support masterClient := wdclient.NewMasterClient( grpcDialOption, - "", // filerGroup - not needed for admin + filerGroup, "admin", // clientType "", // clientHost - not needed for admin "", // dataCenter - not needed for admin @@ -162,6 +163,7 @@ func NewAdminServer(masters string, templateFS http.FileSystem, dataDir string, masterClient: masterClient, templateFS: templateFS, dataDir: dataDir, + filerGroup: filerGroup, grpcDialOption: grpcDialOption, cacheExpiration: defaultCacheTimeout, filerCacheExpiration: defaultFilerCacheTimeout, @@ -293,6 +295,13 @@ func NewAdminServer(masters string, templateFS http.FileSystem, dataDir string, return server } +func (s *AdminServer) listClusterNodesRequest(clientType string) *master_pb.ListClusterNodesRequest { + return &master_pb.ListClusterNodesRequest{ + ClientType: clientType, + FilerGroup: s.filerGroup, + } +} + // vacuumToggler abstracts the master's vacuum enable/disable for testing. type vacuumToggler interface { disableVacuum() error @@ -1112,9 +1121,7 @@ func (s *AdminServer) GetClusterFilers() (*ClusterFilersData, error) { // Get filer information from master using ListClusterNodes err := s.WithMasterClient(func(client master_pb.SeaweedClient) error { - resp, err := client.ListClusterNodes(context.Background(), &master_pb.ListClusterNodesRequest{ - ClientType: cluster.FilerType, - }) + resp, err := client.ListClusterNodes(context.Background(), s.listClusterNodesRequest(cluster.FilerType)) if err != nil { return err } @@ -1159,9 +1166,7 @@ func (s *AdminServer) GetClusterBrokers() (*ClusterBrokersData, error) { // Get broker information from master using ListClusterNodes err := s.WithMasterClient(func(client master_pb.SeaweedClient) error { - resp, err := client.ListClusterNodes(context.Background(), &master_pb.ListClusterNodesRequest{ - ClientType: cluster.BrokerType, - }) + resp, err := client.ListClusterNodes(context.Background(), s.listClusterNodesRequest(cluster.BrokerType)) if err != nil { return err } @@ -1206,9 +1211,7 @@ func (s *AdminServer) GetClusterS3Servers() (*ClusterS3ServersData, error) { // Get S3 server information from master using ListClusterNodes err := s.WithMasterClient(func(client master_pb.SeaweedClient) error { - resp, err := client.ListClusterNodes(context.Background(), &master_pb.ListClusterNodesRequest{ - ClientType: cluster.S3Type, - }) + resp, err := client.ListClusterNodes(context.Background(), s.listClusterNodesRequest(cluster.S3Type)) if err != nil { return err } @@ -1642,9 +1645,7 @@ func (s *AdminServer) UpdateTopicRetention(namespace, name string, enabled bool, // Get broker information from master var brokerAddress string err := s.WithMasterClient(func(client master_pb.SeaweedClient) error { - resp, err := client.ListClusterNodes(context.Background(), &master_pb.ListClusterNodesRequest{ - ClientType: cluster.BrokerType, - }) + resp, err := client.ListClusterNodes(context.Background(), s.listClusterNodesRequest(cluster.BrokerType)) if err != nil { return err } diff --git a/weed/admin/dash/admin_server_filergroup_test.go b/weed/admin/dash/admin_server_filergroup_test.go new file mode 100644 index 0000000000..411f8429fa --- /dev/null +++ b/weed/admin/dash/admin_server_filergroup_test.go @@ -0,0 +1,30 @@ +package dash + +import ( + "testing" + + "github.com/seaweedfs/seaweedfs/weed/cluster" +) + +func TestListClusterNodesRequestIncludesFilerGroup(t *testing.T) { + server := &AdminServer{filerGroup: "tenant-a"} + + req := server.listClusterNodesRequest(cluster.FilerType) + + if req.ClientType != cluster.FilerType { + t.Fatalf("ClientType = %q, want %q", req.ClientType, cluster.FilerType) + } + if req.FilerGroup != "tenant-a" { + t.Fatalf("FilerGroup = %q, want %q", req.FilerGroup, "tenant-a") + } +} + +func TestListClusterNodesRequestKeepsDefaultFilerGroupEmpty(t *testing.T) { + server := &AdminServer{} + + req := server.listClusterNodesRequest(cluster.FilerType) + + if req.FilerGroup != "" { + t.Fatalf("FilerGroup = %q, want empty", req.FilerGroup) + } +} diff --git a/weed/admin/dash/client_management.go b/weed/admin/dash/client_management.go index 009b08ce5a..6867782f49 100644 --- a/weed/admin/dash/client_management.go +++ b/weed/admin/dash/client_management.go @@ -76,9 +76,7 @@ func (s *AdminServer) getDiscoveredFilers() []string { // Discover filers from masters var filers []string err := s.WithMasterClient(func(client master_pb.SeaweedClient) error { - resp, err := client.ListClusterNodes(context.Background(), &master_pb.ListClusterNodesRequest{ - ClientType: cluster.FilerType, - }) + resp, err := client.ListClusterNodes(context.Background(), s.listClusterNodesRequest(cluster.FilerType)) if err != nil { return err } diff --git a/weed/admin/dash/mq_management.go b/weed/admin/dash/mq_management.go index c6d8de1fc1..9ce91d40f9 100644 --- a/weed/admin/dash/mq_management.go +++ b/weed/admin/dash/mq_management.go @@ -494,9 +494,7 @@ func (s *AdminServer) findBrokerLeader() (string, error) { // First, try to find any broker from the cluster var brokers []string err := s.WithMasterClient(func(client master_pb.SeaweedClient) error { - resp, err := client.ListClusterNodes(context.Background(), &master_pb.ListClusterNodesRequest{ - ClientType: cluster.BrokerType, - }) + resp, err := client.ListClusterNodes(context.Background(), s.listClusterNodesRequest(cluster.BrokerType)) if err != nil { return err } @@ -524,7 +522,7 @@ func (s *AdminServer) findBrokerLeader() (string, error) { // Try to find broker leader _, err := client.FindBrokerLeader(ctx, &mq_pb.FindBrokerLeaderRequest{ - FilerGroup: "", + FilerGroup: s.filerGroup, }) if err == nil { return nil // This broker is the leader diff --git a/weed/admin/dash/plugin_api.go b/weed/admin/dash/plugin_api.go index 34b34632f9..7f37003062 100644 --- a/weed/admin/dash/plugin_api.go +++ b/weed/admin/dash/plugin_api.go @@ -805,9 +805,7 @@ func (s *AdminServer) buildDefaultPluginClusterContext() *plugin_pb.ClusterConte s3Seen := map[string]struct{}{} if err := s.WithMasterClient(func(client master_pb.SeaweedClient) error { - resp, err := client.ListClusterNodes(context.Background(), &master_pb.ListClusterNodesRequest{ - ClientType: cluster.S3Type, - }) + resp, err := client.ListClusterNodes(context.Background(), s.listClusterNodesRequest(cluster.S3Type)) if err != nil { return err } diff --git a/weed/command/admin.go b/weed/command/admin.go index e89a24d701..1615759525 100644 --- a/weed/command/admin.go +++ b/weed/command/admin.go @@ -44,6 +44,7 @@ type AdminOptions struct { grpcPort *int master *string masters *string // deprecated, for backward compatibility + filerGroup *string adminUser *string adminPassword *string readOnlyUser *string @@ -65,6 +66,7 @@ func init() { a.grpcPort = cmdAdmin.Flag.Int("port.grpc", 0, "gRPC server port for worker connections (default: http port + 10000)") a.master = cmdAdmin.Flag.String("master", "localhost:9333", "comma-separated master servers") a.masters = cmdAdmin.Flag.String("masters", "", "comma-separated master servers (deprecated, use -master instead)") + a.filerGroup = cmdAdmin.Flag.String("filerGroup", "", "filerGroup for the filers, brokers, and S3 servers") a.dataDir = cmdAdmin.Flag.String("dataDir", ".", "directory to store admin configuration and data files (default current dir; required for maintenance task state to persist)") a.adminUser = cmdAdmin.Flag.String("adminUser", "admin", "admin interface username") @@ -82,7 +84,7 @@ func init() { } var cmdAdmin = &Command{ - UsageLine: "admin -port=23646 -master=localhost:9333 [-port.grpc=33646] [-dataDir=/path/to/data]", + UsageLine: "admin -port=23646 -master=localhost:9333 [-filerGroup=group] [-port.grpc=33646] [-dataDir=/path/to/data]", Short: "start SeaweedFS web admin interface", Long: `Start a web admin interface for SeaweedFS cluster management. @@ -99,6 +101,7 @@ var cmdAdmin = &Command{ Example Usage: weed admin -port=23646 -master="master1:9333,master2:9333" + weed admin -port=23646 -master="localhost:9333" -filerGroup="tenant-a" weed admin -port=23646 -master="localhost:9333" -dataDir="/var/lib/seaweedfs-admin" weed admin -port=23646 -port.grpc=33646 -master="localhost:9333" -dataDir="~/seaweedfs-admin" weed admin -port=9900 -port.grpc=19900 -master="localhost:9333" @@ -383,7 +386,7 @@ func startAdminServer(ctx context.Context, options AdminOptions, enableUI bool, r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", admin.StaticHandler())) // Create admin server (plugin is always enabled) - adminServer := dash.NewAdminServer(*options.master, nil, dataDir, icebergPort) + adminServer := dash.NewAdminServer(*options.master, *options.filerGroup, nil, dataDir, icebergPort) // Show discovered filers filers := adminServer.GetAllFilers() diff --git a/weed/command/mini.go b/weed/command/mini.go index 8831dd6047..6116ccbc82 100644 --- a/weed/command/mini.go +++ b/weed/command/mini.go @@ -543,6 +543,8 @@ func initMiniAdminFlags() { miniAdminOptions.port = cmdMini.Flag.Int("admin.port", 23646, "admin server http listen port") miniAdminOptions.grpcPort = cmdMini.Flag.Int("admin.port.grpc", 0, "admin server grpc listen port (default: admin http port + GrpcPortOffset)") miniAdminOptions.master = cmdMini.Flag.String("admin.master", "", "master server address (automatically set)") + // admin discovery must query the same group the co-located filer registers under + miniAdminOptions.filerGroup = miniFilerOptions.filerGroup miniAdminOptions.dataDir = cmdMini.Flag.String("admin.dataDir", "", "directory to store admin configuration and data files") miniAdminOptions.adminUser = cmdMini.Flag.String("admin.user", "admin", "admin interface username") miniAdminOptions.adminPassword = cmdMini.Flag.String("admin.password", "", "admin interface password (if empty, auth is disabled)")