github.com/minio/madmin-go/v3@v3.0.51/info-commands.go (about) 1 // 2 // Copyright (c) 2015-2022 MinIO, Inc. 3 // 4 // This file is part of MinIO Object Storage stack 5 // 6 // This program is free software: you can redistribute it and/or modify 7 // it under the terms of the GNU Affero General Public License as 8 // published by the Free Software Foundation, either version 3 of the 9 // License, or (at your option) any later version. 10 // 11 // This program is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU Affero General Public License for more details. 15 // 16 // You should have received a copy of the GNU Affero General Public License 17 // along with this program. If not, see <http://www.gnu.org/licenses/>. 18 // 19 20 package madmin 21 22 import ( 23 "context" 24 "encoding/json" 25 "net/http" 26 "net/url" 27 "strconv" 28 "time" 29 ) 30 31 // BackendType - represents different backend types. 32 type BackendType int 33 34 // Enum for different backend types. 35 const ( 36 Unknown BackendType = iota 37 // Filesystem backend. 38 FS 39 // Multi disk Erasure (single, distributed) backend. 40 Erasure 41 // Gateway to other storage 42 Gateway 43 44 // Add your own backend. 45 ) 46 47 // ItemState - represents the status of any item in offline,init,online state 48 type ItemState string 49 50 const ( 51 52 // ItemOffline indicates that the item is offline 53 ItemOffline = ItemState("offline") 54 // ItemInitializing indicates that the item is still in initialization phase 55 ItemInitializing = ItemState("initializing") 56 // ItemOnline indicates that the item is online 57 ItemOnline = ItemState("online") 58 ) 59 60 // StorageInfo - represents total capacity of underlying storage. 61 type StorageInfo struct { 62 Disks []Disk 63 64 // Backend type. 65 Backend BackendInfo 66 } 67 68 // BackendInfo - contains info of the underlying backend 69 type BackendInfo struct { 70 // Represents various backend types, currently on FS, Erasure and Gateway 71 Type BackendType 72 73 // Following fields are only meaningful if BackendType is Gateway. 74 GatewayOnline bool 75 76 // Following fields are only meaningful if BackendType is Erasure. 77 OnlineDisks BackendDisks // Online disks during server startup. 78 OfflineDisks BackendDisks // Offline disks during server startup. 79 80 // Following fields are only meaningful if BackendType is Erasure. 81 StandardSCData []int // Data disks for currently configured Standard storage class. 82 StandardSCParities []int // Parity disks per pool for currently configured Standard storage class 83 RRSCData []int // Data disks for currently configured Reduced Redundancy storage class. 84 RRSCParities []int // Parity disks per pool for currently configured Reduced Redundancy storage class. 85 86 // Adds number of erasure sets and drives per set. 87 TotalSets []int // Each index value corresponds to per pool 88 DrivesPerSet []int // Each index value corresponds to per pool 89 90 // Deprecated Aug 2023 91 StandardSCParity int // Parity disks for currently configured Standard storage class. 92 RRSCParity int // Parity disks for currently configured Reduced Redundancy storage class. 93 } 94 95 // BackendDisks - represents the map of endpoint-disks. 96 type BackendDisks map[string]int 97 98 // Sum - Return the sum of the disks in the endpoint-disk map. 99 func (d1 BackendDisks) Sum() (sum int) { 100 for _, count := range d1 { 101 sum += count 102 } 103 return sum 104 } 105 106 // Merge - Reduces two endpoint-disk maps. 107 func (d1 BackendDisks) Merge(d2 BackendDisks) BackendDisks { 108 if len(d2) == 0 { 109 d2 = make(BackendDisks) 110 } 111 merged := make(BackendDisks) 112 for i1, v1 := range d1 { 113 if v2, ok := d2[i1]; ok { 114 merged[i1] = v2 + v1 115 continue 116 } 117 merged[i1] = v1 118 } 119 return merged 120 } 121 122 // StorageInfo - Connect to a minio server and call Storage Info Management API 123 // to fetch server's information represented by StorageInfo structure 124 func (adm *AdminClient) StorageInfo(ctx context.Context) (StorageInfo, error) { 125 resp, err := adm.executeMethod(ctx, http.MethodGet, requestData{relPath: adminAPIPrefix + "/storageinfo"}) 126 defer closeResponse(resp) 127 if err != nil { 128 return StorageInfo{}, err 129 } 130 131 // Check response http status code 132 if resp.StatusCode != http.StatusOK { 133 return StorageInfo{}, httpRespToErrorResponse(resp) 134 } 135 136 // Unmarshal the server's json response 137 var storageInfo StorageInfo 138 if err = json.NewDecoder(resp.Body).Decode(&storageInfo); err != nil { 139 return StorageInfo{}, err 140 } 141 142 return storageInfo, nil 143 } 144 145 // BucketUsageInfo - bucket usage info provides 146 // - total size of the bucket 147 // - total objects in a bucket 148 // - object size histogram per bucket 149 type BucketUsageInfo struct { 150 Size uint64 `json:"size"` 151 ReplicationPendingSize uint64 `json:"objectsPendingReplicationTotalSize"` 152 ReplicationFailedSize uint64 `json:"objectsFailedReplicationTotalSize"` 153 ReplicatedSize uint64 `json:"objectsReplicatedTotalSize"` 154 ReplicaSize uint64 `json:"objectReplicaTotalSize"` 155 ReplicationPendingCount uint64 `json:"objectsPendingReplicationCount"` 156 ReplicationFailedCount uint64 `json:"objectsFailedReplicationCount"` 157 158 VersionsCount uint64 `json:"versionsCount"` 159 ObjectsCount uint64 `json:"objectsCount"` 160 DeleteMarkersCount uint64 `json:"deleteMarkersCount"` 161 ObjectSizesHistogram map[string]uint64 `json:"objectsSizesHistogram"` 162 ObjectVersionsHistogram map[string]uint64 `json:"objectsVersionsHistogram"` 163 } 164 165 // DataUsageInfo represents data usage stats of the underlying Object API 166 type DataUsageInfo struct { 167 // LastUpdate is the timestamp of when the data usage info was last updated. 168 // This does not indicate a full scan. 169 LastUpdate time.Time `json:"lastUpdate"` 170 171 // Objects total count across all buckets 172 ObjectsTotalCount uint64 `json:"objectsCount"` 173 174 // Objects total size across all buckets 175 ObjectsTotalSize uint64 `json:"objectsTotalSize"` 176 177 // Total Size for objects that have not yet been replicated 178 ReplicationPendingSize uint64 `json:"objectsPendingReplicationTotalSize"` 179 180 // Total size for objects that have witness one or more failures and will be retried 181 ReplicationFailedSize uint64 `json:"objectsFailedReplicationTotalSize"` 182 183 // Total size for objects that have been replicated to destination 184 ReplicatedSize uint64 `json:"objectsReplicatedTotalSize"` 185 186 // Total size for objects that are replicas 187 ReplicaSize uint64 `json:"objectsReplicaTotalSize"` 188 189 // Total number of objects pending replication 190 ReplicationPendingCount uint64 `json:"objectsPendingReplicationCount"` 191 192 // Total number of objects that failed replication 193 ReplicationFailedCount uint64 `json:"objectsFailedReplicationCount"` 194 195 // Total number of buckets in this cluster 196 BucketsCount uint64 `json:"bucketsCount"` 197 198 // Buckets usage info provides following information across all buckets 199 // - total size of the bucket 200 // - total objects in a bucket 201 // - object size histogram per bucket 202 BucketsUsage map[string]BucketUsageInfo `json:"bucketsUsageInfo"` 203 204 // TierStats holds per-tier stats like bytes tiered, etc. 205 TierStats map[string]TierStats `json:"tierStats"` 206 207 // Deprecated kept here for backward compatibility reasons. 208 BucketSizes map[string]uint64 `json:"bucketsSizes"` 209 210 // Server capacity related data 211 TotalCapacity uint64 `json:"capacity"` 212 TotalFreeCapacity uint64 `json:"freeCapacity"` 213 TotalUsedCapacity uint64 `json:"usedCapacity"` 214 } 215 216 // DataUsageInfo - returns data usage of the current object API 217 func (adm *AdminClient) DataUsageInfo(ctx context.Context) (DataUsageInfo, error) { 218 values := make(url.Values) 219 values.Set("capacity", "true") // We can make this configurable in future but for now its fine. 220 221 resp, err := adm.executeMethod(ctx, http.MethodGet, requestData{ 222 relPath: adminAPIPrefix + "/datausageinfo", 223 queryValues: values, 224 }) 225 defer closeResponse(resp) 226 if err != nil { 227 return DataUsageInfo{}, err 228 } 229 230 // Check response http status code 231 if resp.StatusCode != http.StatusOK { 232 return DataUsageInfo{}, httpRespToErrorResponse(resp) 233 } 234 235 // Unmarshal the server's json response 236 var dataUsageInfo DataUsageInfo 237 if err = json.NewDecoder(resp.Body).Decode(&dataUsageInfo); err != nil { 238 return DataUsageInfo{}, err 239 } 240 241 return dataUsageInfo, nil 242 } 243 244 // ErasureSetInfo provides information per erasure set 245 type ErasureSetInfo struct { 246 ID int `json:"id"` 247 RawUsage uint64 `json:"rawUsage"` 248 RawCapacity uint64 `json:"rawCapacity"` 249 Usage uint64 `json:"usage"` 250 ObjectsCount uint64 `json:"objectsCount"` 251 VersionsCount uint64 `json:"versionsCount"` 252 DeleteMarkersCount uint64 `json:"deleteMarkersCount"` 253 HealDisks int `json:"healDisks"` 254 } 255 256 // InfoMessage container to hold server admin related information. 257 type InfoMessage struct { 258 Mode string `json:"mode,omitempty"` 259 Domain []string `json:"domain,omitempty"` 260 Region string `json:"region,omitempty"` 261 SQSARN []string `json:"sqsARN,omitempty"` 262 DeploymentID string `json:"deploymentID,omitempty"` 263 Buckets Buckets `json:"buckets,omitempty"` 264 Objects Objects `json:"objects,omitempty"` 265 Versions Versions `json:"versions,omitempty"` 266 DeleteMarkers DeleteMarkers `json:"deletemarkers,omitempty"` 267 Usage Usage `json:"usage,omitempty"` 268 Services Services `json:"services,omitempty"` 269 Backend ErasureBackend `json:"backend,omitempty"` 270 Servers []ServerProperties `json:"servers,omitempty"` 271 272 Pools map[int]map[int]ErasureSetInfo `json:"pools,omitempty"` 273 } 274 275 func (info InfoMessage) BackendType() BackendType { 276 // MinIO server type default 277 switch info.Backend.Type { 278 case "Erasure": 279 return Erasure 280 case "FS": 281 return FS 282 default: 283 return Unknown 284 } 285 } 286 287 func (info InfoMessage) StandardParity() int { 288 switch info.BackendType() { 289 case Erasure: 290 return info.Backend.StandardSCParity 291 default: 292 return -1 293 } 294 } 295 296 // Services contains different services information 297 type Services struct { 298 KMS KMS `json:"kms,omitempty"` // deprecated july 2023 299 KMSStatus []KMS `json:"kmsStatus,omitempty"` 300 LDAP LDAP `json:"ldap,omitempty"` 301 Logger []Logger `json:"logger,omitempty"` 302 Audit []Audit `json:"audit,omitempty"` 303 Notifications []map[string][]TargetIDStatus `json:"notifications,omitempty"` 304 } 305 306 // Buckets contains the number of buckets 307 type Buckets struct { 308 Count uint64 `json:"count"` 309 Error string `json:"error,omitempty"` 310 } 311 312 // Objects contains the number of objects 313 type Objects struct { 314 Count uint64 `json:"count"` 315 Error string `json:"error,omitempty"` 316 } 317 318 // Versions contains the number of versions 319 type Versions struct { 320 Count uint64 `json:"count"` 321 Error string `json:"error,omitempty"` 322 } 323 324 // DeleteMarkers contains the number of delete markers 325 type DeleteMarkers struct { 326 Count uint64 `json:"count"` 327 Error string `json:"error,omitempty"` 328 } 329 330 // Usage contains the total size used 331 type Usage struct { 332 Size uint64 `json:"size"` 333 Error string `json:"error,omitempty"` 334 } 335 336 // TierStats contains per-tier statistics like total size, number of 337 // objects/versions transitioned, etc. 338 type TierStats struct { 339 TotalSize uint64 `json:"totalSize"` 340 NumVersions int `json:"numVersions"` 341 NumObjects int `json:"numObjects"` 342 } 343 344 // KMS contains KMS status information 345 type KMS struct { 346 Status string `json:"status,omitempty"` 347 Encrypt string `json:"encrypt,omitempty"` 348 Decrypt string `json:"decrypt,omitempty"` 349 Endpoint string `json:"endpoint,omitempty"` 350 Version string `json:"version,omitempty"` 351 } 352 353 // LDAP contains ldap status 354 type LDAP struct { 355 Status string `json:"status,omitempty"` 356 } 357 358 // Status of endpoint 359 type Status struct { 360 Status string `json:"status,omitempty"` 361 } 362 363 // Audit contains audit logger status 364 type Audit map[string]Status 365 366 // Logger contains logger status 367 type Logger map[string]Status 368 369 // TargetIDStatus containsid and status 370 type TargetIDStatus map[string]Status 371 372 // backendType - indicates the type of backend storage 373 type backendType string 374 375 const ( 376 // FsType - Backend is FS Type 377 FsType = backendType("FS") 378 // ErasureType - Backend is Erasure type 379 ErasureType = backendType("Erasure") 380 ) 381 382 // FSBackend contains specific FS storage information 383 type FSBackend struct { 384 Type backendType `json:"backendType"` 385 } 386 387 // ErasureBackend contains specific erasure storage information 388 type ErasureBackend struct { 389 Type backendType `json:"backendType"` 390 OnlineDisks int `json:"onlineDisks"` 391 OfflineDisks int `json:"offlineDisks"` 392 // Parity disks for currently configured Standard storage class. 393 StandardSCParity int `json:"standardSCParity"` 394 // Parity disks for currently configured Reduced Redundancy storage class. 395 RRSCParity int `json:"rrSCParity"` 396 397 // Per pool information 398 TotalSets []int `json:"totalSets"` 399 DrivesPerSet []int `json:"totalDrivesPerSet"` 400 } 401 402 // ServerProperties holds server information 403 type ServerProperties struct { 404 State string `json:"state,omitempty"` 405 Endpoint string `json:"endpoint,omitempty"` 406 Scheme string `json:"scheme,omitempty"` 407 Uptime int64 `json:"uptime,omitempty"` 408 Version string `json:"version,omitempty"` 409 CommitID string `json:"commitID,omitempty"` 410 Network map[string]string `json:"network,omitempty"` 411 Disks []Disk `json:"drives,omitempty"` 412 PoolNumber int `json:"poolNumber,omitempty"` // Only set if len(PoolNumbers) == 1 413 PoolNumbers []int `json:"poolNumbers,omitempty"` 414 MemStats MemStats `json:"mem_stats"` 415 GoMaxProcs int `json:"go_max_procs,omitempty"` 416 NumCPU int `json:"num_cpu,omitempty"` 417 RuntimeVersion string `json:"runtime_version,omitempty"` 418 GCStats *GCStats `json:"gc_stats,omitempty"` 419 MinioEnvVars map[string]string `json:"minio_env_vars,omitempty"` 420 } 421 422 // DiskMetrics has the information about XL Storage APIs 423 // the number of calls of each API and the moving average of 424 // the duration, in nanosecond, of each API. 425 type DiskMetrics struct { 426 LastMinute map[string]TimedAction `json:"lastMinute,omitempty"` 427 APICalls map[string]uint64 `json:"apiCalls,omitempty"` 428 429 // TotalTokens set per drive max concurrent I/O. 430 TotalTokens uint32 `json:"totalTokens,omitempty"` 431 // TotalWaiting the amount of concurrent I/O waiting on disk 432 TotalWaiting uint32 `json:"totalWaiting,omitempty"` 433 434 // Captures all data availability errors such as 435 // permission denied, faulty disk and timeout errors. 436 TotalErrorsAvailability uint64 `json:"totalErrorsAvailability,omitempty"` 437 // Captures all timeout only errors 438 TotalErrorsTimeout uint64 `json:"totalErrorsTimeout,omitempty"` 439 440 // Total writes on disk (could be empty if the feature 441 // is not enabled on the server) 442 TotalWrites uint64 `json:"totalWrites,omitempty"` 443 // Total deletes on disk (could be empty if the feature 444 // is not enabled on the server) 445 TotalDeletes uint64 `json:"totalDeletes,omitempty"` 446 447 // Deprecated: Use LastMinute instead. Not populated from servers after July 2022. 448 APILatencies map[string]interface{} `json:"apiLatencies,omitempty"` 449 } 450 451 // Disk holds Disk information 452 type Disk struct { 453 Endpoint string `json:"endpoint,omitempty"` 454 RootDisk bool `json:"rootDisk,omitempty"` 455 DrivePath string `json:"path,omitempty"` 456 Healing bool `json:"healing,omitempty"` 457 Scanning bool `json:"scanning,omitempty"` 458 State string `json:"state,omitempty"` 459 UUID string `json:"uuid,omitempty"` 460 Major uint32 `json:"major"` 461 Minor uint32 `json:"minor"` 462 Model string `json:"model,omitempty"` 463 TotalSpace uint64 `json:"totalspace,omitempty"` 464 UsedSpace uint64 `json:"usedspace,omitempty"` 465 AvailableSpace uint64 `json:"availspace,omitempty"` 466 ReadThroughput float64 `json:"readthroughput,omitempty"` 467 WriteThroughPut float64 `json:"writethroughput,omitempty"` 468 ReadLatency float64 `json:"readlatency,omitempty"` 469 WriteLatency float64 `json:"writelatency,omitempty"` 470 Utilization float64 `json:"utilization,omitempty"` 471 Metrics *DiskMetrics `json:"metrics,omitempty"` 472 HealInfo *HealingDisk `json:"heal_info,omitempty"` 473 UsedInodes uint64 `json:"used_inodes"` 474 FreeInodes uint64 `json:"free_inodes,omitempty"` 475 Local bool `json:"local,omitempty"` 476 477 // Indexes, will be -1 until assigned a set. 478 PoolIndex int `json:"pool_index"` 479 SetIndex int `json:"set_index"` 480 DiskIndex int `json:"disk_index"` 481 } 482 483 // ServerInfoOpts ask for additional data from the server 484 type ServerInfoOpts struct { 485 Metrics bool 486 } 487 488 // WithDriveMetrics asks server to return additional metrics per drive 489 func WithDriveMetrics(metrics bool) func(*ServerInfoOpts) { 490 return func(opts *ServerInfoOpts) { 491 opts.Metrics = metrics 492 } 493 } 494 495 // ServerInfo - Connect to a minio server and call Server Admin Info Management API 496 // to fetch server's information represented by infoMessage structure 497 func (adm *AdminClient) ServerInfo(ctx context.Context, options ...func(*ServerInfoOpts)) (InfoMessage, error) { 498 srvOpts := &ServerInfoOpts{} 499 500 for _, o := range options { 501 o(srvOpts) 502 } 503 504 values := make(url.Values) 505 values.Set("metrics", strconv.FormatBool(srvOpts.Metrics)) 506 507 resp, err := adm.executeMethod(ctx, 508 http.MethodGet, 509 requestData{ 510 relPath: adminAPIPrefix + "/info", 511 queryValues: values, 512 }) 513 defer closeResponse(resp) 514 if err != nil { 515 return InfoMessage{}, err 516 } 517 518 // Check response http status code 519 if resp.StatusCode != http.StatusOK { 520 return InfoMessage{}, httpRespToErrorResponse(resp) 521 } 522 523 // Unmarshal the server's json response 524 var message InfoMessage 525 if err = json.NewDecoder(resp.Body).Decode(&message); err != nil { 526 return InfoMessage{}, err 527 } 528 529 return message, nil 530 }