You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							127 lines
						
					
					
						
							3.4 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							127 lines
						
					
					
						
							3.4 KiB
						
					
					
				
								package dash
							 | 
						|
								
							 | 
						|
								import (
							 | 
						|
									"context"
							 | 
						|
									"fmt"
							 | 
						|
									"time"
							 | 
						|
								
							 | 
						|
									"github.com/seaweedfs/seaweedfs/weed/glog"
							 | 
						|
									"github.com/seaweedfs/seaweedfs/weed/pb/master_pb"
							 | 
						|
								)
							 | 
						|
								
							 | 
						|
								// 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 {
							 | 
						|
										currentMaster := s.masterClient.GetMaster(context.Background())
							 | 
						|
										glog.Errorf("Failed to connect to master server %s: %v", currentMaster, err)
							 | 
						|
										return nil, fmt.Errorf("gRPC topology request failed: %w", 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 {
							 | 
						|
											currentMaster := s.masterClient.GetMaster(context.Background())
							 | 
						|
											glog.Errorf("Failed to get volume list from master %s: %v", currentMaster, 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
							 | 
						|
								
							 | 
						|
															// Sum up individual volume information
							 | 
						|
															for _, volInfo := range diskInfo.VolumeInfos {
							 | 
						|
																totalSize += int64(volInfo.Size)
							 | 
						|
																totalFiles += int64(volInfo.FileCount)
							 | 
						|
															}
							 | 
						|
								
							 | 
						|
															// Sum up EC shard sizes
							 | 
						|
															for _, ecShardInfo := range diskInfo.EcShardInfos {
							 | 
						|
																for _, shardSize := range ecShardInfo.ShardSizes {
							 | 
						|
																	totalSize += shardSize
							 | 
						|
																}
							 | 
						|
															}
							 | 
						|
														}
							 | 
						|
								
							 | 
						|
														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(),
							 | 
						|
														}
							 | 
						|
								
							 | 
						|
														rackObj.Nodes = append(rackObj.Nodes, vs)
							 | 
						|
														topology.VolumeServers = append(topology.VolumeServers, vs)
							 | 
						|
														topology.TotalVolumes += vs.Volumes
							 | 
						|
														topology.TotalFiles += totalFiles
							 | 
						|
														topology.TotalSize += totalSize
							 | 
						|
													}
							 | 
						|
								
							 | 
						|
													dataCenter.Racks = append(dataCenter.Racks, rackObj)
							 | 
						|
												}
							 | 
						|
								
							 | 
						|
												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
							 | 
						|
								}
							 |