Merge pull request #25865 from jsafrane/devel/pv-convert-from-12

Automatic merge from submit-queue

volume controller: Convert PersistentVolumes from Kubernetes 1.2

In Kubernetes 1.2 we used template PersistentVolume for provisioning. When a claim for dynamic volume was detected, Kubernetes did:

- create template PV for the claim with dummy pointer to storage asset
- allocate storage asset such as AWS EBS
- fill real pointer to the created storage asset to the template PV

In refactored volume provisioner, Kubernetes allocates the storage asset first and then creates a Kubernetes PV instance already with the correct pointer to the storage asset.

To support seamles upgrade from 1.2 to 1.3 we need to remove these unprovisioned template PVs. The new controller does not use them, it will see PVC for dynamic provisioning and create real PV instead.

See https://github.com/pmorie/pv-haxxz/pull/3 for pseudocode.
This commit is contained in:
k8s-merge-robot
2016-06-03 23:27:13 -07:00
3 changed files with 164 additions and 15 deletions

View File

@@ -33,7 +33,7 @@ import (
// can't reliably simulate periodic sync of volumes/claims - it would be
// either very timing-sensitive or slow to wait for real periodic sync.
func TestControllerSync(t *testing.T) {
expectedChanges := []int{4, 1, 1}
expectedChanges := []int{4, 1, 1, 2, 1, 1, 1}
tests := []controllerTest{
// [Unit test set 5] - controller tests.
// We test the controller as if
@@ -87,6 +87,74 @@ func TestControllerSync(t *testing.T) {
return nil
},
},
{
// addVolume with provisioned volume from Kubernetes 1.2. No "action"
// is expected - it should stay bound.
"5-5 - add bound volume from 1.2",
novolumes,
[]*api.PersistentVolume{addVolumeAnnotation(newVolume("volume5-5", "10Gi", "uid5-5", "claim5-5", api.VolumeBound, api.PersistentVolumeReclaimDelete), pvProvisioningRequiredAnnotationKey, pvProvisioningCompletedAnnotationValue)},
newClaimArray("claim5-5", "uid5-5", "1Gi", "", api.ClaimPending),
newClaimArray("claim5-5", "uid5-5", "1Gi", "volume5-5", api.ClaimBound, annBindCompleted, annBoundByController),
noevents, noerrors,
// Custom test function that generates a add event
func(ctrl *PersistentVolumeController, reactor *volumeReactor, test controllerTest) error {
volume := newVolume("volume5-5", "10Gi", "uid5-5", "claim5-5", api.VolumeBound, api.PersistentVolumeReclaimDelete)
volume = addVolumeAnnotation(volume, pvProvisioningRequiredAnnotationKey, pvProvisioningCompletedAnnotationValue)
reactor.addVolumeEvent(volume)
return nil
},
},
{
// updateVolume with provisioned volume from Kubernetes 1.2. No
// "action" is expected - it should stay bound.
"5-6 - update bound volume from 1.2",
[]*api.PersistentVolume{addVolumeAnnotation(newVolume("volume5-6", "10Gi", "uid5-6", "claim5-6", api.VolumeBound, api.PersistentVolumeReclaimDelete), pvProvisioningRequiredAnnotationKey, pvProvisioningCompletedAnnotationValue)},
[]*api.PersistentVolume{addVolumeAnnotation(newVolume("volume5-6", "10Gi", "uid5-6", "claim5-6", api.VolumeBound, api.PersistentVolumeReclaimDelete), pvProvisioningRequiredAnnotationKey, pvProvisioningCompletedAnnotationValue)},
newClaimArray("claim5-6", "uid5-6", "1Gi", "volume5-6", api.ClaimBound),
newClaimArray("claim5-6", "uid5-6", "1Gi", "volume5-6", api.ClaimBound, annBindCompleted),
noevents, noerrors,
// Custom test function that generates a add event
func(ctrl *PersistentVolumeController, reactor *volumeReactor, test controllerTest) error {
volume := newVolume("volume5-6", "10Gi", "uid5-6", "claim5-6", api.VolumeBound, api.PersistentVolumeReclaimDelete)
volume = addVolumeAnnotation(volume, pvProvisioningRequiredAnnotationKey, pvProvisioningCompletedAnnotationValue)
reactor.modifyVolumeEvent(volume)
return nil
},
},
{
// addVolume with unprovisioned volume from Kubernetes 1.2. The
// volume should be deleted.
"5-7 - add unprovisioned volume from 1.2",
novolumes,
novolumes,
newClaimArray("claim5-7", "uid5-7", "1Gi", "", api.ClaimPending),
newClaimArray("claim5-7", "uid5-7", "1Gi", "", api.ClaimPending),
noevents, noerrors,
// Custom test function that generates a add event
func(ctrl *PersistentVolumeController, reactor *volumeReactor, test controllerTest) error {
volume := newVolume("volume5-7", "10Gi", "uid5-7", "claim5-7", api.VolumeBound, api.PersistentVolumeReclaimDelete)
volume = addVolumeAnnotation(volume, pvProvisioningRequiredAnnotationKey, "yes")
reactor.addVolumeEvent(volume)
return nil
},
},
{
// updateVolume with unprovisioned volume from Kubernetes 1.2. The
// volume should be deleted.
"5-8 - update bound volume from 1.2",
novolumes,
novolumes,
newClaimArray("claim5-8", "uid5-8", "1Gi", "", api.ClaimPending),
newClaimArray("claim5-8", "uid5-8", "1Gi", "", api.ClaimPending),
noevents, noerrors,
// Custom test function that generates a add event
func(ctrl *PersistentVolumeController, reactor *volumeReactor, test controllerTest) error {
volume := newVolume("volume5-8", "10Gi", "uid5-8", "claim5-8", api.VolumeBound, api.PersistentVolumeReclaimDelete)
volume = addVolumeAnnotation(volume, pvProvisioningRequiredAnnotationKey, "yes")
reactor.modifyVolumeEvent(volume)
return nil
},
},
}
for ix, test := range tests {
@@ -108,7 +176,7 @@ func TestControllerSync(t *testing.T) {
}
// Start the controller
defer ctrl.Stop()
count := reactor.getChangeCount()
go ctrl.Run()
// Wait for the controller to pass initial sync and fill its caches.
@@ -121,8 +189,6 @@ func TestControllerSync(t *testing.T) {
}
glog.V(4).Infof("controller synced, starting test")
count := reactor.getChangeCount()
// Call the tested function
err := test.test(ctrl, reactor, test)
if err != nil {
@@ -133,10 +199,15 @@ func TestControllerSync(t *testing.T) {
ctrl.claims.Resync()
ctrl.volumes.store.Resync()
// Wait at least once, just in case expectedChanges[ix] == 0
reactor.waitTest()
// Wait for expected number of operations.
for reactor.getChangeCount() < count+expectedChanges[ix] {
reactor.waitTest()
}
ctrl.Stop()
evaluateTestResults(ctrl, reactor, test, t)
}
}
@@ -208,3 +279,11 @@ func TestControllerCacheParsingError(t *testing.T) {
t.Errorf("Expected parsing error, got nil instead")
}
}
func addVolumeAnnotation(volume *api.PersistentVolume, annName, annValue string) *api.PersistentVolume {
if volume.Annotations == nil {
volume.Annotations = make(map[string]string)
}
volume.Annotations[annName] = annValue
return volume
}