aboutsummaryrefslogtreecommitdiff
path: root/weed/admin/dash/admin_server.go
diff options
context:
space:
mode:
Diffstat (limited to 'weed/admin/dash/admin_server.go')
-rw-r--r--weed/admin/dash/admin_server.go861
1 files changed, 14 insertions, 847 deletions
diff --git a/weed/admin/dash/admin_server.go b/weed/admin/dash/admin_server.go
index 93b556af8..03a44a6da 100644
--- a/weed/admin/dash/admin_server.go
+++ b/weed/admin/dash/admin_server.go
@@ -5,19 +5,15 @@ import (
"context"
"fmt"
"net/http"
- "sort"
"time"
"github.com/seaweedfs/seaweedfs/weed/cluster"
"github.com/seaweedfs/seaweedfs/weed/credential"
"github.com/seaweedfs/seaweedfs/weed/filer"
"github.com/seaweedfs/seaweedfs/weed/glog"
- "github.com/seaweedfs/seaweedfs/weed/operation"
- "github.com/seaweedfs/seaweedfs/weed/pb"
"github.com/seaweedfs/seaweedfs/weed/pb/filer_pb"
"github.com/seaweedfs/seaweedfs/weed/pb/iam_pb"
"github.com/seaweedfs/seaweedfs/weed/pb/master_pb"
- "github.com/seaweedfs/seaweedfs/weed/pb/volume_server_pb"
"github.com/seaweedfs/seaweedfs/weed/security"
"github.com/seaweedfs/seaweedfs/weed/util"
"google.golang.org/grpc"
@@ -40,190 +36,7 @@ type AdminServer struct {
credentialManager *credential.CredentialManager
}
-type ClusterTopology struct {
- Masters []MasterNode `json:"masters"`
- DataCenters []DataCenter `json:"datacenters"`
- VolumeServers []VolumeServer `json:"volume_servers"`
- TotalVolumes int `json:"total_volumes"`
- TotalFiles int64 `json:"total_files"`
- TotalSize int64 `json:"total_size"`
- UpdatedAt time.Time `json:"updated_at"`
-}
-
-type MasterNode struct {
- Address string `json:"address"`
- IsLeader bool `json:"is_leader"`
-}
-
-type DataCenter struct {
- ID string `json:"id"`
- Racks []Rack `json:"racks"`
-}
-
-type Rack struct {
- ID string `json:"id"`
- Nodes []VolumeServer `json:"nodes"`
-}
-
-type VolumeServer struct {
- ID string `json:"id"`
- Address string `json:"address"`
- DataCenter string `json:"datacenter"`
- Rack string `json:"rack"`
- PublicURL string `json:"public_url"`
- Volumes int `json:"volumes"`
- MaxVolumes int `json:"max_volumes"`
- DiskUsage int64 `json:"disk_usage"`
- DiskCapacity int64 `json:"disk_capacity"`
- LastHeartbeat time.Time `json:"last_heartbeat"`
-}
-
-// S3 Bucket management structures
-type S3Bucket struct {
- Name string `json:"name"`
- CreatedAt time.Time `json:"created_at"`
- Size int64 `json:"size"`
- ObjectCount int64 `json:"object_count"`
- LastModified time.Time `json:"last_modified"`
- Quota int64 `json:"quota"` // Quota in bytes, 0 means no quota
- QuotaEnabled bool `json:"quota_enabled"` // Whether quota is enabled
-}
-
-type S3Object struct {
- Key string `json:"key"`
- Size int64 `json:"size"`
- LastModified time.Time `json:"last_modified"`
- ETag string `json:"etag"`
- StorageClass string `json:"storage_class"`
-}
-
-type BucketDetails struct {
- Bucket S3Bucket `json:"bucket"`
- Objects []S3Object `json:"objects"`
- TotalSize int64 `json:"total_size"`
- TotalCount int64 `json:"total_count"`
- UpdatedAt time.Time `json:"updated_at"`
-}
-
-// Cluster management data structures
-type ClusterVolumeServersData struct {
- Username string `json:"username"`
- VolumeServers []VolumeServer `json:"volume_servers"`
- TotalVolumeServers int `json:"total_volume_servers"`
- TotalVolumes int `json:"total_volumes"`
- TotalCapacity int64 `json:"total_capacity"`
- LastUpdated time.Time `json:"last_updated"`
-}
-
-type VolumeWithTopology struct {
- *master_pb.VolumeInformationMessage
- Server string `json:"server"`
- DataCenter string `json:"datacenter"`
- Rack string `json:"rack"`
-}
-
-type ClusterVolumesData struct {
- Username string `json:"username"`
- Volumes []VolumeWithTopology `json:"volumes"`
- TotalVolumes int `json:"total_volumes"`
- TotalSize int64 `json:"total_size"`
- LastUpdated time.Time `json:"last_updated"`
-
- // Pagination
- CurrentPage int `json:"current_page"`
- TotalPages int `json:"total_pages"`
- PageSize int `json:"page_size"`
-
- // Sorting
- SortBy string `json:"sort_by"`
- SortOrder string `json:"sort_order"`
-
- // Statistics
- DataCenterCount int `json:"datacenter_count"`
- RackCount int `json:"rack_count"`
- DiskTypeCount int `json:"disk_type_count"`
- CollectionCount int `json:"collection_count"`
- VersionCount int `json:"version_count"`
-
- // Conditional display flags
- ShowDataCenterColumn bool `json:"show_datacenter_column"`
- ShowRackColumn bool `json:"show_rack_column"`
- ShowDiskTypeColumn bool `json:"show_disk_type_column"`
- ShowCollectionColumn bool `json:"show_collection_column"`
- ShowVersionColumn bool `json:"show_version_column"`
-
- // Single values when only one exists
- SingleDataCenter string `json:"single_datacenter"`
- SingleRack string `json:"single_rack"`
- SingleDiskType string `json:"single_disk_type"`
- SingleCollection string `json:"single_collection"`
- SingleVersion string `json:"single_version"`
-
- // All versions when multiple exist
- AllVersions []string `json:"all_versions"`
-
- // All disk types when multiple exist
- AllDiskTypes []string `json:"all_disk_types"`
-
- // Filtering
- FilterCollection string `json:"filter_collection"`
-}
-
-type VolumeDetailsData struct {
- Volume VolumeWithTopology `json:"volume"`
- Replicas []VolumeWithTopology `json:"replicas"`
- VolumeSizeLimit uint64 `json:"volume_size_limit"`
- ReplicationCount int `json:"replication_count"`
- LastUpdated time.Time `json:"last_updated"`
-}
-
-type CollectionInfo struct {
- Name string `json:"name"`
- DataCenter string `json:"datacenter"`
- VolumeCount int `json:"volume_count"`
- FileCount int64 `json:"file_count"`
- TotalSize int64 `json:"total_size"`
- DiskTypes []string `json:"disk_types"`
-}
-
-type ClusterCollectionsData struct {
- Username string `json:"username"`
- Collections []CollectionInfo `json:"collections"`
- TotalCollections int `json:"total_collections"`
- TotalVolumes int `json:"total_volumes"`
- TotalFiles int64 `json:"total_files"`
- TotalSize int64 `json:"total_size"`
- LastUpdated time.Time `json:"last_updated"`
-}
-
-type MasterInfo struct {
- Address string `json:"address"`
- IsLeader bool `json:"is_leader"`
- Suffrage string `json:"suffrage"`
-}
-
-type ClusterMastersData struct {
- Username string `json:"username"`
- Masters []MasterInfo `json:"masters"`
- TotalMasters int `json:"total_masters"`
- LeaderCount int `json:"leader_count"`
- LastUpdated time.Time `json:"last_updated"`
-}
-
-type FilerInfo struct {
- Address string `json:"address"`
- DataCenter string `json:"datacenter"`
- Rack string `json:"rack"`
- Version string `json:"version"`
- CreatedAt time.Time `json:"created_at"`
-}
-
-type ClusterFilersData struct {
- Username string `json:"username"`
- Filers []FilerInfo `json:"filers"`
- TotalFilers int `json:"total_filers"`
- LastUpdated time.Time `json:"last_updated"`
-}
+// Type definitions moved to types.go
func NewAdminServer(masterAddress string, templateFS http.FileSystem) *AdminServer {
server := &AdminServer{
@@ -277,189 +90,17 @@ func (s *AdminServer) GetCredentialManager() *credential.CredentialManager {
return s.credentialManager
}
-// GetFilerAddress returns a filer address, discovering from masters if needed
-func (s *AdminServer) GetFilerAddress() string {
- // Discover filers from masters
- filers := s.getDiscoveredFilers()
- if len(filers) > 0 {
- return filers[0] // Return the first available filer
- }
-
- return ""
-}
-
-// getDiscoveredFilers returns cached filers or discovers them from masters
-func (s *AdminServer) getDiscoveredFilers() []string {
- // Check if cache is still valid
- if time.Since(s.lastFilerUpdate) < s.filerCacheExpiration && len(s.cachedFilers) > 0 {
- return s.cachedFilers
- }
-
- // 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,
- })
- if err != nil {
- return err
- }
-
- for _, node := range resp.ClusterNodes {
- filers = append(filers, node.Address)
- }
-
- return nil
- })
-
- if err != nil {
- glog.Warningf("Failed to discover filers from master %s: %v", s.masterAddress, err)
- // Return cached filers even if expired, better than nothing
- return s.cachedFilers
- }
-
- // Update cache
- s.cachedFilers = filers
- s.lastFilerUpdate = time.Now()
-
- return filers
-}
-
-// WithMasterClient executes a function with a master client connection
-func (s *AdminServer) WithMasterClient(f func(client master_pb.SeaweedClient) error) error {
- masterAddr := pb.ServerAddress(s.masterAddress)
-
- return pb.WithMasterClient(false, masterAddr, s.grpcDialOption, false, func(client master_pb.SeaweedClient) error {
- return f(client)
- })
-}
-
-// WithFilerClient executes a function with a filer client connection
-func (s *AdminServer) WithFilerClient(f func(client filer_pb.SeaweedFilerClient) error) error {
- filerAddr := s.GetFilerAddress()
- if filerAddr == "" {
- return fmt.Errorf("no filer available")
- }
-
- return pb.WithGrpcFilerClient(false, 0, pb.ServerAddress(filerAddr), s.grpcDialOption, func(client filer_pb.SeaweedFilerClient) error {
- return f(client)
- })
-}
-
-// WithVolumeServerClient executes a function with a volume server client connection
-func (s *AdminServer) WithVolumeServerClient(address pb.ServerAddress, f func(client volume_server_pb.VolumeServerClient) error) error {
- return operation.WithVolumeServerClient(false, address, s.grpcDialOption, func(client volume_server_pb.VolumeServerClient) error {
- return f(client)
- })
-}
-
-// GetClusterTopology returns the current cluster topology with caching
-func (s *AdminServer) GetClusterTopology() (*ClusterTopology, error) {
- now := time.Now()
- if s.cachedTopology != nil && now.Sub(s.lastCacheUpdate) < s.cacheExpiration {
- return s.cachedTopology, nil
- }
-
- topology := &ClusterTopology{
- UpdatedAt: now,
- }
-
- // Use gRPC only
- err := s.getTopologyViaGRPC(topology)
- if err != nil {
- glog.Errorf("Failed to connect to master server %s: %v", s.masterAddress, err)
- return nil, fmt.Errorf("gRPC topology request failed: %v", err)
- }
-
- // Cache the result
- s.cachedTopology = topology
- s.lastCacheUpdate = now
-
- return topology, nil
-}
-
-// getTopologyViaGRPC gets topology using gRPC (original method)
-func (s *AdminServer) getTopologyViaGRPC(topology *ClusterTopology) error {
- // Get cluster status from master
- err := s.WithMasterClient(func(client master_pb.SeaweedClient) error {
- resp, err := client.VolumeList(context.Background(), &master_pb.VolumeListRequest{})
- if err != nil {
- glog.Errorf("Failed to get volume list from master %s: %v", s.masterAddress, err)
- return err
- }
-
- if resp.TopologyInfo != nil {
- // Process gRPC response
- for _, dc := range resp.TopologyInfo.DataCenterInfos {
- dataCenter := DataCenter{
- ID: dc.Id,
- Racks: []Rack{},
- }
-
- for _, rack := range dc.RackInfos {
- rackObj := Rack{
- ID: rack.Id,
- Nodes: []VolumeServer{},
- }
-
- for _, node := range rack.DataNodeInfos {
- // Calculate totals from disk infos
- var totalVolumes int64
- var totalMaxVolumes int64
- var totalSize int64
- var totalFiles int64
-
- for _, diskInfo := range node.DiskInfos {
- totalVolumes += diskInfo.VolumeCount
- totalMaxVolumes += diskInfo.MaxVolumeCount
+// Filer discovery methods moved to client_management.go
- // Sum up individual volume information
- for _, volInfo := range diskInfo.VolumeInfos {
- totalSize += int64(volInfo.Size)
- totalFiles += int64(volInfo.FileCount)
- }
- }
+// Client management methods moved to client_management.go
- vs := VolumeServer{
- ID: node.Id,
- Address: node.Id,
- DataCenter: dc.Id,
- Rack: rack.Id,
- PublicURL: node.Id,
- Volumes: int(totalVolumes),
- MaxVolumes: int(totalMaxVolumes),
- DiskUsage: totalSize,
- DiskCapacity: totalMaxVolumes * int64(resp.VolumeSizeLimitMb) * 1024 * 1024,
- LastHeartbeat: time.Now(),
- }
+// WithFilerClient and WithVolumeServerClient methods moved to client_management.go
- rackObj.Nodes = append(rackObj.Nodes, vs)
- topology.VolumeServers = append(topology.VolumeServers, vs)
- topology.TotalVolumes += vs.Volumes
- topology.TotalFiles += totalFiles
- topology.TotalSize += totalSize
- }
+// Cluster topology methods moved to cluster_topology.go
- dataCenter.Racks = append(dataCenter.Racks, rackObj)
- }
+// getTopologyViaGRPC method moved to cluster_topology.go
- topology.DataCenters = append(topology.DataCenters, dataCenter)
- }
- }
-
- return nil
- })
-
- return err
-}
-
-// InvalidateCache forces a refresh of cached data
-func (s *AdminServer) InvalidateCache() {
- s.lastCacheUpdate = time.Time{}
- s.cachedTopology = nil
- s.lastFilerUpdate = time.Time{}
- s.cachedFilers = nil
-}
+// InvalidateCache method moved to cluster_topology.go
// GetS3Buckets retrieves all Object Store buckets from the filer and collects size/object data from collections
func (s *AdminServer) GetS3Buckets() ([]S3Bucket, error) {
@@ -780,393 +421,13 @@ func (s *AdminServer) GetObjectStoreUsers() ([]ObjectStoreUser, error) {
return users, nil
}
-// GetClusterVolumeServers retrieves cluster volume servers data
-func (s *AdminServer) GetClusterVolumeServers() (*ClusterVolumeServersData, error) {
- topology, err := s.GetClusterTopology()
- if err != nil {
- return nil, err
- }
+// Volume server methods moved to volume_management.go
- var totalCapacity int64
- var totalVolumes int
- for _, vs := range topology.VolumeServers {
- totalCapacity += vs.DiskCapacity
- totalVolumes += vs.Volumes
- }
+// Volume methods moved to volume_management.go
- return &ClusterVolumeServersData{
- VolumeServers: topology.VolumeServers,
- TotalVolumeServers: len(topology.VolumeServers),
- TotalVolumes: totalVolumes,
- TotalCapacity: totalCapacity,
- LastUpdated: time.Now(),
- }, nil
-}
+// sortVolumes method moved to volume_management.go
-// GetClusterVolumes retrieves cluster volumes data with pagination, sorting, and filtering
-func (s *AdminServer) GetClusterVolumes(page int, pageSize int, sortBy string, sortOrder string, collection string) (*ClusterVolumesData, error) {
- // Set defaults
- if page < 1 {
- page = 1
- }
- if pageSize < 1 || pageSize > 1000 {
- pageSize = 100
- }
- if sortBy == "" {
- sortBy = "id"
- }
- if sortOrder == "" {
- sortOrder = "asc"
- }
- var volumes []VolumeWithTopology
- var totalSize int64
-
- // Get detailed volume information via gRPC
- err := s.WithMasterClient(func(client master_pb.SeaweedClient) error {
- resp, err := client.VolumeList(context.Background(), &master_pb.VolumeListRequest{})
- if err != nil {
- return err
- }
-
- if resp.TopologyInfo != nil {
- for _, dc := range resp.TopologyInfo.DataCenterInfos {
- for _, rack := range dc.RackInfos {
- for _, node := range rack.DataNodeInfos {
- for _, diskInfo := range node.DiskInfos {
- for _, volInfo := range diskInfo.VolumeInfos {
- volume := VolumeWithTopology{
- VolumeInformationMessage: volInfo,
- Server: node.Id,
- DataCenter: dc.Id,
- Rack: rack.Id,
- }
- volumes = append(volumes, volume)
- totalSize += int64(volInfo.Size)
- }
- }
- }
- }
- }
- }
-
- return nil
- })
-
- if err != nil {
- return nil, err
- }
-
- // Filter by collection if specified
- if collection != "" {
- var filteredVolumes []VolumeWithTopology
- var filteredTotalSize int64
- for _, volume := range volumes {
- // Handle "default" collection filtering for empty collections
- volumeCollection := volume.Collection
- if volumeCollection == "" {
- volumeCollection = "default"
- }
-
- if volumeCollection == collection {
- filteredVolumes = append(filteredVolumes, volume)
- filteredTotalSize += int64(volume.Size)
- }
- }
- volumes = filteredVolumes
- totalSize = filteredTotalSize
- }
-
- // Calculate unique data center, rack, disk type, collection, and version counts from filtered volumes
- dataCenterMap := make(map[string]bool)
- rackMap := make(map[string]bool)
- diskTypeMap := make(map[string]bool)
- collectionMap := make(map[string]bool)
- versionMap := make(map[string]bool)
- for _, volume := range volumes {
- if volume.DataCenter != "" {
- dataCenterMap[volume.DataCenter] = true
- }
- if volume.Rack != "" {
- rackMap[volume.Rack] = true
- }
- diskType := volume.DiskType
- if diskType == "" {
- diskType = "hdd" // Default to hdd if not specified
- }
- diskTypeMap[diskType] = true
-
- // Handle collection for display purposes
- collectionName := volume.Collection
- if collectionName == "" {
- collectionName = "default"
- }
- collectionMap[collectionName] = true
-
- versionMap[fmt.Sprintf("%d", volume.Version)] = true
- }
- dataCenterCount := len(dataCenterMap)
- rackCount := len(rackMap)
- diskTypeCount := len(diskTypeMap)
- collectionCount := len(collectionMap)
- versionCount := len(versionMap)
-
- // Sort volumes
- s.sortVolumes(volumes, sortBy, sortOrder)
-
- // Calculate pagination
- totalVolumes := len(volumes)
- totalPages := (totalVolumes + pageSize - 1) / pageSize
- if totalPages == 0 {
- totalPages = 1
- }
-
- // Apply pagination
- startIndex := (page - 1) * pageSize
- endIndex := startIndex + pageSize
- if startIndex >= totalVolumes {
- volumes = []VolumeWithTopology{}
- } else {
- if endIndex > totalVolumes {
- endIndex = totalVolumes
- }
- volumes = volumes[startIndex:endIndex]
- }
-
- // Determine conditional display flags and extract single values
- showDataCenterColumn := dataCenterCount > 1
- showRackColumn := rackCount > 1
- showDiskTypeColumn := diskTypeCount > 1
- showCollectionColumn := collectionCount > 1 && collection == "" // Hide column when filtering by collection
- showVersionColumn := versionCount > 1
-
- var singleDataCenter, singleRack, singleDiskType, singleCollection, singleVersion string
- var allVersions, allDiskTypes []string
-
- if dataCenterCount == 1 {
- for dc := range dataCenterMap {
- singleDataCenter = dc
- break
- }
- }
- if rackCount == 1 {
- for rack := range rackMap {
- singleRack = rack
- break
- }
- }
- if diskTypeCount == 1 {
- for diskType := range diskTypeMap {
- singleDiskType = diskType
- break
- }
- } else {
- // Collect all disk types and sort them
- for diskType := range diskTypeMap {
- allDiskTypes = append(allDiskTypes, diskType)
- }
- sort.Strings(allDiskTypes)
- }
- if collectionCount == 1 {
- for collection := range collectionMap {
- singleCollection = collection
- break
- }
- }
- if versionCount == 1 {
- for version := range versionMap {
- singleVersion = "v" + version
- break
- }
- } else {
- // Collect all versions and sort them
- for version := range versionMap {
- allVersions = append(allVersions, "v"+version)
- }
- sort.Strings(allVersions)
- }
-
- return &ClusterVolumesData{
- Volumes: volumes,
- TotalVolumes: totalVolumes,
- TotalSize: totalSize,
- LastUpdated: time.Now(),
- CurrentPage: page,
- TotalPages: totalPages,
- PageSize: pageSize,
- SortBy: sortBy,
- SortOrder: sortOrder,
- DataCenterCount: dataCenterCount,
- RackCount: rackCount,
- DiskTypeCount: diskTypeCount,
- CollectionCount: collectionCount,
- VersionCount: versionCount,
- ShowDataCenterColumn: showDataCenterColumn,
- ShowRackColumn: showRackColumn,
- ShowDiskTypeColumn: showDiskTypeColumn,
- ShowCollectionColumn: showCollectionColumn,
- ShowVersionColumn: showVersionColumn,
- SingleDataCenter: singleDataCenter,
- SingleRack: singleRack,
- SingleDiskType: singleDiskType,
- SingleCollection: singleCollection,
- SingleVersion: singleVersion,
- AllVersions: allVersions,
- AllDiskTypes: allDiskTypes,
- FilterCollection: collection,
- }, nil
-}
-
-// sortVolumes sorts the volumes slice based on the specified field and order
-func (s *AdminServer) sortVolumes(volumes []VolumeWithTopology, sortBy string, sortOrder string) {
- sort.Slice(volumes, func(i, j int) bool {
- var less bool
-
- switch sortBy {
- case "id":
- less = volumes[i].Id < volumes[j].Id
- case "server":
- less = volumes[i].Server < volumes[j].Server
- case "datacenter":
- less = volumes[i].DataCenter < volumes[j].DataCenter
- case "rack":
- less = volumes[i].Rack < volumes[j].Rack
- case "collection":
- less = volumes[i].Collection < volumes[j].Collection
- case "size":
- less = volumes[i].Size < volumes[j].Size
- case "filecount":
- less = volumes[i].FileCount < volumes[j].FileCount
- case "replication":
- less = volumes[i].ReplicaPlacement < volumes[j].ReplicaPlacement
- case "disktype":
- less = volumes[i].DiskType < volumes[j].DiskType
- case "version":
- less = volumes[i].Version < volumes[j].Version
- default:
- less = volumes[i].Id < volumes[j].Id
- }
-
- if sortOrder == "desc" {
- return !less
- }
- return less
- })
-}
-
-// GetClusterCollections retrieves cluster collections data
-func (s *AdminServer) GetClusterCollections() (*ClusterCollectionsData, error) {
- var collections []CollectionInfo
- var totalVolumes int
- var totalFiles int64
- var totalSize int64
- collectionMap := make(map[string]*CollectionInfo)
-
- // Get actual collection information from volume data
- err := s.WithMasterClient(func(client master_pb.SeaweedClient) error {
- resp, err := client.VolumeList(context.Background(), &master_pb.VolumeListRequest{})
- if err != nil {
- return err
- }
-
- if resp.TopologyInfo != nil {
- for _, dc := range resp.TopologyInfo.DataCenterInfos {
- for _, rack := range dc.RackInfos {
- for _, node := range rack.DataNodeInfos {
- for _, diskInfo := range node.DiskInfos {
- for _, volInfo := range diskInfo.VolumeInfos {
- // Extract collection name from volume info
- collectionName := volInfo.Collection
- if collectionName == "" {
- collectionName = "default" // Default collection for volumes without explicit collection
- }
-
- // Get disk type from volume info, default to hdd if empty
- diskType := volInfo.DiskType
- if diskType == "" {
- diskType = "hdd"
- }
-
- // Get or create collection info
- if collection, exists := collectionMap[collectionName]; exists {
- collection.VolumeCount++
- collection.FileCount += int64(volInfo.FileCount)
- collection.TotalSize += int64(volInfo.Size)
-
- // Update data center if this collection spans multiple DCs
- if collection.DataCenter != dc.Id && collection.DataCenter != "multi" {
- collection.DataCenter = "multi"
- }
-
- // Add disk type if not already present
- diskTypeExists := false
- for _, existingDiskType := range collection.DiskTypes {
- if existingDiskType == diskType {
- diskTypeExists = true
- break
- }
- }
- if !diskTypeExists {
- collection.DiskTypes = append(collection.DiskTypes, diskType)
- }
-
- totalVolumes++
- totalFiles += int64(volInfo.FileCount)
- totalSize += int64(volInfo.Size)
- } else {
- newCollection := CollectionInfo{
- Name: collectionName,
- DataCenter: dc.Id,
- VolumeCount: 1,
- FileCount: int64(volInfo.FileCount),
- TotalSize: int64(volInfo.Size),
- DiskTypes: []string{diskType},
- }
- collectionMap[collectionName] = &newCollection
- totalVolumes++
- totalFiles += int64(volInfo.FileCount)
- totalSize += int64(volInfo.Size)
- }
- }
- }
- }
- }
- }
- }
-
- return nil
- })
-
- if err != nil {
- return nil, err
- }
-
- // Convert map to slice
- for _, collection := range collectionMap {
- collections = append(collections, *collection)
- }
-
- // If no collections found, show a message indicating no collections exist
- if len(collections) == 0 {
- // Return empty collections data instead of creating fake ones
- return &ClusterCollectionsData{
- Collections: []CollectionInfo{},
- TotalCollections: 0,
- TotalVolumes: 0,
- TotalFiles: 0,
- TotalSize: 0,
- LastUpdated: time.Now(),
- }, nil
- }
-
- return &ClusterCollectionsData{
- Collections: collections,
- TotalCollections: len(collections),
- TotalVolumes: totalVolumes,
- TotalFiles: totalFiles,
- TotalSize: totalSize,
- LastUpdated: time.Now(),
- }, nil
-}
+// GetClusterCollections method moved to collection_management.go
// GetClusterMasters retrieves cluster masters data
func (s *AdminServer) GetClusterMasters() (*ClusterMastersData, error) {
@@ -1302,102 +563,8 @@ func (s *AdminServer) GetClusterFilers() (*ClusterFilersData, error) {
}, nil
}
-// GetAllFilers returns all discovered filers
-func (s *AdminServer) GetAllFilers() []string {
- return s.getDiscoveredFilers()
-}
-
-// GetVolumeDetails retrieves detailed information about a specific volume
-func (s *AdminServer) GetVolumeDetails(volumeID int, server string) (*VolumeDetailsData, error) {
- var primaryVolume VolumeWithTopology
- var replicas []VolumeWithTopology
- var volumeSizeLimit uint64
- var found bool
-
- // Find the volume and all its replicas in the cluster
- err := s.WithMasterClient(func(client master_pb.SeaweedClient) error {
- resp, err := client.VolumeList(context.Background(), &master_pb.VolumeListRequest{})
- if err != nil {
- return err
- }
-
- if resp.TopologyInfo != nil {
- for _, dc := range resp.TopologyInfo.DataCenterInfos {
- for _, rack := range dc.RackInfos {
- for _, node := range rack.DataNodeInfos {
- for _, diskInfo := range node.DiskInfos {
- for _, volInfo := range diskInfo.VolumeInfos {
- if int(volInfo.Id) == volumeID {
- diskType := volInfo.DiskType
- if diskType == "" {
- diskType = "hdd"
- }
-
- volume := VolumeWithTopology{
- VolumeInformationMessage: volInfo,
- Server: node.Id,
- DataCenter: dc.Id,
- Rack: rack.Id,
- }
-
- // If this is the requested server, it's the primary volume
- if node.Id == server {
- primaryVolume = volume
- found = true
- } else {
- // This is a replica on another server
- replicas = append(replicas, volume)
- }
- }
- }
- }
- }
- }
- }
- }
- return nil
- })
-
- if err != nil {
- return nil, err
- }
+// GetAllFilers method moved to client_management.go
- if !found {
- return nil, fmt.Errorf("volume %d not found on server %s", volumeID, server)
- }
+// GetVolumeDetails method moved to volume_management.go
- // Get volume size limit from master
- err = s.WithMasterClient(func(client master_pb.SeaweedClient) error {
- resp, err := client.GetMasterConfiguration(context.Background(), &master_pb.GetMasterConfigurationRequest{})
- if err != nil {
- return err
- }
- volumeSizeLimit = uint64(resp.VolumeSizeLimitMB) * 1024 * 1024 // Convert MB to bytes
- return nil
- })
-
- if err != nil {
- // If we can't get the limit, set a default
- volumeSizeLimit = 30 * 1024 * 1024 * 1024 // 30GB default
- }
-
- return &VolumeDetailsData{
- Volume: primaryVolume,
- Replicas: replicas,
- VolumeSizeLimit: volumeSizeLimit,
- ReplicationCount: len(replicas) + 1, // Include the primary volume
- LastUpdated: time.Now(),
- }, nil
-}
-
-// VacuumVolume performs a vacuum operation on a specific volume
-func (s *AdminServer) VacuumVolume(volumeID int, server string) error {
- return s.WithMasterClient(func(client master_pb.SeaweedClient) error {
- _, err := client.VacuumVolume(context.Background(), &master_pb.VacuumVolumeRequest{
- VolumeId: uint32(volumeID),
- GarbageThreshold: 0.0001, // A very low threshold to ensure all garbage is collected
- Collection: "", // Empty for all collections
- })
- return err
- })
-}
+// VacuumVolume method moved to volume_management.go