Skip to content

Commit a2b4532

Browse files
committed
baremetal: add API to set maintenance and maintenance reason
For very historical reasons, Ironic requires a special API to set them. While the maintenance itself can be set directly (for even more historical reasons), the reason cannot.
1 parent 614ab7b commit a2b4532

File tree

6 files changed

+133
-0
lines changed

6 files changed

+133
-0
lines changed

acceptance/openstack/baremetal/v1/nodes_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,38 @@ func TestNodesUpdate(t *testing.T) {
6868
th.AssertEquals(t, updated.Maintenance, true)
6969
}
7070

71+
func TestNodesMaintenance(t *testing.T) {
72+
clients.RequireLong(t)
73+
74+
client, err := clients.NewBareMetalV1Client()
75+
th.AssertNoErr(t, err)
76+
client.Microversion = "1.38"
77+
78+
node, err := CreateNode(t, client)
79+
th.AssertNoErr(t, err)
80+
defer DeleteNode(t, client, node)
81+
82+
err = nodes.SetMaintenance(client, node.UUID, nodes.MaintenanceOpts{
83+
Reason: "I'm tired",
84+
}).ExtractErr()
85+
th.AssertNoErr(t, err)
86+
87+
updated, err := nodes.Get(client, node.UUID).Extract()
88+
th.AssertNoErr(t, err)
89+
90+
th.AssertEquals(t, updated.Maintenance, true)
91+
th.AssertEquals(t, updated.MaintenanceReason, "I'm tired")
92+
93+
err = nodes.UnsetMaintenance(client, node.UUID).ExtractErr()
94+
th.AssertNoErr(t, err)
95+
96+
updated, err = nodes.Get(client, node.UUID).Extract()
97+
th.AssertNoErr(t, err)
98+
99+
th.AssertEquals(t, updated.Maintenance, false)
100+
th.AssertEquals(t, updated.MaintenanceReason, "")
101+
}
102+
71103
func TestNodesRAIDConfig(t *testing.T) {
72104
clients.SkipReleasesBelow(t, "stable/ussuri")
73105
clients.RequireLong(t)

openstack/baremetal/v1/nodes/requests.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -835,3 +835,47 @@ func CreateSubscription(client *gophercloud.ServiceClient, id string, method Cal
835835
_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
836836
return r
837837
}
838+
839+
// MaintenanceOpts for a request to set the node's maintenance mode.
840+
type MaintenanceOpts struct {
841+
Reason string `json:"reason,omitempty"`
842+
}
843+
844+
// MaintenanceOptsBuilder allows extensions to add additional parameters to the SetMaintenance request.
845+
type MaintenanceOptsBuilder interface {
846+
ToMaintenanceMap() (map[string]interface{}, error)
847+
}
848+
849+
// ToMaintenanceMap assembles a request body based on the contents of a MaintenanceOpts.
850+
func (opts MaintenanceOpts) ToMaintenanceMap() (map[string]interface{}, error) {
851+
body, err := gophercloud.BuildRequestBody(opts, "")
852+
if err != nil {
853+
return nil, err
854+
}
855+
856+
return body, nil
857+
}
858+
859+
// Request to set the Node's maintenance mode.
860+
func SetMaintenance(client *gophercloud.ServiceClient, id string, opts MaintenanceOptsBuilder) (r SetMaintenanceResult) {
861+
reqBody, err := opts.ToMaintenanceMap()
862+
if err != nil {
863+
r.Err = err
864+
return
865+
}
866+
867+
resp, err := client.Put(maintenanceURL(client, id), reqBody, nil, &gophercloud.RequestOpts{
868+
OkCodes: []int{202},
869+
})
870+
_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
871+
return
872+
}
873+
874+
// Request to unset the Node's maintenance mode.
875+
func UnsetMaintenance(client *gophercloud.ServiceClient, id string) (r SetMaintenanceResult) {
876+
resp, err := client.Delete(maintenanceURL(client, id), &gophercloud.RequestOpts{
877+
OkCodes: []int{202},
878+
})
879+
_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
880+
return
881+
}

openstack/baremetal/v1/nodes/results.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,3 +501,9 @@ type SubscriptionVendorPassthru struct {
501501
EventTypes []string `json:"EventTypes"`
502502
Protocol string `json:"Protocol"`
503503
}
504+
505+
// SetMaintenanceResult is the response from a SetMaintenance operation. Call its ExtractErr
506+
// method to determine if the call succeeded or failed.
507+
type SetMaintenanceResult struct {
508+
gophercloud.ErrResult
509+
}

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -806,6 +806,12 @@ const NodeCreateSubscriptionVendorPassthruRequiredParametersBody = `
806806
}
807807
`
808808

809+
const NodeSetMaintenanceBody = `
810+
{
811+
"reason": "I'm tired"
812+
}
813+
`
814+
809815
var (
810816
NodeFoo = nodes.Node{
811817
UUID: "d2630783-6ec8-4836-b556-ab427c4b581e",
@@ -1524,3 +1530,22 @@ func HandleDeleteSubscriptionVendorPassthruSuccessfully(t *testing.T) {
15241530
w.WriteHeader(http.StatusNoContent)
15251531
})
15261532
}
1533+
1534+
func HandleSetNodeMaintenanceSuccessfully(t *testing.T) {
1535+
th.Mux.HandleFunc("/nodes/1234asdf/maintenance", func(w http.ResponseWriter, r *http.Request) {
1536+
th.TestMethod(t, r, "PUT")
1537+
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
1538+
th.TestJSONRequest(t, r, NodeSetMaintenanceBody)
1539+
1540+
w.WriteHeader(http.StatusAccepted)
1541+
})
1542+
}
1543+
1544+
func HandleUnsetNodeMaintenanceSuccessfully(t *testing.T) {
1545+
th.Mux.HandleFunc("/nodes/1234asdf/maintenance", func(w http.ResponseWriter, r *http.Request) {
1546+
th.TestMethod(t, r, "DELETE")
1547+
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
1548+
1549+
w.WriteHeader(http.StatusAccepted)
1550+
})
1551+
}

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -689,3 +689,25 @@ func TestDeleteSubscription(t *testing.T) {
689689
err := nodes.DeleteSubscription(c, "1234asdf", method, deleteOpt).ExtractErr()
690690
th.AssertNoErr(t, err)
691691
}
692+
693+
func TestSetMaintenance(t *testing.T) {
694+
th.SetupHTTP()
695+
defer th.TeardownHTTP()
696+
HandleSetNodeMaintenanceSuccessfully(t)
697+
698+
c := client.ServiceClient()
699+
err := nodes.SetMaintenance(c, "1234asdf", nodes.MaintenanceOpts{
700+
Reason: "I'm tired",
701+
}).ExtractErr()
702+
th.AssertNoErr(t, err)
703+
}
704+
705+
func TestUnsetMaintenance(t *testing.T) {
706+
th.SetupHTTP()
707+
defer th.TeardownHTTP()
708+
HandleUnsetNodeMaintenanceSuccessfully(t)
709+
710+
c := client.ServiceClient()
711+
err := nodes.UnsetMaintenance(c, "1234asdf").ExtractErr()
712+
th.AssertNoErr(t, err)
713+
}

openstack/baremetal/v1/nodes/urls.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,7 @@ func vendorPassthruMethodsURL(client *gophercloud.ServiceClient, id string) stri
7373
func vendorPassthruCallURL(client *gophercloud.ServiceClient, id string) string {
7474
return client.ServiceURL("nodes", id, "vendor_passthru")
7575
}
76+
77+
func maintenanceURL(client *gophercloud.ServiceClient, id string) string {
78+
return client.ServiceURL("nodes", id, "maintenance")
79+
}

0 commit comments

Comments
 (0)