1 changed files with 141 additions and 0 deletions
@ -0,0 +1,141 @@ |
|||||
|
package shell |
||||
|
|
||||
|
import ( |
||||
|
"bytes" |
||||
|
"flag" |
||||
|
"fmt" |
||||
|
"github.com/chrislusf/seaweedfs/weed/filer" |
||||
|
"github.com/chrislusf/seaweedfs/weed/pb/filer_pb" |
||||
|
"io" |
||||
|
"math" |
||||
|
) |
||||
|
|
||||
|
func init() { |
||||
|
Commands = append(Commands, &commandS3BucketQuotaCheck{}) |
||||
|
} |
||||
|
|
||||
|
type commandS3BucketQuotaCheck struct { |
||||
|
} |
||||
|
|
||||
|
func (c *commandS3BucketQuotaCheck) Name() string { |
||||
|
return "s3.bucket.quota.check" |
||||
|
} |
||||
|
|
||||
|
func (c *commandS3BucketQuotaCheck) Help() string { |
||||
|
return `check quota for all buckets, make the bucket read only if over the limit |
||||
|
|
||||
|
Example: |
||||
|
s3.bucket.quota.check -force |
||||
|
` |
||||
|
} |
||||
|
|
||||
|
func (c *commandS3BucketQuotaCheck) Do(args []string, commandEnv *CommandEnv, writer io.Writer) (err error) { |
||||
|
|
||||
|
bucketCommand := flag.NewFlagSet(c.Name(), flag.ContinueOnError) |
||||
|
enforceQuotaLimit := bucketCommand.Bool("force", false, "actually change the buckets readonly attribute") |
||||
|
if err = bucketCommand.Parse(args); err != nil { |
||||
|
return nil |
||||
|
} |
||||
|
|
||||
|
// collect collection information
|
||||
|
topologyInfo, _, err := collectTopologyInfo(commandEnv) |
||||
|
if err != nil { |
||||
|
return err |
||||
|
} |
||||
|
collectionInfos := make(map[string]*CollectionInfo) |
||||
|
collectCollectionInfo(topologyInfo, collectionInfos) |
||||
|
|
||||
|
// read buckets path
|
||||
|
var filerBucketsPath string |
||||
|
filerBucketsPath, err = readFilerBucketsPath(commandEnv) |
||||
|
if err != nil { |
||||
|
return fmt.Errorf("read buckets: %v", err) |
||||
|
} |
||||
|
|
||||
|
// read existing filer configuration
|
||||
|
fc, err := filer.ReadFilerConf(commandEnv.option.FilerAddress, commandEnv.option.GrpcDialOption, commandEnv.MasterClient) |
||||
|
if err != nil { |
||||
|
return err |
||||
|
} |
||||
|
|
||||
|
// process each bucket
|
||||
|
hasConfChanges := false |
||||
|
err = filer_pb.List(commandEnv, filerBucketsPath, "", func(entry *filer_pb.Entry, isLast bool) error { |
||||
|
if !entry.IsDirectory { |
||||
|
return nil |
||||
|
} |
||||
|
collection := entry.Name |
||||
|
var collectionSize uint64 |
||||
|
if collectionInfo, found := collectionInfos[collection]; found { |
||||
|
collectionSize = collectionInfo.Size |
||||
|
} |
||||
|
if c.processEachBucket(fc, filerBucketsPath, entry, writer, collectionSize) { |
||||
|
hasConfChanges = true |
||||
|
} |
||||
|
return nil |
||||
|
}, "", false, math.MaxUint32) |
||||
|
if err != nil { |
||||
|
return fmt.Errorf("list buckets under %v: %v", filerBucketsPath, err) |
||||
|
} |
||||
|
|
||||
|
// apply the configuration changes
|
||||
|
if hasConfChanges && *enforceQuotaLimit { |
||||
|
|
||||
|
var buf2 bytes.Buffer |
||||
|
fc.ToText(&buf2) |
||||
|
|
||||
|
if err = commandEnv.WithFilerClient(false, func(client filer_pb.SeaweedFilerClient) error { |
||||
|
return filer.SaveInsideFiler(client, filer.DirectoryEtcSeaweedFS, filer.FilerConfName, buf2.Bytes()) |
||||
|
}); err != nil && err != filer_pb.ErrNotFound { |
||||
|
return err |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return err |
||||
|
|
||||
|
} |
||||
|
|
||||
|
func (c *commandS3BucketQuotaCheck) processEachBucket(fc *filer.FilerConf, filerBucketsPath string, entry *filer_pb.Entry, writer io.Writer, collectionSize uint64) (hasConfChanges bool) { |
||||
|
|
||||
|
locPrefix := filerBucketsPath + "/" + entry.Name + "/" |
||||
|
locConf := fc.MatchStorageRule(locPrefix) |
||||
|
if locConf == nil { |
||||
|
locConf = &filer_pb.FilerConf_PathConf{ |
||||
|
LocationPrefix: locPrefix, |
||||
|
Collection: entry.Name, |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if entry.Quota > 0 { |
||||
|
if locConf.ReadOnly { |
||||
|
if collectionSize < uint64(entry.Quota) { |
||||
|
locConf.ReadOnly = false |
||||
|
hasConfChanges = true |
||||
|
} |
||||
|
} else { |
||||
|
if collectionSize > uint64(entry.Quota) { |
||||
|
locConf.ReadOnly = true |
||||
|
hasConfChanges = true |
||||
|
} |
||||
|
} |
||||
|
} else { |
||||
|
if locConf.ReadOnly { |
||||
|
locConf.ReadOnly = false |
||||
|
hasConfChanges = true |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if hasConfChanges { |
||||
|
fmt.Fprintf(writer, " %s\tsize:%d", entry.Name, collectionSize) |
||||
|
fmt.Fprintf(writer, "\tquota:%d\tusage:%.2f%%", entry.Quota, float64(collectionSize)*100/float64(entry.Quota)) |
||||
|
fmt.Fprintln(writer) |
||||
|
if locConf.ReadOnly { |
||||
|
fmt.Fprintf(writer, " changing bucket %s to read only!\n", entry.Name) |
||||
|
} else { |
||||
|
fmt.Fprintf(writer, " changing bucket %s to writable.\n", entry.Name) |
||||
|
} |
||||
|
fc.AddLocationConf(locConf) |
||||
|
} |
||||
|
|
||||
|
return |
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue