Skip to content

Commit 3678704

Browse files
authored
Merge pull request kubernetes#73653 from ddebroy/migprov1
Support dynamic provisioning for CSI migration scenarios
2 parents 711b310 + 23478f1 commit 3678704

File tree

5 files changed

+62
-8
lines changed

5 files changed

+62
-8
lines changed

pkg/controller/volume/persistentvolume/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ go_library(
6262
"//staging/src/k8s.io/cloud-provider:go_default_library",
6363
"//staging/src/k8s.io/cloud-provider/volume/errors:go_default_library",
6464
"//staging/src/k8s.io/csi-api/pkg/client/clientset/versioned:go_default_library",
65+
"//staging/src/k8s.io/csi-translation-lib:go_default_library",
6566
"//vendor/github.com/prometheus/client_golang/prometheus:go_default_library",
6667
"//vendor/k8s.io/klog:go_default_library",
6768
],

pkg/controller/volume/persistentvolume/framework_test.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -988,6 +988,22 @@ func wrapTestWithProvisionCalls(expectedProvisionCalls []provisionCall, toWrap t
988988
return wrapTestWithPluginCalls(nil, nil, expectedProvisionCalls, toWrap)
989989
}
990990

991+
// wrapTestWithCSIMigrationProvisionCalls returns a testCall that:
992+
// - configures controller with a volume plugin that emulates CSI migration
993+
// - calls given testCall
994+
func wrapTestWithCSIMigrationProvisionCalls(toWrap testCall) testCall {
995+
return func(ctrl *PersistentVolumeController, reactor *volumeReactor, test controllerTest) error {
996+
plugin := &mockVolumePlugin{
997+
isMigratedToCSI: true,
998+
}
999+
ctrl.volumePluginMgr.InitPlugins([]vol.VolumePlugin{plugin}, nil /* prober */, ctrl)
1000+
ctrl.csiNameFromIntreeNameHook = func(string) (string, error) {
1001+
return "vendor.com/MockCSIPlugin", nil
1002+
}
1003+
return toWrap(ctrl, reactor, test)
1004+
}
1005+
}
1006+
9911007
// wrapTestWithInjectedOperation returns a testCall that:
9921008
// - starts the controller and lets it run original testCall until
9931009
// scheduleOperation() call. It blocks the controller there and calls the
@@ -1229,6 +1245,7 @@ type mockVolumePlugin struct {
12291245
deleteCallCounter int
12301246
recycleCalls []error
12311247
recycleCallCounter int
1248+
isMigratedToCSI bool
12321249
provisionOptions vol.VolumeOptions
12331250
}
12341251

@@ -1259,7 +1276,7 @@ func (plugin *mockVolumePlugin) CanSupport(spec *vol.Spec) bool {
12591276
}
12601277

12611278
func (plugin *mockVolumePlugin) IsMigratedToCSI() bool {
1262-
return false
1279+
return plugin.isMigratedToCSI
12631280
}
12641281

12651282
func (plugin *mockVolumePlugin) RequiresRemount() bool {

pkg/controller/volume/persistentvolume/provision_test.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,17 @@ func TestProvisionSync(t *testing.T) {
421421
[]string{"Warning ProvisioningFailed Mount options"},
422422
noerrors, wrapTestWithProvisionCalls([]provisionCall{}, testSyncClaim),
423423
},
424+
{
425+
// No provisioning due to CSI migration + normal event with external provisioner
426+
"11-21 - external provisioner for CSI migration",
427+
novolumes,
428+
novolumes,
429+
newClaimArray("claim11-21", "uid11-21", "1Gi", "", v1.ClaimPending, &classGold),
430+
claimWithAnnotation(annStorageProvisioner, "vendor.com/MockCSIPlugin",
431+
newClaimArray("claim11-21", "uid11-21", "1Gi", "", v1.ClaimPending, &classGold)),
432+
[]string{"Normal ExternalProvisioning"},
433+
noerrors, wrapTestWithCSIMigrationProvisionCalls(testSyncClaim),
434+
},
424435
}
425436
runSyncTests(t, tests, storageClasses, []*v1.Pod{})
426437
}

