github.com/minio/madmin-go@v1.7.5/info-commands.go (about)

     1  //
     2  // MinIO Object Storage (c) 2021 MinIO, Inc.
     3  //
     4  // Licensed under the Apache License, Version 2.0 (the "License");
     5  // you may not use this file except in compliance with the License.
     6  // You may obtain a copy of the License at
     7  //
     8  //      http://www.apache.org/licenses/LICENSE-2.0
     9  //
    10  // Unless required by applicable law or agreed to in writing, software
    11  // distributed under the License is distributed on an "AS IS" BASIS,
    12  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  // See the License for the specific language governing permissions and
    14  // limitations under the License.
    15  //
    16  
    17  package madmin
    18  
    19  import (
    20  	"context"
    21  	"encoding/json"
    22  	"net/http"
    23  	"time"
    24  )
    25  
    26  // BackendType - represents different backend types.
    27  type BackendType int
    28  
    29  // Enum for different backend types.
    30  const (
    31  	Unknown BackendType = iota
    32  	// Filesystem backend.
    33  	FS
    34  	// Multi disk Erasure (single, distributed) backend.
    35  	Erasure
    36  	// Gateway to other storage
    37  	Gateway
    38  
    39  	// Add your own backend.
    40  )
    41  
    42  // ItemState - represents the status of any item in offline,init,online state
    43  type ItemState string
    44  
    45  const (
    46  
    47  	// ItemOffline indicates that the item is offline
    48  	ItemOffline = ItemState("offline")
    49  	// ItemInitializing indicates that the item is still in initialization phase
    50  	ItemInitializing = ItemState("initializing")
    51  	// ItemOnline indicates that the item is online
    52  	ItemOnline = ItemState("online")
    53  )
    54  
    55  // StorageInfo - represents total capacity of underlying storage.
    56  type StorageInfo struct {
    57  	Disks []Disk
    58  
    59  	// Backend type.
    60  	Backend BackendInfo
    61  }
    62  
    63  // BackendInfo - contains info of the underlying backend
    64  type BackendInfo struct {
    65  	// Represents various backend types, currently on FS, Erasure and Gateway
    66  	Type BackendType
    67  
    68  	// Following fields are only meaningful if BackendType is Gateway.
    69  	GatewayOnline bool
    70  
    71  	// Following fields are only meaningful if BackendType is Erasure.
    72  	OnlineDisks  BackendDisks // Online disks during server startup.
    73  	OfflineDisks BackendDisks // Offline disks during server startup.
    74  
    75  	// Following fields are only meaningful if BackendType is Erasure.
    76  	StandardSCData   []int // Data disks for currently configured Standard storage class.
    77  	StandardSCParity int   // Parity disks for currently configured Standard storage class.
    78  	RRSCData         []int // Data disks for currently configured Reduced Redundancy storage class.
    79  	RRSCParity       int   // Parity disks for currently configured Reduced Redundancy storage class.
    80  
    81  	// Adds number of erasure sets and drives per set.
    82  	TotalSets    []int // Each index value corresponds to per pool
    83  	DrivesPerSet []int // Each index value corresponds to per pool
    84  }
    85  
    86  // BackendDisks - represents the map of endpoint-disks.
    87  type BackendDisks map[string]int
    88  
    89  // Sum - Return the sum of the disks in the endpoint-disk map.
    90  func (d1 BackendDisks) Sum() (sum int) {
    91  	for _, count := range d1 {
    92  		sum += count
    93  	}
    94  	return sum
    95  }
    96  
    97  // Merge - Reduces two endpoint-disk maps.
    98  func (d1 BackendDisks) Merge(d2 BackendDisks) BackendDisks {
    99  	if len(d2) == 0 {
   100  		d2 = make(BackendDisks)
   101  	}
   102  	merged := make(BackendDisks)
   103  	for i1, v1 := range d1 {
   104  		if v2, ok := d2[i1]; ok {
   105  			merged[i1] = v2 + v1
   106  			continue
   107  		}
   108  		merged[i1] = v1
   109  	}
   110  	return merged
   111  }
   112  
   113  // StorageInfo - Connect to a minio server and call Storage Info Management API
   114  // to fetch server's information represented by StorageInfo structure
   115  func (adm *AdminClient) StorageInfo(ctx context.Context) (StorageInfo, error) {
   116  	resp, err := adm.executeMethod(ctx, http.MethodGet, requestData{relPath: adminAPIPrefix + "/storageinfo"})
   117  	defer closeResponse(resp)
   118  	if err != nil {
   119  		return StorageInfo{}, err
   120  	}
   121  
   122  	// Check response http status code
   123  	if resp.StatusCode != http.StatusOK {
   124  		return StorageInfo{}, httpRespToErrorResponse(resp)
   125  	}
   126  
   127  	// Unmarshal the server's json response
   128  	var storageInfo StorageInfo
   129  	if err = json.NewDecoder(resp.Body).Decode(&storageInfo); err != nil {
   130  		return StorageInfo{}, err
   131  	}
   132  
   133  	return storageInfo, nil
   134  }
   135  
   136  // BucketUsageInfo - bucket usage info provides
   137  // - total size of the bucket
   138  // - total objects in a bucket
   139  // - object size histogram per bucket
   140  type BucketUsageInfo struct {
   141  	Size                    uint64 `json:"size"`
   142  	ReplicationPendingSize  uint64 `json:"objectsPendingReplicationTotalSize"`
   143  	ReplicationFailedSize   uint64 `json:"objectsFailedReplicationTotalSize"`
   144  	ReplicatedSize          uint64 `json:"objectsReplicatedTotalSize"`
   145  	ReplicaSize             uint64 `json:"objectReplicaTotalSize"`
   146  	ReplicationPendingCount uint64 `json:"objectsPendingReplicationCount"`
   147  	ReplicationFailedCount  uint64 `json:"objectsFailedReplicationCount"`
   148  
   149  	VersionsCount        uint64            `json:"versionsCount"`
   150  	ObjectsCount         uint64            `json:"objectsCount"`
   151  	ObjectSizesHistogram map[string]uint64 `json:"objectsSizesHistogram"`
   152  }
   153  
   154  // DataUsageInfo represents data usage stats of the underlying Object API
   155  type DataUsageInfo struct {
   156  	// LastUpdate is the timestamp of when the data usage info was last updated.
   157  	// This does not indicate a full scan.
   158  	LastUpdate time.Time `json:"lastUpdate"`
   159  
   160  	// Objects total count across all buckets
   161  	ObjectsTotalCount uint64 `json:"objectsCount"`
   162  
   163  	// Objects total size across all buckets
   164  	ObjectsTotalSize uint64 `json:"objectsTotalSize"`
   165  
   166  	// Total Size for objects that have not yet been replicated
   167  	ReplicationPendingSize uint64 `json:"objectsPendingReplicationTotalSize"`
   168  
   169  	// Total size for objects that have witness one or more failures and will be retried
   170  	ReplicationFailedSize uint64 `json:"objectsFailedReplicationTotalSize"`
   171  
   172  	// Total size for objects that have been replicated to destination
   173  	ReplicatedSize uint64 `json:"objectsReplicatedTotalSize"`
   174  
   175  	// Total size for objects that are replicas
   176  	ReplicaSize uint64 `json:"objectsReplicaTotalSize"`
   177  
   178  	// Total number of objects pending replication
   179  	ReplicationPendingCount uint64 `json:"objectsPendingReplicationCount"`
   180  
   181  	// Total number of objects that failed replication
   182  	ReplicationFailedCount uint64 `json:"objectsFailedReplicationCount"`
   183  
   184  	// Total number of buckets in this cluster
   185  	BucketsCount uint64 `json:"bucketsCount"`
   186  
   187  	// Buckets usage info provides following information across all buckets
   188  	// - total size of the bucket
   189  	// - total objects in a bucket
   190  	// - object size histogram per bucket
   191  	BucketsUsage map[string]BucketUsageInfo `json:"bucketsUsageInfo"`
   192  
   193  	// TierStats holds per-tier stats like bytes tiered, etc.
   194  	TierStats map[string]TierStats `json:"tierStats"`
   195  
   196  	// Deprecated kept here for backward compatibility reasons.
   197  	BucketSizes map[string]uint64 `json:"bucketsSizes"`
   198  }
   199  
   200  // DataUsageInfo - returns data usage of the current object API
   201  func (adm *AdminClient) DataUsageInfo(ctx context.Context) (DataUsageInfo, error) {
   202  	resp, err := adm.executeMethod(ctx, http.MethodGet, requestData{relPath: adminAPIPrefix + "/datausageinfo"})
   203  	defer closeResponse(resp)
   204  	if err != nil {
   205  		return DataUsageInfo{}, err
   206  	}
   207  
   208  	// Check response http status code
   209  	if resp.StatusCode != http.StatusOK {
   210  		return DataUsageInfo{}, httpRespToErrorResponse(resp)
   211  	}
   212  
   213  	// Unmarshal the server's json response
   214  	var dataUsageInfo DataUsageInfo
   215  	if err = json.NewDecoder(resp.Body).Decode(&dataUsageInfo); err != nil {
   216  		return DataUsageInfo{}, err
   217  	}
   218  
   219  	return dataUsageInfo, nil
   220  }
   221  
   222  // InfoMessage container to hold server admin related information.
   223  type InfoMessage struct {
   224  	Mode         string             `json:"mode,omitempty"`
   225  	Domain       []string           `json:"domain,omitempty"`
   226  	Region       string             `json:"region,omitempty"`
   227  	SQSARN       []string           `json:"sqsARN,omitempty"`
   228  	DeploymentID string             `json:"deploymentID,omitempty"`
   229  	Buckets      Buckets            `json:"buckets,omitempty"`
   230  	Objects      Objects            `json:"objects,omitempty"`
   231  	Versions     Versions           `json:"versions,omitempty"`
   232  	Usage        Usage              `json:"usage,omitempty"`
   233  	Services     Services           `json:"services,omitempty"`
   234  	Backend      interface{}        `json:"backend,omitempty"`
   235  	Servers      []ServerProperties `json:"servers,omitempty"`
   236  }
   237  
   238  func (info InfoMessage) BackendType() BackendType {
   239  	// MinIO server type default
   240  	backendType := Unknown
   241  
   242  	// Set the type of MinIO server ("FS", "Erasure", "Unknown")
   243  	switch v := info.Backend.(type) {
   244  	case FSBackend:
   245  		backendType = FS
   246  	case ErasureBackend:
   247  		backendType = Erasure
   248  	case map[string]interface{}:
   249  		vt, ok := v["backendType"]
   250  		if ok {
   251  			backendTypeS, _ := vt.(string)
   252  			switch backendTypeS {
   253  			case "Erasure":
   254  				backendType = Erasure
   255  			}
   256  		}
   257  	}
   258  	return backendType
   259  }
   260  
   261  func (info InfoMessage) StandardParity() int {
   262  	switch info.BackendType() {
   263  	case Erasure:
   264  		switch v := info.Backend.(type) {
   265  		case ErasureBackend:
   266  			return v.StandardSCParity
   267  		case map[string]interface{}:
   268  			scParity, ok := v["standardSCParity"].(float64)
   269  			if ok {
   270  				return int(scParity)
   271  			}
   272  		}
   273  	}
   274  	return -1
   275  }
   276  
   277  // Services contains different services information
   278  type Services struct {
   279  	KMS           KMS                           `json:"kms,omitempty"`
   280  	LDAP          LDAP                          `json:"ldap,omitempty"`
   281  	Logger        []Logger                      `json:"logger,omitempty"`
   282  	Audit         []Audit                       `json:"audit,omitempty"`
   283  	Notifications []map[string][]TargetIDStatus `json:"notifications,omitempty"`
   284  }
   285  
   286  // Buckets contains the number of buckets
   287  type Buckets struct {
   288  	Count uint64 `json:"count"`
   289  	Error string `json:"error,omitempty"`
   290  }
   291  
   292  // Objects contains the number of objects
   293  type Objects struct {
   294  	Count uint64 `json:"count"`
   295  	Error string `json:"error,omitempty"`
   296  }
   297  
   298  // Versions contains the number of versions
   299  type Versions struct {
   300  	Count uint64 `json:"count"`
   301  	Error string `json:"error,omitempty"`
   302  }
   303  
   304  // Usage contains the total size used
   305  type Usage struct {
   306  	Size  uint64 `json:"size"`
   307  	Error string `json:"error,omitempty"`
   308  }
   309  
   310  // TierStats contains per-tier statistics like total size, number of
   311  // objects/versions transitioned, etc.
   312  type TierStats struct {
   313  	TotalSize   uint64 `json:"totalSize"`
   314  	NumVersions int    `json:"numVersions"`
   315  	NumObjects  int    `json:"numObjects"`
   316  }
   317  
   318  // KMS contains KMS status information
   319  type KMS struct {
   320  	Status  string `json:"status,omitempty"`
   321  	Encrypt string `json:"encrypt,omitempty"`
   322  	Decrypt string `json:"decrypt,omitempty"`
   323  }
   324  
   325  // LDAP contains ldap status
   326  type LDAP struct {
   327  	Status string `json:"status,omitempty"`
   328  }
   329  
   330  // Status of endpoint
   331  type Status struct {
   332  	Status string `json:"status,omitempty"`
   333  }
   334  
   335  // Audit contains audit logger status
   336  type Audit map[string]Status
   337  
   338  // Logger contains logger status
   339  type Logger map[string]Status
   340  
   341  // TargetIDStatus containsid and status
   342  type TargetIDStatus map[string]Status
   343  
   344  // backendType - indicates the type of backend storage
   345  type backendType string
   346  
   347  const (
   348  	// FsType - Backend is FS Type
   349  	FsType = backendType("FS")
   350  	// ErasureType - Backend is Erasure type
   351  	ErasureType = backendType("Erasure")
   352  )
   353  
   354  // FSBackend contains specific FS storage information
   355  type FSBackend struct {
   356  	Type backendType `json:"backendType,omitempty"`
   357  }
   358  
   359  // ErasureBackend contains specific erasure storage information
   360  type ErasureBackend struct {
   361  	Type         backendType `json:"backendType,omitempty"`
   362  	OnlineDisks  int         `json:"onlineDisks,omitempty"`
   363  	OfflineDisks int         `json:"offlineDisks,omitempty"`
   364  	// Parity disks for currently configured Standard storage class.
   365  	StandardSCParity int `json:"standardSCParity,omitempty"`
   366  	// Parity disks for currently configured Reduced Redundancy storage class.
   367  	RRSCParity int `json:"rrSCParity,omitempty"`
   368  }
   369  
   370  // ServerProperties holds server information
   371  type ServerProperties struct {
   372  	State          string            `json:"state,omitempty"`
   373  	Endpoint       string            `json:"endpoint,omitempty"`
   374  	Scheme         string            `json:"scheme,omitempty"`
   375  	Uptime         int64             `json:"uptime,omitempty"`
   376  	Version        string            `json:"version,omitempty"`
   377  	CommitID       string            `json:"commitID,omitempty"`
   378  	Network        map[string]string `json:"network,omitempty"`
   379  	Disks          []Disk            `json:"drives,omitempty"`
   380  	PoolNumber     int               `json:"poolNumber,omitempty"`
   381  	MemStats       MemStats          `json:"mem_stats"`
   382  	GoMaxProcs     int               `json:"go_max_procs,omitempty"`
   383  	NumCPU         int               `json:"num_cpu,omitempty"`
   384  	RuntimeVersion string            `json:"runtime_version,omitempty"`
   385  	GCStats        *GCStats          `json:"gc_stats,omitempty"`
   386  	MinioEnvVars   map[string]string `json:"minio_env_vars,omitempty"`
   387  }
   388  
   389  // DiskMetrics has the information about XL Storage APIs
   390  // the number of calls of each API and the moving average of
   391  // the duration, in nanosecond, of each API.
   392  type DiskMetrics struct {
   393  	LastMinute map[string]TimedAction `json:"lastMinute,omitempty"`
   394  	APICalls   map[string]uint64      `json:"apiCalls,omitempty"`
   395  
   396  	// Deprecated: Use LastMinute instead. Not populated from servers after July 2022.
   397  	APILatencies map[string]interface{} `json:"apiLatencies,omitempty"`
   398  }
   399  
   400  // Disk holds Disk information
   401  type Disk struct {
   402  	Endpoint        string       `json:"endpoint,omitempty"`
   403  	RootDisk        bool         `json:"rootDisk,omitempty"`
   404  	DrivePath       string       `json:"path,omitempty"`
   405  	Healing         bool         `json:"healing,omitempty"`
   406  	Scanning        bool         `json:"scanning,omitempty"`
   407  	State           string       `json:"state,omitempty"`
   408  	UUID            string       `json:"uuid,omitempty"`
   409  	Major           uint32       `json:"major"`
   410  	Minor           uint32       `json:"minor"`
   411  	Model           string       `json:"model,omitempty"`
   412  	TotalSpace      uint64       `json:"totalspace,omitempty"`
   413  	UsedSpace       uint64       `json:"usedspace,omitempty"`
   414  	AvailableSpace  uint64       `json:"availspace,omitempty"`
   415  	ReadThroughput  float64      `json:"readthroughput,omitempty"`
   416  	WriteThroughPut float64      `json:"writethroughput,omitempty"`
   417  	ReadLatency     float64      `json:"readlatency,omitempty"`
   418  	WriteLatency    float64      `json:"writelatency,omitempty"`
   419  	Utilization     float64      `json:"utilization,omitempty"`
   420  	Metrics         *DiskMetrics `json:"metrics,omitempty"`
   421  	HealInfo        *HealingDisk `json:"heal_info,omitempty"`
   422  	FreeInodes      uint64       `json:"free_inodes,omitempty"`
   423  
   424  	// Indexes, will be -1 until assigned a set.
   425  	PoolIndex int `json:"pool_index"`
   426  	SetIndex  int `json:"set_index"`
   427  	DiskIndex int `json:"disk_index"`
   428  }
   429  
   430  // ServerInfo - Connect to a minio server and call Server Admin Info Management API
   431  // to fetch server's information represented by infoMessage structure
   432  func (adm *AdminClient) ServerInfo(ctx context.Context) (InfoMessage, error) {
   433  	resp, err := adm.executeMethod(ctx,
   434  		http.MethodGet,
   435  		requestData{relPath: adminAPIPrefix + "/info"},
   436  	)
   437  	defer closeResponse(resp)
   438  	if err != nil {
   439  		return InfoMessage{}, err
   440  	}
   441  
   442  	// Check response http status code
   443  	if resp.StatusCode != http.StatusOK {
   444  		return InfoMessage{}, httpRespToErrorResponse(resp)
   445  	}
   446  
   447  	// Unmarshal the server's json response
   448  	var message InfoMessage
   449  	if err = json.NewDecoder(resp.Body).Decode(&message); err != nil {
   450  		return InfoMessage{}, err
   451  	}
   452  
   453  	return message, nil
   454  }