Merge pull request #83098 from ddebroy/disable-intree
CSI Migration phase 2: disable probing of in-tree plugins
This commit is contained in:
@@ -88,6 +88,7 @@ filegroup(
|
||||
"//pkg/volume/cinder:all-srcs",
|
||||
"//pkg/volume/configmap:all-srcs",
|
||||
"//pkg/volume/csi:all-srcs",
|
||||
"//pkg/volume/csimigration:all-srcs",
|
||||
"//pkg/volume/downwardapi:all-srcs",
|
||||
"//pkg/volume/emptydir:all-srcs",
|
||||
"//pkg/volume/fc:all-srcs",
|
||||
|
||||
@@ -89,11 +89,6 @@ func (plugin *awsElasticBlockStorePlugin) CanSupport(spec *volume.Spec) bool {
|
||||
(spec.Volume != nil && spec.Volume.AWSElasticBlockStore != nil)
|
||||
}
|
||||
|
||||
func (plugin *awsElasticBlockStorePlugin) IsMigratedToCSI() bool {
|
||||
return utilfeature.DefaultFeatureGate.Enabled(features.CSIMigration) &&
|
||||
utilfeature.DefaultFeatureGate.Enabled(features.CSIMigrationAWS)
|
||||
}
|
||||
|
||||
func (plugin *awsElasticBlockStorePlugin) RequiresRemount() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -31,8 +31,6 @@ import (
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
"k8s.io/kubernetes/pkg/volume/util"
|
||||
"k8s.io/legacy-cloud-providers/azure"
|
||||
@@ -122,11 +120,6 @@ func (plugin *azureDataDiskPlugin) CanSupport(spec *volume.Spec) bool {
|
||||
(spec.Volume != nil && spec.Volume.AzureDisk != nil)
|
||||
}
|
||||
|
||||
func (plugin *azureDataDiskPlugin) IsMigratedToCSI() bool {
|
||||
return utilfeature.DefaultFeatureGate.Enabled(features.CSIMigration) &&
|
||||
utilfeature.DefaultFeatureGate.Enabled(features.CSIMigrationAzureDisk)
|
||||
}
|
||||
|
||||
func (plugin *azureDataDiskPlugin) RequiresRemount() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@ go_library(
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/pkg/volume/azure_file",
|
||||
deps = [
|
||||
"//pkg/features:go_default_library",
|
||||
"//pkg/util/mount:go_default_library",
|
||||
"//pkg/volume:go_default_library",
|
||||
"//pkg/volume/util:go_default_library",
|
||||
@@ -25,7 +24,6 @@ go_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/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/volume/helpers:go_default_library",
|
||||
"//staging/src/k8s.io/legacy-cloud-providers/azure:go_default_library",
|
||||
|
||||
@@ -28,11 +28,9 @@ import (
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
cloudprovider "k8s.io/cloud-provider"
|
||||
volumehelpers "k8s.io/cloud-provider/volume/helpers"
|
||||
"k8s.io/klog"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
"k8s.io/kubernetes/pkg/util/mount"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
volutil "k8s.io/kubernetes/pkg/volume/util"
|
||||
@@ -85,11 +83,6 @@ func (plugin *azureFilePlugin) CanSupport(spec *volume.Spec) bool {
|
||||
(spec.Volume != nil && spec.Volume.AzureFile != nil)
|
||||
}
|
||||
|
||||
func (plugin *azureFilePlugin) IsMigratedToCSI() bool {
|
||||
return utilfeature.DefaultFeatureGate.Enabled(features.CSIMigration) &&
|
||||
utilfeature.DefaultFeatureGate.Enabled(features.CSIMigrationAzureFile)
|
||||
}
|
||||
|
||||
func (plugin *azureFilePlugin) RequiresRemount() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -71,10 +71,6 @@ func (plugin *cephfsPlugin) CanSupport(spec *volume.Spec) bool {
|
||||
return (spec.Volume != nil && spec.Volume.CephFS != nil) || (spec.PersistentVolume != nil && spec.PersistentVolume.Spec.CephFS != nil)
|
||||
}
|
||||
|
||||
func (plugin *cephfsPlugin) IsMigratedToCSI() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (plugin *cephfsPlugin) RequiresRemount() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -111,11 +111,6 @@ func (plugin *cinderPlugin) CanSupport(spec *volume.Spec) bool {
|
||||
return (spec.Volume != nil && spec.Volume.Cinder != nil) || (spec.PersistentVolume != nil && spec.PersistentVolume.Spec.Cinder != nil)
|
||||
}
|
||||
|
||||
func (plugin *cinderPlugin) IsMigratedToCSI() bool {
|
||||
return utilfeature.DefaultFeatureGate.Enabled(features.CSIMigration) &&
|
||||
utilfeature.DefaultFeatureGate.Enabled(features.CSIMigrationOpenStack)
|
||||
}
|
||||
|
||||
func (plugin *cinderPlugin) RequiresRemount() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -77,10 +77,6 @@ func (plugin *configMapPlugin) CanSupport(spec *volume.Spec) bool {
|
||||
return spec.Volume != nil && spec.Volume.ConfigMap != nil
|
||||
}
|
||||
|
||||
func (plugin *configMapPlugin) IsMigratedToCSI() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (plugin *configMapPlugin) RequiresRemount() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -314,10 +314,6 @@ func (p *csiPlugin) CanSupport(spec *volume.Spec) bool {
|
||||
return spec.PersistentVolume != nil && spec.PersistentVolume.Spec.CSI != nil
|
||||
}
|
||||
|
||||
func (p *csiPlugin) IsMigratedToCSI() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *csiPlugin) RequiresRemount() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
45
pkg/volume/csimigration/BUILD
Normal file
45
pkg/volume/csimigration/BUILD
Normal file
@@ -0,0 +1,45 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["plugin_manager.go"],
|
||||
importpath = "k8s.io/kubernetes/pkg/volume/csimigration",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//pkg/features:go_default_library",
|
||||
"//pkg/volume:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//staging/src/k8s.io/component-base/featuregate:go_default_library",
|
||||
"//staging/src/k8s.io/csi-translation-lib/plugins:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["plugin_manager_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/features:go_default_library",
|
||||
"//pkg/volume:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature: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/csi-translation-lib:go_default_library",
|
||||
],
|
||||
)
|
||||
156
pkg/volume/csimigration/plugin_manager.go
Normal file
156
pkg/volume/csimigration/plugin_manager.go
Normal file
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
Copyright 2019 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 csimigration
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/component-base/featuregate"
|
||||
csilibplugins "k8s.io/csi-translation-lib/plugins"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
)
|
||||
|
||||
// PluginNameMapper contains utility methods to retrieve names of plugins
|
||||
// that support a spec, map intree <=> migrated CSI plugin names, etc
|
||||
type PluginNameMapper interface {
|
||||
GetInTreePluginNameFromSpec(pv *v1.PersistentVolume, vol *v1.Volume) (string, error)
|
||||
GetCSINameFromInTreeName(pluginName string) (string, error)
|
||||
}
|
||||
|
||||
// PluginManager keeps track of migrated state of in-tree plugins
|
||||
type PluginManager struct {
|
||||
PluginNameMapper
|
||||
}
|
||||
|
||||
// NewPluginManager returns a new PluginManager instance
|
||||
func NewPluginManager(m PluginNameMapper) PluginManager {
|
||||
return PluginManager{
|
||||
PluginNameMapper: m,
|
||||
}
|
||||
}
|
||||
|
||||
// IsMigrationCompleteForPlugin indicates whether CSI migration has been completed
|
||||
// for a particular storage plugin
|
||||
func (pm PluginManager) IsMigrationCompleteForPlugin(pluginName string) bool {
|
||||
// CSIMigration feature and plugin specific migration feature flags should
|
||||
// be enabled for plugin specific migration completion feature flags to be
|
||||
// take effect
|
||||
if !pm.IsMigrationEnabledForPlugin(pluginName) {
|
||||
return false
|
||||
}
|
||||
|
||||
switch pluginName {
|
||||
case csilibplugins.AWSEBSInTreePluginName:
|
||||
return utilfeature.DefaultFeatureGate.Enabled(features.CSIMigrationAWSComplete)
|
||||
case csilibplugins.GCEPDInTreePluginName:
|
||||
return utilfeature.DefaultFeatureGate.Enabled(features.CSIMigrationGCEComplete)
|
||||
case csilibplugins.AzureFileInTreePluginName:
|
||||
return utilfeature.DefaultFeatureGate.Enabled(features.CSIMigrationAzureFileComplete)
|
||||
case csilibplugins.AzureDiskInTreePluginName:
|
||||
return utilfeature.DefaultFeatureGate.Enabled(features.CSIMigrationAzureDiskComplete)
|
||||
case csilibplugins.CinderInTreePluginName:
|
||||
return utilfeature.DefaultFeatureGate.Enabled(features.CSIMigrationOpenStackComplete)
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// IsMigrationEnabledForPlugin indicates whether CSI migration has been enabled
|
||||
// for a particular storage plugin
|
||||
func (pm PluginManager) IsMigrationEnabledForPlugin(pluginName string) bool {
|
||||
// CSIMigration feature should be enabled along with the plugin-specific one
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.CSIMigration) {
|
||||
return false
|
||||
}
|
||||
|
||||
switch pluginName {
|
||||
case csilibplugins.AWSEBSInTreePluginName:
|
||||
return utilfeature.DefaultFeatureGate.Enabled(features.CSIMigrationAWS)
|
||||
case csilibplugins.GCEPDInTreePluginName:
|
||||
return utilfeature.DefaultFeatureGate.Enabled(features.CSIMigrationGCE)
|
||||
case csilibplugins.AzureFileInTreePluginName:
|
||||
return utilfeature.DefaultFeatureGate.Enabled(features.CSIMigrationAzureFile)
|
||||
case csilibplugins.AzureDiskInTreePluginName:
|
||||
return utilfeature.DefaultFeatureGate.Enabled(features.CSIMigrationAzureDisk)
|
||||
case csilibplugins.CinderInTreePluginName:
|
||||
return utilfeature.DefaultFeatureGate.Enabled(features.CSIMigrationOpenStack)
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// IsMigratable indicates whether CSI migration has been enabled for a volume
|
||||
// plugin that the spec refers to
|
||||
func (pm PluginManager) IsMigratable(spec *volume.Spec) (bool, error) {
|
||||
if spec == nil {
|
||||
return false, fmt.Errorf("could not find if plugin is migratable because volume spec is nil")
|
||||
}
|
||||
|
||||
pluginName, _ := pm.GetInTreePluginNameFromSpec(spec.PersistentVolume, spec.Volume)
|
||||
if pluginName == "" {
|
||||
return false, nil
|
||||
}
|
||||
// found an in-tree plugin that supports the spec
|
||||
return pm.IsMigrationEnabledForPlugin(pluginName), nil
|
||||
}
|
||||
|
||||
// InTreeToCSITranslator performs translation of Volume sources for PV and Volume objects
|
||||
// from references to in-tree plugins to migrated CSI plugins
|
||||
type InTreeToCSITranslator interface {
|
||||
TranslateInTreePVToCSI(pv *v1.PersistentVolume) (*v1.PersistentVolume, error)
|
||||
TranslateInTreeInlineVolumeToCSI(volume *v1.Volume) (*v1.PersistentVolume, error)
|
||||
}
|
||||
|
||||
// TranslateInTreeSpecToCSI translates a volume spec (either PV or inline volume)
|
||||
// supported by an in-tree plugin to CSI
|
||||
func TranslateInTreeSpecToCSI(spec *volume.Spec, translator InTreeToCSITranslator) (*volume.Spec, error) {
|
||||
var csiPV *v1.PersistentVolume
|
||||
var err error
|
||||
inlineVolume := false
|
||||
if spec.PersistentVolume != nil {
|
||||
csiPV, err = translator.TranslateInTreePVToCSI(spec.PersistentVolume)
|
||||
} else if spec.Volume != nil {
|
||||
csiPV, err = translator.TranslateInTreeInlineVolumeToCSI(spec.Volume)
|
||||
inlineVolume = true
|
||||
} else {
|
||||
err = errors.New("not a valid volume spec")
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to translate in-tree pv to CSI: %v", err)
|
||||
}
|
||||
return &volume.Spec{
|
||||
PersistentVolume: csiPV,
|
||||
ReadOnly: spec.ReadOnly,
|
||||
InlineVolumeSpecForCSIMigration: inlineVolume,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// CheckMigrationFeatureFlags checks the configuration of feature flags related
|
||||
// to CSI Migration is valid
|
||||
func CheckMigrationFeatureFlags(f featuregate.FeatureGate, pluginMigration, pluginMigrationComplete featuregate.Feature) error {
|
||||
if f.Enabled(pluginMigration) && !f.Enabled(features.CSIMigration) {
|
||||
return fmt.Errorf("enabling %q requires CSIMigration to be enabled", pluginMigration)
|
||||
}
|
||||
if f.Enabled(pluginMigrationComplete) && !f.Enabled(pluginMigration) {
|
||||
return fmt.Errorf("enabling %q requires %q to be enabled", pluginMigrationComplete, pluginMigration)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
325
pkg/volume/csimigration/plugin_manager_test.go
Normal file
325
pkg/volume/csimigration/plugin_manager_test.go
Normal file
@@ -0,0 +1,325 @@
|
||||
/*
|
||||
Copyright 2019 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 csimigration
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/component-base/featuregate"
|
||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||
csitrans "k8s.io/csi-translation-lib"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
)
|
||||
|
||||
func TestIsMigratable(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
pluginFeature featuregate.Feature
|
||||
pluginFeatureEnabled bool
|
||||
csiMigrationEnabled bool
|
||||
isMigratable bool
|
||||
spec *volume.Spec
|
||||
}{
|
||||
{
|
||||
name: "GCE PD PV source with CSIMigrationGCE enabled",
|
||||
pluginFeature: features.CSIMigrationGCE,
|
||||
pluginFeatureEnabled: true,
|
||||
isMigratable: true,
|
||||
csiMigrationEnabled: true,
|
||||
spec: &volume.Spec{
|
||||
PersistentVolume: &v1.PersistentVolume{
|
||||
Spec: v1.PersistentVolumeSpec{
|
||||
PersistentVolumeSource: v1.PersistentVolumeSource{
|
||||
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
|
||||
PDName: "test-disk",
|
||||
FSType: "ext4",
|
||||
Partition: 0,
|
||||
ReadOnly: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "GCE PD PV Source with CSIMigrationGCE disabled",
|
||||
pluginFeature: features.CSIMigrationGCE,
|
||||
pluginFeatureEnabled: false,
|
||||
isMigratable: false,
|
||||
csiMigrationEnabled: true,
|
||||
spec: &volume.Spec{
|
||||
PersistentVolume: &v1.PersistentVolume{
|
||||
Spec: v1.PersistentVolumeSpec{
|
||||
PersistentVolumeSource: v1.PersistentVolumeSource{
|
||||
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
|
||||
PDName: "test-disk",
|
||||
FSType: "ext4",
|
||||
Partition: 0,
|
||||
ReadOnly: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "AWS EBS PV with CSIMigrationAWS enabled",
|
||||
pluginFeature: features.CSIMigrationAWS,
|
||||
pluginFeatureEnabled: true,
|
||||
isMigratable: true,
|
||||
csiMigrationEnabled: true,
|
||||
spec: &volume.Spec{
|
||||
PersistentVolume: &v1.PersistentVolume{
|
||||
Spec: v1.PersistentVolumeSpec{
|
||||
PersistentVolumeSource: v1.PersistentVolumeSource{
|
||||
AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{
|
||||
VolumeID: "vol01",
|
||||
FSType: "ext3",
|
||||
Partition: 1,
|
||||
ReadOnly: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "AWS EBS PV with CSIMigration and CSIMigrationAWS disabled",
|
||||
pluginFeature: features.CSIMigrationAWS,
|
||||
pluginFeatureEnabled: false,
|
||||
isMigratable: false,
|
||||
csiMigrationEnabled: false,
|
||||
spec: &volume.Spec{
|
||||
PersistentVolume: &v1.PersistentVolume{
|
||||
Spec: v1.PersistentVolumeSpec{
|
||||
PersistentVolumeSource: v1.PersistentVolumeSource{
|
||||
AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{
|
||||
VolumeID: "vol01",
|
||||
FSType: "ext3",
|
||||
Partition: 1,
|
||||
ReadOnly: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
csiTranslator := csitrans.New()
|
||||
for _, test := range testCases {
|
||||
pm := NewPluginManager(csiTranslator)
|
||||
t.Run(fmt.Sprintf("Testing %v", test.name), func(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIMigration, test.csiMigrationEnabled)()
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, test.pluginFeature, test.pluginFeatureEnabled)()
|
||||
migratable, err := pm.IsMigratable(test.spec)
|
||||
if migratable != test.isMigratable {
|
||||
t.Errorf("Expected migratability of spec: %v does not match obtained migratability: %v", test.isMigratable, migratable)
|
||||
}
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckMigrationFeatureFlags(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
pluginFeature featuregate.Feature
|
||||
pluginFeatureEnabled bool
|
||||
csiMigrationEnabled bool
|
||||
pluginFeatureComplete featuregate.Feature
|
||||
pluginFeatureCompleteEnabled bool
|
||||
result bool
|
||||
}{
|
||||
{
|
||||
name: "plugin specific feature flag enabled with migration flag disabled",
|
||||
pluginFeature: features.CSIMigrationGCE,
|
||||
pluginFeatureEnabled: true,
|
||||
csiMigrationEnabled: false,
|
||||
pluginFeatureComplete: features.CSIMigrationGCEComplete,
|
||||
pluginFeatureCompleteEnabled: false,
|
||||
result: false,
|
||||
},
|
||||
{
|
||||
name: "plugin specific complete flag enabled but plugin specific feature flag disabled",
|
||||
pluginFeature: features.CSIMigrationAWS,
|
||||
pluginFeatureEnabled: false,
|
||||
csiMigrationEnabled: true,
|
||||
pluginFeatureComplete: features.CSIMigrationAWSComplete,
|
||||
pluginFeatureCompleteEnabled: true,
|
||||
result: false,
|
||||
},
|
||||
{
|
||||
name: "plugin specific complete feature disabled but plugin specific migration feature and CSI migration flag enabled",
|
||||
pluginFeature: features.CSIMigrationGCE,
|
||||
pluginFeatureEnabled: true,
|
||||
csiMigrationEnabled: true,
|
||||
pluginFeatureComplete: features.CSIMigrationGCEComplete,
|
||||
pluginFeatureCompleteEnabled: false,
|
||||
result: true,
|
||||
},
|
||||
{
|
||||
name: "all features enabled",
|
||||
pluginFeature: features.CSIMigrationAWS,
|
||||
pluginFeatureEnabled: true,
|
||||
csiMigrationEnabled: true,
|
||||
pluginFeatureComplete: features.CSIMigrationAWSComplete,
|
||||
pluginFeatureCompleteEnabled: true,
|
||||
result: true,
|
||||
},
|
||||
}
|
||||
for _, test := range testCases {
|
||||
t.Run(fmt.Sprintf("Testing %v", test.name), func(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIMigration, test.csiMigrationEnabled)()
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, test.pluginFeature, test.pluginFeatureEnabled)()
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, test.pluginFeatureComplete, test.pluginFeatureCompleteEnabled)()
|
||||
err := CheckMigrationFeatureFlags(utilfeature.DefaultFeatureGate, test.pluginFeature, test.pluginFeatureComplete)
|
||||
if err != nil && test.result == true {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
if err == nil && test.result == false {
|
||||
t.Errorf("Unexpected validation pass")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestMigrationFeatureFlagStatus(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
pluginName string
|
||||
csiMigrationEnabled bool
|
||||
pluginFeature featuregate.Feature
|
||||
pluginFeatureEnabled bool
|
||||
pluginFeatureComplete featuregate.Feature
|
||||
pluginFeatureCompleteEnabled bool
|
||||
csiMigrationResult bool
|
||||
csiMigrationCompleteResult bool
|
||||
}{
|
||||
{
|
||||
name: "gce-pd migration flag disabled and migration-complete flag disabled with CSI migration flag disabled",
|
||||
pluginName: "kubernetes.io/gce-pd",
|
||||
pluginFeature: features.CSIMigrationGCE,
|
||||
pluginFeatureEnabled: false,
|
||||
csiMigrationEnabled: false,
|
||||
pluginFeatureComplete: features.CSIMigrationGCEComplete,
|
||||
pluginFeatureCompleteEnabled: false,
|
||||
csiMigrationResult: false,
|
||||
csiMigrationCompleteResult: false,
|
||||
},
|
||||
{
|
||||
name: "gce-pd migration flag disabled and migration-complete flag disabled with CSI migration flag enabled",
|
||||
pluginName: "kubernetes.io/gce-pd",
|
||||
pluginFeature: features.CSIMigrationGCE,
|
||||
pluginFeatureEnabled: false,
|
||||
csiMigrationEnabled: true,
|
||||
pluginFeatureComplete: features.CSIMigrationGCEComplete,
|
||||
pluginFeatureCompleteEnabled: false,
|
||||
csiMigrationResult: false,
|
||||
csiMigrationCompleteResult: false,
|
||||
},
|
||||
{
|
||||
name: "gce-pd migration flag enabled and migration-complete flag disabled with CSI migration flag enabled",
|
||||
pluginName: "kubernetes.io/gce-pd",
|
||||
pluginFeature: features.CSIMigrationGCE,
|
||||
pluginFeatureEnabled: true,
|
||||
csiMigrationEnabled: true,
|
||||
pluginFeatureComplete: features.CSIMigrationGCEComplete,
|
||||
pluginFeatureCompleteEnabled: false,
|
||||
csiMigrationResult: true,
|
||||
csiMigrationCompleteResult: false,
|
||||
},
|
||||
{
|
||||
name: "gce-pd migration flag enabled and migration-complete flag enabled with CSI migration flag enabled",
|
||||
pluginName: "kubernetes.io/gce-pd",
|
||||
pluginFeature: features.CSIMigrationGCE,
|
||||
pluginFeatureEnabled: true,
|
||||
csiMigrationEnabled: true,
|
||||
pluginFeatureComplete: features.CSIMigrationGCEComplete,
|
||||
pluginFeatureCompleteEnabled: true,
|
||||
csiMigrationResult: true,
|
||||
csiMigrationCompleteResult: true,
|
||||
},
|
||||
{
|
||||
name: "aws-ebs migration flag disabled and migration-complete flag disabled with CSI migration flag disabled",
|
||||
pluginName: "kubernetes.io/aws-ebs",
|
||||
pluginFeature: features.CSIMigrationAWS,
|
||||
pluginFeatureEnabled: false,
|
||||
csiMigrationEnabled: false,
|
||||
pluginFeatureComplete: features.CSIMigrationAWSComplete,
|
||||
pluginFeatureCompleteEnabled: false,
|
||||
csiMigrationResult: false,
|
||||
csiMigrationCompleteResult: false,
|
||||
},
|
||||
{
|
||||
name: "aws-ebs migration flag disabled and migration-complete flag disabled with CSI migration flag enabled",
|
||||
pluginName: "kubernetes.io/aws-ebs",
|
||||
pluginFeature: features.CSIMigrationAWS,
|
||||
pluginFeatureEnabled: false,
|
||||
csiMigrationEnabled: true,
|
||||
pluginFeatureComplete: features.CSIMigrationAWSComplete,
|
||||
pluginFeatureCompleteEnabled: false,
|
||||
csiMigrationResult: false,
|
||||
csiMigrationCompleteResult: false,
|
||||
},
|
||||
{
|
||||
name: "aws-ebs migration flag enabled and migration-complete flag disabled with CSI migration flag enabled",
|
||||
pluginName: "kubernetes.io/aws-ebs",
|
||||
pluginFeature: features.CSIMigrationAWS,
|
||||
pluginFeatureEnabled: true,
|
||||
csiMigrationEnabled: true,
|
||||
pluginFeatureComplete: features.CSIMigrationAWSComplete,
|
||||
pluginFeatureCompleteEnabled: false,
|
||||
csiMigrationResult: true,
|
||||
csiMigrationCompleteResult: false,
|
||||
},
|
||||
{
|
||||
name: "aws-ebs migration flag enabled and migration-complete flag enabled with CSI migration flag enabled",
|
||||
pluginName: "kubernetes.io/aws-ebs",
|
||||
pluginFeature: features.CSIMigrationAWS,
|
||||
pluginFeatureEnabled: true,
|
||||
csiMigrationEnabled: true,
|
||||
pluginFeatureComplete: features.CSIMigrationAWSComplete,
|
||||
pluginFeatureCompleteEnabled: true,
|
||||
csiMigrationResult: true,
|
||||
csiMigrationCompleteResult: true,
|
||||
},
|
||||
}
|
||||
csiTranslator := csitrans.New()
|
||||
for _, test := range testCases {
|
||||
pm := NewPluginManager(csiTranslator)
|
||||
t.Run(fmt.Sprintf("Testing %v", test.name), func(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIMigration, test.csiMigrationEnabled)()
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, test.pluginFeature, test.pluginFeatureEnabled)()
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, test.pluginFeatureComplete, test.pluginFeatureCompleteEnabled)()
|
||||
|
||||
csiMigrationResult := pm.IsMigrationEnabledForPlugin(test.pluginName)
|
||||
if csiMigrationResult != test.csiMigrationResult {
|
||||
t.Errorf("Expected migratability of plugin %v: %v does not match obtained migratability: %v", test.pluginName, test.csiMigrationResult, csiMigrationResult)
|
||||
}
|
||||
csiMigrationCompleteResult := pm.IsMigrationCompleteForPlugin(test.pluginName)
|
||||
if csiMigrationCompleteResult != test.csiMigrationCompleteResult {
|
||||
t.Errorf("Expected migration complete status of plugin: %v: %v does not match obtained migratability: %v", test.pluginName, test.csiMigrationCompleteResult, csiMigrationResult)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -80,10 +80,6 @@ func (plugin *downwardAPIPlugin) CanSupport(spec *volume.Spec) bool {
|
||||
return spec.Volume != nil && spec.Volume.DownwardAPI != nil
|
||||
}
|
||||
|
||||
func (plugin *downwardAPIPlugin) IsMigratedToCSI() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (plugin *downwardAPIPlugin) RequiresRemount() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -90,10 +90,6 @@ func (plugin *emptyDirPlugin) CanSupport(spec *volume.Spec) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (plugin *emptyDirPlugin) IsMigratedToCSI() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (plugin *emptyDirPlugin) RequiresRemount() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -88,10 +88,6 @@ func (plugin *fcPlugin) CanSupport(spec *volume.Spec) bool {
|
||||
return (spec.Volume != nil && spec.Volume.FC != nil) || (spec.PersistentVolume != nil && spec.PersistentVolume.Spec.FC != nil)
|
||||
}
|
||||
|
||||
func (plugin *fcPlugin) IsMigratedToCSI() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (plugin *fcPlugin) RequiresRemount() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -148,10 +148,6 @@ func (plugin *flexVolumePlugin) CanSupport(spec *volume.Spec) bool {
|
||||
return sourceDriver == plugin.driverName
|
||||
}
|
||||
|
||||
func (plugin *flexVolumePlugin) IsMigratedToCSI() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// RequiresRemount is part of the volume.VolumePlugin interface.
|
||||
func (plugin *flexVolumePlugin) RequiresRemount() bool {
|
||||
return false
|
||||
|
||||
@@ -107,10 +107,6 @@ func (p *flockerPlugin) CanSupport(spec *volume.Spec) bool {
|
||||
(spec.Volume != nil && spec.Volume.Flocker != nil)
|
||||
}
|
||||
|
||||
func (p *flockerPlugin) IsMigratedToCSI() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *flockerPlugin) RequiresRemount() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -100,11 +100,6 @@ func (plugin *gcePersistentDiskPlugin) CanSupport(spec *volume.Spec) bool {
|
||||
(spec.Volume != nil && spec.Volume.GCEPersistentDisk != nil)
|
||||
}
|
||||
|
||||
func (plugin *gcePersistentDiskPlugin) IsMigratedToCSI() bool {
|
||||
return utilfeature.DefaultFeatureGate.Enabled(features.CSIMigration) &&
|
||||
utilfeature.DefaultFeatureGate.Enabled(features.CSIMigrationGCE)
|
||||
}
|
||||
|
||||
func (plugin *gcePersistentDiskPlugin) RequiresRemount() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -77,10 +77,6 @@ func (plugin *gitRepoPlugin) CanSupport(spec *volume.Spec) bool {
|
||||
return spec.Volume != nil && spec.Volume.GitRepo != nil
|
||||
}
|
||||
|
||||
func (plugin *gitRepoPlugin) IsMigratedToCSI() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (plugin *gitRepoPlugin) RequiresRemount() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -118,10 +118,6 @@ func (plugin *glusterfsPlugin) CanSupport(spec *volume.Spec) bool {
|
||||
(spec.Volume != nil && spec.Volume.Glusterfs != nil)
|
||||
}
|
||||
|
||||
func (plugin *glusterfsPlugin) IsMigratedToCSI() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (plugin *glusterfsPlugin) RequiresRemount() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -84,10 +84,6 @@ func (plugin *hostPathPlugin) CanSupport(spec *volume.Spec) bool {
|
||||
(spec.Volume != nil && spec.Volume.HostPath != nil)
|
||||
}
|
||||
|
||||
func (plugin *hostPathPlugin) IsMigratedToCSI() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (plugin *hostPathPlugin) RequiresRemount() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -78,10 +78,6 @@ func (plugin *iscsiPlugin) CanSupport(spec *volume.Spec) bool {
|
||||
return (spec.Volume != nil && spec.Volume.ISCSI != nil) || (spec.PersistentVolume != nil && spec.PersistentVolume.Spec.ISCSI != nil)
|
||||
}
|
||||
|
||||
func (plugin *iscsiPlugin) IsMigratedToCSI() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (plugin *iscsiPlugin) RequiresRemount() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -83,10 +83,6 @@ func (plugin *localVolumePlugin) CanSupport(spec *volume.Spec) bool {
|
||||
return (spec.PersistentVolume != nil && spec.PersistentVolume.Spec.Local != nil)
|
||||
}
|
||||
|
||||
func (plugin *localVolumePlugin) IsMigratedToCSI() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (plugin *localVolumePlugin) RequiresRemount() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -89,10 +89,6 @@ func (plugin *nfsPlugin) CanSupport(spec *volume.Spec) bool {
|
||||
(spec.Volume != nil && spec.Volume.NFS != nil)
|
||||
}
|
||||
|
||||
func (plugin *nfsPlugin) IsMigratedToCSI() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (plugin *nfsPlugin) RequiresRemount() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -48,10 +48,6 @@ func (n *noopExpandableVolumePluginInstance) CanSupport(spec *Spec) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (n *noopExpandableVolumePluginInstance) IsMigratedToCSI() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (n *noopExpandableVolumePluginInstance) RequiresRemount() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -159,10 +159,6 @@ type VolumePlugin interface {
|
||||
// const.
|
||||
CanSupport(spec *Spec) bool
|
||||
|
||||
// IsMigratedToCSI tests whether a CSIDriver implements this plugin's
|
||||
// functionality
|
||||
IsMigratedToCSI() bool
|
||||
|
||||
// RequiresRemount returns true if this plugin requires mount calls to be
|
||||
// reexecuted. Atomically updating volumes, like Downward API, depend on
|
||||
// this to update the contents of the volume.
|
||||
@@ -693,39 +689,6 @@ func (pm *VolumePluginMgr) FindPluginBySpec(spec *Spec) (VolumePlugin, error) {
|
||||
return matches[0], nil
|
||||
}
|
||||
|
||||
// IsPluginMigratableBySpec looks for a plugin that can support a given volume
|
||||
// specification and whether that plugin is Migratable. If no plugins can
|
||||
// support or more than one plugin can support it, return error.
|
||||
func (pm *VolumePluginMgr) IsPluginMigratableBySpec(spec *Spec) (bool, error) {
|
||||
pm.mutex.Lock()
|
||||
defer pm.mutex.Unlock()
|
||||
|
||||
if spec == nil {
|
||||
return false, fmt.Errorf("could not find if plugin is migratable because volume spec is nil")
|
||||
}
|
||||
|
||||
matches := []VolumePlugin{}
|
||||
for _, v := range pm.plugins {
|
||||
if v.CanSupport(spec) {
|
||||
matches = append(matches, v)
|
||||
}
|
||||
}
|
||||
|
||||
if len(matches) == 0 {
|
||||
// Not a known plugin (flex) in which case it is not migratable
|
||||
return false, nil
|
||||
}
|
||||
if len(matches) > 1 {
|
||||
matchedPluginNames := []string{}
|
||||
for _, plugin := range matches {
|
||||
matchedPluginNames = append(matchedPluginNames, plugin.GetPluginName())
|
||||
}
|
||||
return false, fmt.Errorf("multiple volume plugins matched: %s", strings.Join(matchedPluginNames, ","))
|
||||
}
|
||||
|
||||
return matches[0].IsMigratedToCSI(), nil
|
||||
}
|
||||
|
||||
// FindPluginByName fetches a plugin by name or by legacy name. If no plugin
|
||||
// is found, returns error.
|
||||
func (pm *VolumePluginMgr) FindPluginByName(name string) (VolumePlugin, error) {
|
||||
|
||||
@@ -75,10 +75,6 @@ func (plugin *testPlugins) CanSupport(spec *Spec) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (plugin *testPlugins) IsMigratedToCSI() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (plugin *testPlugins) RequiresRemount() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -95,10 +95,6 @@ func (plugin *portworxVolumePlugin) CanSupport(spec *volume.Spec) bool {
|
||||
(spec.Volume != nil && spec.Volume.PortworxVolume != nil)
|
||||
}
|
||||
|
||||
func (plugin *portworxVolumePlugin) IsMigratedToCSI() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (plugin *portworxVolumePlugin) RequiresRemount() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -95,10 +95,6 @@ func (plugin *projectedPlugin) CanSupport(spec *volume.Spec) bool {
|
||||
return spec.Volume != nil && spec.Volume.Projected != nil
|
||||
}
|
||||
|
||||
func (plugin *projectedPlugin) IsMigratedToCSI() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (plugin *projectedPlugin) RequiresRemount() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -110,10 +110,6 @@ func (plugin *quobytePlugin) CanSupport(spec *volume.Spec) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (plugin *quobytePlugin) IsMigratedToCSI() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (plugin *quobytePlugin) RequiresRemount() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -108,10 +108,6 @@ func (plugin *rbdPlugin) CanSupport(spec *volume.Spec) bool {
|
||||
return (spec.Volume != nil && spec.Volume.RBD != nil) || (spec.PersistentVolume != nil && spec.PersistentVolume.Spec.RBD != nil)
|
||||
}
|
||||
|
||||
func (plugin *rbdPlugin) IsMigratedToCSI() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (plugin *rbdPlugin) RequiresRemount() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -72,10 +72,6 @@ func (p *sioPlugin) CanSupport(spec *volume.Spec) bool {
|
||||
(spec.Volume != nil && spec.Volume.ScaleIO != nil)
|
||||
}
|
||||
|
||||
func (p *sioPlugin) IsMigratedToCSI() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *sioPlugin) RequiresRemount() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -80,10 +80,6 @@ func (plugin *secretPlugin) CanSupport(spec *volume.Spec) bool {
|
||||
return spec.Volume != nil && spec.Volume.Secret != nil
|
||||
}
|
||||
|
||||
func (plugin *secretPlugin) IsMigratedToCSI() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (plugin *secretPlugin) RequiresRemount() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -91,10 +91,6 @@ func (plugin *storageosPlugin) CanSupport(spec *volume.Spec) bool {
|
||||
(spec.Volume != nil && spec.Volume.StorageOS != nil)
|
||||
}
|
||||
|
||||
func (plugin *storageosPlugin) IsMigratedToCSI() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (plugin *storageosPlugin) RequiresRemount() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -411,10 +411,6 @@ func (plugin *FakeVolumePlugin) CanSupport(spec *Spec) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (plugin *FakeVolumePlugin) IsMigratedToCSI() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (plugin *FakeVolumePlugin) RequiresRemount() bool {
|
||||
return false
|
||||
}
|
||||
@@ -653,10 +649,6 @@ func (f *FakeBasicVolumePlugin) CanSupport(spec *Spec) bool {
|
||||
return strings.HasPrefix(spec.Name(), f.GetPluginName())
|
||||
}
|
||||
|
||||
func (plugin *FakeBasicVolumePlugin) IsMigratedToCSI() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (f *FakeBasicVolumePlugin) ConstructVolumeSpec(ame, mountPath string) (*Spec, error) {
|
||||
return f.Plugin.ConstructVolumeSpec(ame, mountPath)
|
||||
}
|
||||
@@ -750,10 +742,6 @@ func (plugin *FakeFileVolumePlugin) CanSupport(spec *Spec) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (plugin *FakeFileVolumePlugin) IsMigratedToCSI() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (plugin *FakeFileVolumePlugin) RequiresRemount() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ go_library(
|
||||
"//pkg/kubelet/events:go_default_library",
|
||||
"//pkg/util/mount:go_default_library",
|
||||
"//pkg/volume:go_default_library",
|
||||
"//pkg/volume/csi:go_default_library",
|
||||
"//pkg/volume/util:go_default_library",
|
||||
"//pkg/volume/util/hostutil:go_default_library",
|
||||
"//pkg/volume/util/nestedpendingoperations:go_default_library",
|
||||
@@ -30,7 +29,6 @@ go_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/types:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/tools/record:go_default_library",
|
||||
@@ -48,10 +46,8 @@ go_test(
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/features:go_default_library",
|
||||
"//pkg/volume:go_default_library",
|
||||
"//pkg/volume/awsebs:go_default_library",
|
||||
"//pkg/volume/csi:go_default_library",
|
||||
"//pkg/volume/csi/testing:go_default_library",
|
||||
"//pkg/volume/gcepd:go_default_library",
|
||||
"//pkg/volume/testing:go_default_library",
|
||||
@@ -61,11 +57,8 @@ go_test(
|
||||
"//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/util/uuid:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/tools/record: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/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",
|
||||
|
||||
@@ -31,7 +31,6 @@ import (
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/kubernetes/pkg/util/mount"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
"k8s.io/kubernetes/pkg/volume/csi"
|
||||
"k8s.io/kubernetes/pkg/volume/util"
|
||||
"k8s.io/kubernetes/pkg/volume/util/hostutil"
|
||||
"k8s.io/kubernetes/pkg/volume/util/nestedpendingoperations"
|
||||
@@ -640,45 +639,25 @@ func (oe *operationExecutor) VerifyVolumesAreAttached(
|
||||
continue
|
||||
}
|
||||
|
||||
// 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.GetCSITranslator(), oe.operationGenerator.GetVolumePluginMgr(), volumeAttached.VolumeSpec, node)
|
||||
volumePlugin, err :=
|
||||
oe.operationGenerator.GetVolumePluginMgr().FindPluginBySpec(volumeAttached.VolumeSpec)
|
||||
if err != nil {
|
||||
klog.Errorf(volumeAttached.GenerateErrorDetailed("VolumesAreAttached.NodeUsingCSIPlugin failed", err).Error())
|
||||
klog.Errorf(
|
||||
"VolumesAreAttached.FindPluginBySpec failed for volume %q (spec.Name: %q) on node %q with error: %v",
|
||||
volumeAttached.VolumeName,
|
||||
volumeAttached.VolumeSpec.Name(),
|
||||
volumeAttached.NodeName,
|
||||
err)
|
||||
continue
|
||||
}
|
||||
|
||||
var volumePlugin volume.VolumePlugin
|
||||
if useCSIPlugin(oe.operationGenerator.GetCSITranslator(), oe.operationGenerator.GetVolumePluginMgr(), volumeAttached.VolumeSpec) && nu {
|
||||
// The volume represented by this spec is CSI and thus should be migrated
|
||||
volumePlugin, err = oe.operationGenerator.GetVolumePluginMgr().FindPluginByName(csi.CSIPluginName)
|
||||
if err != nil || volumePlugin == nil {
|
||||
klog.Errorf(
|
||||
"VolumesAreAttached.Name failed for volume %q (spec.Name: %q) on node %q with error: %v",
|
||||
volumeAttached.VolumeName,
|
||||
volumeAttached.VolumeSpec.Name(),
|
||||
volumeAttached.NodeName,
|
||||
err)
|
||||
continue
|
||||
}
|
||||
|
||||
csiSpec, err := translateSpec(oe.operationGenerator.GetCSITranslator(), volumeAttached.VolumeSpec)
|
||||
if err != nil {
|
||||
klog.Errorf(volumeAttached.GenerateErrorDetailed("VolumesAreAttached.TranslateSpec failed", err).Error())
|
||||
continue
|
||||
}
|
||||
volumeAttached.VolumeSpec = csiSpec
|
||||
} else {
|
||||
volumePlugin, err =
|
||||
oe.operationGenerator.GetVolumePluginMgr().FindPluginBySpec(volumeAttached.VolumeSpec)
|
||||
if err != nil || volumePlugin == nil {
|
||||
klog.Errorf(
|
||||
"VolumesAreAttached.FindPluginBySpec failed for volume %q (spec.Name: %q) on node %q with error: %v",
|
||||
volumeAttached.VolumeName,
|
||||
volumeAttached.VolumeSpec.Name(),
|
||||
volumeAttached.NodeName,
|
||||
err)
|
||||
continue
|
||||
}
|
||||
if volumePlugin == nil {
|
||||
// should never happen since FindPluginBySpec always returns error if volumePlugin = nil
|
||||
klog.Errorf(
|
||||
"Failed to find volume plugin for volume %q (spec.Name: %q) on node %q",
|
||||
volumeAttached.VolumeName,
|
||||
volumeAttached.VolumeSpec.Name(),
|
||||
volumeAttached.NodeName)
|
||||
continue
|
||||
}
|
||||
|
||||
pluginName := volumePlugin.GetPluginName()
|
||||
|
||||
@@ -27,7 +27,6 @@ import (
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/tools/record"
|
||||
@@ -37,7 +36,6 @@ import (
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
kevents "k8s.io/kubernetes/pkg/kubelet/events"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
"k8s.io/kubernetes/pkg/volume/csi"
|
||||
"k8s.io/kubernetes/pkg/volume/util"
|
||||
ioutil "k8s.io/kubernetes/pkg/volume/util"
|
||||
"k8s.io/kubernetes/pkg/volume/util/hostutil"
|
||||
@@ -170,38 +168,12 @@ func (og *operationGenerator) GenerateVolumesAreAttachedFunc(
|
||||
klog.Errorf("VerifyVolumesAreAttached.GenerateVolumesAreAttachedFunc: nil spec for volume %s", volumeAttached.VolumeName)
|
||||
continue
|
||||
}
|
||||
|
||||
// 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.translator, og.volumePluginMgr, volumeAttached.VolumeSpec, nodeName)
|
||||
if err != nil {
|
||||
klog.Errorf(volumeAttached.GenerateErrorDetailed("VolumesAreAttached.NodeUsingCSIPlugin failed", err).Error())
|
||||
volumePlugin, err :=
|
||||
og.volumePluginMgr.FindPluginBySpec(volumeAttached.VolumeSpec)
|
||||
if err != nil || volumePlugin == nil {
|
||||
klog.Errorf(volumeAttached.GenerateErrorDetailed("VolumesAreAttached.FindPluginBySpec failed", err).Error())
|
||||
continue
|
||||
}
|
||||
|
||||
var volumePlugin volume.VolumePlugin
|
||||
if useCSIPlugin(og.translator, og.volumePluginMgr, volumeAttached.VolumeSpec) && nu {
|
||||
// The volume represented by this spec is CSI and thus should be migrated
|
||||
volumePlugin, err = og.volumePluginMgr.FindPluginByName(csi.CSIPluginName)
|
||||
if err != nil || volumePlugin == nil {
|
||||
klog.Errorf(volumeAttached.GenerateErrorDetailed("VolumesAreAttached.FindPluginByName failed", err).Error())
|
||||
continue
|
||||
}
|
||||
|
||||
csiSpec, err := translateSpec(og.translator, volumeAttached.VolumeSpec)
|
||||
if err != nil {
|
||||
klog.Errorf(volumeAttached.GenerateErrorDetailed("VolumesAreAttached.TranslateSpec failed", err).Error())
|
||||
continue
|
||||
}
|
||||
volumeAttached.VolumeSpec = csiSpec
|
||||
} else {
|
||||
volumePlugin, err =
|
||||
og.volumePluginMgr.FindPluginBySpec(volumeAttached.VolumeSpec)
|
||||
if err != nil || volumePlugin == nil {
|
||||
klog.Errorf(volumeAttached.GenerateErrorDetailed("VolumesAreAttached.FindPluginBySpec failed", err).Error())
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
volumeSpecList, pluginExists := volumesPerPlugin[volumePlugin.GetPluginName()]
|
||||
if !pluginExists {
|
||||
volumeSpecList = []*volume.Spec{}
|
||||
@@ -345,34 +317,12 @@ func (og *operationGenerator) GenerateBulkVolumeVerifyFunc(
|
||||
func (og *operationGenerator) GenerateAttachVolumeFunc(
|
||||
volumeToAttach VolumeToAttach,
|
||||
actualStateOfWorld ActualStateOfWorldAttacherUpdater) volumetypes.GeneratedOperations {
|
||||
originalSpec := volumeToAttach.VolumeSpec
|
||||
|
||||
attachVolumeFunc := func() (error, error) {
|
||||
var attachableVolumePlugin volume.AttachableVolumePlugin
|
||||
|
||||
nu, err := nodeUsingCSIPlugin(og.translator, og.volumePluginMgr, volumeToAttach.VolumeSpec, volumeToAttach.NodeName)
|
||||
if err != nil {
|
||||
return volumeToAttach.GenerateError("AttachVolume.NodeUsingCSIPlugin failed", err)
|
||||
}
|
||||
|
||||
// useCSIPlugin will check both CSIMigration and the plugin specific feature gates
|
||||
if useCSIPlugin(og.translator, og.volumePluginMgr, volumeToAttach.VolumeSpec) && nu {
|
||||
// The volume represented by this spec is CSI and thus should be migrated
|
||||
attachableVolumePlugin, err = og.volumePluginMgr.FindAttachablePluginByName(csi.CSIPluginName)
|
||||
if err != nil || attachableVolumePlugin == nil {
|
||||
return volumeToAttach.GenerateError("AttachVolume.FindAttachablePluginByName failed", err)
|
||||
}
|
||||
|
||||
csiSpec, err := translateSpec(og.translator, volumeToAttach.VolumeSpec)
|
||||
if err != nil {
|
||||
return volumeToAttach.GenerateError("AttachVolume.TranslateSpec failed", err)
|
||||
}
|
||||
volumeToAttach.VolumeSpec = csiSpec
|
||||
} else {
|
||||
attachableVolumePlugin, err =
|
||||
og.volumePluginMgr.FindAttachablePluginBySpec(volumeToAttach.VolumeSpec)
|
||||
if err != nil || attachableVolumePlugin == nil {
|
||||
return volumeToAttach.GenerateError("AttachVolume.FindAttachablePluginBySpec failed", err)
|
||||
}
|
||||
attachableVolumePlugin, err :=
|
||||
og.volumePluginMgr.FindAttachablePluginBySpec(volumeToAttach.VolumeSpec)
|
||||
if err != nil || attachableVolumePlugin == nil {
|
||||
return volumeToAttach.GenerateError("AttachVolume.FindAttachablePluginBySpec failed", err)
|
||||
}
|
||||
|
||||
volumeAttacher, newAttacherErr := attachableVolumePlugin.NewAttacher()
|
||||
@@ -391,7 +341,7 @@ func (og *operationGenerator) GenerateAttachVolumeFunc(
|
||||
}
|
||||
addErr := actualStateOfWorld.MarkVolumeAsUncertain(
|
||||
v1.UniqueVolumeName(""),
|
||||
originalSpec,
|
||||
volumeToAttach.VolumeSpec,
|
||||
uncertainNode)
|
||||
if addErr != nil {
|
||||
klog.Errorf("AttachVolume.MarkVolumeAsUncertain fail to add the volume %q to actual state with %s", volumeToAttach.VolumeName, addErr)
|
||||
@@ -410,7 +360,7 @@ func (og *operationGenerator) GenerateAttachVolumeFunc(
|
||||
|
||||
// Update actual state of world
|
||||
addVolumeNodeErr := actualStateOfWorld.MarkVolumeAsAttached(
|
||||
v1.UniqueVolumeName(""), originalSpec, volumeToAttach.NodeName, devicePath)
|
||||
v1.UniqueVolumeName(""), volumeToAttach.VolumeSpec, volumeToAttach.NodeName, devicePath)
|
||||
if addVolumeNodeErr != nil {
|
||||
// On failure, return error. Caller will log and retry.
|
||||
return volumeToAttach.GenerateError("AttachVolume.MarkVolumeAsAttached failed", addVolumeNodeErr)
|
||||
@@ -428,30 +378,7 @@ func (og *operationGenerator) GenerateAttachVolumeFunc(
|
||||
}
|
||||
|
||||
attachableVolumePluginName := unknownAttachableVolumePlugin
|
||||
// TODO(dyzz) Ignoring this error means that if the plugin is migrated and
|
||||
// any transient error is encountered (API unavailable, driver not installed)
|
||||
// the operation will have it's metric registered with the in-tree plugin instead
|
||||
// of the CSI Driver we migrated to. Fixing this requires a larger refactor that
|
||||
// involves determining the plugin_name for the metric generating "CompleteFunc"
|
||||
// during the actual "OperationFunc" and not during this generation function
|
||||
|
||||
nu, err := nodeUsingCSIPlugin(og.translator, og.volumePluginMgr, volumeToAttach.VolumeSpec, volumeToAttach.NodeName)
|
||||
if err != nil {
|
||||
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
|
||||
// emitted show the correct (migrated) plugin
|
||||
if useCSIPlugin(og.translator, og.volumePluginMgr, volumeToAttach.VolumeSpec) && nu {
|
||||
csiSpec, err := translateSpec(og.translator, volumeToAttach.VolumeSpec)
|
||||
if err == nil {
|
||||
volumeToAttach.VolumeSpec = csiSpec
|
||||
}
|
||||
// If we have an error here we ignore it, the metric emitted will then be for the
|
||||
// in-tree plugin. This error case(skipped one) will also trigger an error
|
||||
// while the generated function is executed. And those errors will be handled during the execution of the generated
|
||||
// function with a back off policy.
|
||||
}
|
||||
// Get attacher plugin
|
||||
attachableVolumePlugin, err :=
|
||||
og.volumePluginMgr.FindAttachablePluginBySpec(volumeToAttach.VolumeSpec)
|
||||
@@ -489,32 +416,10 @@ func (og *operationGenerator) GenerateDetachVolumeFunc(
|
||||
var err error
|
||||
|
||||
if volumeToDetach.VolumeSpec != nil {
|
||||
// Get attacher plugin
|
||||
nu, err := nodeUsingCSIPlugin(og.translator, og.volumePluginMgr, volumeToDetach.VolumeSpec, volumeToDetach.NodeName)
|
||||
if err != nil {
|
||||
return volumetypes.GeneratedOperations{}, volumeToDetach.GenerateErrorDetailed("DetachVolume.NodeUsingCSIPlugin failed", err)
|
||||
}
|
||||
|
||||
// useCSIPlugin will check both CSIMigration and the plugin specific feature gate
|
||||
if useCSIPlugin(og.translator, og.volumePluginMgr, volumeToDetach.VolumeSpec) && nu {
|
||||
// The volume represented by this spec is CSI and thus should be migrated
|
||||
attachableVolumePlugin, err = og.volumePluginMgr.FindAttachablePluginByName(csi.CSIPluginName)
|
||||
if err != nil || attachableVolumePlugin == nil {
|
||||
return volumetypes.GeneratedOperations{}, volumeToDetach.GenerateErrorDetailed("DetachVolume.FindAttachablePluginBySpec failed", err)
|
||||
}
|
||||
|
||||
csiSpec, err := translateSpec(og.translator, volumeToDetach.VolumeSpec)
|
||||
if err != nil {
|
||||
return volumetypes.GeneratedOperations{}, volumeToDetach.GenerateErrorDetailed("DetachVolume.TranslateSpec failed", err)
|
||||
}
|
||||
|
||||
volumeToDetach.VolumeSpec = csiSpec
|
||||
} else {
|
||||
attachableVolumePlugin, err =
|
||||
og.volumePluginMgr.FindAttachablePluginBySpec(volumeToDetach.VolumeSpec)
|
||||
if err != nil || attachableVolumePlugin == nil {
|
||||
return volumetypes.GeneratedOperations{}, volumeToDetach.GenerateErrorDetailed("DetachVolume.FindAttachablePluginBySpec failed", err)
|
||||
}
|
||||
attachableVolumePlugin, err =
|
||||
og.volumePluginMgr.FindAttachablePluginBySpec(volumeToDetach.VolumeSpec)
|
||||
if err != nil || attachableVolumePlugin == nil {
|
||||
return volumetypes.GeneratedOperations{}, volumeToDetach.GenerateErrorDetailed("DetachVolume.FindAttachablePluginBySpec failed", err)
|
||||
}
|
||||
|
||||
volumeName, err =
|
||||
@@ -531,25 +436,9 @@ func (og *operationGenerator) GenerateDetachVolumeFunc(
|
||||
return volumetypes.GeneratedOperations{}, volumeToDetach.GenerateErrorDetailed("DetachVolume.SplitUniqueName failed", err)
|
||||
}
|
||||
|
||||
// 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.
|
||||
// Suggestions welcome...
|
||||
if og.translator.IsMigratableIntreePluginByName(pluginName) && utilfeature.DefaultFeatureGate.Enabled(features.CSIMigration) {
|
||||
// The volume represented by this spec is CSI and thus should be migrated
|
||||
attachableVolumePlugin, err = og.volumePluginMgr.FindAttachablePluginByName(csi.CSIPluginName)
|
||||
if err != nil || attachableVolumePlugin == nil {
|
||||
return volumetypes.GeneratedOperations{}, volumeToDetach.GenerateErrorDetailed("AttachVolume.FindAttachablePluginBySpec failed", err)
|
||||
}
|
||||
// volumeToDetach.VolumeName here is always the in-tree volume name
|
||||
// therefore a workaround is required. volumeToDetach.DevicePath
|
||||
// is the attachID which happens to be what volumeName is needed for in Detach.
|
||||
// Therefore we set volumeName to the attachID. And CSI Detach can detect and use that.
|
||||
volumeName = volumeToDetach.DevicePath
|
||||
} else {
|
||||
attachableVolumePlugin, err = og.volumePluginMgr.FindAttachablePluginByName(pluginName)
|
||||
if err != nil || attachableVolumePlugin == nil {
|
||||
return volumetypes.GeneratedOperations{}, volumeToDetach.GenerateErrorDetailed("DetachVolume.FindAttachablePluginByName failed", err)
|
||||
}
|
||||
attachableVolumePlugin, err = og.volumePluginMgr.FindAttachablePluginByName(pluginName)
|
||||
if err != nil || attachableVolumePlugin == nil {
|
||||
return volumetypes.GeneratedOperations{}, volumeToDetach.GenerateErrorDetailed("DetachVolume.FindAttachablePluginByName failed", err)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -600,21 +489,8 @@ func (og *operationGenerator) GenerateMountVolumeFunc(
|
||||
volumeToMount VolumeToMount,
|
||||
actualStateOfWorld ActualStateOfWorldMounterUpdater,
|
||||
isRemount bool) volumetypes.GeneratedOperations {
|
||||
// Get mounter plugin
|
||||
originalSpec := volumeToMount.VolumeSpec
|
||||
|
||||
volumePluginName := unknownVolumePlugin
|
||||
// Need to translate the spec here if the plugin is migrated so that the metrics
|
||||
// emitted show the correct (migrated) plugin
|
||||
if useCSIPlugin(og.translator, og.volumePluginMgr, volumeToMount.VolumeSpec) {
|
||||
csiSpec, err := translateSpec(og.translator, volumeToMount.VolumeSpec)
|
||||
if err == nil {
|
||||
volumeToMount.VolumeSpec = csiSpec
|
||||
}
|
||||
// If we have an error here we ignore it, the metric emitted will then be for the
|
||||
// in-tree plugin. This error case(skipped one) will also trigger an error
|
||||
// while the generated function is executed. And those errors will be handled during the execution of the generated
|
||||
// function with a back off policy.
|
||||
}
|
||||
volumePlugin, err :=
|
||||
og.volumePluginMgr.FindPluginBySpec(volumeToMount.VolumeSpec)
|
||||
if err == nil && volumePlugin != nil {
|
||||
@@ -622,16 +498,7 @@ func (og *operationGenerator) GenerateMountVolumeFunc(
|
||||
}
|
||||
|
||||
mountVolumeFunc := func() (error, error) {
|
||||
|
||||
// Get mounter plugin
|
||||
if useCSIPlugin(og.translator, og.volumePluginMgr, volumeToMount.VolumeSpec) {
|
||||
csiSpec, err := translateSpec(og.translator, volumeToMount.VolumeSpec)
|
||||
if err != nil {
|
||||
return volumeToMount.GenerateError("MountVolume.TranslateSpec failed", err)
|
||||
}
|
||||
volumeToMount.VolumeSpec = csiSpec
|
||||
}
|
||||
|
||||
volumePlugin, err := og.volumePluginMgr.FindPluginBySpec(volumeToMount.VolumeSpec)
|
||||
if err != nil || volumePlugin == nil {
|
||||
return volumeToMount.GenerateError("MountVolume.FindPluginBySpec failed", err)
|
||||
@@ -789,7 +656,7 @@ func (og *operationGenerator) GenerateMountVolumeFunc(
|
||||
nil,
|
||||
volumeToMount.OuterVolumeSpecName,
|
||||
volumeToMount.VolumeGidValue,
|
||||
originalSpec)
|
||||
volumeToMount.VolumeSpec)
|
||||
if markVolMountedErr != nil {
|
||||
// On failure, return error. Caller will log and retry.
|
||||
return volumeToMount.GenerateError("MountVolume.MarkVolumeAsMounted failed", markVolMountedErr)
|
||||
@@ -816,16 +683,8 @@ func (og *operationGenerator) GenerateUnmountVolumeFunc(
|
||||
volumeToUnmount MountedVolume,
|
||||
actualStateOfWorld ActualStateOfWorldMounterUpdater,
|
||||
podsDir string) (volumetypes.GeneratedOperations, error) {
|
||||
|
||||
var pluginName string
|
||||
if volumeToUnmount.VolumeSpec != nil && useCSIPlugin(og.translator, og.volumePluginMgr, volumeToUnmount.VolumeSpec) {
|
||||
pluginName = csi.CSIPluginName
|
||||
} else {
|
||||
pluginName = volumeToUnmount.PluginName
|
||||
}
|
||||
|
||||
// Get mountable plugin
|
||||
volumePlugin, err := og.volumePluginMgr.FindPluginByName(pluginName)
|
||||
volumePlugin, err := og.volumePluginMgr.FindPluginByName(volumeToUnmount.PluginName)
|
||||
if err != nil || volumePlugin == nil {
|
||||
return volumetypes.GeneratedOperations{}, volumeToUnmount.GenerateErrorDetailed("UnmountVolume.FindPluginByName failed", err)
|
||||
}
|
||||
@@ -884,22 +743,9 @@ func (og *operationGenerator) GenerateUnmountDeviceFunc(
|
||||
deviceToDetach AttachedVolume,
|
||||
actualStateOfWorld ActualStateOfWorldMounterUpdater,
|
||||
hostutil hostutil.HostUtils) (volumetypes.GeneratedOperations, error) {
|
||||
|
||||
var pluginName string
|
||||
if useCSIPlugin(og.translator, og.volumePluginMgr, deviceToDetach.VolumeSpec) {
|
||||
pluginName = csi.CSIPluginName
|
||||
csiSpec, err := translateSpec(og.translator, deviceToDetach.VolumeSpec)
|
||||
if err != nil {
|
||||
return volumetypes.GeneratedOperations{}, deviceToDetach.GenerateErrorDetailed("UnmountDevice.TranslateSpec failed", err)
|
||||
}
|
||||
deviceToDetach.VolumeSpec = csiSpec
|
||||
} else {
|
||||
pluginName = deviceToDetach.PluginName
|
||||
}
|
||||
|
||||
// Get DeviceMounter plugin
|
||||
deviceMountableVolumePlugin, err :=
|
||||
og.volumePluginMgr.FindDeviceMountablePluginByName(pluginName)
|
||||
og.volumePluginMgr.FindDeviceMountablePluginByName(deviceToDetach.PluginName)
|
||||
if err != nil || deviceMountableVolumePlugin == nil {
|
||||
return volumetypes.GeneratedOperations{}, deviceToDetach.GenerateErrorDetailed("UnmountDevice.FindDeviceMountablePluginByName failed", err)
|
||||
}
|
||||
@@ -986,17 +832,6 @@ func (og *operationGenerator) GenerateMapVolumeFunc(
|
||||
volumeToMount VolumeToMount,
|
||||
actualStateOfWorld ActualStateOfWorldMounterUpdater) (volumetypes.GeneratedOperations, error) {
|
||||
|
||||
originalSpec := volumeToMount.VolumeSpec
|
||||
// Translate to CSI spec if migration enabled
|
||||
if useCSIPlugin(og.translator, og.volumePluginMgr, originalSpec) {
|
||||
csiSpec, err := translateSpec(og.translator, originalSpec)
|
||||
if err != nil {
|
||||
return volumetypes.GeneratedOperations{}, volumeToMount.GenerateErrorDetailed("MapVolume.TranslateSpec failed", err)
|
||||
}
|
||||
|
||||
volumeToMount.VolumeSpec = csiSpec
|
||||
}
|
||||
|
||||
// Get block volume mapper plugin
|
||||
blockVolumePlugin, err :=
|
||||
og.volumePluginMgr.FindMapperPluginBySpec(volumeToMount.VolumeSpec)
|
||||
@@ -1156,7 +991,7 @@ func (og *operationGenerator) GenerateMapVolumeFunc(
|
||||
blockVolumeMapper,
|
||||
volumeToMount.OuterVolumeSpecName,
|
||||
volumeToMount.VolumeGidValue,
|
||||
originalSpec)
|
||||
volumeToMount.VolumeSpec)
|
||||
if markVolMountedErr != nil {
|
||||
// On failure, return error. Caller will log and retry.
|
||||
return volumeToMount.GenerateError("MapVolume.MarkVolumeAsMounted failed", markVolMountedErr)
|
||||
@@ -1187,32 +1022,12 @@ func (og *operationGenerator) GenerateUnmapVolumeFunc(
|
||||
volumeToUnmount MountedVolume,
|
||||
actualStateOfWorld ActualStateOfWorldMounterUpdater) (volumetypes.GeneratedOperations, error) {
|
||||
|
||||
var blockVolumePlugin volume.BlockVolumePlugin
|
||||
var err error
|
||||
// Translate to CSI spec if migration enabled
|
||||
// And get block volume unmapper plugin
|
||||
if volumeToUnmount.VolumeSpec != nil && useCSIPlugin(og.translator, og.volumePluginMgr, volumeToUnmount.VolumeSpec) {
|
||||
csiSpec, err := translateSpec(og.translator, volumeToUnmount.VolumeSpec)
|
||||
if err != nil {
|
||||
return volumetypes.GeneratedOperations{}, volumeToUnmount.GenerateErrorDetailed("UnmapVolume.TranslateSpec failed", err)
|
||||
}
|
||||
|
||||
volumeToUnmount.VolumeSpec = csiSpec
|
||||
|
||||
blockVolumePlugin, err =
|
||||
og.volumePluginMgr.FindMapperPluginByName(csi.CSIPluginName)
|
||||
if err != nil {
|
||||
return volumetypes.GeneratedOperations{}, volumeToUnmount.GenerateErrorDetailed("UnmapVolume.FindMapperPluginByName failed", err)
|
||||
}
|
||||
} else {
|
||||
blockVolumePlugin, err =
|
||||
og.volumePluginMgr.FindMapperPluginByName(volumeToUnmount.PluginName)
|
||||
if err != nil {
|
||||
return volumetypes.GeneratedOperations{}, volumeToUnmount.GenerateErrorDetailed("UnmapVolume.FindMapperPluginByName failed", err)
|
||||
}
|
||||
// Get block volume unmapper plugin
|
||||
blockVolumePlugin, err :=
|
||||
og.volumePluginMgr.FindMapperPluginByName(volumeToUnmount.PluginName)
|
||||
if err != nil {
|
||||
return volumetypes.GeneratedOperations{}, volumeToUnmount.GenerateErrorDetailed("UnmapVolume.FindMapperPluginByName failed", err)
|
||||
}
|
||||
|
||||
var blockVolumeUnmapper volume.BlockVolumeUnmapper
|
||||
if blockVolumePlugin == nil {
|
||||
return volumetypes.GeneratedOperations{}, volumeToUnmount.GenerateErrorDetailed("UnmapVolume.FindMapperPluginByName failed to find BlockVolumeMapper plugin. Volume plugin is nil.", nil)
|
||||
}
|
||||
@@ -1289,27 +1104,10 @@ func (og *operationGenerator) GenerateUnmapDeviceFunc(
|
||||
actualStateOfWorld ActualStateOfWorldMounterUpdater,
|
||||
hostutil hostutil.HostUtils) (volumetypes.GeneratedOperations, error) {
|
||||
|
||||
var blockVolumePlugin volume.BlockVolumePlugin
|
||||
var err error
|
||||
// Translate to CSI spec if migration enabled
|
||||
if useCSIPlugin(og.translator, og.volumePluginMgr, deviceToDetach.VolumeSpec) {
|
||||
csiSpec, err := translateSpec(og.translator, deviceToDetach.VolumeSpec)
|
||||
if err != nil {
|
||||
return volumetypes.GeneratedOperations{}, deviceToDetach.GenerateErrorDetailed("UnmapDevice.TranslateSpec failed", err)
|
||||
}
|
||||
|
||||
deviceToDetach.VolumeSpec = csiSpec
|
||||
blockVolumePlugin, err =
|
||||
og.volumePluginMgr.FindMapperPluginByName(csi.CSIPluginName)
|
||||
if err != nil {
|
||||
return volumetypes.GeneratedOperations{}, deviceToDetach.GenerateErrorDetailed("UnmapDevice.FindMapperPluginByName failed", err)
|
||||
}
|
||||
} else {
|
||||
blockVolumePlugin, err =
|
||||
og.volumePluginMgr.FindMapperPluginByName(deviceToDetach.PluginName)
|
||||
if err != nil {
|
||||
return volumetypes.GeneratedOperations{}, deviceToDetach.GenerateErrorDetailed("UnmapDevice.FindMapperPluginByName failed", err)
|
||||
}
|
||||
blockVolumePlugin, err :=
|
||||
og.volumePluginMgr.FindMapperPluginByName(deviceToDetach.PluginName)
|
||||
if err != nil {
|
||||
return volumetypes.GeneratedOperations{}, deviceToDetach.GenerateErrorDetailed("UnmapDevice.FindMapperPluginByName failed", err)
|
||||
}
|
||||
|
||||
if blockVolumePlugin == nil {
|
||||
@@ -1586,22 +1384,13 @@ func (og *operationGenerator) GenerateExpandInUseVolumeFunc(
|
||||
volumeToMount VolumeToMount,
|
||||
actualStateOfWorld ActualStateOfWorldMounterUpdater) (volumetypes.GeneratedOperations, error) {
|
||||
|
||||
fsResizeFunc := func() (error, error) {
|
||||
// Need to translate the spec here if the plugin is migrated so that the metrics
|
||||
// emitted show the correct (migrated) plugin
|
||||
if useCSIPlugin(og.translator, og.volumePluginMgr, volumeToMount.VolumeSpec) {
|
||||
csiSpec, err := translateSpec(og.translator, volumeToMount.VolumeSpec)
|
||||
if err != nil {
|
||||
return volumeToMount.GenerateError("NodeExpandVolume.translateSpec failed", err)
|
||||
}
|
||||
volumeToMount.VolumeSpec = csiSpec
|
||||
}
|
||||
volumePlugin, err :=
|
||||
og.volumePluginMgr.FindPluginBySpec(volumeToMount.VolumeSpec)
|
||||
if err != nil || volumePlugin == nil {
|
||||
return volumeToMount.GenerateError("NodeExpandVolume.FindPluginBySpec failed", err)
|
||||
}
|
||||
volumePlugin, err :=
|
||||
og.volumePluginMgr.FindPluginBySpec(volumeToMount.VolumeSpec)
|
||||
if err != nil || volumePlugin == nil {
|
||||
return volumetypes.GeneratedOperations{}, volumeToMount.GenerateErrorDetailed("NodeExpandVolume.FindPluginBySpec failed", err)
|
||||
}
|
||||
|
||||
fsResizeFunc := func() (error, error) {
|
||||
var resizeDone bool
|
||||
var simpleErr, detailedErr error
|
||||
resizeOptions := volume.NodeResizeOptions{
|
||||
@@ -1659,24 +1448,6 @@ func (og *operationGenerator) GenerateExpandInUseVolumeFunc(
|
||||
}
|
||||
}
|
||||
|
||||
// Need to translate the spec here if the plugin is migrated so that the metrics
|
||||
// emitted show the correct (migrated) plugin
|
||||
if useCSIPlugin(og.translator, og.volumePluginMgr, volumeToMount.VolumeSpec) {
|
||||
csiSpec, err := translateSpec(og.translator, volumeToMount.VolumeSpec)
|
||||
if err == nil {
|
||||
volumeToMount.VolumeSpec = csiSpec
|
||||
}
|
||||
// If we have an error here we ignore it, the metric emitted will then be for the
|
||||
// in-tree plugin. This error case(skipped one) will also trigger an error
|
||||
// while the generated function is executed. And those errors will be handled during the execution of the generated
|
||||
// function with a back off policy.
|
||||
}
|
||||
volumePlugin, err :=
|
||||
og.volumePluginMgr.FindPluginBySpec(volumeToMount.VolumeSpec)
|
||||
if err != nil || volumePlugin == nil {
|
||||
return volumetypes.GeneratedOperations{}, volumeToMount.GenerateErrorDetailed("NodeExpandVolume.FindPluginBySpec failed", err)
|
||||
}
|
||||
|
||||
return volumetypes.GeneratedOperations{
|
||||
OperationName: "volume_fs_resize",
|
||||
OperationFunc: fsResizeFunc,
|
||||
@@ -1822,134 +1593,3 @@ func isDeviceOpened(deviceToDetach AttachedVolume, hostUtil hostutil.HostUtils)
|
||||
}
|
||||
return deviceOpened, nil
|
||||
}
|
||||
|
||||
func useCSIPlugin(tr InTreeToCSITranslator, vpm *volume.VolumePluginMgr, spec *volume.Spec) bool {
|
||||
// TODO(#75146) Check whether the driver is installed as well so that
|
||||
// we can throw a better error when the driver is not installed.
|
||||
// The error should be of the approximate form:
|
||||
// fmt.Errorf("in-tree plugin %s is migrated on node %s but driver %s is not installed", pluginName, string(nodeName), driverName)
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.CSIMigration) {
|
||||
return false
|
||||
}
|
||||
if tr.IsPVMigratable(spec.PersistentVolume) || tr.IsInlineMigratable(spec.Volume) {
|
||||
migratable, err := vpm.IsPluginMigratableBySpec(spec)
|
||||
if err == nil && migratable {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func nodeUsingCSIPlugin(tr InTreeToCSITranslator, vpm *volume.VolumePluginMgr, spec *volume.Spec, nodeName types.NodeName) (bool, error) {
|
||||
migratable, err := vpm.IsPluginMigratableBySpec(spec)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.CSIMigration) ||
|
||||
!utilfeature.DefaultFeatureGate.Enabled(features.CSINodeInfo) ||
|
||||
!migratable {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
if len(nodeName) == 0 {
|
||||
return false, goerrors.New("nodeName is empty")
|
||||
}
|
||||
|
||||
kubeClient := vpm.Host.GetKubeClient()
|
||||
if kubeClient == nil {
|
||||
// Don't handle the controller/kubelet version skew check and fallback
|
||||
// to just checking the feature gates. This can happen if
|
||||
// we are in a standalone (headless) Kubelet
|
||||
return true, nil
|
||||
}
|
||||
|
||||
adcHost, ok := vpm.Host.(volume.AttachDetachVolumeHost)
|
||||
if !ok {
|
||||
// Don't handle the controller/kubelet version skew check and fallback
|
||||
// to just checking the feature gates. This can happen if
|
||||
// "enableControllerAttachDetach" is set to true on kubelet
|
||||
return true, nil
|
||||
}
|
||||
|
||||
if adcHost.CSINodeLister() == nil {
|
||||
return false, goerrors.New("could not find CSINodeLister in attachDetachController")
|
||||
}
|
||||
|
||||
csiNode, err := adcHost.CSINodeLister().Get(string(nodeName))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
ann := csiNode.GetAnnotations()
|
||||
if ann == nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
var mpaSet sets.String
|
||||
mpa := ann[v1.MigratedPluginsAnnotationKey]
|
||||
tok := strings.Split(mpa, ",")
|
||||
if len(mpa) == 0 {
|
||||
mpaSet = sets.NewString()
|
||||
} else {
|
||||
mpaSet = sets.NewString(tok...)
|
||||
}
|
||||
|
||||
pluginName, err := tr.GetInTreePluginNameFromSpec(spec.PersistentVolume, spec.Volume)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if len(pluginName) == 0 {
|
||||
// Could not find a plugin name from translation directory, assume not translated
|
||||
return false, nil
|
||||
}
|
||||
|
||||
isMigratedOnNode := mpaSet.Has(pluginName)
|
||||
|
||||
if isMigratedOnNode {
|
||||
installed := false
|
||||
driverName, err := tr.GetCSINameFromInTreeName(pluginName)
|
||||
if err != nil {
|
||||
return isMigratedOnNode, err
|
||||
}
|
||||
for _, driver := range csiNode.Spec.Drivers {
|
||||
if driver.Name == driverName {
|
||||
installed = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !installed {
|
||||
return true, fmt.Errorf("in-tree plugin %s is migrated on node %s but driver %s is not installed", pluginName, string(nodeName), driverName)
|
||||
}
|
||||
}
|
||||
|
||||
return isMigratedOnNode, nil
|
||||
|
||||
}
|
||||
|
||||
func translateSpec(tr InTreeToCSITranslator, spec *volume.Spec) (*volume.Spec, error) {
|
||||
var csiPV *v1.PersistentVolume
|
||||
var err error
|
||||
inlineVolume := false
|
||||
if spec.PersistentVolume != nil {
|
||||
// TranslateInTreePVToCSI will create a new PV
|
||||
csiPV, err = tr.TranslateInTreePVToCSI(spec.PersistentVolume)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to translate in tree pv to CSI: %v", err)
|
||||
}
|
||||
} else if spec.Volume != nil {
|
||||
// TranslateInTreeInlineVolumeToCSI will create a new PV
|
||||
csiPV, err = tr.TranslateInTreeInlineVolumeToCSI(spec.Volume)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to translate in tree inline volume to CSI: %v", err)
|
||||
}
|
||||
inlineVolume = true
|
||||
} else {
|
||||
return &volume.Spec{}, goerrors.New("not a valid volume spec")
|
||||
}
|
||||
return &volume.Spec{
|
||||
PersistentVolume: csiPV,
|
||||
ReadOnly: spec.ReadOnly,
|
||||
InlineVolumeSpecForCSIMigration: inlineVolume,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -17,24 +17,18 @@ limitations under the License.
|
||||
package operationexecutor
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/prometheus/client_model/go"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/uuid"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
fakeclient "k8s.io/client-go/kubernetes/fake"
|
||||
"k8s.io/client-go/tools/record"
|
||||
"k8s.io/component-base/featuregate"
|
||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||
"k8s.io/component-base/metrics/legacyregistry"
|
||||
"k8s.io/csi-translation-lib/plugins"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
"k8s.io/kubernetes/pkg/volume/awsebs"
|
||||
"k8s.io/kubernetes/pkg/volume/csi"
|
||||
csitesting "k8s.io/kubernetes/pkg/volume/csi/testing"
|
||||
"k8s.io/kubernetes/pkg/volume/gcepd"
|
||||
volumetesting "k8s.io/kubernetes/pkg/volume/testing"
|
||||
@@ -46,21 +40,16 @@ import (
|
||||
// generated func so there is no need to test the plugin name that's used inside generated function
|
||||
func TestOperationGenerator_GenerateUnmapVolumeFunc_PluginName(t *testing.T) {
|
||||
type testcase struct {
|
||||
name string
|
||||
isCsiMigrationEnabled bool
|
||||
pluginName string
|
||||
csiDriverName string
|
||||
csiMigrationFeature featuregate.Feature
|
||||
pvSpec v1.PersistentVolumeSpec
|
||||
probVolumePlugins []volume.VolumePlugin
|
||||
name string
|
||||
pluginName string
|
||||
pvSpec v1.PersistentVolumeSpec
|
||||
probVolumePlugins []volume.VolumePlugin
|
||||
}
|
||||
|
||||
testcases := []testcase{
|
||||
{
|
||||
name: "gce pd plugin: csi migration disabled",
|
||||
isCsiMigrationEnabled: false,
|
||||
pluginName: plugins.GCEPDInTreePluginName,
|
||||
csiMigrationFeature: features.CSIMigrationGCE,
|
||||
name: "gce pd plugin: csi migration disabled",
|
||||
pluginName: plugins.GCEPDInTreePluginName,
|
||||
pvSpec: v1.PersistentVolumeSpec{
|
||||
PersistentVolumeSource: v1.PersistentVolumeSource{
|
||||
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{},
|
||||
@@ -68,34 +57,8 @@ func TestOperationGenerator_GenerateUnmapVolumeFunc_PluginName(t *testing.T) {
|
||||
probVolumePlugins: gcepd.ProbeVolumePlugins(),
|
||||
},
|
||||
{
|
||||
name: "gce pd plugin: csi migration enabled",
|
||||
isCsiMigrationEnabled: true,
|
||||
pluginName: plugins.GCEPDInTreePluginName,
|
||||
csiDriverName: plugins.GCEPDDriverName,
|
||||
csiMigrationFeature: features.CSIMigrationGCE,
|
||||
pvSpec: v1.PersistentVolumeSpec{
|
||||
PersistentVolumeSource: v1.PersistentVolumeSource{
|
||||
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{},
|
||||
}},
|
||||
probVolumePlugins: gcepd.ProbeVolumePlugins(),
|
||||
},
|
||||
{
|
||||
name: "aws ebs plugin: csi migration disabled",
|
||||
isCsiMigrationEnabled: false,
|
||||
pluginName: plugins.AWSEBSInTreePluginName,
|
||||
csiMigrationFeature: features.CSIMigrationAWS,
|
||||
pvSpec: v1.PersistentVolumeSpec{
|
||||
PersistentVolumeSource: v1.PersistentVolumeSource{
|
||||
AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{},
|
||||
}},
|
||||
probVolumePlugins: awsebs.ProbeVolumePlugins(),
|
||||
},
|
||||
{
|
||||
name: "aws ebs plugin: csi migration enabled",
|
||||
isCsiMigrationEnabled: true,
|
||||
pluginName: plugins.AWSEBSInTreePluginName,
|
||||
csiDriverName: plugins.AWSEBSDriverName,
|
||||
csiMigrationFeature: features.CSIMigrationAWS,
|
||||
name: "aws ebs plugin: csi migration disabled",
|
||||
pluginName: plugins.AWSEBSInTreePluginName,
|
||||
pvSpec: v1.PersistentVolumeSpec{
|
||||
PersistentVolumeSource: v1.PersistentVolumeSource{
|
||||
AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{},
|
||||
@@ -106,13 +69,7 @@ func TestOperationGenerator_GenerateUnmapVolumeFunc_PluginName(t *testing.T) {
|
||||
|
||||
for _, tc := range testcases {
|
||||
expectedPluginName := tc.pluginName
|
||||
if tc.isCsiMigrationEnabled {
|
||||
expectedPluginName = fmt.Sprintf("%s:%s", csi.CSIPluginName, tc.csiDriverName)
|
||||
}
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIMigration, tc.isCsiMigrationEnabled)()
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, tc.csiMigrationFeature, tc.isCsiMigrationEnabled)()
|
||||
|
||||
volumePluginMgr, plugin, tmpDir := initTestPlugins(t, tc.probVolumePlugins, tc.pluginName)
|
||||
volumePluginMgr, tmpDir := initTestPlugins(t, tc.probVolumePlugins, tc.pluginName)
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
operationGenerator := getTestOperationGenerator(volumePluginMgr)
|
||||
@@ -120,21 +77,6 @@ func TestOperationGenerator_GenerateUnmapVolumeFunc_PluginName(t *testing.T) {
|
||||
pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{UID: types.UID(string(uuid.NewUUID()))}}
|
||||
volumeToUnmount := getTestVolumeToUnmount(pod, tc.pvSpec, tc.pluginName)
|
||||
|
||||
if tc.isCsiMigrationEnabled {
|
||||
// GenerateUnmapVolumeFunc call blockVolumePlugin.NewBlockVolumeUnmapper and when the plugin is csi,
|
||||
// csi plugin looks a file that contains some information about the volume,
|
||||
// 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.
|
||||
csiSpec, err := translateSpec(operationGenerator.GetCSITranslator(), volumeToUnmount.VolumeSpec)
|
||||
if err != nil {
|
||||
t.Fatalf("Can't translate volume to CSI")
|
||||
}
|
||||
_, mapperError := (*plugin).(volume.BlockVolumePlugin).NewBlockVolumeMapper(csiSpec, pod, volume.VolumeOptions{})
|
||||
if mapperError != nil {
|
||||
t.Fatalf("mapper error: %v\n", mapperError)
|
||||
}
|
||||
}
|
||||
|
||||
unmapVolumeFunc, e := operationGenerator.GenerateUnmapVolumeFunc(volumeToUnmount, nil)
|
||||
if e != nil {
|
||||
t.Fatalf("Error occurred while generating unmapVolumeFunc: %v", e)
|
||||
@@ -238,9 +180,9 @@ func getMetricFamily(metricFamilyName string) *io_prometheus_client.MetricFamily
|
||||
return nil
|
||||
}
|
||||
|
||||
func initTestPlugins(t *testing.T, plugs []volume.VolumePlugin, pluginName string) (*volume.VolumePluginMgr, *volume.VolumePlugin, string) {
|
||||
func initTestPlugins(t *testing.T, plugs []volume.VolumePlugin, pluginName string) (*volume.VolumePluginMgr, string) {
|
||||
client := fakeclient.NewSimpleClientset()
|
||||
pluginMgr, csiPlugin, tmpDir := csitesting.NewTestPlugin(t, client)
|
||||
pluginMgr, _, tmpDir := csitesting.NewTestPlugin(t, client)
|
||||
|
||||
err := pluginMgr.InitPlugins(plugs, nil, pluginMgr.Host)
|
||||
if err != nil {
|
||||
@@ -252,5 +194,5 @@ func initTestPlugins(t *testing.T, plugs []volume.VolumePlugin, pluginName strin
|
||||
t.Fatalf("Can't find the plugin by name: %s", pluginName)
|
||||
}
|
||||
|
||||
return pluginMgr, csiPlugin, tmpDir
|
||||
return pluginMgr, tmpDir
|
||||
}
|
||||
|
||||
@@ -85,10 +85,6 @@ func (plugin *vsphereVolumePlugin) CanSupport(spec *volume.Spec) bool {
|
||||
(spec.Volume != nil && spec.Volume.VsphereVolume != nil)
|
||||
}
|
||||
|
||||
func (plugin *vsphereVolumePlugin) IsMigratedToCSI() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (plugin *vsphereVolumePlugin) RequiresRemount() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user