1
16
17 package operationexecutor
18
19 import (
20 "fmt"
21
22 v1 "k8s.io/api/core/v1"
23 "k8s.io/apimachinery/pkg/api/resource"
24 clientset "k8s.io/client-go/kubernetes"
25 "k8s.io/client-go/tools/record"
26 "k8s.io/klog/v2"
27 kevents "k8s.io/kubernetes/pkg/kubelet/events"
28 "k8s.io/kubernetes/pkg/volume/util"
29 volumetypes "k8s.io/kubernetes/pkg/volume/util/types"
30 )
31
32 type NodeExpander struct {
33 nodeResizeOperationOpts
34 kubeClient clientset.Interface
35 recorder record.EventRecorder
36
37
38 pvcStatusCap resource.Quantity
39 pvCap resource.Quantity
40 resizeStatus v1.ClaimResourceStatus
41
42
43
44
45 pvcAlreadyUpdated bool
46 }
47
48 func newNodeExpander(resizeOp nodeResizeOperationOpts, client clientset.Interface, recorder record.EventRecorder) *NodeExpander {
49 return &NodeExpander{
50 kubeClient: client,
51 nodeResizeOperationOpts: resizeOp,
52 recorder: recorder,
53 }
54 }
55
56
57 type testResponseData struct {
58
59
60 resizeCalledOnPlugin bool
61
62
63
64
65
66
67 assumeResizeFinished bool
68 }
69
70
71
72
73 func (ne *NodeExpander) runPreCheck() bool {
74 ne.pvcStatusCap = ne.pvc.Status.Capacity[v1.ResourceStorage]
75 ne.pvCap = ne.pv.Spec.Capacity[v1.ResourceStorage]
76
77 allocatedResourceStatus := ne.pvc.Status.AllocatedResourceStatuses
78 if currentStatus, ok := allocatedResourceStatus[v1.ResourceStorage]; ok {
79 ne.resizeStatus = currentStatus
80 }
81
82
83
84 if ne.pvcStatusCap.Cmp(ne.pluginResizeOpts.NewSize) >= 0 && ne.resizeStatus == "" {
85 ne.pvcAlreadyUpdated = true
86 return true
87 }
88
89
90 if ne.resizeStatus == "" {
91 return false
92 }
93
94 resizeStatusVal := ne.resizeStatus
95
96
97
98 if resizeStatusVal == v1.PersistentVolumeClaimNodeResizePending ||
99 resizeStatusVal == v1.PersistentVolumeClaimNodeResizeInProgress {
100 return true
101 }
102 return false
103 }
104
105 func (ne *NodeExpander) expandOnPlugin() (bool, error, testResponseData) {
106 allowExpansion := ne.runPreCheck()
107 if !allowExpansion {
108 return false, nil, testResponseData{false, true}
109 }
110
111 var err error
112 nodeName := ne.vmt.Pod.Spec.NodeName
113
114 if !ne.pvcAlreadyUpdated {
115 ne.pvc, err = util.MarkNodeExpansionInProgress(ne.pvc, ne.kubeClient)
116
117 if err != nil {
118 msg := ne.vmt.GenerateErrorDetailed("MountVolume.NodeExpandVolume failed to mark node expansion in progress: %v", err)
119 klog.Errorf(msg.Error())
120 return false, err, testResponseData{}
121 }
122 }
123 _, resizeErr := ne.volumePlugin.NodeExpand(ne.pluginResizeOpts)
124 if resizeErr != nil {
125 if volumetypes.IsOperationFinishedError(resizeErr) {
126 var markFailedError error
127 ne.pvc, markFailedError = util.MarkNodeExpansionFailed(ne.pvc, ne.kubeClient)
128 if markFailedError != nil {
129 klog.Errorf(ne.vmt.GenerateErrorDetailed("MountMount.NodeExpandVolume failed to mark node expansion as failed: %v", err).Error())
130 }
131 }
132
133
134
135
136 if volumetypes.IsFailedPreconditionError(resizeErr) {
137 ne.actualStateOfWorld.MarkForInUseExpansionError(ne.vmt.VolumeName)
138 klog.Errorf(ne.vmt.GenerateErrorDetailed("MountVolume.NodeExapndVolume failed with %v", resizeErr).Error())
139 return false, nil, testResponseData{assumeResizeFinished: true, resizeCalledOnPlugin: true}
140 }
141 return false, resizeErr, testResponseData{assumeResizeFinished: true, resizeCalledOnPlugin: true}
142 }
143 simpleMsg, detailedMsg := ne.vmt.GenerateMsg("MountVolume.NodeExpandVolume succeeded", nodeName)
144 ne.recorder.Eventf(ne.vmt.Pod, v1.EventTypeNormal, kevents.FileSystemResizeSuccess, simpleMsg)
145 ne.recorder.Eventf(ne.pvc, v1.EventTypeNormal, kevents.FileSystemResizeSuccess, simpleMsg)
146 klog.InfoS(detailedMsg, "pod", klog.KObj(ne.vmt.Pod))
147
148
149 if ne.pvcAlreadyUpdated {
150 return true, nil, testResponseData{true, true}
151 }
152
153
154 ne.pvc, err = util.MarkFSResizeFinished(ne.pvc, ne.pluginResizeOpts.NewSize, ne.kubeClient)
155 if err != nil {
156 return true, fmt.Errorf("mountVolume.NodeExpandVolume update pvc status failed: %v", err), testResponseData{true, true}
157 }
158 return true, nil, testResponseData{true, true}
159 }
160
View as plain text