Implement syncClaim with bound claims.
This commit is contained in:
@@ -417,7 +417,82 @@ func (ctrl *PersistentVolumeController) syncUnboundClaim(claim *api.PersistentVo
|
||||
// syncBoundClaim is the main controller method to decide what to do with a
|
||||
// bound claim.
|
||||
func (ctrl *PersistentVolumeController) syncBoundClaim(claim *api.PersistentVolumeClaim) error {
|
||||
return nil
|
||||
// hasAnnotation(pvc, annBindCompleted)
|
||||
// This PVC has previously been bound
|
||||
// OBSERVATION: pvc is not "Pending"
|
||||
// [Unit test set 3]
|
||||
if claim.Spec.VolumeName == "" {
|
||||
// Claim was bound before but not any more.
|
||||
if claim.Status.Phase != api.ClaimLost {
|
||||
// Log the error only once, when we enter 'Lost' phase
|
||||
glog.V(3).Infof("synchronizing bound PersistentVolumeClaim[%s]: volume reference lost!", claimToClaimKey(claim))
|
||||
}
|
||||
// TODO: emit event and save reason
|
||||
if _, err := ctrl.updateClaimPhase(claim, api.ClaimLost); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
obj, found, err := ctrl.volumes.store.GetByKey(claim.Spec.VolumeName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !found {
|
||||
// Claim is bound to a non-existing volume.
|
||||
if claim.Status.Phase != api.ClaimLost {
|
||||
// Log the error only once, when we enter 'Lost' phase
|
||||
glog.V(3).Infof("synchronizing bound PersistentVolumeClaim[%s]: volume %q lost!", claimToClaimKey(claim), claim.Spec.VolumeName)
|
||||
}
|
||||
// TODO: emit event and save reason
|
||||
if _, err = ctrl.updateClaimPhase(claim, api.ClaimLost); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
} else {
|
||||
volume, ok := obj.(*api.PersistentVolume)
|
||||
if !ok {
|
||||
return fmt.Errorf("Cannot convert object from volume cache to volume %q!?: %+v", claim.Spec.VolumeName, obj)
|
||||
}
|
||||
|
||||
glog.V(4).Infof("synchronizing bound PersistentVolumeClaim[%s]: volume %q found: %s", claimToClaimKey(claim), claim.Spec.VolumeName, ctrl.getVolumeStatusForLogging(volume))
|
||||
if volume.Spec.ClaimRef == nil {
|
||||
// Claim is bound but volume has come unbound.
|
||||
// Or, a claim was bound and the controller has not received updated
|
||||
// volume yet. We can't distinguish these cases.
|
||||
// Bind the volume again and set all states to Bound.
|
||||
glog.V(4).Infof("synchronizing bound PersistentVolumeClaim[%s]: volume is unbound, fixing", claimToClaimKey(claim))
|
||||
if err = ctrl.bind(volume, claim); err != nil {
|
||||
// Objects not saved, next syncPV or syncClaim will try again
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
} else if volume.Spec.ClaimRef.UID == claim.UID {
|
||||
// All is well
|
||||
// NOTE: syncPV can handle this so it can be left out.
|
||||
// NOTE: bind() call here will do nothing in most cases as
|
||||
// everything should be already set.
|
||||
glog.V(4).Infof("synchronizing bound PersistentVolumeClaim[%s]: claim is already correctly bound", claimToClaimKey(claim))
|
||||
if err = ctrl.bind(volume, claim); err != nil {
|
||||
// Objects not saved, next syncPV or syncClaim will try again
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
} else {
|
||||
// Claim is bound but volume has a different claimant.
|
||||
// Set the claim phase to 'Lost', which is a terminal
|
||||
// phase.
|
||||
otherClaimName := fmt.Sprintf("%s/%s", volume.Spec.ClaimRef.Namespace, volume.Spec.ClaimRef.Name)
|
||||
if claim.Status.Phase != api.ClaimLost {
|
||||
// Log the error only once, when we enter 'Lost' phase
|
||||
glog.V(3).Infof("synchronizing bound PersistentVolumeClaim[%s]: volume %q bound to another claim %q, this claim is lost!", claimToClaimKey(claim), claim.Spec.VolumeName, otherClaimName)
|
||||
}
|
||||
// TODO: emit event and save reason
|
||||
if _, err = ctrl.updateClaimPhase(claim, api.ClaimLost); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// syncVolume is the main controller method to decide what to do with a volume.
|
||||
|
@@ -137,26 +137,152 @@ func TestSync(t *testing.T) {
|
||||
newClaimArray("claim1-9", "uid1-9", "1Gi", "volume1-9", api.ClaimBound, annBoundByController, annBindCompleted),
|
||||
testSyncClaim,
|
||||
},
|
||||
/* TODO: enable when syncClaim with annBindCompleted is implemented
|
||||
controllerTest{
|
||||
// syncClaim completes binding - simulates controller crash after
|
||||
// PVC.VolumeName is saved
|
||||
"10 - complete bind after crash - PVC bound",
|
||||
[]*api.PersistentVolume{
|
||||
newVolume("volume1-10", "1Gi", "uid1-10", "claim1-10", api.VolumeBound, annBoundByController),
|
||||
},
|
||||
[]*api.PersistentVolume{
|
||||
newVolume("volume1-10", "1Gi", "uid1-10", "claim1-10", api.VolumeBound, annBoundByController),
|
||||
},
|
||||
[]*api.PersistentVolumeClaim{
|
||||
newClaim("claim1-10", "uid1-10", "1Gi", "volume1-10", api.ClaimPending, annBoundByController, annBindCompleted),
|
||||
},
|
||||
[]*api.PersistentVolumeClaim{
|
||||
newClaim("claim1-10", "uid1-10", "1Gi", "volume1-10", api.ClaimBound, annBoundByController, annBindCompleted),
|
||||
},
|
||||
testSyncClaim,
|
||||
},
|
||||
*/
|
||||
{
|
||||
// syncClaim completes binding - simulates controller crash after
|
||||
// PVC.VolumeName is saved
|
||||
"10 - complete bind after crash - PVC bound",
|
||||
newVolumeArray("volume1-10", "1Gi", "uid1-10", "claim1-10", api.VolumeBound, annBoundByController),
|
||||
newVolumeArray("volume1-10", "1Gi", "uid1-10", "claim1-10", api.VolumeBound, annBoundByController),
|
||||
newClaimArray("claim1-10", "uid1-10", "1Gi", "volume1-10", api.ClaimPending, annBoundByController, annBindCompleted),
|
||||
newClaimArray("claim1-10", "uid1-10", "1Gi", "volume1-10", api.ClaimBound, annBoundByController, annBindCompleted),
|
||||
testSyncClaim,
|
||||
},
|
||||
// [Unit test set 2] User asked for a specific PV.
|
||||
// Test the binding when pv.ClaimRef is already set by controller or
|
||||
// by user.
|
||||
{
|
||||
// syncClaim with claim pre-bound to a PV that does not exist
|
||||
"2-1 - claim prebound to non-existing volume - noop",
|
||||
novolumes,
|
||||
novolumes,
|
||||
newClaimArray("claim2-1", "uid2-1", "10Gi", "volume2-1", api.ClaimPending),
|
||||
newClaimArray("claim2-1", "uid2-1", "10Gi", "volume2-1", api.ClaimPending),
|
||||
testSyncClaim,
|
||||
},
|
||||
{
|
||||
// syncClaim with claim pre-bound to a PV that does not exist.
|
||||
// Check that the claim status is reset to Pending
|
||||
"2-2 - claim prebound to non-existing volume - reset status",
|
||||
novolumes,
|
||||
novolumes,
|
||||
newClaimArray("claim2-2", "uid2-2", "10Gi", "volume2-2", api.ClaimBound),
|
||||
newClaimArray("claim2-2", "uid2-2", "10Gi", "volume2-2", api.ClaimPending),
|
||||
testSyncClaim,
|
||||
},
|
||||
{
|
||||
// syncClaim with claim pre-bound to a PV that exists and is
|
||||
// unbound. Check it gets bound and no annBoundByController is set.
|
||||
"2-3 - claim prebound to unbound volume",
|
||||
newVolumeArray("volume2-3", "1Gi", "", "", api.VolumePending),
|
||||
newVolumeArray("volume2-3", "1Gi", "uid2-3", "claim2-3", api.VolumeBound, annBoundByController),
|
||||
newClaimArray("claim2-3", "uid2-3", "10Gi", "volume2-3", api.ClaimPending),
|
||||
newClaimArray("claim2-3", "uid2-3", "10Gi", "volume2-3", api.ClaimBound, annBindCompleted),
|
||||
testSyncClaim,
|
||||
},
|
||||
{
|
||||
// claim with claim pre-bound to a PV that is pre-bound to the claim
|
||||
// by name. Check it gets bound and no annBoundByController is set.
|
||||
"2-4 - claim prebound to prebound volume by name",
|
||||
newVolumeArray("volume2-4", "1Gi", "", "claim2-4", api.VolumePending),
|
||||
newVolumeArray("volume2-4", "1Gi", "uid2-4", "claim2-4", api.VolumeBound),
|
||||
newClaimArray("claim2-4", "uid2-4", "10Gi", "volume2-4", api.ClaimPending),
|
||||
newClaimArray("claim2-4", "uid2-4", "10Gi", "volume2-4", api.ClaimBound, annBindCompleted),
|
||||
testSyncClaim,
|
||||
},
|
||||
{
|
||||
// syncClaim with claim pre-bound to a PV that is pre-bound to the
|
||||
// claim by UID. Check it gets bound and no annBoundByController is
|
||||
// set.
|
||||
"2-5 - claim prebound to prebound volume by UID",
|
||||
newVolumeArray("volume2-5", "1Gi", "uid2-5", "claim2-5", api.VolumePending),
|
||||
newVolumeArray("volume2-5", "1Gi", "uid2-5", "claim2-5", api.VolumeBound),
|
||||
newClaimArray("claim2-5", "uid2-5", "10Gi", "volume2-5", api.ClaimPending),
|
||||
newClaimArray("claim2-5", "uid2-5", "10Gi", "volume2-5", api.ClaimBound, annBindCompleted),
|
||||
testSyncClaim,
|
||||
},
|
||||
{
|
||||
// syncClaim with claim pre-bound to a PV that is bound to different
|
||||
// claim. Check it's reset to Pending.
|
||||
"2-6 - claim prebound to already bound volume",
|
||||
newVolumeArray("volume2-6", "1Gi", "uid2-6_1", "claim2-6_1", api.VolumeBound),
|
||||
newVolumeArray("volume2-6", "1Gi", "uid2-6_1", "claim2-6_1", api.VolumeBound),
|
||||
newClaimArray("claim2-6", "uid2-6", "10Gi", "volume2-6", api.ClaimBound),
|
||||
newClaimArray("claim2-6", "uid2-6", "10Gi", "volume2-6", api.ClaimPending),
|
||||
testSyncClaim,
|
||||
},
|
||||
{
|
||||
// syncClaim with claim bound by controller to a PV that is bound to
|
||||
// different claim. Check it throws an error.
|
||||
"2-7 - claim bound by controller to already bound volume",
|
||||
newVolumeArray("volume2-7", "1Gi", "uid2-7_1", "claim2-7_1", api.VolumeBound),
|
||||
newVolumeArray("volume2-7", "1Gi", "uid2-7_1", "claim2-7_1", api.VolumeBound),
|
||||
newClaimArray("claim2-7", "uid2-7", "10Gi", "volume2-7", api.ClaimBound, annBoundByController),
|
||||
newClaimArray("claim2-7", "uid2-7", "10Gi", "volume2-7", api.ClaimBound, annBoundByController),
|
||||
testSyncClaimError,
|
||||
},
|
||||
// [Unit test set 3] Syncing bound claim
|
||||
{
|
||||
// syncClaim with claim bound and its claim.Spec.VolumeName is
|
||||
// removed. Check it's marked as Lost.
|
||||
"3-1 - bound claim with missing VolumeName",
|
||||
novolumes,
|
||||
novolumes,
|
||||
newClaimArray("claim3-1", "uid3-1", "10Gi", "", api.ClaimBound, annBoundByController, annBindCompleted),
|
||||
newClaimArray("claim3-1", "uid3-1", "10Gi", "", api.ClaimLost, annBoundByController, annBindCompleted),
|
||||
testSyncClaim,
|
||||
},
|
||||
{
|
||||
// syncClaim with claim bound to non-exising volume. Check it's
|
||||
// marked as Lost.
|
||||
"3-2 - bound claim with missing volume",
|
||||
novolumes,
|
||||
novolumes,
|
||||
newClaimArray("claim3-2", "uid3-2", "10Gi", "volume3-2", api.ClaimBound, annBoundByController, annBindCompleted),
|
||||
newClaimArray("claim3-2", "uid3-2", "10Gi", "volume3-2", api.ClaimLost, annBoundByController, annBindCompleted),
|
||||
testSyncClaim,
|
||||
},
|
||||
{
|
||||
// syncClaim with claim bound to unbound volume. Check it's bound.
|
||||
// Also check that Pending phase is set to Bound
|
||||
"3-3 - bound claim with unbound volume",
|
||||
newVolumeArray("volume3-3", "10Gi", "", "", api.VolumePending),
|
||||
newVolumeArray("volume3-3", "10Gi", "uid3-3", "claim3-3", api.VolumeBound, annBoundByController),
|
||||
newClaimArray("claim3-3", "uid3-3", "10Gi", "volume3-3", api.ClaimPending, annBoundByController, annBindCompleted),
|
||||
newClaimArray("claim3-3", "uid3-3", "10Gi", "volume3-3", api.ClaimBound, annBoundByController, annBindCompleted),
|
||||
testSyncClaim,
|
||||
},
|
||||
{
|
||||
// syncClaim with claim bound to volume with missing (or different)
|
||||
// volume.Spec.ClaimRef.UID. Check that the claim is marked as lost.
|
||||
"3-4 - bound claim with prebound volume",
|
||||
newVolumeArray("volume3-4", "10Gi", "claim3-4-x", "claim3-4", api.VolumePending),
|
||||
newVolumeArray("volume3-4", "10Gi", "claim3-4-x", "claim3-4", api.VolumePending),
|
||||
newClaimArray("claim3-4", "uid3-4", "10Gi", "volume3-4", api.ClaimPending, annBoundByController, annBindCompleted),
|
||||
newClaimArray("claim3-4", "uid3-4", "10Gi", "volume3-4", api.ClaimLost, annBoundByController, annBindCompleted),
|
||||
testSyncClaim,
|
||||
},
|
||||
{
|
||||
// syncClaim with claim bound to bound volume. Check that the
|
||||
// controller does not do anything. Also check that Pending phase is
|
||||
// set to Bound
|
||||
"3-5 - bound claim with bound volume",
|
||||
newVolumeArray("volume3-5", "10Gi", "uid3-5", "claim3-5", api.VolumePending),
|
||||
newVolumeArray("volume3-5", "10Gi", "uid3-5", "claim3-5", api.VolumeBound),
|
||||
newClaimArray("claim3-5", "uid3-5", "10Gi", "volume3-5", api.ClaimPending, annBindCompleted),
|
||||
newClaimArray("claim3-5", "uid3-5", "10Gi", "volume3-5", api.ClaimBound, annBindCompleted),
|
||||
testSyncClaim,
|
||||
},
|
||||
{
|
||||
// syncClaim with claim bound to a volume that is bound to different
|
||||
// claim. Check that the claim is marked as lost.
|
||||
// TODO: test that an event is emitted
|
||||
"3-6 - bound claim with bound volume",
|
||||
newVolumeArray("volume3-6", "10Gi", "uid3-6-x", "claim3-6-x", api.VolumePending),
|
||||
newVolumeArray("volume3-6", "10Gi", "uid3-6-x", "claim3-6-x", api.VolumePending),
|
||||
newClaimArray("claim3-6", "uid3-6", "10Gi", "volume3-6", api.ClaimPending, annBindCompleted),
|
||||
newClaimArray("claim3-6", "uid3-6", "10Gi", "volume3-6", api.ClaimLost, annBindCompleted),
|
||||
testSyncClaim,
|
||||
},
|
||||
}
|
||||
runSyncTests(t, tests)
|
||||
}
|
||||
|
Reference in New Issue
Block a user