Skip to content

Commit dd1cf76

Browse files
Merge pull request noobaa#1826 from aayushchouhan09/quota-warn
Added a warning when quota exceeding the available space
2 parents a990105 + 1469915 commit dd1cf76

6 files changed

Lines changed: 106 additions & 0 deletions

File tree

pkg/bucket/bucket.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package bucket
22

33
import (
44
"fmt"
5+
"os"
56
"strconv"
67

78
"github.com/noobaa/noobaa-operator/v5/pkg/bucketclass"
@@ -131,6 +132,9 @@ func RunCreate(cmd *cobra.Command, args []string) {
131132
if err != nil {
132133
log.Fatal(err)
133134
}
135+
nb.WarnIfQuotaCappedByFree(bucketName, nil, nbClient, &quota, func(format string, args ...interface{}) {
136+
fmt.Fprintf(os.Stderr, "Warning: "+format+"\n", args...)
137+
})
134138
}
135139

136140
// RunUpdate runs a CLI command
@@ -169,6 +173,9 @@ func RunUpdate(cmd *cobra.Command, args []string) {
169173
if err != nil {
170174
log.Fatal(err)
171175
}
176+
nb.WarnIfQuotaCappedByFree(bucketName, nil, nbClient, updateParams.Quota, func(format string, args ...interface{}) {
177+
fmt.Fprintf(os.Stderr, "Warning: "+format+"\n", args...)
178+
})
172179
}
173180

174181
// RunDelete runs a CLI command

pkg/cosi/provisioner.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,10 @@ func (r *APIRequest) CreateBucket(
388388
Quota: quotaConfig,
389389
}
390390

391+
nb.WarnIfQuotaCappedByFree(r.BucketName, nil, r.SysClient.NBClient, quotaConfig, func(format string, args ...interface{}) {
392+
log.Warnf("QUOTA_WARN: "+format, args...)
393+
})
394+
391395
err = r.SysClient.NBClient.UpdateBucketAPI(*createBucketParams)
392396
if err != nil {
393397
return fmt.Errorf("failed to update bucket %q with error: %v", r.BucketName, err)

pkg/nb/quota.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package nb
2+
3+
import "math/big"
4+
5+
// WarnIfQuotaCappedByFree emits a best-effort warning when the configured size quota exceeds
6+
// the bucket's effective free capacity, meaning raising the quota will not increase Data Space Avail
7+
func WarnIfQuotaCappedByFree(bucketName string, bucket *BucketInfo, nbClient Client, quota *QuotaConfig, warnf func(format string, args ...interface{})) {
8+
if quota == nil || quota.Size == nil || warnf == nil {
9+
return
10+
}
11+
requestedQuotaBytes, ok := QuotaSizeToBytes(quota.Size)
12+
if !ok {
13+
return
14+
}
15+
16+
if bucket == nil {
17+
if nbClient == nil {
18+
return
19+
}
20+
b, err := nbClient.ReadBucketAPI(ReadBucketParams{Name: bucketName})
21+
if err != nil {
22+
return
23+
}
24+
bucket = &b
25+
}
26+
27+
cap := bucket.DataCapacity
28+
if bucket.BucketType == "NAMESPACE" || cap == nil || cap.Free == nil || cap.Size == nil {
29+
return
30+
}
31+
32+
// warn if (quota - used) > free, meaning free space is the binding constraint
33+
// use big.Int to avoid int64 overflow for large capacity values
34+
quotaMinusUsed := new(big.Int).Sub(big.NewInt(requestedQuotaBytes), cap.Size.ToBig())
35+
if quotaMinusUsed.Cmp(cap.Free.ToBig()) > 0 {
36+
warnf("bucket %q size quota (%s) exceeds current effective free capacity (%s); Data Space Avail will remain capped (min(free, quota-used))",
37+
bucketName,
38+
IntToHumanBytes(requestedQuotaBytes),
39+
BigIntToHumanBytes(cap.Free),
40+
)
41+
}
42+
}

pkg/nb/types.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package nb
33
import (
44
"encoding/json"
55
"math"
6+
"math/big"
67
"reflect"
78
"strconv"
89

@@ -167,6 +168,11 @@ func (n *BigInt) ToString() string {
167168
return strconv.FormatInt((n.N + (n.Peta * petaInBytes)), 10)
168169
}
169170

171+
// ToBig converts bigInt to a math/big.Int for overflow-safe arithmetic
172+
func (n *BigInt) ToBig() *big.Int {
173+
return new(big.Int).Add(big.NewInt(n.N), new(big.Int).Mul(big.NewInt(n.Peta), big.NewInt(petaInBytes)))
174+
}
175+
170176
// PoolInfo is a struct of pool info returned by the API
171177
type PoolInfo struct {
172178
Name string `json:"name"`
@@ -816,6 +822,46 @@ func GetBytesAndUnits(bi int64, prec int) (float64, string) {
816822
return f, units[u]
817823
}
818824

825+
// QuotaSizeToBytes converts a NooBaa quota size config (value + unit like "G") to bytes using base-2 units
826+
// Returns ok=false if the input is invalid or out of int64 range
827+
func QuotaSizeToBytes(q *SizeQuotaConfig) (bytes int64, ok bool) {
828+
if q == nil || q.Value <= 0 {
829+
return 0, false
830+
}
831+
832+
var pow int
833+
switch q.Unit {
834+
case "": // bytes, pow stays 0
835+
case "K":
836+
pow = 1
837+
case "M":
838+
pow = 2
839+
case "G":
840+
pow = 3
841+
case "T":
842+
pow = 4
843+
case "P":
844+
pow = 5
845+
case "E":
846+
pow = 6
847+
case "Z":
848+
pow = 7
849+
case "Y":
850+
pow = 8
851+
default:
852+
return 0, false
853+
}
854+
855+
f := q.Value * math.Pow(1024, float64(pow))
856+
if math.IsNaN(f) || math.IsInf(f, 0) {
857+
return 0, false
858+
}
859+
if f > math.MaxInt64 {
860+
return 0, false
861+
}
862+
return int64(math.Round(f)), true
863+
}
864+
819865
// UInt64ToBigInt convert uint64 based value to BigInt value
820866
func UInt64ToBigInt(value uint64) BigInt {
821867
return BigInt{

pkg/obc/obc.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"encoding/json"
66
"fmt"
7+
"os"
78
"time"
89

910
nbv1 "github.com/noobaa/noobaa-operator/v5/pkg/apis/noobaa/v1alpha1"
@@ -493,6 +494,9 @@ func RunStatus(cmd *cobra.Command, args []string) {
493494
fmt.Printf(" %-22s : %s\n", "Data Space Avail", nb.BigIntToHumanBytes(b.DataCapacity.AvailableSizeToUpload))
494495
fmt.Printf(" %-22s : %s\n", "Num Objects Avail", b.DataCapacity.AvailableQuantityToUpload.ToString())
495496
}
497+
nb.WarnIfQuotaCappedByFree(b.Name, b, nil, b.Quota, func(format string, args ...interface{}) {
498+
fmt.Fprintf(os.Stderr, "Warning: "+format+"\n", args...)
499+
})
496500
fmt.Printf("\n")
497501
}
498502
}

pkg/obc/provisioner.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,9 @@ func (r *BucketRequest) UpdateBucket() error {
535535
if quotaConfig.IsEqual(bucket.Quota) {
536536
r.Provisioner.Logger.Infof("UpdateBucket: no changes in quota config")
537537
} else {
538+
nb.WarnIfQuotaCappedByFree(r.BucketName, &bucket, nil, quotaConfig, func(format string, args ...interface{}) {
539+
log.Warnf("QUOTA_WARN: "+format, args...)
540+
})
538541
createBucketParams := &nb.CreateBucketParams{
539542
Name: r.BucketName,
540543
Quota: quotaConfig,

0 commit comments

Comments
 (0)