testing.go 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506
  1. /*
  2. Copyright 2014 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package testing
  14. import (
  15. "fmt"
  16. "net"
  17. "os"
  18. "os/exec"
  19. "path/filepath"
  20. "strings"
  21. "sync"
  22. "testing"
  23. "time"
  24. authenticationv1 "k8s.io/api/authentication/v1"
  25. "k8s.io/api/core/v1"
  26. "k8s.io/apimachinery/pkg/api/resource"
  27. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  28. "k8s.io/apimachinery/pkg/types"
  29. "k8s.io/apimachinery/pkg/util/uuid"
  30. clientset "k8s.io/client-go/kubernetes"
  31. storagelisters "k8s.io/client-go/listers/storage/v1beta1"
  32. "k8s.io/client-go/tools/record"
  33. utiltesting "k8s.io/client-go/util/testing"
  34. cloudprovider "k8s.io/cloud-provider"
  35. "k8s.io/kubernetes/pkg/util/mount"
  36. . "k8s.io/kubernetes/pkg/volume"
  37. "k8s.io/kubernetes/pkg/volume/util"
  38. "k8s.io/kubernetes/pkg/volume/util/recyclerclient"
  39. "k8s.io/kubernetes/pkg/volume/util/subpath"
  40. "k8s.io/kubernetes/pkg/volume/util/volumepathhandler"
  41. utilstrings "k8s.io/utils/strings"
  42. )
  43. const (
  44. // A hook specified in storage class to indicate it's provisioning
  45. // is expected to fail.
  46. ExpectProvisionFailureKey = "expect-provision-failure"
  47. // The node is marked as uncertain. The attach operation will fail and return timeout error
  48. // for the first attach call. The following call will return sucesssfully.
  49. UncertainAttachNode = "uncertain-attach-node"
  50. // The node is marked as timeout. The attach operation will always fail and return timeout error
  51. // but the operation is actually succeeded.
  52. TimeoutAttachNode = "timeout-attach-node"
  53. // The node is marked as multi-attach which means it is allowed to attach the volume to multiple nodes.
  54. MultiAttachNode = "multi-attach-node"
  55. )
  56. // fakeVolumeHost is useful for testing volume plugins.
  57. type fakeVolumeHost struct {
  58. rootDir string
  59. kubeClient clientset.Interface
  60. pluginMgr VolumePluginMgr
  61. cloud cloudprovider.Interface
  62. mounter mount.Interface
  63. exec mount.Exec
  64. nodeLabels map[string]string
  65. nodeName string
  66. subpather subpath.Interface
  67. csiDriverLister storagelisters.CSIDriverLister
  68. }
  69. var _ VolumeHost = &fakeVolumeHost{}
  70. var _ AttachDetachVolumeHost = &fakeVolumeHost{}
  71. func NewFakeVolumeHost(rootDir string, kubeClient clientset.Interface, plugins []VolumePlugin) *fakeVolumeHost {
  72. return newFakeVolumeHost(rootDir, kubeClient, plugins, nil, nil)
  73. }
  74. func NewFakeVolumeHostWithCloudProvider(rootDir string, kubeClient clientset.Interface, plugins []VolumePlugin, cloud cloudprovider.Interface) *fakeVolumeHost {
  75. return newFakeVolumeHost(rootDir, kubeClient, plugins, cloud, nil)
  76. }
  77. func NewFakeVolumeHostWithNodeLabels(rootDir string, kubeClient clientset.Interface, plugins []VolumePlugin, labels map[string]string) *fakeVolumeHost {
  78. volHost := newFakeVolumeHost(rootDir, kubeClient, plugins, nil, nil)
  79. volHost.nodeLabels = labels
  80. return volHost
  81. }
  82. func NewFakeVolumeHostWithCSINodeName(rootDir string, kubeClient clientset.Interface, plugins []VolumePlugin, nodeName string, driverLister storagelisters.CSIDriverLister) *fakeVolumeHost {
  83. volHost := newFakeVolumeHost(rootDir, kubeClient, plugins, nil, nil)
  84. volHost.nodeName = nodeName
  85. if driverLister != nil {
  86. volHost.csiDriverLister = driverLister
  87. }
  88. return volHost
  89. }
  90. func newFakeVolumeHost(rootDir string, kubeClient clientset.Interface, plugins []VolumePlugin, cloud cloudprovider.Interface, pathToTypeMap map[string]mount.FileType) *fakeVolumeHost {
  91. host := &fakeVolumeHost{rootDir: rootDir, kubeClient: kubeClient, cloud: cloud}
  92. host.mounter = &mount.FakeMounter{
  93. Filesystem: pathToTypeMap,
  94. }
  95. host.exec = mount.NewFakeExec(nil)
  96. host.pluginMgr.InitPlugins(plugins, nil /* prober */, host)
  97. host.subpather = &subpath.FakeSubpath{}
  98. return host
  99. }
  100. func NewFakeVolumeHostWithMounterFSType(rootDir string, kubeClient clientset.Interface, plugins []VolumePlugin, pathToTypeMap map[string]mount.FileType) *fakeVolumeHost {
  101. volHost := newFakeVolumeHost(rootDir, kubeClient, plugins, nil, pathToTypeMap)
  102. return volHost
  103. }
  104. func (f *fakeVolumeHost) GetPluginDir(podUID string) string {
  105. return filepath.Join(f.rootDir, "plugins", podUID)
  106. }
  107. func (f *fakeVolumeHost) GetVolumeDevicePluginDir(pluginName string) string {
  108. return filepath.Join(f.rootDir, "plugins", pluginName, "volumeDevices")
  109. }
  110. func (f *fakeVolumeHost) GetPodsDir() string {
  111. return filepath.Join(f.rootDir, "pods")
  112. }
  113. func (f *fakeVolumeHost) GetPodVolumeDir(podUID types.UID, pluginName, volumeName string) string {
  114. return filepath.Join(f.rootDir, "pods", string(podUID), "volumes", pluginName, volumeName)
  115. }
  116. func (f *fakeVolumeHost) GetPodVolumeDeviceDir(podUID types.UID, pluginName string) string {
  117. return filepath.Join(f.rootDir, "pods", string(podUID), "volumeDevices", pluginName)
  118. }
  119. func (f *fakeVolumeHost) GetPodPluginDir(podUID types.UID, pluginName string) string {
  120. return filepath.Join(f.rootDir, "pods", string(podUID), "plugins", pluginName)
  121. }
  122. func (f *fakeVolumeHost) GetKubeClient() clientset.Interface {
  123. return f.kubeClient
  124. }
  125. func (f *fakeVolumeHost) GetCloudProvider() cloudprovider.Interface {
  126. return f.cloud
  127. }
  128. func (f *fakeVolumeHost) GetMounter(pluginName string) mount.Interface {
  129. return f.mounter
  130. }
  131. func (f *fakeVolumeHost) GetSubpather() subpath.Interface {
  132. return f.subpather
  133. }
  134. func (f *fakeVolumeHost) NewWrapperMounter(volName string, spec Spec, pod *v1.Pod, opts VolumeOptions) (Mounter, error) {
  135. // The name of wrapper volume is set to "wrapped_{wrapped_volume_name}"
  136. wrapperVolumeName := "wrapped_" + volName
  137. if spec.Volume != nil {
  138. spec.Volume.Name = wrapperVolumeName
  139. }
  140. plug, err := f.pluginMgr.FindPluginBySpec(&spec)
  141. if err != nil {
  142. return nil, err
  143. }
  144. return plug.NewMounter(&spec, pod, opts)
  145. }
  146. func (f *fakeVolumeHost) NewWrapperUnmounter(volName string, spec Spec, podUID types.UID) (Unmounter, error) {
  147. // The name of wrapper volume is set to "wrapped_{wrapped_volume_name}"
  148. wrapperVolumeName := "wrapped_" + volName
  149. if spec.Volume != nil {
  150. spec.Volume.Name = wrapperVolumeName
  151. }
  152. plug, err := f.pluginMgr.FindPluginBySpec(&spec)
  153. if err != nil {
  154. return nil, err
  155. }
  156. return plug.NewUnmounter(spec.Name(), podUID)
  157. }
  158. // Returns the hostname of the host kubelet is running on
  159. func (f *fakeVolumeHost) GetHostName() string {
  160. return "fakeHostName"
  161. }
  162. // Returns host IP or nil in the case of error.
  163. func (f *fakeVolumeHost) GetHostIP() (net.IP, error) {
  164. return nil, fmt.Errorf("GetHostIP() not implemented")
  165. }
  166. func (f *fakeVolumeHost) GetNodeAllocatable() (v1.ResourceList, error) {
  167. return v1.ResourceList{}, nil
  168. }
  169. func (f *fakeVolumeHost) GetSecretFunc() func(namespace, name string) (*v1.Secret, error) {
  170. return func(namespace, name string) (*v1.Secret, error) {
  171. return f.kubeClient.CoreV1().Secrets(namespace).Get(name, metav1.GetOptions{})
  172. }
  173. }
  174. func (f *fakeVolumeHost) GetExec(pluginName string) mount.Exec {
  175. return f.exec
  176. }
  177. func (f *fakeVolumeHost) GetConfigMapFunc() func(namespace, name string) (*v1.ConfigMap, error) {
  178. return func(namespace, name string) (*v1.ConfigMap, error) {
  179. return f.kubeClient.CoreV1().ConfigMaps(namespace).Get(name, metav1.GetOptions{})
  180. }
  181. }
  182. func (f *fakeVolumeHost) GetServiceAccountTokenFunc() func(string, string, *authenticationv1.TokenRequest) (*authenticationv1.TokenRequest, error) {
  183. return func(namespace, name string, tr *authenticationv1.TokenRequest) (*authenticationv1.TokenRequest, error) {
  184. return f.kubeClient.CoreV1().ServiceAccounts(namespace).CreateToken(name, tr)
  185. }
  186. }
  187. func (f *fakeVolumeHost) DeleteServiceAccountTokenFunc() func(types.UID) {
  188. return func(types.UID) {}
  189. }
  190. func (f *fakeVolumeHost) GetNodeLabels() (map[string]string, error) {
  191. if f.nodeLabels == nil {
  192. f.nodeLabels = map[string]string{"test-label": "test-value"}
  193. }
  194. return f.nodeLabels, nil
  195. }
  196. func (f *fakeVolumeHost) GetNodeName() types.NodeName {
  197. return types.NodeName(f.nodeName)
  198. }
  199. func (f *fakeVolumeHost) GetEventRecorder() record.EventRecorder {
  200. return nil
  201. }
  202. func ProbeVolumePlugins(config VolumeConfig) []VolumePlugin {
  203. if _, ok := config.OtherAttributes["fake-property"]; ok {
  204. return []VolumePlugin{
  205. &FakeVolumePlugin{
  206. PluginName: "fake-plugin",
  207. Host: nil,
  208. // SomeFakeProperty: config.OtherAttributes["fake-property"] -- string, may require parsing by plugin
  209. },
  210. }
  211. }
  212. return []VolumePlugin{&FakeVolumePlugin{PluginName: "fake-plugin"}}
  213. }
  214. // FakeVolumePlugin is useful for testing. It tries to be a fully compliant
  215. // plugin, but all it does is make empty directories.
  216. // Use as:
  217. // volume.RegisterPlugin(&FakePlugin{"fake-name"})
  218. type FakeVolumePlugin struct {
  219. sync.RWMutex
  220. PluginName string
  221. Host VolumeHost
  222. Config VolumeConfig
  223. LastProvisionerOptions VolumeOptions
  224. NewAttacherCallCount int
  225. NewDetacherCallCount int
  226. VolumeLimits map[string]int64
  227. VolumeLimitsError error
  228. LimitKey string
  229. ProvisionDelaySeconds int
  230. // Add callbacks as needed
  231. WaitForAttachHook func(spec *Spec, devicePath string, pod *v1.Pod, spectimeout time.Duration) (string, error)
  232. UnmountDeviceHook func(globalMountPath string) error
  233. Mounters []*FakeVolume
  234. Unmounters []*FakeVolume
  235. Attachers []*FakeVolume
  236. Detachers []*FakeVolume
  237. BlockVolumeMappers []*FakeVolume
  238. BlockVolumeUnmappers []*FakeVolume
  239. }
  240. var _ VolumePlugin = &FakeVolumePlugin{}
  241. var _ BlockVolumePlugin = &FakeVolumePlugin{}
  242. var _ RecyclableVolumePlugin = &FakeVolumePlugin{}
  243. var _ DeletableVolumePlugin = &FakeVolumePlugin{}
  244. var _ ProvisionableVolumePlugin = &FakeVolumePlugin{}
  245. var _ AttachableVolumePlugin = &FakeVolumePlugin{}
  246. var _ VolumePluginWithAttachLimits = &FakeVolumePlugin{}
  247. var _ DeviceMountableVolumePlugin = &FakeVolumePlugin{}
  248. var _ NodeExpandableVolumePlugin = &FakeVolumePlugin{}
  249. func (plugin *FakeVolumePlugin) getFakeVolume(list *[]*FakeVolume) *FakeVolume {
  250. volumeList := *list
  251. if list != nil && len(volumeList) > 0 {
  252. volume := volumeList[0]
  253. volume.Lock()
  254. defer volume.Unlock()
  255. volume.WaitForAttachHook = plugin.WaitForAttachHook
  256. volume.UnmountDeviceHook = plugin.UnmountDeviceHook
  257. return volume
  258. }
  259. volume := &FakeVolume{
  260. WaitForAttachHook: plugin.WaitForAttachHook,
  261. UnmountDeviceHook: plugin.UnmountDeviceHook,
  262. }
  263. volume.VolumesAttached = make(map[string]types.NodeName)
  264. *list = append(*list, volume)
  265. return volume
  266. }
  267. func (plugin *FakeVolumePlugin) Init(host VolumeHost) error {
  268. plugin.Lock()
  269. defer plugin.Unlock()
  270. plugin.Host = host
  271. return nil
  272. }
  273. func (plugin *FakeVolumePlugin) GetPluginName() string {
  274. plugin.RLock()
  275. defer plugin.RUnlock()
  276. return plugin.PluginName
  277. }
  278. func (plugin *FakeVolumePlugin) GetVolumeName(spec *Spec) (string, error) {
  279. var volumeName string
  280. if spec.Volume != nil && spec.Volume.GCEPersistentDisk != nil {
  281. volumeName = spec.Volume.GCEPersistentDisk.PDName
  282. } else if spec.PersistentVolume != nil &&
  283. spec.PersistentVolume.Spec.GCEPersistentDisk != nil {
  284. volumeName = spec.PersistentVolume.Spec.GCEPersistentDisk.PDName
  285. }
  286. if volumeName == "" {
  287. volumeName = spec.Name()
  288. }
  289. return volumeName, nil
  290. }
  291. func (plugin *FakeVolumePlugin) CanSupport(spec *Spec) bool {
  292. // TODO: maybe pattern-match on spec.Name() to decide?
  293. return true
  294. }
  295. func (plugin *FakeVolumePlugin) IsMigratedToCSI() bool {
  296. return false
  297. }
  298. func (plugin *FakeVolumePlugin) RequiresRemount() bool {
  299. return false
  300. }
  301. func (plugin *FakeVolumePlugin) SupportsMountOption() bool {
  302. return true
  303. }
  304. func (plugin *FakeVolumePlugin) SupportsBulkVolumeVerification() bool {
  305. return false
  306. }
  307. func (plugin *FakeVolumePlugin) NewMounter(spec *Spec, pod *v1.Pod, opts VolumeOptions) (Mounter, error) {
  308. plugin.Lock()
  309. defer plugin.Unlock()
  310. volume := plugin.getFakeVolume(&plugin.Mounters)
  311. volume.Lock()
  312. defer volume.Unlock()
  313. volume.PodUID = pod.UID
  314. volume.VolName = spec.Name()
  315. volume.Plugin = plugin
  316. volume.MetricsNil = MetricsNil{}
  317. return volume, nil
  318. }
  319. func (plugin *FakeVolumePlugin) GetMounters() (Mounters []*FakeVolume) {
  320. plugin.RLock()
  321. defer plugin.RUnlock()
  322. return plugin.Mounters
  323. }
  324. func (plugin *FakeVolumePlugin) NewUnmounter(volName string, podUID types.UID) (Unmounter, error) {
  325. plugin.Lock()
  326. defer plugin.Unlock()
  327. volume := plugin.getFakeVolume(&plugin.Unmounters)
  328. volume.Lock()
  329. defer volume.Unlock()
  330. volume.PodUID = podUID
  331. volume.VolName = volName
  332. volume.Plugin = plugin
  333. volume.MetricsNil = MetricsNil{}
  334. return volume, nil
  335. }
  336. func (plugin *FakeVolumePlugin) GetUnmounters() (Unmounters []*FakeVolume) {
  337. plugin.RLock()
  338. defer plugin.RUnlock()
  339. return plugin.Unmounters
  340. }
  341. // Block volume support
  342. func (plugin *FakeVolumePlugin) NewBlockVolumeMapper(spec *Spec, pod *v1.Pod, opts VolumeOptions) (BlockVolumeMapper, error) {
  343. plugin.Lock()
  344. defer plugin.Unlock()
  345. volume := plugin.getFakeVolume(&plugin.BlockVolumeMappers)
  346. volume.Lock()
  347. defer volume.Unlock()
  348. if pod != nil {
  349. volume.PodUID = pod.UID
  350. }
  351. volume.VolName = spec.Name()
  352. volume.Plugin = plugin
  353. return volume, nil
  354. }
  355. // Block volume support
  356. func (plugin *FakeVolumePlugin) GetBlockVolumeMapper() (BlockVolumeMappers []*FakeVolume) {
  357. plugin.RLock()
  358. defer plugin.RUnlock()
  359. return plugin.BlockVolumeMappers
  360. }
  361. // Block volume support
  362. func (plugin *FakeVolumePlugin) NewBlockVolumeUnmapper(volName string, podUID types.UID) (BlockVolumeUnmapper, error) {
  363. plugin.Lock()
  364. defer plugin.Unlock()
  365. volume := plugin.getFakeVolume(&plugin.BlockVolumeUnmappers)
  366. volume.Lock()
  367. defer volume.Unlock()
  368. volume.PodUID = podUID
  369. volume.VolName = volName
  370. volume.Plugin = plugin
  371. return volume, nil
  372. }
  373. // Block volume support
  374. func (plugin *FakeVolumePlugin) GetBlockVolumeUnmapper() (BlockVolumeUnmappers []*FakeVolume) {
  375. plugin.RLock()
  376. defer plugin.RUnlock()
  377. return plugin.BlockVolumeUnmappers
  378. }
  379. func (plugin *FakeVolumePlugin) NewAttacher() (Attacher, error) {
  380. plugin.Lock()
  381. defer plugin.Unlock()
  382. plugin.NewAttacherCallCount = plugin.NewAttacherCallCount + 1
  383. return plugin.getFakeVolume(&plugin.Attachers), nil
  384. }
  385. func (plugin *FakeVolumePlugin) NewDeviceMounter() (DeviceMounter, error) {
  386. return plugin.NewAttacher()
  387. }
  388. func (plugin *FakeVolumePlugin) GetAttachers() (Attachers []*FakeVolume) {
  389. plugin.RLock()
  390. defer plugin.RUnlock()
  391. return plugin.Attachers
  392. }
  393. func (plugin *FakeVolumePlugin) GetNewAttacherCallCount() int {
  394. plugin.RLock()
  395. defer plugin.RUnlock()
  396. return plugin.NewAttacherCallCount
  397. }
  398. func (plugin *FakeVolumePlugin) NewDetacher() (Detacher, error) {
  399. plugin.Lock()
  400. defer plugin.Unlock()
  401. plugin.NewDetacherCallCount = plugin.NewDetacherCallCount + 1
  402. detacher := plugin.getFakeVolume(&plugin.Detachers)
  403. attacherList := plugin.Attachers
  404. if attacherList != nil && len(attacherList) > 0 {
  405. detacherList := plugin.Detachers
  406. if detacherList != nil && len(detacherList) > 0 {
  407. detacherList[0].VolumesAttached = attacherList[0].VolumesAttached
  408. }
  409. }
  410. return detacher, nil
  411. }
  412. func (plugin *FakeVolumePlugin) NewDeviceUnmounter() (DeviceUnmounter, error) {
  413. return plugin.NewDetacher()
  414. }
  415. func (plugin *FakeVolumePlugin) GetDetachers() (Detachers []*FakeVolume) {
  416. plugin.RLock()
  417. defer plugin.RUnlock()
  418. return plugin.Detachers
  419. }
  420. func (plugin *FakeVolumePlugin) GetNewDetacherCallCount() int {
  421. plugin.RLock()
  422. defer plugin.RUnlock()
  423. return plugin.NewDetacherCallCount
  424. }
  425. func (plugin *FakeVolumePlugin) CanAttach(spec *Spec) (bool, error) {
  426. return true, nil
  427. }
  428. func (plugin *FakeVolumePlugin) CanDeviceMount(spec *Spec) (bool, error) {
  429. return true, nil
  430. }
  431. func (plugin *FakeVolumePlugin) Recycle(pvName string, spec *Spec, eventRecorder recyclerclient.RecycleEventRecorder) error {
  432. return nil
  433. }
  434. func (plugin *FakeVolumePlugin) NewDeleter(spec *Spec) (Deleter, error) {
  435. return &FakeDeleter{"/attributesTransferredFromSpec", MetricsNil{}}, nil
  436. }
  437. func (plugin *FakeVolumePlugin) NewProvisioner(options VolumeOptions) (Provisioner, error) {
  438. plugin.Lock()
  439. defer plugin.Unlock()
  440. plugin.LastProvisionerOptions = options
  441. return &FakeProvisioner{options, plugin.Host, plugin.ProvisionDelaySeconds}, nil
  442. }
  443. func (plugin *FakeVolumePlugin) GetAccessModes() []v1.PersistentVolumeAccessMode {
  444. return []v1.PersistentVolumeAccessMode{}
  445. }
  446. func (plugin *FakeVolumePlugin) ConstructVolumeSpec(volumeName, mountPath string) (*Spec, error) {
  447. return &Spec{
  448. Volume: &v1.Volume{
  449. Name: volumeName,
  450. },
  451. }, nil
  452. }
  453. // Block volume support
  454. func (plugin *FakeVolumePlugin) ConstructBlockVolumeSpec(podUID types.UID, volumeName, mountPath string) (*Spec, error) {
  455. return &Spec{
  456. Volume: &v1.Volume{
  457. Name: volumeName,
  458. },
  459. }, nil
  460. }
  461. func (plugin *FakeVolumePlugin) GetDeviceMountRefs(deviceMountPath string) ([]string, error) {
  462. return []string{}, nil
  463. }
  464. // Expandable volume support
  465. func (plugin *FakeVolumePlugin) ExpandVolumeDevice(spec *Spec, newSize resource.Quantity, oldSize resource.Quantity) (resource.Quantity, error) {
  466. return resource.Quantity{}, nil
  467. }
  468. func (plugin *FakeVolumePlugin) RequiresFSResize() bool {
  469. return true
  470. }
  471. func (plugin *FakeVolumePlugin) NodeExpand(resizeOptions NodeResizeOptions) (bool, error) {
  472. return true, nil
  473. }
  474. func (plugin *FakeVolumePlugin) GetVolumeLimits() (map[string]int64, error) {
  475. return plugin.VolumeLimits, plugin.VolumeLimitsError
  476. }
  477. func (plugin *FakeVolumePlugin) VolumeLimitKey(spec *Spec) string {
  478. return plugin.LimitKey
  479. }
  480. // FakeBasicVolumePlugin implements a basic volume plugin. It wrappers on
  481. // FakeVolumePlugin but implements VolumePlugin interface only.
  482. // It is useful to test logic involving plugin interfaces.
  483. type FakeBasicVolumePlugin struct {
  484. Plugin FakeVolumePlugin
  485. }
  486. func (f *FakeBasicVolumePlugin) GetPluginName() string {
  487. return f.Plugin.GetPluginName()
  488. }
  489. func (f *FakeBasicVolumePlugin) GetVolumeName(spec *Spec) (string, error) {
  490. return f.Plugin.GetVolumeName(spec)
  491. }
  492. // CanSupport tests whether the plugin supports a given volume specification by
  493. // testing volume spec name begins with plugin name or not.
  494. // This is useful to choose plugin by volume in testing.
  495. func (f *FakeBasicVolumePlugin) CanSupport(spec *Spec) bool {
  496. return strings.HasPrefix(spec.Name(), f.GetPluginName())
  497. }
  498. func (plugin *FakeBasicVolumePlugin) IsMigratedToCSI() bool {
  499. return false
  500. }
  501. func (f *FakeBasicVolumePlugin) ConstructVolumeSpec(ame, mountPath string) (*Spec, error) {
  502. return f.Plugin.ConstructVolumeSpec(ame, mountPath)
  503. }
  504. func (f *FakeBasicVolumePlugin) Init(ost VolumeHost) error {
  505. return f.Plugin.Init(ost)
  506. }
  507. func (f *FakeBasicVolumePlugin) NewMounter(spec *Spec, pod *v1.Pod, opts VolumeOptions) (Mounter, error) {
  508. return f.Plugin.NewMounter(spec, pod, opts)
  509. }
  510. func (f *FakeBasicVolumePlugin) NewUnmounter(volName string, podUID types.UID) (Unmounter, error) {
  511. return f.Plugin.NewUnmounter(volName, podUID)
  512. }
  513. func (f *FakeBasicVolumePlugin) RequiresRemount() bool {
  514. return f.Plugin.RequiresRemount()
  515. }
  516. func (f *FakeBasicVolumePlugin) SupportsBulkVolumeVerification() bool {
  517. return f.Plugin.SupportsBulkVolumeVerification()
  518. }
  519. func (f *FakeBasicVolumePlugin) SupportsMountOption() bool {
  520. return f.Plugin.SupportsMountOption()
  521. }
  522. var _ VolumePlugin = &FakeBasicVolumePlugin{}
  523. // FakeDeviceMountableVolumePlugin implements an device mountable plugin based on FakeBasicVolumePlugin.
  524. type FakeDeviceMountableVolumePlugin struct {
  525. FakeBasicVolumePlugin
  526. }
  527. func (f *FakeDeviceMountableVolumePlugin) CanDeviceMount(spec *Spec) (bool, error) {
  528. return true, nil
  529. }
  530. func (f *FakeDeviceMountableVolumePlugin) NewDeviceMounter() (DeviceMounter, error) {
  531. return f.Plugin.NewDeviceMounter()
  532. }
  533. func (f *FakeDeviceMountableVolumePlugin) NewDeviceUnmounter() (DeviceUnmounter, error) {
  534. return f.Plugin.NewDeviceUnmounter()
  535. }
  536. func (f *FakeDeviceMountableVolumePlugin) GetDeviceMountRefs(deviceMountPath string) ([]string, error) {
  537. return f.Plugin.GetDeviceMountRefs(deviceMountPath)
  538. }
  539. var _ VolumePlugin = &FakeDeviceMountableVolumePlugin{}
  540. var _ DeviceMountableVolumePlugin = &FakeDeviceMountableVolumePlugin{}
  541. // FakeAttachableVolumePlugin implements an attachable plugin based on FakeDeviceMountableVolumePlugin.
  542. type FakeAttachableVolumePlugin struct {
  543. FakeDeviceMountableVolumePlugin
  544. }
  545. func (f *FakeAttachableVolumePlugin) NewAttacher() (Attacher, error) {
  546. return f.Plugin.NewAttacher()
  547. }
  548. func (f *FakeAttachableVolumePlugin) NewDetacher() (Detacher, error) {
  549. return f.Plugin.NewDetacher()
  550. }
  551. func (f *FakeAttachableVolumePlugin) CanAttach(spec *Spec) (bool, error) {
  552. return true, nil
  553. }
  554. var _ VolumePlugin = &FakeAttachableVolumePlugin{}
  555. var _ AttachableVolumePlugin = &FakeAttachableVolumePlugin{}
  556. type FakeFileVolumePlugin struct {
  557. }
  558. func (plugin *FakeFileVolumePlugin) Init(host VolumeHost) error {
  559. return nil
  560. }
  561. func (plugin *FakeFileVolumePlugin) GetPluginName() string {
  562. return "fake-file-plugin"
  563. }
  564. func (plugin *FakeFileVolumePlugin) GetVolumeName(spec *Spec) (string, error) {
  565. return "", nil
  566. }
  567. func (plugin *FakeFileVolumePlugin) CanSupport(spec *Spec) bool {
  568. return true
  569. }
  570. func (plugin *FakeFileVolumePlugin) IsMigratedToCSI() bool {
  571. return false
  572. }
  573. func (plugin *FakeFileVolumePlugin) RequiresRemount() bool {
  574. return false
  575. }
  576. func (plugin *FakeFileVolumePlugin) SupportsMountOption() bool {
  577. return false
  578. }
  579. func (plugin *FakeFileVolumePlugin) SupportsBulkVolumeVerification() bool {
  580. return false
  581. }
  582. func (plugin *FakeFileVolumePlugin) NewMounter(spec *Spec, podRef *v1.Pod, opts VolumeOptions) (Mounter, error) {
  583. return nil, nil
  584. }
  585. func (plugin *FakeFileVolumePlugin) NewUnmounter(name string, podUID types.UID) (Unmounter, error) {
  586. return nil, nil
  587. }
  588. func (plugin *FakeFileVolumePlugin) ConstructVolumeSpec(volumeName, mountPath string) (*Spec, error) {
  589. return nil, nil
  590. }
  591. func NewFakeFileVolumePlugin() []VolumePlugin {
  592. return []VolumePlugin{&FakeFileVolumePlugin{}}
  593. }
  594. type FakeVolume struct {
  595. sync.RWMutex
  596. PodUID types.UID
  597. VolName string
  598. Plugin *FakeVolumePlugin
  599. MetricsNil
  600. VolumesAttached map[string]types.NodeName
  601. // Add callbacks as needed
  602. WaitForAttachHook func(spec *Spec, devicePath string, pod *v1.Pod, spectimeout time.Duration) (string, error)
  603. UnmountDeviceHook func(globalMountPath string) error
  604. SetUpCallCount int
  605. TearDownCallCount int
  606. AttachCallCount int
  607. DetachCallCount int
  608. WaitForAttachCallCount int
  609. MountDeviceCallCount int
  610. UnmountDeviceCallCount int
  611. GetDeviceMountPathCallCount int
  612. SetUpDeviceCallCount int
  613. TearDownDeviceCallCount int
  614. MapDeviceCallCount int
  615. GlobalMapPathCallCount int
  616. PodDeviceMapPathCallCount int
  617. }
  618. func getUniqueVolumeName(spec *Spec) (string, error) {
  619. var volumeName string
  620. if spec.Volume != nil && spec.Volume.GCEPersistentDisk != nil {
  621. volumeName = spec.Volume.GCEPersistentDisk.PDName
  622. } else if spec.PersistentVolume != nil &&
  623. spec.PersistentVolume.Spec.GCEPersistentDisk != nil {
  624. volumeName = spec.PersistentVolume.Spec.GCEPersistentDisk.PDName
  625. }
  626. if volumeName == "" {
  627. volumeName = spec.Name()
  628. }
  629. return volumeName, nil
  630. }
  631. func (_ *FakeVolume) GetAttributes() Attributes {
  632. return Attributes{
  633. ReadOnly: false,
  634. Managed: true,
  635. SupportsSELinux: true,
  636. }
  637. }
  638. func (fv *FakeVolume) CanMount() error {
  639. return nil
  640. }
  641. func (fv *FakeVolume) SetUp(mounterArgs MounterArgs) error {
  642. fv.Lock()
  643. defer fv.Unlock()
  644. fv.SetUpCallCount++
  645. return fv.SetUpAt(fv.getPath(), mounterArgs)
  646. }
  647. func (fv *FakeVolume) GetSetUpCallCount() int {
  648. fv.RLock()
  649. defer fv.RUnlock()
  650. return fv.SetUpCallCount
  651. }
  652. func (fv *FakeVolume) SetUpAt(dir string, mounterArgs MounterArgs) error {
  653. return os.MkdirAll(dir, 0750)
  654. }
  655. func (fv *FakeVolume) GetPath() string {
  656. fv.RLock()
  657. defer fv.RUnlock()
  658. return fv.getPath()
  659. }
  660. func (fv *FakeVolume) getPath() string {
  661. return filepath.Join(fv.Plugin.Host.GetPodVolumeDir(fv.PodUID, utilstrings.EscapeQualifiedName(fv.Plugin.PluginName), fv.VolName))
  662. }
  663. func (fv *FakeVolume) TearDown() error {
  664. fv.Lock()
  665. defer fv.Unlock()
  666. fv.TearDownCallCount++
  667. return fv.TearDownAt(fv.getPath())
  668. }
  669. func (fv *FakeVolume) GetTearDownCallCount() int {
  670. fv.RLock()
  671. defer fv.RUnlock()
  672. return fv.TearDownCallCount
  673. }
  674. func (fv *FakeVolume) TearDownAt(dir string) error {
  675. return os.RemoveAll(dir)
  676. }
  677. // Block volume support
  678. func (fv *FakeVolume) SetUpDevice() (string, error) {
  679. fv.Lock()
  680. defer fv.Unlock()
  681. fv.SetUpDeviceCallCount++
  682. return "", nil
  683. }
  684. // Block volume support
  685. func (fv *FakeVolume) GetSetUpDeviceCallCount() int {
  686. fv.RLock()
  687. defer fv.RUnlock()
  688. return fv.SetUpDeviceCallCount
  689. }
  690. // Block volume support
  691. func (fv *FakeVolume) GetGlobalMapPath(spec *Spec) (string, error) {
  692. fv.RLock()
  693. defer fv.RUnlock()
  694. fv.GlobalMapPathCallCount++
  695. return fv.getGlobalMapPath()
  696. }
  697. // Block volume support
  698. func (fv *FakeVolume) getGlobalMapPath() (string, error) {
  699. return filepath.Join(fv.Plugin.Host.GetVolumeDevicePluginDir(utilstrings.EscapeQualifiedName(fv.Plugin.PluginName)), "pluginDependentPath"), nil
  700. }
  701. // Block volume support
  702. func (fv *FakeVolume) GetGlobalMapPathCallCount() int {
  703. fv.RLock()
  704. defer fv.RUnlock()
  705. return fv.GlobalMapPathCallCount
  706. }
  707. // Block volume support
  708. func (fv *FakeVolume) GetPodDeviceMapPath() (string, string) {
  709. fv.RLock()
  710. defer fv.RUnlock()
  711. fv.PodDeviceMapPathCallCount++
  712. return fv.getPodDeviceMapPath()
  713. }
  714. // Block volume support
  715. func (fv *FakeVolume) getPodDeviceMapPath() (string, string) {
  716. return filepath.Join(fv.Plugin.Host.GetPodVolumeDeviceDir(fv.PodUID, utilstrings.EscapeQualifiedName(fv.Plugin.PluginName))), fv.VolName
  717. }
  718. // Block volume support
  719. func (fv *FakeVolume) GetPodDeviceMapPathCallCount() int {
  720. fv.RLock()
  721. defer fv.RUnlock()
  722. return fv.PodDeviceMapPathCallCount
  723. }
  724. // Block volume support
  725. func (fv *FakeVolume) TearDownDevice(mapPath string, devicePath string) error {
  726. fv.Lock()
  727. defer fv.Unlock()
  728. fv.TearDownDeviceCallCount++
  729. return nil
  730. }
  731. // Block volume support
  732. func (fv *FakeVolume) GetTearDownDeviceCallCount() int {
  733. fv.RLock()
  734. defer fv.RUnlock()
  735. return fv.TearDownDeviceCallCount
  736. }
  737. // Block volume support
  738. func (fv *FakeVolume) MapDevice(devicePath, globalMapPath, volumeMapPath, volumeMapName string, pod types.UID) error {
  739. fv.Lock()
  740. defer fv.Unlock()
  741. fv.MapDeviceCallCount++
  742. return nil
  743. }
  744. // Block volume support
  745. func (fv *FakeVolume) GetMapDeviceCallCount() int {
  746. fv.RLock()
  747. defer fv.RUnlock()
  748. return fv.MapDeviceCallCount
  749. }
  750. func (fv *FakeVolume) Attach(spec *Spec, nodeName types.NodeName) (string, error) {
  751. fv.Lock()
  752. defer fv.Unlock()
  753. fv.AttachCallCount++
  754. volumeName, err := getUniqueVolumeName(spec)
  755. if err != nil {
  756. return "", err
  757. }
  758. volumeNode, exist := fv.VolumesAttached[volumeName]
  759. if exist {
  760. if nodeName == UncertainAttachNode {
  761. return "/dev/vdb-test", nil
  762. }
  763. // even if volume was previously attached to time out, we need to keep returning error
  764. // so as reconciler can not confirm this volume as attached.
  765. if nodeName == TimeoutAttachNode {
  766. return "", fmt.Errorf("Timed out to attach volume %q to node %q", volumeName, nodeName)
  767. }
  768. if volumeNode == nodeName || volumeNode == MultiAttachNode || nodeName == MultiAttachNode {
  769. return "/dev/vdb-test", nil
  770. }
  771. return "", fmt.Errorf("volume %q trying to attach to node %q is already attached to node %q", volumeName, nodeName, volumeNode)
  772. }
  773. fv.VolumesAttached[volumeName] = nodeName
  774. if nodeName == UncertainAttachNode || nodeName == TimeoutAttachNode {
  775. return "", fmt.Errorf("Timed out to attach volume %q to node %q", volumeName, nodeName)
  776. }
  777. return "/dev/vdb-test", nil
  778. }
  779. func (fv *FakeVolume) GetAttachCallCount() int {
  780. fv.RLock()
  781. defer fv.RUnlock()
  782. return fv.AttachCallCount
  783. }
  784. func (fv *FakeVolume) WaitForAttach(spec *Spec, devicePath string, pod *v1.Pod, spectimeout time.Duration) (string, error) {
  785. fv.Lock()
  786. defer fv.Unlock()
  787. fv.WaitForAttachCallCount++
  788. if fv.WaitForAttachHook != nil {
  789. return fv.WaitForAttachHook(spec, devicePath, pod, spectimeout)
  790. }
  791. return "/dev/sdb", nil
  792. }
  793. func (fv *FakeVolume) GetWaitForAttachCallCount() int {
  794. fv.RLock()
  795. defer fv.RUnlock()
  796. return fv.WaitForAttachCallCount
  797. }
  798. func (fv *FakeVolume) GetDeviceMountPath(spec *Spec) (string, error) {
  799. fv.Lock()
  800. defer fv.Unlock()
  801. fv.GetDeviceMountPathCallCount++
  802. return "", nil
  803. }
  804. func (fv *FakeVolume) MountDevice(spec *Spec, devicePath string, deviceMountPath string) error {
  805. fv.Lock()
  806. defer fv.Unlock()
  807. fv.MountDeviceCallCount++
  808. return nil
  809. }
  810. func (fv *FakeVolume) GetMountDeviceCallCount() int {
  811. fv.RLock()
  812. defer fv.RUnlock()
  813. return fv.MountDeviceCallCount
  814. }
  815. func (fv *FakeVolume) Detach(volumeName string, nodeName types.NodeName) error {
  816. fv.Lock()
  817. defer fv.Unlock()
  818. fv.DetachCallCount++
  819. if _, exist := fv.VolumesAttached[volumeName]; !exist {
  820. return fmt.Errorf("Trying to detach volume %q that is not attached to the node %q", volumeName, nodeName)
  821. }
  822. delete(fv.VolumesAttached, volumeName)
  823. return nil
  824. }
  825. func (fv *FakeVolume) VolumesAreAttached(spec []*Spec, nodeName types.NodeName) (map[*Spec]bool, error) {
  826. fv.Lock()
  827. defer fv.Unlock()
  828. return nil, nil
  829. }
  830. func (fv *FakeVolume) GetDetachCallCount() int {
  831. fv.RLock()
  832. defer fv.RUnlock()
  833. return fv.DetachCallCount
  834. }
  835. func (fv *FakeVolume) UnmountDevice(globalMountPath string) error {
  836. fv.Lock()
  837. defer fv.Unlock()
  838. fv.UnmountDeviceCallCount++
  839. if fv.UnmountDeviceHook != nil {
  840. return fv.UnmountDeviceHook(globalMountPath)
  841. }
  842. return nil
  843. }
  844. type FakeDeleter struct {
  845. path string
  846. MetricsNil
  847. }
  848. func (fd *FakeDeleter) Delete() error {
  849. // nil is success, else error
  850. return nil
  851. }
  852. func (fd *FakeDeleter) GetPath() string {
  853. return fd.path
  854. }
  855. type FakeProvisioner struct {
  856. Options VolumeOptions
  857. Host VolumeHost
  858. ProvisionDelaySeconds int
  859. }
  860. func (fc *FakeProvisioner) Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) {
  861. // Add provision failure hook
  862. if fc.Options.Parameters != nil {
  863. if _, ok := fc.Options.Parameters[ExpectProvisionFailureKey]; ok {
  864. return nil, fmt.Errorf("expected error")
  865. }
  866. }
  867. fullpath := fmt.Sprintf("/tmp/hostpath_pv/%s", uuid.NewUUID())
  868. pv := &v1.PersistentVolume{
  869. ObjectMeta: metav1.ObjectMeta{
  870. Name: fc.Options.PVName,
  871. Annotations: map[string]string{
  872. util.VolumeDynamicallyCreatedByKey: "fakeplugin-provisioner",
  873. },
  874. },
  875. Spec: v1.PersistentVolumeSpec{
  876. PersistentVolumeReclaimPolicy: fc.Options.PersistentVolumeReclaimPolicy,
  877. AccessModes: fc.Options.PVC.Spec.AccessModes,
  878. Capacity: v1.ResourceList{
  879. v1.ResourceName(v1.ResourceStorage): fc.Options.PVC.Spec.Resources.Requests[v1.ResourceName(v1.ResourceStorage)],
  880. },
  881. PersistentVolumeSource: v1.PersistentVolumeSource{
  882. HostPath: &v1.HostPathVolumeSource{
  883. Path: fullpath,
  884. },
  885. },
  886. },
  887. }
  888. if fc.ProvisionDelaySeconds > 0 {
  889. time.Sleep(time.Duration(fc.ProvisionDelaySeconds) * time.Second)
  890. }
  891. return pv, nil
  892. }
  893. var _ volumepathhandler.BlockVolumePathHandler = &FakeVolumePathHandler{}
  894. //NewDeviceHandler Create a new IoHandler implementation
  895. func NewBlockVolumePathHandler() volumepathhandler.BlockVolumePathHandler {
  896. return &FakeVolumePathHandler{}
  897. }
  898. type FakeVolumePathHandler struct {
  899. sync.RWMutex
  900. }
  901. func (fv *FakeVolumePathHandler) MapDevice(devicePath string, mapDir string, linkName string) error {
  902. // nil is success, else error
  903. return nil
  904. }
  905. func (fv *FakeVolumePathHandler) UnmapDevice(mapDir string, linkName string) error {
  906. // nil is success, else error
  907. return nil
  908. }
  909. func (fv *FakeVolumePathHandler) RemoveMapPath(mapPath string) error {
  910. // nil is success, else error
  911. return nil
  912. }
  913. func (fv *FakeVolumePathHandler) IsSymlinkExist(mapPath string) (bool, error) {
  914. // nil is success, else error
  915. return true, nil
  916. }
  917. func (fv *FakeVolumePathHandler) GetDeviceSymlinkRefs(devPath string, mapPath string) ([]string, error) {
  918. // nil is success, else error
  919. return []string{}, nil
  920. }
  921. func (fv *FakeVolumePathHandler) FindGlobalMapPathUUIDFromPod(pluginDir, mapPath string, podUID types.UID) (string, error) {
  922. // nil is success, else error
  923. return "", nil
  924. }
  925. func (fv *FakeVolumePathHandler) AttachFileDevice(path string) (string, error) {
  926. // nil is success, else error
  927. return "", nil
  928. }
  929. func (fv *FakeVolumePathHandler) GetLoopDevice(path string) (string, error) {
  930. // nil is success, else error
  931. return "/dev/loop1", nil
  932. }
  933. func (fv *FakeVolumePathHandler) RemoveLoopDevice(device string) error {
  934. // nil is success, else error
  935. return nil
  936. }
  937. // FindEmptyDirectoryUsageOnTmpfs finds the expected usage of an empty directory existing on
  938. // a tmpfs filesystem on this system.
  939. func FindEmptyDirectoryUsageOnTmpfs() (*resource.Quantity, error) {
  940. tmpDir, err := utiltesting.MkTmpdir("metrics_du_test")
  941. if err != nil {
  942. return nil, err
  943. }
  944. defer os.RemoveAll(tmpDir)
  945. out, err := exec.Command("nice", "-n", "19", "du", "-s", "-B", "1", tmpDir).CombinedOutput()
  946. if err != nil {
  947. return nil, fmt.Errorf("failed command 'du' on %s with error %v", tmpDir, err)
  948. }
  949. used, err := resource.ParseQuantity(strings.Fields(string(out))[0])
  950. if err != nil {
  951. return nil, fmt.Errorf("failed to parse 'du' output %s due to error %v", out, err)
  952. }
  953. used.Format = resource.BinarySI
  954. return &used, nil
  955. }
  956. // VerifyAttachCallCount ensures that at least one of the Attachers for this
  957. // plugin has the expectedAttachCallCount number of calls. Otherwise it returns
  958. // an error.
  959. func VerifyAttachCallCount(
  960. expectedAttachCallCount int,
  961. fakeVolumePlugin *FakeVolumePlugin) error {
  962. for _, attacher := range fakeVolumePlugin.GetAttachers() {
  963. actualCallCount := attacher.GetAttachCallCount()
  964. if actualCallCount >= expectedAttachCallCount {
  965. return nil
  966. }
  967. }
  968. return fmt.Errorf(
  969. "No attachers have expected AttachCallCount. Expected: <%v>.",
  970. expectedAttachCallCount)
  971. }
  972. // VerifyZeroAttachCalls ensures that all of the Attachers for this plugin have
  973. // a zero AttachCallCount. Otherwise it returns an error.
  974. func VerifyZeroAttachCalls(fakeVolumePlugin *FakeVolumePlugin) error {
  975. for _, attacher := range fakeVolumePlugin.GetAttachers() {
  976. actualCallCount := attacher.GetAttachCallCount()
  977. if actualCallCount != 0 {
  978. return fmt.Errorf(
  979. "At least one attacher has non-zero AttachCallCount: <%v>.",
  980. actualCallCount)
  981. }
  982. }
  983. return nil
  984. }
  985. // VerifyWaitForAttachCallCount ensures that at least one of the Mounters for
  986. // this plugin has the expectedWaitForAttachCallCount number of calls. Otherwise
  987. // it returns an error.
  988. func VerifyWaitForAttachCallCount(
  989. expectedWaitForAttachCallCount int,
  990. fakeVolumePlugin *FakeVolumePlugin) error {
  991. for _, attacher := range fakeVolumePlugin.GetAttachers() {
  992. actualCallCount := attacher.GetWaitForAttachCallCount()
  993. if actualCallCount >= expectedWaitForAttachCallCount {
  994. return nil
  995. }
  996. }
  997. return fmt.Errorf(
  998. "No Attachers have expected WaitForAttachCallCount. Expected: <%v>.",
  999. expectedWaitForAttachCallCount)
  1000. }
  1001. // VerifyZeroWaitForAttachCallCount ensures that all Attachers for this plugin
  1002. // have a zero WaitForAttachCallCount. Otherwise it returns an error.
  1003. func VerifyZeroWaitForAttachCallCount(fakeVolumePlugin *FakeVolumePlugin) error {
  1004. for _, attacher := range fakeVolumePlugin.GetAttachers() {
  1005. actualCallCount := attacher.GetWaitForAttachCallCount()
  1006. if actualCallCount != 0 {
  1007. return fmt.Errorf(
  1008. "At least one attacher has non-zero WaitForAttachCallCount: <%v>.",
  1009. actualCallCount)
  1010. }
  1011. }
  1012. return nil
  1013. }
  1014. // VerifyMountDeviceCallCount ensures that at least one of the Mounters for
  1015. // this plugin has the expectedMountDeviceCallCount number of calls. Otherwise
  1016. // it returns an error.
  1017. func VerifyMountDeviceCallCount(
  1018. expectedMountDeviceCallCount int,
  1019. fakeVolumePlugin *FakeVolumePlugin) error {
  1020. for _, attacher := range fakeVolumePlugin.GetAttachers() {
  1021. actualCallCount := attacher.GetMountDeviceCallCount()
  1022. if actualCallCount >= expectedMountDeviceCallCount {
  1023. return nil
  1024. }
  1025. }
  1026. return fmt.Errorf(
  1027. "No Attachers have expected MountDeviceCallCount. Expected: <%v>.",
  1028. expectedMountDeviceCallCount)
  1029. }
  1030. // VerifyZeroMountDeviceCallCount ensures that all Attachers for this plugin
  1031. // have a zero MountDeviceCallCount. Otherwise it returns an error.
  1032. func VerifyZeroMountDeviceCallCount(fakeVolumePlugin *FakeVolumePlugin) error {
  1033. for _, attacher := range fakeVolumePlugin.GetAttachers() {
  1034. actualCallCount := attacher.GetMountDeviceCallCount()
  1035. if actualCallCount != 0 {
  1036. return fmt.Errorf(
  1037. "At least one attacher has non-zero MountDeviceCallCount: <%v>.",
  1038. actualCallCount)
  1039. }
  1040. }
  1041. return nil
  1042. }
  1043. // VerifySetUpCallCount ensures that at least one of the Mounters for this
  1044. // plugin has the expectedSetUpCallCount number of calls. Otherwise it returns
  1045. // an error.
  1046. func VerifySetUpCallCount(
  1047. expectedSetUpCallCount int,
  1048. fakeVolumePlugin *FakeVolumePlugin) error {
  1049. for _, mounter := range fakeVolumePlugin.GetMounters() {
  1050. actualCallCount := mounter.GetSetUpCallCount()
  1051. if actualCallCount >= expectedSetUpCallCount {
  1052. return nil
  1053. }
  1054. }
  1055. return fmt.Errorf(
  1056. "No Mounters have expected SetUpCallCount. Expected: <%v>.",
  1057. expectedSetUpCallCount)
  1058. }
  1059. // VerifyZeroSetUpCallCount ensures that all Mounters for this plugin have a
  1060. // zero SetUpCallCount. Otherwise it returns an error.
  1061. func VerifyZeroSetUpCallCount(fakeVolumePlugin *FakeVolumePlugin) error {
  1062. for _, mounter := range fakeVolumePlugin.GetMounters() {
  1063. actualCallCount := mounter.GetSetUpCallCount()
  1064. if actualCallCount != 0 {
  1065. return fmt.Errorf(
  1066. "At least one mounter has non-zero SetUpCallCount: <%v>.",
  1067. actualCallCount)
  1068. }
  1069. }
  1070. return nil
  1071. }
  1072. // VerifyTearDownCallCount ensures that at least one of the Unounters for this
  1073. // plugin has the expectedTearDownCallCount number of calls. Otherwise it
  1074. // returns an error.
  1075. func VerifyTearDownCallCount(
  1076. expectedTearDownCallCount int,
  1077. fakeVolumePlugin *FakeVolumePlugin) error {
  1078. for _, unmounter := range fakeVolumePlugin.GetUnmounters() {
  1079. actualCallCount := unmounter.GetTearDownCallCount()
  1080. if actualCallCount >= expectedTearDownCallCount {
  1081. return nil
  1082. }
  1083. }
  1084. return fmt.Errorf(
  1085. "No Unmounters have expected SetUpCallCount. Expected: <%v>.",
  1086. expectedTearDownCallCount)
  1087. }
  1088. // VerifyZeroTearDownCallCount ensures that all Mounters for this plugin have a
  1089. // zero TearDownCallCount. Otherwise it returns an error.
  1090. func VerifyZeroTearDownCallCount(fakeVolumePlugin *FakeVolumePlugin) error {
  1091. for _, mounter := range fakeVolumePlugin.GetMounters() {
  1092. actualCallCount := mounter.GetTearDownCallCount()
  1093. if actualCallCount != 0 {
  1094. return fmt.Errorf(
  1095. "At least one mounter has non-zero TearDownCallCount: <%v>.",
  1096. actualCallCount)
  1097. }
  1098. }
  1099. return nil
  1100. }
  1101. // VerifyDetachCallCount ensures that at least one of the Attachers for this
  1102. // plugin has the expectedDetachCallCount number of calls. Otherwise it returns
  1103. // an error.
  1104. func VerifyDetachCallCount(
  1105. expectedDetachCallCount int,
  1106. fakeVolumePlugin *FakeVolumePlugin) error {
  1107. for _, detacher := range fakeVolumePlugin.GetDetachers() {
  1108. actualCallCount := detacher.GetDetachCallCount()
  1109. if actualCallCount == expectedDetachCallCount {
  1110. return nil
  1111. }
  1112. }
  1113. return fmt.Errorf(
  1114. "No Detachers have expected DetachCallCount. Expected: <%v>.",
  1115. expectedDetachCallCount)
  1116. }
  1117. // VerifyZeroDetachCallCount ensures that all Detachers for this plugin have a
  1118. // zero DetachCallCount. Otherwise it returns an error.
  1119. func VerifyZeroDetachCallCount(fakeVolumePlugin *FakeVolumePlugin) error {
  1120. for _, detacher := range fakeVolumePlugin.GetDetachers() {
  1121. actualCallCount := detacher.GetDetachCallCount()
  1122. if actualCallCount != 0 {
  1123. return fmt.Errorf(
  1124. "At least one detacher has non-zero DetachCallCount: <%v>.",
  1125. actualCallCount)
  1126. }
  1127. }
  1128. return nil
  1129. }
  1130. // VerifySetUpDeviceCallCount ensures that at least one of the Mappers for this
  1131. // plugin has the expectedSetUpDeviceCallCount number of calls. Otherwise it
  1132. // returns an error.
  1133. func VerifySetUpDeviceCallCount(
  1134. expectedSetUpDeviceCallCount int,
  1135. fakeVolumePlugin *FakeVolumePlugin) error {
  1136. for _, mapper := range fakeVolumePlugin.GetBlockVolumeMapper() {
  1137. actualCallCount := mapper.GetSetUpDeviceCallCount()
  1138. if actualCallCount >= expectedSetUpDeviceCallCount {
  1139. return nil
  1140. }
  1141. }
  1142. return fmt.Errorf(
  1143. "No Mapper have expected SetUpDeviceCallCount. Expected: <%v>.",
  1144. expectedSetUpDeviceCallCount)
  1145. }
  1146. // VerifyTearDownDeviceCallCount ensures that at least one of the Unmappers for this
  1147. // plugin has the expectedTearDownDeviceCallCount number of calls. Otherwise it
  1148. // returns an error.
  1149. func VerifyTearDownDeviceCallCount(
  1150. expectedTearDownDeviceCallCount int,
  1151. fakeVolumePlugin *FakeVolumePlugin) error {
  1152. for _, unmapper := range fakeVolumePlugin.GetBlockVolumeUnmapper() {
  1153. actualCallCount := unmapper.GetTearDownDeviceCallCount()
  1154. if actualCallCount >= expectedTearDownDeviceCallCount {
  1155. return nil
  1156. }
  1157. }
  1158. return fmt.Errorf(
  1159. "No Unmapper have expected TearDownDeviceCallCount. Expected: <%v>.",
  1160. expectedTearDownDeviceCallCount)
  1161. }
  1162. // VerifyZeroTearDownDeviceCallCount ensures that all Mappers for this plugin have a
  1163. // zero TearDownDeviceCallCount. Otherwise it returns an error.
  1164. func VerifyZeroTearDownDeviceCallCount(fakeVolumePlugin *FakeVolumePlugin) error {
  1165. for _, unmapper := range fakeVolumePlugin.GetBlockVolumeUnmapper() {
  1166. actualCallCount := unmapper.GetTearDownDeviceCallCount()
  1167. if actualCallCount != 0 {
  1168. return fmt.Errorf(
  1169. "At least one unmapper has non-zero TearDownDeviceCallCount: <%v>.",
  1170. actualCallCount)
  1171. }
  1172. }
  1173. return nil
  1174. }
  1175. // VerifyGetGlobalMapPathCallCount ensures that at least one of the Mappers for this
  1176. // plugin has the expectedGlobalMapPathCallCount number of calls. Otherwise it returns
  1177. // an error.
  1178. func VerifyGetGlobalMapPathCallCount(
  1179. expectedGlobalMapPathCallCount int,
  1180. fakeVolumePlugin *FakeVolumePlugin) error {
  1181. for _, mapper := range fakeVolumePlugin.GetBlockVolumeMapper() {
  1182. actualCallCount := mapper.GetGlobalMapPathCallCount()
  1183. if actualCallCount == expectedGlobalMapPathCallCount {
  1184. return nil
  1185. }
  1186. }
  1187. return fmt.Errorf(
  1188. "No Mappers have expected GetGlobalMapPathCallCount. Expected: <%v>.",
  1189. expectedGlobalMapPathCallCount)
  1190. }
  1191. // VerifyGetPodDeviceMapPathCallCount ensures that at least one of the Mappers for this
  1192. // plugin has the expectedPodDeviceMapPathCallCount number of calls. Otherwise it returns
  1193. // an error.
  1194. func VerifyGetPodDeviceMapPathCallCount(
  1195. expectedPodDeviceMapPathCallCount int,
  1196. fakeVolumePlugin *FakeVolumePlugin) error {
  1197. for _, mapper := range fakeVolumePlugin.GetBlockVolumeMapper() {
  1198. actualCallCount := mapper.GetPodDeviceMapPathCallCount()
  1199. if actualCallCount == expectedPodDeviceMapPathCallCount {
  1200. return nil
  1201. }
  1202. }
  1203. return fmt.Errorf(
  1204. "No Mappers have expected GetPodDeviceMapPathCallCount. Expected: <%v>.",
  1205. expectedPodDeviceMapPathCallCount)
  1206. }
  1207. // VerifyGetMapDeviceCallCount ensures that at least one of the Mappers for this
  1208. // plugin has the expectedMapDeviceCallCount number of calls. Otherwise it
  1209. // returns an error.
  1210. func VerifyGetMapDeviceCallCount(
  1211. expectedMapDeviceCallCount int,
  1212. fakeVolumePlugin *FakeVolumePlugin) error {
  1213. for _, mapper := range fakeVolumePlugin.GetBlockVolumeMapper() {
  1214. actualCallCount := mapper.GetMapDeviceCallCount()
  1215. if actualCallCount >= expectedMapDeviceCallCount {
  1216. return nil
  1217. }
  1218. }
  1219. return fmt.Errorf(
  1220. "No Mapper have expected MapdDeviceCallCount. Expected: <%v>.",
  1221. expectedMapDeviceCallCount)
  1222. }
  1223. // GetTestVolumePluginMgr creates, initializes, and returns a test volume plugin
  1224. // manager and fake volume plugin using a fake volume host.
  1225. func GetTestVolumePluginMgr(
  1226. t *testing.T) (*VolumePluginMgr, *FakeVolumePlugin) {
  1227. v := NewFakeVolumeHost(
  1228. "", /* rootDir */
  1229. nil, /* kubeClient */
  1230. nil, /* plugins */
  1231. )
  1232. plugins := ProbeVolumePlugins(VolumeConfig{})
  1233. if err := v.pluginMgr.InitPlugins(plugins, nil /* prober */, v); err != nil {
  1234. t.Fatal(err)
  1235. }
  1236. return &v.pluginMgr, plugins[0].(*FakeVolumePlugin)
  1237. }
  1238. // CreateTestPVC returns a provisionable PVC for tests
  1239. func CreateTestPVC(capacity string, accessModes []v1.PersistentVolumeAccessMode) *v1.PersistentVolumeClaim {
  1240. claim := v1.PersistentVolumeClaim{
  1241. ObjectMeta: metav1.ObjectMeta{
  1242. Name: "dummy",
  1243. Namespace: "default",
  1244. },
  1245. Spec: v1.PersistentVolumeClaimSpec{
  1246. AccessModes: accessModes,
  1247. Resources: v1.ResourceRequirements{
  1248. Requests: v1.ResourceList{
  1249. v1.ResourceName(v1.ResourceStorage): resource.MustParse(capacity),
  1250. },
  1251. },
  1252. },
  1253. }
  1254. return &claim
  1255. }
  1256. func MetricsEqualIgnoreTimestamp(a *Metrics, b *Metrics) bool {
  1257. available := a.Available == b.Available
  1258. capacity := a.Capacity == b.Capacity
  1259. used := a.Used == b.Used
  1260. inodes := a.Inodes == b.Inodes
  1261. inodesFree := a.InodesFree == b.InodesFree
  1262. inodesUsed := a.InodesUsed == b.InodesUsed
  1263. return available && capacity && used && inodes && inodesFree && inodesUsed
  1264. }
  1265. func ContainsAccessMode(modes []v1.PersistentVolumeAccessMode, mode v1.PersistentVolumeAccessMode) bool {
  1266. for _, m := range modes {
  1267. if m == mode {
  1268. return true
  1269. }
  1270. }
  1271. return false
  1272. }
  1273. func (f *fakeVolumeHost) CSIDriverLister() storagelisters.CSIDriverLister {
  1274. return f.csiDriverLister
  1275. }
  1276. func (f *fakeVolumeHost) CSINodeLister() storagelisters.CSINodeLister {
  1277. // not needed for testing
  1278. return nil
  1279. }
  1280. func (f *fakeVolumeHost) IsAttachDetachController() bool {
  1281. return true
  1282. }