@@ -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
1620type DellIdracManager struct {
17- BMC * redfish.Manager
21+ BMC * redfish.Manager
22+ Service * gofish.Service
1823}
1924
2025type 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'.\n Possible settings %v" ,
193+ errs ,
194+ maps .Keys (filteredAttr ),
195+ )
196+ }
197+
198+ return result , nil
84199}
85200
86201func (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