Skip to content

Commit

Permalink
Allow Firmware Updates via Servicing with HostUpdatePolicy
Browse files Browse the repository at this point in the history
This commit adds the support for firmware updates using
HostUpdatePolicy.

Signed-off-by: Iury Gregory Melo Ferreira <imelofer@redhat.com>
  • Loading branch information
iurygregory committed Nov 11, 2024
1 parent af93711 commit e5b02f9
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 20 deletions.
30 changes: 29 additions & 1 deletion controllers/metal3.io/baremetalhost_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -1373,6 +1373,8 @@ func (r *BareMetalHostReconciler) doServiceIfNeeded(prov provisioner.Provisioner

var fwDirty bool
var hfsDirty bool
var hfcDirty bool
var hfc *metal3api.HostFirmwareComponents
var liveFirmwareSettingsAllowed bool

if hup != nil {
Expand All @@ -1396,9 +1398,17 @@ func (r *BareMetalHostReconciler) doServiceIfNeeded(prov provisioner.Provisioner
servicingData.ActualFirmwareSettings = hfs.Status.Settings
servicingData.TargetFirmwareSettings = hfs.Spec.Settings
}

hfcDirty, hfc, err = r.getHostFirmwareComponents(info)
if err != nil {
return actionError{fmt.Errorf("could not determine firmware components: %w", err)}
}
if hfcDirty {
servicingData.TargetFirmwareComponents = hfc.Spec.Updates
}
}

hasChanges := fwDirty || hfsDirty
hasChanges := fwDirty || hfsDirty || hfcDirty

// Even if settings are clean, we need to check the result of the current servicing.
if !hasChanges && info.host.Status.OperationalStatus != metal3api.OperationalStatusServicing && info.host.Status.ErrorType != metal3api.ServicingError {
Expand All @@ -1422,6 +1432,9 @@ func (r *BareMetalHostReconciler) doServiceIfNeeded(prov provisioner.Provisioner
}
if provResult.ErrorMessage != "" {
info.host.Status.Provisioning.Firmware = nil
if hfcDirty {
hfc.Status.Updates = nil
}
result = recordActionFailure(info, metal3api.ServicingError, provResult.ErrorMessage)
return result
}
Expand All @@ -1433,6 +1446,21 @@ func (r *BareMetalHostReconciler) doServiceIfNeeded(prov provisioner.Provisioner
dirty = true
}

if hfcDirty && started {
hfcStillDirty, err := r.saveHostFirmwareComponents(prov, info, hfc)
if err != nil {
return actionError{errors.Wrap(err, "could not save the host firmware components")}
}

if hfcStillDirty {
info.log.Info("going to update the host firmware components")
if err := r.Status().Update(info.ctx, hfc); err != nil {
return actionError{errors.Wrap(err, "failed to update hostfirmwarecomponents status")}
}
}
dirty = true
}

resultAction := actionContinue{delay: provResult.RequeueAfter}
if dirty {
return actionUpdate{resultAction}
Expand Down
26 changes: 13 additions & 13 deletions pkg/provisioner/ironic/ironic.go
Original file line number Diff line number Diff line change
Expand Up @@ -1215,6 +1215,18 @@ func (p *ironicProvisioner) getNewFirmwareSettings(actualFirmwareSettings metal3
return newSettings
}

// getFirmwareComponentsUpdates extract the updates in a format that ironic accepts [{"component":"...", "url":"..."}, {"component":"...","url":".."}].
func (p *ironicProvisioner) getFirmwareComponentsUpdates(targetFirmwareComponents []metal3api.FirmwareUpdate) (newUpdates []map[string]string) {
for _, update := range targetFirmwareComponents {
newComponentUpdate := map[string]string{
"component": update.Component,
"url": update.URL,
}
newUpdates = append(newUpdates, newComponentUpdate)
}
return newUpdates
}

func (p *ironicProvisioner) buildManualCleaningSteps(bmcAccess bmc.AccessDetails, data provisioner.PrepareData) (cleanSteps []nodes.CleanStep, err error) {
// Build raid clean steps
raidCleanSteps, err := BuildRAIDCleanSteps(bmcAccess.RAIDInterface(), data.TargetRAIDConfig, data.ActualRAIDConfig)
Expand Down Expand Up @@ -1249,19 +1261,7 @@ func (p *ironicProvisioner) buildManualCleaningSteps(bmcAccess bmc.AccessDetails
)
}

// extract to generate the updates that will trigger a clean step
// the format we send to ironic is:
// [{"component":"...", "url":"..."}, {"component":"...","url":".."}]
var newUpdates []map[string]string
if data.TargetFirmwareComponents != nil {
for _, update := range data.TargetFirmwareComponents {
newComponentUpdate := map[string]string{
"component": update.Component,
"url": update.URL,
}
newUpdates = append(newUpdates, newComponentUpdate)
}
}
newUpdates := p.getFirmwareComponentsUpdates(data.TargetFirmwareComponents)

if len(newUpdates) != 0 {
p.log.Info("Applying Firmware Update clean steps", "settings", newUpdates)
Expand Down
17 changes: 15 additions & 2 deletions pkg/provisioner/ironic/servicing.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,22 @@ func (p *ironicProvisioner) buildServiceSteps(bmcAccess bmc.AccessDetails, data
)
}

// TODO: Add service steps for firmware updates
newUpdates := p.getFirmwareComponentsUpdates(data.TargetFirmwareComponents)
if len(newUpdates) != 0 {
p.log.Info("Applying Firmware Update clean steps", "settings", newUpdates)
serviceSteps = append(
serviceSteps,
nodes.ServiceStep{
Interface: nodes.InterfaceFirmware,
Step: "update",
Args: map[string]interface{}{
"settings": newUpdates,
},
},
)
}

return
return serviceSteps, nil
}

func (p *ironicProvisioner) startServicing(bmcAccess bmc.AccessDetails, ironicNode *nodes.Node, data provisioner.ServicingData) (success bool, result provisioner.Result, err error) {
Expand Down
8 changes: 4 additions & 4 deletions pkg/provisioner/provisioner.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,10 @@ type PrepareData struct {
}

type ServicingData struct {
FirmwareConfig *metal3api.FirmwareConfig
TargetFirmwareSettings metal3api.DesiredSettingsMap
ActualFirmwareSettings metal3api.SettingsMap
// TargetFirmwareComponents []metal3api.FirmwareUpdate
FirmwareConfig *metal3api.FirmwareConfig
TargetFirmwareSettings metal3api.DesiredSettingsMap
ActualFirmwareSettings metal3api.SettingsMap
TargetFirmwareComponents []metal3api.FirmwareUpdate
}

type ProvisionData struct {
Expand Down

0 comments on commit e5b02f9

Please sign in to comment.