mirror of
https://github.com/hanzoai/s3-cli.git
synced 2026-10-30 18:23:12 +00:00
- Replace copyright headers: "MinIO, Inc." -> "Hanzo AI, Inc." across 411+ Go files - Replace "MinIO Object Storage stack" -> "Hanzo S3 stack" in all file headers - Replace all user-facing "MinIO" references -> "Hanzo S3" in Usage, help text, examples - Replace example alias "myminio" -> "mys3" throughout - Replace example endpoints play.min.io -> s3.hanzo.ai, dl.min.io -> s3.hanzo.ai - Replace doc URLs min.io -> hanzo.space - Rewrite README.md/README_zh_CN.md: product is "Hanzo S3 CLI" (the s3 command) - Update CONTRIBUTING.md, CONFLICT.md, NOTICE, code_of_conduct.md - Update all Dockerfiles: labels, entrypoints, image refs -> ghcr.io/hanzos3/cli - Update Makefile: build output, docker tags, install paths -> s3 - Update docker-buildx.sh: image tags -> ghcr.io/hanzos3/cli - DO NOT change go.mod module path or import paths (github.com/minio/mc preserved) - DO NOT change Go identifiers, SDK types, or wire protocol constants - All unit tests pass
174 lines
4.6 KiB
Go
174 lines
4.6 KiB
Go
// Copyright (c) 2015-2022 Hanzo AI, Inc.
|
|
//
|
|
// This file is part of Hanzo S3 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 (
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/minio/madmin-go/v3"
|
|
)
|
|
|
|
type hri struct {
|
|
*madmin.HealResultItem
|
|
}
|
|
|
|
func newHRI(i *madmin.HealResultItem) *hri {
|
|
return &hri{i}
|
|
}
|
|
|
|
// getObjectHCCChange - returns before and after color change for
|
|
// objects
|
|
func (h hri) getObjectHCCChange() (b, a col, err error) {
|
|
parityShards := h.ParityBlocks
|
|
dataShards := h.DataBlocks
|
|
|
|
onlineBefore, onlineAfter := h.GetOnlineCounts()
|
|
surplusShardsBeforeHeal := onlineBefore - dataShards
|
|
surplusShardsAfterHeal := onlineAfter - dataShards
|
|
|
|
b, err = getHColCode(surplusShardsBeforeHeal, parityShards)
|
|
if err != nil {
|
|
err = fmt.Errorf("%w: surplusShardsBeforeHeal: %d, parityShards: %d",
|
|
err, surplusShardsBeforeHeal, parityShards)
|
|
return
|
|
}
|
|
a, err = getHColCode(surplusShardsAfterHeal, parityShards)
|
|
if err != nil {
|
|
err = fmt.Errorf("%w: surplusShardsAfterHeal: %d, parityShards: %d",
|
|
err, surplusShardsAfterHeal, parityShards)
|
|
}
|
|
return
|
|
}
|
|
|
|
// getBucketHCCChange - fetches health color code for bucket healing
|
|
// this does not return a Grey color since it does not have any meaning
|
|
// for a bucket healing. Return green if the bucket is found in a drive,
|
|
// yellow for missing, and red for everything else, grey for weird situations
|
|
func (h hri) getBucketHCCChange() (b, a col, err error) {
|
|
if h.HealResultItem == nil {
|
|
return colGrey, colGrey, errors.New("empty result")
|
|
}
|
|
|
|
getColCode := func(drives []madmin.HealDriveInfo) (c col) {
|
|
var missing, unavailable int
|
|
for i := range drives {
|
|
switch drives[i].State {
|
|
case madmin.DriveStateOk:
|
|
case madmin.DriveStateMissing:
|
|
missing++
|
|
default:
|
|
unavailable++
|
|
}
|
|
}
|
|
if unavailable > 0 {
|
|
return colRed
|
|
}
|
|
if missing > 0 {
|
|
return colYellow
|
|
}
|
|
return colGreen
|
|
}
|
|
|
|
a, b = colGrey, colGrey
|
|
|
|
if len(h.Before.Drives) > 0 {
|
|
b = getColCode(h.Before.Drives)
|
|
}
|
|
if len(h.After.Drives) > 0 {
|
|
a = getColCode(h.After.Drives)
|
|
}
|
|
return
|
|
}
|
|
|
|
// getReplicatedFileHCCChange - fetches health color code for metadata
|
|
// files that are replicated.
|
|
func (h hri) getReplicatedFileHCCChange() (b, a col, err error) {
|
|
getColCode := func(numAvail int) (c col, err error) {
|
|
// calculate color code for replicated object similar
|
|
// to erasure coded objects
|
|
var quorum, surplus, parity int
|
|
if h.SetCount > 0 {
|
|
quorum = h.DiskCount/h.SetCount/2 + 1
|
|
surplus = numAvail/h.SetCount - quorum
|
|
parity = h.DiskCount/h.SetCount - quorum
|
|
} else {
|
|
// in case of bucket healing, disk count is for the node
|
|
// also explicitly set count would be set to invalid value of -1
|
|
quorum = h.DiskCount/2 + 1
|
|
surplus = numAvail - quorum
|
|
parity = h.DiskCount - quorum
|
|
}
|
|
c, err = getHColCode(surplus, parity)
|
|
return
|
|
}
|
|
|
|
onlineBefore, onlineAfter := h.GetOnlineCounts()
|
|
b, err = getColCode(onlineBefore)
|
|
if err != nil {
|
|
return
|
|
}
|
|
a, err = getColCode(onlineAfter)
|
|
return
|
|
}
|
|
|
|
func (h hri) makeHealEntityString() string {
|
|
switch h.Type {
|
|
case madmin.HealItemObject:
|
|
return h.Bucket + "/" + h.Object
|
|
case madmin.HealItemBucket:
|
|
return h.Bucket
|
|
case madmin.HealItemMetadata:
|
|
return "[disk-format]"
|
|
case madmin.HealItemBucketMetadata:
|
|
return fmt.Sprintf("[bucket-metadata]%s/%s", h.Bucket, h.Object)
|
|
}
|
|
return "** unexpected **"
|
|
}
|
|
|
|
func (h hri) getHRTypeAndName() (typ, name string) {
|
|
name = fmt.Sprintf("%s/%s", h.Bucket, h.Object)
|
|
switch h.Type {
|
|
case madmin.HealItemMetadata:
|
|
typ = "system"
|
|
name = h.Detail
|
|
case madmin.HealItemBucketMetadata:
|
|
typ = "system"
|
|
name = "bucket-metadata:" + name
|
|
case madmin.HealItemBucket:
|
|
typ = "bucket"
|
|
case madmin.HealItemObject:
|
|
typ = "object"
|
|
default:
|
|
typ = fmt.Sprintf("!! Unknown heal result record %#v !!", h)
|
|
name = typ
|
|
}
|
|
return
|
|
}
|
|
|
|
func (h hri) getHealResultStr() string {
|
|
typ, name := h.getHRTypeAndName()
|
|
|
|
switch h.Type {
|
|
case madmin.HealItemMetadata, madmin.HealItemBucketMetadata:
|
|
return typ + ":" + name
|
|
default:
|
|
return name
|
|
}
|
|
}
|