Skip to content

Commit 0c28435

Browse files
HandleServerMaintainenceRefs in BMCVersionSet
1 parent 74f3bba commit 0c28435

File tree

2 files changed

+341
-7
lines changed

2 files changed

+341
-7
lines changed

internal/controller/bmcversionset_controller.go

Lines changed: 155 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ func (r *BMCVersionSetReconciler) reconcile(
204204
return ctrl.Result{}, fmt.Errorf("failed to delete orphaned BMCVersion resources %w", err)
205205
}
206206

207-
if err := r.patchBMCVersionfromTemplate(ctx, log, &bmcVersionSet.Spec.BMCVersionTemplate, ownedBMCVersions); err != nil {
207+
if err := r.patchBMCVersionfromTemplate(ctx, log, bmcList, bmcVersionSet, ownedBMCVersions); err != nil {
208208
return ctrl.Result{}, fmt.Errorf("failed to patch BMCVersion spec from template %w", err)
209209
}
210210

@@ -240,9 +240,16 @@ func (r *BMCVersionSetReconciler) createMissingBMCVersions(
240240
ObjectMeta: metav1.ObjectMeta{
241241
GenerateName: "bmc-version-set-",
242242
}}
243-
243+
serverMaintenanceRefsProvided, err := r.getProvidedServerMaintenanceRefs(ctx, &bmc, bmcVersionSet)
244+
if err != nil {
245+
errs = append(errs, fmt.Errorf("failed to get provided ServerMaintenanceRefs for BMC %s: %w", bmc.Name, err))
246+
continue
247+
}
244248
opResult, err := controllerutil.CreateOrPatch(ctx, r.Client, newBMCVersion, func() error {
245249
newBMCVersion.Spec.BMCVersionTemplate = *bmcVersionSet.Spec.BMCVersionTemplate.DeepCopy()
250+
// patch ServerMaintenance referenced by BMC's Servers
251+
newBMCVersion.Spec.ServerMaintenanceRefs = serverMaintenanceRefsProvided
252+
246253
newBMCVersion.Spec.BMCRef = &corev1.LocalObjectReference{Name: bmc.Name}
247254
return controllerutil.SetControllerReference(bmcVersionSet, newBMCVersion, r.Client.Scheme())
248255
})
@@ -255,6 +262,52 @@ func (r *BMCVersionSetReconciler) createMissingBMCVersions(
255262
return errors.Join(errs...)
256263
}
257264

265+
func (r *BMCVersionSetReconciler) getProvidedServerMaintenanceRefs(
266+
ctx context.Context,
267+
bmc *metalv1alpha1.BMC,
268+
bmcVersionSet *metalv1alpha1.BMCVersionSet,
269+
) ([]metalv1alpha1.ServerMaintenanceRefItem, error) {
270+
serverMaintenanceRefMap := make(map[string]metalv1alpha1.ServerMaintenanceRefItem)
271+
for _, ref := range bmcVersionSet.Spec.BMCVersionTemplate.ServerMaintenanceRefs {
272+
if ref.ServerMaintenanceRef != nil {
273+
serverMaintenanceRefMap[ref.ServerMaintenanceRef.Name] = ref
274+
}
275+
}
276+
// get servers for this BMC
277+
serverList, err := r.getBMCOwnedServers(ctx, bmc)
278+
if err != nil {
279+
return nil, fmt.Errorf("failed to get servers owned by BMC %s: %w", bmc.Name, err)
280+
}
281+
// get map of servers owned by this BMC
282+
serverMap := make(map[string]struct{})
283+
for _, server := range serverList.Items {
284+
serverMap[server.Name] = struct{}{}
285+
}
286+
// filter the serverMaintenances which are for servers owned by this BMC
287+
serverMaintenancesList := &metalv1alpha1.ServerMaintenanceList{}
288+
err = clientutils.ListAndFilter(ctx, r.Client, serverMaintenancesList, func(object client.Object) (bool, error) {
289+
serverMaintenance := object.(*metalv1alpha1.ServerMaintenance)
290+
if serverMaintenance.Spec.ServerRef == nil {
291+
return false, nil
292+
}
293+
if _, exists := serverMap[serverMaintenance.Spec.ServerRef.Name]; !exists {
294+
return false, nil
295+
}
296+
return true, nil
297+
})
298+
if err != nil {
299+
return nil, fmt.Errorf("failed to list ServerMaintenance for BMC's %s: Servers. Error %w", bmc.Name, err)
300+
}
301+
302+
serverMaintenanceRefs := []metalv1alpha1.ServerMaintenanceRefItem{}
303+
for _, serverMaintenance := range serverMaintenancesList.Items {
304+
if ref, exists := serverMaintenanceRefMap[serverMaintenance.Name]; exists {
305+
serverMaintenanceRefs = append(serverMaintenanceRefs, ref)
306+
}
307+
}
308+
return serverMaintenanceRefs, nil
309+
}
310+
258311
func (r *BMCVersionSetReconciler) deleteOrphanBMCVersions(
259312
ctx context.Context,
260313
log logr.Logger,
@@ -288,21 +341,80 @@ func (r *BMCVersionSetReconciler) deleteOrphanBMCVersions(
288341
func (r *BMCVersionSetReconciler) patchBMCVersionfromTemplate(
289342
ctx context.Context,
290343
log logr.Logger,
291-
bmcVersionTemplate *metalv1alpha1.BMCVersionTemplate,
344+
bmcList *metalv1alpha1.BMCList,
345+
bmcVersionSet *metalv1alpha1.BMCVersionSet,
292346
bmcVersionList *metalv1alpha1.BMCVersionList,
293347
) error {
294348
if len(bmcVersionList.Items) == 0 {
295349
log.V(1).Info("No BMCVersion found, skipping spec template update")
296350
return nil
297351
}
352+
bmcNameMap := make(map[string]metalv1alpha1.BMC)
353+
for _, bmc := range bmcList.Items {
354+
bmcNameMap[bmc.Name] = bmc
355+
}
298356

299357
var errs []error
300358
for _, bmcVersion := range bmcVersionList.Items {
301-
if bmcVersion.Status.State == metalv1alpha1.BMCVersionStateInProgress {
359+
if bmcVersion.Status.State == metalv1alpha1.BMCVersionStateInProgress && bmcVersion.Status.UpgradeTask != nil {
360+
log.V(1).Info("Skipping BMCVersion spec patching as it is in InProgress state with an active UpgradeTask")
361+
continue
362+
}
363+
bmc, exists := bmcNameMap[bmcVersion.Spec.BMCRef.Name]
364+
if !exists {
365+
errs = append(errs, fmt.Errorf("BMC %s not found for BMCVersion %s", bmcVersion.Spec.BMCRef.Name, bmcVersion.Name))
366+
continue
367+
}
368+
serverMaintenanceRefsProvided, err := r.getProvidedServerMaintenanceRefs(ctx, &bmc, bmcVersionSet)
369+
if err != nil {
370+
errs = append(errs, fmt.Errorf("failed to get ServerMaintenanceRefs for BMC %s: %w", bmc.Name, err))
371+
continue
372+
}
373+
374+
serverMaintenancesRefsCreated, err := r.getCreatedServerMaintenanceRefs(ctx, &bmcVersion)
375+
if err != nil {
376+
errs = append(errs, fmt.Errorf("failed to get owned ServerMaintenance for BMCVersion %s: %w", bmcVersion.Name, err))
302377
continue
303378
}
379+
380+
var serverMaintenanceRefsMerged []metalv1alpha1.ServerMaintenanceRefItem
381+
if len(serverMaintenancesRefsCreated) > 0 && len(serverMaintenanceRefsProvided) > 0 {
382+
// merge provided and created serverMaintenanceRefs
383+
serverMaintenanceRefMap := make(map[string]metalv1alpha1.ServerMaintenanceRefItem)
384+
for _, ref := range serverMaintenanceRefsProvided {
385+
if ref.ServerMaintenanceRef != nil {
386+
serverMaintenanceRefMap[ref.ServerMaintenanceRef.Name] = ref
387+
}
388+
}
389+
for _, ref := range serverMaintenancesRefsCreated {
390+
if ref.ServerMaintenanceRef != nil {
391+
serverMaintenanceRefMap[ref.ServerMaintenanceRef.Name] = ref
392+
}
393+
}
394+
for _, ref := range serverMaintenanceRefMap {
395+
serverMaintenanceRefsMerged = append(serverMaintenanceRefsMerged, ref)
396+
}
397+
398+
// check if the lenght is as expected
399+
server, err := r.getBMCOwnedServers(ctx, &bmc)
400+
if err != nil {
401+
errs = append(errs, fmt.Errorf("failed to get servers owned by BMC %s to verify serverMaintenanceRef: %w", bmc.Name, err))
402+
continue
403+
}
404+
if len(serverMaintenanceRefsMerged) > len(server.Items) {
405+
errs = append(errs, fmt.Errorf("number of ServerMaintenanceRefs %d exceeds number of Servers %d for BMC %s",
406+
len(serverMaintenanceRefsMerged), len(server.Items), bmc.Name))
407+
continue
408+
}
409+
} else if len(serverMaintenanceRefsProvided) > 0 {
410+
serverMaintenanceRefsMerged = serverMaintenanceRefsProvided
411+
} else {
412+
serverMaintenanceRefsMerged = serverMaintenancesRefsCreated
413+
}
414+
304415
opResult, err := controllerutil.CreateOrPatch(ctx, r.Client, &bmcVersion, func() error {
305-
bmcVersion.Spec.BMCVersionTemplate = *bmcVersionTemplate.DeepCopy()
416+
bmcVersion.Spec.BMCVersionTemplate = *bmcVersionSet.Spec.BMCVersionTemplate.DeepCopy()
417+
bmcVersion.Spec.BMCVersionTemplate.ServerMaintenanceRefs = serverMaintenanceRefsMerged
306418
return nil
307419
}) //nolint:errcheck
308420
if err != nil {
@@ -346,6 +458,44 @@ func (r *BMCVersionSetReconciler) getOwnedBMCVersions(
346458
return bmcVersionList, nil
347459
}
348460

461+
func (r *BMCVersionSetReconciler) getBMCOwnedServers(
462+
ctx context.Context,
463+
bmc *metalv1alpha1.BMC,
464+
) (*metalv1alpha1.ServerList, error) {
465+
serverList := &metalv1alpha1.ServerList{}
466+
if err := clientutils.ListAndFilterControlledBy(ctx, r.Client, bmc, serverList); err != nil {
467+
return nil, err
468+
}
469+
return serverList, nil
470+
}
471+
472+
func (r *BMCVersionSetReconciler) getCreatedServerMaintenanceRefs(
473+
ctx context.Context,
474+
bmcVersion *metalv1alpha1.BMCVersion,
475+
) ([]metalv1alpha1.ServerMaintenanceRefItem, error) {
476+
serverMaintenanceRefMap := make(map[string]metalv1alpha1.ServerMaintenanceRefItem)
477+
for _, ref := range bmcVersion.Spec.BMCVersionTemplate.ServerMaintenanceRefs {
478+
if ref.ServerMaintenanceRef != nil {
479+
serverMaintenanceRefMap[ref.ServerMaintenanceRef.Name] = ref
480+
}
481+
}
482+
483+
serverMaintenanceList := &metalv1alpha1.ServerMaintenanceList{}
484+
if err := clientutils.ListAndFilterControlledBy(ctx, r.Client, bmcVersion, serverMaintenanceList); err != nil {
485+
return nil, err
486+
}
487+
488+
bmcVersion.Spec.ServerMaintenanceRefs = []metalv1alpha1.ServerMaintenanceRefItem{}
489+
490+
serverMaintenanceRefs := []metalv1alpha1.ServerMaintenanceRefItem{}
491+
for _, serverMaintenance := range serverMaintenanceList.Items {
492+
if ref, exists := serverMaintenanceRefMap[serverMaintenance.Name]; exists {
493+
serverMaintenanceRefs = append(serverMaintenanceRefs, ref)
494+
}
495+
}
496+
return serverMaintenanceRefs, nil
497+
}
498+
349499
func (r *BMCVersionSetReconciler) getBMCBySelector(
350500
ctx context.Context,
351501
bmcVersionSet *metalv1alpha1.BMCVersionSet,

0 commit comments

Comments
 (0)