@@ -30,6 +30,7 @@ import (
30
30
apierrors "k8s.io/apimachinery/pkg/api/errors"
31
31
"k8s.io/client-go/tools/cache"
32
32
"k8s.io/klog/v2"
33
+ "k8s.io/utils/ptr"
33
34
)
34
35
35
36
const (
@@ -40,8 +41,6 @@ const (
40
41
41
42
// The return value bool is only used as a sentinel value when function returns without actually performing modification
42
43
func (ctrl * modifyController ) modify (pvc * v1.PersistentVolumeClaim , pv * v1.PersistentVolume ) (* v1.PersistentVolumeClaim , * v1.PersistentVolume , error , bool ) {
43
- pvcSpecVacName := pvc .Spec .VolumeAttributesClassName
44
- curVacName := pvc .Status .CurrentVolumeAttributesClassName
45
44
pvcKey , err := cache .MetaNamespaceKeyFunc (pvc )
46
45
if err != nil {
47
46
return pvc , pv , err , false
@@ -53,59 +52,68 @@ func (ctrl *modifyController) modify(pvc *v1.PersistentVolumeClaim, pv *v1.Persi
53
52
return pvc , pv , delayModificationErr , false
54
53
}
55
54
56
- if pvcSpecVacName != nil && curVacName == nil {
57
- // First time adding VAC to a PVC
58
- return ctrl .validateVACAndModifyVolumeWithTarget (pvc , pv )
59
- } else if pvcSpecVacName != nil && curVacName != nil && * pvcSpecVacName != * curVacName {
60
- // Check if PVC in uncertain state
61
- _ , inUncertainState := ctrl .uncertainPVCs .Load (pvcKey )
62
- if ! inUncertainState {
63
- klog .V (3 ).InfoS ("previous operation on the PVC failed with a final error, retrying" )
64
- return ctrl .validateVACAndModifyVolumeWithTarget (pvc , pv )
65
- } else {
66
- vac , err := ctrl .vacLister .Get (* pvcSpecVacName )
67
- if err != nil {
68
- if apierrors .IsNotFound (err ) {
69
- ctrl .eventRecorder .Eventf (pvc , v1 .EventTypeWarning , util .VolumeModifyFailed , "VAC " + * pvcSpecVacName + " does not exist." )
70
- }
71
- return pvc , pv , err , false
72
- }
73
- return ctrl .controllerModifyVolumeWithTarget (pvc , pv , vac , pvcSpecVacName )
55
+ pvcSpecVacName := ptr .Deref (pvc .Spec .VolumeAttributesClassName , "" )
56
+ curVacName := ptr .Deref (pvc .Status .CurrentVolumeAttributesClassName , "" )
57
+ if pvc .Status .ModifyVolumeStatus == nil && pvcSpecVacName == curVacName {
58
+ // No modification required, already reached target state
59
+ return pvc , pv , nil , false
60
+ }
61
+
62
+ if pvcSpecVacName == "" &&
63
+ (pvc .Status .ModifyVolumeStatus == nil || pvc .Status .ModifyVolumeStatus .Status == v1 .PersistentVolumeClaimModifyVolumeInfeasible ) {
64
+ // User don't care the target state, and we've reached a relatively stable state. Just keep it here.
65
+ // Note: APIServer generally not allowing setting pvcSpecVacName to empty when curVacName is not empty.
66
+ klog .V (4 ).InfoS ("stop reconcile for rolled back PVC" , "PV" , klog .KObj (pv ))
67
+ return pvc , pv , nil , false
68
+ }
69
+
70
+ // Check if we should change our target
71
+ _ , inUncertainState := ctrl .uncertainPVCs .Load (pvcKey )
72
+ if inUncertainState || pvcSpecVacName == "" {
73
+ vac , err := ctrl .getTargetVAC (pvc , pvc .Status .ModifyVolumeStatus .TargetVolumeAttributesClassName )
74
+ if err != nil {
75
+ return pvc , pv , err , false
74
76
}
77
+ return ctrl .controllerModifyVolumeWithTarget (pvc , pv , vac )
75
78
}
76
79
77
- // No modification required
78
- return pvc , pv , nil , false
80
+ return ctrl .validateVACAndModifyVolumeWithTarget (pvc , pv )
81
+ }
82
+
83
+ func (ctrl * modifyController ) getTargetVAC (pvc * v1.PersistentVolumeClaim , vacName string ) (* storagev1beta1.VolumeAttributesClass , error ) {
84
+ vac , err := ctrl .vacLister .Get (vacName )
85
+ // Check if pvcSpecVac is valid and exist
86
+ if err != nil {
87
+ if apierrors .IsNotFound (err ) {
88
+ ctrl .eventRecorder .Eventf (pvc , v1 .EventTypeWarning , util .VolumeModifyFailed , "VAC %q does not exist." , vacName )
89
+ }
90
+ return nil , fmt .Errorf ("get VAC with vac name %s in VACInformer cache failed: %w" , vacName , err )
91
+ }
92
+ return vac , nil
79
93
}
80
94
81
95
// func validateVACAndModifyVolumeWithTarget validate the VAC. The function sets pvc.Status.ModifyVolumeStatus
82
96
// to Pending if VAC does not exist and proceeds to trigger ModifyVolume if VAC exists
83
97
func (ctrl * modifyController ) validateVACAndModifyVolumeWithTarget (
84
98
pvc * v1.PersistentVolumeClaim ,
85
99
pv * v1.PersistentVolume ) (* v1.PersistentVolumeClaim , * v1.PersistentVolume , error , bool ) {
86
- // The controller only triggers ModifyVolume if pvcSpecVacName is not nil nor empty
87
- pvcSpecVacName := pvc .Spec .VolumeAttributesClassName
88
- // Check if pvcSpecVac is valid and exist
89
- vac , err := ctrl .vacLister .Get (* pvcSpecVacName )
90
- if err == nil {
91
- // Mark pvc.Status.ModifyVolumeStatus as in progress
92
- pvc , err = ctrl .markControllerModifyVolumeStatus (pvc , v1 .PersistentVolumeClaimModifyVolumeInProgress , nil )
93
- if err != nil {
94
- return pvc , pv , err , false
95
- }
96
- // Record an event to indicate that external resizer is modifying this volume.
97
- ctrl .eventRecorder .Event (pvc , v1 .EventTypeNormal , util .VolumeModify ,
98
- fmt .Sprintf ("external resizer is modifying volume %s with vac %s" , pvc .Name , * pvcSpecVacName ))
99
- return ctrl .controllerModifyVolumeWithTarget (pvc , pv , vac , pvcSpecVacName )
100
- } else {
101
- if apierrors .IsNotFound (err ) {
102
- ctrl .eventRecorder .Eventf (pvc , v1 .EventTypeWarning , util .VolumeModifyFailed , "VAC " + * pvcSpecVacName + " does not exist." )
103
- }
104
- klog .Errorf ("Get VAC with vac name %s in VACInformer cache failed: %v" , * pvcSpecVacName , err )
100
+
101
+ vac , err := ctrl .getTargetVAC (pvc , * pvc .Spec .VolumeAttributesClassName )
102
+ if err != nil {
105
103
// Mark pvc.Status.ModifyVolumeStatus as pending
106
104
pvc , err = ctrl .markControllerModifyVolumeStatus (pvc , v1 .PersistentVolumeClaimModifyVolumePending , nil )
107
105
return pvc , pv , err , false
108
106
}
107
+
108
+ // Mark pvc.Status.ModifyVolumeStatus as in progress
109
+ pvc , err = ctrl .markControllerModifyVolumeStatus (pvc , v1 .PersistentVolumeClaimModifyVolumeInProgress , nil )
110
+ if err != nil {
111
+ return pvc , pv , err , false
112
+ }
113
+ // Record an event to indicate that external resizer is modifying this volume.
114
+ ctrl .eventRecorder .Event (pvc , v1 .EventTypeNormal , util .VolumeModify ,
115
+ fmt .Sprintf ("external resizer is modifying volume %s with vac %s" , pvc .Name , vac .Name ))
116
+ return ctrl .controllerModifyVolumeWithTarget (pvc , pv , vac )
109
117
}
110
118
111
119
// func controllerModifyVolumeWithTarget trigger the CSI ControllerModifyVolume API call
@@ -114,11 +122,11 @@ func (ctrl *modifyController) controllerModifyVolumeWithTarget(
114
122
pvc * v1.PersistentVolumeClaim ,
115
123
pv * v1.PersistentVolume ,
116
124
vacObj * storagev1beta1.VolumeAttributesClass ,
117
- pvcSpecVacName * string ) (* v1.PersistentVolumeClaim , * v1.PersistentVolume , error , bool ) {
125
+ ) (* v1.PersistentVolumeClaim , * v1.PersistentVolume , error , bool ) {
118
126
var err error
119
127
pvc , pv , err = ctrl .callModifyVolumeOnPlugin (pvc , pv , vacObj )
120
128
if err == nil {
121
- klog .V (4 ).Infof ("Update volumeAttributesClass of PV %q to %s succeeded" , pv .Name , * pvcSpecVacName )
129
+ klog .V (4 ).Infof ("Update volumeAttributesClass of PV %q to %s succeeded" , pv .Name , vacObj . Name )
122
130
// Record an event to indicate that modify operation is successful.
123
131
ctrl .eventRecorder .Eventf (pvc , v1 .EventTypeNormal , util .VolumeModifySuccess , fmt .Sprintf ("external resizer modified volume %s with vac %s successfully" , pvc .Name , vacObj .Name ))
124
132
return pvc , pv , nil , true
0 commit comments