From f922af5138f03c47f1ad4a016dc79de4a672ebdd Mon Sep 17 00:00:00 2001 From: NickrenREN Date: Mon, 13 Mar 2017 19:51:21 +0800 Subject: [PATCH] make sure that the volume satisfies the requirements of the claim before binding check if the volume requested by the claim satisfies the requirements of the claim before binding when syncUnboundClaim and claim.Spec.VolumeName is not set --- .../volume/persistentvolume/binder_test.go | 29 ++++++++++++++++--- .../volume/persistentvolume/pv_controller.go | 29 ++++++++++++++++++- 2 files changed, 53 insertions(+), 5 deletions(-) diff --git a/pkg/controller/volume/persistentvolume/binder_test.go b/pkg/controller/volume/persistentvolume/binder_test.go index 07fe19ca306..5a26deed51f 100644 --- a/pkg/controller/volume/persistentvolume/binder_test.go +++ b/pkg/controller/volume/persistentvolume/binder_test.go @@ -254,12 +254,33 @@ func TestSync(t *testing.T) { // unbound, but does not match the selector. Check it gets bound // and no annBoundByController is set. "2-8 - claim prebound to unbound volume that does not match the selector", - newVolumeArray("volume2-3", "1Gi", "", "", v1.VolumePending, v1.PersistentVolumeReclaimRetain, classEmpty), - newVolumeArray("volume2-3", "1Gi", "uid2-3", "claim2-3", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty, annBoundByController), - withLabelSelector(labels, newClaimArray("claim2-3", "uid2-3", "1Gi", "volume2-3", v1.ClaimPending, nil)), - withLabelSelector(labels, newClaimArray("claim2-3", "uid2-3", "1Gi", "volume2-3", v1.ClaimBound, nil, annBindCompleted)), + newVolumeArray("volume2-8", "1Gi", "", "", v1.VolumePending, v1.PersistentVolumeReclaimRetain, classEmpty), + newVolumeArray("volume2-8", "1Gi", "uid2-8", "claim2-8", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty, annBoundByController), + withLabelSelector(labels, newClaimArray("claim2-8", "uid2-8", "1Gi", "volume2-8", v1.ClaimPending, nil)), + withLabelSelector(labels, newClaimArray("claim2-8", "uid2-8", "1Gi", "volume2-8", v1.ClaimBound, nil, annBindCompleted)), noevents, noerrors, testSyncClaim, }, + { + // syncClaim with claim pre-bound to a PV that exists and is + // unbound, but its size is smaller than requested. + //Check that the claim status is reset to Pending + "2-9 - claim prebound to unbound volume that size is smaller than requested", + newVolumeArray("volume2-9", "1Gi", "", "", v1.VolumePending, v1.PersistentVolumeReclaimRetain, classEmpty), + newVolumeArray("volume2-9", "1Gi", "", "", v1.VolumePending, v1.PersistentVolumeReclaimRetain, classEmpty), + newClaimArray("claim2-9", "uid2-9", "2Gi", "volume2-9", v1.ClaimBound, nil), + newClaimArray("claim2-9", "uid2-9", "2Gi", "volume2-9", v1.ClaimPending, nil), + []string{"Warning VolumeMismatch"}, noerrors, testSyncClaim, + }, + { + // syncClaim with claim pre-bound to a PV that exists and is + // unbound, but its class does not match. Check that the claim status is reset to Pending + "2-10 - claim prebound to unbound volume that class is different", + newVolumeArray("volume2-10", "1Gi", "1", "", v1.VolumePending, v1.PersistentVolumeReclaimRetain, classGold), + newVolumeArray("volume2-10", "1Gi", "", "", v1.VolumePending, v1.PersistentVolumeReclaimRetain, classGold), + newClaimArray("claim2-10", "uid2-10", "1Gi", "volume2-10", v1.ClaimBound, nil), + newClaimArray("claim2-10", "uid2-10", "1Gi", "volume2-10", v1.ClaimPending, nil), + []string{"Warning VolumeMismatch"}, noerrors, testSyncClaim, + }, // [Unit test set 3] Syncing bound claim { diff --git a/pkg/controller/volume/persistentvolume/pv_controller.go b/pkg/controller/volume/persistentvolume/pv_controller.go index de1708ea256..b165b2ea380 100644 --- a/pkg/controller/volume/persistentvolume/pv_controller.go +++ b/pkg/controller/volume/persistentvolume/pv_controller.go @@ -225,6 +225,25 @@ func (ctrl *PersistentVolumeController) syncClaim(claim *v1.PersistentVolumeClai } } +//checkVolumeSatisfyClaim checks if the volume requested by the claim satisfies the requirements of the claim +func checkVolumeSatisfyClaim(volume *v1.PersistentVolume, claim *v1.PersistentVolumeClaim) error { + requestedQty := claim.Spec.Resources.Requests[v1.ResourceName(v1.ResourceStorage)] + requestedSize := requestedQty.Value() + + volumeQty := volume.Spec.Capacity[v1.ResourceStorage] + volumeSize := volumeQty.Value() + if volumeSize < requestedSize { + return fmt.Errorf("Storage capacity of volume[%s] requested by claim[%v] is not enough", volume.Name, claimToClaimKey(claim)) + } + + requestedClass := v1.GetPersistentVolumeClaimClass(claim) + if v1.GetPersistentVolumeClass(volume) != requestedClass { + return fmt.Errorf("Class of volume[%s] is not the same as claim[%v]", volume.Name, claimToClaimKey(claim)) + } + + return nil +} + // syncUnboundClaim is the main controller method to decide what to do with an // unbound claim. func (ctrl *PersistentVolumeController) syncUnboundClaim(claim *v1.PersistentVolumeClaim) error { @@ -295,7 +314,15 @@ func (ctrl *PersistentVolumeController) syncUnboundClaim(claim *v1.PersistentVol // User asked for a PV that is not claimed // OBSERVATION: pvc is "Pending", pv is "Available" glog.V(4).Infof("synchronizing unbound PersistentVolumeClaim[%s]: volume is unbound, binding", claimToClaimKey(claim)) - if err = ctrl.bind(volume, claim); err != nil { + if err = checkVolumeSatisfyClaim(volume, claim); err != nil { + glog.V(4).Infof("Can't bind the claim to volume %q: %v", volume.Name, err) + //send a event + ctrl.eventRecorder.Event(volume, v1.EventTypeWarning, "VolumeMismatch", "Volume's size is smaller than requested or volume's class does not match with claim") + //volume does not satisfy the requirements of the claim + if _, err = ctrl.updateClaimStatus(claim, v1.ClaimPending, nil); err != nil { + return err + } + } else if err = ctrl.bind(volume, claim); err != nil { // On any error saving the volume or the claim, subsequent // syncClaim will finish the binding. return err