...

Source file src/k8s.io/kubernetes/pkg/volume/testing/testing.go

Documentation: k8s.io/kubernetes/pkg/volume/testing

     1  /*
     2  Copyright 2014 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package testing
    18  
    19  import (
    20  	"fmt"
    21  	"os"
    22  	"path/filepath"
    23  	goruntime "runtime"
    24  	"strings"
    25  	"sync"
    26  	"testing"
    27  	"time"
    28  
    29  	"k8s.io/klog/v2"
    30  
    31  	"k8s.io/apimachinery/pkg/util/sets"
    32  	"k8s.io/utils/exec"
    33  	testingexec "k8s.io/utils/exec/testing"
    34  	utilstrings "k8s.io/utils/strings"
    35  
    36  	v1 "k8s.io/api/core/v1"
    37  	"k8s.io/apimachinery/pkg/api/resource"
    38  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    39  	"k8s.io/apimachinery/pkg/types"
    40  	"k8s.io/apimachinery/pkg/util/uuid"
    41  	utiltesting "k8s.io/client-go/util/testing"
    42  	"k8s.io/kubernetes/pkg/volume"
    43  	"k8s.io/kubernetes/pkg/volume/util"
    44  	"k8s.io/kubernetes/pkg/volume/util/recyclerclient"
    45  	volumetypes "k8s.io/kubernetes/pkg/volume/util/types"
    46  	"k8s.io/kubernetes/pkg/volume/util/volumepathhandler"
    47  )
    48  
    49  const (
    50  	// A hook specified in storage class to indicate it's provisioning
    51  	// is expected to fail.
    52  	ExpectProvisionFailureKey = "expect-provision-failure"
    53  	// The node is marked as uncertain. The attach operation will fail and return timeout error
    54  	// for the first attach call. The following call will return successfully.
    55  	UncertainAttachNode = "uncertain-attach-node"
    56  	// The detach operation will keep failing on the node.
    57  	FailDetachNode = "fail-detach-node"
    58  	// The node is marked as timeout. The attach operation will always fail and return timeout error
    59  	// but the operation is actually succeeded.
    60  	TimeoutAttachNode = "timeout-attach-node"
    61  	// The node is marked as multi-attach which means it is allowed to attach the volume to multiple nodes.
    62  	MultiAttachNode = "multi-attach-node"
    63  	// TimeoutOnSetupVolumeName will cause Setup call to timeout but volume will finish mounting.
    64  	TimeoutOnSetupVolumeName = "timeout-setup-volume"
    65  	// FailOnSetupVolumeName will cause setup call to fail
    66  	FailOnSetupVolumeName = "fail-setup-volume"
    67  	//TimeoutAndFailOnSetupVolumeName will first timeout and then fail the setup
    68  	TimeoutAndFailOnSetupVolumeName = "timeout-and-fail-setup-volume"
    69  	// SuccessAndTimeoutSetupVolumeName will cause first mount operation to succeed but subsequent attempts to timeout
    70  	SuccessAndTimeoutSetupVolumeName = "success-and-timeout-setup-volume-name"
    71  	// SuccessAndFailOnSetupVolumeName will cause first mount operation to succeed but subsequent attempts to fail
    72  	SuccessAndFailOnSetupVolumeName = "success-and-failed-setup-device-name"
    73  
    74  	// TimeoutOnMountDeviceVolumeName will cause MountDevice call to timeout but Setup will finish.
    75  	TimeoutOnMountDeviceVolumeName = "timeout-mount-device-volume"
    76  	// TimeoutAndFailOnMountDeviceVolumeName will cause first MountDevice call to timeout but second call will fail
    77  	TimeoutAndFailOnMountDeviceVolumeName = "timeout-and-fail-mount-device-name"
    78  	// FailMountDeviceVolumeName will cause MountDevice operation on volume to fail
    79  	FailMountDeviceVolumeName = "fail-mount-device-volume-name"
    80  	// SuccessAndTimeoutDeviceName will cause first mount operation to succeed but subsequent attempts to timeout
    81  	SuccessAndTimeoutDeviceName = "success-and-timeout-device-name"
    82  	// SuccessAndFailOnMountDeviceName will cause first mount operation to succeed but subsequent attempts to fail
    83  	SuccessAndFailOnMountDeviceName = "success-and-failed-mount-device-name"
    84  
    85  	// FailWithInUseVolumeName will cause NodeExpandVolume to result in FailedPrecondition error
    86  	FailWithInUseVolumeName       = "fail-expansion-in-use"
    87  	FailWithUnSupportedVolumeName = "fail-expansion-unsupported"
    88  
    89  	FailVolumeExpansion = "fail-expansion-test"
    90  
    91  	AlwaysFailNodeExpansion = "always-fail-node-expansion"
    92  
    93  	deviceNotMounted     = "deviceNotMounted"
    94  	deviceMountUncertain = "deviceMountUncertain"
    95  	deviceMounted        = "deviceMounted"
    96  
    97  	volumeNotMounted     = "volumeNotMounted"
    98  	volumeMountUncertain = "volumeMountUncertain"
    99  	volumeMounted        = "volumeMounted"
   100  
   101  	FailNewMounter = "fail-new-mounter"
   102  )
   103  
   104  // CommandScript is used to pre-configure a command that will be executed and
   105  // optionally set it's output (stdout and stderr combined) and return code.
   106  type CommandScript struct {
   107  	// Cmd is the command to execute, e.g. "ls"
   108  	Cmd string
   109  	// Args is a slice of arguments to pass to the command, e.g. "-a"
   110  	Args []string
   111  	// Output is the combined stdout and stderr of the command to return
   112  	Output string
   113  	// ReturnCode is the exit code for the command. Setting this to non-zero will
   114  	// cause the command to return an error with this exit code set.
   115  	ReturnCode int
   116  }
   117  
   118  // ScriptCommands configures fe, the FakeExec, to have a pre-configured list of
   119  // commands to expect. Calling more commands using fe than those scripted will
   120  // result in a panic. By default, the fe does not enforce command argument checking
   121  // or order -- if you have given an Output to the command, the first command scripted
   122  // will return its output on the first command call, even if the command called is
   123  // different than the one scripted. This is mostly useful to make sure that the
   124  // right number of commands were called. If you want to check the exact commands
   125  // and arguments were called, set fe.ExectOrder to true.
   126  func ScriptCommands(fe *testingexec.FakeExec, scripts []CommandScript) {
   127  	fe.DisableScripts = false
   128  	for _, script := range scripts {
   129  		fakeCmd := &testingexec.FakeCmd{}
   130  		cmdAction := makeFakeCmd(fakeCmd, script.Cmd, script.Args...)
   131  		outputAction := makeFakeOutput(script.Output, script.ReturnCode)
   132  		fakeCmd.CombinedOutputScript = append(fakeCmd.CombinedOutputScript, outputAction)
   133  		fe.CommandScript = append(fe.CommandScript, cmdAction)
   134  	}
   135  }
   136  
   137  func makeFakeCmd(fakeCmd *testingexec.FakeCmd, cmd string, args ...string) testingexec.FakeCommandAction {
   138  	fc := fakeCmd
   139  	c := cmd
   140  	a := args
   141  	return func(cmd string, args ...string) exec.Cmd {
   142  		command := testingexec.InitFakeCmd(fc, c, a...)
   143  		return command
   144  	}
   145  }
   146  
   147  func makeFakeOutput(output string, rc int) testingexec.FakeAction {
   148  	o := output
   149  	var e error
   150  	if rc != 0 {
   151  		e = testingexec.FakeExitError{Status: rc}
   152  	}
   153  	return func() ([]byte, []byte, error) {
   154  		return []byte(o), nil, e
   155  	}
   156  }
   157  
   158  func ProbeVolumePlugins(config volume.VolumeConfig) []volume.VolumePlugin {
   159  	if _, ok := config.OtherAttributes["fake-property"]; ok {
   160  		return []volume.VolumePlugin{
   161  			&FakeVolumePlugin{
   162  				PluginName: "fake-plugin",
   163  				Host:       nil,
   164  				// SomeFakeProperty: config.OtherAttributes["fake-property"] -- string, may require parsing by plugin
   165  			},
   166  		}
   167  	}
   168  	return []volume.VolumePlugin{&FakeVolumePlugin{PluginName: "fake-plugin"}}
   169  }
   170  
   171  // FakeVolumePlugin is useful for testing.  It tries to be a fully compliant
   172  // plugin, but all it does is make empty directories.
   173  // Use as:
   174  //
   175  //	volume.RegisterPlugin(&FakePlugin{"fake-name"})
   176  type FakeVolumePlugin struct {
   177  	sync.RWMutex
   178  	PluginName             string
   179  	Host                   volume.VolumeHost
   180  	Config                 volume.VolumeConfig
   181  	LastProvisionerOptions volume.VolumeOptions
   182  	NewAttacherCallCount   int
   183  	NewDetacherCallCount   int
   184  	NodeExpandCallCount    int
   185  	VolumeLimits           map[string]int64
   186  	VolumeLimitsError      error
   187  	LimitKey               string
   188  	ProvisionDelaySeconds  int
   189  	SupportsRemount        bool
   190  	SupportsSELinux        bool
   191  	DisableNodeExpansion   bool
   192  	CanSupportFn           func(*volume.Spec) bool
   193  
   194  	// default to false which means it is attachable by default
   195  	NonAttachable bool
   196  
   197  	// Add callbacks as needed
   198  	WaitForAttachHook func(spec *volume.Spec, devicePath string, pod *v1.Pod, spectimeout time.Duration) (string, error)
   199  	UnmountDeviceHook func(globalMountPath string) error
   200  
   201  	Mounters             []*FakeVolume
   202  	Unmounters           []*FakeVolume
   203  	Attachers            []*FakeVolume
   204  	Detachers            []*FakeVolume
   205  	BlockVolumeMappers   []*FakeVolume
   206  	BlockVolumeUnmappers []*FakeVolume
   207  }
   208  
   209  var _ volume.VolumePlugin = &FakeVolumePlugin{}
   210  var _ volume.BlockVolumePlugin = &FakeVolumePlugin{}
   211  var _ volume.RecyclableVolumePlugin = &FakeVolumePlugin{}
   212  var _ volume.DeletableVolumePlugin = &FakeVolumePlugin{}
   213  var _ volume.ProvisionableVolumePlugin = &FakeVolumePlugin{}
   214  var _ volume.AttachableVolumePlugin = &FakeVolumePlugin{}
   215  var _ volume.VolumePluginWithAttachLimits = &FakeVolumePlugin{}
   216  var _ volume.DeviceMountableVolumePlugin = &FakeVolumePlugin{}
   217  var _ volume.NodeExpandableVolumePlugin = &FakeVolumePlugin{}
   218  
   219  func (plugin *FakeVolumePlugin) getFakeVolume(list *[]*FakeVolume) *FakeVolume {
   220  	if list != nil {
   221  		volumeList := *list
   222  		if len(volumeList) > 0 {
   223  			volume := volumeList[0]
   224  			volume.Lock()
   225  			defer volume.Unlock()
   226  			volume.WaitForAttachHook = plugin.WaitForAttachHook
   227  			volume.UnmountDeviceHook = plugin.UnmountDeviceHook
   228  			return volume
   229  		}
   230  	}
   231  	volume := &FakeVolume{
   232  		WaitForAttachHook: plugin.WaitForAttachHook,
   233  		UnmountDeviceHook: plugin.UnmountDeviceHook,
   234  	}
   235  	volume.VolumesAttached = make(map[string]sets.String)
   236  	volume.DeviceMountState = make(map[string]string)
   237  	volume.VolumeMountState = make(map[string]string)
   238  	if list != nil {
   239  		*list = append(*list, volume)
   240  	}
   241  	return volume
   242  }
   243  
   244  func (plugin *FakeVolumePlugin) Init(host volume.VolumeHost) error {
   245  	plugin.Lock()
   246  	defer plugin.Unlock()
   247  	plugin.Host = host
   248  	return nil
   249  }
   250  
   251  func (plugin *FakeVolumePlugin) GetPluginName() string {
   252  	plugin.RLock()
   253  	defer plugin.RUnlock()
   254  	return plugin.PluginName
   255  }
   256  
   257  func (plugin *FakeVolumePlugin) GetVolumeName(spec *volume.Spec) (string, error) {
   258  	var volumeName string
   259  	if spec.Volume != nil && spec.Volume.GCEPersistentDisk != nil {
   260  		volumeName = spec.Volume.GCEPersistentDisk.PDName
   261  	} else if spec.Volume != nil && spec.Volume.RBD != nil {
   262  		volumeName = spec.Volume.RBD.RBDImage
   263  	} else if spec.PersistentVolume != nil &&
   264  		spec.PersistentVolume.Spec.GCEPersistentDisk != nil {
   265  		volumeName = spec.PersistentVolume.Spec.GCEPersistentDisk.PDName
   266  	} else if spec.PersistentVolume != nil &&
   267  		spec.PersistentVolume.Spec.RBD != nil {
   268  		volumeName = spec.PersistentVolume.Spec.RBD.RBDImage
   269  	} else if spec.Volume != nil && spec.Volume.CSI != nil {
   270  		volumeName = spec.Volume.CSI.Driver
   271  	}
   272  	if volumeName == "" {
   273  		volumeName = spec.Name()
   274  	}
   275  	return volumeName, nil
   276  }
   277  
   278  func (plugin *FakeVolumePlugin) CanSupport(spec *volume.Spec) bool {
   279  	if plugin.CanSupportFn != nil {
   280  		return plugin.CanSupportFn(spec)
   281  	}
   282  
   283  	return true
   284  }
   285  
   286  func (plugin *FakeVolumePlugin) RequiresRemount(spec *volume.Spec) bool {
   287  	return plugin.SupportsRemount
   288  }
   289  
   290  func (plugin *FakeVolumePlugin) SupportsMountOption() bool {
   291  	return true
   292  }
   293  
   294  func (plugin *FakeVolumePlugin) SupportsBulkVolumeVerification() bool {
   295  	return false
   296  }
   297  
   298  func (plugin *FakeVolumePlugin) SupportsSELinuxContextMount(spec *volume.Spec) (bool, error) {
   299  	return plugin.SupportsSELinux, nil
   300  }
   301  
   302  func (plugin *FakeVolumePlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, opts volume.VolumeOptions) (volume.Mounter, error) {
   303  	plugin.Lock()
   304  	defer plugin.Unlock()
   305  	if spec.Name() == FailNewMounter {
   306  		return nil, fmt.Errorf("AlwaysFailNewMounter")
   307  	}
   308  	fakeVolume := plugin.getFakeVolume(&plugin.Mounters)
   309  	fakeVolume.Lock()
   310  	defer fakeVolume.Unlock()
   311  	fakeVolume.PodUID = pod.UID
   312  	fakeVolume.VolName = spec.Name()
   313  	fakeVolume.Plugin = plugin
   314  	fakeVolume.MetricsNil = volume.MetricsNil{}
   315  	return fakeVolume, nil
   316  }
   317  
   318  func (plugin *FakeVolumePlugin) GetMounters() (Mounters []*FakeVolume) {
   319  	plugin.RLock()
   320  	defer plugin.RUnlock()
   321  	return plugin.Mounters
   322  }
   323  
   324  func (plugin *FakeVolumePlugin) NewUnmounter(volName string, podUID types.UID) (volume.Unmounter, error) {
   325  	plugin.Lock()
   326  	defer plugin.Unlock()
   327  	fakeVolume := plugin.getFakeVolume(&plugin.Unmounters)
   328  	fakeVolume.Lock()
   329  	defer fakeVolume.Unlock()
   330  	fakeVolume.PodUID = podUID
   331  	fakeVolume.VolName = volName
   332  	fakeVolume.Plugin = plugin
   333  	fakeVolume.MetricsNil = volume.MetricsNil{}
   334  	return fakeVolume, nil
   335  }
   336  
   337  func (plugin *FakeVolumePlugin) GetUnmounters() (Unmounters []*FakeVolume) {
   338  	plugin.RLock()
   339  	defer plugin.RUnlock()
   340  	return plugin.Unmounters
   341  }
   342  
   343  // Block volume support
   344  func (plugin *FakeVolumePlugin) NewBlockVolumeMapper(spec *volume.Spec, pod *v1.Pod, opts volume.VolumeOptions) (volume.BlockVolumeMapper, error) {
   345  	plugin.Lock()
   346  	defer plugin.Unlock()
   347  	volume := plugin.getFakeVolume(&plugin.BlockVolumeMappers)
   348  	volume.Lock()
   349  	defer volume.Unlock()
   350  	if pod != nil {
   351  		volume.PodUID = pod.UID
   352  	}
   353  	volume.VolName = spec.Name()
   354  	volume.Plugin = plugin
   355  	return volume, nil
   356  }
   357  
   358  // Block volume support
   359  func (plugin *FakeVolumePlugin) GetBlockVolumeMapper() (BlockVolumeMappers []*FakeVolume) {
   360  	plugin.RLock()
   361  	defer plugin.RUnlock()
   362  	return plugin.BlockVolumeMappers
   363  }
   364  
   365  // Block volume support
   366  func (plugin *FakeVolumePlugin) NewBlockVolumeUnmapper(volName string, podUID types.UID) (volume.BlockVolumeUnmapper, error) {
   367  	plugin.Lock()
   368  	defer plugin.Unlock()
   369  	volume := plugin.getFakeVolume(&plugin.BlockVolumeUnmappers)
   370  	volume.Lock()
   371  	defer volume.Unlock()
   372  	volume.PodUID = podUID
   373  	volume.VolName = volName
   374  	volume.Plugin = plugin
   375  	return volume, nil
   376  }
   377  
   378  // Block volume support
   379  func (plugin *FakeVolumePlugin) GetBlockVolumeUnmapper() (BlockVolumeUnmappers []*FakeVolume) {
   380  	plugin.RLock()
   381  	defer plugin.RUnlock()
   382  	return plugin.BlockVolumeUnmappers
   383  }
   384  
   385  func (plugin *FakeVolumePlugin) NewAttacher() (volume.Attacher, error) {
   386  	plugin.Lock()
   387  	defer plugin.Unlock()
   388  	plugin.NewAttacherCallCount = plugin.NewAttacherCallCount + 1
   389  	return plugin.getFakeVolume(&plugin.Attachers), nil
   390  }
   391  
   392  func (plugin *FakeVolumePlugin) NewDeviceMounter() (volume.DeviceMounter, error) {
   393  	return plugin.NewAttacher()
   394  }
   395  
   396  func (plugin *FakeVolumePlugin) GetAttachers() (Attachers []*FakeVolume) {
   397  	plugin.RLock()
   398  	defer plugin.RUnlock()
   399  	return plugin.Attachers
   400  }
   401  
   402  func (plugin *FakeVolumePlugin) GetNewAttacherCallCount() int {
   403  	plugin.RLock()
   404  	defer plugin.RUnlock()
   405  	return plugin.NewAttacherCallCount
   406  }
   407  
   408  func (plugin *FakeVolumePlugin) NewDetacher() (volume.Detacher, error) {
   409  	plugin.Lock()
   410  	defer plugin.Unlock()
   411  	plugin.NewDetacherCallCount = plugin.NewDetacherCallCount + 1
   412  	detacher := plugin.getFakeVolume(&plugin.Detachers)
   413  	attacherList := plugin.Attachers
   414  	if len(attacherList) > 0 {
   415  		detacherList := plugin.Detachers
   416  		if len(detacherList) > 0 {
   417  			detacherList[0].VolumesAttached = attacherList[0].VolumesAttached
   418  		}
   419  
   420  	}
   421  	return detacher, nil
   422  }
   423  
   424  func (plugin *FakeVolumePlugin) NewDeviceUnmounter() (volume.DeviceUnmounter, error) {
   425  	return plugin.NewDetacher()
   426  }
   427  
   428  func (plugin *FakeVolumePlugin) GetDetachers() (Detachers []*FakeVolume) {
   429  	plugin.RLock()
   430  	defer plugin.RUnlock()
   431  	return plugin.Detachers
   432  }
   433  
   434  func (plugin *FakeVolumePlugin) GetNewDetacherCallCount() int {
   435  	plugin.RLock()
   436  	defer plugin.RUnlock()
   437  	return plugin.NewDetacherCallCount
   438  }
   439  
   440  func (plugin *FakeVolumePlugin) CanAttach(spec *volume.Spec) (bool, error) {
   441  	return !plugin.NonAttachable, nil
   442  }
   443  
   444  func (plugin *FakeVolumePlugin) CanDeviceMount(spec *volume.Spec) (bool, error) {
   445  	return true, nil
   446  }
   447  
   448  func (plugin *FakeVolumePlugin) Recycle(pvName string, spec *volume.Spec, eventRecorder recyclerclient.RecycleEventRecorder) error {
   449  	return nil
   450  }
   451  
   452  func (plugin *FakeVolumePlugin) NewDeleter(logger klog.Logger, spec *volume.Spec) (volume.Deleter, error) {
   453  	return &FakeDeleter{"/attributesTransferredFromSpec", volume.MetricsNil{}}, nil
   454  }
   455  
   456  func (plugin *FakeVolumePlugin) NewProvisioner(logger klog.Logger, options volume.VolumeOptions) (volume.Provisioner, error) {
   457  	plugin.Lock()
   458  	defer plugin.Unlock()
   459  	plugin.LastProvisionerOptions = options
   460  	return &FakeProvisioner{options, plugin.Host, plugin.ProvisionDelaySeconds}, nil
   461  }
   462  
   463  func (plugin *FakeVolumePlugin) GetAccessModes() []v1.PersistentVolumeAccessMode {
   464  	return []v1.PersistentVolumeAccessMode{}
   465  }
   466  
   467  func (plugin *FakeVolumePlugin) ConstructVolumeSpec(volumeName, mountPath string) (volume.ReconstructedVolume, error) {
   468  	return volume.ReconstructedVolume{
   469  		Spec: &volume.Spec{
   470  			Volume: &v1.Volume{
   471  				Name: volumeName,
   472  			},
   473  		},
   474  	}, nil
   475  }
   476  
   477  // Block volume support
   478  func (plugin *FakeVolumePlugin) ConstructBlockVolumeSpec(podUID types.UID, volumeName, mountPath string) (*volume.Spec, error) {
   479  	return &volume.Spec{
   480  		Volume: &v1.Volume{
   481  			Name: volumeName,
   482  		},
   483  	}, nil
   484  }
   485  
   486  func (plugin *FakeVolumePlugin) GetDeviceMountRefs(deviceMountPath string) ([]string, error) {
   487  	return []string{}, nil
   488  }
   489  
   490  // Expandable volume support
   491  func (plugin *FakeVolumePlugin) ExpandVolumeDevice(spec *volume.Spec, newSize resource.Quantity, oldSize resource.Quantity) (resource.Quantity, error) {
   492  	return resource.Quantity{}, nil
   493  }
   494  
   495  func (plugin *FakeVolumePlugin) RequiresFSResize() bool {
   496  	return !plugin.DisableNodeExpansion
   497  }
   498  
   499  func (plugin *FakeVolumePlugin) NodeExpand(resizeOptions volume.NodeResizeOptions) (bool, error) {
   500  	plugin.NodeExpandCallCount++
   501  	if resizeOptions.VolumeSpec.Name() == FailWithInUseVolumeName {
   502  		return false, volumetypes.NewFailedPreconditionError("volume-in-use")
   503  	}
   504  	if resizeOptions.VolumeSpec.Name() == FailWithUnSupportedVolumeName {
   505  		return false, volumetypes.NewOperationNotSupportedError("volume-unsupported")
   506  	}
   507  
   508  	if resizeOptions.VolumeSpec.Name() == AlwaysFailNodeExpansion {
   509  		return false, fmt.Errorf("test failure: NodeExpand")
   510  	}
   511  
   512  	if resizeOptions.VolumeSpec.Name() == FailVolumeExpansion {
   513  		return false, fmt.Errorf("fail volume expansion for volume: %s", FailVolumeExpansion)
   514  	}
   515  	return true, nil
   516  }
   517  
   518  func (plugin *FakeVolumePlugin) GetVolumeLimits() (map[string]int64, error) {
   519  	return plugin.VolumeLimits, plugin.VolumeLimitsError
   520  }
   521  
   522  func (plugin *FakeVolumePlugin) VolumeLimitKey(spec *volume.Spec) string {
   523  	return plugin.LimitKey
   524  }
   525  
   526  // FakeBasicVolumePlugin implements a basic volume plugin. It wrappers on
   527  // FakeVolumePlugin but implements VolumePlugin interface only.
   528  // It is useful to test logic involving plugin interfaces.
   529  type FakeBasicVolumePlugin struct {
   530  	Plugin FakeVolumePlugin
   531  }
   532  
   533  func (f *FakeBasicVolumePlugin) GetPluginName() string {
   534  	return f.Plugin.GetPluginName()
   535  }
   536  
   537  func (f *FakeBasicVolumePlugin) GetVolumeName(spec *volume.Spec) (string, error) {
   538  	return f.Plugin.GetVolumeName(spec)
   539  }
   540  
   541  // CanSupport tests whether the plugin supports a given volume specification by
   542  // testing volume spec name begins with plugin name or not.
   543  // This is useful to choose plugin by volume in testing.
   544  func (f *FakeBasicVolumePlugin) CanSupport(spec *volume.Spec) bool {
   545  	return strings.HasPrefix(spec.Name(), f.GetPluginName())
   546  }
   547  
   548  func (f *FakeBasicVolumePlugin) ConstructVolumeSpec(ame, mountPath string) (volume.ReconstructedVolume, error) {
   549  	return f.Plugin.ConstructVolumeSpec(ame, mountPath)
   550  }
   551  
   552  func (f *FakeBasicVolumePlugin) Init(ost volume.VolumeHost) error {
   553  	return f.Plugin.Init(ost)
   554  }
   555  
   556  func (f *FakeBasicVolumePlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, opts volume.VolumeOptions) (volume.Mounter, error) {
   557  	return f.Plugin.NewMounter(spec, pod, opts)
   558  }
   559  
   560  func (f *FakeBasicVolumePlugin) NewUnmounter(volName string, podUID types.UID) (volume.Unmounter, error) {
   561  	return f.Plugin.NewUnmounter(volName, podUID)
   562  }
   563  
   564  func (f *FakeBasicVolumePlugin) RequiresRemount(spec *volume.Spec) bool {
   565  	return f.Plugin.RequiresRemount(spec)
   566  }
   567  
   568  func (f *FakeBasicVolumePlugin) SupportsBulkVolumeVerification() bool {
   569  	return f.Plugin.SupportsBulkVolumeVerification()
   570  }
   571  
   572  func (f *FakeBasicVolumePlugin) SupportsSELinuxContextMount(spec *volume.Spec) (bool, error) {
   573  	return f.Plugin.SupportsSELinuxContextMount(spec)
   574  }
   575  
   576  func (f *FakeBasicVolumePlugin) SupportsMountOption() bool {
   577  	return f.Plugin.SupportsMountOption()
   578  }
   579  
   580  var _ volume.VolumePlugin = &FakeBasicVolumePlugin{}
   581  
   582  // FakeDeviceMountableVolumePlugin implements an device mountable plugin based on FakeBasicVolumePlugin.
   583  type FakeDeviceMountableVolumePlugin struct {
   584  	FakeBasicVolumePlugin
   585  }
   586  
   587  func (f *FakeDeviceMountableVolumePlugin) CanDeviceMount(spec *volume.Spec) (bool, error) {
   588  	return true, nil
   589  }
   590  
   591  func (f *FakeDeviceMountableVolumePlugin) NewDeviceMounter() (volume.DeviceMounter, error) {
   592  	return f.Plugin.NewDeviceMounter()
   593  }
   594  
   595  func (f *FakeDeviceMountableVolumePlugin) NewDeviceUnmounter() (volume.DeviceUnmounter, error) {
   596  	return f.Plugin.NewDeviceUnmounter()
   597  }
   598  
   599  func (f *FakeDeviceMountableVolumePlugin) GetDeviceMountRefs(deviceMountPath string) ([]string, error) {
   600  	return f.Plugin.GetDeviceMountRefs(deviceMountPath)
   601  }
   602  
   603  var _ volume.VolumePlugin = &FakeDeviceMountableVolumePlugin{}
   604  var _ volume.DeviceMountableVolumePlugin = &FakeDeviceMountableVolumePlugin{}
   605  
   606  // FakeAttachableVolumePlugin implements an attachable plugin based on FakeDeviceMountableVolumePlugin.
   607  type FakeAttachableVolumePlugin struct {
   608  	FakeDeviceMountableVolumePlugin
   609  }
   610  
   611  func (f *FakeAttachableVolumePlugin) NewAttacher() (volume.Attacher, error) {
   612  	return f.Plugin.NewAttacher()
   613  }
   614  
   615  func (f *FakeAttachableVolumePlugin) NewDetacher() (volume.Detacher, error) {
   616  	return f.Plugin.NewDetacher()
   617  }
   618  
   619  func (f *FakeAttachableVolumePlugin) CanAttach(spec *volume.Spec) (bool, error) {
   620  	return true, nil
   621  }
   622  
   623  var _ volume.VolumePlugin = &FakeAttachableVolumePlugin{}
   624  var _ volume.AttachableVolumePlugin = &FakeAttachableVolumePlugin{}
   625  
   626  type FakeFileVolumePlugin struct {
   627  }
   628  
   629  func (plugin *FakeFileVolumePlugin) Init(host volume.VolumeHost) error {
   630  	return nil
   631  }
   632  
   633  func (plugin *FakeFileVolumePlugin) GetPluginName() string {
   634  	return "fake-file-plugin"
   635  }
   636  
   637  func (plugin *FakeFileVolumePlugin) GetVolumeName(spec *volume.Spec) (string, error) {
   638  	return "", nil
   639  }
   640  
   641  func (plugin *FakeFileVolumePlugin) CanSupport(spec *volume.Spec) bool {
   642  	return true
   643  }
   644  
   645  func (plugin *FakeFileVolumePlugin) RequiresRemount(spec *volume.Spec) bool {
   646  	return false
   647  }
   648  
   649  func (plugin *FakeFileVolumePlugin) SupportsMountOption() bool {
   650  	return false
   651  }
   652  
   653  func (plugin *FakeFileVolumePlugin) SupportsBulkVolumeVerification() bool {
   654  	return false
   655  }
   656  
   657  func (plugin *FakeFileVolumePlugin) SupportsSELinuxContextMount(spec *volume.Spec) (bool, error) {
   658  	return false, nil
   659  }
   660  
   661  func (plugin *FakeFileVolumePlugin) NewMounter(spec *volume.Spec, podRef *v1.Pod, opts volume.VolumeOptions) (volume.Mounter, error) {
   662  	return nil, nil
   663  }
   664  
   665  func (plugin *FakeFileVolumePlugin) NewUnmounter(name string, podUID types.UID) (volume.Unmounter, error) {
   666  	return nil, nil
   667  }
   668  
   669  func (plugin *FakeFileVolumePlugin) ConstructVolumeSpec(volumeName, mountPath string) (volume.ReconstructedVolume, error) {
   670  	return volume.ReconstructedVolume{}, nil
   671  }
   672  
   673  func NewFakeFileVolumePlugin() []volume.VolumePlugin {
   674  	return []volume.VolumePlugin{&FakeFileVolumePlugin{}}
   675  }
   676  
   677  type FakeVolume struct {
   678  	sync.RWMutex
   679  	PodUID  types.UID
   680  	VolName string
   681  	Plugin  *FakeVolumePlugin
   682  	volume.MetricsNil
   683  	VolumesAttached  map[string]sets.String
   684  	DeviceMountState map[string]string
   685  	VolumeMountState map[string]string
   686  
   687  	// Add callbacks as needed
   688  	WaitForAttachHook func(spec *volume.Spec, devicePath string, pod *v1.Pod, spectimeout time.Duration) (string, error)
   689  	UnmountDeviceHook func(globalMountPath string) error
   690  
   691  	SetUpCallCount              int
   692  	TearDownCallCount           int
   693  	AttachCallCount             int
   694  	DetachCallCount             int
   695  	WaitForAttachCallCount      int
   696  	MountDeviceCallCount        int
   697  	UnmountDeviceCallCount      int
   698  	GetDeviceMountPathCallCount int
   699  	SetUpDeviceCallCount        int
   700  	TearDownDeviceCallCount     int
   701  	MapPodDeviceCallCount       int
   702  	UnmapPodDeviceCallCount     int
   703  	GlobalMapPathCallCount      int
   704  	PodDeviceMapPathCallCount   int
   705  }
   706  
   707  func getUniqueVolumeName(spec *volume.Spec) (string, error) {
   708  	var volumeName string
   709  	if spec.Volume != nil && spec.Volume.GCEPersistentDisk != nil {
   710  		volumeName = spec.Volume.GCEPersistentDisk.PDName
   711  	} else if spec.Volume != nil && spec.Volume.RBD != nil {
   712  		volumeName = spec.Volume.RBD.RBDImage
   713  	} else if spec.PersistentVolume != nil &&
   714  		spec.PersistentVolume.Spec.GCEPersistentDisk != nil {
   715  		volumeName = spec.PersistentVolume.Spec.GCEPersistentDisk.PDName
   716  	} else if spec.PersistentVolume != nil &&
   717  		spec.PersistentVolume.Spec.RBD != nil {
   718  		volumeName = spec.PersistentVolume.Spec.RBD.RBDImage
   719  	}
   720  	if volumeName == "" {
   721  		volumeName = spec.Name()
   722  	}
   723  	return volumeName, nil
   724  }
   725  
   726  func (_ *FakeVolume) GetAttributes() volume.Attributes {
   727  	return volume.Attributes{
   728  		ReadOnly:       false,
   729  		Managed:        true,
   730  		SELinuxRelabel: true,
   731  	}
   732  }
   733  
   734  func (fv *FakeVolume) SetUp(mounterArgs volume.MounterArgs) error {
   735  	fv.Lock()
   736  	defer fv.Unlock()
   737  	err := fv.setupInternal(mounterArgs)
   738  	fv.SetUpCallCount++
   739  	return err
   740  }
   741  
   742  func (fv *FakeVolume) setupInternal(mounterArgs volume.MounterArgs) error {
   743  	if fv.VolName == TimeoutOnSetupVolumeName {
   744  		fv.VolumeMountState[fv.VolName] = volumeMountUncertain
   745  		return volumetypes.NewUncertainProgressError("time out on setup")
   746  	}
   747  
   748  	if fv.VolName == FailOnSetupVolumeName {
   749  		fv.VolumeMountState[fv.VolName] = volumeNotMounted
   750  		return fmt.Errorf("mounting volume failed")
   751  	}
   752  
   753  	if fv.VolName == TimeoutAndFailOnSetupVolumeName {
   754  		_, ok := fv.VolumeMountState[fv.VolName]
   755  		if !ok {
   756  			fv.VolumeMountState[fv.VolName] = volumeMountUncertain
   757  			return volumetypes.NewUncertainProgressError("time out on setup")
   758  		}
   759  		fv.VolumeMountState[fv.VolName] = volumeNotMounted
   760  		return fmt.Errorf("mounting volume failed")
   761  
   762  	}
   763  
   764  	if fv.VolName == SuccessAndFailOnSetupVolumeName {
   765  		_, ok := fv.VolumeMountState[fv.VolName]
   766  		if ok {
   767  			fv.VolumeMountState[fv.VolName] = volumeNotMounted
   768  			return fmt.Errorf("mounting volume failed")
   769  		}
   770  	}
   771  
   772  	if fv.VolName == SuccessAndTimeoutSetupVolumeName {
   773  		_, ok := fv.VolumeMountState[fv.VolName]
   774  		if ok {
   775  			fv.VolumeMountState[fv.VolName] = volumeMountUncertain
   776  			return volumetypes.NewUncertainProgressError("time out on setup")
   777  		}
   778  	}
   779  
   780  	fv.VolumeMountState[fv.VolName] = volumeNotMounted
   781  	return fv.SetUpAt(fv.getPath(), mounterArgs)
   782  }
   783  
   784  func (fv *FakeVolume) GetSetUpCallCount() int {
   785  	fv.RLock()
   786  	defer fv.RUnlock()
   787  	return fv.SetUpCallCount
   788  }
   789  
   790  func (fv *FakeVolume) SetUpAt(dir string, mounterArgs volume.MounterArgs) error {
   791  	return os.MkdirAll(dir, 0750)
   792  }
   793  
   794  func (fv *FakeVolume) GetPath() string {
   795  	fv.RLock()
   796  	defer fv.RUnlock()
   797  	return fv.getPath()
   798  }
   799  
   800  func (fv *FakeVolume) getPath() string {
   801  	return filepath.Join(fv.Plugin.Host.GetPodVolumeDir(fv.PodUID, utilstrings.EscapeQualifiedName(fv.Plugin.PluginName), fv.VolName))
   802  }
   803  
   804  func (fv *FakeVolume) TearDown() error {
   805  	fv.Lock()
   806  	defer fv.Unlock()
   807  	fv.TearDownCallCount++
   808  	return fv.TearDownAt(fv.getPath())
   809  }
   810  
   811  func (fv *FakeVolume) GetTearDownCallCount() int {
   812  	fv.RLock()
   813  	defer fv.RUnlock()
   814  	return fv.TearDownCallCount
   815  }
   816  
   817  func (fv *FakeVolume) TearDownAt(dir string) error {
   818  	return os.RemoveAll(dir)
   819  }
   820  
   821  // Block volume support
   822  func (fv *FakeVolume) SetUpDevice() (string, error) {
   823  	fv.Lock()
   824  	defer fv.Unlock()
   825  	if fv.VolName == TimeoutOnMountDeviceVolumeName {
   826  		fv.DeviceMountState[fv.VolName] = deviceMountUncertain
   827  		return "", volumetypes.NewUncertainProgressError("mount failed")
   828  	}
   829  	if fv.VolName == FailMountDeviceVolumeName {
   830  		fv.DeviceMountState[fv.VolName] = deviceNotMounted
   831  		return "", fmt.Errorf("error mapping disk: %s", fv.VolName)
   832  	}
   833  
   834  	if fv.VolName == TimeoutAndFailOnMountDeviceVolumeName {
   835  		_, ok := fv.DeviceMountState[fv.VolName]
   836  		if !ok {
   837  			fv.DeviceMountState[fv.VolName] = deviceMountUncertain
   838  			return "", volumetypes.NewUncertainProgressError("timed out mounting error")
   839  		}
   840  		fv.DeviceMountState[fv.VolName] = deviceNotMounted
   841  		return "", fmt.Errorf("error mapping disk: %s", fv.VolName)
   842  	}
   843  
   844  	if fv.VolName == SuccessAndTimeoutDeviceName {
   845  		_, ok := fv.DeviceMountState[fv.VolName]
   846  		if ok {
   847  			fv.DeviceMountState[fv.VolName] = deviceMountUncertain
   848  			return "", volumetypes.NewUncertainProgressError("error mounting state")
   849  		}
   850  	}
   851  	if fv.VolName == SuccessAndFailOnMountDeviceName {
   852  		_, ok := fv.DeviceMountState[fv.VolName]
   853  		if ok {
   854  			return "", fmt.Errorf("error mapping disk: %s", fv.VolName)
   855  		}
   856  	}
   857  
   858  	fv.DeviceMountState[fv.VolName] = deviceMounted
   859  	fv.SetUpDeviceCallCount++
   860  
   861  	return "", nil
   862  }
   863  
   864  func (fv *FakeVolume) GetStagingPath() string {
   865  	return filepath.Join(fv.Plugin.Host.GetVolumeDevicePluginDir(utilstrings.EscapeQualifiedName(fv.Plugin.PluginName)), "staging", fv.VolName)
   866  }
   867  
   868  // Block volume support
   869  func (fv *FakeVolume) GetSetUpDeviceCallCount() int {
   870  	fv.RLock()
   871  	defer fv.RUnlock()
   872  	return fv.SetUpDeviceCallCount
   873  }
   874  
   875  // Block volume support
   876  func (fv *FakeVolume) GetGlobalMapPath(spec *volume.Spec) (string, error) {
   877  	fv.Lock()
   878  	defer fv.Unlock()
   879  	fv.GlobalMapPathCallCount++
   880  	return fv.getGlobalMapPath()
   881  }
   882  
   883  // Block volume support
   884  func (fv *FakeVolume) getGlobalMapPath() (string, error) {
   885  	return filepath.Join(fv.Plugin.Host.GetVolumeDevicePluginDir(utilstrings.EscapeQualifiedName(fv.Plugin.PluginName)), "pluginDependentPath"), nil
   886  }
   887  
   888  // Block volume support
   889  func (fv *FakeVolume) GetGlobalMapPathCallCount() int {
   890  	fv.RLock()
   891  	defer fv.RUnlock()
   892  	return fv.GlobalMapPathCallCount
   893  }
   894  
   895  // Block volume support
   896  func (fv *FakeVolume) GetPodDeviceMapPath() (string, string) {
   897  	fv.RLock()
   898  	defer fv.RUnlock()
   899  	fv.PodDeviceMapPathCallCount++
   900  	return fv.getPodDeviceMapPath()
   901  }
   902  
   903  // Block volume support
   904  func (fv *FakeVolume) getPodDeviceMapPath() (string, string) {
   905  	return filepath.Join(fv.Plugin.Host.GetPodVolumeDeviceDir(fv.PodUID, utilstrings.EscapeQualifiedName(fv.Plugin.PluginName))), fv.VolName
   906  }
   907  
   908  // Block volume support
   909  func (fv *FakeVolume) GetPodDeviceMapPathCallCount() int {
   910  	fv.RLock()
   911  	defer fv.RUnlock()
   912  	return fv.PodDeviceMapPathCallCount
   913  }
   914  
   915  // Block volume support
   916  func (fv *FakeVolume) TearDownDevice(mapPath string, devicePath string) error {
   917  	fv.Lock()
   918  	defer fv.Unlock()
   919  	fv.TearDownDeviceCallCount++
   920  	return nil
   921  }
   922  
   923  // Block volume support
   924  func (fv *FakeVolume) GetTearDownDeviceCallCount() int {
   925  	fv.RLock()
   926  	defer fv.RUnlock()
   927  	return fv.TearDownDeviceCallCount
   928  }
   929  
   930  // Block volume support
   931  func (fv *FakeVolume) UnmapPodDevice() error {
   932  	fv.Lock()
   933  	defer fv.Unlock()
   934  	fv.UnmapPodDeviceCallCount++
   935  	return nil
   936  }
   937  
   938  // Block volume support
   939  func (fv *FakeVolume) GetUnmapPodDeviceCallCount() int {
   940  	fv.RLock()
   941  	defer fv.RUnlock()
   942  	return fv.UnmapPodDeviceCallCount
   943  }
   944  
   945  // Block volume support
   946  func (fv *FakeVolume) MapPodDevice() (string, error) {
   947  	fv.Lock()
   948  	defer fv.Unlock()
   949  
   950  	if fv.VolName == TimeoutOnSetupVolumeName {
   951  		fv.VolumeMountState[fv.VolName] = volumeMountUncertain
   952  		return "", volumetypes.NewUncertainProgressError("time out on setup")
   953  	}
   954  
   955  	if fv.VolName == FailOnSetupVolumeName {
   956  		fv.VolumeMountState[fv.VolName] = volumeNotMounted
   957  		return "", fmt.Errorf("mounting volume failed")
   958  	}
   959  
   960  	if fv.VolName == TimeoutAndFailOnSetupVolumeName {
   961  		_, ok := fv.VolumeMountState[fv.VolName]
   962  		if !ok {
   963  			fv.VolumeMountState[fv.VolName] = volumeMountUncertain
   964  			return "", volumetypes.NewUncertainProgressError("time out on setup")
   965  		}
   966  		fv.VolumeMountState[fv.VolName] = volumeNotMounted
   967  		return "", fmt.Errorf("mounting volume failed")
   968  
   969  	}
   970  
   971  	if fv.VolName == SuccessAndFailOnSetupVolumeName {
   972  		_, ok := fv.VolumeMountState[fv.VolName]
   973  		if ok {
   974  			fv.VolumeMountState[fv.VolName] = volumeNotMounted
   975  			return "", fmt.Errorf("mounting volume failed")
   976  		}
   977  	}
   978  
   979  	if fv.VolName == SuccessAndTimeoutSetupVolumeName {
   980  		_, ok := fv.VolumeMountState[fv.VolName]
   981  		if ok {
   982  			fv.VolumeMountState[fv.VolName] = volumeMountUncertain
   983  			return "", volumetypes.NewUncertainProgressError("time out on setup")
   984  		}
   985  	}
   986  
   987  	fv.VolumeMountState[fv.VolName] = volumeMounted
   988  	fv.MapPodDeviceCallCount++
   989  	return "", nil
   990  }
   991  
   992  // Block volume support
   993  func (fv *FakeVolume) GetMapPodDeviceCallCount() int {
   994  	fv.RLock()
   995  	defer fv.RUnlock()
   996  	return fv.MapPodDeviceCallCount
   997  }
   998  
   999  func (fv *FakeVolume) Attach(spec *volume.Spec, nodeName types.NodeName) (string, error) {
  1000  	fv.Lock()
  1001  	defer fv.Unlock()
  1002  	fv.AttachCallCount++
  1003  
  1004  	volumeName, err := getUniqueVolumeName(spec)
  1005  	if err != nil {
  1006  		return "", err
  1007  	}
  1008  	volumeNodes, exist := fv.VolumesAttached[volumeName]
  1009  	if exist {
  1010  		if nodeName == UncertainAttachNode {
  1011  			return "/dev/vdb-test", nil
  1012  		}
  1013  		// even if volume was previously attached to time out, we need to keep returning error
  1014  		// so as reconciler can not confirm this volume as attached.
  1015  		if nodeName == TimeoutAttachNode {
  1016  			return "", fmt.Errorf("timed out to attach volume %q to node %q", volumeName, nodeName)
  1017  		}
  1018  		if volumeNodes.Has(string(nodeName)) || volumeNodes.Has(MultiAttachNode) || nodeName == MultiAttachNode {
  1019  			volumeNodes.Insert(string(nodeName))
  1020  			return "/dev/vdb-test", nil
  1021  		}
  1022  		return "", fmt.Errorf("volume %q trying to attach to node %q is already attached to node %q", volumeName, nodeName, volumeNodes)
  1023  	}
  1024  
  1025  	fv.VolumesAttached[volumeName] = sets.NewString(string(nodeName))
  1026  	if nodeName == UncertainAttachNode || nodeName == TimeoutAttachNode {
  1027  		return "", fmt.Errorf("timed out to attach volume %q to node %q", volumeName, nodeName)
  1028  	}
  1029  	return "/dev/vdb-test", nil
  1030  }
  1031  
  1032  func (fv *FakeVolume) GetAttachCallCount() int {
  1033  	fv.RLock()
  1034  	defer fv.RUnlock()
  1035  	return fv.AttachCallCount
  1036  }
  1037  
  1038  func (fv *FakeVolume) WaitForAttach(spec *volume.Spec, devicePath string, pod *v1.Pod, spectimeout time.Duration) (string, error) {
  1039  	fv.Lock()
  1040  	defer fv.Unlock()
  1041  	fv.WaitForAttachCallCount++
  1042  	if fv.WaitForAttachHook != nil {
  1043  		return fv.WaitForAttachHook(spec, devicePath, pod, spectimeout)
  1044  	}
  1045  	return "/dev/sdb", nil
  1046  }
  1047  
  1048  func (fv *FakeVolume) GetWaitForAttachCallCount() int {
  1049  	fv.RLock()
  1050  	defer fv.RUnlock()
  1051  	return fv.WaitForAttachCallCount
  1052  }
  1053  
  1054  func (fv *FakeVolume) GetDeviceMountPath(spec *volume.Spec) (string, error) {
  1055  	fv.Lock()
  1056  	defer fv.Unlock()
  1057  	fv.GetDeviceMountPathCallCount++
  1058  	return "", nil
  1059  }
  1060  
  1061  func (fv *FakeVolume) mountDeviceInternal(spec *volume.Spec, devicePath string, deviceMountPath string) error {
  1062  	fv.Lock()
  1063  	defer fv.Unlock()
  1064  	if spec.Name() == TimeoutOnMountDeviceVolumeName {
  1065  		fv.DeviceMountState[spec.Name()] = deviceMountUncertain
  1066  		return volumetypes.NewUncertainProgressError("mount failed")
  1067  	}
  1068  
  1069  	if spec.Name() == FailMountDeviceVolumeName {
  1070  		fv.DeviceMountState[spec.Name()] = deviceNotMounted
  1071  		return fmt.Errorf("error mounting disk: %s", devicePath)
  1072  	}
  1073  
  1074  	if spec.Name() == TimeoutAndFailOnMountDeviceVolumeName {
  1075  		_, ok := fv.DeviceMountState[spec.Name()]
  1076  		if !ok {
  1077  			fv.DeviceMountState[spec.Name()] = deviceMountUncertain
  1078  			return volumetypes.NewUncertainProgressError("timed out mounting error")
  1079  		}
  1080  		fv.DeviceMountState[spec.Name()] = deviceNotMounted
  1081  		return fmt.Errorf("error mounting disk: %s", devicePath)
  1082  	}
  1083  
  1084  	if spec.Name() == SuccessAndTimeoutDeviceName {
  1085  		_, ok := fv.DeviceMountState[spec.Name()]
  1086  		if ok {
  1087  			fv.DeviceMountState[spec.Name()] = deviceMountUncertain
  1088  			return volumetypes.NewUncertainProgressError("error mounting state")
  1089  		}
  1090  	}
  1091  
  1092  	if spec.Name() == SuccessAndFailOnMountDeviceName {
  1093  		_, ok := fv.DeviceMountState[spec.Name()]
  1094  		if ok {
  1095  			return fmt.Errorf("error mounting disk: %s", devicePath)
  1096  		}
  1097  	}
  1098  	fv.DeviceMountState[spec.Name()] = deviceMounted
  1099  	fv.MountDeviceCallCount++
  1100  	return nil
  1101  }
  1102  
  1103  func (fv *FakeVolume) MountDevice(spec *volume.Spec, devicePath string, deviceMountPath string, _ volume.DeviceMounterArgs) error {
  1104  	return fv.mountDeviceInternal(spec, devicePath, deviceMountPath)
  1105  }
  1106  
  1107  func (fv *FakeVolume) GetMountDeviceCallCount() int {
  1108  	fv.RLock()
  1109  	defer fv.RUnlock()
  1110  	return fv.MountDeviceCallCount
  1111  }
  1112  
  1113  func (fv *FakeVolume) GetUnmountDeviceCallCount() int {
  1114  	fv.RLock()
  1115  	defer fv.RUnlock()
  1116  	return fv.UnmountDeviceCallCount
  1117  }
  1118  
  1119  func (fv *FakeVolume) Detach(volumeName string, nodeName types.NodeName) error {
  1120  	fv.Lock()
  1121  	defer fv.Unlock()
  1122  
  1123  	node := string(nodeName)
  1124  	volumeNodes, exist := fv.VolumesAttached[volumeName]
  1125  	if !exist || !volumeNodes.Has(node) {
  1126  		return fmt.Errorf("trying to detach volume %q that is not attached to the node %q", volumeName, node)
  1127  	}
  1128  
  1129  	fv.DetachCallCount++
  1130  	if nodeName == FailDetachNode {
  1131  		return fmt.Errorf("fail to detach volume %q to node %q", volumeName, nodeName)
  1132  	}
  1133  
  1134  	volumeNodes.Delete(node)
  1135  	if volumeNodes.Len() == 0 {
  1136  		delete(fv.VolumesAttached, volumeName)
  1137  	}
  1138  
  1139  	return nil
  1140  }
  1141  
  1142  func (fv *FakeVolume) VolumesAreAttached(spec []*volume.Spec, nodeName types.NodeName) (map[*volume.Spec]bool, error) {
  1143  	fv.Lock()
  1144  	defer fv.Unlock()
  1145  	return nil, nil
  1146  }
  1147  
  1148  func (fv *FakeVolume) GetDetachCallCount() int {
  1149  	fv.RLock()
  1150  	defer fv.RUnlock()
  1151  	return fv.DetachCallCount
  1152  }
  1153  
  1154  func (fv *FakeVolume) UnmountDevice(globalMountPath string) error {
  1155  	fv.Lock()
  1156  	defer fv.Unlock()
  1157  	fv.UnmountDeviceCallCount++
  1158  	if fv.UnmountDeviceHook != nil {
  1159  		return fv.UnmountDeviceHook(globalMountPath)
  1160  	}
  1161  	return nil
  1162  }
  1163  
  1164  type FakeDeleter struct {
  1165  	path string
  1166  	volume.MetricsNil
  1167  }
  1168  
  1169  func (fd *FakeDeleter) Delete() error {
  1170  	// nil is success, else error
  1171  	return nil
  1172  }
  1173  
  1174  func (fd *FakeDeleter) GetPath() string {
  1175  	return fd.path
  1176  }
  1177  
  1178  type FakeProvisioner struct {
  1179  	Options               volume.VolumeOptions
  1180  	Host                  volume.VolumeHost
  1181  	ProvisionDelaySeconds int
  1182  }
  1183  
  1184  func (fc *FakeProvisioner) Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) {
  1185  	// Add provision failure hook
  1186  	if fc.Options.Parameters != nil {
  1187  		if _, ok := fc.Options.Parameters[ExpectProvisionFailureKey]; ok {
  1188  			return nil, fmt.Errorf("expected error")
  1189  		}
  1190  	}
  1191  	fullpath := fmt.Sprintf("/%s/hostpath_pv/%s", os.TempDir(), uuid.NewUUID())
  1192  
  1193  	pv := &v1.PersistentVolume{
  1194  		ObjectMeta: metav1.ObjectMeta{
  1195  			Name: fc.Options.PVName,
  1196  			Annotations: map[string]string{
  1197  				util.VolumeDynamicallyCreatedByKey: "fakeplugin-provisioner",
  1198  			},
  1199  		},
  1200  		Spec: v1.PersistentVolumeSpec{
  1201  			PersistentVolumeReclaimPolicy: fc.Options.PersistentVolumeReclaimPolicy,
  1202  			AccessModes:                   fc.Options.PVC.Spec.AccessModes,
  1203  			Capacity: v1.ResourceList{
  1204  				v1.ResourceName(v1.ResourceStorage): fc.Options.PVC.Spec.Resources.Requests[v1.ResourceName(v1.ResourceStorage)],
  1205  			},
  1206  			PersistentVolumeSource: v1.PersistentVolumeSource{
  1207  				HostPath: &v1.HostPathVolumeSource{
  1208  					Path: fullpath,
  1209  				},
  1210  			},
  1211  		},
  1212  	}
  1213  
  1214  	if fc.ProvisionDelaySeconds > 0 {
  1215  		time.Sleep(time.Duration(fc.ProvisionDelaySeconds) * time.Second)
  1216  	}
  1217  
  1218  	return pv, nil
  1219  }
  1220  
  1221  var _ volumepathhandler.BlockVolumePathHandler = &FakeVolumePathHandler{}
  1222  
  1223  // NewDeviceHandler Create a new IoHandler implementation
  1224  func NewBlockVolumePathHandler() volumepathhandler.BlockVolumePathHandler {
  1225  	return &FakeVolumePathHandler{}
  1226  }
  1227  
  1228  type FakeVolumePathHandler struct {
  1229  	sync.RWMutex
  1230  }
  1231  
  1232  func (fv *FakeVolumePathHandler) MapDevice(devicePath string, mapDir string, linkName string, bindMount bool) error {
  1233  	// nil is success, else error
  1234  	return nil
  1235  }
  1236  
  1237  func (fv *FakeVolumePathHandler) UnmapDevice(mapDir string, linkName string, bindMount bool) error {
  1238  	// nil is success, else error
  1239  	return nil
  1240  }
  1241  
  1242  func (fv *FakeVolumePathHandler) RemoveMapPath(mapPath string) error {
  1243  	// nil is success, else error
  1244  	return nil
  1245  }
  1246  
  1247  func (fv *FakeVolumePathHandler) IsSymlinkExist(mapPath string) (bool, error) {
  1248  	// nil is success, else error
  1249  	return true, nil
  1250  }
  1251  
  1252  func (fv *FakeVolumePathHandler) IsDeviceBindMountExist(mapPath string) (bool, error) {
  1253  	// nil is success, else error
  1254  	return true, nil
  1255  }
  1256  
  1257  func (fv *FakeVolumePathHandler) GetDeviceBindMountRefs(devPath string, mapPath string) ([]string, error) {
  1258  	// nil is success, else error
  1259  	return []string{}, nil
  1260  }
  1261  
  1262  func (fv *FakeVolumePathHandler) FindGlobalMapPathUUIDFromPod(pluginDir, mapPath string, podUID types.UID) (string, error) {
  1263  	// nil is success, else error
  1264  	return "", nil
  1265  }
  1266  
  1267  func (fv *FakeVolumePathHandler) AttachFileDevice(path string) (string, error) {
  1268  	// nil is success, else error
  1269  	return "", nil
  1270  }
  1271  
  1272  func (fv *FakeVolumePathHandler) DetachFileDevice(path string) error {
  1273  	// nil is success, else error
  1274  	return nil
  1275  }
  1276  
  1277  func (fv *FakeVolumePathHandler) GetLoopDevice(path string) (string, error) {
  1278  	// nil is success, else error
  1279  	return "/dev/loop1", nil
  1280  }
  1281  
  1282  // FindEmptyDirectoryUsageOnTmpfs finds the expected usage of an empty directory existing on
  1283  // a tmpfs filesystem on this system.
  1284  func FindEmptyDirectoryUsageOnTmpfs() (*resource.Quantity, error) {
  1285  	// The command below does not exist on Windows. Additionally, empty folders have size 0 on Windows.
  1286  	if goruntime.GOOS == "windows" {
  1287  		used, err := resource.ParseQuantity("0")
  1288  		return &used, err
  1289  	}
  1290  	tmpDir, err := utiltesting.MkTmpdir("metrics_du_test")
  1291  	if err != nil {
  1292  		return nil, err
  1293  	}
  1294  	defer os.RemoveAll(tmpDir)
  1295  	out, err := exec.New().Command("nice", "-n", "19", "du", "-x", "-s", "-B", "1", tmpDir).CombinedOutput()
  1296  	if err != nil {
  1297  		return nil, fmt.Errorf("failed command 'du' on %s with error %v", tmpDir, err)
  1298  	}
  1299  	used, err := resource.ParseQuantity(strings.Fields(string(out))[0])
  1300  	if err != nil {
  1301  		return nil, fmt.Errorf("failed to parse 'du' output %s due to error %v", out, err)
  1302  	}
  1303  	used.Format = resource.BinarySI
  1304  	return &used, nil
  1305  }
  1306  
  1307  // VerifyAttachCallCount ensures that at least one of the Attachers for this
  1308  // plugin has the expectedAttachCallCount number of calls. Otherwise it returns
  1309  // an error.
  1310  func VerifyAttachCallCount(
  1311  	expectedAttachCallCount int,
  1312  	fakeVolumePlugin *FakeVolumePlugin) error {
  1313  	for _, attacher := range fakeVolumePlugin.GetAttachers() {
  1314  		actualCallCount := attacher.GetAttachCallCount()
  1315  		if actualCallCount >= expectedAttachCallCount {
  1316  			return nil
  1317  		}
  1318  	}
  1319  
  1320  	return fmt.Errorf(
  1321  		"No attachers have expected AttachCallCount. Expected: <%v>.",
  1322  		expectedAttachCallCount)
  1323  }
  1324  
  1325  // VerifyZeroAttachCalls ensures that all of the Attachers for this plugin have
  1326  // a zero AttachCallCount. Otherwise it returns an error.
  1327  func VerifyZeroAttachCalls(fakeVolumePlugin *FakeVolumePlugin) error {
  1328  	for _, attacher := range fakeVolumePlugin.GetAttachers() {
  1329  		actualCallCount := attacher.GetAttachCallCount()
  1330  		if actualCallCount != 0 {
  1331  			return fmt.Errorf(
  1332  				"At least one attacher has non-zero AttachCallCount: <%v>.",
  1333  				actualCallCount)
  1334  		}
  1335  	}
  1336  
  1337  	return nil
  1338  }
  1339  
  1340  // VerifyWaitForAttachCallCount ensures that at least one of the Mounters for
  1341  // this plugin has the expectedWaitForAttachCallCount number of calls. Otherwise
  1342  // it returns an error.
  1343  func VerifyWaitForAttachCallCount(
  1344  	expectedWaitForAttachCallCount int,
  1345  	fakeVolumePlugin *FakeVolumePlugin) error {
  1346  	for _, attacher := range fakeVolumePlugin.GetAttachers() {
  1347  		actualCallCount := attacher.GetWaitForAttachCallCount()
  1348  		if actualCallCount >= expectedWaitForAttachCallCount {
  1349  			return nil
  1350  		}
  1351  	}
  1352  
  1353  	return fmt.Errorf(
  1354  		"No Attachers have expected WaitForAttachCallCount. Expected: <%v>.",
  1355  		expectedWaitForAttachCallCount)
  1356  }
  1357  
  1358  // VerifyZeroWaitForAttachCallCount ensures that all Attachers for this plugin
  1359  // have a zero WaitForAttachCallCount. Otherwise it returns an error.
  1360  func VerifyZeroWaitForAttachCallCount(fakeVolumePlugin *FakeVolumePlugin) error {
  1361  	for _, attacher := range fakeVolumePlugin.GetAttachers() {
  1362  		actualCallCount := attacher.GetWaitForAttachCallCount()
  1363  		if actualCallCount != 0 {
  1364  			return fmt.Errorf(
  1365  				"At least one attacher has non-zero WaitForAttachCallCount: <%v>.",
  1366  				actualCallCount)
  1367  		}
  1368  	}
  1369  
  1370  	return nil
  1371  }
  1372  
  1373  // VerifyMountDeviceCallCount ensures that at least one of the Mounters for
  1374  // this plugin has the expectedMountDeviceCallCount number of calls. Otherwise
  1375  // it returns an error.
  1376  func VerifyMountDeviceCallCount(
  1377  	expectedMountDeviceCallCount int,
  1378  	fakeVolumePlugin *FakeVolumePlugin) error {
  1379  	for _, attacher := range fakeVolumePlugin.GetAttachers() {
  1380  		actualCallCount := attacher.GetMountDeviceCallCount()
  1381  		if actualCallCount >= expectedMountDeviceCallCount {
  1382  			return nil
  1383  		}
  1384  	}
  1385  
  1386  	return fmt.Errorf(
  1387  		"No Attachers have expected MountDeviceCallCount. Expected: <%v>.",
  1388  		expectedMountDeviceCallCount)
  1389  }
  1390  
  1391  func VerifyUnmountDeviceCallCount(expectedCallCount int, fakeVolumePlugin *FakeVolumePlugin) error {
  1392  	detachers := fakeVolumePlugin.GetDetachers()
  1393  	if len(detachers) == 0 && (expectedCallCount == 0) {
  1394  		return nil
  1395  	}
  1396  	actualCallCount := 0
  1397  	for _, detacher := range detachers {
  1398  		actualCallCount = detacher.GetUnmountDeviceCallCount()
  1399  		if expectedCallCount == 0 && actualCallCount == expectedCallCount {
  1400  			return nil
  1401  		}
  1402  
  1403  		if (expectedCallCount > 0) && (actualCallCount >= expectedCallCount) {
  1404  			return nil
  1405  		}
  1406  	}
  1407  
  1408  	return fmt.Errorf(
  1409  		"Expected DeviceUnmount Call %d, got %d",
  1410  		expectedCallCount, actualCallCount)
  1411  }
  1412  
  1413  // VerifyZeroMountDeviceCallCount ensures that all Attachers for this plugin
  1414  // have a zero MountDeviceCallCount. Otherwise it returns an error.
  1415  func VerifyZeroMountDeviceCallCount(fakeVolumePlugin *FakeVolumePlugin) error {
  1416  	for _, attacher := range fakeVolumePlugin.GetAttachers() {
  1417  		actualCallCount := attacher.GetMountDeviceCallCount()
  1418  		if actualCallCount != 0 {
  1419  			return fmt.Errorf(
  1420  				"At least one attacher has non-zero MountDeviceCallCount: <%v>.",
  1421  				actualCallCount)
  1422  		}
  1423  	}
  1424  
  1425  	return nil
  1426  }
  1427  
  1428  // VerifySetUpCallCount ensures that at least one of the Mounters for this
  1429  // plugin has the expectedSetUpCallCount number of calls. Otherwise it returns
  1430  // an error.
  1431  func VerifySetUpCallCount(
  1432  	expectedSetUpCallCount int,
  1433  	fakeVolumePlugin *FakeVolumePlugin) error {
  1434  	for _, mounter := range fakeVolumePlugin.GetMounters() {
  1435  		actualCallCount := mounter.GetSetUpCallCount()
  1436  		if actualCallCount >= expectedSetUpCallCount {
  1437  			return nil
  1438  		}
  1439  	}
  1440  
  1441  	return fmt.Errorf(
  1442  		"No Mounters have expected SetUpCallCount. Expected: <%v>.",
  1443  		expectedSetUpCallCount)
  1444  }
  1445  
  1446  // VerifyZeroSetUpCallCount ensures that all Mounters for this plugin have a
  1447  // zero SetUpCallCount. Otherwise it returns an error.
  1448  func VerifyZeroSetUpCallCount(fakeVolumePlugin *FakeVolumePlugin) error {
  1449  	for _, mounter := range fakeVolumePlugin.GetMounters() {
  1450  		actualCallCount := mounter.GetSetUpCallCount()
  1451  		if actualCallCount != 0 {
  1452  			return fmt.Errorf(
  1453  				"At least one mounter has non-zero SetUpCallCount: <%v>.",
  1454  				actualCallCount)
  1455  		}
  1456  	}
  1457  
  1458  	return nil
  1459  }
  1460  
  1461  // VerifyTearDownCallCount ensures that at least one of the Unounters for this
  1462  // plugin has the expectedTearDownCallCount number of calls. Otherwise it
  1463  // returns an error.
  1464  func VerifyTearDownCallCount(
  1465  	expectedTearDownCallCount int,
  1466  	fakeVolumePlugin *FakeVolumePlugin) error {
  1467  	unmounters := fakeVolumePlugin.GetUnmounters()
  1468  	if len(unmounters) == 0 && (expectedTearDownCallCount == 0) {
  1469  		return nil
  1470  	}
  1471  
  1472  	for _, unmounter := range unmounters {
  1473  		actualCallCount := unmounter.GetTearDownCallCount()
  1474  		if expectedTearDownCallCount == 0 && actualCallCount == expectedTearDownCallCount {
  1475  			return nil
  1476  		}
  1477  
  1478  		if (expectedTearDownCallCount > 0) && (actualCallCount >= expectedTearDownCallCount) {
  1479  			return nil
  1480  		}
  1481  	}
  1482  
  1483  	return fmt.Errorf(
  1484  		"No Unmounters have expected SetUpCallCount. Expected: <%v>.",
  1485  		expectedTearDownCallCount)
  1486  }
  1487  
  1488  // VerifyZeroTearDownCallCount ensures that all Mounters for this plugin have a
  1489  // zero TearDownCallCount. Otherwise it returns an error.
  1490  func VerifyZeroTearDownCallCount(fakeVolumePlugin *FakeVolumePlugin) error {
  1491  	for _, mounter := range fakeVolumePlugin.GetMounters() {
  1492  		actualCallCount := mounter.GetTearDownCallCount()
  1493  		if actualCallCount != 0 {
  1494  			return fmt.Errorf(
  1495  				"At least one mounter has non-zero TearDownCallCount: <%v>.",
  1496  				actualCallCount)
  1497  		}
  1498  	}
  1499  
  1500  	return nil
  1501  }
  1502  
  1503  // VerifyDetachCallCount ensures that at least one of the Attachers for this
  1504  // plugin has the expectedDetachCallCount number of calls. Otherwise it returns
  1505  // an error.
  1506  func VerifyDetachCallCount(
  1507  	expectedDetachCallCount int,
  1508  	fakeVolumePlugin *FakeVolumePlugin) error {
  1509  	for _, detacher := range fakeVolumePlugin.GetDetachers() {
  1510  		actualCallCount := detacher.GetDetachCallCount()
  1511  		if actualCallCount == expectedDetachCallCount {
  1512  			return nil
  1513  		}
  1514  	}
  1515  
  1516  	return fmt.Errorf(
  1517  		"No Detachers have expected DetachCallCount. Expected: <%v>.",
  1518  		expectedDetachCallCount)
  1519  }
  1520  
  1521  // VerifyZeroDetachCallCount ensures that all Detachers for this plugin have a
  1522  // zero DetachCallCount. Otherwise it returns an error.
  1523  func VerifyZeroDetachCallCount(fakeVolumePlugin *FakeVolumePlugin) error {
  1524  	for _, detacher := range fakeVolumePlugin.GetDetachers() {
  1525  		actualCallCount := detacher.GetDetachCallCount()
  1526  		if actualCallCount != 0 {
  1527  			return fmt.Errorf(
  1528  				"At least one detacher has non-zero DetachCallCount: <%v>.",
  1529  				actualCallCount)
  1530  		}
  1531  	}
  1532  
  1533  	return nil
  1534  }
  1535  
  1536  // VerifyTearDownDeviceCallCount ensures that at least one of the Unmappers for this
  1537  // plugin has the expectedTearDownDeviceCallCount number of calls. Otherwise it
  1538  // returns an error.
  1539  func VerifyTearDownDeviceCallCount(
  1540  	expectedTearDownDeviceCallCount int,
  1541  	fakeVolumePlugin *FakeVolumePlugin) error {
  1542  	for _, unmapper := range fakeVolumePlugin.GetBlockVolumeUnmapper() {
  1543  		actualCallCount := unmapper.GetTearDownDeviceCallCount()
  1544  		if actualCallCount >= expectedTearDownDeviceCallCount {
  1545  			return nil
  1546  		}
  1547  	}
  1548  
  1549  	return fmt.Errorf(
  1550  		"No Unmapper have expected TearDownDeviceCallCount. Expected: <%v>.",
  1551  		expectedTearDownDeviceCallCount)
  1552  }
  1553  
  1554  // VerifyZeroTearDownDeviceCallCount ensures that all Mappers for this plugin have a
  1555  // zero TearDownDeviceCallCount. Otherwise it returns an error.
  1556  func VerifyZeroTearDownDeviceCallCount(fakeVolumePlugin *FakeVolumePlugin) error {
  1557  	for _, unmapper := range fakeVolumePlugin.GetBlockVolumeUnmapper() {
  1558  		actualCallCount := unmapper.GetTearDownDeviceCallCount()
  1559  		if actualCallCount != 0 {
  1560  			return fmt.Errorf(
  1561  				"At least one unmapper has non-zero TearDownDeviceCallCount: <%v>.",
  1562  				actualCallCount)
  1563  		}
  1564  	}
  1565  
  1566  	return nil
  1567  }
  1568  
  1569  // VerifyUnmapPodDeviceCallCount ensures that at least one of the Unmappers for this
  1570  // plugin has the expected number of UnmapPodDevice calls. Otherwise it
  1571  // returns an error.
  1572  func VerifyUnmapPodDeviceCallCount(
  1573  	expectedUnmapPodDeviceCallCount int,
  1574  	fakeVolumePlugin *FakeVolumePlugin) error {
  1575  	for _, unmapper := range fakeVolumePlugin.GetBlockVolumeUnmapper() {
  1576  		actualCallCount := unmapper.GetUnmapPodDeviceCallCount()
  1577  		if actualCallCount >= expectedUnmapPodDeviceCallCount {
  1578  			return nil
  1579  		}
  1580  	}
  1581  
  1582  	return fmt.Errorf(
  1583  		"No Unmapper have expected UnmapPodDeviceCallCount. Expected: <%v>.",
  1584  		expectedUnmapPodDeviceCallCount)
  1585  }
  1586  
  1587  // VerifyZeroUnmapPodDeviceCallCount ensures that all Mappers for this plugin have a
  1588  // zero UnmapPodDevice calls. Otherwise it returns an error.
  1589  func VerifyZeroUnmapPodDeviceCallCount(fakeVolumePlugin *FakeVolumePlugin) error {
  1590  	for _, unmapper := range fakeVolumePlugin.GetBlockVolumeUnmapper() {
  1591  		actualCallCount := unmapper.GetUnmapPodDeviceCallCount()
  1592  		if actualCallCount != 0 {
  1593  			return fmt.Errorf(
  1594  				"At least one unmapper has non-zero UnmapPodDeviceCallCount: <%v>.",
  1595  				actualCallCount)
  1596  		}
  1597  	}
  1598  
  1599  	return nil
  1600  }
  1601  
  1602  // VerifyGetGlobalMapPathCallCount ensures that at least one of the Mappers for this
  1603  // plugin has the expectedGlobalMapPathCallCount number of calls. Otherwise it returns
  1604  // an error.
  1605  func VerifyGetGlobalMapPathCallCount(
  1606  	expectedGlobalMapPathCallCount int,
  1607  	fakeVolumePlugin *FakeVolumePlugin) error {
  1608  	for _, mapper := range fakeVolumePlugin.GetBlockVolumeMapper() {
  1609  		actualCallCount := mapper.GetGlobalMapPathCallCount()
  1610  		if actualCallCount == expectedGlobalMapPathCallCount {
  1611  			return nil
  1612  		}
  1613  	}
  1614  
  1615  	return fmt.Errorf(
  1616  		"No Mappers have expected GetGlobalMapPathCallCount. Expected: <%v>.",
  1617  		expectedGlobalMapPathCallCount)
  1618  }
  1619  
  1620  // VerifyGetPodDeviceMapPathCallCount ensures that at least one of the Mappers for this
  1621  // plugin has the expectedPodDeviceMapPathCallCount number of calls. Otherwise it returns
  1622  // an error.
  1623  func VerifyGetPodDeviceMapPathCallCount(
  1624  	expectedPodDeviceMapPathCallCount int,
  1625  	fakeVolumePlugin *FakeVolumePlugin) error {
  1626  	for _, mapper := range fakeVolumePlugin.GetBlockVolumeMapper() {
  1627  		actualCallCount := mapper.GetPodDeviceMapPathCallCount()
  1628  		if actualCallCount == expectedPodDeviceMapPathCallCount {
  1629  			return nil
  1630  		}
  1631  	}
  1632  
  1633  	return fmt.Errorf(
  1634  		"No Mappers have expected GetPodDeviceMapPathCallCount. Expected: <%v>.",
  1635  		expectedPodDeviceMapPathCallCount)
  1636  }
  1637  
  1638  // VerifyGetMapPodDeviceCallCount ensures that at least one of the Mappers for this
  1639  // plugin has the expectedMapPodDeviceCallCount number of calls. Otherwise it
  1640  // returns an error.
  1641  func VerifyGetMapPodDeviceCallCount(
  1642  	expectedMapPodDeviceCallCount int,
  1643  	fakeVolumePlugin *FakeVolumePlugin) error {
  1644  	for _, mapper := range fakeVolumePlugin.GetBlockVolumeMapper() {
  1645  		actualCallCount := mapper.GetMapPodDeviceCallCount()
  1646  		if actualCallCount >= expectedMapPodDeviceCallCount {
  1647  			return nil
  1648  		}
  1649  	}
  1650  
  1651  	return fmt.Errorf(
  1652  		"No Mapper have expected MapPodDeviceCallCount. Expected: <%v>.",
  1653  		expectedMapPodDeviceCallCount)
  1654  }
  1655  
  1656  // GetTestVolumePluginMgr creates, initializes, and returns a test volume plugin
  1657  // manager and fake volume plugin using a fake volume host.
  1658  func GetTestVolumePluginMgr(t *testing.T) (*volume.VolumePluginMgr, *FakeVolumePlugin) {
  1659  	plugins := ProbeVolumePlugins(volume.VolumeConfig{})
  1660  	v := NewFakeVolumeHost(
  1661  		t,
  1662  		"",      /* rootDir */
  1663  		nil,     /* kubeClient */
  1664  		plugins, /* plugins */
  1665  	)
  1666  	return v.GetPluginMgr(), plugins[0].(*FakeVolumePlugin)
  1667  }
  1668  
  1669  func GetTestKubeletVolumePluginMgr(t *testing.T) (*volume.VolumePluginMgr, *FakeVolumePlugin) {
  1670  	plugins := ProbeVolumePlugins(volume.VolumeConfig{})
  1671  	v := NewFakeKubeletVolumeHost(
  1672  		t,
  1673  		"",      /* rootDir */
  1674  		nil,     /* kubeClient */
  1675  		plugins, /* plugins */
  1676  	)
  1677  	return v.GetPluginMgr(), plugins[0].(*FakeVolumePlugin)
  1678  }
  1679  
  1680  func GetTestKubeletVolumePluginMgrWithNode(t *testing.T, node *v1.Node) (*volume.VolumePluginMgr, *FakeVolumePlugin) {
  1681  	plugins := ProbeVolumePlugins(volume.VolumeConfig{})
  1682  	v := NewFakeKubeletVolumeHost(
  1683  		t,
  1684  		"",      /* rootDir */
  1685  		nil,     /* kubeClient */
  1686  		plugins, /* plugins */
  1687  	)
  1688  	v.WithNode(node)
  1689  
  1690  	return v.GetPluginMgr(), plugins[0].(*FakeVolumePlugin)
  1691  }
  1692  
  1693  func GetTestKubeletVolumePluginMgrWithNodeAndRoot(t *testing.T, node *v1.Node, rootDir string) (*volume.VolumePluginMgr, *FakeVolumePlugin) {
  1694  	plugins := ProbeVolumePlugins(volume.VolumeConfig{})
  1695  	v := NewFakeKubeletVolumeHost(
  1696  		t,
  1697  		rootDir, /* rootDir */
  1698  		nil,     /* kubeClient */
  1699  		plugins, /* plugins */
  1700  	)
  1701  	v.WithNode(node)
  1702  
  1703  	return v.GetPluginMgr(), plugins[0].(*FakeVolumePlugin)
  1704  }
  1705  
  1706  // CreateTestPVC returns a provisionable PVC for tests
  1707  func CreateTestPVC(capacity string, accessModes []v1.PersistentVolumeAccessMode) *v1.PersistentVolumeClaim {
  1708  	claim := v1.PersistentVolumeClaim{
  1709  		ObjectMeta: metav1.ObjectMeta{
  1710  			Name:      "dummy",
  1711  			Namespace: "default",
  1712  		},
  1713  		Spec: v1.PersistentVolumeClaimSpec{
  1714  			AccessModes: accessModes,
  1715  			Resources: v1.VolumeResourceRequirements{
  1716  				Requests: v1.ResourceList{
  1717  					v1.ResourceName(v1.ResourceStorage): resource.MustParse(capacity),
  1718  				},
  1719  			},
  1720  		},
  1721  	}
  1722  	return &claim
  1723  }
  1724  
  1725  func MetricsEqualIgnoreTimestamp(a *volume.Metrics, b *volume.Metrics) bool {
  1726  	available := a.Available == b.Available
  1727  	capacity := a.Capacity == b.Capacity
  1728  	used := a.Used == b.Used
  1729  	inodes := a.Inodes == b.Inodes
  1730  	inodesFree := a.InodesFree == b.InodesFree
  1731  	inodesUsed := a.InodesUsed == b.InodesUsed
  1732  	return available && capacity && used && inodes && inodesFree && inodesUsed
  1733  }
  1734  
  1735  func ContainsAccessMode(modes []v1.PersistentVolumeAccessMode, mode v1.PersistentVolumeAccessMode) bool {
  1736  	for _, m := range modes {
  1737  		if m == mode {
  1738  			return true
  1739  		}
  1740  	}
  1741  	return false
  1742  }
  1743  

View as plain text