@@ -278,29 +278,21 @@ func (ctrl *csiSnapshotSideCarController) checkandUpdateContentStatusOperation(c
278278 }
279279 driverName = content .Spec .Driver
280280 snapshotID = * content .Spec .Source .SnapshotHandle
281- } else {
282- class , snapshotterCredentials , err := ctrl .getCSISnapshotInput (content )
283- if err != nil {
284- return nil , fmt .Errorf ("failed to get input parameters to create snapshot %s: %q" , content .Name , err )
281+
282+ klog .V (5 ).Infof ("checkandUpdateContentStatusOperation: driver %s, snapshotId %s, creationTime %v, size %d, readyToUse %t" , driverName , snapshotID , creationTime , size , readyToUse )
283+
284+ if creationTime .IsZero () {
285+ creationTime = time .Now ()
285286 }
286287
287- driverName , snapshotID , creationTime , size , readyToUse , err = ctrl .handler . CreateSnapshot (content , class . Parameters , snapshotterCredentials )
288+ updatedContent , err : = ctrl .updateSnapshotContentStatus (content , snapshotID , readyToUse , creationTime . UnixNano (), size )
288289 if err != nil {
289- klog .Errorf ("checkandUpdateContentStatusOperation: failed to call create snapshot to check whether the snapshot is ready to use %q" , err )
290290 return nil , err
291291 }
292+ return updatedContent , nil
293+ } else {
294+ return ctrl .createSnapshotOperation (content )
292295 }
293- klog .V (5 ).Infof ("checkandUpdateContentStatusOperation: driver %s, snapshotId %s, creationTime %v, size %d, readyToUse %t" , driverName , snapshotID , creationTime , size , readyToUse )
294-
295- if creationTime .IsZero () {
296- creationTime = time .Now ()
297- }
298-
299- updateContent , err := ctrl .updateSnapshotContentStatus (content , snapshotID , readyToUse , creationTime .UnixNano (), size )
300- if err != nil {
301- return nil , err
302- }
303- return updateContent , nil
304296}
305297
306298// The function goes through the snapshot creation process.
@@ -335,16 +327,13 @@ func (ctrl *csiSnapshotSideCarController) createSnapshotOperation(content *crdv1
335327 driverName , snapshotID , creationTime , size , readyToUse , err := ctrl .handler .CreateSnapshot (content , class .Parameters , snapshotterCredentials )
336328 if err != nil {
337329 // NOTE(xyang): handle create timeout
338- // If it is not a timeout error, remove annotation to indicate
330+ // If it is a final error, remove annotation to indicate
339331 // storage system has responded with an error
340332 klog .Infof ("createSnapshotOperation: CreateSnapshot for content %s returned error: %v" , content .Name , err )
341- if e , ok := status .FromError (err ); ok {
342- klog .Infof ("createSnapshotOperation: CreateSnapshot for content %s error status: %+v" , content .Name , e )
343- if e .Code () != codes .DeadlineExceeded {
344- err = ctrl .removeAnnVolumeSnapshotBeingCreated (content )
345- if err != nil {
346- return nil , fmt .Errorf ("failed to remove VolumeSnapshotBeingCreated annotation from the content %s: %q" , content .Name , err )
347- }
333+ if isFinalError (err ) {
334+ err = ctrl .removeAnnVolumeSnapshotBeingCreated (content )
335+ if err != nil {
336+ return nil , fmt .Errorf ("failed to remove VolumeSnapshotBeingCreated annotation from the content %s: %q" , content .Name , err )
348337 }
349338 }
350339
@@ -353,8 +342,11 @@ func (ctrl *csiSnapshotSideCarController) createSnapshotOperation(content *crdv1
353342
354343 klog .V (5 ).Infof ("Created snapshot: driver %s, snapshotId %s, creationTime %v, size %d, readyToUse %t" , driverName , snapshotID , creationTime , size , readyToUse )
355344
356- timestamp := creationTime .UnixNano ()
357- newContent , err := ctrl .updateSnapshotContentStatus (content , snapshotID , readyToUse , timestamp , size )
345+ if creationTime .IsZero () {
346+ creationTime = time .Now ()
347+ }
348+
349+ newContent , err := ctrl .updateSnapshotContentStatus (content , snapshotID , readyToUse , creationTime .UnixNano (), size )
358350 if err != nil {
359351 strerr := fmt .Sprintf ("error updating volume snapshot content status for snapshot %s: %v." , content .Name , err )
360352 klog .Error (strerr )
@@ -614,12 +606,12 @@ func (ctrl *csiSnapshotSideCarController) setAnnVolumeSnapshotBeingCreated(conte
614606 contentClone := content .DeepCopy ()
615607 metav1 .SetMetaDataAnnotation (& contentClone .ObjectMeta , utils .AnnVolumeSnapshotBeingCreated , "yes" )
616608
617- updateContent , err := ctrl .clientset .SnapshotV1beta1 ().VolumeSnapshotContents ().Update (contentClone )
609+ updatedContent , err := ctrl .clientset .SnapshotV1beta1 ().VolumeSnapshotContents ().Update (contentClone )
618610 if err != nil {
619611 return newControllerUpdateError (content .Name , err .Error ())
620612 }
621613 // update content if update is successful
622- content = updateContent
614+ content = updatedContent
623615
624616 _ , err = ctrl .storeContentUpdate (content )
625617 if err != nil {
@@ -641,12 +633,12 @@ func (ctrl csiSnapshotSideCarController) removeAnnVolumeSnapshotBeingCreated(con
641633 contentClone := content .DeepCopy ()
642634 delete (contentClone .ObjectMeta .Annotations , utils .AnnVolumeSnapshotBeingCreated )
643635
644- updateContent , err := ctrl .clientset .SnapshotV1beta1 ().VolumeSnapshotContents ().Update (contentClone )
636+ updatedContent , err := ctrl .clientset .SnapshotV1beta1 ().VolumeSnapshotContents ().Update (contentClone )
645637 if err != nil {
646638 return newControllerUpdateError (content .Name , err .Error ())
647639 }
648640 // update content if update is successful
649- content = updateContent
641+ content = updatedContent
650642
651643 klog .V (5 ).Infof ("Removed VolumeSnapshotBeingCreated annotation from volume snapshot content %s" , content .Name )
652644 _ , err = ctrl .storeContentUpdate (content )
@@ -655,3 +647,28 @@ func (ctrl csiSnapshotSideCarController) removeAnnVolumeSnapshotBeingCreated(con
655647 }
656648 return nil
657649}
650+
651+ // This function checks if the error is final
652+ func isFinalError (err error ) bool {
653+ // Sources:
654+ // https://github.com/grpc/grpc/blob/master/doc/statuscodes.md
655+ // https://github.com/container-storage-interface/spec/blob/master/spec.md
656+ st , ok := status .FromError (err )
657+ if ! ok {
658+ // This is not gRPC error. The operation must have failed before gRPC
659+ // method was called, otherwise we would get gRPC error.
660+ // We don't know if any previous CreateSnapshot is in progress, be on the safe side.
661+ return false
662+ }
663+ switch st .Code () {
664+ case codes .Canceled , // gRPC: Client Application cancelled the request
665+ codes .DeadlineExceeded , // gRPC: Timeout
666+ codes .Unavailable , // gRPC: Server shutting down, TCP connection broken - previous CreateSnapshot() may be still in progress.
667+ codes .ResourceExhausted , // gRPC: Server temporarily out of resources - previous CreateSnapshot() may be still in progress.
668+ codes .Aborted : // CSI: Operation pending for Snapshot
669+ return false
670+ }
671+ // All other errors mean that creating snapshot either did not
672+ // even start or failed. It is for sure not in progress.
673+ return true
674+ }
0 commit comments