1
16
17
21 package cache
22
23 import (
24 "fmt"
25 "sync"
26
27 v1 "k8s.io/api/core/v1"
28 "k8s.io/apimachinery/pkg/api/resource"
29 "k8s.io/apimachinery/pkg/types"
30 utilfeature "k8s.io/apiserver/pkg/util/feature"
31 "k8s.io/klog/v2"
32 "k8s.io/kubernetes/pkg/features"
33 "k8s.io/kubernetes/pkg/volume"
34 "k8s.io/kubernetes/pkg/volume/util"
35 "k8s.io/kubernetes/pkg/volume/util/operationexecutor"
36 volumetypes "k8s.io/kubernetes/pkg/volume/util/types"
37 )
38
39
40
41
42
43
44
45
46
47 type ActualStateOfWorld interface {
48
49
50 operationexecutor.ActualStateOfWorldMounterUpdater
51
52
53
54 operationexecutor.ActualStateOfWorldAttacherUpdater
55
56
57
58
59
60
61
62
63 AddPodToVolume(operationexecutor.MarkVolumeOpts) error
64
65
66
67
68
69
70 MarkRemountRequired(podName volumetypes.UniquePodName)
71
72
73
74
75
76
77
78 SetDeviceMountState(volumeName v1.UniqueVolumeName, deviceMountState operationexecutor.DeviceMountState, devicePath, deviceMountPath, seLinuxMountContext string) error
79
80
81
82
83
84
85
86 DeletePodFromVolume(podName volumetypes.UniquePodName, volumeName v1.UniqueVolumeName) error
87
88
89
90
91
92
93
94
95 DeleteVolume(volumeName v1.UniqueVolumeName) error
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112 PodExistsInVolume(podName volumetypes.UniquePodName, volumeName v1.UniqueVolumeName, desiredVolumeSize resource.Quantity, seLinuxLabel string) (bool, string, error)
113
114
115
116
117
118
119
120 PodRemovedFromVolume(podName volumetypes.UniquePodName, volumeName v1.UniqueVolumeName) bool
121
122
123
124
125
126
127 VolumeExistsWithSpecName(podName volumetypes.UniquePodName, volumeSpecName string) bool
128
129
130
131
132 VolumeExists(volumeName v1.UniqueVolumeName) bool
133
134
135
136
137 GetMountedVolumes() []MountedVolume
138
139
140
141 GetAllMountedVolumes() []MountedVolume
142
143
144
145
146 GetMountedVolumesForPod(podName volumetypes.UniquePodName) []MountedVolume
147
148
149
150
151 GetPossiblyMountedVolumesForPod(podName volumetypes.UniquePodName) []MountedVolume
152
153
154
155
156
157
158
159 GetGloballyMountedVolumes() []AttachedVolume
160
161
162
163
164 GetUnmountedVolumes() []AttachedVolume
165
166
167
168
169 GetAttachedVolumes() []AttachedVolume
170
171
172
173 SyncReconstructedVolume(volumeName v1.UniqueVolumeName, podName volumetypes.UniquePodName, outerVolumeSpecName string)
174
175
176 AddAttachUncertainReconstructedVolume(volumeName v1.UniqueVolumeName, volumeSpec *volume.Spec, nodeName types.NodeName, devicePath string) error
177
178
179
180
181
182 UpdateReconstructedDevicePath(volumeName v1.UniqueVolumeName, devicePath string)
183
184
185 UpdateReconstructedVolumeAttachability(volumeName v1.UniqueVolumeName, volumeAttachable bool)
186 }
187
188
189 type MountedVolume struct {
190 operationexecutor.MountedVolume
191 }
192
193
194 type AttachedVolume struct {
195 operationexecutor.AttachedVolume
196
197
198 DeviceMountState operationexecutor.DeviceMountState
199
200
201
202
203 SELinuxMountContext string
204 }
205
206
207
208 func (av AttachedVolume) DeviceMayBeMounted() bool {
209 return av.DeviceMountState == operationexecutor.DeviceGloballyMounted ||
210 av.DeviceMountState == operationexecutor.DeviceMountUncertain
211 }
212
213
214 func NewActualStateOfWorld(
215 nodeName types.NodeName,
216 volumePluginMgr *volume.VolumePluginMgr) ActualStateOfWorld {
217 return &actualStateOfWorld{
218 nodeName: nodeName,
219 attachedVolumes: make(map[v1.UniqueVolumeName]attachedVolume),
220 foundDuringReconstruction: make(map[v1.UniqueVolumeName]map[volumetypes.UniquePodName]types.UID),
221 volumePluginMgr: volumePluginMgr,
222 }
223 }
224
225
226
227 func IsVolumeNotAttachedError(err error) bool {
228 _, ok := err.(volumeNotAttachedError)
229 return ok
230 }
231
232
233
234 func IsRemountRequiredError(err error) bool {
235 _, ok := err.(remountRequiredError)
236 return ok
237 }
238
239 type actualStateOfWorld struct {
240
241 nodeName types.NodeName
242
243
244
245
246
247
248
249 attachedVolumes map[v1.UniqueVolumeName]attachedVolume
250
251
252 foundDuringReconstruction map[v1.UniqueVolumeName]map[volumetypes.UniquePodName]types.UID
253
254
255
256 volumePluginMgr *volume.VolumePluginMgr
257 sync.RWMutex
258 }
259
260 type volumeAttachability string
261
262 const (
263 volumeAttachabilityTrue volumeAttachability = "True"
264 volumeAttachabilityFalse volumeAttachability = "False"
265 volumeAttachabilityUncertain volumeAttachability = "Uncertain"
266 )
267
268
269
270
271 type attachedVolume struct {
272
273 volumeName v1.UniqueVolumeName
274
275
276
277
278
279 mountedPods map[volumetypes.UniquePodName]mountedPod
280
281
282
283
284
285
286 spec *volume.Spec
287
288
289
290
291
292
293 pluginName string
294
295
296
297 pluginIsAttachable volumeAttachability
298
299
300
301 deviceMountState operationexecutor.DeviceMountState
302
303
304
305 devicePath string
306
307
308
309 deviceMountPath string
310
311
312
313 volumeInUseErrorForExpansion bool
314
315
316
317 persistentVolumeSize *resource.Quantity
318
319
320
321
322 seLinuxMountContext *string
323 }
324
325
326
327 type mountedPod struct {
328
329 podName volumetypes.UniquePodName
330
331
332 podUID types.UID
333
334
335 mounter volume.Mounter
336
337
338 blockVolumeMapper volume.BlockVolumeMapper
339
340
341
342
343
344
345 volumeSpec *volume.Spec
346
347
348
349
350
351 outerVolumeSpecName string
352
353
354
355
356
357
358
359 remountRequired bool
360
361
362 volumeGidValue string
363
364
365
366
367 volumeMountStateForPod operationexecutor.VolumeMountState
368
369
370
371
372 seLinuxMountContext string
373 }
374
375 func (asw *actualStateOfWorld) MarkVolumeAsAttached(
376 logger klog.Logger,
377 volumeName v1.UniqueVolumeName, volumeSpec *volume.Spec, _ types.NodeName, devicePath string) error {
378
379 pluginIsAttachable := volumeAttachabilityFalse
380 if attachablePlugin, err := asw.volumePluginMgr.FindAttachablePluginBySpec(volumeSpec); err == nil && attachablePlugin != nil {
381 pluginIsAttachable = volumeAttachabilityTrue
382 }
383
384 return asw.addVolume(volumeName, volumeSpec, devicePath, pluginIsAttachable)
385 }
386
387 func (asw *actualStateOfWorld) AddAttachUncertainReconstructedVolume(
388 volumeName v1.UniqueVolumeName, volumeSpec *volume.Spec, _ types.NodeName, devicePath string) error {
389
390 return asw.addVolume(volumeName, volumeSpec, devicePath, volumeAttachabilityUncertain)
391 }
392
393 func (asw *actualStateOfWorld) MarkVolumeAsUncertain(
394 logger klog.Logger, volumeName v1.UniqueVolumeName, volumeSpec *volume.Spec, _ types.NodeName) error {
395 return nil
396 }
397
398 func (asw *actualStateOfWorld) MarkVolumeAsDetached(
399 volumeName v1.UniqueVolumeName, nodeName types.NodeName) {
400 asw.DeleteVolume(volumeName)
401 }
402
403 func (asw *actualStateOfWorld) IsVolumeReconstructed(volumeName v1.UniqueVolumeName, podName volumetypes.UniquePodName) bool {
404 volumeState := asw.GetVolumeMountState(volumeName, podName)
405
406
407 if volumeState != operationexecutor.VolumeMountUncertain {
408 return false
409 }
410
411 asw.RLock()
412 defer asw.RUnlock()
413 podMap, ok := asw.foundDuringReconstruction[volumeName]
414 if !ok {
415 return false
416 }
417 _, foundPod := podMap[podName]
418 return foundPod
419 }
420
421 func (asw *actualStateOfWorld) IsVolumeDeviceReconstructed(volumeName v1.UniqueVolumeName) bool {
422 asw.RLock()
423 defer asw.RUnlock()
424 _, ok := asw.foundDuringReconstruction[volumeName]
425 return ok
426 }
427
428 func (asw *actualStateOfWorld) CheckAndMarkVolumeAsUncertainViaReconstruction(opts operationexecutor.MarkVolumeOpts) (bool, error) {
429 asw.Lock()
430 defer asw.Unlock()
431
432 volumeObj, volumeExists := asw.attachedVolumes[opts.VolumeName]
433 if !volumeExists {
434 return false, nil
435 }
436
437 podObj, podExists := volumeObj.mountedPods[opts.PodName]
438 if podExists {
439
440 if podObj.volumeMountStateForPod == operationexecutor.VolumeMountUncertain {
441 return false, nil
442 }
443 if podObj.volumeMountStateForPod == operationexecutor.VolumeMounted {
444 return false, nil
445 }
446 }
447
448 podName := opts.PodName
449 podUID := opts.PodUID
450 volumeName := opts.VolumeName
451 mounter := opts.Mounter
452 blockVolumeMapper := opts.BlockVolumeMapper
453 outerVolumeSpecName := opts.OuterVolumeSpecName
454 volumeGidValue := opts.VolumeGidVolume
455 volumeSpec := opts.VolumeSpec
456
457 podObj = mountedPod{
458 podName: podName,
459 podUID: podUID,
460 mounter: mounter,
461 blockVolumeMapper: blockVolumeMapper,
462 outerVolumeSpecName: outerVolumeSpecName,
463 volumeGidValue: volumeGidValue,
464 volumeSpec: volumeSpec,
465 remountRequired: false,
466 volumeMountStateForPod: operationexecutor.VolumeMountUncertain,
467 }
468
469 if mounter != nil {
470
471
472 podObj.mounter = mounter
473 }
474
475 asw.attachedVolumes[volumeName].mountedPods[podName] = podObj
476
477 podMap, ok := asw.foundDuringReconstruction[opts.VolumeName]
478 if !ok {
479 podMap = map[volumetypes.UniquePodName]types.UID{}
480 }
481 podMap[opts.PodName] = opts.PodUID
482 asw.foundDuringReconstruction[opts.VolumeName] = podMap
483 return true, nil
484 }
485
486 func (asw *actualStateOfWorld) CheckAndMarkDeviceUncertainViaReconstruction(volumeName v1.UniqueVolumeName, deviceMountPath string) bool {
487 asw.Lock()
488 defer asw.Unlock()
489
490 volumeObj, volumeExists := asw.attachedVolumes[volumeName]
491
492
493 if !volumeExists || volumeObj.deviceMountState != operationexecutor.DeviceNotMounted {
494 return false
495 }
496
497 volumeObj.deviceMountState = operationexecutor.DeviceMountUncertain
498
499
500 volumeObj.deviceMountPath = deviceMountPath
501 asw.attachedVolumes[volumeName] = volumeObj
502 return true
503
504 }
505
506 func (asw *actualStateOfWorld) MarkVolumeAsMounted(markVolumeOpts operationexecutor.MarkVolumeOpts) error {
507 return asw.AddPodToVolume(markVolumeOpts)
508 }
509
510 func (asw *actualStateOfWorld) AddVolumeToReportAsAttached(logger klog.Logger, volumeName v1.UniqueVolumeName, nodeName types.NodeName) {
511
512 }
513
514 func (asw *actualStateOfWorld) RemoveVolumeFromReportAsAttached(volumeName v1.UniqueVolumeName, nodeName types.NodeName) error {
515
516 return nil
517 }
518
519 func (asw *actualStateOfWorld) MarkVolumeAsUnmounted(
520 podName volumetypes.UniquePodName, volumeName v1.UniqueVolumeName) error {
521 return asw.DeletePodFromVolume(podName, volumeName)
522 }
523
524 func (asw *actualStateOfWorld) MarkDeviceAsMounted(
525 volumeName v1.UniqueVolumeName, devicePath, deviceMountPath, seLinuxMountContext string) error {
526 return asw.SetDeviceMountState(volumeName, operationexecutor.DeviceGloballyMounted, devicePath, deviceMountPath, seLinuxMountContext)
527 }
528
529 func (asw *actualStateOfWorld) MarkDeviceAsUncertain(
530 volumeName v1.UniqueVolumeName, devicePath, deviceMountPath, seLinuxMountContext string) error {
531 return asw.SetDeviceMountState(volumeName, operationexecutor.DeviceMountUncertain, devicePath, deviceMountPath, seLinuxMountContext)
532 }
533
534 func (asw *actualStateOfWorld) MarkVolumeMountAsUncertain(markVolumeOpts operationexecutor.MarkVolumeOpts) error {
535 markVolumeOpts.VolumeMountState = operationexecutor.VolumeMountUncertain
536 return asw.AddPodToVolume(markVolumeOpts)
537 }
538
539 func (asw *actualStateOfWorld) MarkDeviceAsUnmounted(
540 volumeName v1.UniqueVolumeName) error {
541 return asw.SetDeviceMountState(volumeName, operationexecutor.DeviceNotMounted, "", "", "")
542 }
543
544 func (asw *actualStateOfWorld) UpdateReconstructedDevicePath(volumeName v1.UniqueVolumeName, devicePath string) {
545 asw.Lock()
546 defer asw.Unlock()
547
548 volumeObj, volumeExists := asw.attachedVolumes[volumeName]
549 if !volumeExists {
550 return
551 }
552 if volumeObj.deviceMountState != operationexecutor.DeviceMountUncertain {
553
554
555 return
556 }
557
558 volumeObj.devicePath = devicePath
559 asw.attachedVolumes[volumeName] = volumeObj
560 }
561
562 func (asw *actualStateOfWorld) UpdateReconstructedVolumeAttachability(volumeName v1.UniqueVolumeName, attachable bool) {
563 asw.Lock()
564 defer asw.Unlock()
565
566 volumeObj, volumeExists := asw.attachedVolumes[volumeName]
567 if !volumeExists {
568 return
569 }
570 if volumeObj.pluginIsAttachable != volumeAttachabilityUncertain {
571
572
573 return
574 }
575
576 if attachable {
577 volumeObj.pluginIsAttachable = volumeAttachabilityTrue
578 } else {
579 volumeObj.pluginIsAttachable = volumeAttachabilityFalse
580 }
581 asw.attachedVolumes[volumeName] = volumeObj
582 }
583
584 func (asw *actualStateOfWorld) GetDeviceMountState(volumeName v1.UniqueVolumeName) operationexecutor.DeviceMountState {
585 asw.RLock()
586 defer asw.RUnlock()
587
588 volumeObj, volumeExists := asw.attachedVolumes[volumeName]
589 if !volumeExists {
590 return operationexecutor.DeviceNotMounted
591 }
592
593 return volumeObj.deviceMountState
594 }
595
596 func (asw *actualStateOfWorld) MarkForInUseExpansionError(volumeName v1.UniqueVolumeName) {
597 asw.Lock()
598 defer asw.Unlock()
599
600 volumeObj, ok := asw.attachedVolumes[volumeName]
601 if ok {
602 volumeObj.volumeInUseErrorForExpansion = true
603 asw.attachedVolumes[volumeName] = volumeObj
604 }
605 }
606
607 func (asw *actualStateOfWorld) GetVolumeMountState(volumeName v1.UniqueVolumeName, podName volumetypes.UniquePodName) operationexecutor.VolumeMountState {
608 asw.RLock()
609 defer asw.RUnlock()
610
611 volumeObj, volumeExists := asw.attachedVolumes[volumeName]
612 if !volumeExists {
613 return operationexecutor.VolumeNotMounted
614 }
615
616 podObj, podExists := volumeObj.mountedPods[podName]
617 if !podExists {
618 return operationexecutor.VolumeNotMounted
619 }
620 return podObj.volumeMountStateForPod
621 }
622
623 func (asw *actualStateOfWorld) IsVolumeMountedElsewhere(volumeName v1.UniqueVolumeName, podName volumetypes.UniquePodName) bool {
624 asw.RLock()
625 defer asw.RUnlock()
626
627 volumeObj, volumeExists := asw.attachedVolumes[volumeName]
628 if !volumeExists {
629 return false
630 }
631
632 for _, podObj := range volumeObj.mountedPods {
633 if podName != podObj.podName {
634
635 if podObj.volumeMountStateForPod != operationexecutor.VolumeNotMounted {
636 return true
637 }
638 }
639 }
640 return false
641 }
642
643
644
645
646
647
648
649 func (asw *actualStateOfWorld) addVolume(
650 volumeName v1.UniqueVolumeName, volumeSpec *volume.Spec, devicePath string, attachability volumeAttachability) error {
651 asw.Lock()
652 defer asw.Unlock()
653
654 volumePlugin, err := asw.volumePluginMgr.FindPluginBySpec(volumeSpec)
655 if err != nil || volumePlugin == nil {
656 return fmt.Errorf(
657 "failed to get Plugin from volumeSpec for volume %q err=%v",
658 volumeSpec.Name(),
659 err)
660 }
661
662 if len(volumeName) == 0 {
663 volumeName, err = util.GetUniqueVolumeNameFromSpec(volumePlugin, volumeSpec)
664 if err != nil {
665 return fmt.Errorf(
666 "failed to GetUniqueVolumeNameFromSpec for volumeSpec %q using volume plugin %q err=%v",
667 volumeSpec.Name(),
668 volumePlugin.GetPluginName(),
669 err)
670 }
671 }
672
673 volumeObj, volumeExists := asw.attachedVolumes[volumeName]
674 if !volumeExists {
675 volumeObj = attachedVolume{
676 volumeName: volumeName,
677 spec: volumeSpec,
678 mountedPods: make(map[volumetypes.UniquePodName]mountedPod),
679 pluginName: volumePlugin.GetPluginName(),
680 pluginIsAttachable: attachability,
681 deviceMountState: operationexecutor.DeviceNotMounted,
682 devicePath: devicePath,
683 }
684 } else {
685
686 volumeObj.devicePath = devicePath
687 klog.V(2).InfoS("Volume is already added to attachedVolume list, update device path", "volumeName", volumeName, "path", devicePath)
688 }
689 asw.attachedVolumes[volumeName] = volumeObj
690
691 return nil
692 }
693
694 func (asw *actualStateOfWorld) AddPodToVolume(markVolumeOpts operationexecutor.MarkVolumeOpts) error {
695 podName := markVolumeOpts.PodName
696 podUID := markVolumeOpts.PodUID
697 volumeName := markVolumeOpts.VolumeName
698 mounter := markVolumeOpts.Mounter
699 blockVolumeMapper := markVolumeOpts.BlockVolumeMapper
700 outerVolumeSpecName := markVolumeOpts.OuterVolumeSpecName
701 volumeGidValue := markVolumeOpts.VolumeGidVolume
702 volumeSpec := markVolumeOpts.VolumeSpec
703 asw.Lock()
704 defer asw.Unlock()
705
706 volumeObj, volumeExists := asw.attachedVolumes[volumeName]
707 if !volumeExists {
708 return fmt.Errorf(
709 "no volume with the name %q exists in the list of attached volumes",
710 volumeName)
711 }
712
713 podObj, podExists := volumeObj.mountedPods[podName]
714
715 updateUncertainVolume := false
716 if podExists {
717
718
719
720 updateUncertainVolume = utilfeature.DefaultFeatureGate.Enabled(features.NewVolumeManagerReconstruction) && podObj.volumeMountStateForPod == operationexecutor.VolumeMountUncertain
721 }
722 if !podExists || updateUncertainVolume {
723
724 podObj = mountedPod{
725 podName: podName,
726 podUID: podUID,
727 mounter: mounter,
728 blockVolumeMapper: blockVolumeMapper,
729 outerVolumeSpecName: outerVolumeSpecName,
730 volumeGidValue: volumeGidValue,
731 volumeSpec: volumeSpec,
732 volumeMountStateForPod: markVolumeOpts.VolumeMountState,
733 seLinuxMountContext: markVolumeOpts.SELinuxMountContext,
734 }
735 }
736
737
738 podObj.remountRequired = false
739 podObj.volumeMountStateForPod = markVolumeOpts.VolumeMountState
740
741
742 if markVolumeOpts.VolumeMountState == operationexecutor.VolumeMounted {
743 delete(asw.foundDuringReconstruction[volumeName], podName)
744 }
745 if mounter != nil {
746
747
748 podObj.mounter = mounter
749 }
750 asw.attachedVolumes[volumeName].mountedPods[podName] = podObj
751 if utilfeature.DefaultFeatureGate.Enabled(features.SELinuxMountReadWriteOncePod) {
752
753
754 if volumeObj.seLinuxMountContext == nil {
755 volumeObj.seLinuxMountContext = &markVolumeOpts.SELinuxMountContext
756 asw.attachedVolumes[volumeName] = volumeObj
757 }
758 }
759
760 return nil
761 }
762
763 func (asw *actualStateOfWorld) MarkVolumeAsResized(volumeName v1.UniqueVolumeName, claimSize *resource.Quantity) bool {
764 asw.Lock()
765 defer asw.Unlock()
766
767 volumeObj, ok := asw.attachedVolumes[volumeName]
768 if ok {
769 volumeObj.persistentVolumeSize = claimSize
770 asw.attachedVolumes[volumeName] = volumeObj
771 return true
772 }
773 return false
774 }
775
776 func (asw *actualStateOfWorld) MarkRemountRequired(
777 podName volumetypes.UniquePodName) {
778 asw.Lock()
779 defer asw.Unlock()
780 for volumeName, volumeObj := range asw.attachedVolumes {
781 if podObj, podExists := volumeObj.mountedPods[podName]; podExists {
782 volumePlugin, err :=
783 asw.volumePluginMgr.FindPluginBySpec(podObj.volumeSpec)
784 if err != nil || volumePlugin == nil {
785
786 klog.ErrorS(nil, "MarkRemountRequired failed to FindPluginBySpec for volume", "uniquePodName", podObj.podName, "podUID", podObj.podUID, "volumeName", volumeName, "volumeSpecName", podObj.volumeSpec.Name())
787 continue
788 }
789
790 if volumePlugin.RequiresRemount(podObj.volumeSpec) {
791 podObj.remountRequired = true
792 asw.attachedVolumes[volumeName].mountedPods[podName] = podObj
793 }
794 }
795 }
796 }
797
798 func (asw *actualStateOfWorld) SetDeviceMountState(
799 volumeName v1.UniqueVolumeName, deviceMountState operationexecutor.DeviceMountState, devicePath, deviceMountPath, seLinuxMountContext string) error {
800 asw.Lock()
801 defer asw.Unlock()
802
803 volumeObj, volumeExists := asw.attachedVolumes[volumeName]
804 if !volumeExists {
805 return fmt.Errorf(
806 "no volume with the name %q exists in the list of attached volumes",
807 volumeName)
808 }
809
810 volumeObj.deviceMountState = deviceMountState
811 volumeObj.deviceMountPath = deviceMountPath
812 if devicePath != "" {
813 volumeObj.devicePath = devicePath
814 }
815 if utilfeature.DefaultFeatureGate.Enabled(features.SELinuxMountReadWriteOncePod) {
816 if seLinuxMountContext != "" {
817 volumeObj.seLinuxMountContext = &seLinuxMountContext
818 }
819 }
820
821 asw.attachedVolumes[volumeName] = volumeObj
822 return nil
823 }
824
825 func (asw *actualStateOfWorld) InitializeClaimSize(logger klog.Logger, volumeName v1.UniqueVolumeName, claimSize *resource.Quantity) {
826 asw.Lock()
827 defer asw.Unlock()
828
829 volumeObj, ok := asw.attachedVolumes[volumeName]
830
831
832 if ok && volumeObj.persistentVolumeSize == nil {
833 volumeObj.persistentVolumeSize = claimSize
834 asw.attachedVolumes[volumeName] = volumeObj
835 }
836 }
837
838 func (asw *actualStateOfWorld) GetClaimSize(volumeName v1.UniqueVolumeName) *resource.Quantity {
839 asw.RLock()
840 defer asw.RUnlock()
841
842 volumeObj, ok := asw.attachedVolumes[volumeName]
843 if ok {
844 return volumeObj.persistentVolumeSize
845 }
846 return nil
847 }
848
849 func (asw *actualStateOfWorld) DeletePodFromVolume(
850 podName volumetypes.UniquePodName, volumeName v1.UniqueVolumeName) error {
851 asw.Lock()
852 defer asw.Unlock()
853
854 volumeObj, volumeExists := asw.attachedVolumes[volumeName]
855 if !volumeExists {
856 return fmt.Errorf(
857 "no volume with the name %q exists in the list of attached volumes",
858 volumeName)
859 }
860
861 _, podExists := volumeObj.mountedPods[podName]
862 if podExists {
863 delete(asw.attachedVolumes[volumeName].mountedPods, podName)
864 }
865
866
867 _, podExists = asw.foundDuringReconstruction[volumeName]
868 if podExists {
869 delete(asw.foundDuringReconstruction[volumeName], podName)
870 }
871
872 return nil
873 }
874
875 func (asw *actualStateOfWorld) DeleteVolume(volumeName v1.UniqueVolumeName) error {
876 asw.Lock()
877 defer asw.Unlock()
878
879 volumeObj, volumeExists := asw.attachedVolumes[volumeName]
880 if !volumeExists {
881 return nil
882 }
883
884 if len(volumeObj.mountedPods) != 0 {
885 return fmt.Errorf(
886 "failed to DeleteVolume %q, it still has %v mountedPods",
887 volumeName,
888 len(volumeObj.mountedPods))
889 }
890
891 delete(asw.attachedVolumes, volumeName)
892 delete(asw.foundDuringReconstruction, volumeName)
893 return nil
894 }
895
896 func (asw *actualStateOfWorld) PodExistsInVolume(podName volumetypes.UniquePodName, volumeName v1.UniqueVolumeName, desiredVolumeSize resource.Quantity, seLinuxLabel string) (bool, string, error) {
897 asw.RLock()
898 defer asw.RUnlock()
899
900 volumeObj, volumeExists := asw.attachedVolumes[volumeName]
901 if !volumeExists {
902 return false, "", newVolumeNotAttachedError(volumeName)
903 }
904
905
906 if utilfeature.DefaultFeatureGate.Enabled(features.SELinuxMountReadWriteOncePod) {
907 if volumeObj.seLinuxMountContext != nil && *volumeObj.seLinuxMountContext != seLinuxLabel {
908 fullErr := newSELinuxMountMismatchError(volumeName)
909 return false, volumeObj.devicePath, fullErr
910 }
911 }
912
913 podObj, podExists := volumeObj.mountedPods[podName]
914 if podExists {
915
916 if podObj.volumeMountStateForPod == operationexecutor.VolumeMountUncertain {
917 return false, volumeObj.devicePath, nil
918 }
919 if podObj.remountRequired {
920 return true, volumeObj.devicePath, newRemountRequiredError(volumeObj.volumeName, podObj.podName)
921 }
922 if currentSize, expandVolume := asw.volumeNeedsExpansion(volumeObj, desiredVolumeSize); expandVolume {
923 return true, volumeObj.devicePath, newFsResizeRequiredError(volumeObj.volumeName, podObj.podName, currentSize)
924 }
925 }
926
927 return podExists, volumeObj.devicePath, nil
928 }
929
930 func (asw *actualStateOfWorld) volumeNeedsExpansion(volumeObj attachedVolume, desiredVolumeSize resource.Quantity) (resource.Quantity, bool) {
931 currentSize := resource.Quantity{}
932 if volumeObj.persistentVolumeSize != nil {
933 currentSize = volumeObj.persistentVolumeSize.DeepCopy()
934 }
935 if volumeObj.volumeInUseErrorForExpansion {
936 return currentSize, false
937 }
938 if volumeObj.persistentVolumeSize == nil || desiredVolumeSize.IsZero() {
939 return currentSize, false
940 }
941
942 if desiredVolumeSize.Cmp(*volumeObj.persistentVolumeSize) > 0 {
943 volumePlugin, err := asw.volumePluginMgr.FindNodeExpandablePluginBySpec(volumeObj.spec)
944 if err != nil || volumePlugin == nil {
945
946 klog.InfoS("PodExistsInVolume failed to find expandable plugin",
947 "volume", volumeObj.volumeName,
948 "volumeSpecName", volumeObj.spec.Name())
949 return currentSize, false
950 }
951 if volumePlugin.RequiresFSResize() {
952 return currentSize, true
953 }
954 }
955 return currentSize, false
956 }
957
958 func (asw *actualStateOfWorld) PodRemovedFromVolume(
959 podName volumetypes.UniquePodName,
960 volumeName v1.UniqueVolumeName) bool {
961 asw.RLock()
962 defer asw.RUnlock()
963
964 volumeObj, volumeExists := asw.attachedVolumes[volumeName]
965 if !volumeExists {
966 return true
967 }
968
969 podObj, podExists := volumeObj.mountedPods[podName]
970 if podExists {
971
972 if podObj.volumeMountStateForPod == operationexecutor.VolumeMountUncertain {
973 return false
974 }
975 if podObj.volumeMountStateForPod == operationexecutor.VolumeMounted {
976 return false
977 }
978 }
979 return true
980 }
981
982 func (asw *actualStateOfWorld) VolumeExistsWithSpecName(podName volumetypes.UniquePodName, volumeSpecName string) bool {
983 asw.RLock()
984 defer asw.RUnlock()
985 for _, volumeObj := range asw.attachedVolumes {
986 if podObj, podExists := volumeObj.mountedPods[podName]; podExists {
987 if podObj.volumeSpec.Name() == volumeSpecName {
988 return true
989 }
990 }
991 }
992 return false
993 }
994
995 func (asw *actualStateOfWorld) VolumeExists(
996 volumeName v1.UniqueVolumeName) bool {
997 asw.RLock()
998 defer asw.RUnlock()
999
1000 _, volumeExists := asw.attachedVolumes[volumeName]
1001 return volumeExists
1002 }
1003
1004 func (asw *actualStateOfWorld) GetMountedVolumes() []MountedVolume {
1005 asw.RLock()
1006 defer asw.RUnlock()
1007 mountedVolume := make([]MountedVolume, 0 , len(asw.attachedVolumes) )
1008 for _, volumeObj := range asw.attachedVolumes {
1009 for _, podObj := range volumeObj.mountedPods {
1010 if podObj.volumeMountStateForPod == operationexecutor.VolumeMounted {
1011 mountedVolume = append(
1012 mountedVolume,
1013 getMountedVolume(&podObj, &volumeObj))
1014 }
1015 }
1016 }
1017 return mountedVolume
1018 }
1019
1020
1021 func (asw *actualStateOfWorld) GetAllMountedVolumes() []MountedVolume {
1022 asw.RLock()
1023 defer asw.RUnlock()
1024 mountedVolume := make([]MountedVolume, 0 , len(asw.attachedVolumes) )
1025 for _, volumeObj := range asw.attachedVolumes {
1026 for _, podObj := range volumeObj.mountedPods {
1027 if podObj.volumeMountStateForPod == operationexecutor.VolumeMounted ||
1028 podObj.volumeMountStateForPod == operationexecutor.VolumeMountUncertain {
1029 mountedVolume = append(
1030 mountedVolume,
1031 getMountedVolume(&podObj, &volumeObj))
1032 }
1033 }
1034 }
1035
1036 return mountedVolume
1037 }
1038
1039 func (asw *actualStateOfWorld) GetMountedVolumesForPod(
1040 podName volumetypes.UniquePodName) []MountedVolume {
1041 asw.RLock()
1042 defer asw.RUnlock()
1043 mountedVolume := make([]MountedVolume, 0 , len(asw.attachedVolumes) )
1044 for _, volumeObj := range asw.attachedVolumes {
1045 for mountedPodName, podObj := range volumeObj.mountedPods {
1046 if mountedPodName == podName && podObj.volumeMountStateForPod == operationexecutor.VolumeMounted {
1047 mountedVolume = append(
1048 mountedVolume,
1049 getMountedVolume(&podObj, &volumeObj))
1050 }
1051 }
1052 }
1053
1054 return mountedVolume
1055 }
1056
1057 func (asw *actualStateOfWorld) GetPossiblyMountedVolumesForPod(
1058 podName volumetypes.UniquePodName) []MountedVolume {
1059 asw.RLock()
1060 defer asw.RUnlock()
1061 mountedVolume := make([]MountedVolume, 0 , len(asw.attachedVolumes) )
1062 for _, volumeObj := range asw.attachedVolumes {
1063 for mountedPodName, podObj := range volumeObj.mountedPods {
1064 if mountedPodName == podName &&
1065 (podObj.volumeMountStateForPod == operationexecutor.VolumeMounted ||
1066 podObj.volumeMountStateForPod == operationexecutor.VolumeMountUncertain) {
1067 mountedVolume = append(
1068 mountedVolume,
1069 getMountedVolume(&podObj, &volumeObj))
1070 }
1071 }
1072 }
1073
1074 return mountedVolume
1075 }
1076
1077 func (asw *actualStateOfWorld) GetGloballyMountedVolumes() []AttachedVolume {
1078 asw.RLock()
1079 defer asw.RUnlock()
1080 globallyMountedVolumes := make(
1081 []AttachedVolume, 0 , len(asw.attachedVolumes) )
1082 for _, volumeObj := range asw.attachedVolumes {
1083 if volumeObj.deviceMountState == operationexecutor.DeviceGloballyMounted {
1084 globallyMountedVolumes = append(
1085 globallyMountedVolumes,
1086 asw.newAttachedVolume(&volumeObj))
1087 }
1088 }
1089
1090 return globallyMountedVolumes
1091 }
1092
1093 func (asw *actualStateOfWorld) GetAttachedVolumes() []AttachedVolume {
1094 asw.RLock()
1095 defer asw.RUnlock()
1096 allAttachedVolumes := make(
1097 []AttachedVolume, 0 , len(asw.attachedVolumes) )
1098 for _, volumeObj := range asw.attachedVolumes {
1099 allAttachedVolumes = append(
1100 allAttachedVolumes,
1101 asw.newAttachedVolume(&volumeObj))
1102 }
1103
1104 return allAttachedVolumes
1105 }
1106
1107 func (asw *actualStateOfWorld) GetUnmountedVolumes() []AttachedVolume {
1108 asw.RLock()
1109 defer asw.RUnlock()
1110 unmountedVolumes := make([]AttachedVolume, 0 , len(asw.attachedVolumes) )
1111 for _, volumeObj := range asw.attachedVolumes {
1112 if len(volumeObj.mountedPods) == 0 {
1113 unmountedVolumes = append(
1114 unmountedVolumes,
1115 asw.newAttachedVolume(&volumeObj))
1116 }
1117 }
1118
1119 return unmountedVolumes
1120 }
1121
1122 func (asw *actualStateOfWorld) SyncReconstructedVolume(volumeName v1.UniqueVolumeName, podName volumetypes.UniquePodName, outerVolumeSpecName string) {
1123 asw.Lock()
1124 defer asw.Unlock()
1125 if volumeObj, volumeExists := asw.attachedVolumes[volumeName]; volumeExists {
1126 if podObj, podExists := volumeObj.mountedPods[podName]; podExists {
1127 if podObj.outerVolumeSpecName != outerVolumeSpecName {
1128 podObj.outerVolumeSpecName = outerVolumeSpecName
1129 asw.attachedVolumes[volumeName].mountedPods[podName] = podObj
1130 }
1131 }
1132 }
1133 }
1134
1135 func (asw *actualStateOfWorld) newAttachedVolume(
1136 attachedVolume *attachedVolume) AttachedVolume {
1137 seLinuxMountContext := ""
1138 if utilfeature.DefaultFeatureGate.Enabled(features.SELinuxMountReadWriteOncePod) {
1139 if attachedVolume.seLinuxMountContext != nil {
1140 seLinuxMountContext = *attachedVolume.seLinuxMountContext
1141 }
1142 }
1143 return AttachedVolume{
1144 AttachedVolume: operationexecutor.AttachedVolume{
1145 VolumeName: attachedVolume.volumeName,
1146 VolumeSpec: attachedVolume.spec,
1147 NodeName: asw.nodeName,
1148 PluginIsAttachable: attachedVolume.pluginIsAttachable == volumeAttachabilityTrue,
1149 DevicePath: attachedVolume.devicePath,
1150 DeviceMountPath: attachedVolume.deviceMountPath,
1151 PluginName: attachedVolume.pluginName,
1152 SELinuxMountContext: seLinuxMountContext},
1153 DeviceMountState: attachedVolume.deviceMountState,
1154 SELinuxMountContext: seLinuxMountContext,
1155 }
1156 }
1157
1158
1159 var _ error = volumeNotAttachedError{}
1160
1161
1162
1163 type volumeNotAttachedError struct {
1164 volumeName v1.UniqueVolumeName
1165 }
1166
1167 func (err volumeNotAttachedError) Error() string {
1168 return fmt.Sprintf(
1169 "volumeName %q does not exist in the list of attached volumes",
1170 err.volumeName)
1171 }
1172
1173 func newVolumeNotAttachedError(volumeName v1.UniqueVolumeName) error {
1174 return volumeNotAttachedError{
1175 volumeName: volumeName,
1176 }
1177 }
1178
1179
1180 var _ error = remountRequiredError{}
1181
1182
1183
1184
1185
1186 type remountRequiredError struct {
1187 volumeName v1.UniqueVolumeName
1188 podName volumetypes.UniquePodName
1189 }
1190
1191 func (err remountRequiredError) Error() string {
1192 return fmt.Sprintf(
1193 "volumeName %q is mounted to %q but should be remounted",
1194 err.volumeName, err.podName)
1195 }
1196
1197 func newRemountRequiredError(
1198 volumeName v1.UniqueVolumeName, podName volumetypes.UniquePodName) error {
1199 return remountRequiredError{
1200 volumeName: volumeName,
1201 podName: podName,
1202 }
1203 }
1204
1205
1206
1207
1208 type FsResizeRequiredError struct {
1209 CurrentSize resource.Quantity
1210 volumeName v1.UniqueVolumeName
1211 podName volumetypes.UniquePodName
1212 }
1213
1214 func (err FsResizeRequiredError) Error() string {
1215 return fmt.Sprintf(
1216 "volumeName %q mounted to %q needs to resize file system",
1217 err.volumeName, err.podName)
1218 }
1219
1220 func newFsResizeRequiredError(
1221 volumeName v1.UniqueVolumeName, podName volumetypes.UniquePodName, currentSize resource.Quantity) error {
1222 return FsResizeRequiredError{
1223 CurrentSize: currentSize,
1224 volumeName: volumeName,
1225 podName: podName,
1226 }
1227 }
1228
1229
1230
1231 func IsFSResizeRequiredError(err error) bool {
1232 _, ok := err.(FsResizeRequiredError)
1233 return ok
1234 }
1235
1236
1237
1238 func getMountedVolume(
1239 mountedPod *mountedPod, attachedVolume *attachedVolume) MountedVolume {
1240 seLinuxMountContext := ""
1241 if attachedVolume.seLinuxMountContext != nil {
1242 seLinuxMountContext = *attachedVolume.seLinuxMountContext
1243 }
1244 return MountedVolume{
1245 MountedVolume: operationexecutor.MountedVolume{
1246 PodName: mountedPod.podName,
1247 VolumeName: attachedVolume.volumeName,
1248 InnerVolumeSpecName: mountedPod.volumeSpec.Name(),
1249 OuterVolumeSpecName: mountedPod.outerVolumeSpecName,
1250 PluginName: attachedVolume.pluginName,
1251 PodUID: mountedPod.podUID,
1252 Mounter: mountedPod.mounter,
1253 BlockVolumeMapper: mountedPod.blockVolumeMapper,
1254 VolumeGidValue: mountedPod.volumeGidValue,
1255 VolumeSpec: mountedPod.volumeSpec,
1256 DeviceMountPath: attachedVolume.deviceMountPath,
1257 SELinuxMountContext: seLinuxMountContext}}
1258
1259 }
1260
1261
1262
1263 type seLinuxMountMismatchError struct {
1264 volumeName v1.UniqueVolumeName
1265 }
1266
1267 func (err seLinuxMountMismatchError) Error() string {
1268 return fmt.Sprintf(
1269 "waiting for unmount of volume %q, because it is already mounted to a different pod with a different SELinux label",
1270 err.volumeName)
1271 }
1272
1273 func newSELinuxMountMismatchError(volumeName v1.UniqueVolumeName) error {
1274 return seLinuxMountMismatchError{
1275 volumeName: volumeName,
1276 }
1277 }
1278
1279
1280
1281 func IsSELinuxMountMismatchError(err error) bool {
1282 _, ok := err.(seLinuxMountMismatchError)
1283 return ok
1284 }
1285
View as plain text