@@ -22,6 +22,7 @@ package reconcile
2222
2323import (
2424 "context"
25+ "time"
2526
2627 core "k8s.io/api/core/v1"
2728
@@ -35,6 +36,10 @@ import (
3536 inspectorInterface "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector"
3637)
3738
39+ const (
40+ persistentVolumeClaimPostCreationDelay = time .Minute
41+ )
42+
3843func (r * Reconciler ) volumeMemberReplacement (ctx context.Context , apiObject k8sutil.APIObject ,
3944 spec api.DeploymentSpec , status api.DeploymentStatus ,
4045 context PlanBuilderContext ) api.Plan {
@@ -68,6 +73,23 @@ func (r *Reconciler) volumeMemberReplacement(ctx context.Context, apiObject k8su
6873 client , ok := context .ACS ().ClusterCache (member .Member .ClusterID )
6974 if ok {
7075 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+
7193 // Server is not part of plan and is not ready
7294 return api.Plan {actions .NewAction (api .ActionTypeRemoveMemberPVC , member .Group , member .Member , "PVC is unschedulable" ).AddParam ("pvc" , string (pvc .GetUID ()))}
7395 }
@@ -87,45 +109,51 @@ func (r *Reconciler) updateMemberConditionTypeMemberVolumeUnschedulableCondition
87109
88110 cache := context .ACS ().CurrentClusterCache ()
89111
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 {
90131 volumeClient , err := cache .PersistentVolume ().V1 ()
91132 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
94135 }
95136
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+ }
109141
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 )
119149 }
120150 }
121151 }
122152 }
123153
124- return plan
154+ return false
125155}
126156
127- type memberConditionTypeMemberVolumeUnschedulableCalculateFunc func (cache inspectorInterface.Inspector , pv * core.PersistentVolume , pvc * core.PersistentVolumeClaim ) bool
128-
129157func memberConditionTypeMemberVolumeUnschedulableCalculate (cache inspectorInterface.Inspector , pv * core.PersistentVolume , pvc * core.PersistentVolumeClaim , funcs ... memberConditionTypeMemberVolumeUnschedulableCalculateFunc ) bool {
130158 for _ , f := range funcs {
131159 if f (cache , pv , pvc ) {
0 commit comments