Skip to content

Commit 6f0db54

Browse files
Merge pull request #1749 from metal3-io-bot/cherry-pick-1695-to-release-0.6
🐛 Fix Status logic for HostFirmwareComponents
2 parents 3086599 + fa57241 commit 6f0db54

File tree

7 files changed

+35
-60
lines changed

7 files changed

+35
-60
lines changed

apis/metal3.io/v1alpha1/hostfirmwarecomponents_types.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,11 @@ type HostFirmwareComponentsSpec struct {
5656
type HostFirmwareComponentsStatus struct {
5757
// Updates is the list of all firmware components that should be updated
5858
// they are specified via name and url fields.
59+
// +optional
5960
Updates []FirmwareUpdate `json:"updates"`
6061

6162
// Components is the list of all available firmware components and their information.
62-
Components []FirmwareComponentStatus `json:"components"`
63+
Components []FirmwareComponentStatus `json:"components,omitempty"`
6364

6465
// Time that the status was last updated
6566
// +optional

config/base/crds/bases/metal3.io_hostfirmwarecomponents.yaml

-3
Original file line numberDiff line numberDiff line change
@@ -170,9 +170,6 @@ spec:
170170
- url
171171
type: object
172172
type: array
173-
required:
174-
- components
175-
- updates
176173
type: object
177174
type: object
178175
served: true

config/render/capm3.yaml

-3
Original file line numberDiff line numberDiff line change
@@ -1770,9 +1770,6 @@ spec:
17701770
- url
17711771
type: object
17721772
type: array
1773-
required:
1774-
- components
1775-
- updates
17761773
type: object
17771774
type: object
17781775
served: true

controllers/metal3.io/hostfirmwarecomponents_controller.go

+16-38
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package controllers
1818

1919
import (
2020
"context"
21+
"errors"
2122
"fmt"
2223
"reflect"
2324

@@ -151,23 +152,21 @@ func (r *HostFirmwareComponentsReconciler) Reconcile(ctx context.Context, req ct
151152
return ctrl.Result{Requeue: true, RequeueAfter: provisionerRetryDelay}, nil
152153
}
153154

154-
newStatus, err := r.updateHostFirmware(info)
155-
if err != nil {
156-
return ctrl.Result{}, fmt.Errorf("could not update hostfirmwarecomponents: %w", err)
157-
}
158-
155+
info.log.Info("retrieving firmware components and saving to resource", "Node", bmh.Status.Provisioning.ID)
159156
// Check ironic for the components information if possible
160157
components, err := prov.GetFirmwareComponents()
161-
info.log.Info("retrieving firmware components and saving to resource", "Node", bmh.Status.Provisioning.ID)
162158

163159
if err != nil {
164-
reqLogger.Error(err, "provisioner returns error", "RequeueAfter", provisionerRetryDelay)
165-
setUpdatesCondition(info.hfc.GetGeneration(), &newStatus, info, metal3api.HostFirmwareComponentsValid, metav1.ConditionFalse, reasonInvalidComponent, err.Error())
160+
if errors.Is(err, provisioner.ErrFirmwareUpdateUnsupported) {
161+
return ctrl.Result{Requeue: false}, err
162+
}
163+
reqLogger.Info("provisioner returns error", "Error", err.Error(), "RequeueAfter", provisionerRetryDelay)
166164
return ctrl.Result{Requeue: true, RequeueAfter: provisionerRetryDelay}, err
167165
}
168166

169-
if err = r.updateHostFirmwareComponents(newStatus, components, info); err != nil {
170-
return ctrl.Result{Requeue: false}, err
167+
if err = r.updateHostFirmware(info, components); err != nil {
168+
info.log.Info("updateHostFirmware returned error")
169+
return ctrl.Result{}, fmt.Errorf("could not update hostfirmwarecomponents: %w", err)
171170
}
172171

173172
for _, e := range info.events {
@@ -181,14 +180,19 @@ func (r *HostFirmwareComponentsReconciler) Reconcile(ctx context.Context, req ct
181180
}
182181

183182
// Update the HostFirmwareComponents resource using the components from provisioner.
184-
func (r *HostFirmwareComponentsReconciler) updateHostFirmware(info *rhfcInfo) (newStatus metal3api.HostFirmwareComponentsStatus, err error) {
183+
func (r *HostFirmwareComponentsReconciler) updateHostFirmware(info *rhfcInfo, components []metal3api.FirmwareComponentStatus) (err error) {
185184
dirty := false
186-
185+
var newStatus metal3api.HostFirmwareComponentsStatus
187186
// change the Updates in Status
188187
newStatus.Updates = info.hfc.Spec.Updates
188+
// change the Components in Status
189+
newStatus.Components = components
189190

190191
// Check if the updates in the Spec are different than Status
191192
updatesMismatch := !reflect.DeepEqual(info.hfc.Status.Updates, info.hfc.Spec.Updates)
193+
if len(info.hfc.Spec.Updates) == 0 && len(info.hfc.Status.Updates) == 0 {
194+
updatesMismatch = false
195+
}
192196

193197
reason := reasonValidComponent
194198
generation := info.hfc.GetGeneration()
@@ -222,32 +226,6 @@ func (r *HostFirmwareComponentsReconciler) updateHostFirmware(info *rhfcInfo) (n
222226
info.log.Info("Status for HostFirmwareComponents changed")
223227
info.hfc.Status = *newStatus.DeepCopy()
224228

225-
t := metav1.Now()
226-
info.hfc.Status.LastUpdated = &t
227-
return newStatus, r.Status().Update(info.ctx, info.hfc)
228-
}
229-
return newStatus, nil
230-
}
231-
232-
// Update the HostFirmwareComponents resource using the components from provisioner.
233-
func (r *HostFirmwareComponentsReconciler) updateHostFirmwareComponents(newStatus metal3api.HostFirmwareComponentsStatus, components []metal3api.FirmwareComponentStatus, info *rhfcInfo) (err error) {
234-
dirty := false
235-
// change the Components in Status
236-
newStatus.Components = components
237-
// Check if the components information we retrieved is different from the one in Status
238-
componentsInfoMismatch := !reflect.DeepEqual(components, info.hfc.Status.Components)
239-
reason := reasonValidComponent
240-
generation := info.hfc.GetGeneration()
241-
// Log the components we have
242-
info.log.Info("firmware components for node", "components", components, "bmh", info.bmh.Name)
243-
if componentsInfoMismatch {
244-
setUpdatesCondition(generation, &newStatus, info, metal3api.HostFirmwareComponentsChangeDetected, metav1.ConditionTrue, reason, "")
245-
dirty = true
246-
}
247-
if dirty {
248-
info.log.Info("Components Status for HostFirmwareComponents changed")
249-
info.hfc.Status = *newStatus.DeepCopy()
250-
251229
t := metav1.Now()
252230
info.hfc.Status.LastUpdated = &t
253231
return r.Status().Update(info.ctx, info.hfc)

controllers/metal3.io/hostfirmwarecomponents_test.go

+1-4
Original file line numberDiff line numberDiff line change
@@ -425,12 +425,9 @@ func TestStoreHostFirmwareComponents(t *testing.T) {
425425
bmh: bmh,
426426
}
427427

428-
currentStatus, err := r.updateHostFirmware(info)
429-
assert.NoError(t, err)
430-
431428
components, err := prov.GetFirmwareComponents()
432429
assert.NoError(t, err)
433-
err = r.updateHostFirmwareComponents(currentStatus, components, info)
430+
err = r.updateHostFirmware(info, components)
434431
assert.NoError(t, err)
435432

436433
// Check that resources get created or updated

pkg/provisioner/ironic/ironic.go

+13-11
Original file line numberDiff line numberDiff line change
@@ -1162,21 +1162,20 @@ func (p *ironicProvisioner) GetFirmwareComponents() ([]metal3api.FirmwareCompone
11621162
if !p.availableFeatures.HasFirmwareUpdates() {
11631163
return nil, fmt.Errorf("current ironic version does not support firmware updates")
11641164
}
1165+
1166+
// Setting to 2 since we only support bmc and bios
1167+
componentsInfo := make([]metal3api.FirmwareComponentStatus, 0, 2)
1168+
1169+
if ironicNode.FirmwareInterface == "no-firmware" {
1170+
return componentsInfo, provisioner.ErrFirmwareUpdateUnsupported
1171+
}
11651172
// Get the components from Ironic via Gophercloud
11661173
componentList, componentListErr := nodes.ListFirmware(p.ctx, p.client, ironicNode.UUID).Extract()
11671174

1168-
if componentListErr != nil || len(componentList) == 0 {
1169-
bmcAccess, _ := p.bmcAccess()
1170-
if ironicNode.FirmwareInterface == "no-firmware" {
1171-
return nil, fmt.Errorf("driver %s does not support firmware updates", bmcAccess.Driver())
1172-
}
1173-
1175+
if componentListErr != nil {
11741176
return nil, fmt.Errorf("could not get firmware components for node %s: %w", ironicNode.UUID, componentListErr)
11751177
}
11761178

1177-
// Setting to 2 since we only support bmc and bios
1178-
componentsInfo := make([]metal3api.FirmwareComponentStatus, 0, 2)
1179-
11801179
// Iterate over the list of components to extract their information and update the list.
11811180
for _, fwc := range componentList {
11821181
if fwc.Component != "bios" && fwc.Component != "bmc" {
@@ -1188,9 +1187,12 @@ func (p *ironicProvisioner) GetFirmwareComponents() ([]metal3api.FirmwareCompone
11881187
InitialVersion: fwc.InitialVersion,
11891188
CurrentVersion: fwc.CurrentVersion,
11901189
LastVersionFlashed: fwc.LastVersionFlashed,
1191-
UpdatedAt: metav1.Time{
1190+
}
1191+
// Check if UpdatedAt is nil before adding it.
1192+
if fwc.UpdatedAt != nil {
1193+
component.UpdatedAt = metav1.Time{
11921194
Time: *fwc.UpdatedAt,
1193-
},
1195+
}
11941196
}
11951197
componentsInfo = append(componentsInfo, component)
11961198
p.log.Info("firmware component added for node", "component", fwc.Component, "node", ironicNode.UUID)

pkg/provisioner/provisioner.go

+3
Original file line numberDiff line numberDiff line change
@@ -231,3 +231,6 @@ var ErrNeedsRegistration = errors.New("host not registered")
231231
// ErrNeedsPreprovisioningImage is returned if a preprovisioning image is
232232
// required.
233233
var ErrNeedsPreprovisioningImage = errors.New("no suitable Preprovisioning image available")
234+
235+
// ErrFirmwareUpdateUnsupported is returned if the host can't execute firmware updates.
236+
var ErrFirmwareUpdateUnsupported = errors.New("host does not support Firmware Updates")

0 commit comments

Comments
 (0)