Skip to content

Commit 8069960

Browse files
committed
Add AnnVolumeSnapshotBeingCreated
1 parent 883842f commit 8069960

File tree

2 files changed

+87
-1
lines changed

2 files changed

+87
-1
lines changed

pkg/sidecar-controller/snapshot_controller.go

+71-1
Original file line numberDiff line numberDiff line change
@@ -331,14 +331,45 @@ func (ctrl *csiSnapshotSideCarController) createSnapshotOperation(content *crdv1
331331
return nil, fmt.Errorf("failed to get input parameters to create snapshot for content %s: %q", content.Name, err)
332332
}
333333

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+
334346
driverName, snapshotID, creationTime, size, readyToUse, err := ctrl.handler.CreateSnapshot(content, class.Parameters, snapshotterCredentials)
335347
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+
336359
return nil, fmt.Errorf("failed to take snapshot of the volume, %s: %q", *content.Spec.Source.VolumeHandle, err)
337360
}
338361
if driverName != class.Driver {
339362
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)
340363
}
341364

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+
342373
klog.V(5).Infof("Created snapshot: driver %s, snapshotId %s, creationTime %v, size %d, readyToUse %t", driverName, snapshotID, creationTime, size, readyToUse)
343374

344375
timestamp := creationTime.UnixNano()
@@ -573,9 +604,48 @@ func (ctrl *csiSnapshotSideCarController) shouldDelete(content *crdv1.VolumeSnap
573604
if content.Spec.Source.SnapshotHandle != nil && content.Spec.VolumeSnapshotRef.UID == "" {
574605
return true
575606
}
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
577618
if metav1.HasAnnotation(content.ObjectMeta, utils.AnnVolumeSnapshotBeingDeleted) {
578619
return true
579620
}
580621
return false
581622
}
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+
}

pkg/utils/util.go

+16
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,22 @@ const (
7878
// backing the snapshot content.
7979
AnnVolumeSnapshotBeingDeleted = "snapshot.storage.kubernetes.io/volumesnapshot-being-deleted"
8080

81+
// AnnVolumeSnapshotBeingCreated annotation applies to VolumeSnapshotContents.
82+
// If it is set and value is "yes", it indicates that the csi-snapshotter
83+
// sidecar has sent the create snapshot request to the storage system and
84+
// is waiting for a response of success or failure.
85+
// This annotation will be set to "no" if the driver's CreateSnapshot
86+
// CSI function returns success or failure. If the create snapshot
87+
// request times out, retry will happen and the annotation value will
88+
// stay as "yes".
89+
// This only applies to dynamic provisioning of snapshots because
90+
// the create snapshot CSI method will not be called for pre-provisioned
91+
// snapshots.
92+
AnnVolumeSnapshotBeingCreated = "snapshot.storage.kubernetes.io/volumesnapshot-being-created"
93+
// VolumeSnapshotBeingCreated annotation values can be "yes" or "no"
94+
AnnVolumeSnapshotBeingCreated_Yes = "yes"
95+
AnnVolumeSnapshotBeingCreated_No = "no"
96+
8197
// Annotation for secret name and namespace will be added to the content
8298
// and used at snapshot content deletion time.
8399
AnnDeletionSecretRefName = "snapshot.storage.kubernetes.io/deletion-secret-name"

0 commit comments

Comments
 (0)