pkg/controller/volume/persistentvolume/pv_controller.go

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import (
3939
"k8s.io/client-go/util/workqueue"
4040
cloudprovider "k8s.io/cloud-provider"
4141
volerr "k8s.io/cloud-provider/volume/errors"
42+
csitranslation "k8s.io/csi-translation-lib"
4243
v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
4344
"k8s.io/kubernetes/pkg/controller/volume/events"
4445
"k8s.io/kubernetes/pkg/controller/volume/persistentvolume/metrics"
@@ -230,6 +231,10 @@ type PersistentVolumeController struct {
230231

231232
createProvisionedPVRetryCount int
232233
createProvisionedPVInterval time.Duration
234+
235+
// For testing only: hook to intercept CSI driver name <=> Intree plugin name mapping
236+
// Not used when set to nil
237+
csiNameFromIntreeNameHook func(pluginName string) (string, error)
233238
}
234239

235240
// syncClaim is the main controller method to decide what to do with a claim.
@@ -1346,6 +1351,13 @@ func (ctrl *PersistentVolumeController) provisionClaim(claim *v1.PersistentVolum
13461351
return nil
13471352
}
13481353

1354+
func (ctrl *PersistentVolumeController) getCSINameFromIntreeName(pluginName string) (string, error) {
1355+
if ctrl.csiNameFromIntreeNameHook != nil {
1356+
return ctrl.csiNameFromIntreeNameHook(pluginName)
1357+
}
1358+
return csitranslation.GetCSINameFromIntreeName(pluginName)
1359+
}
1360+
13491361
// provisionClaimOperation provisions a volume. This method is running in
13501362
// standalone goroutine and already has all necessary locks.
13511363
func (ctrl *PersistentVolumeController) provisionClaimOperation(claim *v1.PersistentVolumeClaim) (string, error) {
@@ -1362,20 +1374,34 @@ func (ctrl *PersistentVolumeController) provisionClaimOperation(claim *v1.Persis
13621374
}
13631375

13641376
var pluginName string
1377+
provisionerName := storageClass.Provisioner
13651378
if plugin != nil {
1366-
pluginName = plugin.GetPluginName()
1379+
if plugin.IsMigratedToCSI() {
1380+
// pluginName is not set here to align with existing behavior
1381+
// of not setting pluginName for external provisioners (including CSI)
1382+
// Set provisionerName to CSI plugin name for setClaimProvisioner
1383+
provisionerName, err = ctrl.getCSINameFromIntreeName(storageClass.Provisioner)
1384+
if err != nil {
1385+
strerr := fmt.Sprintf("error getting CSI name for In tree plugin %s: %v", storageClass.Provisioner, err)
1386+
klog.V(2).Infof("%s", strerr)
1387+
ctrl.eventRecorder.Event(claim, v1.EventTypeWarning, events.ProvisioningFailed, strerr)
1388+
return "", err
1389+
}
1390+
} else {
1391+
pluginName = plugin.GetPluginName()
1392+
}
13671393
}
13681394

13691395
// Add provisioner annotation so external provisioners know when to start
1370-
newClaim, err := ctrl.setClaimProvisioner(claim, storageClass)
1396+
newClaim, err := ctrl.setClaimProvisioner(claim, provisionerName)
13711397
if err != nil {
13721398
// Save failed, the controller will retry in the next sync
13731399
klog.V(2).Infof("error saving claim %s: %v", claimToClaimKey(claim), err)
13741400
return pluginName, err
13751401
}
13761402
claim = newClaim
13771403

1378-
if plugin == nil {
1404+
if plugin == nil || plugin.IsMigratedToCSI() {
13791405
// findProvisionablePlugin returned no error nor plugin.
13801406
// This means that an unknown provisioner is requested. Report an event
13811407
// and wait for the external provisioner

pkg/controller/volume/persistentvolume/pv_controller_base.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import (
2222
"time"
2323

2424
"k8s.io/api/core/v1"
25-
storage "k8s.io/api/storage/v1"
2625
"k8s.io/apimachinery/pkg/api/errors"
2726
"k8s.io/apimachinery/pkg/api/meta"
2827
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -428,16 +427,16 @@ func (ctrl *PersistentVolumeController) resync() {
428427

429428
// setClaimProvisioner saves
430429
// claim.Annotations[annStorageProvisioner] = class.Provisioner
431-
func (ctrl *PersistentVolumeController) setClaimProvisioner(claim *v1.PersistentVolumeClaim, class *storage.StorageClass) (*v1.PersistentVolumeClaim, error) {
432-
if val, ok := claim.Annotations[annStorageProvisioner]; ok && val == class.Provisioner {
430+
func (ctrl *PersistentVolumeController) setClaimProvisioner(claim *v1.PersistentVolumeClaim, provisionerName string) (*v1.PersistentVolumeClaim, error) {
431+
if val, ok := claim.Annotations[annStorageProvisioner]; ok && val == provisionerName {
433432
// annotation is already set, nothing to do
434433
return claim, nil
435434
}
436435

437436
// The volume from method args can be pointing to watcher cache. We must not
438437
// modify these, therefore create a copy.
439438
claimClone := claim.DeepCopy()
440-
metav1.SetMetaDataAnnotation(&claimClone.ObjectMeta, annStorageProvisioner, class.Provisioner)
439+
metav1.SetMetaDataAnnotation(&claimClone.ObjectMeta, annStorageProvisioner, provisionerName)
441440
newClaim, err := ctrl.kubeClient.CoreV1().PersistentVolumeClaims(claim.Namespace).Update(claimClone)
442441
if err != nil {
443442
return newClaim, err

0 commit comments

Comments
 (0)