@@ -67,37 +67,16 @@ func (hec *HypervisorMaintenanceController) Reconcile(ctx context.Context, req c
6767 return ctrl.Result {}, nil
6868 }
6969
70- // Determine desired disabled condition and eviction state
71- disabledCond , evictingCond , evicted , err := hec .reconcileComputeService (ctx , hv )
72- if err != nil {
73- return ctrl.Result {}, err
74- }
75-
76- evictingCond , evicted , err = hec .reconcileEviction (ctx , hv , evictingCond , evicted )
77- if err != nil {
78- return ctrl.Result {}, err
79- }
80-
81- // Build status apply config: always include conditions this controller owns;
82- // omit ConditionTypeEvicting when it should be removed (SSA prunes it).
83- statusCfg := apiv1 .HypervisorStatus ().WithEvicted (evicted )
70+ // Build status apply config upfront; sub-functions mutate it directly.
71+ statusCfg := apiv1 .HypervisorStatus ().WithEvicted (hv .Status .Evicted )
8472 statusCfg .Conditions = utils .ConditionsFromStatus (hv .Status .Conditions )
8573
86- if disabledCond != nil {
87- utils . SetApplyConfigurationStatusCondition ( & statusCfg . Conditions , * disabledCond )
74+ if err := hec . reconcileComputeService ( ctx , hv , statusCfg ); err != nil {
75+ return ctrl. Result {}, err
8876 }
8977
90- if evictingCond != nil {
91- utils .SetApplyConfigurationStatusCondition (& statusCfg .Conditions , * evictingCond )
92- } else {
93- // Remove ConditionTypeEvicting by omitting it — SSA prunes sole-owned entries.
94- filtered := statusCfg .Conditions [:0 ]
95- for _ , c := range statusCfg .Conditions {
96- if c .Type == nil || * c .Type != kvmv1 .ConditionTypeEvicting {
97- filtered = append (filtered , c )
98- }
99- }
100- statusCfg .Conditions = filtered
78+ if err := hec .reconcileEviction (ctx , hv , statusCfg ); err != nil {
79+ return ctrl.Result {}, err
10180 }
10281
10382 return ctrl.Result {}, hec .Status ().Apply (ctx ,
@@ -106,85 +85,67 @@ func (hec *HypervisorMaintenanceController) Reconcile(ctx context.Context, req c
10685}
10786
10887// reconcileComputeService enables/disables the nova-compute service based on
109- // hv.Spec.Maintenance. Returns the desired HypervisorDisabled condition (nil if
110- // service ID is unset) and the initial evicting/evicted state.
111- func (hec * HypervisorMaintenanceController ) reconcileComputeService (ctx context.Context , hv * kvmv1.Hypervisor ) (
112- disabledCond * k8sacmetav1.ConditionApplyConfiguration ,
113- evictingCond * k8sacmetav1.ConditionApplyConfiguration ,
114- evicted bool ,
115- err error ,
116- ) {
88+ // hv.Spec.Maintenance and sets the HypervisorDisabled condition on statusCfg.
89+ func (hec * HypervisorMaintenanceController ) reconcileComputeService (ctx context.Context , hv * kvmv1.Hypervisor , statusCfg * apiv1.HypervisorStatusApplyConfiguration ) error {
11790 log := logger .FromContext (ctx )
11891 serviceId := hv .Status .ServiceID
11992
12093 if serviceId == "" {
12194 // We can only do something here, if there is a service to begin with.
12295 // The onboarding should take care of that.
123- return nil , nil , false , nil
96+ return nil
12497 }
12598
12699 switch hv .Spec .Maintenance {
127100 case kvmv1 .MaintenanceUnset :
128- cond := k8sacmetav1 .Condition ().
129- WithType (kvmv1 .ConditionTypeHypervisorDisabled ).
130- WithStatus (metav1 .ConditionFalse ).
131- WithMessage ("Hypervisor is enabled" ).
132- WithReason (kvmv1 .ConditionReasonSucceeded )
133-
134101 existing := meta .FindStatusCondition (hv .Status .Conditions , kvmv1 .ConditionTypeHypervisorDisabled )
135- if existing != nil && existing .Status == metav1 .ConditionFalse {
136- // Already enabled, nothing to do
137- return cond , nil , false , nil
138- }
139-
140- enableService := services.UpdateOpts {Status : services .ServiceEnabled }
141- // We need to enable the host as per spec
142- log .Info ("Enabling hypervisor" , "id" , serviceId )
143- if _ , err := services .Update (ctx , hec .computeClient , serviceId , enableService ).Extract (); err != nil {
144- return nil , nil , false , fmt .Errorf ("failed to enable hypervisor due to %w" , err )
102+ if existing == nil || existing .Status != metav1 .ConditionFalse {
103+ // We need to enable the host as per spec
104+ enableService := services.UpdateOpts {Status : services .ServiceEnabled }
105+ log .Info ("Enabling hypervisor" , "id" , serviceId )
106+ if _ , err := services .Update (ctx , hec .computeClient , serviceId , enableService ).Extract (); err != nil {
107+ return fmt .Errorf ("failed to enable hypervisor due to %w" , err )
108+ }
145109 }
146- return cond , nil , false , nil
110+ utils .SetApplyConfigurationStatusCondition (& statusCfg .Conditions ,
111+ * k8sacmetav1 .Condition ().
112+ WithType (kvmv1 .ConditionTypeHypervisorDisabled ).
113+ WithStatus (metav1 .ConditionFalse ).
114+ WithMessage ("Hypervisor is enabled" ).
115+ WithReason (kvmv1 .ConditionReasonSucceeded ))
147116
148117 case kvmv1 .MaintenanceManual , kvmv1 .MaintenanceAuto , kvmv1 .MaintenanceHA , kvmv1 .MaintenanceTermination :
149118 // Disable the compute service.
150119 // Also in case of HA, as it doesn't hurt to disable it twice, and this
151120 // allows us to enable the service again, when the maintenance field is
152121 // cleared in the case above.
153- cond := k8sacmetav1 .Condition ().
154- WithType (kvmv1 .ConditionTypeHypervisorDisabled ).
155- WithStatus (metav1 .ConditionTrue ).
156- WithMessage ("Hypervisor is disabled" ).
157- WithReason (kvmv1 .ConditionReasonSucceeded )
158-
159122 existing := meta .FindStatusCondition (hv .Status .Conditions , kvmv1 .ConditionTypeHypervisorDisabled )
160- if existing != nil && existing .Status == metav1 .ConditionTrue {
161- // Already disabled, nothing to do
162- return cond , nil , false , nil
163- }
164-
165- disableService := services.UpdateOpts {
166- Status : services .ServiceDisabled ,
167- DisabledReason : "Hypervisor CRD: spec.maintenance=" + hv .Spec .Maintenance ,
168- }
169- // We need to disable the host as per spec
170- log .Info ("Disabling hypervisor" , "id" , serviceId )
171- if _ , err := services .Update (ctx , hec .computeClient , serviceId , disableService ).Extract (); err != nil {
172- return nil , nil , false , fmt .Errorf ("failed to disable hypervisor due to %w" , err )
123+ if existing == nil || existing .Status != metav1 .ConditionTrue {
124+ disableService := services.UpdateOpts {
125+ Status : services .ServiceDisabled ,
126+ DisabledReason : "Hypervisor CRD: spec.maintenance=" + hv .Spec .Maintenance ,
127+ }
128+ // We need to disable the host as per spec
129+ log .Info ("Disabling hypervisor" , "id" , serviceId )
130+ if _ , err := services .Update (ctx , hec .computeClient , serviceId , disableService ).Extract (); err != nil {
131+ return fmt .Errorf ("failed to disable hypervisor due to %w" , err )
132+ }
173133 }
174- return cond , nil , false , nil
134+ utils .SetApplyConfigurationStatusCondition (& statusCfg .Conditions ,
135+ * k8sacmetav1 .Condition ().
136+ WithType (kvmv1 .ConditionTypeHypervisorDisabled ).
137+ WithStatus (metav1 .ConditionTrue ).
138+ WithMessage ("Hypervisor is disabled" ).
139+ WithReason (kvmv1 .ConditionReasonSucceeded ))
175140 }
176141
177- return nil , nil , false , nil
142+ return nil
178143}
179144
180- // reconcileEviction creates/deletes the Eviction CR and returns the desired
181- // ConditionTypeEvicting apply configuration (nil means remove the condition).
182- func (hec * HypervisorMaintenanceController ) reconcileEviction (
183- ctx context.Context ,
184- hv * kvmv1.Hypervisor ,
185- evictingCond * k8sacmetav1.ConditionApplyConfiguration ,
186- evicted bool ,
187- ) (* k8sacmetav1.ConditionApplyConfiguration , bool , error ) {
145+ // reconcileEviction creates/deletes the Eviction CR and sets the ConditionTypeEvicting
146+ // condition and Evicted scalar on statusCfg. When eviction should be removed, the
147+ // condition entry is filtered out so SSA prunes it.
148+ func (hec * HypervisorMaintenanceController ) reconcileEviction (ctx context.Context , hv * kvmv1.Hypervisor , statusCfg * apiv1.HypervisorStatusApplyConfiguration ) error {
188149 eviction := & kvmv1.Eviction {
189150 ObjectMeta : metav1.ObjectMeta {Name : hv .Name },
190151 }
@@ -193,45 +154,55 @@ func (hec *HypervisorMaintenanceController) reconcileEviction(
193154 case kvmv1 .MaintenanceUnset :
194155 // Avoid deleting the eviction over and over.
195156 if ! hv .Status .Evicted && meta .FindStatusCondition (hv .Status .Conditions , kvmv1 .ConditionTypeEvicting ) == nil {
196- return nil , false , nil
157+ return nil
158+ }
159+ if err := k8sclient .IgnoreNotFound (hec .Delete (ctx , eviction )); err != nil {
160+ return err
197161 }
198- err := k8sclient .IgnoreNotFound (hec .Delete (ctx , eviction ))
199- return nil , false , err // nil evictingCond → condition omitted from apply → SSA prunes it
162+ // Remove ConditionTypeEvicting by omitting it — SSA prunes sole-owned entries.
163+ filtered := statusCfg .Conditions [:0 ]
164+ for _ , c := range statusCfg .Conditions {
165+ if c .Type == nil || * c .Type != kvmv1 .ConditionTypeEvicting {
166+ filtered = append (filtered , c )
167+ }
168+ }
169+ statusCfg .Conditions = filtered
170+ statusCfg .WithEvicted (false )
200171
201172 case kvmv1 .MaintenanceManual , kvmv1 .MaintenanceAuto , kvmv1 .MaintenanceTermination :
202173 // In case of "ha", the host gets emptied from the HA service
203174 if cond := meta .FindStatusCondition (hv .Status .Conditions , kvmv1 .ConditionTypeEvicting ); cond != nil {
204175 if cond .Reason == kvmv1 .ConditionReasonSucceeded {
205176 // We are done here, no need to look at the eviction any more
206- return evictingCond , evicted , nil
177+ return nil
207178 }
208179 }
209180
210181 status , err := hec .ensureEviction (ctx , eviction , hv )
211182 if err != nil {
212- return evictingCond , evicted , err
183+ return err
213184 }
214185
215186 var reason , message string
216187 if status == metav1 .ConditionFalse {
217188 message = "Evicted"
218189 reason = kvmv1 .ConditionReasonSucceeded
219- evicted = true
190+ statusCfg . WithEvicted ( true )
220191 } else {
221192 message = "Evicting"
222193 reason = kvmv1 .ConditionReasonRunning
223- evicted = false
194+ statusCfg . WithEvicted ( false )
224195 }
225196
226- cond := k8sacmetav1 . Condition ().
227- WithType ( kvmv1 . ConditionTypeEvicting ).
228- WithStatus ( status ).
229- WithReason ( reason ).
230- WithMessage ( message )
231- return cond , evicted , nil
197+ utils . SetApplyConfigurationStatusCondition ( & statusCfg . Conditions ,
198+ * k8sacmetav1 . Condition ( ).
199+ WithType ( kvmv1 . ConditionTypeEvicting ).
200+ WithStatus ( status ).
201+ WithReason ( reason ).
202+ WithMessage ( message ))
232203 }
233204
234- return evictingCond , evicted , nil
205+ return nil
235206}
236207
237208func (hec * HypervisorMaintenanceController ) ensureEviction (ctx context.Context , eviction * kvmv1.Eviction , hypervisor * kvmv1.Hypervisor ) (metav1.ConditionStatus , error ) {
0 commit comments