@@ -18,6 +18,7 @@ import (
18
18
19
19
apierrors "k8s.io/apimachinery/pkg/api/errors"
20
20
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
21
+ "k8s.io/apimachinery/pkg/types"
21
22
22
23
vmv1 "github.com/neondatabase/autoscaling/neonvm/apis/neonvm/v1"
23
24
neonvm "github.com/neondatabase/autoscaling/neonvm/client/clientset/versioned"
@@ -175,14 +176,12 @@ func (i *IPAM) acquireORrelease(ctx context.Context, vmName string, vmNamespace
175
176
176
177
// Performing IPAM actions
177
178
func (i * IPAM ) runIPAM (ctx context.Context , vmName string , vmNamespace string , action int ) (net.IPNet , error ) {
178
- var ip net.IPNet
179
- var ipamerr error
179
+ log := log .FromContext (ctx )
180
180
181
- // check action
182
181
switch action {
183
182
case Acquire , Release :
184
183
default :
185
- return ip , fmt .Errorf ("got an unknown action: %v" , action )
184
+ return net. IPNet {} , fmt .Errorf ("got an unknown action: %v" , action )
186
185
}
187
186
188
187
ctx , ctxCancel := context .WithTimeout (ctx , IpamRequestTimeout )
@@ -192,67 +191,73 @@ func (i *IPAM) runIPAM(ctx context.Context, vmName string, vmNamespace string, a
192
191
for _ , ipRange := range i .Config .IPRanges {
193
192
// retry loop used to retry CRUD operations against Kubernetes
194
193
// if we meet some issue then just do another attepmt
195
- RETRY:
196
- for retry := 0 ; retry < DatastoreRetries ; retry ++ {
197
- select {
198
- case <- ctx .Done ():
199
- break RETRY
200
- default :
201
- // live in retry loop until context not cancelled
202
- }
194
+ ip , err := i .runIPAMRange (ctx , types.NamespacedName {Name : vmName , Namespace : vmNamespace }, ipRange , action )
195
+ // break ipRanges loop if ip was acquired/released
196
+ if err == nil {
197
+ return ip , nil
198
+ }
199
+ log .Error (err , "error acquiring/releasing IP from range" , ipRange .Range )
200
+ }
201
+ switch action {
202
+ case Acquire :
203
+ return net.IPNet {}, errors .New ("can not acquire IP, probably there are no space in IP pools" )
204
+ case Release :
205
+ return net.IPNet {}, errors .New ("can not release IP" )
206
+ }
207
+ return net.IPNet {}, errors .New ("unknown action" )
208
+ }
203
209
204
- // read IPPool from ipppols.vm.neon.tech custom resource
205
- pool , err := i .getNeonvmIPPool (ctx , ipRange .Range )
206
- if err != nil {
207
- if e , ok := err .(Temporary ); ok && e .Temporary () {
208
- // retry attempt to read IPPool
209
- time .Sleep (DatastoreRetriesDelay )
210
- continue
211
- }
212
- return ip , fmt .Errorf ("error reading IP pool: %w" , err )
213
- }
210
+ func (i * IPAM ) runIPAMRange (ctx context.Context , vmName types.NamespacedName , ipRange RangeConfiguration , action int ) (net.IPNet , error ) {
211
+ var ip net.IPNet
212
+ for retry := 0 ; retry < DatastoreRetries ; retry ++ {
213
+ select {
214
+ case <- ctx .Done ():
215
+ return net.IPNet {}, ctx .Err ()
216
+ default :
217
+ // live in retry loop until context not cancelled
218
+ }
214
219
215
- currentReservation := pool .Allocations (ctx )
216
- var newReservation []whereaboutstypes.IPReservation
217
- switch action {
218
- case Acquire :
219
- ip , newReservation , ipamerr = doAcquire (ctx , ipRange , currentReservation , vmName , vmNamespace )
220
- if ipamerr != nil {
221
- // no space in the pool ? try another pool
222
- break RETRY
223
- }
224
- case Release :
225
- ip , newReservation , ipamerr = doRelease (ctx , ipRange , currentReservation , vmName , vmNamespace )
226
- if ipamerr != nil {
227
- // not found in the pool ? try another pool
228
- break RETRY
229
- }
220
+ // read IPPool from ipppols.vm.neon.tech custom resource
221
+ pool , err := i .getNeonvmIPPool (ctx , ipRange .Range )
222
+ if err != nil {
223
+ if e , ok := err .(Temporary ); ok && e .Temporary () {
224
+ // retry attempt to read IPPool
225
+ time .Sleep (DatastoreRetriesDelay )
226
+ continue
230
227
}
228
+ return net.IPNet {}, fmt .Errorf ("error reading IP pool: %w" , err )
229
+ }
231
230
232
- // update IPPool with newReservation
233
- err = pool .Update (ctx , newReservation )
231
+ currentReservation := pool .Allocations (ctx )
232
+ var newReservation []whereaboutstypes.IPReservation
233
+ switch action {
234
+ case Acquire :
235
+ ip , newReservation , err = doAcquire (ctx , ipRange , currentReservation , vmName .Name , vmName .Namespace )
234
236
if err != nil {
235
- if e , ok := err .(Temporary ); ok && e .Temporary () {
236
- // retry attempt to update IPPool
237
- time .Sleep (DatastoreRetriesDelay )
238
- continue
239
- }
240
- return ip , fmt .Errorf ("error updating IP pool: %w" , err )
237
+ // no space in the pool ? try another pool
238
+ return net.IPNet {}, err
239
+ }
240
+ case Release :
241
+ ip , newReservation , err = doRelease (ctx , ipRange , currentReservation , vmName .Name , vmName .Namespace )
242
+ if err != nil {
243
+ // not found in the pool ? try another pool
244
+ return net.IPNet {}, err
241
245
}
242
- // pool was read, acquire or release was processed, pool was updated
243
- // now we can break retry loop
244
- break
245
246
}
246
- // break ipRanges loop if ip was acquired/released
247
- if ip .IP != nil {
248
- break
247
+
248
+ // update IPPool with newReservation
249
+ err = pool .Update (ctx , newReservation )
250
+ if err != nil {
251
+ if e , ok := err .(Temporary ); ok && e .Temporary () {
252
+ // retry attempt to update IPPool
253
+ time .Sleep (DatastoreRetriesDelay )
254
+ continue
255
+ }
256
+ return net.IPNet {}, fmt .Errorf ("error updating IP pool: %w" , err )
249
257
}
258
+ return ip , nil
250
259
}
251
- if ip .IP == nil && action == Acquire {
252
- return ip , errors .New ("can not acquire IP, probably there are no space in IP pools" )
253
- }
254
-
255
- return ip , ipamerr
260
+ return ip , errors .New ("IPAMretries limit reached" )
256
261
}
257
262
258
263
// Status do List() request to check NeonVM client connectivity
0 commit comments