@@ -331,14 +331,45 @@ func (ctrl *csiSnapshotSideCarController) createSnapshotOperation(content *crdv1
331
331
return nil , fmt .Errorf ("failed to get input parameters to create snapshot for content %s: %q" , content .Name , err )
332
332
}
333
333
334
+ // NOTE(xyang): handle create timeout
335
+ // Add annotation and set to Yes to indicate create snapshot request is
336
+ // sent to the storage system and wait for a response of success or failure.
337
+ // Annotation will be set to No only after storage system has responded
338
+ // with success or failure. If the request times out, retry will happen
339
+ // and annotation will stay as Yes to avoid leaking of snapshot
340
+ // resources on the storage system
341
+ err = ctrl .setAnnVolumeSnapshotBeingCreated (content , utils .AnnVolumeSnapshotBeingCreated_Yes )
342
+ if err != nil {
343
+ return nil , fmt .Errorf ("failed to set VolumeSnapshotBeingCreated annotation to Yes on the content %s: %q" , content .Name , err )
344
+ }
345
+
334
346
driverName , snapshotID , creationTime , size , readyToUse , err := ctrl .handler .CreateSnapshot (content , class .Parameters , snapshotterCredentials )
335
347
if err != nil {
348
+ // NOTE(xyang): handle create timeout
349
+ // If it is not a timeout error, set annotation to No to indicate
350
+ // storage system has responded with an error
351
+ errStr := fmt .Sprintf ("%q" , err )
352
+ if ! strings .Contains (errStr , "DeadlineExceeded" ) {
353
+ err = ctrl .setAnnVolumeSnapshotBeingCreated (content , utils .AnnVolumeSnapshotBeingCreated_No )
354
+ if err != nil {
355
+ return nil , fmt .Errorf ("failed to set VolumeSnapshotBeingCreated annotation to No on the content %s: %q" , content .Name , err )
356
+ }
357
+ }
358
+
336
359
return nil , fmt .Errorf ("failed to take snapshot of the volume, %s: %q" , * content .Spec .Source .VolumeHandle , err )
337
360
}
338
361
if driverName != class .Driver {
339
362
return nil , fmt .Errorf ("failed to take snapshot of the volume, %s: driver name %s returned from the driver is different from driver %s in snapshot class" , * content .Spec .Source .VolumeHandle , driverName , class .Driver )
340
363
}
341
364
365
+ // NOTE(xyang): handle create timeout
366
+ // Set annotation to No to indicate storage system has successfully
367
+ // cut the snapshot
368
+ err = ctrl .setAnnVolumeSnapshotBeingCreated (content , utils .AnnVolumeSnapshotBeingCreated_No )
369
+ if err != nil {
370
+ return nil , fmt .Errorf ("failed to set VolumeSnapshotBeingCreated annotation to No on the content %s: %q" , content .Name , err )
371
+ }
372
+
342
373
klog .V (5 ).Infof ("Created snapshot: driver %s, snapshotId %s, creationTime %v, size %d, readyToUse %t" , driverName , snapshotID , creationTime , size , readyToUse )
343
374
344
375
timestamp := creationTime .UnixNano ()
@@ -573,9 +604,48 @@ func (ctrl *csiSnapshotSideCarController) shouldDelete(content *crdv1.VolumeSnap
573
604
if content .Spec .Source .SnapshotHandle != nil && content .Spec .VolumeSnapshotRef .UID == "" {
574
605
return true
575
606
}
576
- // 2) shouldDelete returns true if AnnVolumeSnapshotBeingDeleted annotation is set
607
+
608
+ // NOTE(xyang): Handle create snapshot timeout
609
+ // 2) shouldDelete returns false if AnnVolumeSnapshotBeingCreated
610
+ // annotation is set and its value is Yes. This indicates a
611
+ // CreateSnapshot CSI RPC has not responded with success or failure.
612
+ // We need to keep waiting for a response from the CSI driver.
613
+ if metav1 .HasAnnotation (content .ObjectMeta , utils .AnnVolumeSnapshotBeingCreated ) && content .ObjectMeta .Annotations [utils .AnnVolumeSnapshotBeingCreated ] == utils .AnnVolumeSnapshotBeingCreated_Yes {
614
+ return false
615
+ }
616
+
617
+ // 3) shouldDelete returns true if AnnVolumeSnapshotBeingDeleted annotation is set
577
618
if metav1 .HasAnnotation (content .ObjectMeta , utils .AnnVolumeSnapshotBeingDeleted ) {
578
619
return true
579
620
}
580
621
return false
581
622
}
623
+
624
+ // setAnnVolumeSnapshotBeingCreated sets VolumeSnapshotBeingCreated annotation
625
+ // on VolumeSnapshotContent
626
+ // If beingCreated is true, it indicates snapshot is being created
627
+ // If beingCreated if false, it indicates CreateSnapshot CSI RPC returns
628
+ // success or failure
629
+ func (ctrl * csiSnapshotSideCarController ) setAnnVolumeSnapshotBeingCreated (content * crdv1.VolumeSnapshotContent , annBeingCreated string ) error {
630
+ // Set AnnVolumeSnapshotBeingCreated if it is not set yet or if it is
631
+ // set but has a different value
632
+ if ! metav1 .HasAnnotation (content .ObjectMeta , utils .AnnVolumeSnapshotBeingCreated ) || content .ObjectMeta .Annotations [utils .AnnVolumeSnapshotBeingCreated ] != annBeingCreated {
633
+ klog .V (5 ).Infof ("setAnnVolumeSnapshotBeingCreated: set annotation [%s] on content [%s]." , utils .AnnVolumeSnapshotBeingCreated , content .Name )
634
+ metav1 .SetMetaDataAnnotation (& content .ObjectMeta , utils .AnnVolumeSnapshotBeingCreated , annBeingCreated )
635
+
636
+ updateContent , err := ctrl .clientset .SnapshotV1beta1 ().VolumeSnapshotContents ().Update (content )
637
+ if err != nil {
638
+ return newControllerUpdateError (content .Name , err .Error ())
639
+ }
640
+ // update content if update is successful
641
+ content = updateContent
642
+
643
+ _ , err = ctrl .storeContentUpdate (content )
644
+ if err != nil {
645
+ klog .V (4 ).Infof ("setAnnVolumeSnapshotBeingCreated for content [%s]: cannot update internal cache %v" , content .Name , err )
646
+ return err
647
+ }
648
+ klog .V (5 ).Infof ("setAnnVolumeSnapshotBeingCreated: volume snapshot content %+v" , content )
649
+ }
650
+ return nil
651
+ }
0 commit comments