mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-25 12:43:23 +00:00
Merge pull request #82683 from davidz627/fix/translationStruct
Refactor CSI Translation Library into a struct that is injected into various components to simplify unit testing
This commit is contained in:
commit
14e5adfc85
@ -141,6 +141,7 @@ go_library(
|
|||||||
"//staging/src/k8s.io/component-base/cli/globalflag:go_default_library",
|
"//staging/src/k8s.io/component-base/cli/globalflag:go_default_library",
|
||||||
"//staging/src/k8s.io/component-base/version:go_default_library",
|
"//staging/src/k8s.io/component-base/version:go_default_library",
|
||||||
"//staging/src/k8s.io/component-base/version/verflag:go_default_library",
|
"//staging/src/k8s.io/component-base/version/verflag:go_default_library",
|
||||||
|
"//staging/src/k8s.io/csi-translation-lib:go_default_library",
|
||||||
"//staging/src/k8s.io/metrics/pkg/client/clientset/versioned/typed/metrics/v1beta1:go_default_library",
|
"//staging/src/k8s.io/metrics/pkg/client/clientset/versioned/typed/metrics/v1beta1:go_default_library",
|
||||||
"//staging/src/k8s.io/metrics/pkg/client/custom_metrics:go_default_library",
|
"//staging/src/k8s.io/metrics/pkg/client/custom_metrics:go_default_library",
|
||||||
"//staging/src/k8s.io/metrics/pkg/client/external_metrics:go_default_library",
|
"//staging/src/k8s.io/metrics/pkg/client/external_metrics:go_default_library",
|
||||||
|
@ -36,6 +36,7 @@ import (
|
|||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/client-go/metadata"
|
"k8s.io/client-go/metadata"
|
||||||
restclient "k8s.io/client-go/rest"
|
restclient "k8s.io/client-go/rest"
|
||||||
|
csitrans "k8s.io/csi-translation-lib"
|
||||||
"k8s.io/kubernetes/pkg/controller"
|
"k8s.io/kubernetes/pkg/controller"
|
||||||
cloudcontroller "k8s.io/kubernetes/pkg/controller/cloud"
|
cloudcontroller "k8s.io/kubernetes/pkg/controller/cloud"
|
||||||
endpointcontroller "k8s.io/kubernetes/pkg/controller/endpoint"
|
endpointcontroller "k8s.io/kubernetes/pkg/controller/endpoint"
|
||||||
@ -309,7 +310,8 @@ func startVolumeExpandController(ctx ControllerContext) (http.Handler, bool, err
|
|||||||
ctx.InformerFactory.Core().V1().PersistentVolumes(),
|
ctx.InformerFactory.Core().V1().PersistentVolumes(),
|
||||||
ctx.InformerFactory.Storage().V1().StorageClasses(),
|
ctx.InformerFactory.Storage().V1().StorageClasses(),
|
||||||
ctx.Cloud,
|
ctx.Cloud,
|
||||||
ProbeExpandableVolumePlugins(ctx.ComponentConfig.PersistentVolumeBinderController.VolumeConfiguration))
|
ProbeExpandableVolumePlugins(ctx.ComponentConfig.PersistentVolumeBinderController.VolumeConfiguration),
|
||||||
|
csitrans.New())
|
||||||
|
|
||||||
if expandControllerErr != nil {
|
if expandControllerErr != nil {
|
||||||
return nil, true, fmt.Errorf("failed to start volume expand controller : %v", expandControllerErr)
|
return nil, true, fmt.Errorf("failed to start volume expand controller : %v", expandControllerErr)
|
||||||
|
@ -32,7 +32,6 @@ go_library(
|
|||||||
"//staging/src/k8s.io/client-go/tools/record:go_default_library",
|
"//staging/src/k8s.io/client-go/tools/record:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/util/workqueue:go_default_library",
|
"//staging/src/k8s.io/client-go/util/workqueue:go_default_library",
|
||||||
"//staging/src/k8s.io/cloud-provider:go_default_library",
|
"//staging/src/k8s.io/cloud-provider:go_default_library",
|
||||||
"//staging/src/k8s.io/csi-translation-lib:go_default_library",
|
|
||||||
"//vendor/k8s.io/klog:go_default_library",
|
"//vendor/k8s.io/klog:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@ -75,6 +74,7 @@ go_test(
|
|||||||
"//staging/src/k8s.io/client-go/informers:go_default_library",
|
"//staging/src/k8s.io/client-go/informers:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/testing:go_default_library",
|
"//staging/src/k8s.io/client-go/testing:go_default_library",
|
||||||
"//staging/src/k8s.io/component-base/featuregate/testing:go_default_library",
|
"//staging/src/k8s.io/component-base/featuregate/testing:go_default_library",
|
||||||
|
"//staging/src/k8s.io/csi-translation-lib:go_default_library",
|
||||||
"//staging/src/k8s.io/csi-translation-lib/plugins:go_default_library",
|
"//staging/src/k8s.io/csi-translation-lib/plugins:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -41,7 +41,6 @@ import (
|
|||||||
"k8s.io/client-go/tools/record"
|
"k8s.io/client-go/tools/record"
|
||||||
"k8s.io/client-go/util/workqueue"
|
"k8s.io/client-go/util/workqueue"
|
||||||
cloudprovider "k8s.io/cloud-provider"
|
cloudprovider "k8s.io/cloud-provider"
|
||||||
csitranslation "k8s.io/csi-translation-lib"
|
|
||||||
v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
|
v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
|
||||||
"k8s.io/kubernetes/pkg/controller/volume/events"
|
"k8s.io/kubernetes/pkg/controller/volume/events"
|
||||||
"k8s.io/kubernetes/pkg/util/mount"
|
"k8s.io/kubernetes/pkg/util/mount"
|
||||||
@ -62,6 +61,11 @@ type ExpandController interface {
|
|||||||
Run(stopCh <-chan struct{})
|
Run(stopCh <-chan struct{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CSINameTranslator can get the CSI Driver name based on the in-tree plugin name
|
||||||
|
type CSINameTranslator interface {
|
||||||
|
GetCSINameFromInTreeName(pluginName string) (string, error)
|
||||||
|
}
|
||||||
|
|
||||||
type expandController struct {
|
type expandController struct {
|
||||||
// kubeClient is the kube API client used by volumehost to communicate with
|
// kubeClient is the kube API client used by volumehost to communicate with
|
||||||
// the API server.
|
// the API server.
|
||||||
@ -92,6 +96,8 @@ type expandController struct {
|
|||||||
operationGenerator operationexecutor.OperationGenerator
|
operationGenerator operationexecutor.OperationGenerator
|
||||||
|
|
||||||
queue workqueue.RateLimitingInterface
|
queue workqueue.RateLimitingInterface
|
||||||
|
|
||||||
|
translator CSINameTranslator
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewExpandController expands the pvs
|
// NewExpandController expands the pvs
|
||||||
@ -101,7 +107,8 @@ func NewExpandController(
|
|||||||
pvInformer coreinformers.PersistentVolumeInformer,
|
pvInformer coreinformers.PersistentVolumeInformer,
|
||||||
scInformer storageclassinformer.StorageClassInformer,
|
scInformer storageclassinformer.StorageClassInformer,
|
||||||
cloud cloudprovider.Interface,
|
cloud cloudprovider.Interface,
|
||||||
plugins []volume.VolumePlugin) (ExpandController, error) {
|
plugins []volume.VolumePlugin,
|
||||||
|
translator CSINameTranslator) (ExpandController, error) {
|
||||||
|
|
||||||
expc := &expandController{
|
expc := &expandController{
|
||||||
kubeClient: kubeClient,
|
kubeClient: kubeClient,
|
||||||
@ -113,6 +120,7 @@ func NewExpandController(
|
|||||||
classLister: scInformer.Lister(),
|
classLister: scInformer.Lister(),
|
||||||
classListerSynced: scInformer.Informer().HasSynced,
|
classListerSynced: scInformer.Informer().HasSynced,
|
||||||
queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "volume_expand"),
|
queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "volume_expand"),
|
||||||
|
translator: translator,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := expc.volumePluginMgr.InitPlugins(plugins, nil, expc); err != nil {
|
if err := expc.volumePluginMgr.InitPlugins(plugins, nil, expc); err != nil {
|
||||||
@ -255,7 +263,7 @@ func (expc *expandController) syncHandler(key string) error {
|
|||||||
if volumePlugin.IsMigratedToCSI() {
|
if volumePlugin.IsMigratedToCSI() {
|
||||||
msg := fmt.Sprintf("CSI migration enabled for %s; waiting for external resizer to expand the pvc", volumeResizerName)
|
msg := fmt.Sprintf("CSI migration enabled for %s; waiting for external resizer to expand the pvc", volumeResizerName)
|
||||||
expc.recorder.Event(pvc, v1.EventTypeNormal, events.ExternalExpanding, msg)
|
expc.recorder.Event(pvc, v1.EventTypeNormal, events.ExternalExpanding, msg)
|
||||||
csiResizerName, err := csitranslation.GetCSINameFromInTreeName(class.Provisioner)
|
csiResizerName, err := expc.translator.GetCSINameFromInTreeName(class.Provisioner)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorMsg := fmt.Sprintf("error getting CSI driver name for pvc %s, with error %v", util.ClaimToClaimKey(pvc), err)
|
errorMsg := fmt.Sprintf("error getting CSI driver name for pvc %s, with error %v", util.ClaimToClaimKey(pvc), err)
|
||||||
expc.recorder.Event(pvc, v1.EventTypeWarning, events.ExternalExpanding, errorMsg)
|
expc.recorder.Event(pvc, v1.EventTypeWarning, events.ExternalExpanding, errorMsg)
|
||||||
|
@ -33,6 +33,7 @@ import (
|
|||||||
"k8s.io/client-go/informers"
|
"k8s.io/client-go/informers"
|
||||||
coretesting "k8s.io/client-go/testing"
|
coretesting "k8s.io/client-go/testing"
|
||||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||||
|
csitrans "k8s.io/csi-translation-lib"
|
||||||
csitranslationplugins "k8s.io/csi-translation-lib/plugins"
|
csitranslationplugins "k8s.io/csi-translation-lib/plugins"
|
||||||
"k8s.io/kubernetes/pkg/controller"
|
"k8s.io/kubernetes/pkg/controller"
|
||||||
controllervolumetesting "k8s.io/kubernetes/pkg/controller/volume/attachdetach/testing"
|
controllervolumetesting "k8s.io/kubernetes/pkg/controller/volume/attachdetach/testing"
|
||||||
@ -123,7 +124,7 @@ func TestSyncHandler(t *testing.T) {
|
|||||||
if tc.storageClass != nil {
|
if tc.storageClass != nil {
|
||||||
informerFactory.Storage().V1().StorageClasses().Informer().GetIndexer().Add(tc.storageClass)
|
informerFactory.Storage().V1().StorageClasses().Informer().GetIndexer().Add(tc.storageClass)
|
||||||
}
|
}
|
||||||
expc, err := NewExpandController(fakeKubeClient, pvcInformer, pvInformer, storageClassInformer, nil, allPlugins)
|
expc, err := NewExpandController(fakeKubeClient, pvcInformer, pvInformer, storageClassInformer, nil, allPlugins, csitrans.New())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("error creating expand controller : %v", err)
|
t.Fatalf("error creating expand controller : %v", err)
|
||||||
}
|
}
|
||||||
|
@ -101,6 +101,7 @@ go_test(
|
|||||||
"//staging/src/k8s.io/client-go/tools/record:go_default_library",
|
"//staging/src/k8s.io/client-go/tools/record:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/tools/reference:go_default_library",
|
"//staging/src/k8s.io/client-go/tools/reference:go_default_library",
|
||||||
"//staging/src/k8s.io/component-base/featuregate/testing:go_default_library",
|
"//staging/src/k8s.io/component-base/featuregate/testing:go_default_library",
|
||||||
|
"//staging/src/k8s.io/csi-translation-lib:go_default_library",
|
||||||
"//vendor/k8s.io/klog:go_default_library",
|
"//vendor/k8s.io/klog:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -521,6 +521,12 @@ func wrapTestWithProvisionCalls(expectedProvisionCalls []provisionCall, toWrap t
|
|||||||
return wrapTestWithPluginCalls(nil, nil, expectedProvisionCalls, toWrap)
|
return wrapTestWithPluginCalls(nil, nil, expectedProvisionCalls, toWrap)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type fakeCSINameTranslator struct{}
|
||||||
|
|
||||||
|
func (t fakeCSINameTranslator) GetCSINameFromInTreeName(pluginName string) (string, error) {
|
||||||
|
return "vendor.com/MockCSIPlugin", nil
|
||||||
|
}
|
||||||
|
|
||||||
// wrapTestWithCSIMigrationProvisionCalls returns a testCall that:
|
// wrapTestWithCSIMigrationProvisionCalls returns a testCall that:
|
||||||
// - configures controller with a volume plugin that emulates CSI migration
|
// - configures controller with a volume plugin that emulates CSI migration
|
||||||
// - calls given testCall
|
// - calls given testCall
|
||||||
@ -530,9 +536,7 @@ func wrapTestWithCSIMigrationProvisionCalls(toWrap testCall) testCall {
|
|||||||
isMigratedToCSI: true,
|
isMigratedToCSI: true,
|
||||||
}
|
}
|
||||||
ctrl.volumePluginMgr.InitPlugins([]vol.VolumePlugin{plugin}, nil /* prober */, ctrl)
|
ctrl.volumePluginMgr.InitPlugins([]vol.VolumePlugin{plugin}, nil /* prober */, ctrl)
|
||||||
ctrl.csiNameFromIntreeNameHook = func(string) (string, error) {
|
ctrl.translator = fakeCSINameTranslator{}
|
||||||
return "vendor.com/MockCSIPlugin", nil
|
|
||||||
}
|
|
||||||
return toWrap(ctrl, reactor, test)
|
return toWrap(ctrl, reactor, test)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,6 @@ import (
|
|||||||
"k8s.io/client-go/util/workqueue"
|
"k8s.io/client-go/util/workqueue"
|
||||||
cloudprovider "k8s.io/cloud-provider"
|
cloudprovider "k8s.io/cloud-provider"
|
||||||
volerr "k8s.io/cloud-provider/volume/errors"
|
volerr "k8s.io/cloud-provider/volume/errors"
|
||||||
csitranslation "k8s.io/csi-translation-lib"
|
|
||||||
v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
|
v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
|
||||||
"k8s.io/kubernetes/pkg/controller/volume/events"
|
"k8s.io/kubernetes/pkg/controller/volume/events"
|
||||||
"k8s.io/kubernetes/pkg/controller/volume/persistentvolume/metrics"
|
"k8s.io/kubernetes/pkg/controller/volume/persistentvolume/metrics"
|
||||||
@ -134,6 +133,11 @@ const createProvisionedPVRetryCount = 5
|
|||||||
// Interval between retries when we create a PV object for a provisioned volume.
|
// Interval between retries when we create a PV object for a provisioned volume.
|
||||||
const createProvisionedPVInterval = 10 * time.Second
|
const createProvisionedPVInterval = 10 * time.Second
|
||||||
|
|
||||||
|
// CSINameTranslator can get the CSI Driver name based on the in-tree plugin name
|
||||||
|
type CSINameTranslator interface {
|
||||||
|
GetCSINameFromInTreeName(pluginName string) (string, error)
|
||||||
|
}
|
||||||
|
|
||||||
// PersistentVolumeController is a controller that synchronizes
|
// PersistentVolumeController is a controller that synchronizes
|
||||||
// PersistentVolumeClaims and PersistentVolumes. It starts two
|
// PersistentVolumeClaims and PersistentVolumes. It starts two
|
||||||
// cache.Controllers that watch PersistentVolume and PersistentVolumeClaim
|
// cache.Controllers that watch PersistentVolume and PersistentVolumeClaim
|
||||||
@ -200,10 +204,6 @@ type PersistentVolumeController struct {
|
|||||||
createProvisionedPVRetryCount int
|
createProvisionedPVRetryCount int
|
||||||
createProvisionedPVInterval time.Duration
|
createProvisionedPVInterval time.Duration
|
||||||
|
|
||||||
// For testing only: hook to intercept CSI driver name <=> Intree plugin name mapping
|
|
||||||
// Not used when set to nil
|
|
||||||
csiNameFromIntreeNameHook func(pluginName string) (string, error)
|
|
||||||
|
|
||||||
// operationTimestamps caches start timestamp of operations
|
// operationTimestamps caches start timestamp of operations
|
||||||
// (currently provision + binding/deletion) for metric recording.
|
// (currently provision + binding/deletion) for metric recording.
|
||||||
// Detailed lifecyle/key for each operation
|
// Detailed lifecyle/key for each operation
|
||||||
@ -225,6 +225,8 @@ type PersistentVolumeController struct {
|
|||||||
// the corresponding timestamp entry will be deleted from cache
|
// the corresponding timestamp entry will be deleted from cache
|
||||||
// abort: N.A.
|
// abort: N.A.
|
||||||
operationTimestamps metrics.OperationStartTimeCache
|
operationTimestamps metrics.OperationStartTimeCache
|
||||||
|
|
||||||
|
translator CSINameTranslator
|
||||||
}
|
}
|
||||||
|
|
||||||
// syncClaim is the main controller method to decide what to do with a claim.
|
// syncClaim is the main controller method to decide what to do with a claim.
|
||||||
@ -1355,13 +1357,6 @@ func (ctrl *PersistentVolumeController) provisionClaim(claim *v1.PersistentVolum
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ctrl *PersistentVolumeController) getCSINameFromIntreeName(pluginName string) (string, error) {
|
|
||||||
if ctrl.csiNameFromIntreeNameHook != nil {
|
|
||||||
return ctrl.csiNameFromIntreeNameHook(pluginName)
|
|
||||||
}
|
|
||||||
return csitranslation.GetCSINameFromInTreeName(pluginName)
|
|
||||||
}
|
|
||||||
|
|
||||||
// provisionClaimOperation provisions a volume. This method is running in
|
// provisionClaimOperation provisions a volume. This method is running in
|
||||||
// standalone goroutine and already has all necessary locks.
|
// standalone goroutine and already has all necessary locks.
|
||||||
func (ctrl *PersistentVolumeController) provisionClaimOperation(
|
func (ctrl *PersistentVolumeController) provisionClaimOperation(
|
||||||
@ -1571,7 +1566,7 @@ func (ctrl *PersistentVolumeController) provisionClaimOperationExternal(
|
|||||||
provisionerName := storageClass.Provisioner
|
provisionerName := storageClass.Provisioner
|
||||||
if plugin != nil {
|
if plugin != nil {
|
||||||
// update the provisioner name to use the CSI in-tree name
|
// update the provisioner name to use the CSI in-tree name
|
||||||
provisionerName, err = ctrl.getCSINameFromIntreeName(storageClass.Provisioner)
|
provisionerName, err = ctrl.translator.GetCSINameFromInTreeName(storageClass.Provisioner)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
strerr := fmt.Sprintf("error getting CSI name for In tree plugin %s: %v", storageClass.Provisioner, err)
|
strerr := fmt.Sprintf("error getting CSI name for In tree plugin %s: %v", storageClass.Provisioner, err)
|
||||||
klog.V(2).Infof("%s", strerr)
|
klog.V(2).Infof("%s", strerr)
|
||||||
@ -1732,7 +1727,7 @@ func (ctrl *PersistentVolumeController) getProvisionerNameFromVolume(volume *v1.
|
|||||||
return "N/A"
|
return "N/A"
|
||||||
}
|
}
|
||||||
if plugin != nil {
|
if plugin != nil {
|
||||||
provisionerName, err := ctrl.getCSINameFromIntreeName(class.Provisioner)
|
provisionerName, err := ctrl.translator.GetCSINameFromInTreeName(class.Provisioner)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return provisionerName
|
return provisionerName
|
||||||
}
|
}
|
||||||
@ -1747,7 +1742,7 @@ func (ctrl *PersistentVolumeController) getProvisionerName(plugin vol.Provisiona
|
|||||||
return plugin.GetPluginName()
|
return plugin.GetPluginName()
|
||||||
} else if plugin != nil {
|
} else if plugin != nil {
|
||||||
// get the CSI in-tree name from storage class provisioner name
|
// get the CSI in-tree name from storage class provisioner name
|
||||||
provisionerName, err := ctrl.getCSINameFromIntreeName(storageClass.Provisioner)
|
provisionerName, err := ctrl.translator.GetCSINameFromInTreeName(storageClass.Provisioner)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "N/A"
|
return "N/A"
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,7 @@ import (
|
|||||||
"k8s.io/client-go/tools/record"
|
"k8s.io/client-go/tools/record"
|
||||||
"k8s.io/client-go/util/workqueue"
|
"k8s.io/client-go/util/workqueue"
|
||||||
cloudprovider "k8s.io/cloud-provider"
|
cloudprovider "k8s.io/cloud-provider"
|
||||||
|
csitrans "k8s.io/csi-translation-lib"
|
||||||
"k8s.io/kubernetes/pkg/controller"
|
"k8s.io/kubernetes/pkg/controller"
|
||||||
"k8s.io/kubernetes/pkg/controller/volume/persistentvolume/metrics"
|
"k8s.io/kubernetes/pkg/controller/volume/persistentvolume/metrics"
|
||||||
pvutil "k8s.io/kubernetes/pkg/controller/volume/persistentvolume/util"
|
pvutil "k8s.io/kubernetes/pkg/controller/volume/persistentvolume/util"
|
||||||
@ -93,6 +94,7 @@ func NewController(p ControllerParameters) (*PersistentVolumeController, error)
|
|||||||
volumeQueue: workqueue.NewNamed("volumes"),
|
volumeQueue: workqueue.NewNamed("volumes"),
|
||||||
resyncPeriod: p.SyncPeriod,
|
resyncPeriod: p.SyncPeriod,
|
||||||
operationTimestamps: metrics.NewOperationStartTimeCache(),
|
operationTimestamps: metrics.NewOperationStartTimeCache(),
|
||||||
|
translator: csitrans.New(),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prober is nil because PV is not aware of Flexvolume.
|
// Prober is nil because PV is not aware of Flexvolume.
|
||||||
|
@ -30,6 +30,7 @@ import (
|
|||||||
storagelisters "k8s.io/client-go/listers/storage/v1"
|
storagelisters "k8s.io/client-go/listers/storage/v1"
|
||||||
core "k8s.io/client-go/testing"
|
core "k8s.io/client-go/testing"
|
||||||
"k8s.io/client-go/tools/cache"
|
"k8s.io/client-go/tools/cache"
|
||||||
|
csitrans "k8s.io/csi-translation-lib"
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
"k8s.io/kubernetes/pkg/controller"
|
"k8s.io/kubernetes/pkg/controller"
|
||||||
pvtesting "k8s.io/kubernetes/pkg/controller/volume/persistentvolume/testing"
|
pvtesting "k8s.io/kubernetes/pkg/controller/volume/persistentvolume/testing"
|
||||||
@ -438,6 +439,7 @@ func TestDelayBindingMode(t *testing.T) {
|
|||||||
classInformer := informerFactory.Storage().V1().StorageClasses()
|
classInformer := informerFactory.Storage().V1().StorageClasses()
|
||||||
ctrl := &PersistentVolumeController{
|
ctrl := &PersistentVolumeController{
|
||||||
classLister: classInformer.Lister(),
|
classLister: classInformer.Lister(),
|
||||||
|
translator: csitrans.New(),
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, class := range classes {
|
for _, class := range classes {
|
||||||
|
@ -23,7 +23,7 @@ import (
|
|||||||
storagev1beta1 "k8s.io/api/storage/v1beta1"
|
storagev1beta1 "k8s.io/api/storage/v1beta1"
|
||||||
"k8s.io/apimachinery/pkg/util/rand"
|
"k8s.io/apimachinery/pkg/util/rand"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
csilib "k8s.io/csi-translation-lib"
|
csitrans "k8s.io/csi-translation-lib"
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
|
v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
|
||||||
"k8s.io/kubernetes/pkg/features"
|
"k8s.io/kubernetes/pkg/features"
|
||||||
@ -31,6 +31,16 @@ import (
|
|||||||
volumeutil "k8s.io/kubernetes/pkg/volume/util"
|
volumeutil "k8s.io/kubernetes/pkg/volume/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// InTreeToCSITranslator contains methods required to check migratable status
|
||||||
|
// and perform translations from InTree PV's to CSI
|
||||||
|
type InTreeToCSITranslator interface {
|
||||||
|
IsPVMigratable(pv *v1.PersistentVolume) bool
|
||||||
|
IsMigratableIntreePluginByName(inTreePluginName string) bool
|
||||||
|
GetInTreePluginNameFromSpec(pv *v1.PersistentVolume, vol *v1.Volume) (string, error)
|
||||||
|
GetCSINameFromInTreeName(pluginName string) (string, error)
|
||||||
|
TranslateInTreePVToCSI(pv *v1.PersistentVolume) (*v1.PersistentVolume, error)
|
||||||
|
}
|
||||||
|
|
||||||
// CSIMaxVolumeLimitChecker defines predicate needed for counting CSI volumes
|
// CSIMaxVolumeLimitChecker defines predicate needed for counting CSI volumes
|
||||||
type CSIMaxVolumeLimitChecker struct {
|
type CSIMaxVolumeLimitChecker struct {
|
||||||
csiNodeInfo CSINodeInfo
|
csiNodeInfo CSINodeInfo
|
||||||
@ -39,6 +49,8 @@ type CSIMaxVolumeLimitChecker struct {
|
|||||||
scInfo StorageClassInfo
|
scInfo StorageClassInfo
|
||||||
|
|
||||||
randomVolumeIDPrefix string
|
randomVolumeIDPrefix string
|
||||||
|
|
||||||
|
translator InTreeToCSITranslator
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCSIMaxVolumeLimitPredicate returns a predicate for counting CSI volumes
|
// NewCSIMaxVolumeLimitPredicate returns a predicate for counting CSI volumes
|
||||||
@ -50,6 +62,7 @@ func NewCSIMaxVolumeLimitPredicate(
|
|||||||
pvcInfo: pvcInfo,
|
pvcInfo: pvcInfo,
|
||||||
scInfo: scInfo,
|
scInfo: scInfo,
|
||||||
randomVolumeIDPrefix: rand.String(32),
|
randomVolumeIDPrefix: rand.String(32),
|
||||||
|
translator: csitrans.New(),
|
||||||
}
|
}
|
||||||
return c.attachableLimitPredicate
|
return c.attachableLimitPredicate
|
||||||
}
|
}
|
||||||
@ -201,11 +214,11 @@ func (c *CSIMaxVolumeLimitChecker) getCSIDriverInfo(csiNode *storagev1beta1.CSIN
|
|||||||
csiSource := pv.Spec.PersistentVolumeSource.CSI
|
csiSource := pv.Spec.PersistentVolumeSource.CSI
|
||||||
if csiSource == nil {
|
if csiSource == nil {
|
||||||
// We make a fast path for non-CSI volumes that aren't migratable
|
// We make a fast path for non-CSI volumes that aren't migratable
|
||||||
if !csilib.IsPVMigratable(pv) {
|
if !c.translator.IsPVMigratable(pv) {
|
||||||
return "", ""
|
return "", ""
|
||||||
}
|
}
|
||||||
|
|
||||||
pluginName, err := csilib.GetInTreePluginNameFromSpec(pv, nil)
|
pluginName, err := c.translator.GetInTreePluginNameFromSpec(pv, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.V(5).Infof("Unable to look up plugin name from PV spec: %v", err)
|
klog.V(5).Infof("Unable to look up plugin name from PV spec: %v", err)
|
||||||
return "", ""
|
return "", ""
|
||||||
@ -216,7 +229,7 @@ func (c *CSIMaxVolumeLimitChecker) getCSIDriverInfo(csiNode *storagev1beta1.CSIN
|
|||||||
return "", ""
|
return "", ""
|
||||||
}
|
}
|
||||||
|
|
||||||
csiPV, err := csilib.TranslateInTreePVToCSI(pv)
|
csiPV, err := c.translator.TranslateInTreePVToCSI(pv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.V(5).Infof("Unable to translate in-tree volume to CSI: %v", err)
|
klog.V(5).Infof("Unable to translate in-tree volume to CSI: %v", err)
|
||||||
return "", ""
|
return "", ""
|
||||||
@ -258,13 +271,13 @@ func (c *CSIMaxVolumeLimitChecker) getCSIDriverInfoFromSC(csiNode *storagev1beta
|
|||||||
volumeHandle := fmt.Sprintf("%s-%s/%s", c.randomVolumeIDPrefix, namespace, pvcName)
|
volumeHandle := fmt.Sprintf("%s-%s/%s", c.randomVolumeIDPrefix, namespace, pvcName)
|
||||||
|
|
||||||
provisioner := storageClass.Provisioner
|
provisioner := storageClass.Provisioner
|
||||||
if csilib.IsMigratableIntreePluginByName(provisioner) {
|
if c.translator.IsMigratableIntreePluginByName(provisioner) {
|
||||||
if !isCSIMigrationOn(csiNode, provisioner) {
|
if !isCSIMigrationOn(csiNode, provisioner) {
|
||||||
klog.V(5).Infof("CSI Migration of plugin %s is not enabled", provisioner)
|
klog.V(5).Infof("CSI Migration of plugin %s is not enabled", provisioner)
|
||||||
return "", ""
|
return "", ""
|
||||||
}
|
}
|
||||||
|
|
||||||
driverName, err := csilib.GetCSINameFromInTreeName(provisioner)
|
driverName, err := c.translator.GetCSINameFromInTreeName(provisioner)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.V(5).Infof("Unable to look up driver name from plugin name: %v", err)
|
klog.V(5).Infof("Unable to look up driver name from plugin name: %v", err)
|
||||||
return "", ""
|
return "", ""
|
||||||
|
@ -67,6 +67,7 @@ go_test(
|
|||||||
"//staging/src/k8s.io/component-base/featuregate:go_default_library",
|
"//staging/src/k8s.io/component-base/featuregate:go_default_library",
|
||||||
"//staging/src/k8s.io/component-base/featuregate/testing:go_default_library",
|
"//staging/src/k8s.io/component-base/featuregate/testing:go_default_library",
|
||||||
"//staging/src/k8s.io/component-base/metrics/legacyregistry:go_default_library",
|
"//staging/src/k8s.io/component-base/metrics/legacyregistry:go_default_library",
|
||||||
|
"//staging/src/k8s.io/csi-translation-lib:go_default_library",
|
||||||
"//staging/src/k8s.io/csi-translation-lib/plugins:go_default_library",
|
"//staging/src/k8s.io/csi-translation-lib/plugins:go_default_library",
|
||||||
"//vendor/github.com/prometheus/client_model/go:go_default_library",
|
"//vendor/github.com/prometheus/client_model/go:go_default_library",
|
||||||
"//vendor/github.com/stretchr/testify/assert:go_default_library",
|
"//vendor/github.com/stretchr/testify/assert:go_default_library",
|
||||||
|
@ -21,6 +21,7 @@ import (
|
|||||||
|
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
|
csitrans "k8s.io/csi-translation-lib"
|
||||||
"k8s.io/kubernetes/pkg/volume"
|
"k8s.io/kubernetes/pkg/volume"
|
||||||
"k8s.io/kubernetes/pkg/volume/util/hostutil"
|
"k8s.io/kubernetes/pkg/volume/util/hostutil"
|
||||||
volumetypes "k8s.io/kubernetes/pkg/volume/util/types"
|
volumetypes "k8s.io/kubernetes/pkg/volume/util/types"
|
||||||
@ -88,6 +89,10 @@ func (f *fakeOGCounter) GetVolumePluginMgr() *volume.VolumePluginMgr {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *fakeOGCounter) GetCSITranslator() InTreeToCSITranslator {
|
||||||
|
return csitrans.New()
|
||||||
|
}
|
||||||
|
|
||||||
func (f *fakeOGCounter) GenerateBulkVolumeVerifyFunc(
|
func (f *fakeOGCounter) GenerateBulkVolumeVerifyFunc(
|
||||||
map[types.NodeName][]*volume.Spec,
|
map[types.NodeName][]*volume.Spec,
|
||||||
string,
|
string,
|
||||||
|
@ -641,14 +641,14 @@ func (oe *operationExecutor) VerifyVolumesAreAttached(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Migration: Must also check the Node since Attach would have been done with in-tree if node is not using Migration
|
// Migration: Must also check the Node since Attach would have been done with in-tree if node is not using Migration
|
||||||
nu, err := nodeUsingCSIPlugin(oe.operationGenerator, volumeAttached.VolumeSpec, node)
|
nu, err := nodeUsingCSIPlugin(oe.operationGenerator.GetCSITranslator(), oe.operationGenerator.GetVolumePluginMgr(), volumeAttached.VolumeSpec, node)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf(volumeAttached.GenerateErrorDetailed("VolumesAreAttached.NodeUsingCSIPlugin failed", err).Error())
|
klog.Errorf(volumeAttached.GenerateErrorDetailed("VolumesAreAttached.NodeUsingCSIPlugin failed", err).Error())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var volumePlugin volume.VolumePlugin
|
var volumePlugin volume.VolumePlugin
|
||||||
if useCSIPlugin(oe.operationGenerator.GetVolumePluginMgr(), volumeAttached.VolumeSpec) && nu {
|
if useCSIPlugin(oe.operationGenerator.GetCSITranslator(), oe.operationGenerator.GetVolumePluginMgr(), volumeAttached.VolumeSpec) && nu {
|
||||||
// The volume represented by this spec is CSI and thus should be migrated
|
// The volume represented by this spec is CSI and thus should be migrated
|
||||||
volumePlugin, err = oe.operationGenerator.GetVolumePluginMgr().FindPluginByName(csi.CSIPluginName)
|
volumePlugin, err = oe.operationGenerator.GetVolumePluginMgr().FindPluginByName(csi.CSIPluginName)
|
||||||
if err != nil || volumePlugin == nil {
|
if err != nil || volumePlugin == nil {
|
||||||
@ -661,7 +661,7 @@ func (oe *operationExecutor) VerifyVolumesAreAttached(
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
csiSpec, err := translateSpec(volumeAttached.VolumeSpec)
|
csiSpec, err := translateSpec(oe.operationGenerator.GetCSITranslator(), volumeAttached.VolumeSpec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf(volumeAttached.GenerateErrorDetailed("VolumesAreAttached.TranslateSpec failed", err).Error())
|
klog.Errorf(volumeAttached.GenerateErrorDetailed("VolumesAreAttached.TranslateSpec failed", err).Error())
|
||||||
continue
|
continue
|
||||||
|
@ -25,6 +25,7 @@ import (
|
|||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
"k8s.io/apimachinery/pkg/util/uuid"
|
"k8s.io/apimachinery/pkg/util/uuid"
|
||||||
|
csitrans "k8s.io/csi-translation-lib"
|
||||||
"k8s.io/kubernetes/pkg/volume"
|
"k8s.io/kubernetes/pkg/volume"
|
||||||
"k8s.io/kubernetes/pkg/volume/util/hostutil"
|
"k8s.io/kubernetes/pkg/volume/util/hostutil"
|
||||||
volumetypes "k8s.io/kubernetes/pkg/volume/util/types"
|
volumetypes "k8s.io/kubernetes/pkg/volume/util/types"
|
||||||
@ -520,6 +521,10 @@ func (fopg *fakeOperationGenerator) GetVolumePluginMgr() *volume.VolumePluginMgr
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (fopg *fakeOperationGenerator) GetCSITranslator() InTreeToCSITranslator {
|
||||||
|
return csitrans.New()
|
||||||
|
}
|
||||||
|
|
||||||
func getTestPodWithSecret(podName, secretName string) *v1.Pod {
|
func getTestPodWithSecret(podName, secretName string) *v1.Pod {
|
||||||
return &v1.Pod{
|
return &v1.Pod{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
@ -32,7 +32,7 @@ import (
|
|||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/client-go/tools/record"
|
"k8s.io/client-go/tools/record"
|
||||||
volerr "k8s.io/cloud-provider/volume/errors"
|
volerr "k8s.io/cloud-provider/volume/errors"
|
||||||
csilib "k8s.io/csi-translation-lib"
|
csitrans "k8s.io/csi-translation-lib"
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
"k8s.io/kubernetes/pkg/features"
|
"k8s.io/kubernetes/pkg/features"
|
||||||
kevents "k8s.io/kubernetes/pkg/kubelet/events"
|
kevents "k8s.io/kubernetes/pkg/kubelet/events"
|
||||||
@ -49,6 +49,18 @@ const (
|
|||||||
unknownAttachableVolumePlugin string = "UnknownAttachableVolumePlugin"
|
unknownAttachableVolumePlugin string = "UnknownAttachableVolumePlugin"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// InTreeToCSITranslator contains methods required to check migratable status
|
||||||
|
// and perform translations from InTree PVs and Inline to CSI
|
||||||
|
type InTreeToCSITranslator interface {
|
||||||
|
IsPVMigratable(pv *v1.PersistentVolume) bool
|
||||||
|
IsInlineMigratable(vol *v1.Volume) bool
|
||||||
|
IsMigratableIntreePluginByName(inTreePluginName string) bool
|
||||||
|
GetInTreePluginNameFromSpec(pv *v1.PersistentVolume, vol *v1.Volume) (string, error)
|
||||||
|
GetCSINameFromInTreeName(pluginName string) (string, error)
|
||||||
|
TranslateInTreePVToCSI(pv *v1.PersistentVolume) (*v1.PersistentVolume, error)
|
||||||
|
TranslateInTreeInlineVolumeToCSI(volume *v1.Volume) (*v1.PersistentVolume, error)
|
||||||
|
}
|
||||||
|
|
||||||
var _ OperationGenerator = &operationGenerator{}
|
var _ OperationGenerator = &operationGenerator{}
|
||||||
|
|
||||||
type operationGenerator struct {
|
type operationGenerator struct {
|
||||||
@ -70,6 +82,8 @@ type operationGenerator struct {
|
|||||||
|
|
||||||
// blkUtil provides volume path related operations for block volume
|
// blkUtil provides volume path related operations for block volume
|
||||||
blkUtil volumepathhandler.BlockVolumePathHandler
|
blkUtil volumepathhandler.BlockVolumePathHandler
|
||||||
|
|
||||||
|
translator InTreeToCSITranslator
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewOperationGenerator is returns instance of operationGenerator
|
// NewOperationGenerator is returns instance of operationGenerator
|
||||||
@ -85,6 +99,7 @@ func NewOperationGenerator(kubeClient clientset.Interface,
|
|||||||
recorder: recorder,
|
recorder: recorder,
|
||||||
checkNodeCapabilitiesBeforeMount: checkNodeCapabilitiesBeforeMount,
|
checkNodeCapabilitiesBeforeMount: checkNodeCapabilitiesBeforeMount,
|
||||||
blkUtil: blkUtil,
|
blkUtil: blkUtil,
|
||||||
|
translator: csitrans.New(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,6 +138,9 @@ type OperationGenerator interface {
|
|||||||
// GetVolumePluginMgr returns volume plugin manager
|
// GetVolumePluginMgr returns volume plugin manager
|
||||||
GetVolumePluginMgr() *volume.VolumePluginMgr
|
GetVolumePluginMgr() *volume.VolumePluginMgr
|
||||||
|
|
||||||
|
// GetCSITranslator returns the CSI Translation Library
|
||||||
|
GetCSITranslator() InTreeToCSITranslator
|
||||||
|
|
||||||
GenerateBulkVolumeVerifyFunc(
|
GenerateBulkVolumeVerifyFunc(
|
||||||
map[types.NodeName][]*volume.Spec,
|
map[types.NodeName][]*volume.Spec,
|
||||||
string,
|
string,
|
||||||
@ -153,14 +171,14 @@ func (og *operationGenerator) GenerateVolumesAreAttachedFunc(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Migration: Must also check the Node since Attach would have been done with in-tree if node is not using Migration
|
// Migration: Must also check the Node since Attach would have been done with in-tree if node is not using Migration
|
||||||
nu, err := nodeUsingCSIPlugin(og, volumeAttached.VolumeSpec, nodeName)
|
nu, err := nodeUsingCSIPlugin(og.translator, og.volumePluginMgr, volumeAttached.VolumeSpec, nodeName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf(volumeAttached.GenerateErrorDetailed("VolumesAreAttached.NodeUsingCSIPlugin failed", err).Error())
|
klog.Errorf(volumeAttached.GenerateErrorDetailed("VolumesAreAttached.NodeUsingCSIPlugin failed", err).Error())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var volumePlugin volume.VolumePlugin
|
var volumePlugin volume.VolumePlugin
|
||||||
if useCSIPlugin(og.volumePluginMgr, volumeAttached.VolumeSpec) && nu {
|
if useCSIPlugin(og.translator, og.volumePluginMgr, volumeAttached.VolumeSpec) && nu {
|
||||||
// The volume represented by this spec is CSI and thus should be migrated
|
// The volume represented by this spec is CSI and thus should be migrated
|
||||||
volumePlugin, err = og.volumePluginMgr.FindPluginByName(csi.CSIPluginName)
|
volumePlugin, err = og.volumePluginMgr.FindPluginByName(csi.CSIPluginName)
|
||||||
if err != nil || volumePlugin == nil {
|
if err != nil || volumePlugin == nil {
|
||||||
@ -168,7 +186,7 @@ func (og *operationGenerator) GenerateVolumesAreAttachedFunc(
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
csiSpec, err := translateSpec(volumeAttached.VolumeSpec)
|
csiSpec, err := translateSpec(og.translator, volumeAttached.VolumeSpec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf(volumeAttached.GenerateErrorDetailed("VolumesAreAttached.TranslateSpec failed", err).Error())
|
klog.Errorf(volumeAttached.GenerateErrorDetailed("VolumesAreAttached.TranslateSpec failed", err).Error())
|
||||||
continue
|
continue
|
||||||
@ -330,20 +348,20 @@ func (og *operationGenerator) GenerateAttachVolumeFunc(
|
|||||||
attachVolumeFunc := func() (error, error) {
|
attachVolumeFunc := func() (error, error) {
|
||||||
var attachableVolumePlugin volume.AttachableVolumePlugin
|
var attachableVolumePlugin volume.AttachableVolumePlugin
|
||||||
|
|
||||||
nu, err := nodeUsingCSIPlugin(og, volumeToAttach.VolumeSpec, volumeToAttach.NodeName)
|
nu, err := nodeUsingCSIPlugin(og.translator, og.volumePluginMgr, volumeToAttach.VolumeSpec, volumeToAttach.NodeName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return volumeToAttach.GenerateError("AttachVolume.NodeUsingCSIPlugin failed", err)
|
return volumeToAttach.GenerateError("AttachVolume.NodeUsingCSIPlugin failed", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// useCSIPlugin will check both CSIMigration and the plugin specific feature gates
|
// useCSIPlugin will check both CSIMigration and the plugin specific feature gates
|
||||||
if useCSIPlugin(og.volumePluginMgr, volumeToAttach.VolumeSpec) && nu {
|
if useCSIPlugin(og.translator, og.volumePluginMgr, volumeToAttach.VolumeSpec) && nu {
|
||||||
// The volume represented by this spec is CSI and thus should be migrated
|
// The volume represented by this spec is CSI and thus should be migrated
|
||||||
attachableVolumePlugin, err = og.volumePluginMgr.FindAttachablePluginByName(csi.CSIPluginName)
|
attachableVolumePlugin, err = og.volumePluginMgr.FindAttachablePluginByName(csi.CSIPluginName)
|
||||||
if err != nil || attachableVolumePlugin == nil {
|
if err != nil || attachableVolumePlugin == nil {
|
||||||
return volumeToAttach.GenerateError("AttachVolume.FindAttachablePluginByName failed", err)
|
return volumeToAttach.GenerateError("AttachVolume.FindAttachablePluginByName failed", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
csiSpec, err := translateSpec(volumeToAttach.VolumeSpec)
|
csiSpec, err := translateSpec(og.translator, volumeToAttach.VolumeSpec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return volumeToAttach.GenerateError("AttachVolume.TranslateSpec failed", err)
|
return volumeToAttach.GenerateError("AttachVolume.TranslateSpec failed", err)
|
||||||
}
|
}
|
||||||
@ -416,15 +434,15 @@ func (og *operationGenerator) GenerateAttachVolumeFunc(
|
|||||||
// involves determining the plugin_name for the metric generating "CompleteFunc"
|
// involves determining the plugin_name for the metric generating "CompleteFunc"
|
||||||
// during the actual "OperationFunc" and not during this generation function
|
// during the actual "OperationFunc" and not during this generation function
|
||||||
|
|
||||||
nu, err := nodeUsingCSIPlugin(og, volumeToAttach.VolumeSpec, volumeToAttach.NodeName)
|
nu, err := nodeUsingCSIPlugin(og.translator, og.volumePluginMgr, volumeToAttach.VolumeSpec, volumeToAttach.NodeName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("GenerateAttachVolumeFunc failed to check if node is using CSI Plugin, metric for this operation may be inaccurate: %v", err)
|
klog.Errorf("GenerateAttachVolumeFunc failed to check if node is using CSI Plugin, metric for this operation may be inaccurate: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Need to translate the spec here if the plugin is migrated so that the metrics
|
// Need to translate the spec here if the plugin is migrated so that the metrics
|
||||||
// emitted show the correct (migrated) plugin
|
// emitted show the correct (migrated) plugin
|
||||||
if useCSIPlugin(og.volumePluginMgr, volumeToAttach.VolumeSpec) && nu {
|
if useCSIPlugin(og.translator, og.volumePluginMgr, volumeToAttach.VolumeSpec) && nu {
|
||||||
csiSpec, err := translateSpec(volumeToAttach.VolumeSpec)
|
csiSpec, err := translateSpec(og.translator, volumeToAttach.VolumeSpec)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
volumeToAttach.VolumeSpec = csiSpec
|
volumeToAttach.VolumeSpec = csiSpec
|
||||||
}
|
}
|
||||||
@ -456,6 +474,10 @@ func (og *operationGenerator) GetVolumePluginMgr() *volume.VolumePluginMgr {
|
|||||||
return og.volumePluginMgr
|
return og.volumePluginMgr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (og *operationGenerator) GetCSITranslator() InTreeToCSITranslator {
|
||||||
|
return og.translator
|
||||||
|
}
|
||||||
|
|
||||||
func (og *operationGenerator) GenerateDetachVolumeFunc(
|
func (og *operationGenerator) GenerateDetachVolumeFunc(
|
||||||
volumeToDetach AttachedVolume,
|
volumeToDetach AttachedVolume,
|
||||||
verifySafeToDetach bool,
|
verifySafeToDetach bool,
|
||||||
@ -467,20 +489,20 @@ func (og *operationGenerator) GenerateDetachVolumeFunc(
|
|||||||
|
|
||||||
if volumeToDetach.VolumeSpec != nil {
|
if volumeToDetach.VolumeSpec != nil {
|
||||||
// Get attacher plugin
|
// Get attacher plugin
|
||||||
nu, err := nodeUsingCSIPlugin(og, volumeToDetach.VolumeSpec, volumeToDetach.NodeName)
|
nu, err := nodeUsingCSIPlugin(og.translator, og.volumePluginMgr, volumeToDetach.VolumeSpec, volumeToDetach.NodeName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return volumetypes.GeneratedOperations{}, volumeToDetach.GenerateErrorDetailed("DetachVolume.NodeUsingCSIPlugin failed", err)
|
return volumetypes.GeneratedOperations{}, volumeToDetach.GenerateErrorDetailed("DetachVolume.NodeUsingCSIPlugin failed", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// useCSIPlugin will check both CSIMigration and the plugin specific feature gate
|
// useCSIPlugin will check both CSIMigration and the plugin specific feature gate
|
||||||
if useCSIPlugin(og.volumePluginMgr, volumeToDetach.VolumeSpec) && nu {
|
if useCSIPlugin(og.translator, og.volumePluginMgr, volumeToDetach.VolumeSpec) && nu {
|
||||||
// The volume represented by this spec is CSI and thus should be migrated
|
// The volume represented by this spec is CSI and thus should be migrated
|
||||||
attachableVolumePlugin, err = og.volumePluginMgr.FindAttachablePluginByName(csi.CSIPluginName)
|
attachableVolumePlugin, err = og.volumePluginMgr.FindAttachablePluginByName(csi.CSIPluginName)
|
||||||
if err != nil || attachableVolumePlugin == nil {
|
if err != nil || attachableVolumePlugin == nil {
|
||||||
return volumetypes.GeneratedOperations{}, volumeToDetach.GenerateErrorDetailed("DetachVolume.FindAttachablePluginBySpec failed", err)
|
return volumetypes.GeneratedOperations{}, volumeToDetach.GenerateErrorDetailed("DetachVolume.FindAttachablePluginBySpec failed", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
csiSpec, err := translateSpec(volumeToDetach.VolumeSpec)
|
csiSpec, err := translateSpec(og.translator, volumeToDetach.VolumeSpec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return volumetypes.GeneratedOperations{}, volumeToDetach.GenerateErrorDetailed("DetachVolume.TranslateSpec failed", err)
|
return volumetypes.GeneratedOperations{}, volumeToDetach.GenerateErrorDetailed("DetachVolume.TranslateSpec failed", err)
|
||||||
}
|
}
|
||||||
@ -511,7 +533,7 @@ func (og *operationGenerator) GenerateDetachVolumeFunc(
|
|||||||
// TODO(dyzz): This case can't distinguish between PV and In-line which is necessary because
|
// TODO(dyzz): This case can't distinguish between PV and In-line which is necessary because
|
||||||
// if it was PV it may have been migrated, but the same plugin with in-line may not have been.
|
// if it was PV it may have been migrated, but the same plugin with in-line may not have been.
|
||||||
// Suggestions welcome...
|
// Suggestions welcome...
|
||||||
if csilib.IsMigratableIntreePluginByName(pluginName) && utilfeature.DefaultFeatureGate.Enabled(features.CSIMigration) {
|
if og.translator.IsMigratableIntreePluginByName(pluginName) && utilfeature.DefaultFeatureGate.Enabled(features.CSIMigration) {
|
||||||
// The volume represented by this spec is CSI and thus should be migrated
|
// The volume represented by this spec is CSI and thus should be migrated
|
||||||
attachableVolumePlugin, err = og.volumePluginMgr.FindAttachablePluginByName(csi.CSIPluginName)
|
attachableVolumePlugin, err = og.volumePluginMgr.FindAttachablePluginByName(csi.CSIPluginName)
|
||||||
if err != nil || attachableVolumePlugin == nil {
|
if err != nil || attachableVolumePlugin == nil {
|
||||||
@ -582,8 +604,8 @@ func (og *operationGenerator) GenerateMountVolumeFunc(
|
|||||||
volumePluginName := unknownVolumePlugin
|
volumePluginName := unknownVolumePlugin
|
||||||
// Need to translate the spec here if the plugin is migrated so that the metrics
|
// Need to translate the spec here if the plugin is migrated so that the metrics
|
||||||
// emitted show the correct (migrated) plugin
|
// emitted show the correct (migrated) plugin
|
||||||
if useCSIPlugin(og.volumePluginMgr, volumeToMount.VolumeSpec) {
|
if useCSIPlugin(og.translator, og.volumePluginMgr, volumeToMount.VolumeSpec) {
|
||||||
csiSpec, err := translateSpec(volumeToMount.VolumeSpec)
|
csiSpec, err := translateSpec(og.translator, volumeToMount.VolumeSpec)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
volumeToMount.VolumeSpec = csiSpec
|
volumeToMount.VolumeSpec = csiSpec
|
||||||
}
|
}
|
||||||
@ -601,8 +623,8 @@ func (og *operationGenerator) GenerateMountVolumeFunc(
|
|||||||
mountVolumeFunc := func() (error, error) {
|
mountVolumeFunc := func() (error, error) {
|
||||||
|
|
||||||
// Get mounter plugin
|
// Get mounter plugin
|
||||||
if useCSIPlugin(og.volumePluginMgr, volumeToMount.VolumeSpec) {
|
if useCSIPlugin(og.translator, og.volumePluginMgr, volumeToMount.VolumeSpec) {
|
||||||
csiSpec, err := translateSpec(volumeToMount.VolumeSpec)
|
csiSpec, err := translateSpec(og.translator, volumeToMount.VolumeSpec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return volumeToMount.GenerateError("MountVolume.TranslateSpec failed", err)
|
return volumeToMount.GenerateError("MountVolume.TranslateSpec failed", err)
|
||||||
}
|
}
|
||||||
@ -795,7 +817,7 @@ func (og *operationGenerator) GenerateUnmountVolumeFunc(
|
|||||||
podsDir string) (volumetypes.GeneratedOperations, error) {
|
podsDir string) (volumetypes.GeneratedOperations, error) {
|
||||||
|
|
||||||
var pluginName string
|
var pluginName string
|
||||||
if volumeToUnmount.VolumeSpec != nil && useCSIPlugin(og.volumePluginMgr, volumeToUnmount.VolumeSpec) {
|
if volumeToUnmount.VolumeSpec != nil && useCSIPlugin(og.translator, og.volumePluginMgr, volumeToUnmount.VolumeSpec) {
|
||||||
pluginName = csi.CSIPluginName
|
pluginName = csi.CSIPluginName
|
||||||
} else {
|
} else {
|
||||||
pluginName = volumeToUnmount.PluginName
|
pluginName = volumeToUnmount.PluginName
|
||||||
@ -863,9 +885,9 @@ func (og *operationGenerator) GenerateUnmountDeviceFunc(
|
|||||||
hostutil hostutil.HostUtils) (volumetypes.GeneratedOperations, error) {
|
hostutil hostutil.HostUtils) (volumetypes.GeneratedOperations, error) {
|
||||||
|
|
||||||
var pluginName string
|
var pluginName string
|
||||||
if useCSIPlugin(og.volumePluginMgr, deviceToDetach.VolumeSpec) {
|
if useCSIPlugin(og.translator, og.volumePluginMgr, deviceToDetach.VolumeSpec) {
|
||||||
pluginName = csi.CSIPluginName
|
pluginName = csi.CSIPluginName
|
||||||
csiSpec, err := translateSpec(deviceToDetach.VolumeSpec)
|
csiSpec, err := translateSpec(og.translator, deviceToDetach.VolumeSpec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return volumetypes.GeneratedOperations{}, deviceToDetach.GenerateErrorDetailed("UnmountDevice.TranslateSpec failed", err)
|
return volumetypes.GeneratedOperations{}, deviceToDetach.GenerateErrorDetailed("UnmountDevice.TranslateSpec failed", err)
|
||||||
}
|
}
|
||||||
@ -965,8 +987,8 @@ func (og *operationGenerator) GenerateMapVolumeFunc(
|
|||||||
|
|
||||||
originalSpec := volumeToMount.VolumeSpec
|
originalSpec := volumeToMount.VolumeSpec
|
||||||
// Translate to CSI spec if migration enabled
|
// Translate to CSI spec if migration enabled
|
||||||
if useCSIPlugin(og.volumePluginMgr, originalSpec) {
|
if useCSIPlugin(og.translator, og.volumePluginMgr, originalSpec) {
|
||||||
csiSpec, err := translateSpec(originalSpec)
|
csiSpec, err := translateSpec(og.translator, originalSpec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return volumetypes.GeneratedOperations{}, volumeToMount.GenerateErrorDetailed("MapVolume.TranslateSpec failed", err)
|
return volumetypes.GeneratedOperations{}, volumeToMount.GenerateErrorDetailed("MapVolume.TranslateSpec failed", err)
|
||||||
}
|
}
|
||||||
@ -1153,8 +1175,8 @@ func (og *operationGenerator) GenerateUnmapVolumeFunc(
|
|||||||
var err error
|
var err error
|
||||||
// Translate to CSI spec if migration enabled
|
// Translate to CSI spec if migration enabled
|
||||||
// And get block volume unmapper plugin
|
// And get block volume unmapper plugin
|
||||||
if volumeToUnmount.VolumeSpec != nil && useCSIPlugin(og.volumePluginMgr, volumeToUnmount.VolumeSpec) {
|
if volumeToUnmount.VolumeSpec != nil && useCSIPlugin(og.translator, og.volumePluginMgr, volumeToUnmount.VolumeSpec) {
|
||||||
csiSpec, err := translateSpec(volumeToUnmount.VolumeSpec)
|
csiSpec, err := translateSpec(og.translator, volumeToUnmount.VolumeSpec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return volumetypes.GeneratedOperations{}, volumeToUnmount.GenerateErrorDetailed("UnmapVolume.TranslateSpec failed", err)
|
return volumetypes.GeneratedOperations{}, volumeToUnmount.GenerateErrorDetailed("UnmapVolume.TranslateSpec failed", err)
|
||||||
}
|
}
|
||||||
@ -1249,8 +1271,8 @@ func (og *operationGenerator) GenerateUnmapDeviceFunc(
|
|||||||
var blockVolumePlugin volume.BlockVolumePlugin
|
var blockVolumePlugin volume.BlockVolumePlugin
|
||||||
var err error
|
var err error
|
||||||
// Translate to CSI spec if migration enabled
|
// Translate to CSI spec if migration enabled
|
||||||
if useCSIPlugin(og.volumePluginMgr, deviceToDetach.VolumeSpec) {
|
if useCSIPlugin(og.translator, og.volumePluginMgr, deviceToDetach.VolumeSpec) {
|
||||||
csiSpec, err := translateSpec(deviceToDetach.VolumeSpec)
|
csiSpec, err := translateSpec(og.translator, deviceToDetach.VolumeSpec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return volumetypes.GeneratedOperations{}, deviceToDetach.GenerateErrorDetailed("UnmapDevice.TranslateSpec failed", err)
|
return volumetypes.GeneratedOperations{}, deviceToDetach.GenerateErrorDetailed("UnmapDevice.TranslateSpec failed", err)
|
||||||
}
|
}
|
||||||
@ -1564,8 +1586,8 @@ func (og *operationGenerator) GenerateExpandInUseVolumeFunc(
|
|||||||
fsResizeFunc := func() (error, error) {
|
fsResizeFunc := func() (error, error) {
|
||||||
// Need to translate the spec here if the plugin is migrated so that the metrics
|
// Need to translate the spec here if the plugin is migrated so that the metrics
|
||||||
// emitted show the correct (migrated) plugin
|
// emitted show the correct (migrated) plugin
|
||||||
if useCSIPlugin(og.volumePluginMgr, volumeToMount.VolumeSpec) {
|
if useCSIPlugin(og.translator, og.volumePluginMgr, volumeToMount.VolumeSpec) {
|
||||||
csiSpec, err := translateSpec(volumeToMount.VolumeSpec)
|
csiSpec, err := translateSpec(og.translator, volumeToMount.VolumeSpec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return volumeToMount.GenerateError("NodeExpandVolume.translateSpec failed", err)
|
return volumeToMount.GenerateError("NodeExpandVolume.translateSpec failed", err)
|
||||||
}
|
}
|
||||||
@ -1636,8 +1658,8 @@ func (og *operationGenerator) GenerateExpandInUseVolumeFunc(
|
|||||||
|
|
||||||
// Need to translate the spec here if the plugin is migrated so that the metrics
|
// Need to translate the spec here if the plugin is migrated so that the metrics
|
||||||
// emitted show the correct (migrated) plugin
|
// emitted show the correct (migrated) plugin
|
||||||
if useCSIPlugin(og.volumePluginMgr, volumeToMount.VolumeSpec) {
|
if useCSIPlugin(og.translator, og.volumePluginMgr, volumeToMount.VolumeSpec) {
|
||||||
csiSpec, err := translateSpec(volumeToMount.VolumeSpec)
|
csiSpec, err := translateSpec(og.translator, volumeToMount.VolumeSpec)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
volumeToMount.VolumeSpec = csiSpec
|
volumeToMount.VolumeSpec = csiSpec
|
||||||
}
|
}
|
||||||
@ -1796,7 +1818,7 @@ func isDeviceOpened(deviceToDetach AttachedVolume, hostUtil hostutil.HostUtils)
|
|||||||
return deviceOpened, nil
|
return deviceOpened, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func useCSIPlugin(vpm *volume.VolumePluginMgr, spec *volume.Spec) bool {
|
func useCSIPlugin(tr InTreeToCSITranslator, vpm *volume.VolumePluginMgr, spec *volume.Spec) bool {
|
||||||
// TODO(#75146) Check whether the driver is installed as well so that
|
// TODO(#75146) Check whether the driver is installed as well so that
|
||||||
// we can throw a better error when the driver is not installed.
|
// we can throw a better error when the driver is not installed.
|
||||||
// The error should be of the approximate form:
|
// The error should be of the approximate form:
|
||||||
@ -1804,7 +1826,7 @@ func useCSIPlugin(vpm *volume.VolumePluginMgr, spec *volume.Spec) bool {
|
|||||||
if !utilfeature.DefaultFeatureGate.Enabled(features.CSIMigration) {
|
if !utilfeature.DefaultFeatureGate.Enabled(features.CSIMigration) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if csilib.IsPVMigratable(spec.PersistentVolume) || csilib.IsInlineMigratable(spec.Volume) {
|
if tr.IsPVMigratable(spec.PersistentVolume) || tr.IsInlineMigratable(spec.Volume) {
|
||||||
migratable, err := vpm.IsPluginMigratableBySpec(spec)
|
migratable, err := vpm.IsPluginMigratableBySpec(spec)
|
||||||
if err == nil && migratable {
|
if err == nil && migratable {
|
||||||
return true
|
return true
|
||||||
@ -1813,9 +1835,7 @@ func useCSIPlugin(vpm *volume.VolumePluginMgr, spec *volume.Spec) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func nodeUsingCSIPlugin(og OperationGenerator, spec *volume.Spec, nodeName types.NodeName) (bool, error) {
|
func nodeUsingCSIPlugin(tr InTreeToCSITranslator, vpm *volume.VolumePluginMgr, spec *volume.Spec, nodeName types.NodeName) (bool, error) {
|
||||||
vpm := og.GetVolumePluginMgr()
|
|
||||||
|
|
||||||
migratable, err := vpm.IsPluginMigratableBySpec(spec)
|
migratable, err := vpm.IsPluginMigratableBySpec(spec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
@ -1869,7 +1889,7 @@ func nodeUsingCSIPlugin(og OperationGenerator, spec *volume.Spec, nodeName types
|
|||||||
mpaSet = sets.NewString(tok...)
|
mpaSet = sets.NewString(tok...)
|
||||||
}
|
}
|
||||||
|
|
||||||
pluginName, err := csilib.GetInTreePluginNameFromSpec(spec.PersistentVolume, spec.Volume)
|
pluginName, err := tr.GetInTreePluginNameFromSpec(spec.PersistentVolume, spec.Volume)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
@ -1883,7 +1903,7 @@ func nodeUsingCSIPlugin(og OperationGenerator, spec *volume.Spec, nodeName types
|
|||||||
|
|
||||||
if isMigratedOnNode {
|
if isMigratedOnNode {
|
||||||
installed := false
|
installed := false
|
||||||
driverName, err := csilib.GetCSINameFromInTreeName(pluginName)
|
driverName, err := tr.GetCSINameFromInTreeName(pluginName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return isMigratedOnNode, err
|
return isMigratedOnNode, err
|
||||||
}
|
}
|
||||||
@ -1902,19 +1922,19 @@ func nodeUsingCSIPlugin(og OperationGenerator, spec *volume.Spec, nodeName types
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func translateSpec(spec *volume.Spec) (*volume.Spec, error) {
|
func translateSpec(tr InTreeToCSITranslator, spec *volume.Spec) (*volume.Spec, error) {
|
||||||
var csiPV *v1.PersistentVolume
|
var csiPV *v1.PersistentVolume
|
||||||
var err error
|
var err error
|
||||||
inlineVolume := false
|
inlineVolume := false
|
||||||
if spec.PersistentVolume != nil {
|
if spec.PersistentVolume != nil {
|
||||||
// TranslateInTreePVToCSI will create a new PV
|
// TranslateInTreePVToCSI will create a new PV
|
||||||
csiPV, err = csilib.TranslateInTreePVToCSI(spec.PersistentVolume)
|
csiPV, err = tr.TranslateInTreePVToCSI(spec.PersistentVolume)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to translate in tree pv to CSI: %v", err)
|
return nil, fmt.Errorf("failed to translate in tree pv to CSI: %v", err)
|
||||||
}
|
}
|
||||||
} else if spec.Volume != nil {
|
} else if spec.Volume != nil {
|
||||||
// TranslateInTreeInlineVolumeToCSI will create a new PV
|
// TranslateInTreeInlineVolumeToCSI will create a new PV
|
||||||
csiPV, err = csilib.TranslateInTreeInlineVolumeToCSI(spec.Volume)
|
csiPV, err = tr.TranslateInTreeInlineVolumeToCSI(spec.Volume)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to translate in tree inline volume to CSI: %v", err)
|
return nil, fmt.Errorf("failed to translate in tree inline volume to CSI: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -125,7 +125,7 @@ func TestOperationGenerator_GenerateUnmapVolumeFunc_PluginName(t *testing.T) {
|
|||||||
// csi plugin looks a file that contains some information about the volume,
|
// csi plugin looks a file that contains some information about the volume,
|
||||||
// and GenerateUnmapVolumeFuncfails if csi plugin can't find that file.
|
// and GenerateUnmapVolumeFuncfails if csi plugin can't find that file.
|
||||||
// So the reason for calling plugin.NewBlockVolumeMapper for csi enabled case is creating that file.
|
// So the reason for calling plugin.NewBlockVolumeMapper for csi enabled case is creating that file.
|
||||||
csiSpec, err := translateSpec(volumeToUnmount.VolumeSpec)
|
csiSpec, err := translateSpec(operationGenerator.GetCSITranslator(), volumeToUnmount.VolumeSpec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Can't translate volume to CSI")
|
t.Fatalf("Can't translate volume to CSI")
|
||||||
}
|
}
|
||||||
|
@ -35,9 +35,20 @@ var (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// CSITranslator translates in-tree storage API objects to their equivalent CSI
|
||||||
|
// API objects. It also provides many helper functions to determine whether
|
||||||
|
// translation logic exists and the mappings between "in-tree plugin <-> csi driver"
|
||||||
|
type CSITranslator struct{}
|
||||||
|
|
||||||
|
// New creates a new CSITranslator which does real translation
|
||||||
|
// for "in-tree plugins <-> csi drivers"
|
||||||
|
func New() CSITranslator {
|
||||||
|
return CSITranslator{}
|
||||||
|
}
|
||||||
|
|
||||||
// TranslateInTreeStorageClassToCSI takes in-tree Storage Class
|
// TranslateInTreeStorageClassToCSI takes in-tree Storage Class
|
||||||
// and translates it to a set of parameters consumable by CSI plugin
|
// and translates it to a set of parameters consumable by CSI plugin
|
||||||
func TranslateInTreeStorageClassToCSI(inTreePluginName string, sc *storage.StorageClass) (*storage.StorageClass, error) {
|
func (ctl CSITranslator) TranslateInTreeStorageClassToCSI(inTreePluginName string, sc *storage.StorageClass) (*storage.StorageClass, error) {
|
||||||
newSC := sc.DeepCopy()
|
newSC := sc.DeepCopy()
|
||||||
for _, curPlugin := range inTreePlugins {
|
for _, curPlugin := range inTreePlugins {
|
||||||
if inTreePluginName == curPlugin.GetInTreePluginName() {
|
if inTreePluginName == curPlugin.GetInTreePluginName() {
|
||||||
@ -50,7 +61,7 @@ func TranslateInTreeStorageClassToCSI(inTreePluginName string, sc *storage.Stora
|
|||||||
// TranslateInTreeInlineVolumeToCSI takes a inline volume and will translate
|
// TranslateInTreeInlineVolumeToCSI takes a inline volume and will translate
|
||||||
// the in-tree volume source to a CSIPersistentVolumeSource (wrapped in a PV)
|
// the in-tree volume source to a CSIPersistentVolumeSource (wrapped in a PV)
|
||||||
// if the translation logic has been implemented.
|
// if the translation logic has been implemented.
|
||||||
func TranslateInTreeInlineVolumeToCSI(volume *v1.Volume) (*v1.PersistentVolume, error) {
|
func (ctl CSITranslator) TranslateInTreeInlineVolumeToCSI(volume *v1.Volume) (*v1.PersistentVolume, error) {
|
||||||
if volume == nil {
|
if volume == nil {
|
||||||
return nil, fmt.Errorf("persistent volume was nil")
|
return nil, fmt.Errorf("persistent volume was nil")
|
||||||
}
|
}
|
||||||
@ -66,7 +77,7 @@ func TranslateInTreeInlineVolumeToCSI(volume *v1.Volume) (*v1.PersistentVolume,
|
|||||||
// the in-tree source to a CSI Source if the translation logic
|
// the in-tree source to a CSI Source if the translation logic
|
||||||
// has been implemented. The input persistent volume will not
|
// has been implemented. The input persistent volume will not
|
||||||
// be modified
|
// be modified
|
||||||
func TranslateInTreePVToCSI(pv *v1.PersistentVolume) (*v1.PersistentVolume, error) {
|
func (ctl CSITranslator) TranslateInTreePVToCSI(pv *v1.PersistentVolume) (*v1.PersistentVolume, error) {
|
||||||
if pv == nil {
|
if pv == nil {
|
||||||
return nil, errors.New("persistent volume was nil")
|
return nil, errors.New("persistent volume was nil")
|
||||||
}
|
}
|
||||||
@ -82,7 +93,7 @@ func TranslateInTreePVToCSI(pv *v1.PersistentVolume) (*v1.PersistentVolume, erro
|
|||||||
// TranslateCSIPVToInTree takes a PV with a CSI PersistentVolume Source and will translate
|
// TranslateCSIPVToInTree takes a PV with a CSI PersistentVolume Source and will translate
|
||||||
// it to a in-tree Persistent Volume Source for the specific in-tree volume specified
|
// it to a in-tree Persistent Volume Source for the specific in-tree volume specified
|
||||||
// by the `Driver` field in the CSI Source. The input PV object will not be modified.
|
// by the `Driver` field in the CSI Source. The input PV object will not be modified.
|
||||||
func TranslateCSIPVToInTree(pv *v1.PersistentVolume) (*v1.PersistentVolume, error) {
|
func (ctl CSITranslator) TranslateCSIPVToInTree(pv *v1.PersistentVolume) (*v1.PersistentVolume, error) {
|
||||||
if pv == nil || pv.Spec.CSI == nil {
|
if pv == nil || pv.Spec.CSI == nil {
|
||||||
return nil, errors.New("CSI persistent volume was nil")
|
return nil, errors.New("CSI persistent volume was nil")
|
||||||
}
|
}
|
||||||
@ -97,7 +108,7 @@ func TranslateCSIPVToInTree(pv *v1.PersistentVolume) (*v1.PersistentVolume, erro
|
|||||||
|
|
||||||
// IsMigratableIntreePluginByName tests whether there is migration logic for the in-tree plugin
|
// IsMigratableIntreePluginByName tests whether there is migration logic for the in-tree plugin
|
||||||
// whose name matches the given name
|
// whose name matches the given name
|
||||||
func IsMigratableIntreePluginByName(inTreePluginName string) bool {
|
func (ctl CSITranslator) IsMigratableIntreePluginByName(inTreePluginName string) bool {
|
||||||
for _, curPlugin := range inTreePlugins {
|
for _, curPlugin := range inTreePlugins {
|
||||||
if curPlugin.GetInTreePluginName() == inTreePluginName {
|
if curPlugin.GetInTreePluginName() == inTreePluginName {
|
||||||
return true
|
return true
|
||||||
@ -108,7 +119,7 @@ func IsMigratableIntreePluginByName(inTreePluginName string) bool {
|
|||||||
|
|
||||||
// IsMigratedCSIDriverByName tests whether there exists an in-tree plugin with logic
|
// IsMigratedCSIDriverByName tests whether there exists an in-tree plugin with logic
|
||||||
// to migrate to the CSI driver with given name
|
// to migrate to the CSI driver with given name
|
||||||
func IsMigratedCSIDriverByName(csiPluginName string) bool {
|
func (ctl CSITranslator) IsMigratedCSIDriverByName(csiPluginName string) bool {
|
||||||
if _, ok := inTreePlugins[csiPluginName]; ok {
|
if _, ok := inTreePlugins[csiPluginName]; ok {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -116,7 +127,7 @@ func IsMigratedCSIDriverByName(csiPluginName string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetInTreePluginNameFromSpec returns the plugin name
|
// GetInTreePluginNameFromSpec returns the plugin name
|
||||||
func GetInTreePluginNameFromSpec(pv *v1.PersistentVolume, vol *v1.Volume) (string, error) {
|
func (ctl CSITranslator) GetInTreePluginNameFromSpec(pv *v1.PersistentVolume, vol *v1.Volume) (string, error) {
|
||||||
if pv != nil {
|
if pv != nil {
|
||||||
for _, curPlugin := range inTreePlugins {
|
for _, curPlugin := range inTreePlugins {
|
||||||
if curPlugin.CanSupport(pv) {
|
if curPlugin.CanSupport(pv) {
|
||||||
@ -138,7 +149,7 @@ func GetInTreePluginNameFromSpec(pv *v1.PersistentVolume, vol *v1.Volume) (strin
|
|||||||
|
|
||||||
// GetCSINameFromInTreeName returns the name of a CSI driver that supersedes the
|
// GetCSINameFromInTreeName returns the name of a CSI driver that supersedes the
|
||||||
// in-tree plugin with the given name
|
// in-tree plugin with the given name
|
||||||
func GetCSINameFromInTreeName(pluginName string) (string, error) {
|
func (ctl CSITranslator) GetCSINameFromInTreeName(pluginName string) (string, error) {
|
||||||
for csiDriverName, curPlugin := range inTreePlugins {
|
for csiDriverName, curPlugin := range inTreePlugins {
|
||||||
if curPlugin.GetInTreePluginName() == pluginName {
|
if curPlugin.GetInTreePluginName() == pluginName {
|
||||||
return csiDriverName, nil
|
return csiDriverName, nil
|
||||||
@ -149,7 +160,7 @@ func GetCSINameFromInTreeName(pluginName string) (string, error) {
|
|||||||
|
|
||||||
// GetInTreeNameFromCSIName returns the name of the in-tree plugin superseded by
|
// GetInTreeNameFromCSIName returns the name of the in-tree plugin superseded by
|
||||||
// a CSI driver with the given name
|
// a CSI driver with the given name
|
||||||
func GetInTreeNameFromCSIName(pluginName string) (string, error) {
|
func (ctl CSITranslator) GetInTreeNameFromCSIName(pluginName string) (string, error) {
|
||||||
if plugin, ok := inTreePlugins[pluginName]; ok {
|
if plugin, ok := inTreePlugins[pluginName]; ok {
|
||||||
return plugin.GetInTreePluginName(), nil
|
return plugin.GetInTreePluginName(), nil
|
||||||
}
|
}
|
||||||
@ -157,7 +168,7 @@ func GetInTreeNameFromCSIName(pluginName string) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IsPVMigratable tests whether there is migration logic for the given Persistent Volume
|
// IsPVMigratable tests whether there is migration logic for the given Persistent Volume
|
||||||
func IsPVMigratable(pv *v1.PersistentVolume) bool {
|
func (ctl CSITranslator) IsPVMigratable(pv *v1.PersistentVolume) bool {
|
||||||
for _, curPlugin := range inTreePlugins {
|
for _, curPlugin := range inTreePlugins {
|
||||||
if curPlugin.CanSupport(pv) {
|
if curPlugin.CanSupport(pv) {
|
||||||
return true
|
return true
|
||||||
@ -167,7 +178,7 @@ func IsPVMigratable(pv *v1.PersistentVolume) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IsInlineMigratable tests whether there is Migration logic for the given Inline Volume
|
// IsInlineMigratable tests whether there is Migration logic for the given Inline Volume
|
||||||
func IsInlineMigratable(vol *v1.Volume) bool {
|
func (ctl CSITranslator) IsInlineMigratable(vol *v1.Volume) bool {
|
||||||
for _, curPlugin := range inTreePlugins {
|
for _, curPlugin := range inTreePlugins {
|
||||||
if curPlugin.CanSupportInline(vol) {
|
if curPlugin.CanSupportInline(vol) {
|
||||||
return true
|
return true
|
||||||
|
@ -61,12 +61,13 @@ func TestTranslationStability(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, test := range testCases {
|
for _, test := range testCases {
|
||||||
|
ctl := New()
|
||||||
t.Logf("Testing %v", test.name)
|
t.Logf("Testing %v", test.name)
|
||||||
csiSource, err := TranslateInTreePVToCSI(test.pv)
|
csiSource, err := ctl.TranslateInTreePVToCSI(test.pv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Error when translating to CSI: %v", err)
|
t.Errorf("Error when translating to CSI: %v", err)
|
||||||
}
|
}
|
||||||
newPV, err := TranslateCSIPVToInTree(csiSource)
|
newPV, err := ctl.TranslateCSIPVToInTree(csiSource)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Error when translating CSI Source to in tree volume: %v", err)
|
t.Errorf("Error when translating CSI Source to in tree volume: %v", err)
|
||||||
}
|
}
|
||||||
@ -95,18 +96,19 @@ func TestPluginNameMappings(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, test := range testCases {
|
for _, test := range testCases {
|
||||||
t.Logf("Testing %v", test.name)
|
t.Logf("Testing %v", test.name)
|
||||||
csiPluginName, err := GetCSINameFromInTreeName(test.inTreePluginName)
|
ctl := New()
|
||||||
|
csiPluginName, err := ctl.GetCSINameFromInTreeName(test.inTreePluginName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Error when mapping In-tree plugin name to CSI plugin name %s", err)
|
t.Errorf("Error when mapping In-tree plugin name to CSI plugin name %s", err)
|
||||||
}
|
}
|
||||||
if !IsMigratedCSIDriverByName(csiPluginName) {
|
if !ctl.IsMigratedCSIDriverByName(csiPluginName) {
|
||||||
t.Errorf("%s expected to supersede an In-tree plugin", csiPluginName)
|
t.Errorf("%s expected to supersede an In-tree plugin", csiPluginName)
|
||||||
}
|
}
|
||||||
inTreePluginName, err := GetInTreeNameFromCSIName(csiPluginName)
|
inTreePluginName, err := ctl.GetInTreeNameFromCSIName(csiPluginName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Error when mapping CSI plugin name to In-tree plugin name %s", err)
|
t.Errorf("Error when mapping CSI plugin name to In-tree plugin name %s", err)
|
||||||
}
|
}
|
||||||
if !IsMigratableIntreePluginByName(inTreePluginName) {
|
if !ctl.IsMigratableIntreePluginByName(inTreePluginName) {
|
||||||
t.Errorf("%s expected to be migratable to a CSI name", inTreePluginName)
|
t.Errorf("%s expected to be migratable to a CSI name", inTreePluginName)
|
||||||
}
|
}
|
||||||
if inTreePluginName != test.inTreePluginName || csiPluginName != test.csiPluginName {
|
if inTreePluginName != test.inTreePluginName || csiPluginName != test.csiPluginName {
|
||||||
|
@ -34,7 +34,7 @@ import (
|
|||||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
csilib "k8s.io/csi-translation-lib"
|
csitrans "k8s.io/csi-translation-lib"
|
||||||
"k8s.io/kubernetes/test/e2e/framework"
|
"k8s.io/kubernetes/test/e2e/framework"
|
||||||
"k8s.io/kubernetes/test/e2e/framework/metrics"
|
"k8s.io/kubernetes/test/e2e/framework/metrics"
|
||||||
"k8s.io/kubernetes/test/e2e/framework/podlogs"
|
"k8s.io/kubernetes/test/e2e/framework/podlogs"
|
||||||
@ -558,7 +558,8 @@ func addOpCounts(o1 opCounts, o2 opCounts) opCounts {
|
|||||||
func getMigrationVolumeOpCounts(cs clientset.Interface, pluginName string) (opCounts, opCounts) {
|
func getMigrationVolumeOpCounts(cs clientset.Interface, pluginName string) (opCounts, opCounts) {
|
||||||
if len(pluginName) > 0 {
|
if len(pluginName) > 0 {
|
||||||
var migratedOps opCounts
|
var migratedOps opCounts
|
||||||
csiName, err := csilib.GetCSINameFromInTreeName(pluginName)
|
l := csitrans.New()
|
||||||
|
csiName, err := l.GetCSINameFromInTreeName(pluginName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
framework.Logf("Could not find CSI Name for in-tree plugin %v", pluginName)
|
framework.Logf("Could not find CSI Name for in-tree plugin %v", pluginName)
|
||||||
migratedOps = opCounts{}
|
migratedOps = opCounts{}
|
||||||
|
Loading…
Reference in New Issue
Block a user