diff --git a/pkg/controller/volume/scheduling/scheduler_binder.go b/pkg/controller/volume/scheduling/scheduler_binder.go index 4281c4219e8..4a5dbad8ac7 100644 --- a/pkg/controller/volume/scheduling/scheduler_binder.go +++ b/pkg/controller/volume/scheduling/scheduler_binder.go @@ -974,8 +974,7 @@ func (b *volumeBinder) hasEnoughCapacity(provisioner string, claim *v1.Persisten sizeInBytes := quantity.Value() for _, capacity := range capacities { if capacity.StorageClassName == storageClass.Name && - capacity.Capacity != nil && - capacity.Capacity.Value() >= sizeInBytes && + capacitySufficient(capacity, sizeInBytes) && b.nodeHasAccess(node, capacity) { // Enough capacity found. return true, nil @@ -989,6 +988,15 @@ func (b *volumeBinder) hasEnoughCapacity(provisioner string, claim *v1.Persisten return false, nil } +func capacitySufficient(capacity *storagev1beta1.CSIStorageCapacity, sizeInBytes int64) bool { + limit := capacity.Capacity + if capacity.MaximumVolumeSize != nil { + // Prefer MaximumVolumeSize if available, it is more precise. + limit = capacity.MaximumVolumeSize + } + return limit != nil && limit.Value() >= sizeInBytes +} + func (b *volumeBinder) nodeHasAccess(node *v1.Node, capacity *storagev1beta1.CSIStorageCapacity) bool { if capacity.NodeTopology == nil { // Unavailable diff --git a/pkg/controller/volume/scheduling/scheduler_binder_test.go b/pkg/controller/volume/scheduling/scheduler_binder_test.go index b092252271a..162ab8a094d 100644 --- a/pkg/controller/volume/scheduling/scheduler_binder_test.go +++ b/pkg/controller/volume/scheduling/scheduler_binder_test.go @@ -743,7 +743,7 @@ func makeCSIDriver(name string, storageCapacity bool) *storagev1.CSIDriver { } } -func makeCapacity(name, storageClassName string, node *v1.Node, capacityStr string) *storagev1beta1.CSIStorageCapacity { +func makeCapacity(name, storageClassName string, node *v1.Node, capacityStr, maximumVolumeSizeStr string) *storagev1beta1.CSIStorageCapacity { c := &storagev1beta1.CSIStorageCapacity{ ObjectMeta: metav1.ObjectMeta{ Name: name, @@ -758,6 +758,10 @@ func makeCapacity(name, storageClassName string, node *v1.Node, capacityStr stri capacityQuantity := resource.MustParse(capacityStr) c.Capacity = &capacityQuantity } + if maximumVolumeSizeStr != "" { + maximumVolumeSizeQuantity := resource.MustParse(maximumVolumeSizeStr) + c.MaximumVolumeSize = &maximumVolumeSizeQuantity + } return c } @@ -2212,21 +2216,21 @@ func TestCapacity(t *testing.T) { "network-attached": { pvcs: []*v1.PersistentVolumeClaim{provisionedPVC}, capacities: []*storagev1beta1.CSIStorageCapacity{ - makeCapacity("net", waitClassWithProvisioner, nil, "1Gi"), + makeCapacity("net", waitClassWithProvisioner, nil, "1Gi", ""), }, }, "local-storage": { pvcs: []*v1.PersistentVolumeClaim{provisionedPVC}, capacities: []*storagev1beta1.CSIStorageCapacity{ - makeCapacity("net", waitClassWithProvisioner, node1, "1Gi"), + makeCapacity("net", waitClassWithProvisioner, node1, "1Gi", ""), }, }, "multiple": { pvcs: []*v1.PersistentVolumeClaim{provisionedPVC}, capacities: []*storagev1beta1.CSIStorageCapacity{ - makeCapacity("net", waitClassWithProvisioner, nil, "1Gi"), - makeCapacity("net", waitClassWithProvisioner, node2, "1Gi"), - makeCapacity("net", waitClassWithProvisioner, node1, "1Gi"), + makeCapacity("net", waitClassWithProvisioner, nil, "1Gi", ""), + makeCapacity("net", waitClassWithProvisioner, node2, "1Gi", ""), + makeCapacity("net", waitClassWithProvisioner, node1, "1Gi", ""), }, }, "no-storage": { @@ -2236,35 +2240,49 @@ func TestCapacity(t *testing.T) { "wrong-node": { pvcs: []*v1.PersistentVolumeClaim{provisionedPVC}, capacities: []*storagev1beta1.CSIStorageCapacity{ - makeCapacity("net", waitClassWithProvisioner, node2, "1Gi"), + makeCapacity("net", waitClassWithProvisioner, node2, "1Gi", ""), }, reasons: ConflictReasons{ErrReasonNotEnoughSpace}, }, "wrong-storage-class": { pvcs: []*v1.PersistentVolumeClaim{provisionedPVC}, capacities: []*storagev1beta1.CSIStorageCapacity{ - makeCapacity("net", waitClass, node1, "1Gi"), + makeCapacity("net", waitClass, node1, "1Gi", ""), }, reasons: ConflictReasons{ErrReasonNotEnoughSpace}, }, "insufficient-storage": { pvcs: []*v1.PersistentVolumeClaim{provisionedPVC}, capacities: []*storagev1beta1.CSIStorageCapacity{ - makeCapacity("net", waitClassWithProvisioner, node1, "1Mi"), + makeCapacity("net", waitClassWithProvisioner, node1, "1Mi", ""), + }, + reasons: ConflictReasons{ErrReasonNotEnoughSpace}, + }, + "insufficient-volume-size": { + pvcs: []*v1.PersistentVolumeClaim{provisionedPVC}, + capacities: []*storagev1beta1.CSIStorageCapacity{ + makeCapacity("net", waitClassWithProvisioner, node1, "1Gi", "1Mi"), }, reasons: ConflictReasons{ErrReasonNotEnoughSpace}, }, "zero-storage": { pvcs: []*v1.PersistentVolumeClaim{provisionedPVC}, capacities: []*storagev1beta1.CSIStorageCapacity{ - makeCapacity("net", waitClassWithProvisioner, node1, "0Mi"), + makeCapacity("net", waitClassWithProvisioner, node1, "0Mi", ""), + }, + reasons: ConflictReasons{ErrReasonNotEnoughSpace}, + }, + "zero-volume-size": { + pvcs: []*v1.PersistentVolumeClaim{provisionedPVC}, + capacities: []*storagev1beta1.CSIStorageCapacity{ + makeCapacity("net", waitClassWithProvisioner, node1, "", "0Mi"), }, reasons: ConflictReasons{ErrReasonNotEnoughSpace}, }, "nil-storage": { pvcs: []*v1.PersistentVolumeClaim{provisionedPVC}, capacities: []*storagev1beta1.CSIStorageCapacity{ - makeCapacity("net", waitClassWithProvisioner, node1, ""), + makeCapacity("net", waitClassWithProvisioner, node1, "", ""), }, reasons: ConflictReasons{ErrReasonNotEnoughSpace}, },