Skip to content

Commit 07bed5a

Browse files
Add check to verify pending setting tasks on bios
1 parent 227aa90 commit 07bed5a

File tree

6 files changed

+237
-112
lines changed

6 files changed

+237
-112
lines changed

bmc/bmc.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ type BMC interface {
4444

4545
GetBiosAttributeValues(ctx context.Context, systemUUID string, attributes []string) (redfish.SettingsAttributes, error)
4646

47+
GetPendingAttributeValues(ctx context.Context, systemUUID string) (redfish.SettingsAttributes, error)
48+
4749
CheckBiosAttributes(attrs redfish.SettingsAttributes) (reset bool, err error)
4850

4951
SetBiosAttributesOnReset(ctx context.Context, systemUUID string, attributes redfish.SettingsAttributes) (err error)

bmc/redfish.go

Lines changed: 18 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,6 @@ func (r *RedfishBMC) GetBiosAttributeValues(
294294
func (r *RedfishBMC) GetPendingAttributeValues(
295295
ctx context.Context,
296296
systemUUID string,
297-
attributes []string,
298297
) (
299298
result redfish.SettingsAttributes,
300299
err error,
@@ -305,8 +304,8 @@ func (r *RedfishBMC) GetPendingAttributeValues(
305304
}
306305

307306
var tSys struct {
308-
redfish.ComputerSystem
309-
Bios common.Link
307+
Bios common.Link
308+
BiosVersion string
310309
}
311310

312311
err = json.Unmarshal(system.RawData, &tSys)
@@ -317,49 +316,39 @@ func (r *RedfishBMC) GetPendingAttributeValues(
317316
var tBios struct {
318317
Settings common.Settings `json:"@Redfish.Settings"`
319318
}
320-
321-
biosResp, err := system.GetClient().Get(tSys.Bios.String())
319+
err = r.GetEntityFromUri(tSys.Bios.String(), system.GetClient(), &tBios)
322320
if err != nil {
323321
return result, err
324322
}
325-
defer biosResp.Body.Close() // nolint: errcheck
326323

327-
biosRawBody, err := io.ReadAll(biosResp.Body)
328-
if err != nil {
329-
return result, err
324+
var tBiosSetting struct {
325+
Attributes redfish.SettingsAttributes `json:"Attributes"`
330326
}
331-
332-
err = json.Unmarshal(biosRawBody, &tBios)
327+
err = r.GetEntityFromUri(tBios.Settings.SettingsObject.String(), system.GetClient(), &tBiosSetting)
333328
if err != nil {
334329
return result, err
335330
}
336331

337-
// todo: might need to use bios here rather that system
338-
// bios, err := system.Bios()
339-
// if err != nil {
340-
// return
341-
// }
342-
respBiosSetting, err := system.GetClient().Get(tBios.Settings.SettingsObject.String())
343-
if err != nil {
344-
return result, err
345-
}
346-
defer respBiosSetting.Body.Close() // nolint: errcheck
332+
return tBiosSetting.Attributes, nil
333+
}
347334

348-
biosSettingRawBody, err := io.ReadAll(respBiosSetting.Body)
335+
func (r *RedfishBMC) GetEntityFromUri(uri string, client common.Client, entity any) error {
336+
Resp, err := client.Get(uri)
349337
if err != nil {
350-
return result, err
338+
return err
351339
}
340+
defer Resp.Body.Close() // nolint: errcheck
352341

353-
var tBiosSetting struct {
354-
Attributes redfish.SettingsAttributes `json:"Attributes"`
342+
RespRawBody, err := io.ReadAll(Resp.Body)
343+
if err != nil {
344+
return err
355345
}
356346

357-
err = json.Unmarshal(biosSettingRawBody, &tBiosSetting)
347+
err = json.Unmarshal(RespRawBody, &entity)
358348
if err != nil {
359-
return result, err
349+
return err
360350
}
361-
362-
return tBiosSetting.Attributes, nil
351+
return nil
363352
}
364353

365354
// SetBiosAttributesOnReset sets given bios attributes.

bmc/redfish_local.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,18 @@ func (r RedfishLocalBMC) PowerOff(ctx context.Context, systemUUID string) error
6262
return nil
6363
}
6464

65+
func (r *RedfishLocalBMC) GetPendingAttributeValues(
66+
ctx context.Context,
67+
systemUUID string,
68+
) (
69+
redfish.SettingsAttributes,
70+
error,
71+
) {
72+
// can not unit test this ATM.
73+
// todo: find a way to enchance refish_local.go to give ability to test this
74+
return nil, nil
75+
}
76+
6577
// mock SetBiosAttributesOnReset sets given bios attributes for unit testing.
6678
func (r *RedfishLocalBMC) SetBiosAttributesOnReset(
6779
ctx context.Context,
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
apiVersion: metal.ironcore.dev/v1alpha1
2-
kind: biossettings
2+
kind: BIOSSettings
33
metadata:
44
labels:
55
app.kubernetes.io/name: metal-operator
@@ -9,7 +9,7 @@ spec:
99
serverRef:
1010
name: endpoint-sample-system-0
1111
biosSettings:
12-
version: 2.10.3
12+
version: 2.10.2
1313
settings:
14-
PxeDev1EnDis: Disable
14+
PxeDev1EnDis: Enabled
1515
ServerMaintenancePolicyTemplate: OwnerApproval

internal/controller/biossettings_controller.go

Lines changed: 77 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -234,8 +234,16 @@ func (r *BiosSettingsReconciler) ensureServerMaintenanceStateTransition(
234234
) (ctrl.Result, error) {
235235
switch biosSettings.Status.State {
236236
case "", metalv1alpha1.BIOSSettingsStatePending:
237-
//todo: check that in initial state there is no pending BIOS maintenance left behind
238-
err := r.updateBiosSettingsStatus(ctx, log, biosSettings, metalv1alpha1.BIOSSettingsStateInProgress)
237+
pendingPresent, pendingSettings, err := r.checkforPendingSettingsOnBIOS(ctx, log, server, nil)
238+
if err != nil {
239+
return ctrl.Result{}, fmt.Errorf("failed to get pending settings on bios: %w", err)
240+
}
241+
if len(pendingSettings) > 0 || pendingPresent {
242+
log.V(1).Info("Pending bios setting tasks found", "biosSettings pending tasks", pendingSettings)
243+
err := r.updateBiosSettingsStatus(ctx, log, biosSettings, metalv1alpha1.BIOSSettingsStateFailed)
244+
return ctrl.Result{}, err
245+
}
246+
err = r.updateBiosSettingsStatus(ctx, log, biosSettings, metalv1alpha1.BIOSSettingsStateInProgress)
239247
return ctrl.Result{}, err
240248
case metalv1alpha1.BIOSSettingsStateInProgress:
241249
return r.handleSettingInProgressState(ctx, log, biosSettings, server)
@@ -256,11 +264,9 @@ func (r *BiosSettingsReconciler) handleSettingInProgressState(
256264
) (ctrl.Result, error) {
257265

258266
currentBiosVersion, settingsDiff, err := r.getBIOSVersionAndSettingDifference(ctx, log, biosSettings, server)
259-
260267
if err != nil {
261268
return ctrl.Result{}, fmt.Errorf("failed to get BIOS settings: %w", err)
262269
}
263-
264270
// if setting is not different, complete the BIOS tasks, does not matter if the bios version do not match
265271
if len(settingsDiff) == 0 {
266272
// move status to completed
@@ -344,16 +350,43 @@ func (r *BiosSettingsReconciler) applySettingUpdateStateTransition(
344350
log.V(1).Info("Reconciled biosSettings at Pending state")
345351
return ctrl.Result{}, err
346352
case metalv1alpha1.BIOSSettingUpdateStateIssue:
347-
// todo: make it idepotent
348353
bmcClient, err := bmcutils.GetBMCClientForServer(ctx, r.Client, server, r.Insecure, r.BMCOptions)
349354
if err != nil {
350355
return ctrl.Result{}, err
351356
}
352357
defer bmcClient.Logout()
353358

354-
err = bmcClient.SetBiosAttributesOnReset(ctx, server.Spec.SystemUUID, settingsDiff)
359+
// check if the pending tasks not present on the bios settings
360+
pendingPresent, _, err := r.checkforPendingSettingsOnBIOS(ctx, log, server, nil)
355361
if err != nil {
356-
return ctrl.Result{}, fmt.Errorf("failed to set BMC settings: %w", err)
362+
return ctrl.Result{}, fmt.Errorf("failed to get pending BIOS settings: %w", err)
363+
}
364+
var pendingSettingsDiff redfish.SettingsAttributes
365+
if !pendingPresent {
366+
err = bmcClient.SetBiosAttributesOnReset(ctx, server.Spec.SystemUUID, settingsDiff)
367+
if err != nil {
368+
return ctrl.Result{}, fmt.Errorf("failed to set BMC settings: %w", err)
369+
}
370+
}
371+
372+
// get latest pending settings, and expect it to be zero different from the required settings.
373+
pendingPresent, pendingSettingsDiff, err = r.checkforPendingSettingsOnBIOS(ctx, log, server, settingsDiff)
374+
if err != nil {
375+
return ctrl.Result{}, fmt.Errorf("failed to get pending BIOS settings: %w", err)
376+
}
377+
378+
// at this point the bios setting update needs to be already issued.
379+
if !pendingPresent {
380+
// todo: fail after X amount of time
381+
log.V(1).Info("bios Setting update issued to bmc not accepted. retrying....")
382+
return ctrl.Result{}, errors.Join(err, fmt.Errorf("bios setting issued to bmc not accepted"))
383+
}
384+
385+
// latest pending settings to be zero different from the required settings.
386+
if len(pendingSettingsDiff) > 0 {
387+
log.V(1).Info("Unknown pending BIOS settings found", "Unknown pending settings", pendingSettingsDiff)
388+
err := r.updateBiosSettingsStatus(ctx, log, biosSettings, metalv1alpha1.BIOSSettingsStateFailed)
389+
return ctrl.Result{}, err
357390
}
358391

359392
// if we dont need (have not requested maintenance) reboot. skip reboot steps.
@@ -367,7 +400,6 @@ func (r *BiosSettingsReconciler) applySettingUpdateStateTransition(
367400
return ctrl.Result{}, err
368401
case metalv1alpha1.BIOSSettingUpdateWaitOnServerRebootPowerOff:
369402
// expected state it to be off and initial state is to be on.
370-
// todo: check that the BIOSSettings setting is actually been issued.
371403
if r.checkForRequiredPowerStatus(server, metalv1alpha1.ServerOnPowerState) {
372404
err := r.patchServerMaintenancePowerState(ctx, log, biosSettings, metalv1alpha1.PowerOff)
373405
if err != nil {
@@ -382,7 +414,6 @@ func (r *BiosSettingsReconciler) applySettingUpdateStateTransition(
382414
return ctrl.Result{}, nil
383415
case metalv1alpha1.BIOSSettingUpdateWaitOnServerRebootPowerOn:
384416
// expected power state it to be on and initial state is to be off.
385-
// todo: check that the BIOSSettings setting is actually been issued.
386417
if r.checkForRequiredPowerStatus(server, metalv1alpha1.ServerOffPowerState) {
387418
err := r.patchServerMaintenancePowerState(ctx, log, biosSettings, metalv1alpha1.PowerOn)
388419
if err != nil {
@@ -408,6 +439,7 @@ func (r *BiosSettingsReconciler) applySettingUpdateStateTransition(
408439
err := r.updateBiosSettingsStatus(ctx, log, biosSettings, metalv1alpha1.BIOSSettingsStateApplied)
409440
return ctrl.Result{}, err
410441
}
442+
// todo: can take some time to setting to take place. might need to fail after certain time.
411443
log.V(1).Info("Reconciled biosSettings at wait for verification")
412444
return ctrl.Result{}, fmt.Errorf("waiting on the BIOS setting to take place")
413445
}
@@ -454,6 +486,42 @@ func (r *BiosSettingsReconciler) handleFailedState(
454486
return ctrl.Result{}, nil
455487
}
456488

489+
func (r *BiosSettingsReconciler) checkforPendingSettingsOnBIOS(
490+
ctx context.Context,
491+
log logr.Logger,
492+
server *metalv1alpha1.Server,
493+
settingsDiff redfish.SettingsAttributes,
494+
) (pendingSettingPresent bool, pendingSettingsDiff redfish.SettingsAttributes, err error) {
495+
bmcClient, err := bmcutils.GetBMCClientForServer(ctx, r.Client, server, r.Insecure, r.BMCOptions)
496+
if err != nil {
497+
return pendingSettingPresent, pendingSettingsDiff, fmt.Errorf("failed to create BMC client: %w", err)
498+
}
499+
defer bmcClient.Logout()
500+
501+
pendingSettingsDiff, err = bmcClient.GetPendingAttributeValues(ctx, server.Spec.SystemUUID)
502+
if err != nil {
503+
return pendingSettingPresent, pendingSettingsDiff, err
504+
}
505+
pendingSettingPresent = len(pendingSettingsDiff) > 0
506+
507+
// if settingsDiff is provided find the difference between settingsDiff and pending
508+
if len(settingsDiff) > 0 {
509+
log.V(1).Info("checking for the difference in the pending settings than that of required")
510+
if !pendingSettingPresent {
511+
return pendingSettingPresent, settingsDiff, nil
512+
}
513+
unknownpendingSettings := make(redfish.SettingsAttributes, len(settingsDiff))
514+
for name, value := range settingsDiff {
515+
if pendingValue, ok := pendingSettingsDiff[name]; ok && value != pendingValue {
516+
unknownpendingSettings[name] = pendingValue
517+
}
518+
}
519+
return pendingSettingPresent, unknownpendingSettings, nil
520+
}
521+
522+
return pendingSettingPresent, pendingSettingsDiff, nil
523+
}
524+
457525
func (r *BiosSettingsReconciler) getBIOSVersionAndSettingDifference(
458526
ctx context.Context,
459527
log logr.Logger,

0 commit comments

Comments
 (0)