Skip to content

Commit 04234e2

Browse files
committed
Onboarding: Undo forceDown
An HA event on a node will cause the HA service to force down the node. This is apparently persisted, so when the node comes up again, it stays forced down, even though the service was deleted. Either way, we can only onboard a node if it isn't `forcedDown`, so we might as well ensure that. We need to duplicate the gophercloud code until v3 is released, as the bugfix is unfortunately a breaking api change. See: gophercloud/gophercloud#3531 In compliance with the Apache License, I kept the attribution and wrote down where the code came from and what has been changed.
1 parent 35477c9 commit 04234e2

2 files changed

Lines changed: 75 additions & 2 deletions

File tree

internal/controller/onboarding_controller.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,8 +199,14 @@ func (r *OnboardingController) initialOnboarding(ctx context.Context, hv *kvmv1.
199199
}
200200
}
201201

202-
if result := services.Update(ctx, r.computeClient, hv.Status.ServiceID,
203-
services.UpdateOpts{Status: services.ServiceEnabled}); result.Err != nil {
202+
// The service may be forced down previously due to an HA event,
203+
// so we need to ensure it not only enabled, but also not forced to be down.
204+
falseVal := false
205+
opts := openstack.UpdateServiceOpts{
206+
Status: services.ServiceEnabled,
207+
ForcedDown: &falseVal,
208+
}
209+
if result := openstack.UpdateService(ctx, r.computeClient, hv.Status.ServiceID, opts); result.Err != nil {
204210
return result.Err
205211
}
206212

internal/openstack/services.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
SPDX-FileCopyrightText: Copyright 2024 SAP SE or an SAP affiliate company and cobaltcore-dev contributors
3+
SPDX-FileCopyrightText: Copyright Gophercloud authors
4+
SPDX-License-Identifier: Apache-2.0
5+
6+
Licensed under the Apache License, Version 2.0 (the "License");
7+
you may not use this file except in compliance with the License.
8+
You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing, software
13+
distributed under the License is distributed on an "AS IS" BASIS,
14+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
See the License for the specific language governing permissions and
16+
limitations under the License.
17+
*/
18+
19+
/* Temporary workaround until gophercloud v3 has been released.
20+
* Functions and structs copied from:
21+
* https://github.com/gophercloud/gophercloud/tree/main/openstack/compute/v2/services
22+
* and renamed to contain "Service".
23+
*/
24+
25+
package openstack
26+
27+
import (
28+
"context"
29+
30+
"github.com/gophercloud/gophercloud/v2"
31+
"github.com/gophercloud/gophercloud/v2/openstack/compute/v2/services"
32+
)
33+
34+
type UpdateServiceOpts struct {
35+
// Status represents the new service status. One of enabled or disabled.
36+
Status services.ServiceStatus `json:"status,omitempty"`
37+
38+
// DisabledReason represents the reason for disabling a service.
39+
DisabledReason string `json:"disabled_reason,omitempty"`
40+
41+
// ForcedDown is a manual override to tell nova that the service in question
42+
// has been fenced manually by the operations team.
43+
ForcedDown *bool `json:"forced_down,omitempty"`
44+
}
45+
46+
// ToServiceUpdateMap formats an UpdateServiceOpts structure into a request body.
47+
func (opts UpdateServiceOpts) ToServiceUpdateMap() (map[string]any, error) {
48+
return gophercloud.BuildRequestBody(opts, "")
49+
}
50+
51+
func updateServiceURL(c *gophercloud.ServiceClient, id string) string {
52+
return c.ServiceURL("os-services", id)
53+
}
54+
55+
// UpdateService requests that various attributes of the indicated service be changed.
56+
func UpdateService(ctx context.Context, client *gophercloud.ServiceClient, id string, opts UpdateServiceOpts) (r services.UpdateResult) {
57+
b, err := opts.ToServiceUpdateMap()
58+
if err != nil {
59+
r.Err = err
60+
return
61+
}
62+
resp, err := client.Put(ctx, updateServiceURL(client, id), b, &r.Body, &gophercloud.RequestOpts{
63+
OkCodes: []int{200},
64+
})
65+
_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
66+
return
67+
}

0 commit comments

Comments
 (0)