Skip to content

Commit 59277df

Browse files
informalictajanikow
authored andcommitted
Fixed bug with changing storage class name (#487)
1 parent 523e1a3 commit 59277df

20 files changed

+1072
-101
lines changed

pkg/apis/deployment/v1/plan.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ const (
5252
ActionTypeRenewTLSCACertificate ActionType = "RenewTLSCACertificate"
5353
// ActionTypeSetCurrentImage causes status.CurrentImage to be updated to the image given in the action.
5454
ActionTypeSetCurrentImage ActionType = "SetCurrentImage"
55+
// ActionTypeDisableClusterScaling turns off scaling DBservers and coordinators
56+
ActionTypeDisableClusterScaling ActionType = "ScalingDisabled"
57+
// ActionTypeEnableClusterScaling turns on scaling DBservers and coordinators
58+
ActionTypeEnableClusterScaling ActionType = "ScalingEnabled"
5559
)
5660

5761
const (
@@ -134,3 +138,8 @@ func (p Plan) Equal(other Plan) bool {
134138

135139
return true
136140
}
141+
142+
// IsEmpty checks if plan is empty
143+
func (p Plan) IsEmpty() bool {
144+
return len(p) == 0
145+
}

pkg/apis/deployment/v1/server_group_spec.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,9 @@ func (s ServerGroupSpec) GetArgs() []string {
147147

148148
// GetStorageClassName returns the value of storageClassName.
149149
func (s ServerGroupSpec) GetStorageClassName() string {
150+
if pvc := s.GetVolumeClaimTemplate(); pvc != nil {
151+
return util.StringOrDefault(pvc.Spec.StorageClassName)
152+
}
150153
return util.StringOrDefault(s.StorageClassName)
151154
}
152155

pkg/apis/deployment/v1alpha/plan.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ const (
5252
ActionTypeRenewTLSCACertificate ActionType = "RenewTLSCACertificate"
5353
// ActionTypeSetCurrentImage causes status.CurrentImage to be updated to the image given in the action.
5454
ActionTypeSetCurrentImage ActionType = "SetCurrentImage"
55+
// ActionTypeDisableClusterScaling turns off scaling DBservers and coordinators
56+
ActionTypeDisableClusterScaling ActionType = "ScalingDisabled"
57+
// ActionTypeEnableClusterScaling turns on scaling DBservers and coordinators
58+
ActionTypeEnableClusterScaling ActionType = "ScalingEnabled"
5559
)
5660

5761
const (
@@ -134,3 +138,8 @@ func (p Plan) Equal(other Plan) bool {
134138

135139
return true
136140
}
141+
142+
// IsEmpty checks if plan is empty
143+
func (p Plan) IsEmpty() bool {
144+
return len(p) == 0
145+
}

pkg/apis/deployment/v1alpha/server_group_spec.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,9 @@ func (s ServerGroupSpec) GetArgs() []string {
147147

148148
// GetStorageClassName returns the value of storageClassName.
149149
func (s ServerGroupSpec) GetStorageClassName() string {
150+
if pvc := s.GetVolumeClaimTemplate(); pvc != nil {
151+
return util.StringOrDefault(pvc.Spec.StorageClassName)
152+
}
150153
return util.StringOrDefault(s.StorageClassName)
151154
}
152155

pkg/deployment/cluster_scaling_integration.go

Lines changed: 103 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ type clusterScalingIntegration struct {
4949
arangod.NumberOfServers
5050
mutex sync.Mutex
5151
}
52+
scaleEnabled struct {
53+
mutex sync.Mutex
54+
enabled bool
55+
}
5256
}
5357

5458
const (
@@ -57,10 +61,12 @@ const (
5761

5862
// newClusterScalingIntegration creates a new clusterScalingIntegration.
5963
func newClusterScalingIntegration(depl *Deployment) *clusterScalingIntegration {
60-
return &clusterScalingIntegration{
64+
ci := &clusterScalingIntegration{
6165
log: depl.deps.Log,
6266
depl: depl,
6367
}
68+
ci.scaleEnabled.enabled = true
69+
return ci
6470
}
6571

6672
// SendUpdateToCluster records the given spec to be sended to the cluster.
@@ -70,37 +76,61 @@ func (ci *clusterScalingIntegration) SendUpdateToCluster(spec api.DeploymentSpec
7076
ci.pendingUpdate.spec = &spec
7177
}
7278

79+
// checkScalingCluster checks if inspection
80+
// returns true if inspection occurred
81+
func (ci *clusterScalingIntegration) checkScalingCluster(expectSuccess bool) bool {
82+
ci.scaleEnabled.mutex.Lock()
83+
defer ci.scaleEnabled.mutex.Unlock()
84+
85+
if !ci.scaleEnabled.enabled {
86+
// Check if it is possible to turn on scaling without any issue
87+
status, _ := ci.depl.GetStatus()
88+
if status.Plan.IsEmpty() && ci.setNumberOfServers() == nil {
89+
// Scaling should be enabled because there is no Plan.
90+
// It can happen when the enabling action fails
91+
ci.scaleEnabled.enabled = true
92+
}
93+
}
94+
95+
if ci.depl.GetPhase() != api.DeploymentPhaseRunning || !ci.scaleEnabled.enabled {
96+
// Deployment must be in running state and scaling must be enabled
97+
return false
98+
}
99+
100+
// Update cluster with our state
101+
ctx := context.Background()
102+
//expectSuccess := *goodInspections > 0 || time.Since(start) > maxClusterBootstrapTime
103+
safeToAskCluster, err := ci.updateClusterServerCount(ctx, expectSuccess)
104+
if err != nil {
105+
if expectSuccess {
106+
ci.log.Debug().Err(err).Msg("Cluster update failed")
107+
}
108+
} else if safeToAskCluster {
109+
// Inspect once
110+
if err := ci.inspectCluster(ctx, expectSuccess); err != nil {
111+
if expectSuccess {
112+
ci.log.Debug().Err(err).Msg("Cluster inspection failed")
113+
}
114+
} else {
115+
return true
116+
}
117+
}
118+
return false
119+
}
120+
73121
// listenForClusterEvents keep listening for changes entered in the UI of the cluster.
74122
func (ci *clusterScalingIntegration) ListenForClusterEvents(stopCh <-chan struct{}) {
75123
start := time.Now()
76124
goodInspections := 0
77125
for {
78-
delay := time.Second * 2
79-
80-
// Is deployment in running state
81-
if ci.depl.GetPhase() == api.DeploymentPhaseRunning {
82-
// Update cluster with our state
83-
ctx := context.Background()
84-
expectSuccess := goodInspections > 0 || time.Since(start) > maxClusterBootstrapTime
85-
safeToAskCluster, err := ci.updateClusterServerCount(ctx, expectSuccess)
86-
if err != nil {
87-
if expectSuccess {
88-
ci.log.Debug().Err(err).Msg("Cluster update failed")
89-
}
90-
} else if safeToAskCluster {
91-
// Inspect once
92-
if err := ci.inspectCluster(ctx, expectSuccess); err != nil {
93-
if expectSuccess {
94-
ci.log.Debug().Err(err).Msg("Cluster inspection failed")
95-
}
96-
} else {
97-
goodInspections++
98-
}
99-
}
126+
expectSuccess := goodInspections > 0 || time.Since(start) > maxClusterBootstrapTime
127+
128+
if ci.checkScalingCluster(expectSuccess) {
129+
goodInspections++
100130
}
101131

102132
select {
103-
case <-time.After(delay):
133+
case <-time.After(time.Second * 2):
104134
// Continue
105135
case <-stopCh:
106136
// We're done
@@ -200,11 +230,6 @@ func (ci *clusterScalingIntegration) updateClusterServerCount(ctx context.Contex
200230
}
201231

202232
log := ci.log
203-
c, err := ci.depl.clientCache.GetDatabase(ctx)
204-
if err != nil {
205-
return false, maskAny(err)
206-
}
207-
208233
var coordinatorCountPtr *int
209234
var dbserverCountPtr *int
210235

@@ -223,13 +248,11 @@ func (ci *clusterScalingIntegration) updateClusterServerCount(ctx context.Contex
223248
dbserverCountPtr = &dbserverCount
224249
}
225250

226-
ci.lastNumberOfServers.mutex.Lock()
227-
lastNumberOfServers := ci.lastNumberOfServers.NumberOfServers
228-
ci.lastNumberOfServers.mutex.Unlock()
251+
lastNumberOfServers := ci.GetLastNumberOfServers()
229252

230253
// This is to prevent unneseccary updates that may override some values written by the WebUI (in the case of a update loop)
231254
if coordinatorCount != lastNumberOfServers.GetCoordinators() || dbserverCount != lastNumberOfServers.GetDBServers() {
232-
if err := arangod.SetNumberOfServers(ctx, c.Connection(), coordinatorCountPtr, dbserverCountPtr); err != nil {
255+
if err := ci.depl.SetNumberOfServers(ctx, coordinatorCountPtr, dbserverCountPtr); err != nil {
233256
if expectSuccess {
234257
log.Debug().Err(err).Msg("Failed to set number of servers")
235258
}
@@ -253,3 +276,50 @@ func (ci *clusterScalingIntegration) updateClusterServerCount(ctx context.Contex
253276
ci.lastNumberOfServers.DBServers = &dbserverCount
254277
return safeToAskCluster, nil
255278
}
279+
280+
// GetLastNumberOfServers returns the last number of servers
281+
func (ci *clusterScalingIntegration) GetLastNumberOfServers() arangod.NumberOfServers {
282+
ci.lastNumberOfServers.mutex.Lock()
283+
defer ci.lastNumberOfServers.mutex.Unlock()
284+
285+
return ci.lastNumberOfServers.NumberOfServers
286+
}
287+
288+
// DisableScalingCluster disables scaling DBservers and coordinators
289+
func (ci *clusterScalingIntegration) DisableScalingCluster() error {
290+
ci.scaleEnabled.mutex.Lock()
291+
defer ci.scaleEnabled.mutex.Unlock()
292+
293+
// Turn off scaling DBservers and coordinators in arangoDB for the UI
294+
ctx := context.Background()
295+
if err := ci.depl.SetNumberOfServers(ctx, nil, nil); err != nil {
296+
return maskAny(err)
297+
}
298+
299+
ci.scaleEnabled.enabled = false
300+
return nil
301+
}
302+
303+
// EnableScalingCluster enables scaling DBservers and coordinators
304+
func (ci *clusterScalingIntegration) EnableScalingCluster() error {
305+
ci.scaleEnabled.mutex.Lock()
306+
defer ci.scaleEnabled.mutex.Unlock()
307+
308+
if ci.scaleEnabled.enabled {
309+
return nil
310+
}
311+
312+
if err := ci.setNumberOfServers(); err != nil {
313+
return maskAny(err)
314+
}
315+
ci.scaleEnabled.enabled = true
316+
return nil
317+
}
318+
319+
func (ci *clusterScalingIntegration) setNumberOfServers() error {
320+
ctx := context.Background()
321+
spec := ci.depl.GetSpec()
322+
numOfCoordinators := spec.Coordinators.GetCount()
323+
numOfDBServers := spec.DBServers.GetCount()
324+
return ci.depl.SetNumberOfServers(ctx, &numOfCoordinators, &numOfDBServers)
325+
}

pkg/deployment/context_impl.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,3 +418,11 @@ func (d *Deployment) GetShardSyncStatus() bool {
418418
func (d *Deployment) InvalidateSyncStatus() {
419419
d.resources.InvalidateSyncStatus()
420420
}
421+
422+
func (d *Deployment) DisableScalingCluster() error {
423+
return d.clusterScalingIntegration.DisableScalingCluster()
424+
}
425+
426+
func (d *Deployment) EnableScalingCluster() error {
427+
return d.clusterScalingIntegration.EnableScalingCluster()
428+
}

pkg/deployment/deployment.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,14 @@
2323
package deployment
2424

2525
import (
26+
"context"
2627
"fmt"
2728
"sync"
2829
"sync/atomic"
2930
"time"
3031

32+
"github.com/arangodb/kube-arangodb/pkg/util/arangod"
33+
3134
"github.com/arangodb/arangosync-client/client"
3235
"github.com/rs/zerolog"
3336
"github.com/rs/zerolog/log"
@@ -541,3 +544,17 @@ func (d *Deployment) lookForServiceMonitorCRD() {
541544
log.Warn().Err(err).Msgf("Error when looking for ServiceMonitor CRD")
542545
return
543546
}
547+
548+
// SetNumberOfServers adjust number of DBservers and coordinators in arangod
549+
func (d *Deployment) SetNumberOfServers(ctx context.Context, noCoordinators, noDBServers *int) error {
550+
c, err := d.clientCache.GetDatabase(ctx)
551+
if err != nil {
552+
return maskAny(err)
553+
}
554+
555+
err = arangod.SetNumberOfServers(ctx, c.Connection(), noCoordinators, noDBServers)
556+
if err != nil {
557+
return maskAny(err)
558+
}
559+
return nil
560+
}

pkg/deployment/reconcile/action_context.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,10 @@ type ActionContext interface {
9090
InvalidateSyncStatus()
9191
// GetSpec returns a copy of the spec
9292
GetSpec() api.DeploymentSpec
93-
93+
// DisableScalingCluster disables scaling DBservers and coordinators
94+
DisableScalingCluster() error
95+
// EnableScalingCluster enables scaling DBservers and coordinators
96+
EnableScalingCluster() error
9497
}
9598

9699
// newActionContext creates a new ActionContext implementation.
@@ -305,3 +308,13 @@ func (ac *actionContext) SetCurrentImage(imageInfo api.ImageInfo) error {
305308
func (ac *actionContext) InvalidateSyncStatus() {
306309
ac.context.InvalidateSyncStatus()
307310
}
311+
312+
// DisableScalingCluster disables scaling DBservers and coordinators
313+
func (ac *actionContext) DisableScalingCluster() error {
314+
return ac.context.DisableScalingCluster()
315+
}
316+
317+
// EnableScalingCluster enables scaling DBservers and coordinators
318+
func (ac *actionContext) EnableScalingCluster() error {
319+
return ac.context.EnableScalingCluster()
320+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package reconcile
2+
3+
import (
4+
"context"
5+
"time"
6+
7+
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
8+
"github.com/rs/zerolog"
9+
)
10+
11+
// actionDisableScalingCluster implements disabling scaling DBservers and coordinators.
12+
type actionDisableScalingCluster struct {
13+
log zerolog.Logger
14+
action api.Action
15+
actionCtx ActionContext
16+
newMemberID string
17+
}
18+
19+
// NewDisableScalingCluster creates the new action with disabling scaling DBservers and coordinators.
20+
func NewDisableScalingCluster(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
21+
return &actionDisableScalingCluster{
22+
log: log,
23+
action: action,
24+
actionCtx: actionCtx,
25+
}
26+
}
27+
28+
// Start disables scaling DBservers and coordinators
29+
func (a *actionDisableScalingCluster) Start(ctx context.Context) (bool, error) {
30+
err := a.actionCtx.DisableScalingCluster()
31+
if err != nil {
32+
return false, err
33+
}
34+
return true, nil
35+
}
36+
37+
// CheckProgress does not matter. Everything is done in 'Start' function
38+
func (a *actionDisableScalingCluster) CheckProgress(ctx context.Context) (bool, bool, error) {
39+
return true, false, nil
40+
}
41+
42+
// Timeout does not matter. Everything is done in 'Start' function
43+
func (a *actionDisableScalingCluster) Timeout() time.Duration {
44+
return 0
45+
}
46+
47+
// MemberID is not used
48+
func (a *actionDisableScalingCluster) MemberID() string {
49+
return ""
50+
}

0 commit comments

Comments
 (0)