@@ -24,12 +24,12 @@ import (
24
24
"github.com/aws/aws-sdk-go/aws/awserr"
25
25
"github.com/ceph/go-ceph/rgw/admin"
26
26
"github.com/coreos/pkg/capnslog"
27
+ "github.com/google/go-cmp/cmp"
27
28
bktv1alpha1 "github.com/kube-object-storage/lib-bucket-provisioner/pkg/apis/objectbucket.io/v1alpha1"
28
29
apibkt "github.com/kube-object-storage/lib-bucket-provisioner/pkg/provisioner/api"
29
30
opcontroller "github.com/rook/rook/pkg/operator/ceph/controller"
30
31
"github.com/rook/rook/pkg/operator/ceph/object"
31
32
storagev1 "k8s.io/api/storage/v1"
32
- "k8s.io/apimachinery/pkg/api/resource"
33
33
34
34
"github.com/pkg/errors"
35
35
"github.com/rook/rook/pkg/clusterd"
@@ -56,6 +56,11 @@ type Provisioner struct {
56
56
adminOpsClient * admin.API
57
57
}
58
58
59
+ type additionalConfigSpec struct {
60
+ maxObjects * int64
61
+ maxSize * int64
62
+ }
63
+
59
64
var _ apibkt.Provisioner = & Provisioner {}
60
65
61
66
func NewProvisioner (context * clusterd.Context , clusterInfo * client.ClusterInfo ) * Provisioner {
@@ -128,7 +133,7 @@ func (p Provisioner) Provision(options *apibkt.BucketOptions) (*bktv1alpha1.Obje
128
133
129
134
err = p .setAdditionalSettings (options )
130
135
if err != nil {
131
- return nil , errors .Wrapf (err , "failed to set additional settings for OBC %q" , options .ObjectBucketClaim .Name )
136
+ return nil , errors .Wrapf (err , "failed to set additional settings for OBC %q in NS %q associated with CephObjectStore %q in NS %q " , options .ObjectBucketClaim .Name , options . ObjectBucketClaim . Namespace , p . objectStoreName , p . clusterInfo . Namespace )
132
137
}
133
138
134
139
return p .composeObjectBucket (), nil
@@ -218,7 +223,7 @@ func (p Provisioner) Grant(options *apibkt.BucketOptions) (*bktv1alpha1.ObjectBu
218
223
// setting quota limit if it is enabled
219
224
err = p .setAdditionalSettings (options )
220
225
if err != nil {
221
- return nil , err
226
+ return nil , errors . Wrapf ( err , "failed to set additional settings for OBC %q in NS %q associated with CephObjectStore %q in NS %q" , options . ObjectBucketClaim . Name , options . ObjectBucketClaim . Namespace , p . objectStoreName , p . clusterInfo . Namespace )
222
227
}
223
228
224
229
// returned ob with connection info
@@ -568,75 +573,61 @@ func (p *Provisioner) populateDomainAndPort(sc *storagev1.StorageClass) error {
568
573
569
574
// Check for additional options mentioned in OBC and set them accordingly
570
575
func (p * Provisioner ) setAdditionalSettings (options * apibkt.BucketOptions ) error {
571
- var maxObjectsInt64 int64 = - 1
572
- var maxSizeInt64 int64 = - 1
573
- var err error
574
- var quotaEnabled bool
575
-
576
- maxObjects := MaxObjectQuota (options .ObjectBucketClaim .Spec .AdditionalConfig )
577
- if maxObjects != "" {
578
- quotaEnabled = true
579
-
580
- maxObjectsInt64 , err = toInt64 (maxObjects )
581
- if err != nil {
582
- return errors .Wrapf (err , "failed to parse maxObjects quota for user %q" , p .cephUserName )
583
- }
584
- }
585
-
586
- maxSize := MaxSizeQuota (options .ObjectBucketClaim .Spec .AdditionalConfig )
587
- if maxSize != "" {
588
- quotaEnabled = true
589
-
590
- maxSizeInt64 , err = toInt64 (maxSize )
591
- if err != nil {
592
- return errors .Wrapf (err , "failed to parse maxSize quota for user %q" , p .cephUserName )
593
- }
576
+ additionalConfig , err := additionalConfigSpecFromMap (options .ObjectBucketClaim .Spec .AdditionalConfig )
577
+ if err != nil {
578
+ return errors .Wrap (err , "failed to process additionalConfig" )
594
579
}
595
580
596
- objectUser , err := p .adminOpsClient .GetUser (p .clusterInfo .Context , admin.User { ID : p .cephUserName })
581
+ liveQuota , err := p .adminOpsClient .GetUserQuota (p .clusterInfo .Context , admin.QuotaSpec { UID : p .cephUserName })
597
582
if err != nil {
598
583
return errors .Wrapf (err , "failed to fetch user %q" , p .cephUserName )
599
584
}
600
585
601
- // enable or disable quota for user
602
- if * objectUser .UserQuota .Enabled != quotaEnabled {
603
- err = p .adminOpsClient .SetUserQuota (p .clusterInfo .Context , admin.QuotaSpec {UID : p .cephUserName , Enabled : & quotaEnabled })
604
- if err != nil {
605
- return errors .Wrapf (err , "failed to set user %q quota enabled=%v for obc" , p .cephUserName , quotaEnabled )
606
- }
586
+ // Copy only the fields that are actively managed by the provisioner to
587
+ // prevent passing back undesirable combinations of fields. It is
588
+ // known to be problematic to set both MaxSize and MaxSizeKB.
589
+ currentQuota := admin.QuotaSpec {
590
+ Enabled : liveQuota .Enabled ,
591
+ MaxObjects : liveQuota .MaxObjects ,
592
+ MaxSize : liveQuota .MaxSize ,
607
593
}
594
+ targetQuota := currentQuota
608
595
609
- if ! quotaEnabled {
610
- // no need to process anything else if quotas are disabled
611
- return nil
596
+ // enable or disable quota for user
597
+ quotaEnabled := (additionalConfig .maxObjects != nil ) || (additionalConfig .maxSize != nil )
598
+
599
+ targetQuota .Enabled = & quotaEnabled
600
+
601
+ if additionalConfig .maxObjects != nil {
602
+ targetQuota .MaxObjects = additionalConfig .maxObjects
603
+ } else if currentQuota .MaxObjects != nil && * currentQuota .MaxObjects >= 0 {
604
+ // if the existing value is already negative, we don't want to change it
605
+ var objects int64 = - 1
606
+ targetQuota .MaxObjects = & objects
612
607
}
613
608
614
- if * objectUser .UserQuota .MaxObjects != maxObjectsInt64 {
615
- err = p .adminOpsClient .SetUserQuota (p .clusterInfo .Context , admin.QuotaSpec {UID : p .cephUserName , MaxObjects : & maxObjectsInt64 })
616
- if err != nil {
617
- return errors .Wrapf (err , "failed to set MaxObjects=%v to user %q" , maxObjectsInt64 , p .cephUserName )
618
- }
609
+ if additionalConfig .maxSize != nil {
610
+ targetQuota .MaxSize = additionalConfig .maxSize
611
+ } else if currentQuota .MaxSize != nil && * currentQuota .MaxSize >= 0 {
612
+ // if the existing value is already negative, we don't want to change it
613
+ var size int64 = - 1
614
+ targetQuota .MaxSize = & size
619
615
}
620
616
621
- if objectUser .UserQuota .MaxSize != & maxSizeInt64 {
622
- err = p .adminOpsClient .SetUserQuota (p .clusterInfo .Context , admin.QuotaSpec {UID : p .cephUserName , MaxSize : & maxSizeInt64 })
617
+ diff := cmp .Diff (currentQuota , targetQuota )
618
+ if diff != "" {
619
+ logger .Debugf ("Quota for user %q has changed. diff:%s" , p .cephUserName , diff )
620
+ // UID is not set in the QuotaSpec returned by GetUser()/GetUserQuota()
621
+ targetQuota .UID = p .cephUserName
622
+ err = p .adminOpsClient .SetUserQuota (p .clusterInfo .Context , targetQuota )
623
623
if err != nil {
624
- return errors .Wrapf (err , "failed to set MaxSize =%v to user %q " , maxSizeInt64 , p .cephUserName )
624
+ return errors .Wrapf (err , "failed to set user %q quota enabled =%v %+v " , p .cephUserName , quotaEnabled , additionalConfig )
625
625
}
626
626
}
627
627
628
628
return nil
629
629
}
630
630
631
- func toInt64 (maxSize string ) (int64 , error ) {
632
- maxSizeInt , err := resource .ParseQuantity (maxSize )
633
- if err != nil {
634
- return 0 , errors .Wrap (err , "failed to parse quantity" )
635
- }
636
-
637
- return maxSizeInt .Value (), nil
638
- }
639
-
640
631
func (p * Provisioner ) setTlsCaCert () error {
641
632
objStore , err := p .getObjectStore ()
642
633
if err != nil {
0 commit comments