1
16
17 package volume
18
19 import (
20 "fmt"
21 "net"
22 "strings"
23 "sync"
24
25 "k8s.io/apimachinery/pkg/util/sets"
26 "k8s.io/klog/v2"
27 "k8s.io/mount-utils"
28 "k8s.io/utils/exec"
29
30 authenticationv1 "k8s.io/api/authentication/v1"
31 v1 "k8s.io/api/core/v1"
32 "k8s.io/apimachinery/pkg/api/resource"
33 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
34 "k8s.io/apimachinery/pkg/types"
35 utilerrors "k8s.io/apimachinery/pkg/util/errors"
36 "k8s.io/apimachinery/pkg/util/validation"
37 "k8s.io/client-go/informers"
38 clientset "k8s.io/client-go/kubernetes"
39 storagelistersv1 "k8s.io/client-go/listers/storage/v1"
40 "k8s.io/client-go/tools/cache"
41 "k8s.io/client-go/tools/record"
42 cloudprovider "k8s.io/cloud-provider"
43 "k8s.io/kubernetes/pkg/volume/util/hostutil"
44 "k8s.io/kubernetes/pkg/volume/util/recyclerclient"
45 "k8s.io/kubernetes/pkg/volume/util/subpath"
46 )
47
48 type ProbeOperation uint32
49 type ProbeEvent struct {
50 Plugin VolumePlugin
51 PluginName string
52 Op ProbeOperation
53 }
54
55 const (
56
57
58
59
60 VolumeParameterFSType = "fstype"
61
62 ProbeAddOrUpdate ProbeOperation = 1 << iota
63 ProbeRemove
64 )
65
66
67 type VolumeOptions struct {
68
69
70
71
72
73 PersistentVolumeReclaimPolicy v1.PersistentVolumeReclaimPolicy
74
75 MountOptions []string
76
77
78
79
80 PVName string
81
82
83
84
85 PVC *v1.PersistentVolumeClaim
86
87 ClusterName string
88
89 CloudTags *map[string]string
90
91 Parameters map[string]string
92 }
93
94
95 type NodeResizeOptions struct {
96 VolumeSpec *Spec
97
98
99
100 DevicePath string
101
102
103
104
105 DeviceMountPath string
106
107
108 DeviceStagePath string
109
110 NewSize resource.Quantity
111 OldSize resource.Quantity
112 }
113
114 type DynamicPluginProber interface {
115 Init() error
116
117
118 Probe() (events []ProbeEvent, err error)
119 }
120
121
122
123 type VolumePlugin interface {
124
125
126
127 Init(host VolumeHost) error
128
129
130
131
132
133 GetPluginName() string
134
135
136
137
138
139
140
141 GetVolumeName(spec *Spec) (string, error)
142
143
144
145
146 CanSupport(spec *Spec) bool
147
148
149
150
151 RequiresRemount(spec *Spec) bool
152
153
154
155
156
157 NewMounter(spec *Spec, podRef *v1.Pod, opts VolumeOptions) (Mounter, error)
158
159
160
161
162 NewUnmounter(name string, podUID types.UID) (Unmounter, error)
163
164
165
166
167
168 ConstructVolumeSpec(volumeName, volumePath string) (ReconstructedVolume, error)
169
170
171
172
173 SupportsMountOption() bool
174
175
176
177
178 SupportsBulkVolumeVerification() bool
179
180
181
182 SupportsSELinuxContextMount(spec *Spec) (bool, error)
183 }
184
185
186
187 type PersistentVolumePlugin interface {
188 VolumePlugin
189
190 GetAccessModes() []v1.PersistentVolumeAccessMode
191 }
192
193
194
195
196 type RecyclableVolumePlugin interface {
197 VolumePlugin
198
199
200
201
202
203
204 Recycle(pvName string, spec *Spec, eventRecorder recyclerclient.RecycleEventRecorder) error
205 }
206
207
208
209
210 type DeletableVolumePlugin interface {
211 VolumePlugin
212
213
214
215 NewDeleter(logger klog.Logger, spec *Spec) (Deleter, error)
216 }
217
218
219
220 type ProvisionableVolumePlugin interface {
221 VolumePlugin
222
223
224
225 NewProvisioner(logger klog.Logger, options VolumeOptions) (Provisioner, error)
226 }
227
228
229
230 type AttachableVolumePlugin interface {
231 DeviceMountableVolumePlugin
232 NewAttacher() (Attacher, error)
233 NewDetacher() (Detacher, error)
234
235 CanAttach(spec *Spec) (bool, error)
236 }
237
238
239
240 type DeviceMountableVolumePlugin interface {
241 VolumePlugin
242 NewDeviceMounter() (DeviceMounter, error)
243 NewDeviceUnmounter() (DeviceUnmounter, error)
244 GetDeviceMountRefs(deviceMountPath string) ([]string, error)
245
246 CanDeviceMount(spec *Spec) (bool, error)
247 }
248
249
250
251 type ExpandableVolumePlugin interface {
252 VolumePlugin
253 ExpandVolumeDevice(spec *Spec, newSize resource.Quantity, oldSize resource.Quantity) (resource.Quantity, error)
254 RequiresFSResize() bool
255 }
256
257
258
259 type NodeExpandableVolumePlugin interface {
260 VolumePlugin
261 RequiresFSResize() bool
262
263 NodeExpand(resizeOptions NodeResizeOptions) (bool, error)
264 }
265
266
267
268 type VolumePluginWithAttachLimits interface {
269 VolumePlugin
270
271
272
273
274
275
276
277
278
279
280
281 GetVolumeLimits() (map[string]int64, error)
282
283
284
285
286
287
288
289 VolumeLimitKey(spec *Spec) string
290 }
291
292
293 type BlockVolumePlugin interface {
294 VolumePlugin
295
296
297
298
299 NewBlockVolumeMapper(spec *Spec, podRef *v1.Pod, opts VolumeOptions) (BlockVolumeMapper, error)
300
301
302
303 NewBlockVolumeUnmapper(name string, podUID types.UID) (BlockVolumeUnmapper, error)
304
305
306
307
308
309 ConstructBlockVolumeSpec(podUID types.UID, volumeName, volumePath string) (*Spec, error)
310 }
311
312
313
314
315
316
317
318
319
320
321 type KubeletVolumeHost interface {
322
323
324 SetKubeletError(err error)
325
326
327 GetInformerFactory() informers.SharedInformerFactory
328
329 CSIDriverLister() storagelistersv1.CSIDriverLister
330
331 CSIDriversSynced() cache.InformerSynced
332
333 WaitForCacheSync() error
334
335 GetHostUtil() hostutil.HostUtils
336
337
338 GetTrustAnchorsByName(name string, allowMissing bool) ([]byte, error)
339
340
341
342 GetTrustAnchorsBySigner(signerName string, labelSelector *metav1.LabelSelector, allowMissing bool) ([]byte, error)
343 }
344
345
346
347 type AttachDetachVolumeHost interface {
348
349 CSINodeLister() storagelistersv1.CSINodeLister
350
351
352 CSIDriverLister() storagelistersv1.CSIDriverLister
353
354
355 VolumeAttachmentLister() storagelistersv1.VolumeAttachmentLister
356
357
358 IsAttachDetachController() bool
359 }
360
361
362 type VolumeHost interface {
363
364
365
366
367 GetPluginDir(pluginName string) string
368
369
370
371
372 GetVolumeDevicePluginDir(pluginName string) string
373
374
375
376 GetPodsDir() string
377
378
379
380
381
382 GetPodVolumeDir(podUID types.UID, pluginName string, volumeName string) string
383
384
385
386
387
388 GetPodPluginDir(podUID types.UID, pluginName string) string
389
390
391
392
393
394
395 GetPodVolumeDeviceDir(podUID types.UID, pluginName string) string
396
397
398 GetKubeClient() clientset.Interface
399
400
401
402
403
404 NewWrapperMounter(volName string, spec Spec, pod *v1.Pod, opts VolumeOptions) (Mounter, error)
405
406
407
408
409 NewWrapperUnmounter(volName string, spec Spec, podUID types.UID) (Unmounter, error)
410
411
412 GetCloudProvider() cloudprovider.Interface
413
414
415 GetMounter(pluginName string) mount.Interface
416
417
418 GetHostName() string
419
420
421 GetHostIP() (net.IP, error)
422
423
424 GetNodeAllocatable() (v1.ResourceList, error)
425
426
427 GetSecretFunc() func(namespace, name string) (*v1.Secret, error)
428
429
430 GetConfigMapFunc() func(namespace, name string) (*v1.ConfigMap, error)
431
432 GetServiceAccountTokenFunc() func(namespace, name string, tr *authenticationv1.TokenRequest) (*authenticationv1.TokenRequest, error)
433
434 DeleteServiceAccountTokenFunc() func(podUID types.UID)
435
436
437 GetExec(pluginName string) exec.Interface
438
439
440 GetNodeLabels() (map[string]string, error)
441
442
443 GetNodeName() types.NodeName
444
445 GetAttachedVolumesFromNodeStatus() (map[v1.UniqueVolumeName]string, error)
446
447
448 GetEventRecorder() record.EventRecorder
449
450
451 GetSubpather() subpath.Interface
452 }
453
454
455 type VolumePluginMgr struct {
456 mutex sync.RWMutex
457 plugins map[string]VolumePlugin
458 prober DynamicPluginProber
459 probedPlugins map[string]VolumePlugin
460 loggedDeprecationWarnings sets.String
461 Host VolumeHost
462 }
463
464
465 type Spec struct {
466 Volume *v1.Volume
467 PersistentVolume *v1.PersistentVolume
468 ReadOnly bool
469 InlineVolumeSpecForCSIMigration bool
470 Migrated bool
471 }
472
473
474 func (spec *Spec) Name() string {
475 switch {
476 case spec.Volume != nil:
477 return spec.Volume.Name
478 case spec.PersistentVolume != nil:
479 return spec.PersistentVolume.Name
480 default:
481 return ""
482 }
483 }
484
485
486
487
488 func (spec *Spec) IsKubeletExpandable() bool {
489 switch {
490 case spec.Volume != nil:
491 return spec.Volume.FlexVolume != nil
492 case spec.PersistentVolume != nil:
493 return spec.PersistentVolume.Spec.FlexVolume != nil
494 default:
495 return false
496 }
497 }
498
499
500
501
502
503 func (spec *Spec) KubeletExpandablePluginName() string {
504 switch {
505 case spec.Volume != nil && spec.Volume.FlexVolume != nil:
506 return spec.Volume.FlexVolume.Driver
507 case spec.PersistentVolume != nil && spec.PersistentVolume.Spec.FlexVolume != nil:
508 return spec.PersistentVolume.Spec.FlexVolume.Driver
509 default:
510 return ""
511 }
512 }
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536 type VolumeConfig struct {
537
538
539
540
541
542 RecyclerPodTemplate *v1.Pod
543
544
545
546
547 RecyclerMinimumTimeout int
548
549
550
551
552
553 RecyclerTimeoutIncrement int
554
555
556
557 PVName string
558
559
560
561
562 OtherAttributes map[string]string
563
564
565
566 ProvisioningEnabled bool
567 }
568
569
570
571 type ReconstructedVolume struct {
572
573 Spec *Spec
574
575
576 SELinuxMountContext string
577 }
578
579
580 func NewSpecFromVolume(vs *v1.Volume) *Spec {
581 return &Spec{
582 Volume: vs,
583 }
584 }
585
586
587 func NewSpecFromPersistentVolume(pv *v1.PersistentVolume, readOnly bool) *Spec {
588 return &Spec{
589 PersistentVolume: pv,
590 ReadOnly: readOnly,
591 }
592 }
593
594
595
596
597 func (pm *VolumePluginMgr) InitPlugins(plugins []VolumePlugin, prober DynamicPluginProber, host VolumeHost) error {
598 pm.mutex.Lock()
599 defer pm.mutex.Unlock()
600
601 pm.Host = host
602 pm.loggedDeprecationWarnings = sets.NewString()
603
604 if prober == nil {
605
606 pm.prober = &dummyPluginProber{}
607 } else {
608 pm.prober = prober
609 }
610 if err := pm.prober.Init(); err != nil {
611
612 klog.ErrorS(err, "Error initializing dynamic plugin prober")
613 pm.prober = &dummyPluginProber{}
614 }
615
616 if pm.plugins == nil {
617 pm.plugins = map[string]VolumePlugin{}
618 }
619 if pm.probedPlugins == nil {
620 pm.probedPlugins = map[string]VolumePlugin{}
621 }
622
623 allErrs := []error{}
624 for _, plugin := range plugins {
625 name := plugin.GetPluginName()
626 if errs := validation.IsQualifiedName(name); len(errs) != 0 {
627 allErrs = append(allErrs, fmt.Errorf("volume plugin has invalid name: %q: %s", name, strings.Join(errs, ";")))
628 continue
629 }
630
631 if _, found := pm.plugins[name]; found {
632 allErrs = append(allErrs, fmt.Errorf("volume plugin %q was registered more than once", name))
633 continue
634 }
635 err := plugin.Init(host)
636 if err != nil {
637 klog.ErrorS(err, "Failed to load volume plugin", "pluginName", name)
638 allErrs = append(allErrs, err)
639 continue
640 }
641 pm.plugins[name] = plugin
642 klog.V(1).InfoS("Loaded volume plugin", "pluginName", name)
643 }
644 return utilerrors.NewAggregate(allErrs)
645 }
646
647 func (pm *VolumePluginMgr) initProbedPlugin(probedPlugin VolumePlugin) error {
648 name := probedPlugin.GetPluginName()
649 if errs := validation.IsQualifiedName(name); len(errs) != 0 {
650 return fmt.Errorf("volume plugin has invalid name: %q: %s", name, strings.Join(errs, ";"))
651 }
652
653 err := probedPlugin.Init(pm.Host)
654 if err != nil {
655 return fmt.Errorf("failed to load volume plugin %s, error: %s", name, err.Error())
656 }
657
658 klog.V(1).InfoS("Loaded volume plugin", "pluginName", name)
659 return nil
660 }
661
662
663
664
665 func (pm *VolumePluginMgr) FindPluginBySpec(spec *Spec) (VolumePlugin, error) {
666 pm.mutex.RLock()
667 defer pm.mutex.RUnlock()
668
669 if spec == nil {
670 return nil, fmt.Errorf("could not find plugin because volume spec is nil")
671 }
672
673 var match VolumePlugin
674 matchedPluginNames := []string{}
675 for _, v := range pm.plugins {
676 if v.CanSupport(spec) {
677 match = v
678 matchedPluginNames = append(matchedPluginNames, v.GetPluginName())
679 }
680 }
681
682 pm.refreshProbedPlugins()
683 for _, plugin := range pm.probedPlugins {
684 if plugin.CanSupport(spec) {
685 match = plugin
686 matchedPluginNames = append(matchedPluginNames, plugin.GetPluginName())
687 }
688 }
689
690 if len(matchedPluginNames) == 0 {
691 return nil, fmt.Errorf("no volume plugin matched")
692 }
693 if len(matchedPluginNames) > 1 {
694 return nil, fmt.Errorf("multiple volume plugins matched: %s", strings.Join(matchedPluginNames, ","))
695 }
696
697 return match, nil
698 }
699
700
701 func (pm *VolumePluginMgr) FindPluginByName(name string) (VolumePlugin, error) {
702 pm.mutex.RLock()
703 defer pm.mutex.RUnlock()
704
705 var match VolumePlugin
706 if v, found := pm.plugins[name]; found {
707 match = v
708 }
709
710 pm.refreshProbedPlugins()
711 if plugin, found := pm.probedPlugins[name]; found {
712 if match != nil {
713 return nil, fmt.Errorf("multiple volume plugins matched: %s and %s", match.GetPluginName(), plugin.GetPluginName())
714 }
715 match = plugin
716 }
717
718 if match == nil {
719 return nil, fmt.Errorf("no volume plugin matched name: %s", name)
720 }
721 return match, nil
722 }
723
724
725
726 func (pm *VolumePluginMgr) refreshProbedPlugins() {
727 events, err := pm.prober.Probe()
728
729 if err != nil {
730 klog.ErrorS(err, "Error dynamically probing plugins")
731 }
732
733
734
735
736 for _, event := range events {
737 if event.Op == ProbeAddOrUpdate {
738 if err := pm.initProbedPlugin(event.Plugin); err != nil {
739 klog.ErrorS(err, "Error initializing dynamically probed plugin",
740 "pluginName", event.Plugin.GetPluginName())
741 continue
742 }
743 pm.probedPlugins[event.Plugin.GetPluginName()] = event.Plugin
744 } else if event.Op == ProbeRemove {
745
746 delete(pm.probedPlugins, event.PluginName)
747 } else {
748 klog.ErrorS(nil, "Unknown Operation on PluginName.",
749 "pluginName", event.Plugin.GetPluginName())
750 }
751 }
752 }
753
754
755 func (pm *VolumePluginMgr) ListVolumePluginWithLimits() []VolumePluginWithAttachLimits {
756 pm.mutex.RLock()
757 defer pm.mutex.RUnlock()
758
759 matchedPlugins := []VolumePluginWithAttachLimits{}
760 for _, v := range pm.plugins {
761 if plugin, ok := v.(VolumePluginWithAttachLimits); ok {
762 matchedPlugins = append(matchedPlugins, plugin)
763 }
764 }
765 return matchedPlugins
766 }
767
768
769
770
771 func (pm *VolumePluginMgr) FindPersistentPluginBySpec(spec *Spec) (PersistentVolumePlugin, error) {
772 volumePlugin, err := pm.FindPluginBySpec(spec)
773 if err != nil {
774 return nil, fmt.Errorf("could not find volume plugin for spec: %#v", spec)
775 }
776 if persistentVolumePlugin, ok := volumePlugin.(PersistentVolumePlugin); ok {
777 return persistentVolumePlugin, nil
778 }
779 return nil, fmt.Errorf("no persistent volume plugin matched")
780 }
781
782
783
784 func (pm *VolumePluginMgr) FindVolumePluginWithLimitsBySpec(spec *Spec) (VolumePluginWithAttachLimits, error) {
785 volumePlugin, err := pm.FindPluginBySpec(spec)
786 if err != nil {
787 return nil, fmt.Errorf("could not find volume plugin for spec : %#v", spec)
788 }
789
790 if limitedPlugin, ok := volumePlugin.(VolumePluginWithAttachLimits); ok {
791 return limitedPlugin, nil
792 }
793 return nil, fmt.Errorf("no plugin with limits found")
794 }
795
796
797
798 func (pm *VolumePluginMgr) FindPersistentPluginByName(name string) (PersistentVolumePlugin, error) {
799 volumePlugin, err := pm.FindPluginByName(name)
800 if err != nil {
801 return nil, err
802 }
803 if persistentVolumePlugin, ok := volumePlugin.(PersistentVolumePlugin); ok {
804 return persistentVolumePlugin, nil
805 }
806 return nil, fmt.Errorf("no persistent volume plugin matched")
807 }
808
809
810
811 func (pm *VolumePluginMgr) FindRecyclablePluginBySpec(spec *Spec) (RecyclableVolumePlugin, error) {
812 volumePlugin, err := pm.FindPluginBySpec(spec)
813 if err != nil {
814 return nil, err
815 }
816 if recyclableVolumePlugin, ok := volumePlugin.(RecyclableVolumePlugin); ok {
817 return recyclableVolumePlugin, nil
818 }
819 return nil, fmt.Errorf("no recyclable volume plugin matched")
820 }
821
822
823
824 func (pm *VolumePluginMgr) FindProvisionablePluginByName(name string) (ProvisionableVolumePlugin, error) {
825 volumePlugin, err := pm.FindPluginByName(name)
826 if err != nil {
827 return nil, err
828 }
829 if provisionableVolumePlugin, ok := volumePlugin.(ProvisionableVolumePlugin); ok {
830 return provisionableVolumePlugin, nil
831 }
832 return nil, fmt.Errorf("no provisionable volume plugin matched")
833 }
834
835
836
837 func (pm *VolumePluginMgr) FindDeletablePluginBySpec(spec *Spec) (DeletableVolumePlugin, error) {
838 volumePlugin, err := pm.FindPluginBySpec(spec)
839 if err != nil {
840 return nil, err
841 }
842 if deletableVolumePlugin, ok := volumePlugin.(DeletableVolumePlugin); ok {
843 return deletableVolumePlugin, nil
844 }
845 return nil, fmt.Errorf("no deletable volume plugin matched")
846 }
847
848
849
850 func (pm *VolumePluginMgr) FindDeletablePluginByName(name string) (DeletableVolumePlugin, error) {
851 volumePlugin, err := pm.FindPluginByName(name)
852 if err != nil {
853 return nil, err
854 }
855 if deletableVolumePlugin, ok := volumePlugin.(DeletableVolumePlugin); ok {
856 return deletableVolumePlugin, nil
857 }
858 return nil, fmt.Errorf("no deletable volume plugin matched")
859 }
860
861
862
863 func (pm *VolumePluginMgr) FindCreatablePluginBySpec(spec *Spec) (ProvisionableVolumePlugin, error) {
864 volumePlugin, err := pm.FindPluginBySpec(spec)
865 if err != nil {
866 return nil, err
867 }
868 if provisionableVolumePlugin, ok := volumePlugin.(ProvisionableVolumePlugin); ok {
869 return provisionableVolumePlugin, nil
870 }
871 return nil, fmt.Errorf("no creatable volume plugin matched")
872 }
873
874
875
876
877
878 func (pm *VolumePluginMgr) FindAttachablePluginBySpec(spec *Spec) (AttachableVolumePlugin, error) {
879 volumePlugin, err := pm.FindPluginBySpec(spec)
880 if err != nil {
881 return nil, err
882 }
883 if attachableVolumePlugin, ok := volumePlugin.(AttachableVolumePlugin); ok {
884 if canAttach, err := attachableVolumePlugin.CanAttach(spec); err != nil {
885 return nil, err
886 } else if canAttach {
887 return attachableVolumePlugin, nil
888 }
889 }
890 return nil, nil
891 }
892
893
894
895
896
897 func (pm *VolumePluginMgr) FindAttachablePluginByName(name string) (AttachableVolumePlugin, error) {
898 volumePlugin, err := pm.FindPluginByName(name)
899 if err != nil {
900 return nil, err
901 }
902 if attachablePlugin, ok := volumePlugin.(AttachableVolumePlugin); ok {
903 return attachablePlugin, nil
904 }
905 return nil, nil
906 }
907
908
909 func (pm *VolumePluginMgr) FindDeviceMountablePluginBySpec(spec *Spec) (DeviceMountableVolumePlugin, error) {
910 volumePlugin, err := pm.FindPluginBySpec(spec)
911 if err != nil {
912 return nil, err
913 }
914 if deviceMountableVolumePlugin, ok := volumePlugin.(DeviceMountableVolumePlugin); ok {
915 if canMount, err := deviceMountableVolumePlugin.CanDeviceMount(spec); err != nil {
916 return nil, err
917 } else if canMount {
918 return deviceMountableVolumePlugin, nil
919 }
920 }
921 return nil, nil
922 }
923
924
925 func (pm *VolumePluginMgr) FindDeviceMountablePluginByName(name string) (DeviceMountableVolumePlugin, error) {
926 volumePlugin, err := pm.FindPluginByName(name)
927 if err != nil {
928 return nil, err
929 }
930 if deviceMountableVolumePlugin, ok := volumePlugin.(DeviceMountableVolumePlugin); ok {
931 return deviceMountableVolumePlugin, nil
932 }
933 return nil, nil
934 }
935
936
937 func (pm *VolumePluginMgr) FindExpandablePluginBySpec(spec *Spec) (ExpandableVolumePlugin, error) {
938 volumePlugin, err := pm.FindPluginBySpec(spec)
939 if err != nil {
940 if spec.IsKubeletExpandable() {
941
942
943 klog.V(4).InfoS("FindExpandablePluginBySpec -> returning noopExpandableVolumePluginInstance", "specName", spec.Name())
944 return &noopExpandableVolumePluginInstance{spec}, nil
945 }
946 klog.V(4).InfoS("FindExpandablePluginBySpec -> err", "specName", spec.Name(), "err", err)
947 return nil, err
948 }
949
950 if expandableVolumePlugin, ok := volumePlugin.(ExpandableVolumePlugin); ok {
951 return expandableVolumePlugin, nil
952 }
953 return nil, nil
954 }
955
956
957 func (pm *VolumePluginMgr) FindExpandablePluginByName(name string) (ExpandableVolumePlugin, error) {
958 volumePlugin, err := pm.FindPluginByName(name)
959 if err != nil {
960 return nil, err
961 }
962
963 if expandableVolumePlugin, ok := volumePlugin.(ExpandableVolumePlugin); ok {
964 return expandableVolumePlugin, nil
965 }
966 return nil, nil
967 }
968
969
970 func (pm *VolumePluginMgr) FindMapperPluginBySpec(spec *Spec) (BlockVolumePlugin, error) {
971 volumePlugin, err := pm.FindPluginBySpec(spec)
972 if err != nil {
973 return nil, err
974 }
975
976 if blockVolumePlugin, ok := volumePlugin.(BlockVolumePlugin); ok {
977 return blockVolumePlugin, nil
978 }
979 return nil, nil
980 }
981
982
983 func (pm *VolumePluginMgr) FindMapperPluginByName(name string) (BlockVolumePlugin, error) {
984 volumePlugin, err := pm.FindPluginByName(name)
985 if err != nil {
986 return nil, err
987 }
988
989 if blockVolumePlugin, ok := volumePlugin.(BlockVolumePlugin); ok {
990 return blockVolumePlugin, nil
991 }
992 return nil, nil
993 }
994
995
996 func (pm *VolumePluginMgr) FindNodeExpandablePluginBySpec(spec *Spec) (NodeExpandableVolumePlugin, error) {
997 volumePlugin, err := pm.FindPluginBySpec(spec)
998 if err != nil {
999 return nil, err
1000 }
1001 if fsResizablePlugin, ok := volumePlugin.(NodeExpandableVolumePlugin); ok {
1002 return fsResizablePlugin, nil
1003 }
1004 return nil, nil
1005 }
1006
1007
1008 func (pm *VolumePluginMgr) FindNodeExpandablePluginByName(name string) (NodeExpandableVolumePlugin, error) {
1009 volumePlugin, err := pm.FindPluginByName(name)
1010 if err != nil {
1011 return nil, err
1012 }
1013
1014 if fsResizablePlugin, ok := volumePlugin.(NodeExpandableVolumePlugin); ok {
1015 return fsResizablePlugin, nil
1016 }
1017
1018 return nil, nil
1019 }
1020
1021 func (pm *VolumePluginMgr) Run(stopCh <-chan struct{}) {
1022 kletHost, ok := pm.Host.(KubeletVolumeHost)
1023 if ok {
1024
1025 informerFactory := kletHost.GetInformerFactory()
1026 informerFactory.Start(stopCh)
1027 informerFactory.WaitForCacheSync(stopCh)
1028 }
1029 }
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045 func NewPersistentVolumeRecyclerPodTemplate() *v1.Pod {
1046 timeout := int64(60)
1047 pod := &v1.Pod{
1048 ObjectMeta: metav1.ObjectMeta{
1049 GenerateName: "pv-recycler-",
1050 Namespace: metav1.NamespaceDefault,
1051 },
1052 Spec: v1.PodSpec{
1053 ActiveDeadlineSeconds: &timeout,
1054 RestartPolicy: v1.RestartPolicyNever,
1055 Volumes: []v1.Volume{
1056 {
1057 Name: "vol",
1058
1059
1060
1061 VolumeSource: v1.VolumeSource{},
1062 },
1063 },
1064 Containers: []v1.Container{
1065 {
1066 Name: "pv-recycler",
1067 Image: "registry.k8s.io/build-image/debian-base:bookworm-v1.0.2",
1068 Command: []string{"/bin/sh"},
1069 Args: []string{"-c", "test -e /scrub && find /scrub -mindepth 1 -delete && test -z \"$(ls -A /scrub)\" || exit 1"},
1070 VolumeMounts: []v1.VolumeMount{
1071 {
1072 Name: "vol",
1073 MountPath: "/scrub",
1074 },
1075 },
1076 },
1077 },
1078 },
1079 }
1080 return pod
1081 }
1082
1083
1084
1085
1086
1087
1088 func ValidateRecyclerPodTemplate(pod *v1.Pod) error {
1089 if len(pod.Spec.Volumes) < 1 {
1090 return fmt.Errorf("does not contain any volume(s)")
1091 }
1092 return nil
1093 }
1094
1095 type dummyPluginProber struct{}
1096
1097 func (*dummyPluginProber) Init() error { return nil }
1098 func (*dummyPluginProber) Probe() ([]ProbeEvent, error) { return nil, nil }
1099
View as plain text