From 09350a804bd4210e8e85eef4ba8786a01c4e4a3d Mon Sep 17 00:00:00 2001 From: Vinayakswami Hariharmath Date: Mon, 27 Nov 2023 15:51:10 +0530 Subject: [PATCH] set quota configuration on bucket draft patch set quota on bucket Signed-off-by: Vinayakswami Hariharmath --- pkg/bucket/bucket.go | 133 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 131 insertions(+), 2 deletions(-) diff --git a/pkg/bucket/bucket.go b/pkg/bucket/bucket.go index 5b164737d6..7dd42f5355 100644 --- a/pkg/bucket/bucket.go +++ b/pkg/bucket/bucket.go @@ -2,12 +2,18 @@ package bucket import ( "fmt" + "log" + "strconv" + "strings" + obv1 "github.com/kube-object-storage/lib-bucket-provisioner/pkg/apis/objectbucket.io/v1alpha1" + nbv1 "github.com/noobaa/noobaa-operator/v5/pkg/apis/noobaa/v1alpha1" "github.com/noobaa/noobaa-operator/v5/pkg/bucketclass" "github.com/noobaa/noobaa-operator/v5/pkg/nb" "github.com/noobaa/noobaa-operator/v5/pkg/options" "github.com/noobaa/noobaa-operator/v5/pkg/system" "github.com/noobaa/noobaa-operator/v5/pkg/util" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/spf13/cobra" ) @@ -36,6 +42,10 @@ func CmdCreate() *cobra.Command { Run: RunCreate, } cmd.Flags().Bool("force_md5_etag", false, "This flag enables md5 etag calculation for bucket") + cmd.Flags().String("max-objects", "", + "Set quota max objects quantity config to requested bucket") + cmd.Flags().String("max-size", "", + "Set quota max size config to requested bucket") return cmd } @@ -47,6 +57,10 @@ func CmdUpdate() *cobra.Command { Run: RunUpdate, } cmd.Flags().Bool("force_md5_etag", false, "This flag enables md5 etag calculation for bucket") + cmd.Flags().String("max-objects", "", + "Set quota max objects quantity config to requested bucket") + cmd.Flags().String("max-size", "", + "Set quota max size config to requested bucket") return cmd } @@ -101,11 +115,36 @@ func RunCreate(cmd *cobra.Command, args []string) { } forceMd5Etag, _ := cmd.Flags().GetBool("force_md5_etag") + maxSize, _ := cmd.Flags().GetString("max-size") + maxObjects, _ := cmd.Flags().GetString("max-objects") + + var bucketMaxSize, bucketMaxObjects int64 + if len(maxSize) > 0 { + bucketMaxSize, _ = strconv.ParseInt(maxSize, 10, 64) + } + if len(maxObjects) > 0 { + bucketMaxObjects, _ = strconv.ParseInt(maxObjects, 10, 64) + } + validateQuotaOnParentObject(nbClient, bucketName, bucketMaxSize, bucketMaxObjects) + + quota := nb.QuotaConfig{} + if bucketMaxSize > 0 { + f, u := nb.GetBytesAndUnits(bucketMaxSize, 2) + quota.Size = &nb.SizeQuotaConfig{Value: f, Unit: u} + } + if bucketMaxObjects > 0 { + quota.Quantity = &nb.QuantityQuotaConfig{Value: int(bucketMaxObjects)} + } err = nbClient.CreateBucketAPI(nb.CreateBucketParams{Name: bucketName, Tiering: tierName, ForceMd5Etag: forceMd5Etag}) if err != nil { log.Fatal(err) } + + err = nbClient.UpdateBucketAPI(nb.CreateBucketParams{Name: bucketName, Quota: "a}) + if err != nil { + log.Fatal(err) + } } // RunUpdate runs a CLI command @@ -116,10 +155,32 @@ func RunUpdate(cmd *cobra.Command, args []string) { } bucketName := args[0] nbClient := system.GetNBClient() - forceMd5Etag, _ := cmd.Flags().GetBool("force_md5_etag") + maxSize, _ := cmd.Flags().GetString("max-size") + maxObjects, _ := cmd.Flags().GetString("max-objects") + + var bucketMaxSize, bucketMaxObjects int64 + if len(maxSize) > 0 { + bucketMaxSize, _ = strconv.ParseInt(maxSize, 10, 64) + } + + if len(maxObjects) > 0 { + bucketMaxObjects, _ = strconv.ParseInt(maxObjects, 10, 64) + } + + validateQuotaOnParentObject(nbClient, bucketName, bucketMaxSize, bucketMaxObjects) + + quota := nb.QuotaConfig{} + if bucketMaxSize > 0 { + f, u := nb.GetBytesAndUnits(bucketMaxSize, 2) + quota.Size = &nb.SizeQuotaConfig{Value: f, Unit: u} + } + + if bucketMaxObjects > 0 { + quota.Quantity = &nb.QuantityQuotaConfig{Value: int(bucketMaxObjects)} + } - err := nbClient.UpdateBucketAPI(nb.CreateBucketParams{Name: bucketName, ForceMd5Etag: forceMd5Etag}) + err := nbClient.UpdateBucketAPI(nb.CreateBucketParams{Name: bucketName, ForceMd5Etag: forceMd5Etag, Quota: "a}) if err != nil { log.Fatal(err) } @@ -212,3 +273,71 @@ func RunList(cmd *cobra.Command, args []string) { fmt.Print(table.String()) fmt.Printf("\n") } + +func validateQuotaOnParentObject(nbClient nb.Client, bucketName string, + bucketMaxSize int64, bucketMaxObjects int64) { + b, err := nbClient.ReadBucketAPI(nb.ReadBucketParams{Name: bucketName}) + if err != nil { + log.Fatal(err) + } + if bucketMaxObjects < b.NumObjects.Value { + log.Fatalf(`❌ Could not update quota value less than the objects/size already present. Available objects = %v Size occupied = %s `, + b.NumObjects.Value, nb.BigIntToHumanBytes(b.DataCapacity.Size)) + } + if b.BucketClaim != nil && (bucketMaxSize > 0 || bucketMaxObjects > 0) { + obc := &obv1.ObjectBucketClaim{ + TypeMeta: metav1.TypeMeta{Kind: "ObjectBucketClaim"}, + ObjectMeta: metav1.ObjectMeta{ + Name: strings.Split(bucketName, "-")[0], + Namespace: b.BucketClaim.Namespace, + }, + } + if !util.KubeCheck(obc) { + log.Fatalf(`❌ Could not find OBC %q in namespace %q`, + obc.Name, obc.Namespace) + } + // Pull maxSize and maxObjects set on obc + if len(obc.Spec.AdditionalConfig["maxObjects"]) > 0 && bucketMaxObjects > 0 { + bucketClaimMaxObjects, _ := strconv.ParseInt(obc.Spec.AdditionalConfig["maxObjects"], 10, 64) + if bucketMaxObjects >= bucketClaimMaxObjects { + log.Fatalf(`❌ Could not update maxObjects on the bucket. Provide maxObjects < obc(%v) maxObjects(%v)`, obc.Name, bucketClaimMaxObjects) + } + } + if len(obc.Spec.AdditionalConfig["maxSize"]) > 0 && bucketMaxSize > 0 { + bucketClaimMaxSize, _ := strconv.ParseInt(obc.Spec.AdditionalConfig["maxSize"], 10, 64) + if bucketMaxSize >= bucketClaimMaxSize { + log.Fatalf(`❌ Could not update maxSize on the bucket. Provide maxSize < obc(%v) maxSize(%v)`, obc.Name, bucketClaimMaxSize) + } + } + + // Pull maxSize and maxObjects set on bucketClass + bucketClass := &nbv1.BucketClass{ + TypeMeta: metav1.TypeMeta{Kind: "BucketClass"}, + ObjectMeta: metav1.ObjectMeta{ + Name: b.BucketClaim.BucketClass, + Namespace: b.BucketClaim.Namespace, + }, + } + if !util.KubeCheck(bucketClass) { + log.Fatalf(`❌ Could not get BucketClass %q in namespace %q`, + bucketClass.Name, bucketClass.Namespace) + } + + if bucketClass.Spec.Quota != nil { + if len(bucketClass.Spec.Quota.MaxObjects) > 0 && bucketMaxObjects > 0 { + bucketClassMaxObjects, _ := strconv.ParseInt(bucketClass.Spec.Quota.MaxObjects, 10, 64) + if bucketMaxObjects >= bucketClassMaxObjects { + log.Fatalf(`❌ Could not update maxObjects on the bucket. Provide maxObjects < bucket class(%v) maxObjects(%v)`, bucketClass.Name, bucketClassMaxObjects) + } + } + + if len(bucketClass.Spec.Quota.MaxSize) > 0 && bucketMaxSize > 0 { + bucketClassMaxSize, _ := strconv.ParseInt(bucketClass.Spec.Quota.MaxSize, 10, 64) + if bucketMaxSize >= bucketClassMaxSize { + log.Fatalf(`❌ Could not update maxSize on the bucket. Provide maxSize < bucket class(%v) maxSize(%v)`, bucketClass.Name, bucketClassMaxSize) + } + } + } + + } +}