mirror of
				https://github.com/minio/minio.git
				synced 2025-10-31 08:11:19 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			114 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			114 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright (c) 2022 MinIO, Inc.
 | |
| //
 | |
| // This file is part of MinIO Object Storage stack
 | |
| //
 | |
| // This program is free software: you can redistribute it and/or modify
 | |
| // it under the terms of the GNU Affero General Public License as published by
 | |
| // the Free Software Foundation, either version 3 of the License, or
 | |
| // (at your option) any later version.
 | |
| //
 | |
| // This program is distributed in the hope that it will be useful
 | |
| // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
| // GNU Affero General Public License for more details.
 | |
| //
 | |
| // You should have received a copy of the GNU Affero General Public License
 | |
| // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | |
| 
 | |
| package cmd
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"time"
 | |
| )
 | |
| 
 | |
| type rebalPoolProgress struct {
 | |
| 	NumObjects  uint64        `json:"objects"`
 | |
| 	NumVersions uint64        `json:"versions"`
 | |
| 	Bytes       uint64        `json:"bytes"`
 | |
| 	Bucket      string        `json:"bucket"`
 | |
| 	Object      string        `json:"object"`
 | |
| 	Elapsed     time.Duration `json:"elapsed"`
 | |
| 	ETA         time.Duration `json:"eta"`
 | |
| }
 | |
| 
 | |
| type rebalancePoolStatus struct {
 | |
| 	ID       int               `json:"id"`                 // Pool index (zero-based)
 | |
| 	Status   string            `json:"status"`             // Active if rebalance is running, empty otherwise
 | |
| 	Used     float64           `json:"used"`               // Percentage used space
 | |
| 	Progress rebalPoolProgress `json:"progress,omitempty"` // is empty when rebalance is not running
 | |
| }
 | |
| 
 | |
| // rebalanceAdminStatus holds rebalance status related information exported to mc, console, etc.
 | |
| type rebalanceAdminStatus struct {
 | |
| 	ID        string                // identifies the ongoing rebalance operation by a uuid
 | |
| 	Pools     []rebalancePoolStatus `json:"pools"` // contains all pools, including inactive
 | |
| 	StoppedAt time.Time             `json:"stoppedAt,omitempty"`
 | |
| }
 | |
| 
 | |
| func rebalanceStatus(ctx context.Context, z *erasureServerPools) (r rebalanceAdminStatus, err error) {
 | |
| 	// Load latest rebalance status
 | |
| 	meta := &rebalanceMeta{}
 | |
| 	err = meta.load(ctx, z.serverPools[0])
 | |
| 	if err != nil {
 | |
| 		return r, err
 | |
| 	}
 | |
| 
 | |
| 	// Compute disk usage percentage
 | |
| 	si := z.StorageInfo(ctx, true)
 | |
| 	diskStats := make([]struct {
 | |
| 		AvailableSpace uint64
 | |
| 		TotalSpace     uint64
 | |
| 	}, len(z.serverPools))
 | |
| 	for _, disk := range si.Disks {
 | |
| 		// Ignore invalid.
 | |
| 		if disk.PoolIndex < 0 || len(diskStats) <= disk.PoolIndex {
 | |
| 			// https://github.com/minio/minio/issues/16500
 | |
| 			continue
 | |
| 		}
 | |
| 		diskStats[disk.PoolIndex].AvailableSpace += disk.AvailableSpace
 | |
| 		diskStats[disk.PoolIndex].TotalSpace += disk.TotalSpace
 | |
| 	}
 | |
| 
 | |
| 	stopTime := meta.StoppedAt
 | |
| 	r = rebalanceAdminStatus{
 | |
| 		ID:        meta.ID,
 | |
| 		StoppedAt: meta.StoppedAt,
 | |
| 		Pools:     make([]rebalancePoolStatus, len(meta.PoolStats)),
 | |
| 	}
 | |
| 	for i, ps := range meta.PoolStats {
 | |
| 		r.Pools[i] = rebalancePoolStatus{
 | |
| 			ID:     i,
 | |
| 			Status: ps.Info.Status.String(),
 | |
| 			Used:   float64(diskStats[i].TotalSpace-diskStats[i].AvailableSpace) / float64(diskStats[i].TotalSpace),
 | |
| 		}
 | |
| 		if !ps.Participating {
 | |
| 			continue
 | |
| 		}
 | |
| 		// for participating pools, total bytes to be rebalanced by this pool is given by,
 | |
| 		// pf_c = (f_i + x)/c_i,
 | |
| 		// pf_c - percentage free space across pools, f_i - ith pool's free space, c_i - ith pool's capacity
 | |
| 		// i.e. x = c_i*pfc -f_i
 | |
| 		totalBytesToRebal := float64(ps.InitCapacity)*meta.PercentFreeGoal - float64(ps.InitFreeSpace)
 | |
| 		elapsed := time.Since(ps.Info.StartTime)
 | |
| 		eta := time.Duration(totalBytesToRebal * float64(elapsed) / float64(ps.Bytes))
 | |
| 		if !ps.Info.EndTime.IsZero() {
 | |
| 			stopTime = ps.Info.EndTime
 | |
| 		}
 | |
| 
 | |
| 		if !stopTime.IsZero() { // rebalance is stopped or completed
 | |
| 			elapsed = stopTime.Sub(ps.Info.StartTime)
 | |
| 			eta = 0
 | |
| 		}
 | |
| 
 | |
| 		r.Pools[i].Progress = rebalPoolProgress{
 | |
| 			NumObjects:  ps.NumObjects,
 | |
| 			NumVersions: ps.NumVersions,
 | |
| 			Bytes:       ps.Bytes,
 | |
| 			Elapsed:     elapsed,
 | |
| 			ETA:         eta,
 | |
| 		}
 | |
| 	}
 | |
| 	return r, nil
 | |
| }
 |