Skip to content

Commit 31c2bac

Browse files
Update design to accomodate difference vedor variations
1 parent 6390b3f commit 31c2bac

File tree

6 files changed

+290
-228
lines changed

6 files changed

+290
-228
lines changed

bmc/bmc.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"encoding/json"
99
"fmt"
1010

11+
"github.com/stmcginnis/gofish"
1112
"github.com/stmcginnis/gofish/common"
1213
"github.com/stmcginnis/gofish/redfish"
1314
"k8s.io/apimachinery/pkg/api/resource"
@@ -59,7 +60,7 @@ type BMC interface {
5960

6061
CheckBiosAttributes(attrs redfish.SettingsAttributes) (reset bool, err error)
6162

62-
CheckBMCAttributes(attrs redfish.SettingsAttributes) (reset bool, err error)
63+
CheckBMCAttributes(UUID string, attrs redfish.SettingsAttributes) (reset bool, err error)
6364

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

@@ -93,7 +94,9 @@ const (
9394
)
9495

9596
type OEMManagerInterface interface {
96-
GetOEMBMCSettingAttribute() ([]oem.DellAttributes, error)
97+
GetOEMBMCSettingAttribute(attributes []string) (redfish.SettingsAttributes, error)
98+
GetBMCPendingAttributeValues() (redfish.SettingsAttributes, error)
99+
CheckBMCAttributes(attributes redfish.SettingsAttributes) (bool, error)
97100
GetObjFromUri(uri string, respObj any) ([]string, error)
98101
UpdateBMCAttributesApplyAt(attrs redfish.SettingsAttributes, applyTime common.ApplyTime) error
99102
}
@@ -268,12 +271,13 @@ type OEMManager struct {
268271
OEMManagerInterface
269272
}
270273

271-
func NewOEMManager(ooem *redfish.Manager) (*OEMManager, error) {
274+
func NewOEMManager(ooem *redfish.Manager, service *gofish.Service) (*OEMManager, error) {
272275
switch ooem.Manufacturer {
273276
case string(DellServers):
274277
return &OEMManager{
275278
OEMManagerInterface: &oem.DellIdracManager{
276-
BMC: ooem,
279+
BMC: ooem,
280+
Service: service,
277281
}}, nil
278282
default:
279283
return &OEMManager{}, fmt.Errorf("unsupported manufacturer: %v", ooem.Manufacturer)

bmc/common/helpers.go

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package common
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
7+
"github.com/stmcginnis/gofish/redfish"
8+
)
9+
10+
// todo: merge with checkBiosAttribues after #298
11+
func CheckAttribues(
12+
attrs redfish.SettingsAttributes,
13+
filtered map[string]redfish.Attribute,
14+
) (reset bool, err error) {
15+
reset = false
16+
var errs []error
17+
//TODO: add more types like maps and Enumerations
18+
for name, value := range attrs {
19+
entryAttribute, ok := filtered[name]
20+
if !ok {
21+
errs = append(errs, fmt.Errorf("attribute %s not found or immutable/hidden", name))
22+
continue
23+
}
24+
if entryAttribute.ResetRequired {
25+
reset = true
26+
}
27+
switch entryAttribute.Type {
28+
case redfish.IntegerAttributeType:
29+
if _, ok := value.(int); !ok {
30+
errs = append(
31+
errs,
32+
fmt.Errorf(
33+
"attribute '%s's' value '%v' has wrong type. needed '%s' for '%v'",
34+
name,
35+
value,
36+
entryAttribute.Type,
37+
entryAttribute,
38+
))
39+
}
40+
case redfish.StringAttributeType:
41+
if _, ok := value.(string); !ok {
42+
errs = append(
43+
errs,
44+
fmt.Errorf(
45+
"attribute '%s's' value '%v' has wrong type. needed '%s' for '%v'",
46+
name,
47+
value,
48+
entryAttribute.Type,
49+
entryAttribute,
50+
))
51+
}
52+
case redfish.EnumerationAttributeType:
53+
if _, ok := value.(string); !ok {
54+
errs = append(
55+
errs,
56+
fmt.Errorf(
57+
"attribute '%s's' value '%v' has wrong type. needed '%s' for '%v'",
58+
name,
59+
value,
60+
entryAttribute.Type,
61+
entryAttribute,
62+
))
63+
break
64+
}
65+
var validEnum bool
66+
for _, attrValue := range entryAttribute.Value {
67+
if attrValue.ValueName == value.(string) {
68+
validEnum = true
69+
break
70+
}
71+
}
72+
if !validEnum {
73+
errs = append(errs, fmt.Errorf("attribute %s value is unknown. needed %v", name, entryAttribute.Value))
74+
}
75+
default:
76+
errs = append(
77+
errs,
78+
fmt.Errorf(
79+
"attribute '%s's' value '%v' has wrong type. needed '%s' for '%v'",
80+
name,
81+
value,
82+
entryAttribute.Type,
83+
entryAttribute,
84+
))
85+
}
86+
}
87+
return reset, errors.Join(errs...)
88+
}

bmc/oem/dell.go

Lines changed: 164 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,18 @@ import (
88
"errors"
99
"fmt"
1010
"io"
11+
"maps"
12+
"strings"
1113

14+
helpers "github.com/ironcore-dev/metal-operator/bmc/common"
15+
"github.com/stmcginnis/gofish"
1216
"github.com/stmcginnis/gofish/common"
1317
"github.com/stmcginnis/gofish/redfish"
1418
)
1519

1620
type DellIdracManager struct {
17-
BMC *redfish.Manager
21+
BMC *redfish.Manager
22+
Service *gofish.Service
1823
}
1924

2025
type DellAttributes struct {
@@ -51,7 +56,7 @@ func (d *DellIdracManager) GetObjFromUri(
5156
return resp.Header["Etag"], nil
5257
}
5358

54-
func (d *DellIdracManager) GetOEMBMCSettingAttribute() ([]DellAttributes, error) {
59+
func (d *DellIdracManager) getCurrentBMCSettingAttribute() ([]DellAttributes, error) {
5560

5661
type temp struct {
5762
DellOEMData DellManagerLinksOEM `json:"Dell"`
@@ -63,32 +68,142 @@ func (d *DellIdracManager) GetOEMBMCSettingAttribute() ([]DellAttributes, error)
6368
return nil, err
6469
}
6570

71+
// get all current attributes values for dell manager
6672
BMCDellAttributes := []DellAttributes{}
67-
err = nil
73+
var errs []error
6874
for _, data := range tempData.DellOEMData.DellLinkAttributes {
6975
BMCDellAttribute := &DellAttributes{}
70-
eTag, errAttr := d.GetObjFromUri(data.String(), BMCDellAttribute)
71-
if errAttr != nil {
72-
err = errors.Join(err, errAttr)
76+
eTag, err := d.GetObjFromUri(data.String(), BMCDellAttribute)
77+
if err != nil {
78+
errs = append(errs, err)
7379
}
7480
if eTag != nil {
7581
BMCDellAttribute.Etag = eTag[0]
7682
}
7783
BMCDellAttributes = append(BMCDellAttributes, *BMCDellAttribute)
7884
}
79-
if err != nil {
80-
return BMCDellAttributes, err
85+
if len(errs) > 0 {
86+
return nil, errors.Join(errs...)
8187
}
8288

8389
return BMCDellAttributes, nil
90+
91+
}
92+
93+
func (d *DellIdracManager) getFilteredBMCRegistryAttributes(
94+
readOnly bool,
95+
immutable bool,
96+
) (
97+
filtered map[string]redfish.Attribute,
98+
err error,
99+
) {
100+
// from the registriesAttribure, get the attributes which can be changed.
101+
registries, err := d.Service.Registries()
102+
if err != nil {
103+
return nil, err
104+
}
105+
bmcRegistryAttribute := &redfish.AttributeRegistry{}
106+
for _, registry := range registries {
107+
if strings.Contains(registry.ID, "ManagerAttributeRegistry") {
108+
_, err = d.GetObjFromUri(registry.Location[0].URI, bmcRegistryAttribute)
109+
if err != nil {
110+
return nil, err
111+
}
112+
break
113+
}
114+
}
115+
// filter out immutable, readonly and hidden attributes
116+
filteredAttr := make(map[string]redfish.Attribute)
117+
for _, entry := range bmcRegistryAttribute.RegistryEntries.Attributes {
118+
if entry.Immutable == immutable && entry.ReadOnly == readOnly && !entry.Hidden {
119+
filteredAttr[entry.AttributeName] = entry
120+
}
121+
}
122+
123+
return filteredAttr, nil
124+
}
125+
126+
func (d *DellIdracManager) GetOEMBMCSettingAttribute(
127+
attributes []string,
128+
) (redfish.SettingsAttributes, error) {
129+
130+
BMCDellAttributes, err := d.getCurrentBMCSettingAttribute()
131+
if err != nil {
132+
return nil, err
133+
}
134+
135+
// merge al the current attributes to single map, to help fetch it later
136+
var mergedBMCAttributes = make(redfish.SettingsAttributes)
137+
for _, BMCattributeValue := range BMCDellAttributes {
138+
for k, v := range BMCattributeValue.Attributes {
139+
if _, ok := mergedBMCAttributes[k]; !ok {
140+
mergedBMCAttributes[k] = v
141+
} else {
142+
return nil, fmt.Errorf("duplicate attributes in BMC settings are not supported duplicate key %v. in attribute %v", k, BMCDellAttributes)
143+
}
144+
}
145+
}
146+
147+
filteredAttr, err := d.getFilteredBMCRegistryAttributes(false, false)
148+
if err != nil {
149+
return nil, err
150+
}
151+
152+
if len(filteredAttr) == 0 {
153+
return nil, fmt.Errorf("'ManagerAttributeRegistry' not found")
154+
}
155+
156+
// from the gives attributes to change, find the ones which can be changed and get current value for them
157+
result := make(redfish.SettingsAttributes, len(attributes))
158+
var errs []error
159+
for _, name := range attributes {
160+
if entry, ok := filteredAttr[name]; ok {
161+
// enumerations current setting comtains display name.
162+
// need to be checked with the actual value rather than the display value
163+
// as the settings provided will have actual values.
164+
// replace display values with actual values
165+
if strings.ToLower(string(entry.Type)) == string(redfish.EnumerationAttributeType) {
166+
for _, attrValue := range entry.Value {
167+
if attrValue.ValueDisplayName == mergedBMCAttributes[name] {
168+
result[name] = attrValue.ValueName
169+
break
170+
}
171+
}
172+
if _, ok := result[name]; !ok {
173+
errs = append(
174+
errs,
175+
fmt.Errorf(
176+
"current setting '%v' for key '%v' not found in possible values for it (%v)",
177+
mergedBMCAttributes[name],
178+
name,
179+
entry.Value,
180+
))
181+
}
182+
} else {
183+
result[name] = mergedBMCAttributes[name]
184+
}
185+
} else {
186+
// possible error in settings key
187+
errs = append(errs, fmt.Errorf("setting key '%v' not found in possible settings", name))
188+
}
189+
}
190+
if len(errs) > 0 {
191+
return result, fmt.Errorf(
192+
"some errors found in the settings '%v'.\nPossible settings %v",
193+
errs,
194+
maps.Keys(filteredAttr),
195+
)
196+
}
197+
198+
return result, nil
84199
}
85200

86201
func (d *DellIdracManager) UpdateBMCAttributesApplyAt(
87202
attrs redfish.SettingsAttributes,
88203
applyTime common.ApplyTime,
89204
) error {
90205

91-
BMCattributeValues, err := d.GetOEMBMCSettingAttribute()
206+
BMCattributeValues, err := d.getCurrentBMCSettingAttribute()
92207
if err != nil {
93208
return err
94209
}
@@ -160,6 +275,46 @@ func (d *DellIdracManager) UpdateBMCAttributesApplyAt(
160275
return nil
161276
}
162277

278+
func (d *DellIdracManager) GetBMCPendingAttributeValues() (redfish.SettingsAttributes, error) {
279+
280+
BMCattributeValues, err := d.getCurrentBMCSettingAttribute()
281+
if err != nil {
282+
return nil, err
283+
}
284+
285+
var mergedPendingBMCAttributes = make(redfish.SettingsAttributes)
286+
var tBMCSetting struct {
287+
Attributes redfish.SettingsAttributes `json:"Attributes"`
288+
}
289+
290+
for _, BMCattributeValue := range BMCattributeValues {
291+
_, err := d.GetObjFromUri(BMCattributeValue.Settings.SettingsObject.String(), &tBMCSetting)
292+
if err != nil {
293+
return nil, err
294+
}
295+
for k, v := range tBMCSetting.Attributes {
296+
if _, ok := mergedPendingBMCAttributes[k]; !ok {
297+
mergedPendingBMCAttributes[k] = v
298+
} else {
299+
return nil, fmt.Errorf("duplicate pending attributes in Idrac settings are not supported %v", k)
300+
}
301+
}
302+
}
303+
304+
return mergedPendingBMCAttributes, nil
305+
}
306+
307+
func (d *DellIdracManager) CheckBMCAttributes(attributes redfish.SettingsAttributes) (bool, error) {
308+
filteredAttr, err := d.getFilteredBMCRegistryAttributes(false, false)
309+
if err != nil {
310+
return false, err
311+
}
312+
if len(filteredAttr) == 0 {
313+
return false, nil
314+
}
315+
return helpers.CheckAttribues(attributes, filteredAttr)
316+
}
317+
163318
// "Dell": {
164319
// "@odata.type": "#DellOem.v1_3_0.DellOemLinks",
165320
// "DellAttributes": [

0 commit comments

Comments
 (0)