@@ -22,6 +22,7 @@ package reconcile
22
22
23
23
import (
24
24
"context"
25
+ "time"
25
26
26
27
core "k8s.io/api/core/v1"
27
28
@@ -35,6 +36,10 @@ import (
35
36
inspectorInterface "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector"
36
37
)
37
38
39
+ const (
40
+ persistentVolumeClaimPostCreationDelay = time .Minute
41
+ )
42
+
38
43
func (r * Reconciler ) volumeMemberReplacement (ctx context.Context , apiObject k8sutil.APIObject ,
39
44
spec api.DeploymentSpec , status api.DeploymentStatus ,
40
45
context PlanBuilderContext ) api.Plan {
@@ -68,6 +73,23 @@ func (r *Reconciler) volumeMemberReplacement(ctx context.Context, apiObject k8su
68
73
client , ok := context .ACS ().ClusterCache (member .Member .ClusterID )
69
74
if ok {
70
75
if pvc , ok := client .PersistentVolumeClaim ().V1 ().GetSimple (n ); ok {
76
+ if pvc .Status .Phase == core .ClaimPending {
77
+ continue
78
+ }
79
+
80
+ // Check if pvc was not created too recently
81
+ if t := pvc .GetCreationTimestamp (); ! t .IsZero () {
82
+ if time .Since (t .Time ) < persistentVolumeClaimPostCreationDelay {
83
+ // PVC was recreated recently, continue
84
+ continue
85
+ }
86
+ }
87
+
88
+ if t := pvc .GetDeletionTimestamp (); t != nil {
89
+ // PVC already under deletion
90
+ return nil
91
+ }
92
+
71
93
// Server is not part of plan and is not ready
72
94
return api.Plan {actions .NewAction (api .ActionTypeRemoveMemberPVC , member .Group , member .Member , "PVC is unschedulable" ).AddParam ("pvc" , string (pvc .GetUID ()))}
73
95
}
@@ -87,45 +109,51 @@ func (r *Reconciler) updateMemberConditionTypeMemberVolumeUnschedulableCondition
87
109
88
110
cache := context .ACS ().CurrentClusterCache ()
89
111
112
+ for _ , e := range status .Members .AsList () {
113
+ unschedulable := memberConditionTypeMemberVolumeUnschedulableRoot (cache , e )
114
+
115
+ if unschedulable == e .Member .Conditions .IsTrue (api .ConditionTypeMemberVolumeUnschedulable ) {
116
+ continue
117
+ } else if unschedulable && ! e .Member .Conditions .IsTrue (api .ConditionTypeMemberVolumeUnschedulable ) {
118
+ plan = append (plan , shared .UpdateMemberConditionActionV2 ("PV Unschedulable" , api .ConditionTypeMemberVolumeUnschedulable , e .Group , e .Member .ID , true ,
119
+ "PV Unschedulable" , "PV Unschedulable" , "" ))
120
+ } else if ! unschedulable && e .Member .Conditions .IsTrue (api .ConditionTypeMemberVolumeUnschedulable ) {
121
+ plan = append (plan , shared .RemoveMemberConditionActionV2 ("PV Schedulable" , api .ConditionTypeMemberVolumeUnschedulable , e .Group , e .Member .ID ))
122
+ }
123
+ }
124
+
125
+ return plan
126
+ }
127
+
128
+ type memberConditionTypeMemberVolumeUnschedulableCalculateFunc func (cache inspectorInterface.Inspector , pv * core.PersistentVolume , pvc * core.PersistentVolumeClaim ) bool
129
+
130
+ func memberConditionTypeMemberVolumeUnschedulableRoot (cache inspectorInterface.Inspector , member api.DeploymentStatusMemberElement ) bool {
90
131
volumeClient , err := cache .PersistentVolume ().V1 ()
91
132
if err != nil {
92
- // We cant fetch volumes, continue
93
- return nil
133
+ // We cant fetch volumes, remove condition as it cannot be evaluated
134
+ return false
94
135
}
95
136
96
- for _ , e := range status .Members .AsList () {
97
- if pvcStatus := e .Member .PersistentVolumeClaim ; pvcStatus != nil {
98
- if pvc , ok := context .ACS ().CurrentClusterCache ().PersistentVolumeClaim ().V1 ().GetSimple (pvcStatus .GetName ()); ok {
99
- if volumeName := pvc .Spec .VolumeName ; volumeName != "" {
100
- if pv , ok := volumeClient .GetSimple (volumeName ); ok {
101
- // We have volume and volumeclaim, lets calculate condition
102
- unschedulable := memberConditionTypeMemberVolumeUnschedulableCalculate (cache , pv , pvc ,
103
- memberConditionTypeMemberVolumeUnschedulableLocalStorageGone )
104
-
105
- if e .Member .Conditions .IsTrue (api .ConditionTypeScheduled ) {
106
- // We are scheduled, above checks can be ignored
107
- unschedulable = false
108
- }
137
+ if member .Member .Conditions .IsTrue (api .ConditionTypeScheduled ) {
138
+ // Scheduled member ignore PV Unschedulable condition
139
+ return false
140
+ }
109
141
110
- if unschedulable == e .Member .Conditions .IsTrue (api .ConditionTypeMemberVolumeUnschedulable ) {
111
- continue
112
- } else if unschedulable && ! e .Member .Conditions .IsTrue (api .ConditionTypeMemberVolumeUnschedulable ) {
113
- plan = append (plan , shared .UpdateMemberConditionActionV2 ("PV Unschedulable" , api .ConditionTypeMemberVolumeUnschedulable , e .Group , e .Member .ID , true ,
114
- "PV Unschedulable" , "PV Unschedulable" , "" ))
115
- } else if ! unschedulable && e .Member .Conditions .IsTrue (api .ConditionTypeMemberVolumeUnschedulable ) {
116
- plan = append (plan , shared .RemoveMemberConditionActionV2 ("PV Schedulable" , api .ConditionTypeMemberVolumeUnschedulable , e .Group , e .Member .ID ))
117
- }
118
- }
142
+ if pvcStatus := member .Member .PersistentVolumeClaim ; pvcStatus != nil {
143
+ if pvc , ok := cache .PersistentVolumeClaim ().V1 ().GetSimple (pvcStatus .GetName ()); ok {
144
+ if volumeName := pvc .Spec .VolumeName ; volumeName != "" {
145
+ if pv , ok := volumeClient .GetSimple (volumeName ); ok {
146
+ // We have volume and volumeclaim, lets calculate condition
147
+ return memberConditionTypeMemberVolumeUnschedulableCalculate (cache , pv , pvc ,
148
+ memberConditionTypeMemberVolumeUnschedulableLocalStorageGone )
119
149
}
120
150
}
121
151
}
122
152
}
123
153
124
- return plan
154
+ return false
125
155
}
126
156
127
- type memberConditionTypeMemberVolumeUnschedulableCalculateFunc func (cache inspectorInterface.Inspector , pv * core.PersistentVolume , pvc * core.PersistentVolumeClaim ) bool
128
-
129
157
func memberConditionTypeMemberVolumeUnschedulableCalculate (cache inspectorInterface.Inspector , pv * core.PersistentVolume , pvc * core.PersistentVolumeClaim , funcs ... memberConditionTypeMemberVolumeUnschedulableCalculateFunc ) bool {
130
158
for _ , f := range funcs {
131
159
if f (cache , pv , pvc ) {
0 commit comments