@@ -26,6 +26,7 @@ import (
26
26
_ "crypto/sha512"
27
27
"encoding/base64"
28
28
"encoding/json"
29
+ "errors"
29
30
"fmt"
30
31
"net"
31
32
"net/url"
@@ -37,7 +38,7 @@ import (
37
38
38
39
"gopkg.in/yaml.v3"
39
40
corev1 "k8s.io/api/core/v1"
40
- "k8s.io/apimachinery/pkg/api/errors"
41
+ k8sapierrors "k8s.io/apimachinery/pkg/api/errors"
41
42
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
42
43
"k8s.io/apimachinery/pkg/runtime"
43
44
"k8s.io/apimachinery/pkg/types"
@@ -161,7 +162,6 @@ func (r *ImageClusterInstallReconciler) Reconcile(ctx context.Context, req ctrl.
161
162
return ctrl.Result {}, err
162
163
}
163
164
164
- /////// Requirements not met yet: setting defaults //////
165
165
cond := hivev1.ClusterInstallCondition {
166
166
Type : hivev1 .ClusterInstallRequirementsMet ,
167
167
Status : corev1 .ConditionFalse ,
@@ -172,31 +172,87 @@ func (r *ImageClusterInstallReconciler) Reconcile(ctx context.Context, req ctrl.
172
172
r .setRequirementsMetCondition (ctx , ici , cond .Status , cond .Reason , cond .Message )
173
173
}()
174
174
175
- /////// Requirements not met yet: starting config (CD, BMH) validation //////
175
+ // 1. Config validation phase
176
+ // Possible reasons for not meeting requirements and exiting reconcile:
177
+ // - ConfigurationPending: it's either the user needs to complete the ImageClusterInstall definition, or some of referenced
178
+ // resources (CD or BMH) are not available yet. In both cases the reconcile ends, and will be triggered again when the
179
+ // problem is resolved.
180
+ // - ConfigurationFailed: sets this reason when AutomatedCleaningMode cannot be modified in BMH.
181
+ cd , bmh , err := r .validateConfiguration (ctx , ici , & cond , log )
182
+ if err != nil {
183
+ return ctrl.Result {}, err
184
+ }
185
+
186
+ // 2. Host validation phase
187
+ // Possible reasons for not meeting requirements and exiting reconcile:
188
+ // - HostValidationPending: if BMH provisioning or hardware inspection is not ready yet, reconcile is requeued for 30s later.
189
+ // - HostValidationFailed: in case of any errors or invalid BMH configuration the reconcile ends here.
190
+ res , err := r .validateHost (ctx , ici , bmh , cd , & cond , log )
191
+ if err != nil {
192
+ return res , err
193
+ }
194
+
195
+ // 3. Image creation phase
196
+ // Possible reasons for not meeting requirements and exiting reconcile:
197
+ // - ImageCreationPending: when lock cannot be acquired, reconcile gets requeued for 5s later to try again.
198
+ // - ImageCreationFailed: any other unexpected error stops the reconcile loop with this reason.
199
+ imageUrl , res , err := r .createImage (ctx , ici , req , bmh , cd , & cond , log )
200
+ if ! res .IsZero () || err != nil {
201
+ return res , err
202
+ }
203
+
204
+ // 4. Host configuration phase
205
+ // Possible reasons for not meeting requirements and exiting reconcile:
206
+ // - HostConfigurationPending: sets this reason in following scenarios:
207
+ // > earlier DataImage instance is still being deleted for some reason (requeue after 30s)
208
+ // > current DataImage was just created less than a second ago so BMO might not be notified yet (requeue after 1s)
209
+ // > image-based-install-managed annotation is not set yet in BMH (no requeue)
210
+ // - HostConfigurationFailed: any unexpected errors during this phase will lead to this reason and finish reconcile.
211
+ // Reason for meeting requirements and completing reconcile:
212
+ // - HostConfigurationSucceeded: all the finishing steps went fine (like setting the boot time to now),
213
+ // and RequirementsMet condition can finally be true.
214
+ res , err = r .configureHost (ctx , ici , imageUrl , bmh , & cond , log )
215
+ if ! res .IsZero () || err != nil {
216
+ return res , err
217
+ }
218
+
219
+ return ctrl.Result {}, nil
220
+ }
221
+
222
+ func GetClusterConfigDir (namespacesDir , namespace , uid string ) string {
223
+ return filepath .Join (namespacesDir , namespace , uid , FilesDir , ClusterConfigDir )
224
+ }
225
+
226
+ func (r * ImageClusterInstallReconciler ) validateConfiguration (
227
+ ctx context.Context ,
228
+ ici * v1alpha1.ImageClusterInstall ,
229
+ cond * hivev1.ClusterInstallCondition ,
230
+ log logrus.FieldLogger ,
231
+ ) (* hivev1.ClusterDeployment , * bmh_v1alpha1.BareMetalHost , error ) {
176
232
cond .Reason = v1alpha1 .ConfigurationPendingReason
177
233
178
234
if ici .Spec .ClusterDeploymentRef == nil || ici .Spec .ClusterDeploymentRef .Name == "" {
179
235
cond .Message = "ClusterDeploymentRef is unset"
180
- return ctrl. Result {} , nil
236
+ return nil , nil , errors . New ( cond . Message )
181
237
}
182
238
183
- clusterDeployment , err := r .getCD (ctx , ici )
239
+ cd , err := r .getCD (ctx , ici )
184
240
if err != nil {
185
241
cond .Message = fmt .Sprintf ("failed to get ClusterDeployment %s/%s" , ici .Namespace , ici .Spec .ClusterDeploymentRef .Name )
186
242
log .WithError (err ).Error (cond .Message )
187
- return ctrl. Result {} , err
243
+ return nil , nil , err
188
244
}
189
245
190
246
if ici .Spec .BareMetalHostRef == nil {
191
247
cond .Message = "no BareMetalHostRef set, nothing to do without provided bmh"
192
- return ctrl. Result {} , nil
248
+ return nil , nil , errors . New ( cond . Message )
193
249
}
194
250
195
251
bmh , err := r .getBMH (ctx , ici .Spec .BareMetalHostRef )
196
252
if err != nil {
197
253
cond .Message = fmt .Sprintf ("failed to get BareMetalHost %s/%s" , ici .Spec .BareMetalHostRef .Namespace , ici .Spec .BareMetalHostRef .Name )
198
254
log .WithError (err ).Error (cond .Message )
199
- return ctrl. Result {} , err
255
+ return nil , nil , err
200
256
}
201
257
202
258
// AutomatedCleaningMode is set at the beginning of this flow because we don't want ironic to format the disk
@@ -208,27 +264,48 @@ func (r *ImageClusterInstallReconciler) Reconcile(ctx context.Context, req ctrl.
208
264
cond .Reason = v1alpha1 .ConfigurationFailedReason
209
265
cond .Message = fmt .Sprintf ("failed to disable automated cleaning mode for BareMetalHost %s/%s" , bmh .Namespace , bmh .Name )
210
266
log .WithError (err ).Error (cond .Message )
211
- return ctrl. Result {} , err
267
+ return nil , nil , err
212
268
}
213
269
}
214
270
215
- /////// Requirements not met yet: config validated, starting host validation //////
271
+ return cd , bmh , nil
272
+ }
273
+
274
+ func (r * ImageClusterInstallReconciler ) validateHost (
275
+ ctx context.Context ,
276
+ ici * v1alpha1.ImageClusterInstall ,
277
+ bmh * bmh_v1alpha1.BareMetalHost ,
278
+ cd * hivev1.ClusterDeployment ,
279
+ cond * hivev1.ClusterInstallCondition ,
280
+ log logrus.FieldLogger ,
281
+ ) (ctrl.Result , error ) {
216
282
cond .Reason = v1alpha1 .HostValidationFailedReason
217
283
218
- if res , err := r .validateBMH (ctx , ici , bmh , & cond ); ! res .IsZero () || err != nil {
284
+ if res , err := r .validateBMH (ici , bmh , cond ); ! res .IsZero () || err != nil {
219
285
return res , err
220
286
}
221
287
222
- if err = r .setClusterInstallMetadata (ctx , log , ici , clusterDeployment ); err != nil {
288
+ if err : = r .setClusterInstallMetadata (ctx , log , ici , cd ); err != nil {
223
289
cond .Message = "failed to set ImageClusterInstall data"
224
290
log .WithError (err ).Error (cond .Message )
225
291
return ctrl.Result {}, err
226
292
}
227
293
228
- /////// Requirements not met yet: host validated, starting image creation //////
294
+ return ctrl.Result {}, nil
295
+ }
296
+
297
+ func (r * ImageClusterInstallReconciler ) createImage (
298
+ ctx context.Context ,
299
+ ici * v1alpha1.ImageClusterInstall ,
300
+ req ctrl.Request ,
301
+ bmh * bmh_v1alpha1.BareMetalHost ,
302
+ cd * hivev1.ClusterDeployment ,
303
+ cond * hivev1.ClusterInstallCondition ,
304
+ log logrus.FieldLogger ,
305
+ ) (string , ctrl.Result , error ) {
229
306
cond .Reason = v1alpha1 .ImageCreationFailedReason
230
307
231
- res , err := r .writeInputData (ctx , log , ici , clusterDeployment , bmh )
308
+ res , err := r .writeInputData (ctx , log , ici , cd , bmh )
232
309
if ! res .IsZero () || err != nil {
233
310
cond .Reason = v1alpha1 .ImageCreationPendingReason
234
311
cond .Message = "could not acquire lock for image data"
@@ -237,19 +314,28 @@ func (r *ImageClusterInstallReconciler) Reconcile(ctx context.Context, req ctrl.
237
314
cond .Message = "failed to create image"
238
315
log .WithError (err ).Error (cond .Message )
239
316
}
240
- return res , err
317
+ return "" , res , err
241
318
}
242
319
243
- r .labelReferencedObjectsForBackup (ctx , log , ici , clusterDeployment )
320
+ r .labelReferencedObjectsForBackup (ctx , log , ici , cd )
244
321
245
322
imageUrl , err := url .JoinPath (r .BaseURL , "images" , req .Namespace , fmt .Sprintf ("%s.iso" , ici .ObjectMeta .UID ))
246
323
if err != nil {
247
324
cond .Message = "failed to create image url"
248
325
log .WithError (err ).Error (cond .Message )
249
- return ctrl.Result {}, err
326
+ return "" , ctrl.Result {}, err
250
327
}
251
328
252
- /////// Requirements not met yet: image created, starting host configuration //////
329
+ return imageUrl , ctrl.Result {}, nil
330
+ }
331
+ func (r * ImageClusterInstallReconciler ) configureHost (
332
+ ctx context.Context ,
333
+ ici * v1alpha1.ImageClusterInstall ,
334
+ imageUrl string ,
335
+ bmh * bmh_v1alpha1.BareMetalHost ,
336
+ cond * hivev1.ClusterInstallCondition ,
337
+ log logrus.FieldLogger ,
338
+ ) (ctrl.Result , error ) {
253
339
cond .Reason = v1alpha1 .HostConfigurationFailedReason
254
340
255
341
dataImage , res , err := r .ensureBMHDataImage (ctx , log , bmh , imageUrl )
@@ -267,8 +353,8 @@ func (r *ImageClusterInstallReconciler) Reconcile(ctx context.Context, req ctrl.
267
353
// in case the dataImage was created less than a second ago requeue to allow BMO some time to get
268
354
// notified about the newly created DataImage before adding the reboot annotation in updateBMHProvisioningState
269
355
cond .Reason = v1alpha1 .HostConfigurationPendingReason
270
- cond .Message = "Waiting for BareMetalHost to get DataImage "
271
- return ctrl.Result {RequeueAfter : r .Options .DataImageCoolDownPeriod }, err
356
+ cond .Message = "Waiting for DataImage to cool down "
357
+ return ctrl.Result {RequeueAfter : r .Options .DataImageCoolDownPeriod }, errors . New ( cond . Message )
272
358
}
273
359
274
360
if err := r .updateBMHProvisioningState (ctx , log , bmh , dataImage ); err != nil {
@@ -281,7 +367,7 @@ func (r *ImageClusterInstallReconciler) Reconcile(ctx context.Context, req ctrl.
281
367
cond .Reason = v1alpha1 .HostConfigurationPendingReason
282
368
cond .Message = fmt .Sprintf ("Waiting for BMH to get %s annotation" , ibioManagedBMH )
283
369
log .Info (cond .Message )
284
- return ctrl.Result {}, nil
370
+ return ctrl.Result {}, errors . New ( cond . Message )
285
371
}
286
372
287
373
if ici .Status .BareMetalHostRef == nil {
@@ -306,12 +392,7 @@ func (r *ImageClusterInstallReconciler) Reconcile(ctx context.Context, req ctrl.
306
392
return ctrl.Result {}, nil
307
393
}
308
394
309
- func GetClusterConfigDir (namespacesDir , namespace , uid string ) string {
310
- return filepath .Join (namespacesDir , namespace , uid , FilesDir , ClusterConfigDir )
311
- }
312
-
313
395
func (r * ImageClusterInstallReconciler ) validateBMH (
314
- ctx context.Context ,
315
396
ici * v1alpha1.ImageClusterInstall ,
316
397
bmh * bmh_v1alpha1.BareMetalHost ,
317
398
cond * hivev1.ClusterInstallCondition ) (ctrl.Result , error ) {
@@ -539,7 +620,7 @@ func (r *ImageClusterInstallReconciler) ensureBMHDataImage(
539
620
return dataImage , ctrl.Result {}, nil
540
621
}
541
622
542
- if err != nil && ! errors .IsNotFound (err ) {
623
+ if err != nil && ! k8sapierrors .IsNotFound (err ) {
543
624
return dataImage , ctrl.Result {}, err
544
625
}
545
626
log .Infof ("creating new dataImage for BareMetalHost (%s/%s)" , bmh .Name , bmh .Namespace )
@@ -600,7 +681,7 @@ func (r *ImageClusterInstallReconciler) removeBMHDataImage(ctx context.Context,
600
681
601
682
bmh := & bmh_v1alpha1.BareMetalHost {}
602
683
if err := r .Get (ctx , bmhRef , bmh ); err != nil {
603
- if errors .IsNotFound (err ) {
684
+ if k8sapierrors .IsNotFound (err ) {
604
685
log .Warnf ("Referenced BareMetalHost %s/%s does not exist, not waiting for dataImage deletion" , bmhRef .Namespace , bmhRef .Name )
605
686
return nil , nil
606
687
} else {
@@ -634,7 +715,7 @@ func (r *ImageClusterInstallReconciler) deleteDataImage(ctx context.Context, log
634
715
dataImage := & bmh_v1alpha1.DataImage {}
635
716
636
717
if err := r .Get (ctx , dataImageRef , dataImage ); err != nil {
637
- if errors .IsNotFound (err ) {
718
+ if k8sapierrors .IsNotFound (err ) {
638
719
log .Infof ("Can't find DataImage from BareMetalHost %s/%s, Nothing to remove" , dataImageRef .Namespace , dataImageRef .Name )
639
720
return nil , nil
640
721
}
0 commit comments