Skip to content

Commit 2590506

Browse files
committed
Add support for bios settings options to get additional fields
For #2166 A recent change to Ironic (https://review.opendev.org/c/openstack/ironic/+/786707) has added support for bios registry fields in the Ironic API. These can be retrieved using the `?detail=True` option.
1 parent 05c2cc8 commit 2590506

4 files changed

Lines changed: 242 additions & 3 deletions

File tree

openstack/baremetal/v1/nodes/requests.go

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -640,9 +640,46 @@ func SetRAIDConfig(client *gophercloud.ServiceClient, id string, raidConfigOptsB
640640
return
641641
}
642642

643+
// ListBIOSSettingsOptsBuilder allows extensions to add additional parameters to the
644+
// ListBIOSSettings request.
645+
type ListBIOSSettingsOptsBuilder interface {
646+
ToListBIOSSettingsOptsQuery() (string, error)
647+
}
648+
649+
// ListBIOSSettingsOpts defines query options that can be passed to ListBIOSettings
650+
type ListBIOSSettingsOpts struct {
651+
// Provide additional information for the BIOS Settings
652+
Detail bool `q:"detail"`
653+
654+
// One or more fields to be returned in the response.
655+
Fields []string `q:"fields"`
656+
}
657+
658+
// ToListBIOSSettingsOptsQuery formats a ListBIOSSettingsOpts into a query string
659+
func (opts ListBIOSSettingsOpts) ToListBIOSSettingsOptsQuery() (string, error) {
660+
if opts.Detail == true && len(opts.Fields) > 0 {
661+
return "", fmt.Errorf("cannot have both fields and detail options for BIOS settings")
662+
}
663+
664+
q, err := gophercloud.BuildQueryString(opts)
665+
return q.String(), err
666+
}
667+
643668
// Get the current BIOS Settings for the given Node.
644-
func ListBIOSSettings(client *gophercloud.ServiceClient, id string) (r ListBIOSSettingsResult) {
645-
resp, err := client.Get(biosListSettingsURL(client, id), &r.Body, &gophercloud.RequestOpts{
669+
// To use the opts requires microversion 1.74.
670+
func ListBIOSSettings(client *gophercloud.ServiceClient, id string, opts ListBIOSSettingsOptsBuilder) (r ListBIOSSettingsResult) {
671+
url := biosListSettingsURL(client, id)
672+
if opts != nil {
673+
674+
query, err := opts.ToListBIOSSettingsOptsQuery()
675+
if err != nil {
676+
r.Err = err
677+
return
678+
}
679+
url += query
680+
}
681+
682+
resp, err := client.Get(url, &r.Body, &gophercloud.RequestOpts{
646683
OkCodes: []int{200},
647684
})
648685
_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)

openstack/baremetal/v1/nodes/results.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,37 @@ type BIOSSetting struct {
354354

355355
// Value of the BIOS setting.
356356
Value string `json:"value"`
357+
358+
// The following fields are returned in microversion 1.74 or later
359+
// when using the `details` option
360+
361+
// The type of setting - Enumeration, String, Integer, or Boolean.
362+
AttributeType string `json:"attribute_type"`
363+
364+
// The allowable value for an Enumeration type setting.
365+
AllowableValues []string `json:"allowable_values"`
366+
367+
// The lowest value for an Integer type setting.
368+
LowerBound *int `json:"lower_bound"`
369+
370+
// The highest value for an Integer type setting.
371+
UpperBound *int `json:"upper_bound"`
372+
373+
// Minimum length for a String type setting.
374+
MinLength *int `json:"min_length"`
375+
376+
// Maximum length for a String type setting.
377+
MaxLength *int `json:"max_length"`
378+
379+
// Whether or not this setting is read only.
380+
ReadOnly *bool `json:"read_only"`
381+
382+
// Whether or not a reset is required after changing this setting.
383+
ResetRequired *bool `json:"reset_required"`
384+
385+
// Whether or not this setting's value is unique to this node, e.g.
386+
// a serial number.
387+
Unique *bool `json:"unique"`
357388
}
358389

359390
type SingleBIOSSetting struct {

openstack/baremetal/v1/nodes/testing/fixtures.go

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -622,6 +622,92 @@ const NodeBIOSSettingsBody = `
622622
]
623623
}
624624
`
625+
626+
const NodeDetailBIOSSettingsBody = `
627+
{
628+
"bios": [
629+
{
630+
"created_at": "2021-05-11T21:33:44+00:00",
631+
"updated_at": null,
632+
"name": "Proc1L2Cache",
633+
"value": "10x256 KB",
634+
"attribute_type": "String",
635+
"allowable_values": [],
636+
"lower_bound": null,
637+
"max_length": 16,
638+
"min_length": 0,
639+
"read_only": true,
640+
"reset_required": null,
641+
"unique": null,
642+
"upper_bound": null,
643+
"links": [
644+
{
645+
"href": "http://ironic.example.com:6385/v1/nodes/d26115bf-1296-4ca8-8c86-6f310d8ec375/bios/Proc1L2Cache",
646+
"rel": "self"
647+
},
648+
{
649+
"href": "http://ironic.example.com:6385/nodes/d26115bf-1296-4ca8-8c86-6f310d8ec375/bios/Proc1L2Cache",
650+
"rel": "bookmark"
651+
}
652+
]
653+
},
654+
{
655+
"created_at": "2021-05-11T21:33:44+00:00",
656+
"updated_at": null,
657+
"name": "Proc1NumCores",
658+
"value": "10",
659+
"attribute_type": "Integer",
660+
"allowable_values": [],
661+
"lower_bound": 0,
662+
"max_length": null,
663+
"min_length": null,
664+
"read_only": true,
665+
"reset_required": null,
666+
"unique": null,
667+
"upper_bound": 20,
668+
"links": [
669+
{
670+
"href": "http://ironic.example.com:6385/v1/nodes/d26115bf-1296-4ca8-8c86-6f310d8ec375/bios/Proc1NumCores",
671+
"rel": "self"
672+
},
673+
{
674+
"href": "http://ironic.example.com:6385/nodes/d26115bf-1296-4ca8-8c86-6f310d8ec375/bios/Proc1NumCores",
675+
"rel": "bookmark"
676+
}
677+
]
678+
},
679+
{
680+
"created_at": "2021-05-11T21:33:44+00:00",
681+
"updated_at": null,
682+
"name": "ProcVirtualization",
683+
"value": "Enabled",
684+
"attribute_type": "Enumeration",
685+
"allowable_values": [
686+
"Enabled",
687+
"Disabled"
688+
],
689+
"lower_bound": null,
690+
"max_length": null,
691+
"min_length": null,
692+
"read_only": false,
693+
"reset_required": null,
694+
"unique": null,
695+
"upper_bound": null,
696+
"links": [
697+
{
698+
"href": "http://ironic.example.com:6385/v1/nodes/d26115bf-1296-4ca8-8c86-6f310d8ec375/bios/ProcVirtualization",
699+
"rel": "self"
700+
},
701+
{
702+
"href": "http://ironic.example.com:6385/nodes/d26115bf-1296-4ca8-8c86-6f310d8ec375/bios/ProcVirtualization",
703+
"rel": "bookmark"
704+
}
705+
]
706+
}
707+
]
708+
}
709+
`
710+
625711
const NodeSingleBIOSSettingBody = `
626712
{
627713
"Setting": {
@@ -854,6 +940,55 @@ var (
854940
},
855941
}
856942

943+
iTrue = true
944+
iFalse = false
945+
minLength = 0
946+
maxLength = 16
947+
lowerBound = 0
948+
upperBound = 20
949+
950+
NodeDetailBIOSSettings = []nodes.BIOSSetting{
951+
{
952+
Name: "Proc1L2Cache",
953+
Value: "10x256 KB",
954+
AttributeType: "String",
955+
AllowableValues: []string{},
956+
LowerBound: nil,
957+
UpperBound: nil,
958+
MinLength: &minLength,
959+
MaxLength: &maxLength,
960+
ReadOnly: &iTrue,
961+
ResetRequired: nil,
962+
Unique: nil,
963+
},
964+
{
965+
Name: "Proc1NumCores",
966+
Value: "10",
967+
AttributeType: "Integer",
968+
AllowableValues: []string{},
969+
LowerBound: &lowerBound,
970+
UpperBound: &upperBound,
971+
MinLength: nil,
972+
MaxLength: nil,
973+
ReadOnly: &iTrue,
974+
ResetRequired: nil,
975+
Unique: nil,
976+
},
977+
{
978+
Name: "ProcVirtualization",
979+
Value: "Enabled",
980+
AttributeType: "Enumeration",
981+
AllowableValues: []string{"Enabled", "Disabled"},
982+
LowerBound: nil,
983+
UpperBound: nil,
984+
MinLength: nil,
985+
MaxLength: nil,
986+
ReadOnly: &iFalse,
987+
ResetRequired: nil,
988+
Unique: nil,
989+
},
990+
}
991+
857992
NodeSingleBIOSSetting = nodes.BIOSSetting{
858993
Name: "ProcVirtualization",
859994
Value: "Enabled",
@@ -1126,6 +1261,16 @@ func HandleListBIOSSettingsSuccessfully(t *testing.T) {
11261261
})
11271262
}
11281263

1264+
func HandleListDetailBIOSSettingsSuccessfully(t *testing.T) {
1265+
th.Mux.HandleFunc("/nodes/1234asdf/bios", func(w http.ResponseWriter, r *http.Request) {
1266+
th.TestMethod(t, r, "GET")
1267+
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
1268+
th.TestHeader(t, r, "Accept", "application/json")
1269+
1270+
fmt.Fprintf(w, NodeDetailBIOSSettingsBody)
1271+
})
1272+
}
1273+
11291274
func HandleGetBIOSSettingSuccessfully(t *testing.T) {
11301275
th.Mux.HandleFunc("/nodes/1234asdf/bios/ProcVirtualization", func(w http.ResponseWriter, r *http.Request) {
11311276
th.TestMethod(t, r, "GET")

openstack/baremetal/v1/nodes/testing/requests_test.go

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -552,11 +552,26 @@ func TestListBIOSSettings(t *testing.T) {
552552
HandleListBIOSSettingsSuccessfully(t)
553553

554554
c := client.ServiceClient()
555-
actual, err := nodes.ListBIOSSettings(c, "1234asdf").Extract()
555+
actual, err := nodes.ListBIOSSettings(c, "1234asdf", nil).Extract()
556556
th.AssertNoErr(t, err)
557557
th.CheckDeepEquals(t, NodeBIOSSettings, actual)
558558
}
559559

560+
func TestListDetailBIOSSettings(t *testing.T) {
561+
th.SetupHTTP()
562+
defer th.TeardownHTTP()
563+
HandleListDetailBIOSSettingsSuccessfully(t)
564+
565+
opts := nodes.ListBIOSSettingsOpts{
566+
Detail: true,
567+
}
568+
569+
c := client.ServiceClient()
570+
actual, err := nodes.ListBIOSSettings(c, "1234asdf", opts).Extract()
571+
th.AssertNoErr(t, err)
572+
th.CheckDeepEquals(t, NodeDetailBIOSSettings, actual)
573+
}
574+
560575
func TestGetBIOSSetting(t *testing.T) {
561576
th.SetupHTTP()
562577
defer th.TeardownHTTP()
@@ -567,3 +582,14 @@ func TestGetBIOSSetting(t *testing.T) {
567582
th.AssertNoErr(t, err)
568583
th.CheckDeepEquals(t, NodeSingleBIOSSetting, *actual)
569584
}
585+
586+
func TestListBIOSSettingsOpts(t *testing.T) {
587+
// Detail cannot take Fields
588+
opts := nodes.ListBIOSSettingsOpts{
589+
Detail: true,
590+
Fields: []string{"name", "value"},
591+
}
592+
593+
_, err := opts.ToListBIOSSettingsOptsQuery()
594+
th.AssertEquals(t, err.Error(), "cannot have both fields and detail options for BIOS settings")
595+
}

0 commit comments

Comments
 (0)