mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	Merge pull request #90911 from divyenpatel/vsphere-csi-migration
Support for vSphere in-tree volumes migration to vSphere CSI driver
This commit is contained in:
		@@ -64,6 +64,7 @@ func appendAttachableLegacyProviderVolumes(allPlugins []volume.VolumePlugin, fea
 | 
				
			|||||||
	pluginMigrationStatus[plugins.GCEPDInTreePluginName] = pluginInfo{pluginMigrationFeature: features.CSIMigrationGCE, pluginMigrationCompleteFeature: features.CSIMigrationGCEComplete, pluginProbeFunction: gcepd.ProbeVolumePlugins}
 | 
						pluginMigrationStatus[plugins.GCEPDInTreePluginName] = pluginInfo{pluginMigrationFeature: features.CSIMigrationGCE, pluginMigrationCompleteFeature: features.CSIMigrationGCEComplete, pluginProbeFunction: gcepd.ProbeVolumePlugins}
 | 
				
			||||||
	pluginMigrationStatus[plugins.CinderInTreePluginName] = pluginInfo{pluginMigrationFeature: features.CSIMigrationOpenStack, pluginMigrationCompleteFeature: features.CSIMigrationOpenStackComplete, pluginProbeFunction: cinder.ProbeVolumePlugins}
 | 
						pluginMigrationStatus[plugins.CinderInTreePluginName] = pluginInfo{pluginMigrationFeature: features.CSIMigrationOpenStack, pluginMigrationCompleteFeature: features.CSIMigrationOpenStackComplete, pluginProbeFunction: cinder.ProbeVolumePlugins}
 | 
				
			||||||
	pluginMigrationStatus[plugins.AzureDiskInTreePluginName] = pluginInfo{pluginMigrationFeature: features.CSIMigrationAzureDisk, pluginMigrationCompleteFeature: features.CSIMigrationAzureDiskComplete, pluginProbeFunction: azure_dd.ProbeVolumePlugins}
 | 
						pluginMigrationStatus[plugins.AzureDiskInTreePluginName] = pluginInfo{pluginMigrationFeature: features.CSIMigrationAzureDisk, pluginMigrationCompleteFeature: features.CSIMigrationAzureDiskComplete, pluginProbeFunction: azure_dd.ProbeVolumePlugins}
 | 
				
			||||||
 | 
						pluginMigrationStatus[plugins.VSphereInTreePluginName] = pluginInfo{pluginMigrationFeature: features.CSIMigrationvSphere, pluginMigrationCompleteFeature: features.CSIMigrationvSphereComplete, pluginProbeFunction: vsphere_volume.ProbeVolumePlugins}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var err error
 | 
						var err error
 | 
				
			||||||
	for pluginName, pluginInfo := range pluginMigrationStatus {
 | 
						for pluginName, pluginInfo := range pluginMigrationStatus {
 | 
				
			||||||
@@ -72,8 +73,6 @@ func appendAttachableLegacyProviderVolumes(allPlugins []volume.VolumePlugin, fea
 | 
				
			|||||||
			return allPlugins, err
 | 
								return allPlugins, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	allPlugins = append(allPlugins, vsphere_volume.ProbeVolumePlugins()...)
 | 
					 | 
				
			||||||
	return allPlugins, nil
 | 
						return allPlugins, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -88,6 +87,7 @@ func appendLegacyProviderVolumes(allPlugins []volume.VolumePlugin, featureGate f
 | 
				
			|||||||
	pluginMigrationStatus[plugins.CinderInTreePluginName] = pluginInfo{pluginMigrationFeature: features.CSIMigrationOpenStack, pluginMigrationCompleteFeature: features.CSIMigrationOpenStackComplete, pluginProbeFunction: cinder.ProbeVolumePlugins}
 | 
						pluginMigrationStatus[plugins.CinderInTreePluginName] = pluginInfo{pluginMigrationFeature: features.CSIMigrationOpenStack, pluginMigrationCompleteFeature: features.CSIMigrationOpenStackComplete, pluginProbeFunction: cinder.ProbeVolumePlugins}
 | 
				
			||||||
	pluginMigrationStatus[plugins.AzureDiskInTreePluginName] = pluginInfo{pluginMigrationFeature: features.CSIMigrationAzureDisk, pluginMigrationCompleteFeature: features.CSIMigrationAzureDiskComplete, pluginProbeFunction: azure_dd.ProbeVolumePlugins}
 | 
						pluginMigrationStatus[plugins.AzureDiskInTreePluginName] = pluginInfo{pluginMigrationFeature: features.CSIMigrationAzureDisk, pluginMigrationCompleteFeature: features.CSIMigrationAzureDiskComplete, pluginProbeFunction: azure_dd.ProbeVolumePlugins}
 | 
				
			||||||
	pluginMigrationStatus[plugins.AzureFileInTreePluginName] = pluginInfo{pluginMigrationFeature: features.CSIMigrationAzureFile, pluginMigrationCompleteFeature: features.CSIMigrationAzureFileComplete, pluginProbeFunction: azure_file.ProbeVolumePlugins}
 | 
						pluginMigrationStatus[plugins.AzureFileInTreePluginName] = pluginInfo{pluginMigrationFeature: features.CSIMigrationAzureFile, pluginMigrationCompleteFeature: features.CSIMigrationAzureFileComplete, pluginProbeFunction: azure_file.ProbeVolumePlugins}
 | 
				
			||||||
 | 
						pluginMigrationStatus[plugins.VSphereInTreePluginName] = pluginInfo{pluginMigrationFeature: features.CSIMigrationvSphere, pluginMigrationCompleteFeature: features.CSIMigrationvSphereComplete, pluginProbeFunction: vsphere_volume.ProbeVolumePlugins}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var err error
 | 
						var err error
 | 
				
			||||||
	for pluginName, pluginInfo := range pluginMigrationStatus {
 | 
						for pluginName, pluginInfo := range pluginMigrationStatus {
 | 
				
			||||||
@@ -96,7 +96,5 @@ func appendLegacyProviderVolumes(allPlugins []volume.VolumePlugin, featureGate f
 | 
				
			|||||||
			return allPlugins, err
 | 
								return allPlugins, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	allPlugins = append(allPlugins, vsphere_volume.ProbeVolumePlugins()...)
 | 
					 | 
				
			||||||
	return allPlugins, nil
 | 
						return allPlugins, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -65,6 +65,7 @@ func appendLegacyProviderVolumes(allPlugins []volume.VolumePlugin, featureGate f
 | 
				
			|||||||
	pluginMigrationStatus[plugins.CinderInTreePluginName] = pluginInfo{pluginMigrationFeature: features.CSIMigrationOpenStack, pluginMigrationCompleteFeature: features.CSIMigrationOpenStackComplete, pluginProbeFunction: cinder.ProbeVolumePlugins}
 | 
						pluginMigrationStatus[plugins.CinderInTreePluginName] = pluginInfo{pluginMigrationFeature: features.CSIMigrationOpenStack, pluginMigrationCompleteFeature: features.CSIMigrationOpenStackComplete, pluginProbeFunction: cinder.ProbeVolumePlugins}
 | 
				
			||||||
	pluginMigrationStatus[plugins.AzureDiskInTreePluginName] = pluginInfo{pluginMigrationFeature: features.CSIMigrationAzureDisk, pluginMigrationCompleteFeature: features.CSIMigrationAzureDiskComplete, pluginProbeFunction: azure_dd.ProbeVolumePlugins}
 | 
						pluginMigrationStatus[plugins.AzureDiskInTreePluginName] = pluginInfo{pluginMigrationFeature: features.CSIMigrationAzureDisk, pluginMigrationCompleteFeature: features.CSIMigrationAzureDiskComplete, pluginProbeFunction: azure_dd.ProbeVolumePlugins}
 | 
				
			||||||
	pluginMigrationStatus[plugins.AzureFileInTreePluginName] = pluginInfo{pluginMigrationFeature: features.CSIMigrationAzureFile, pluginMigrationCompleteFeature: features.CSIMigrationAzureFileComplete, pluginProbeFunction: azure_file.ProbeVolumePlugins}
 | 
						pluginMigrationStatus[plugins.AzureFileInTreePluginName] = pluginInfo{pluginMigrationFeature: features.CSIMigrationAzureFile, pluginMigrationCompleteFeature: features.CSIMigrationAzureFileComplete, pluginProbeFunction: azure_file.ProbeVolumePlugins}
 | 
				
			||||||
 | 
						pluginMigrationStatus[plugins.VSphereInTreePluginName] = pluginInfo{pluginMigrationFeature: features.CSIMigrationvSphere, pluginMigrationCompleteFeature: features.CSIMigrationvSphereComplete, pluginProbeFunction: vsphere_volume.ProbeVolumePlugins}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var err error
 | 
						var err error
 | 
				
			||||||
	for pluginName, pluginInfo := range pluginMigrationStatus {
 | 
						for pluginName, pluginInfo := range pluginMigrationStatus {
 | 
				
			||||||
@@ -73,7 +74,5 @@ func appendLegacyProviderVolumes(allPlugins []volume.VolumePlugin, featureGate f
 | 
				
			|||||||
			return allPlugins, err
 | 
								return allPlugins, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	allPlugins = append(allPlugins, vsphere_volume.ProbeVolumePlugins()...)
 | 
					 | 
				
			||||||
	return allPlugins, nil
 | 
						return allPlugins, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -410,6 +410,19 @@ const (
 | 
				
			|||||||
	// Expects Azure File CSI Driver to be installed and configured on all nodes.
 | 
						// Expects Azure File CSI Driver to be installed and configured on all nodes.
 | 
				
			||||||
	CSIMigrationAzureFileComplete featuregate.Feature = "CSIMigrationAzureFileComplete"
 | 
						CSIMigrationAzureFileComplete featuregate.Feature = "CSIMigrationAzureFileComplete"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// owner: @divyenpatel
 | 
				
			||||||
 | 
						// alpha: v1.19
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// Enables the vSphere in-tree driver to vSphere CSI Driver migration feature.
 | 
				
			||||||
 | 
						CSIMigrationvSphere featuregate.Feature = "CSIMigrationvSphere"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// owner: @divyenpatel
 | 
				
			||||||
 | 
						// alpha: v1.19
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// Disables the vSphere in-tree driver.
 | 
				
			||||||
 | 
						// Expects vSphere CSI Driver to be installed and configured on all nodes.
 | 
				
			||||||
 | 
						CSIMigrationvSphereComplete featuregate.Feature = "CSIMigrationvSphereComplete"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// owner: @gnufied
 | 
						// owner: @gnufied
 | 
				
			||||||
	// alpha: v1.18
 | 
						// alpha: v1.18
 | 
				
			||||||
	// Allows user to configure volume permission change policy for fsGroups when mounting
 | 
						// Allows user to configure volume permission change policy for fsGroups when mounting
 | 
				
			||||||
@@ -631,6 +644,8 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
 | 
				
			|||||||
	CSIMigrationAzureDiskComplete:  {Default: false, PreRelease: featuregate.Alpha},
 | 
						CSIMigrationAzureDiskComplete:  {Default: false, PreRelease: featuregate.Alpha},
 | 
				
			||||||
	CSIMigrationAzureFile:          {Default: false, PreRelease: featuregate.Alpha},
 | 
						CSIMigrationAzureFile:          {Default: false, PreRelease: featuregate.Alpha},
 | 
				
			||||||
	CSIMigrationAzureFileComplete:  {Default: false, PreRelease: featuregate.Alpha},
 | 
						CSIMigrationAzureFileComplete:  {Default: false, PreRelease: featuregate.Alpha},
 | 
				
			||||||
 | 
						CSIMigrationvSphere:            {Default: false, PreRelease: featuregate.Alpha},
 | 
				
			||||||
 | 
						CSIMigrationvSphereComplete:    {Default: false, PreRelease: featuregate.Alpha},
 | 
				
			||||||
	RunAsGroup:                     {Default: true, PreRelease: featuregate.Beta},
 | 
						RunAsGroup:                     {Default: true, PreRelease: featuregate.Beta},
 | 
				
			||||||
	CSIMigrationOpenStack:          {Default: false, PreRelease: featuregate.Beta}, // Off by default (requires OpenStack Cinder CSI driver)
 | 
						CSIMigrationOpenStack:          {Default: false, PreRelease: featuregate.Beta}, // Off by default (requires OpenStack Cinder CSI driver)
 | 
				
			||||||
	CSIMigrationOpenStackComplete:  {Default: false, PreRelease: featuregate.Alpha},
 | 
						CSIMigrationOpenStackComplete:  {Default: false, PreRelease: featuregate.Alpha},
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -219,6 +219,9 @@ func (p *csiPlugin) Init(host volume.VolumeHost) error {
 | 
				
			|||||||
		csitranslationplugins.AzureFileInTreePluginName: func() bool {
 | 
							csitranslationplugins.AzureFileInTreePluginName: func() bool {
 | 
				
			||||||
			return utilfeature.DefaultFeatureGate.Enabled(features.CSIMigration) && utilfeature.DefaultFeatureGate.Enabled(features.CSIMigrationAzureFile)
 | 
								return utilfeature.DefaultFeatureGate.Enabled(features.CSIMigration) && utilfeature.DefaultFeatureGate.Enabled(features.CSIMigrationAzureFile)
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
							csitranslationplugins.VSphereInTreePluginName: func() bool {
 | 
				
			||||||
 | 
								return utilfeature.DefaultFeatureGate.Enabled(features.CSIMigration) && utilfeature.DefaultFeatureGate.Enabled(features.CSIMigrationvSphere)
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Initializing the label management channels
 | 
						// Initializing the label management channels
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -68,6 +68,8 @@ func (pm PluginManager) IsMigrationCompleteForPlugin(pluginName string) bool {
 | 
				
			|||||||
		return utilfeature.DefaultFeatureGate.Enabled(features.CSIMigrationAzureDiskComplete)
 | 
							return utilfeature.DefaultFeatureGate.Enabled(features.CSIMigrationAzureDiskComplete)
 | 
				
			||||||
	case csilibplugins.CinderInTreePluginName:
 | 
						case csilibplugins.CinderInTreePluginName:
 | 
				
			||||||
		return utilfeature.DefaultFeatureGate.Enabled(features.CSIMigrationOpenStackComplete)
 | 
							return utilfeature.DefaultFeatureGate.Enabled(features.CSIMigrationOpenStackComplete)
 | 
				
			||||||
 | 
						case csilibplugins.VSphereInTreePluginName:
 | 
				
			||||||
 | 
							return utilfeature.DefaultFeatureGate.Enabled(features.CSIMigrationvSphereComplete)
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return false
 | 
							return false
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -92,6 +94,8 @@ func (pm PluginManager) IsMigrationEnabledForPlugin(pluginName string) bool {
 | 
				
			|||||||
		return utilfeature.DefaultFeatureGate.Enabled(features.CSIMigrationAzureDisk)
 | 
							return utilfeature.DefaultFeatureGate.Enabled(features.CSIMigrationAzureDisk)
 | 
				
			||||||
	case csilibplugins.CinderInTreePluginName:
 | 
						case csilibplugins.CinderInTreePluginName:
 | 
				
			||||||
		return utilfeature.DefaultFeatureGate.Enabled(features.CSIMigrationOpenStack)
 | 
							return utilfeature.DefaultFeatureGate.Enabled(features.CSIMigrationOpenStack)
 | 
				
			||||||
 | 
						case csilibplugins.VSphereInTreePluginName:
 | 
				
			||||||
 | 
							return utilfeature.DefaultFeatureGate.Enabled(features.CSIMigrationvSphere)
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return false
 | 
							return false
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,6 +20,7 @@ go_library(
 | 
				
			|||||||
    ],
 | 
					    ],
 | 
				
			||||||
    importpath = "k8s.io/kubernetes/pkg/volume/vsphere_volume",
 | 
					    importpath = "k8s.io/kubernetes/pkg/volume/vsphere_volume",
 | 
				
			||||||
    deps = [
 | 
					    deps = [
 | 
				
			||||||
 | 
					        "//pkg/features:go_default_library",
 | 
				
			||||||
        "//pkg/volume:go_default_library",
 | 
					        "//pkg/volume:go_default_library",
 | 
				
			||||||
        "//pkg/volume/util:go_default_library",
 | 
					        "//pkg/volume/util:go_default_library",
 | 
				
			||||||
        "//pkg/volume/util/volumepathhandler:go_default_library",
 | 
					        "//pkg/volume/util/volumepathhandler:go_default_library",
 | 
				
			||||||
@@ -27,6 +28,7 @@ go_library(
 | 
				
			|||||||
        "//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
 | 
					        "//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
 | 
				
			||||||
        "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
 | 
					        "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
 | 
				
			||||||
        "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
 | 
					        "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
 | 
				
			||||||
 | 
					        "//staging/src/k8s.io/apiserver/pkg/util/feature: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/cloud-provider/volume/helpers:go_default_library",
 | 
					        "//staging/src/k8s.io/cloud-provider/volume/helpers:go_default_library",
 | 
				
			||||||
        "//staging/src/k8s.io/legacy-cloud-providers/vsphere:go_default_library",
 | 
					        "//staging/src/k8s.io/legacy-cloud-providers/vsphere:go_default_library",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -25,6 +25,7 @@ import (
 | 
				
			|||||||
	"runtime"
 | 
						"runtime"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						utilfeature "k8s.io/apiserver/pkg/util/feature"
 | 
				
			||||||
	"k8s.io/klog/v2"
 | 
						"k8s.io/klog/v2"
 | 
				
			||||||
	"k8s.io/utils/mount"
 | 
						"k8s.io/utils/mount"
 | 
				
			||||||
	utilstrings "k8s.io/utils/strings"
 | 
						utilstrings "k8s.io/utils/strings"
 | 
				
			||||||
@@ -34,6 +35,8 @@ 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"
 | 
				
			||||||
	volumehelpers "k8s.io/cloud-provider/volume/helpers"
 | 
						volumehelpers "k8s.io/cloud-provider/volume/helpers"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/features"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/volume"
 | 
						"k8s.io/kubernetes/pkg/volume"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/volume/util"
 | 
						"k8s.io/kubernetes/pkg/volume/util"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@@ -70,6 +73,11 @@ func (plugin *vsphereVolumePlugin) GetPluginName() string {
 | 
				
			|||||||
	return vsphereVolumePluginName
 | 
						return vsphereVolumePluginName
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (plugin *vsphereVolumePlugin) IsMigratedToCSI() bool {
 | 
				
			||||||
 | 
						return utilfeature.DefaultFeatureGate.Enabled(features.CSIMigration) &&
 | 
				
			||||||
 | 
							utilfeature.DefaultFeatureGate.Enabled(features.CSIMigrationvSphere)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (plugin *vsphereVolumePlugin) GetVolumeName(spec *volume.Spec) (string, error) {
 | 
					func (plugin *vsphereVolumePlugin) GetVolumeName(spec *volume.Spec) (string, error) {
 | 
				
			||||||
	volumeSource, _, err := getVolumeSource(spec)
 | 
						volumeSource, _, err := getVolumeSource(spec)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,6 +9,7 @@ go_library(
 | 
				
			|||||||
        "gce_pd.go",
 | 
					        "gce_pd.go",
 | 
				
			||||||
        "in_tree_volume.go",
 | 
					        "in_tree_volume.go",
 | 
				
			||||||
        "openstack_cinder.go",
 | 
					        "openstack_cinder.go",
 | 
				
			||||||
 | 
					        "vsphere_volume.go",
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
    importmap = "k8s.io/kubernetes/vendor/k8s.io/csi-translation-lib/plugins",
 | 
					    importmap = "k8s.io/kubernetes/vendor/k8s.io/csi-translation-lib/plugins",
 | 
				
			||||||
    importpath = "k8s.io/csi-translation-lib/plugins",
 | 
					    importpath = "k8s.io/csi-translation-lib/plugins",
 | 
				
			||||||
@@ -45,6 +46,7 @@ go_test(
 | 
				
			|||||||
        "azure_file_test.go",
 | 
					        "azure_file_test.go",
 | 
				
			||||||
        "gce_pd_test.go",
 | 
					        "gce_pd_test.go",
 | 
				
			||||||
        "in_tree_volume_test.go",
 | 
					        "in_tree_volume_test.go",
 | 
				
			||||||
 | 
					        "vsphere_volume_test.go",
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
    embed = [":go_default_library"],
 | 
					    embed = [":go_default_library"],
 | 
				
			||||||
    deps = [
 | 
					    deps = [
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										208
									
								
								staging/src/k8s.io/csi-translation-lib/plugins/vsphere_volume.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										208
									
								
								staging/src/k8s.io/csi-translation-lib/plugins/vsphere_volume.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,208 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					Copyright 2020 The Kubernetes Authors.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					You may obtain a copy of the License at
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					limitations under the License.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package plugins
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						v1 "k8s.io/api/core/v1"
 | 
				
			||||||
 | 
						storage "k8s.io/api/storage/v1"
 | 
				
			||||||
 | 
						metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
				
			||||||
 | 
						"k8s.io/klog/v2"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						// VSphereDriverName is the name of the CSI driver for vSphere Volume
 | 
				
			||||||
 | 
						VSphereDriverName = "csi.vsphere.vmware.com"
 | 
				
			||||||
 | 
						// VSphereInTreePluginName is the name of the in-tree plugin for vSphere Volume
 | 
				
			||||||
 | 
						VSphereInTreePluginName = "kubernetes.io/vsphere-volume"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// paramStoragePolicyName used to supply SPBM Policy name for Volume provisioning
 | 
				
			||||||
 | 
						paramStoragePolicyName = "storagepolicyname"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// This param is used to tell Driver to return volumePath and not VolumeID
 | 
				
			||||||
 | 
						// in-tree vSphere plugin does not understand volume id, it uses volumePath
 | 
				
			||||||
 | 
						paramcsiMigration = "csimigration"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// This param is used to supply datastore name for Volume provisioning
 | 
				
			||||||
 | 
						paramDatastore = "datastore-migrationparam"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// This param supplies disk foramt (thin, thick, zeoredthick) for Volume provisioning
 | 
				
			||||||
 | 
						paramDiskFormat = "diskformat-migrationparam"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// vSAN Policy Parameters
 | 
				
			||||||
 | 
						paramHostFailuresToTolerate = "hostfailurestotolerate-migrationparam"
 | 
				
			||||||
 | 
						paramForceProvisioning      = "forceprovisioning-migrationparam"
 | 
				
			||||||
 | 
						paramCacheReservation       = "cachereservation-migrationparam"
 | 
				
			||||||
 | 
						paramDiskstripes            = "diskstripes-migrationparam"
 | 
				
			||||||
 | 
						paramObjectspacereservation = "objectspacereservation-migrationparam"
 | 
				
			||||||
 | 
						paramIopslimit              = "iopslimit-migrationparam"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// AttributeInitialVolumeFilepath represents the path of volume where volume is created
 | 
				
			||||||
 | 
						AttributeInitialVolumeFilepath = "initialvolumefilepath"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _ InTreePlugin = &vSphereCSITranslator{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// vSphereCSITranslator handles translation of PV spec from In-tree vSphere Volume to vSphere CSI
 | 
				
			||||||
 | 
					type vSphereCSITranslator struct{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewvSphereCSITranslator returns a new instance of vSphereCSITranslator
 | 
				
			||||||
 | 
					func NewvSphereCSITranslator() InTreePlugin {
 | 
				
			||||||
 | 
						return &vSphereCSITranslator{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TranslateInTreeStorageClassToCSI translates InTree vSphere storage class parameters to CSI storage class
 | 
				
			||||||
 | 
					func (t *vSphereCSITranslator) TranslateInTreeStorageClassToCSI(sc *storage.StorageClass) (*storage.StorageClass, error) {
 | 
				
			||||||
 | 
						if sc == nil {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("sc is nil")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var params = map[string]string{}
 | 
				
			||||||
 | 
						for k, v := range sc.Parameters {
 | 
				
			||||||
 | 
							switch strings.ToLower(k) {
 | 
				
			||||||
 | 
							case fsTypeKey:
 | 
				
			||||||
 | 
								params[csiFsTypeKey] = v
 | 
				
			||||||
 | 
							case paramStoragePolicyName:
 | 
				
			||||||
 | 
								params[paramStoragePolicyName] = v
 | 
				
			||||||
 | 
							case "datastore":
 | 
				
			||||||
 | 
								params[paramDatastore] = v
 | 
				
			||||||
 | 
							case "diskformat":
 | 
				
			||||||
 | 
								params[paramDiskFormat] = v
 | 
				
			||||||
 | 
							case "hostfailurestotolerate":
 | 
				
			||||||
 | 
								params[paramHostFailuresToTolerate] = v
 | 
				
			||||||
 | 
							case "forceprovisioning":
 | 
				
			||||||
 | 
								params[paramForceProvisioning] = v
 | 
				
			||||||
 | 
							case "cachereservation":
 | 
				
			||||||
 | 
								params[paramCacheReservation] = v
 | 
				
			||||||
 | 
							case "diskstripes":
 | 
				
			||||||
 | 
								params[paramDiskstripes] = v
 | 
				
			||||||
 | 
							case "objectspacereservation":
 | 
				
			||||||
 | 
								params[paramObjectspacereservation] = v
 | 
				
			||||||
 | 
							case "iopslimit":
 | 
				
			||||||
 | 
								params[paramIopslimit] = v
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								klog.V(2).Infof("StorageClass parameter [name:%q, value:%q] is not supported", k, v)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// This helps vSphere CSI driver to identify in-tree provisioner request vs CSI provisioner request
 | 
				
			||||||
 | 
						// When this is true, Driver returns initialvolumefilepath in the VolumeContext, which is
 | 
				
			||||||
 | 
						// used in TranslateCSIPVToInTree
 | 
				
			||||||
 | 
						params[paramcsiMigration] = "true"
 | 
				
			||||||
 | 
						// Note: sc.AllowedTopologies for Topology based volume provisioning will be supplied as it is.
 | 
				
			||||||
 | 
						sc.Parameters = params
 | 
				
			||||||
 | 
						return sc, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TranslateInTreeInlineVolumeToCSI takes a Volume with VsphereVolume set from in-tree
 | 
				
			||||||
 | 
					// and converts the VsphereVolume source to a CSIPersistentVolumeSource
 | 
				
			||||||
 | 
					func (t *vSphereCSITranslator) TranslateInTreeInlineVolumeToCSI(volume *v1.Volume) (*v1.PersistentVolume, error) {
 | 
				
			||||||
 | 
						if volume == nil || volume.VsphereVolume == nil {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("volume is nil or VsphereVolume not defined on volume")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						pv := &v1.PersistentVolume{
 | 
				
			||||||
 | 
							ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
 | 
								// Must be unique per disk as it is used as the unique part of the
 | 
				
			||||||
 | 
								// staging path
 | 
				
			||||||
 | 
								Name: fmt.Sprintf("%s-%s", VSphereDriverName, volume.VsphereVolume.VolumePath),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							Spec: v1.PersistentVolumeSpec{
 | 
				
			||||||
 | 
								PersistentVolumeSource: v1.PersistentVolumeSource{
 | 
				
			||||||
 | 
									CSI: &v1.CSIPersistentVolumeSource{
 | 
				
			||||||
 | 
										Driver:           VSphereDriverName,
 | 
				
			||||||
 | 
										VolumeHandle:     volume.VsphereVolume.VolumePath,
 | 
				
			||||||
 | 
										FSType:           volume.VsphereVolume.FSType,
 | 
				
			||||||
 | 
										VolumeAttributes: make(map[string]string),
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if volume.VsphereVolume.StoragePolicyName != "" {
 | 
				
			||||||
 | 
							pv.Spec.CSI.VolumeAttributes[paramStoragePolicyName] = pv.Spec.VsphereVolume.StoragePolicyName
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return pv, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TranslateInTreePVToCSI takes a PV with VsphereVolume set from in-tree
 | 
				
			||||||
 | 
					// and converts the VsphereVolume source to a CSIPersistentVolumeSource
 | 
				
			||||||
 | 
					func (t *vSphereCSITranslator) TranslateInTreePVToCSI(pv *v1.PersistentVolume) (*v1.PersistentVolume, error) {
 | 
				
			||||||
 | 
						if pv == nil || pv.Spec.VsphereVolume == nil {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("pv is nil or VsphereVolume not defined on pv")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						csiSource := &v1.CSIPersistentVolumeSource{
 | 
				
			||||||
 | 
							Driver:           VSphereDriverName,
 | 
				
			||||||
 | 
							VolumeHandle:     pv.Spec.VsphereVolume.VolumePath,
 | 
				
			||||||
 | 
							FSType:           pv.Spec.VsphereVolume.FSType,
 | 
				
			||||||
 | 
							VolumeAttributes: make(map[string]string),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if pv.Spec.VsphereVolume.StoragePolicyName != "" {
 | 
				
			||||||
 | 
							csiSource.VolumeAttributes[paramStoragePolicyName] = pv.Spec.VsphereVolume.StoragePolicyName
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						pv.Spec.VsphereVolume = nil
 | 
				
			||||||
 | 
						pv.Spec.CSI = csiSource
 | 
				
			||||||
 | 
						return pv, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TranslateCSIPVToInTree takes a PV with CSIPersistentVolumeSource set and
 | 
				
			||||||
 | 
					// translates the vSphere CSI source to a vSphereVolume source.
 | 
				
			||||||
 | 
					func (t *vSphereCSITranslator) TranslateCSIPVToInTree(pv *v1.PersistentVolume) (*v1.PersistentVolume, error) {
 | 
				
			||||||
 | 
						if pv == nil || pv.Spec.CSI == nil {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("pv is nil or CSI source not defined on pv")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						csiSource := pv.Spec.CSI
 | 
				
			||||||
 | 
						vsphereVirtualDiskVolumeSource := &v1.VsphereVirtualDiskVolumeSource{
 | 
				
			||||||
 | 
							FSType: csiSource.FSType,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						volumeFilePath, ok := csiSource.VolumeAttributes[AttributeInitialVolumeFilepath]
 | 
				
			||||||
 | 
						if ok {
 | 
				
			||||||
 | 
							vsphereVirtualDiskVolumeSource.VolumePath = volumeFilePath
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						pv.Spec.CSI = nil
 | 
				
			||||||
 | 
						pv.Spec.VsphereVolume = vsphereVirtualDiskVolumeSource
 | 
				
			||||||
 | 
						return pv, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CanSupport tests whether the plugin supports a given persistent volume
 | 
				
			||||||
 | 
					// specification from the API.
 | 
				
			||||||
 | 
					func (t *vSphereCSITranslator) CanSupport(pv *v1.PersistentVolume) bool {
 | 
				
			||||||
 | 
						return pv != nil && pv.Spec.VsphereVolume != nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CanSupportInline tests whether the plugin supports a given inline volume
 | 
				
			||||||
 | 
					// specification from the API.
 | 
				
			||||||
 | 
					func (t *vSphereCSITranslator) CanSupportInline(volume *v1.Volume) bool {
 | 
				
			||||||
 | 
						return volume != nil && volume.VsphereVolume != nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetInTreePluginName returns the name of the in-tree plugin driver
 | 
				
			||||||
 | 
					func (t *vSphereCSITranslator) GetInTreePluginName() string {
 | 
				
			||||||
 | 
						return VSphereInTreePluginName
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetCSIPluginName returns the name of the CSI plugin
 | 
				
			||||||
 | 
					func (t *vSphereCSITranslator) GetCSIPluginName() string {
 | 
				
			||||||
 | 
						return VSphereDriverName
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// RepairVolumeHandle is needed in VerifyVolumesAttached on the external attacher when we need to do strict volume
 | 
				
			||||||
 | 
					// handle matching to check VolumeAttachment attached status.
 | 
				
			||||||
 | 
					// vSphere volume does not need patch to help verify whether that volume is attached.
 | 
				
			||||||
 | 
					func (t *vSphereCSITranslator) RepairVolumeHandle(volumeHandle, nodeID string) (string, error) {
 | 
				
			||||||
 | 
						return volumeHandle, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,335 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					Copyright 2020 The Kubernetes Authors.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					You may obtain a copy of the License at
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					limitations under the License.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package plugins
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"reflect"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						v1 "k8s.io/api/core/v1"
 | 
				
			||||||
 | 
						storage "k8s.io/api/storage/v1"
 | 
				
			||||||
 | 
						metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestTranslatevSphereInTreeStorageClassToCSI(t *testing.T) {
 | 
				
			||||||
 | 
						translator := NewvSphereCSITranslator()
 | 
				
			||||||
 | 
						topologySelectorTerm := v1.TopologySelectorTerm{[]v1.TopologySelectorLabelRequirement{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								Key:    v1.LabelZoneFailureDomain,
 | 
				
			||||||
 | 
								Values: []string{"zone-a"},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								Key:    v1.LabelZoneRegion,
 | 
				
			||||||
 | 
								Values: []string{"region-a"},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}}
 | 
				
			||||||
 | 
						cases := []struct {
 | 
				
			||||||
 | 
							name   string
 | 
				
			||||||
 | 
							sc     *storage.StorageClass
 | 
				
			||||||
 | 
							expSc  *storage.StorageClass
 | 
				
			||||||
 | 
							expErr bool
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:   "expect error when sc is nil",
 | 
				
			||||||
 | 
								sc:     nil,
 | 
				
			||||||
 | 
								expSc:  nil,
 | 
				
			||||||
 | 
								expErr: true,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:  "translate with no parameter",
 | 
				
			||||||
 | 
								sc:    NewStorageClass(map[string]string{}, nil),
 | 
				
			||||||
 | 
								expSc: NewStorageClass(map[string]string{paramcsiMigration: "true"}, nil),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:  "translate with unknown parameter",
 | 
				
			||||||
 | 
								sc:    NewStorageClass(map[string]string{"unknownparam": "value"}, nil),
 | 
				
			||||||
 | 
								expSc: NewStorageClass(map[string]string{paramcsiMigration: "true"}, nil),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:  "translate with storagepolicyname and datastore",
 | 
				
			||||||
 | 
								sc:    NewStorageClass(map[string]string{"storagepolicyname": "test-policy-name", "datastore": "vsanDatastore"}, nil),
 | 
				
			||||||
 | 
								expSc: NewStorageClass(map[string]string{"storagepolicyname": "test-policy-name", "datastore-migrationparam": "vsanDatastore", paramcsiMigration: "true"}, nil),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:  "translate with fstype",
 | 
				
			||||||
 | 
								sc:    NewStorageClass(map[string]string{"fstype": "ext4"}, nil),
 | 
				
			||||||
 | 
								expSc: NewStorageClass(map[string]string{"csi.storage.k8s.io/fstype": "ext4", paramcsiMigration: "true"}, nil),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:  "translate with storagepolicyname and fstype",
 | 
				
			||||||
 | 
								sc:    NewStorageClass(map[string]string{"storagepolicyname": "test-policy-name", "fstype": "ext4"}, nil),
 | 
				
			||||||
 | 
								expSc: NewStorageClass(map[string]string{"csi.storage.k8s.io/fstype": "ext4", "storagepolicyname": "test-policy-name", paramcsiMigration: "true"}, nil),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:  "translate with no parameter and allowedTopology",
 | 
				
			||||||
 | 
								sc:    NewStorageClass(map[string]string{}, []v1.TopologySelectorTerm{topologySelectorTerm}),
 | 
				
			||||||
 | 
								expSc: NewStorageClass(map[string]string{paramcsiMigration: "true"}, []v1.TopologySelectorTerm{topologySelectorTerm}),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:  "translate with storagepolicyname and allowedTopology",
 | 
				
			||||||
 | 
								sc:    NewStorageClass(map[string]string{"storagepolicyname": "test-policy-name"}, []v1.TopologySelectorTerm{topologySelectorTerm}),
 | 
				
			||||||
 | 
								expSc: NewStorageClass(map[string]string{"storagepolicyname": "test-policy-name", paramcsiMigration: "true"}, []v1.TopologySelectorTerm{topologySelectorTerm}),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:  "translate with raw vSAN policy parameters, datastore and diskformat",
 | 
				
			||||||
 | 
								sc:    NewStorageClass(map[string]string{"hostfailurestotolerate": "2", "datastore": "vsanDatastore", "diskformat": "thin"}, []v1.TopologySelectorTerm{topologySelectorTerm}),
 | 
				
			||||||
 | 
								expSc: NewStorageClass(map[string]string{"hostfailurestotolerate-migrationparam": "2", "datastore-migrationparam": "vsanDatastore", "diskformat-migrationparam": "thin", paramcsiMigration: "true"}, []v1.TopologySelectorTerm{topologySelectorTerm}),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:  "translate with all parameters",
 | 
				
			||||||
 | 
								sc:    NewStorageClass(map[string]string{"storagepolicyname": "test-policy-name", "datastore": "test-datastore-name", "fstype": "ext4", "diskformat": "thin", "hostfailurestotolerate": "1", "forceprovisioning": "yes", "cachereservation": "25", "diskstripes": "4", "objectspacereservation": "10", "iopslimit": "32"}, []v1.TopologySelectorTerm{topologySelectorTerm}),
 | 
				
			||||||
 | 
								expSc: NewStorageClass(map[string]string{"storagepolicyname": "test-policy-name", "datastore-migrationparam": "test-datastore-name", "csi.storage.k8s.io/fstype": "ext4", "diskformat-migrationparam": "thin", "hostfailurestotolerate-migrationparam": "1", "forceprovisioning-migrationparam": "yes", "cachereservation-migrationparam": "25", "diskstripes-migrationparam": "4", "objectspacereservation-migrationparam": "10", "iopslimit-migrationparam": "32", paramcsiMigration: "true"}, []v1.TopologySelectorTerm{topologySelectorTerm}),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, tc := range cases {
 | 
				
			||||||
 | 
							t.Logf("Testing %v", tc.name)
 | 
				
			||||||
 | 
							got, err := translator.TranslateInTreeStorageClassToCSI(tc.sc)
 | 
				
			||||||
 | 
							if err != nil && !tc.expErr {
 | 
				
			||||||
 | 
								t.Errorf("Did not expect error but got: %v", err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if err == nil && tc.expErr {
 | 
				
			||||||
 | 
								t.Errorf("Expected error, but did not get one.")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if !reflect.DeepEqual(got, tc.expSc) {
 | 
				
			||||||
 | 
								t.Errorf("Got parameters: %v, expected :%v", got, tc.expSc)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestTranslateVSphereCSIPVToInTree(t *testing.T) {
 | 
				
			||||||
 | 
						translator := NewvSphereCSITranslator()
 | 
				
			||||||
 | 
						cases := []struct {
 | 
				
			||||||
 | 
							name     string
 | 
				
			||||||
 | 
							csiPV    *v1.PersistentVolume
 | 
				
			||||||
 | 
							intreePV *v1.PersistentVolume
 | 
				
			||||||
 | 
							expErr   bool
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:     "expect error when pv is nil",
 | 
				
			||||||
 | 
								csiPV:    nil,
 | 
				
			||||||
 | 
								intreePV: nil,
 | 
				
			||||||
 | 
								expErr:   true,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "expect error when pv.Spec.CSI is nil",
 | 
				
			||||||
 | 
								csiPV: &v1.PersistentVolume{
 | 
				
			||||||
 | 
									ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
 | 
										Name: "pvc-d8b4475f-2c47-486e-9b57-43ae006f9b59",
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									Spec: v1.PersistentVolumeSpec{
 | 
				
			||||||
 | 
										PersistentVolumeSource: v1.PersistentVolumeSource{
 | 
				
			||||||
 | 
											CSI: nil,
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								intreePV: nil,
 | 
				
			||||||
 | 
								expErr:   true,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "translate valid vSphere CSI PV to vSphere in-tree PV",
 | 
				
			||||||
 | 
								csiPV: &v1.PersistentVolume{
 | 
				
			||||||
 | 
									ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
 | 
										Name: "pvc-d8b4475f-2c47-486e-9b57-43ae006f9b59",
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									Spec: v1.PersistentVolumeSpec{
 | 
				
			||||||
 | 
										PersistentVolumeSource: v1.PersistentVolumeSource{
 | 
				
			||||||
 | 
											CSI: &v1.CSIPersistentVolumeSource{
 | 
				
			||||||
 | 
												Driver:       VSphereDriverName,
 | 
				
			||||||
 | 
												VolumeHandle: "e4073a6d-642e-4dff-8f4a-b4e3a47c4bbd",
 | 
				
			||||||
 | 
												FSType:       "ext4",
 | 
				
			||||||
 | 
												VolumeAttributes: map[string]string{
 | 
				
			||||||
 | 
													paramStoragePolicyName:         "vSAN Default Storage Policy",
 | 
				
			||||||
 | 
													AttributeInitialVolumeFilepath: "[vsanDatastore] 6785a85e-268e-6352-a2e8-02008b7afadd/kubernetes-dynamic-pvc-68734c9f-a679-42e6-a694-39632c51e31f.vmdk",
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								intreePV: &v1.PersistentVolume{
 | 
				
			||||||
 | 
									ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
 | 
										Name: "pvc-d8b4475f-2c47-486e-9b57-43ae006f9b59",
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									Spec: v1.PersistentVolumeSpec{
 | 
				
			||||||
 | 
										PersistentVolumeSource: v1.PersistentVolumeSource{
 | 
				
			||||||
 | 
											VsphereVolume: &v1.VsphereVirtualDiskVolumeSource{
 | 
				
			||||||
 | 
												VolumePath: "[vsanDatastore] 6785a85e-268e-6352-a2e8-02008b7afadd/kubernetes-dynamic-pvc-68734c9f-a679-42e6-a694-39632c51e31f.vmdk",
 | 
				
			||||||
 | 
												FSType:     "ext4",
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								expErr: false,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, tc := range cases {
 | 
				
			||||||
 | 
							t.Logf("Testing %v", tc.name)
 | 
				
			||||||
 | 
							got, err := translator.TranslateCSIPVToInTree(tc.csiPV)
 | 
				
			||||||
 | 
							if err != nil && !tc.expErr {
 | 
				
			||||||
 | 
								t.Errorf("Did not expect error but got: %v", err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if err == nil && tc.expErr {
 | 
				
			||||||
 | 
								t.Errorf("Expected error, but did not get one.")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if !reflect.DeepEqual(got, tc.intreePV) {
 | 
				
			||||||
 | 
								t.Errorf("Got PV: %v, expected :%v", got, tc.intreePV)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestTranslateVSphereInTreePVToCSI(t *testing.T) {
 | 
				
			||||||
 | 
						translator := NewvSphereCSITranslator()
 | 
				
			||||||
 | 
						cases := []struct {
 | 
				
			||||||
 | 
							name     string
 | 
				
			||||||
 | 
							intreePV *v1.PersistentVolume
 | 
				
			||||||
 | 
							csiPV    *v1.PersistentVolume
 | 
				
			||||||
 | 
							expErr   bool
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:     "expect error when in-tree vsphere PV is nil",
 | 
				
			||||||
 | 
								intreePV: &v1.PersistentVolume{},
 | 
				
			||||||
 | 
								csiPV:    nil,
 | 
				
			||||||
 | 
								expErr:   true,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "translate valid vSphere in-tree PV to vSphere CSI PV",
 | 
				
			||||||
 | 
								intreePV: &v1.PersistentVolume{
 | 
				
			||||||
 | 
									ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
 | 
										Name: "pvc-d8b4475f-2c47-486e-9b57-43ae006f9b59",
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									Spec: v1.PersistentVolumeSpec{
 | 
				
			||||||
 | 
										PersistentVolumeSource: v1.PersistentVolumeSource{
 | 
				
			||||||
 | 
											VsphereVolume: &v1.VsphereVirtualDiskVolumeSource{
 | 
				
			||||||
 | 
												VolumePath:        "[vsanDatastore] 6785a85e-268e-6352-a2e8-02008b7afadd/kubernetes-dynamic-pvc-68734c9f-a679-42e6-a694-39632c51e31f.vmdk",
 | 
				
			||||||
 | 
												FSType:            "ext4",
 | 
				
			||||||
 | 
												StoragePolicyName: "vSAN Default Storage Policy",
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								csiPV: &v1.PersistentVolume{
 | 
				
			||||||
 | 
									ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
 | 
										Name: "pvc-d8b4475f-2c47-486e-9b57-43ae006f9b59",
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									Spec: v1.PersistentVolumeSpec{
 | 
				
			||||||
 | 
										PersistentVolumeSource: v1.PersistentVolumeSource{
 | 
				
			||||||
 | 
											CSI: &v1.CSIPersistentVolumeSource{
 | 
				
			||||||
 | 
												Driver:       VSphereDriverName,
 | 
				
			||||||
 | 
												VolumeHandle: "[vsanDatastore] 6785a85e-268e-6352-a2e8-02008b7afadd/kubernetes-dynamic-pvc-68734c9f-a679-42e6-a694-39632c51e31f.vmdk",
 | 
				
			||||||
 | 
												FSType:       "ext4",
 | 
				
			||||||
 | 
												VolumeAttributes: map[string]string{
 | 
				
			||||||
 | 
													paramStoragePolicyName: "vSAN Default Storage Policy",
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								expErr: false,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, tc := range cases {
 | 
				
			||||||
 | 
							t.Logf("Testing %v", tc.name)
 | 
				
			||||||
 | 
							got, err := translator.TranslateInTreePVToCSI(tc.intreePV)
 | 
				
			||||||
 | 
							if err != nil && !tc.expErr {
 | 
				
			||||||
 | 
								t.Errorf("Did not expect error but got: %v", err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if err == nil && tc.expErr {
 | 
				
			||||||
 | 
								t.Errorf("Expected error, but did not get one.")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if !reflect.DeepEqual(got, tc.csiPV) {
 | 
				
			||||||
 | 
								t.Errorf("Got PV: %v, expected :%v", got, tc.csiPV)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestTranslatevSphereInTreeInlineVolumeToCSI(t *testing.T) {
 | 
				
			||||||
 | 
						translator := NewvSphereCSITranslator()
 | 
				
			||||||
 | 
						cases := []struct {
 | 
				
			||||||
 | 
							name         string
 | 
				
			||||||
 | 
							inlinevolume *v1.Volume
 | 
				
			||||||
 | 
							csiPV        *v1.PersistentVolume
 | 
				
			||||||
 | 
							expErr       bool
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:         "expect error when inline vsphere volume is nil",
 | 
				
			||||||
 | 
								inlinevolume: &v1.Volume{},
 | 
				
			||||||
 | 
								csiPV:        nil,
 | 
				
			||||||
 | 
								expErr:       true,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "translate valid in-tree vsphere volume to vSphere CSI PV",
 | 
				
			||||||
 | 
								inlinevolume: &v1.Volume{
 | 
				
			||||||
 | 
									Name: "inlinevolume",
 | 
				
			||||||
 | 
									VolumeSource: v1.VolumeSource{
 | 
				
			||||||
 | 
										VsphereVolume: &v1.VsphereVirtualDiskVolumeSource{
 | 
				
			||||||
 | 
											VolumePath: "[vsanDatastore] volume/inlinevolume.vmdk",
 | 
				
			||||||
 | 
											FSType:     "ext4",
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									}},
 | 
				
			||||||
 | 
								csiPV: &v1.PersistentVolume{
 | 
				
			||||||
 | 
									ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
 | 
										Name: fmt.Sprintf("%s-%s", VSphereDriverName, "[vsanDatastore] volume/inlinevolume.vmdk"),
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									Spec: v1.PersistentVolumeSpec{
 | 
				
			||||||
 | 
										PersistentVolumeSource: v1.PersistentVolumeSource{
 | 
				
			||||||
 | 
											CSI: &v1.CSIPersistentVolumeSource{
 | 
				
			||||||
 | 
												Driver:           VSphereDriverName,
 | 
				
			||||||
 | 
												VolumeHandle:     "[vsanDatastore] volume/inlinevolume.vmdk",
 | 
				
			||||||
 | 
												FSType:           "ext4",
 | 
				
			||||||
 | 
												VolumeAttributes: make(map[string]string),
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								expErr: false,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, tc := range cases {
 | 
				
			||||||
 | 
							t.Logf("Testing %v", tc.name)
 | 
				
			||||||
 | 
							got, err := translator.TranslateInTreeInlineVolumeToCSI(tc.inlinevolume)
 | 
				
			||||||
 | 
							if err == nil && tc.expErr {
 | 
				
			||||||
 | 
								t.Errorf("Expected error, but did not get one.")
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								if tc.expErr {
 | 
				
			||||||
 | 
									t.Logf("expected error received")
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									t.Errorf("Did not expect error but got: %v", err)
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if !reflect.DeepEqual(got, tc.csiPV) {
 | 
				
			||||||
 | 
								t.Errorf("Got PV: %v, expected :%v", got, tc.csiPV)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -32,6 +32,7 @@ var (
 | 
				
			|||||||
		plugins.CinderDriverName:    plugins.NewOpenStackCinderCSITranslator(),
 | 
							plugins.CinderDriverName:    plugins.NewOpenStackCinderCSITranslator(),
 | 
				
			||||||
		plugins.AzureDiskDriverName: plugins.NewAzureDiskCSITranslator(),
 | 
							plugins.AzureDiskDriverName: plugins.NewAzureDiskCSITranslator(),
 | 
				
			||||||
		plugins.AzureFileDriverName: plugins.NewAzureFileCSITranslator(),
 | 
							plugins.AzureFileDriverName: plugins.NewAzureFileCSITranslator(),
 | 
				
			||||||
 | 
							plugins.VSphereDriverName:   plugins.NewvSphereCSITranslator(),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -384,6 +384,13 @@ func generateUniqueVolumeSource(driverName string) (v1.VolumeSource, error) {
 | 
				
			|||||||
				ShareName:  string(uuid.NewUUID()),
 | 
									ShareName:  string(uuid.NewUUID()),
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		}, nil
 | 
							}, nil
 | 
				
			||||||
 | 
						case plugins.VSphereDriverName:
 | 
				
			||||||
 | 
							return v1.VolumeSource{
 | 
				
			||||||
 | 
								VsphereVolume: &v1.VsphereVirtualDiskVolumeSource{
 | 
				
			||||||
 | 
									VolumePath: " [vsanDatastore] 6785a85e-268e-6352-a2e8-02008b7afadd/kubernetes-dynamic-pvc-" + string(uuid.NewUUID()+".vmdk"),
 | 
				
			||||||
 | 
									FSType:     "ext4",
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							}, nil
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return v1.VolumeSource{}, fmt.Errorf("couldn't find logic for driver: %v", driverName)
 | 
							return v1.VolumeSource{}, fmt.Errorf("couldn't find logic for driver: %v", driverName)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user