@@ -195,9 +195,15 @@ func (r *Reconciler) Reconcile(ctx context.Context,
195
195
}()
196
196
197
197
if instance .DeletionTimestamp != nil {
198
- // TODO: Need to handle deletion if the instance is not fully processed.
199
- log .Info ("instance is being deleted" )
200
- err = removeFinalizer (ctx , r .client , instance )
198
+ log .Info ("instance is marked for deletion" )
199
+ err = r .reconcileDelete (ctx , * instance , request )
200
+ if err != nil {
201
+ log .Error ("failed to reconcile with error " , err )
202
+ return reconcile.Result {}, err
203
+ }
204
+
205
+ log .Info ("removing finalizer and allowing deletion of the instance" )
206
+ err := removeFinalizer (ctx , r .client , instance )
201
207
if err != nil {
202
208
log .Error ("failed to remove finalizer from the instance with error " , err )
203
209
return reconcile.Result {}, err
@@ -220,81 +226,150 @@ func (r *Reconciler) Reconcile(ctx context.Context,
220
226
return reconcile.Result {}, err
221
227
}
222
228
223
- // Initialize backOffDuration for the instance, if required.
224
- duration := getBackoffDuration (ctx , request .NamespacedName )
225
- params , err := getValidatedParams (ctx , * instance )
229
+ err = r .reconcile (ctx , instance , request )
226
230
if err != nil {
227
- log .Error ("failed to get input parameters with error " , err )
231
+ log .Error ("failed to reconcile with error " , err )
228
232
setInstanceError (ctx , r , instance , err .Error ())
229
- return reconcile.Result {RequeueAfter : duration }, nil
233
+ return reconcile.Result {RequeueAfter : getBackoffDuration ( ctx , request . NamespacedName ) }, nil
230
234
}
231
235
232
- k8sClient , err := newK8sClient (ctx )
236
+ msg := "successfully unregistered the volume"
237
+ err = setInstanceSuccess (ctx , r , instance , msg )
233
238
if err != nil {
234
- log .Error ("failed to init K8s client for volume unregistration with error " , err )
235
- setInstanceError (ctx , r , instance , "failed to init K8s client for volume unregistration" )
236
- return reconcile.Result {RequeueAfter : duration }, nil
239
+ log .Warn ("failed to set instance to success with error " , err )
240
+ setInstanceError (ctx , r , instance , "failed to set instance to success" )
241
+ return reconcile.Result {RequeueAfter : getBackoffDuration (ctx , request .NamespacedName )}, nil
242
+ }
243
+
244
+ deleteBackoffEntry (ctx , request .NamespacedName )
245
+ log .Info (msg )
246
+ return reconcile.Result {}, nil
247
+ }
248
+
249
+ func (r * Reconciler ) reconcile (ctx context.Context ,
250
+ instance * v1a1.CnsUnregisterVolume , request reconcile.Request ) error {
251
+ log := logger .GetLogger (ctx ).With ("name" , request .NamespacedName )
252
+
253
+ params , err := getValidatedParams (ctx , * instance )
254
+ if err != nil {
255
+ log .Error ("invalid input parameters" , err )
256
+ return err
237
257
}
238
258
239
- usageInfo , err := getVolumeUsageInfo (ctx , k8sClient , params .pvcName , params .namespace ,
259
+ usageInfo , err := getVolumeUsageInfo (ctx , params .pvcName , params .namespace ,
240
260
instance .Spec .ForceUnregister )
241
261
if err != nil {
242
- setInstanceError ( ctx , r , instance , err . Error () )
243
- return reconcile. Result { RequeueAfter : duration }, nil
262
+ log . Error ( "failed to get volume usage info with error " , err )
263
+ return err
244
264
}
245
265
246
266
if usageInfo .isInUse {
247
267
msg := fmt .Sprintf ("volume %s cannot be unregistered because %s" , params .volumeID , usageInfo )
248
268
log .Error (msg )
249
- setInstanceError (ctx , r , instance , msg )
250
- return reconcile.Result {RequeueAfter : duration }, nil
269
+ return errors .New (msg )
270
+ }
271
+
272
+ err = unregisterVolume (ctx , * r , request , * params )
273
+ if err != nil {
274
+ log .Error ("failed to unregister volume with error " , err )
275
+ return err
276
+ }
277
+
278
+ log .Info ("successfully unregistered volume" )
279
+ return nil
280
+ }
281
+
282
+ // reconcileDelete handles deletion of a CnsUnregisterVolume instance.
283
+ // The reconciler tries to keep the system consistent by carefully deciding
284
+ // when to continue with volume unregistration.
285
+ // The finalizer on the instance will only be removed if the result will keep the system in a consistent state.
286
+ func (r * Reconciler ) reconcileDelete (ctx context.Context ,
287
+ instance v1a1.CnsUnregisterVolume , request reconcile.Request ) error {
288
+ log := logger .GetLogger (ctx ).With ("name" , request .NamespacedName )
289
+
290
+ if instance .Status .Unregistered {
291
+ // If the volume is already unregistered, the instance can be deleted.
292
+ log .Info ("volume is already unregistered" )
293
+ return nil
294
+ }
295
+
296
+ params , err := getValidatedParams (ctx , instance )
297
+ if err != nil {
298
+ // If input parameters are invalid, the instance can be deleted
299
+ // since the volume cannot be unregistered.
300
+ log .Info ("invalid input parameters" )
301
+ return nil
302
+ }
303
+
304
+ usageInfo , err := getVolumeUsageInfo (ctx , params .pvcName , params .namespace ,
305
+ instance .Spec .ForceUnregister )
306
+ if err != nil {
307
+ log .Error ("failed to get volume usage info with error " , err )
308
+ return err
309
+ }
310
+
311
+ if usageInfo .isInUse {
312
+ // If the volume is in use, the instance can be deleted
313
+ // since the volume cannot be unregistered.
314
+ log .Info (usageInfo )
315
+ return nil
316
+ }
317
+
318
+ err = unregisterVolume (ctx , * r , request , * params )
319
+ if err != nil {
320
+ log .Error ("failed to unregister volume with error " , err )
321
+ return err
322
+ }
323
+
324
+ log .Info ("successfully unregistered volume" )
325
+ return nil
326
+ }
327
+
328
+ func unregisterVolume (ctx context.Context , r Reconciler ,
329
+ request reconcile.Request , params params ) error {
330
+ log := logger .GetLogger (ctx ).With ("name" , request .NamespacedName )
331
+
332
+ k8sClient , err := newK8sClient (ctx )
333
+ if err != nil {
334
+ log .Error ("failed to init K8s client for volume unregistration with error " , err )
335
+ return err
251
336
}
252
337
253
338
err = protectPVC (ctx , k8sClient , params .pvcName , params .namespace ,
254
339
cnsoptypes .CNSUnregisterProtectionFinalizer )
255
340
if err != nil {
256
- setInstanceError ( ctx , r , instance , "failed to add finalizer on PVC" )
257
- return reconcile. Result { RequeueAfter : duration }, nil
341
+ log . Error ( "failed to add finalizer on PVC with error " , err )
342
+ return errors . New ( "failed to protect PVC" )
258
343
}
259
344
260
345
err = deletePVC (ctx , k8sClient , params .pvcName , params .namespace )
261
346
if err != nil {
262
- setInstanceError ( ctx , r , instance , "failed to delete PVC" )
263
- return reconcile. Result { RequeueAfter : duration }, nil
347
+ log . Error ( "failed to delete PVC with error " , err )
348
+ return errors . New ( "failed to delete PVC" )
264
349
}
265
350
266
351
err = deletePV (ctx , k8sClient , params .pvName )
267
352
if err != nil {
268
- setInstanceError ( ctx , r , instance , "failed to delete PV" )
269
- return reconcile. Result { RequeueAfter : duration }, nil
353
+ log . Error ( "failed to delete PV with error " , err )
354
+ return errors . New ( "failed to delete PV" )
270
355
}
271
356
272
- unregDisk := ! instance . Spec . RetainFCD
357
+ unregDisk := ! params . retainFCD // If retainFCD is false, unregister the FCD too.
273
358
err = r .volumeManager .UnregisterVolume (ctx , params .volumeID , unregDisk )
274
359
if err != nil {
275
- setInstanceError ( ctx , r , instance , "failed to unregister volume" )
276
- return reconcile. Result { RequeueAfter : duration }, nil
360
+ log . Error ( "failed to unregister volume with error " , err )
361
+ return errors . New ( "failed to unregister volume" )
277
362
}
278
363
279
364
err = removeFinalizerFromPVC (ctx , k8sClient , params .pvcName , params .namespace ,
280
365
cnsoptypes .CNSUnregisterProtectionFinalizer )
281
366
if err != nil {
282
- setInstanceError ( ctx , r , instance , "failed to remove finalizer from PVC" )
283
- return reconcile. Result { RequeueAfter : duration }, nil
367
+ log . Error ( "failed to remove finalizer from PVC with error " , err )
368
+ return errors . New ( "failed to remove finalizer from PVC" )
284
369
}
285
370
286
371
log .Infof ("successfully unregistered CNS volume %s" , params .volumeID )
287
- msg := "successfully unregistered the volume"
288
- err = setInstanceSuccess (ctx , r , instance , msg )
289
- if err != nil {
290
- log .Warn ("failed to set instance to success with error " , err )
291
- setInstanceError (ctx , r , instance , "failed to set instance to success" )
292
- return reconcile.Result {RequeueAfter : duration }, nil
293
- }
294
-
295
- deleteBackoffEntry (ctx , request .NamespacedName )
296
- log .Info (msg )
297
- return reconcile.Result {}, nil
372
+ return nil
298
373
}
299
374
300
375
// setInstanceError sets error and records an event on the CnsUnregisterVolume
@@ -359,6 +434,11 @@ type params struct {
359
434
pvName string
360
435
}
361
436
437
+ func (p * params ) String () string {
438
+ return fmt .Sprintf ("retainFCD: %t, force: %t, namespace: %s, volumeID: %s, pvcName: %s, pvName: %s" ,
439
+ p .retainFCD , p .force , p .namespace , p .volumeID , p .pvcName , p .pvName )
440
+ }
441
+
362
442
var getValidatedParams = _getValidatedParams
363
443
364
444
func _getValidatedParams (ctx context.Context , instance v1a1.CnsUnregisterVolume ) (* params , error ) {
@@ -398,6 +478,7 @@ func _getValidatedParams(ctx context.Context, instance v1a1.CnsUnregisterVolume)
398
478
log .Info ("no PV found for the Volume ID " , p .volumeID )
399
479
}
400
480
481
+ log .Debug ("validated input parameters: " , p )
401
482
return & p , nil
402
483
}
403
484
0 commit comments