Skip to content

Commit 55a2f43

Browse files
authored
Merge pull request kubernetes#131438 from gnufied/automated-cherry-pick-of-#131418-upstream-release-1.32
Automated cherry pick of kubernetes#131418: Check for newer fields when deciding expansion recovery feature status
2 parents 01aff80 + cdbea02 commit 55a2f43

File tree

5 files changed

+184
-35
lines changed

5 files changed

+184
-35
lines changed

pkg/volume/util/operationexecutor/node_expander.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ func (ne *NodeExpander) expandOnPlugin() (bool, resource.Quantity, error) {
184184
}
185185

186186
// File system resize succeeded, now update the PVC's Capacity to match the PV's
187-
ne.pvc, err = util.MarkFSResizeFinished(ne.pvc, ne.pluginResizeOpts.NewSize, ne.kubeClient)
187+
ne.pvc, err = util.MarkNodeExpansionFinishedWithRecovery(ne.pvc, ne.pluginResizeOpts.NewSize, ne.kubeClient)
188188
if err != nil {
189189
return true, ne.pluginResizeOpts.NewSize, fmt.Errorf("mountVolume.NodeExpandVolume update pvc status failed: %w", err)
190190
}

pkg/volume/util/operationexecutor/node_expander_test.go

Lines changed: 54 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,10 @@ func TestNodeExpander(t *testing.T) {
4949

5050
nodeResizePending := v1.PersistentVolumeClaimNodeResizePending
5151
var tests = []struct {
52-
name string
53-
pvc *v1.PersistentVolumeClaim
54-
pv *v1.PersistentVolume
52+
name string
53+
pvc *v1.PersistentVolumeClaim
54+
pv *v1.PersistentVolume
55+
recoverVolumeExpansionFailure bool
5556

5657
// desired size, defaults to pv.Spec.Capacity
5758
desiredSize *resource.Quantity
@@ -67,9 +68,10 @@ func TestNodeExpander(t *testing.T) {
6768
expectError bool
6869
}{
6970
{
70-
name: "pv.spec.cap > pvc.status.cap, resizeStatus=node_expansion_failed",
71-
pvc: getTestPVC("test-vol0", "2G", "1G", "", &nodeResizeFailed),
72-
pv: getTestPV("test-vol0", "2G"),
71+
name: "pv.spec.cap > pvc.status.cap, resizeStatus=node_expansion_failed",
72+
pvc: getTestPVC("test-vol0", "2G", "1G", "", &nodeResizeFailed),
73+
pv: getTestPV("test-vol0", "2G"),
74+
recoverVolumeExpansionFailure: true,
7375

7476
expectedResizeStatus: nodeResizeFailed,
7577
expectResizeCall: false,
@@ -78,41 +80,46 @@ func TestNodeExpander(t *testing.T) {
7880
expectedStatusSize: resource.MustParse("1G"),
7981
},
8082
{
81-
name: "pv.spec.cap > pvc.status.cap, resizeStatus=node_expansion_pending",
82-
pvc: getTestPVC("test-vol0", "2G", "1G", "2G", &nodeResizePending),
83-
pv: getTestPV("test-vol0", "2G"),
83+
name: "pv.spec.cap > pvc.status.cap, resizeStatus=node_expansion_pending",
84+
pvc: getTestPVC("test-vol0", "2G", "1G", "2G", &nodeResizePending),
85+
pv: getTestPV("test-vol0", "2G"),
86+
recoverVolumeExpansionFailure: true,
87+
8488
expectedResizeStatus: "",
8589
expectResizeCall: true,
8690
assumeResizeOpAsFinished: true,
8791
expectFinalErrors: false,
8892
expectedStatusSize: resource.MustParse("2G"),
8993
},
9094
{
91-
name: "pv.spec.cap > pvc.status.cap, resizeStatus=node_expansion_pending, reize_op=infeasible",
92-
pvc: getTestPVC(volumetesting.InfeasibleNodeExpansion, "2G", "1G", "2G", &nodeResizePending),
93-
pv: getTestPV(volumetesting.InfeasibleNodeExpansion, "2G"),
94-
expectError: true,
95-
expectedResizeStatus: nodeResizeFailed,
96-
expectResizeCall: true,
97-
assumeResizeOpAsFinished: true,
98-
expectFinalErrors: true,
99-
expectedStatusSize: resource.MustParse("1G"),
95+
name: "pv.spec.cap > pvc.status.cap, resizeStatus=node_expansion_pending, reize_op=infeasible",
96+
pvc: getTestPVC(volumetesting.InfeasibleNodeExpansion, "2G", "1G", "2G", &nodeResizePending),
97+
pv: getTestPV(volumetesting.InfeasibleNodeExpansion, "2G"),
98+
recoverVolumeExpansionFailure: false,
99+
expectError: true,
100+
expectedResizeStatus: nodeResizeFailed,
101+
expectResizeCall: true,
102+
assumeResizeOpAsFinished: true,
103+
expectFinalErrors: true,
104+
expectedStatusSize: resource.MustParse("1G"),
100105
},
101106
{
102-
name: "pv.spec.cap > pvc.status.cap, resizeStatus=node_expansion_pending, reize_op=failing",
103-
pvc: getTestPVC(volumetesting.OtherFinalNodeExpansionError, "2G", "1G", "2G", &nodeResizePending),
104-
pv: getTestPV(volumetesting.OtherFinalNodeExpansionError, "2G"),
105-
expectError: true,
106-
expectedResizeStatus: v1.PersistentVolumeClaimNodeResizeInProgress,
107-
expectResizeCall: true,
108-
assumeResizeOpAsFinished: true,
109-
expectFinalErrors: true,
110-
expectedStatusSize: resource.MustParse("1G"),
107+
name: "pv.spec.cap > pvc.status.cap, resizeStatus=node_expansion_pending, reize_op=failing",
108+
pvc: getTestPVC(volumetesting.OtherFinalNodeExpansionError, "2G", "1G", "2G", &nodeResizePending),
109+
pv: getTestPV(volumetesting.OtherFinalNodeExpansionError, "2G"),
110+
recoverVolumeExpansionFailure: true,
111+
expectError: true,
112+
expectedResizeStatus: v1.PersistentVolumeClaimNodeResizeInProgress,
113+
expectResizeCall: true,
114+
assumeResizeOpAsFinished: true,
115+
expectFinalErrors: true,
116+
expectedStatusSize: resource.MustParse("1G"),
111117
},
112118
{
113-
name: "RWO volumes, pv.spec.cap = pvc.status.cap, resizeStatus='', desiredSize > actualSize",
114-
pvc: getTestPVC("test-vol0", "2G", "2G", "2G", nil),
115-
pv: getTestPV("test-vol0", "2G"),
119+
name: "RWO volumes, pv.spec.cap = pvc.status.cap, resizeStatus='', desiredSize > actualSize",
120+
pvc: getTestPVC("test-vol0", "2G", "2G", "2G", nil),
121+
pv: getTestPV("test-vol0", "2G"),
122+
recoverVolumeExpansionFailure: false,
116123

117124
expectedResizeStatus: "",
118125
expectResizeCall: false,
@@ -121,9 +128,22 @@ func TestNodeExpander(t *testing.T) {
121128
expectedStatusSize: resource.MustParse("2G"),
122129
},
123130
{
124-
name: "RWX volumes, pv.spec.cap = pvc.status.cap, resizeStatus='', desiredSize > actualSize",
125-
pvc: addAccessMode(getTestPVC("test-vol0", "2G", "2G", "2G", nil), v1.ReadWriteMany),
126-
pv: getTestPV("test-vol0", "2G"),
131+
name: "RWX volumes, pv.spec.cap = pvc.status.cap, resizeStatus='', desiredSize > actualSize",
132+
pvc: addAccessMode(getTestPVC("test-vol0", "2G", "2G", "2G", nil), v1.ReadWriteMany),
133+
pv: getTestPV("test-vol0", "2G"),
134+
recoverVolumeExpansionFailure: true,
135+
136+
expectedResizeStatus: "",
137+
expectResizeCall: true,
138+
assumeResizeOpAsFinished: true,
139+
expectFinalErrors: false,
140+
expectedStatusSize: resource.MustParse("2G"),
141+
},
142+
{
143+
name: "pv.spec.cap > pvc.status.cap, resizeStatus=node_expansion_pending, featuregate=disabled",
144+
pvc: getTestPVC("test-vol0", "2G", "1G", "2G", &nodeResizePending),
145+
pv: getTestPV("test-vol0", "2G"),
146+
recoverVolumeExpansionFailure: false,
127147

128148
expectedResizeStatus: "",
129149
expectResizeCall: true,
@@ -136,7 +156,7 @@ func TestNodeExpander(t *testing.T) {
136156
for i := range tests {
137157
test := tests[i]
138158
t.Run(test.name, func(t *testing.T) {
139-
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.RecoverVolumeExpansionFailure, true)
159+
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.RecoverVolumeExpansionFailure, test.recoverVolumeExpansionFailure)
140160
volumePluginMgr, fakePlugin := volumetesting.GetTestKubeletVolumePluginMgr(t)
141161

142162
pvc := test.pvc

pkg/volume/util/operationexecutor/operation_generator.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2075,6 +2075,11 @@ func (og *operationGenerator) checkForRecoveryFromExpansion(pvc *v1.PersistentVo
20752075
featureGateStatus := utilfeature.DefaultFeatureGate.Enabled(features.RecoverVolumeExpansionFailure)
20762076

20772077
if !featureGateStatus {
2078+
// even though RecoverVolumeExpansionFailure feature-gate is disabled, we should consider it enabled
2079+
// if resizeStatus is not empty or allocatedresources is set
2080+
if resizeStatus != "" || allocatedResource != nil {
2081+
return true
2082+
}
20782083
return false
20792084
}
20802085

pkg/volume/util/operationexecutor/operation_generator_test.go

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,109 @@ func TestExpandDuringMount(t *testing.T) {
402402
})
403403
}
404404
}
405+
func TestCheckForRecoveryFromExpansion(t *testing.T) {
406+
tests := []struct {
407+
name string
408+
pvc *v1.PersistentVolumeClaim
409+
featureGateEnabled bool
410+
expectedRecoveryCheck bool
411+
}{
412+
{
413+
name: "feature gate disabled, no resize status or allocated resources",
414+
pvc: &v1.PersistentVolumeClaim{
415+
ObjectMeta: metav1.ObjectMeta{
416+
Name: "test-pvc-1",
417+
},
418+
Status: v1.PersistentVolumeClaimStatus{
419+
AllocatedResourceStatuses: nil,
420+
AllocatedResources: nil,
421+
},
422+
},
423+
featureGateEnabled: false,
424+
expectedRecoveryCheck: false,
425+
},
426+
{
427+
name: "feature gate disabled, resize status set",
428+
pvc: &v1.PersistentVolumeClaim{
429+
ObjectMeta: metav1.ObjectMeta{
430+
Name: "test-pvc-2",
431+
},
432+
Status: v1.PersistentVolumeClaimStatus{
433+
AllocatedResourceStatuses: map[v1.ResourceName]v1.ClaimResourceStatus{
434+
v1.ResourceStorage: v1.PersistentVolumeClaimNodeResizePending,
435+
},
436+
},
437+
},
438+
featureGateEnabled: false,
439+
expectedRecoveryCheck: true,
440+
},
441+
{
442+
name: "feature gate enabled, resize status and allocated resources set",
443+
pvc: &v1.PersistentVolumeClaim{
444+
ObjectMeta: metav1.ObjectMeta{
445+
Name: "test-pvc-3",
446+
},
447+
Status: v1.PersistentVolumeClaimStatus{
448+
AllocatedResourceStatuses: map[v1.ResourceName]v1.ClaimResourceStatus{
449+
v1.ResourceStorage: v1.PersistentVolumeClaimNodeResizePending,
450+
},
451+
AllocatedResources: v1.ResourceList{
452+
v1.ResourceStorage: resource.MustParse("10Gi"),
453+
},
454+
},
455+
},
456+
featureGateEnabled: true,
457+
expectedRecoveryCheck: true,
458+
},
459+
{
460+
name: "feature gate enabled, no resize status or allocated resources",
461+
pvc: &v1.PersistentVolumeClaim{
462+
ObjectMeta: metav1.ObjectMeta{
463+
Name: "test-pvc-4",
464+
},
465+
Status: v1.PersistentVolumeClaimStatus{
466+
AllocatedResourceStatuses: nil,
467+
AllocatedResources: nil,
468+
},
469+
},
470+
featureGateEnabled: true,
471+
expectedRecoveryCheck: false,
472+
},
473+
{
474+
name: "feature gate enabled, older external resize controller",
475+
pvc: &v1.PersistentVolumeClaim{
476+
ObjectMeta: metav1.ObjectMeta{
477+
Name: "test-pvc-5",
478+
},
479+
Status: v1.PersistentVolumeClaimStatus{
480+
AllocatedResourceStatuses: nil,
481+
AllocatedResources: nil,
482+
},
483+
},
484+
featureGateEnabled: true,
485+
expectedRecoveryCheck: false,
486+
},
487+
}
488+
489+
for _, test := range tests {
490+
t.Run(test.name, func(t *testing.T) {
491+
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.RecoverVolumeExpansionFailure, test.featureGateEnabled)
492+
493+
pod := getTestPod("test-pod", test.pvc.Name)
494+
pv := getTestPV("test-vol0", "2G")
495+
og := &operationGenerator{}
496+
497+
vmt := VolumeToMount{
498+
Pod: pod,
499+
VolumeName: v1.UniqueVolumeName(pv.Name),
500+
VolumeSpec: volume.NewSpecFromPersistentVolume(pv, false),
501+
}
502+
result := og.checkForRecoveryFromExpansion(test.pvc, vmt)
503+
504+
assert.Equal(t, test.expectedRecoveryCheck, result, "unexpected recovery check result for test: %s", test.name)
505+
})
506+
}
507+
}
405508

406509
func getTestPod(podName, pvcName string) *v1.Pod {
407510
return &v1.Pod{

pkg/volume/util/resize_util.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,27 @@ func MarkFSResizeFinished(
236236
return updatedPVC, err
237237
}
238238

239+
func MarkNodeExpansionFinishedWithRecovery(
240+
pvc *v1.PersistentVolumeClaim,
241+
newSize resource.Quantity,
242+
kubeClient clientset.Interface) (*v1.PersistentVolumeClaim, error) {
243+
newPVC := pvc.DeepCopy()
244+
245+
newPVC.Status.Capacity[v1.ResourceStorage] = newSize
246+
247+
allocatedResourceStatusMap := newPVC.Status.AllocatedResourceStatuses
248+
delete(allocatedResourceStatusMap, v1.ResourceStorage)
249+
if len(allocatedResourceStatusMap) == 0 {
250+
newPVC.Status.AllocatedResourceStatuses = nil
251+
} else {
252+
newPVC.Status.AllocatedResourceStatuses = allocatedResourceStatusMap
253+
}
254+
255+
newPVC = MergeResizeConditionOnPVC(newPVC, []v1.PersistentVolumeClaimCondition{}, false /* keepOldResizeConditions */)
256+
updatedPVC, err := PatchPVCStatus(pvc /*oldPVC*/, newPVC, kubeClient)
257+
return updatedPVC, err
258+
}
259+
239260
// MarkNodeExpansionInfeasible marks a PVC for node expansion as failed. Kubelet should not retry expansion
240261
// of volumes which are in failed state.
241262
func MarkNodeExpansionInfeasible(pvc *v1.PersistentVolumeClaim, kubeClient clientset.Interface, err error) (*v1.PersistentVolumeClaim, error) {

0 commit comments

Comments
 (0)