@@ -3,6 +3,7 @@ package main
3
3
import (
4
4
"context"
5
5
"fmt"
6
+ "math"
6
7
"os"
7
8
"strconv"
8
9
"strings"
@@ -21,7 +22,26 @@ var trueVar = true
21
22
var falseVar = false
22
23
23
24
type hetznerDriver struct {
24
- client hetznerClienter
25
+ client hetznerClienter
26
+ nextTry time.Time
27
+ failuresInARow int
28
+ }
29
+
30
+ func (hd * hetznerDriver ) checkBackoff () error {
31
+ if time .Now ().Before (hd .nextTry ) {
32
+ return fmt .Errorf ("last failure too recent; waiting a bit before retrying" )
33
+ }
34
+ return nil
35
+ }
36
+
37
+ func (hd * hetznerDriver ) handleBackoff (err error ) {
38
+ if err == nil {
39
+ hd .failuresInARow = 0
40
+ }
41
+ if err != nil {
42
+ hd .nextTry = time .Now ().Add (time .Duration (int64 (math .Pow (2 , float64 (hd .failuresInARow )))) * time .Second )
43
+ hd .failuresInARow ++
44
+ }
25
45
}
26
46
27
47
func newHetznerDriver () * hetznerDriver {
@@ -36,7 +56,7 @@ func (hd *hetznerDriver) Capabilities() *volume.CapabilitiesResponse {
36
56
}
37
57
}
38
58
39
- func (hd * hetznerDriver ) Create (req * volume.CreateRequest ) error {
59
+ func (hd * hetznerDriver ) createInternal (req * volume.CreateRequest ) error {
40
60
validateOptions (req .Name , req .Options )
41
61
42
62
prefixedName := prefixName (req .Name )
@@ -61,7 +81,7 @@ func (hd *hetznerDriver) Create(req *volume.CreateRequest) error {
61
81
}
62
82
switch f := getOption ("fstype" , req .Options ); f {
63
83
case "xfs" , "ext4" :
64
- opts .Format = hcloud .String (f )
84
+ opts .Format = hcloud .Ptr (f )
65
85
}
66
86
67
87
resp , _ , err := hd .client .Volume ().Create (context .Background (), opts )
@@ -118,7 +138,17 @@ func (hd *hetznerDriver) Create(req *volume.CreateRequest) error {
118
138
return nil
119
139
}
120
140
121
- func (hd * hetznerDriver ) List () (* volume.ListResponse , error ) {
141
+ func (hd * hetznerDriver ) Create (req * volume.CreateRequest ) error {
142
+ if err := hd .checkBackoff (); err != nil {
143
+ return err
144
+ }
145
+
146
+ err := hd .createInternal (req )
147
+ hd .handleBackoff (err )
148
+ return err
149
+ }
150
+
151
+ func (hd * hetznerDriver ) listInternal () (* volume.ListResponse , error ) {
122
152
logrus .Infof ("got list request" )
123
153
124
154
vols , err := hd .client .Volume ().All (context .Background ())
@@ -150,7 +180,17 @@ func (hd *hetznerDriver) List() (*volume.ListResponse, error) {
150
180
return & resp , nil
151
181
}
152
182
153
- func (hd * hetznerDriver ) Get (req * volume.GetRequest ) (* volume.GetResponse , error ) {
183
+ func (hd * hetznerDriver ) List () (* volume.ListResponse , error ) {
184
+ if err := hd .checkBackoff (); err != nil {
185
+ return nil , err
186
+ }
187
+
188
+ resp , err := hd .listInternal ()
189
+ hd .handleBackoff (err )
190
+ return resp , err
191
+ }
192
+
193
+ func (hd * hetznerDriver ) getInternal (req * volume.GetRequest ) (* volume.GetResponse , error ) {
154
194
prefixedName := prefixName (req .Name )
155
195
156
196
logrus .Infof ("fetching information for volume %q" , prefixedName )
@@ -186,7 +226,17 @@ func (hd *hetznerDriver) Get(req *volume.GetRequest) (*volume.GetResponse, error
186
226
return & resp , nil
187
227
}
188
228
189
- func (hd * hetznerDriver ) Remove (req * volume.RemoveRequest ) error {
229
+ func (hd * hetznerDriver ) Get (req * volume.GetRequest ) (* volume.GetResponse , error ) {
230
+ if err := hd .checkBackoff (); err != nil {
231
+ return nil , err
232
+ }
233
+
234
+ resp , err := hd .getInternal (req )
235
+ hd .handleBackoff (err )
236
+ return resp , err
237
+ }
238
+
239
+ func (hd * hetznerDriver ) removeInternal (req * volume.RemoveRequest ) error {
190
240
prefixedName := prefixName (req .Name )
191
241
192
242
logrus .Infof ("starting volume removal for %q" , prefixedName )
@@ -228,7 +278,17 @@ func (hd *hetznerDriver) Remove(req *volume.RemoveRequest) error {
228
278
return nil
229
279
}
230
280
231
- func (hd * hetznerDriver ) Path (req * volume.PathRequest ) (* volume.PathResponse , error ) {
281
+ func (hd * hetznerDriver ) Remove (req * volume.RemoveRequest ) error {
282
+ if err := hd .checkBackoff (); err != nil {
283
+ return err
284
+ }
285
+
286
+ err := hd .removeInternal (req )
287
+ hd .handleBackoff (err )
288
+ return err
289
+ }
290
+
291
+ func (hd * hetznerDriver ) pathInternal (req * volume.PathRequest ) (* volume.PathResponse , error ) {
232
292
prefixedName := prefixName (req .Name )
233
293
234
294
logrus .Infof ("got path request for volume %q" , prefixedName )
@@ -241,7 +301,17 @@ func (hd *hetznerDriver) Path(req *volume.PathRequest) (*volume.PathResponse, er
241
301
return & volume.PathResponse {Mountpoint : resp .Volume .Mountpoint }, nil
242
302
}
243
303
244
- func (hd * hetznerDriver ) Mount (req * volume.MountRequest ) (* volume.MountResponse , error ) {
304
+ func (hd * hetznerDriver ) Path (req * volume.PathRequest ) (* volume.PathResponse , error ) {
305
+ if err := hd .checkBackoff (); err != nil {
306
+ return nil , err
307
+ }
308
+
309
+ resp , err := hd .pathInternal (req )
310
+ hd .handleBackoff (err )
311
+ return resp , err
312
+ }
313
+
314
+ func (hd * hetznerDriver ) mountInternal (req * volume.MountRequest ) (* volume.MountResponse , error ) {
245
315
prefixedName := prefixName (req .Name )
246
316
247
317
logrus .Infof ("received mount request for %q as %q" , prefixedName , req .ID )
@@ -313,7 +383,17 @@ func (hd *hetznerDriver) Mount(req *volume.MountRequest) (*volume.MountResponse,
313
383
return & volume.MountResponse {Mountpoint : mountpoint }, nil
314
384
}
315
385
316
- func (hd * hetznerDriver ) Unmount (req * volume.UnmountRequest ) error {
386
+ func (hd * hetznerDriver ) Mount (req * volume.MountRequest ) (* volume.MountResponse , error ) {
387
+ if err := hd .checkBackoff (); err != nil {
388
+ return nil , err
389
+ }
390
+
391
+ resp , err := hd .mountInternal (req )
392
+ hd .handleBackoff (err )
393
+ return resp , err
394
+ }
395
+
396
+ func (hd * hetznerDriver ) unmountInternal (req * volume.UnmountRequest ) error {
317
397
prefixedName := prefixName (req .Name )
318
398
319
399
logrus .Infof ("received unmount request for %q as %q" , prefixedName , req .ID )
@@ -357,6 +437,16 @@ func (hd *hetznerDriver) Unmount(req *volume.UnmountRequest) error {
357
437
return nil
358
438
}
359
439
440
+ func (hd * hetznerDriver ) Unmount (req * volume.UnmountRequest ) error {
441
+ if err := hd .checkBackoff (); err != nil {
442
+ return err
443
+ }
444
+
445
+ err := hd .unmountInternal (req )
446
+ hd .handleBackoff (err )
447
+ return err
448
+ }
449
+
360
450
func (hd * hetznerDriver ) getServerForLocalhost () (* hcloud.Server , error ) {
361
451
hostname , err := os .Hostname ()
362
452
if err != nil {
0 commit comments