From 5c8339e1e8d6a79d2713912f9226a7ef859cca1f Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Mon, 23 Oct 2023 13:55:45 -0700 Subject: [PATCH] fix: veeam SOS API to higher layers (#18287) - support populating usage info from scanner info - support populating quota for the bucket via quota settings for the bucket --- cmd/erasure-object.go | 16 ---------------- cmd/erasure-server-pool.go | 20 ++++++++++++++++++++ cmd/veeam-sos-api.go | 31 ++++++++++++++++++++++++------- 3 files changed, 44 insertions(+), 23 deletions(-) diff --git a/cmd/erasure-object.go b/cmd/erasure-object.go index 9b1b03290..f3f97a7b1 100644 --- a/cmd/erasure-object.go +++ b/cmd/erasure-object.go @@ -188,14 +188,6 @@ func (er erasureObjects) CopyObject(ctx context.Context, srcBucket, srcObject, d func (er erasureObjects) GetObjectNInfo(ctx context.Context, bucket, object string, rs *HTTPRangeSpec, h http.Header, opts ObjectOptions) (gr *GetObjectReader, err error) { auditObjectErasureSet(ctx, object, &er) - // This is a special call attempted first to check for SOS-API calls. - gr, err = veeamSOSAPIGetObject(ctx, bucket, object, rs, opts) - if err == nil { - return gr, nil - } - // reset any error to 'nil' - err = nil - var unlockOnDefer bool nsUnlocker := func() {} defer func() { @@ -451,14 +443,6 @@ func (er erasureObjects) getObjectWithFileInfo(ctx context.Context, bucket, obje func (er erasureObjects) GetObjectInfo(ctx context.Context, bucket, object string, opts ObjectOptions) (info ObjectInfo, err error) { auditObjectErasureSet(ctx, object, &er) - // This is a special call attempted first to check for SOS-API calls. - info, err = veeamSOSAPIHeadObject(ctx, bucket, object, opts) - if err == nil { - return info, nil - } - // reset any error to 'nil' - err = nil - if !opts.NoLock { // Lock the object before reading. lk := er.NewNSLock(bucket, object) diff --git a/cmd/erasure-server-pool.go b/cmd/erasure-server-pool.go index bba8e60da..2b3e9752f 100644 --- a/cmd/erasure-server-pool.go +++ b/cmd/erasure-server-pool.go @@ -795,6 +795,16 @@ func (z *erasureServerPools) GetObjectNInfo(ctx context.Context, bucket, object return nil, err } + // This is a special call attempted first to check for SOS-API calls. + gr, err = veeamSOSAPIGetObject(ctx, bucket, object, rs, opts) + if err == nil { + return gr, nil + } + + // reset any error to 'nil' and any reader to be 'nil' + gr = nil + err = nil + object = encodeDirObject(object) if z.SinglePool() { @@ -924,6 +934,16 @@ func (z *erasureServerPools) GetObjectInfo(ctx context.Context, bucket, object s return objInfo, err } + // This is a special call attempted first to check for SOS-API calls. + objInfo, err = veeamSOSAPIHeadObject(ctx, bucket, object, opts) + if err == nil { + return objInfo, nil + } + + // reset any error to 'nil', and object info to be empty. + err = nil + objInfo = ObjectInfo{} + object = encodeDirObject(object) if z.SinglePool() { diff --git a/cmd/veeam-sos-api.go b/cmd/veeam-sos-api.go index c3edee512..3eb366b9f 100644 --- a/cmd/veeam-sos-api.go +++ b/cmd/veeam-sos-api.go @@ -22,6 +22,8 @@ import ( "context" "encoding/xml" "io" + + "github.com/minio/madmin-go/v3" ) // From Veeam-SOSAPI_1.0_Document_v1.02d.pdf @@ -143,18 +145,33 @@ func veeamSOSAPIGetObject(ctx context.Context, bucket, object string, rs *HTTPRa if objAPI == nil { return nil, errServerNotInitialized } - info := objAPI.StorageInfo(ctx) - info.Backend = objAPI.BackendInfo() - usableTotal := int64(GetTotalUsableCapacity(info.Disks, info)) - usableFree := int64(GetTotalUsableCapacityFree(info.Disks, info)) + q, _ := globalBucketQuotaSys.Get(ctx, bucket) + binfo, _ := globalBucketQuotaSys.GetBucketUsageInfo(bucket) ci := capacityInfo{ - Capacity: usableTotal, - Available: usableFree, - Used: usableTotal - usableFree, + Used: int64(binfo.Size), } + var quotaSize int64 + if q != nil && q.Type == madmin.HardQuota { + if q.Size > 0 { + quotaSize = int64(q.Size) + } else if q.Quota > 0 { + quotaSize = int64(q.Quota) + } + } + + if quotaSize == 0 { + info := objAPI.StorageInfo(ctx) + info.Backend = objAPI.BackendInfo() + + ci.Capacity = int64(GetTotalUsableCapacity(info.Disks, info)) + } else { + ci.Capacity = quotaSize + } + ci.Available = ci.Capacity - ci.Used + buf = encodeResponse(&ci) default: return nil, errFileNotFound