From 676a3a70129f06239994403770f19b94a7f77f12 Mon Sep 17 00:00:00 2001 From: xing-yang Date: Sat, 5 Dec 2020 21:07:24 +0000 Subject: [PATCH] Only CSI plugin can have a DataSource --- .../volume/persistentvolume/framework_test.go | 10 +++++ .../volume/persistentvolume/provision_test.go | 38 +++++++++++++++++++ .../volume/persistentvolume/pv_controller.go | 10 +++++ 3 files changed, 58 insertions(+) diff --git a/pkg/controller/volume/persistentvolume/framework_test.go b/pkg/controller/volume/persistentvolume/framework_test.go index ee883b0fc66..b7e3d74d856 100644 --- a/pkg/controller/volume/persistentvolume/framework_test.go +++ b/pkg/controller/volume/persistentvolume/framework_test.go @@ -443,6 +443,15 @@ func claimWithAnnotation(name, value string, claims []*v1.PersistentVolumeClaim) return claims } +func claimWithDataSource(name, kind, apiGroup string, claims []*v1.PersistentVolumeClaim) []*v1.PersistentVolumeClaim { + claims[0].Spec.DataSource = &v1.TypedLocalObjectReference{ + Name: name, + Kind: kind, + APIGroup: &apiGroup, + } + return claims +} + func annotateClaim(claim *v1.PersistentVolumeClaim, ann map[string]string) *v1.PersistentVolumeClaim { if claim.Annotations == nil { claim.Annotations = map[string]string{} @@ -514,6 +523,7 @@ var ( classUnsupportedMountOptions string = "unsupported-mountoptions" classLarge string = "large" classWait string = "wait" + classCSI string = "csi" modeWait = storage.VolumeBindingWaitForFirstConsumer ) diff --git a/pkg/controller/volume/persistentvolume/provision_test.go b/pkg/controller/volume/persistentvolume/provision_test.go index 2f6fa907c4b..fba0628cc74 100644 --- a/pkg/controller/volume/persistentvolume/provision_test.go +++ b/pkg/controller/volume/persistentvolume/provision_test.go @@ -127,6 +127,20 @@ var storageClasses = []*storage.StorageClass{ MountOptions: []string{"foo"}, VolumeBindingMode: &modeImmediate, }, + { + TypeMeta: metav1.TypeMeta{ + Kind: "StorageClass", + }, + + ObjectMeta: metav1.ObjectMeta{ + Name: "csi", + }, + + Provisioner: "mydriver.csi.k8s.io", + Parameters: class1Parameters, + ReclaimPolicy: &deleteReclaimPolicy, + VolumeBindingMode: &modeImmediate, + }, } // call to storageClass 1, returning an error @@ -506,6 +520,30 @@ func TestProvisionSync(t *testing.T) { []string{"Normal ExternalProvisioning"}, noerrors, testSyncClaim, }, + { + // Provision a volume with a data source will fail + // for in-tree plugins + "11-25 - failed in-tree provision with data source", + novolumes, + novolumes, + claimWithDataSource("test-snap", "VolumeSnapshot", "snapshot.storage.k8s.io", newClaimArray("claim11-25", "uid11-25", "1Gi", "", v1.ClaimPending, &classGold)), + claimWithDataSource("test-snap", "VolumeSnapshot", "snapshot.storage.k8s.io", newClaimArray("claim11-25", "uid11-25", "1Gi", "", v1.ClaimPending, &classGold)), + []string{"Warning ProvisioningFailed"}, noerrors, + testSyncClaim, + }, + { + // Provision a volume with a data source will proceed + // for CSI plugins + "11-26 - csi with data source", + novolumes, + novolumes, + claimWithAnnotation(pvutil.AnnStorageProvisioner, "mydriver.csi.k8s.io", + claimWithDataSource("test-snap", "VolumeSnapshot", "snapshot.storage.k8s.io", newClaimArray("claim11-26", "uid11-26", "1Gi", "", v1.ClaimPending, &classCSI))), + claimWithAnnotation(pvutil.AnnStorageProvisioner, "mydriver.csi.k8s.io", + claimWithDataSource("test-snap", "VolumeSnapshot", "snapshot.storage.k8s.io", newClaimArray("claim11-26", "uid11-26", "1Gi", "", v1.ClaimPending, &classCSI))), + []string{"Normal ExternalProvisioning"}, + noerrors, wrapTestWithProvisionCalls([]provisionCall{}, testSyncClaim), + }, } runSyncTests(t, tests, storageClasses, []*v1.Pod{}) } diff --git a/pkg/controller/volume/persistentvolume/pv_controller.go b/pkg/controller/volume/persistentvolume/pv_controller.go index 5f9c7e96802..d892bf9ab9f 100644 --- a/pkg/controller/volume/persistentvolume/pv_controller.go +++ b/pkg/controller/volume/persistentvolume/pv_controller.go @@ -1474,7 +1474,17 @@ func (ctrl *PersistentVolumeController) provisionClaimOperation( // called from provisionClaim(), in this case, plugin MUST NOT be nil // NOTE: checks on plugin/storageClass has been saved pluginName := plugin.GetPluginName() + if pluginName != "kubernetes.io/csi" && claim.Spec.DataSource != nil { + // Only CSI plugin can have a DataSource. Fail the operation + // if Datasource in Claim is not nil and it is not a CSI plugin, + strerr := fmt.Sprintf("plugin %q is not a CSI plugin. Only CSI plugin can provision a claim with a datasource", pluginName) + klog.V(2).Infof(strerr) + ctrl.eventRecorder.Event(claim, v1.EventTypeWarning, events.ProvisioningFailed, strerr) + return pluginName, fmt.Errorf(strerr) + + } provisionerName := storageClass.Provisioner + klog.V(4).Infof("provisionClaimOperation [%s]: plugin name: %s, provisioner name: %s", claimToClaimKey(claim), pluginName, provisionerName) // Add provisioner annotation to be consistent with external provisioner workflow newClaim, err := ctrl.setClaimProvisioner(claim, provisionerName)