@@ -33,6 +33,7 @@ import (
3333	klog "k8s.io/klog/v2" 
3434
3535	crdv1 "github.com/kubernetes-csi/external-snapshotter/client/v3/apis/volumesnapshot/v1beta1" 
36+ 	"github.com/kubernetes-csi/external-snapshotter/v3/pkg/metrics" 
3637	"github.com/kubernetes-csi/external-snapshotter/v3/pkg/utils" 
3738)
3839
@@ -236,6 +237,20 @@ func (ctrl *csiSnapshotCommonController) syncSnapshot(snapshot *crdv1.VolumeSnap
236237// 2. Call checkandRemoveSnapshotFinalizersAndCheckandDeleteContent() with information obtained from step 1. This function name is very long but the name suggests what it does. It determines whether to remove finalizers on snapshot and whether to delete content. 
237238func  (ctrl  * csiSnapshotCommonController ) processSnapshotWithDeletionTimestamp (snapshot  * crdv1.VolumeSnapshot ) error  {
238239	klog .V (5 ).Infof ("processSnapshotWithDeletionTimestamp VolumeSnapshot[%s]: %s" , utils .SnapshotKey (snapshot ), utils .GetSnapshotStatusForLogging (snapshot ))
240+ 	driverName , err  :=  ctrl .getSnapshotDriverName (snapshot )
241+ 	if  err  !=  nil  {
242+ 		klog .Errorf ("failed to getSnapshotDriverName while recording metrics for snapshot %q: %v" , utils .SnapshotKey (snapshot ), err )
243+ 	}
244+ 
245+ 	snapshotProvisionType  :=  metrics .DynamicSnapshotType 
246+ 	if  snapshot .Spec .Source .VolumeSnapshotContentName  !=  nil  {
247+ 		snapshotProvisionType  =  metrics .PreProvisionedSnapshotType 
248+ 	}
249+ 
250+ 	// Processing delete, start operation metric 
251+ 	deleteOperationKey  :=  metrics .NewOperationKey (metrics .DeleteSnapshotOperationName , snapshot .UID )
252+ 	deleteOperationValue  :=  metrics .NewOperationValue (driverName , snapshotProvisionType )
253+ 	ctrl .metricsManager .OperationStart (deleteOperationKey , deleteOperationValue )
239254
240255	var  contentName  string 
241256	if  snapshot .Status  !=  nil  &&  snapshot .Status .BoundVolumeSnapshotContentName  !=  nil  {
@@ -270,6 +285,7 @@ func (ctrl *csiSnapshotCommonController) processSnapshotWithDeletionTimestamp(sn
270285	}
271286
272287	klog .V (5 ).Infof ("processSnapshotWithDeletionTimestamp[%s]: delete snapshot content and remove finalizer from snapshot if needed" , utils .SnapshotKey (snapshot ))
288+ 
273289	return  ctrl .checkandRemoveSnapshotFinalizersAndCheckandDeleteContent (snapshot , content , deleteContent )
274290}
275291
@@ -389,6 +405,7 @@ func (ctrl *csiSnapshotCommonController) syncReadySnapshot(snapshot *crdv1.Volum
389405		// snapshot is bound but content is not pointing to the snapshot 
390406		return  ctrl .updateSnapshotErrorStatusWithEvent (snapshot , v1 .EventTypeWarning , "SnapshotMisbound" , "VolumeSnapshotContent is not bound to the VolumeSnapshot correctly" )
391407	}
408+ 
392409	// everything is verified, return 
393410	return  nil 
394411}
@@ -397,20 +414,45 @@ func (ctrl *csiSnapshotCommonController) syncReadySnapshot(snapshot *crdv1.Volum
397414func  (ctrl  * csiSnapshotCommonController ) syncUnreadySnapshot (snapshot  * crdv1.VolumeSnapshot ) error  {
398415	uniqueSnapshotName  :=  utils .SnapshotKey (snapshot )
399416	klog .V (5 ).Infof ("syncUnreadySnapshot %s" , uniqueSnapshotName )
417+ 	driverName , err  :=  ctrl .getSnapshotDriverName (snapshot )
418+ 	if  err  !=  nil  {
419+ 		klog .Errorf ("failed to getSnapshotDriverName while recording metrics for snapshot %q: %s" , utils .SnapshotKey (snapshot ), err )
420+ 	}
421+ 
422+ 	snapshotProvisionType  :=  metrics .DynamicSnapshotType 
423+ 	if  snapshot .Spec .Source .VolumeSnapshotContentName  !=  nil  {
424+ 		snapshotProvisionType  =  metrics .PreProvisionedSnapshotType 
425+ 	}
426+ 
427+ 	// Start metrics operations 
428+ 	if  ! utils .IsSnapshotCreated (snapshot ) {
429+ 		// Only start CreateSnapshot operation if the snapshot has not been cut 
430+ 		ctrl .metricsManager .OperationStart (
431+ 			metrics .NewOperationKey (metrics .CreateSnapshotOperationName , snapshot .UID ),
432+ 			metrics .NewOperationValue (driverName , snapshotProvisionType ),
433+ 		)
434+ 	}
435+ 	ctrl .metricsManager .OperationStart (
436+ 		metrics .NewOperationKey (metrics .CreateSnapshotAndReadyOperationName , snapshot .UID ),
437+ 		metrics .NewOperationValue (driverName , snapshotProvisionType ),
438+ 	)
400439
401440	// Pre-provisioned snapshot 
402441	if  snapshot .Spec .Source .VolumeSnapshotContentName  !=  nil  {
403442		content , err  :=  ctrl .getPreprovisionedContentFromStore (snapshot )
404443		if  err  !=  nil  {
405444			return  err 
406445		}
446+ 
407447		// if no content found yet, update status and return 
408448		if  content  ==  nil  {
409449			// can not find the desired VolumeSnapshotContent from cache store 
410450			ctrl .updateSnapshotErrorStatusWithEvent (snapshot , v1 .EventTypeWarning , "SnapshotContentMissing" , "VolumeSnapshotContent is missing" )
411451			klog .V (4 ).Infof ("syncUnreadySnapshot[%s]: snapshot content %q requested but not found, will try again" , utils .SnapshotKey (snapshot ), * snapshot .Spec .Source .VolumeSnapshotContentName )
452+ 
412453			return  fmt .Errorf ("snapshot %s requests an non-existing content %s" , utils .SnapshotKey (snapshot ), * snapshot .Spec .Source .VolumeSnapshotContentName )
413454		}
455+ 
414456		// Set VolumeSnapshotRef UID 
415457		newContent , err  :=  ctrl .checkandBindSnapshotContent (snapshot , content )
416458		if  err  !=  nil  {
@@ -427,8 +469,10 @@ func (ctrl *csiSnapshotCommonController) syncUnreadySnapshot(snapshot *crdv1.Vol
427469			ctrl .updateSnapshotErrorStatusWithEvent (snapshot , v1 .EventTypeWarning , "SnapshotStatusUpdateFailed" , fmt .Sprintf ("Snapshot status update failed, %v" , err ))
428470			return  err 
429471		}
472+ 
430473		return  nil 
431474	}
475+ 
432476	// snapshot.Spec.Source.VolumeSnapshotContentName == nil - dynamically creating snapshot 
433477	klog .V (5 ).Infof ("getDynamicallyProvisionedContentFromStore for snapshot %s" , uniqueSnapshotName )
434478	contentObj , err  :=  ctrl .getDynamicallyProvisionedContentFromStore (snapshot )
@@ -1095,10 +1139,30 @@ func (ctrl *csiSnapshotCommonController) updateSnapshotStatus(snapshot *crdv1.Vo
10951139	if  updated  {
10961140		snapshotClone  :=  snapshotObj .DeepCopy ()
10971141		snapshotClone .Status  =  newStatus 
1142+ 
1143+ 		// We need to record metrics before updating the status due to a bug causing cache entries after a failed UpdateStatus call. 
1144+ 		// Must meet the following criteria to emit a successful CreateSnapshot status 
1145+ 		// 1. Previous status was nil OR Previous status had a nil CreationTime 
1146+ 		// 2. New status must be non-nil with a non-nil CreationTime 
1147+ 		driverName  :=  content .Spec .Driver 
1148+ 		createOperationKey  :=  metrics .NewOperationKey (metrics .CreateSnapshotOperationName , snapshot .UID )
1149+ 		if  ! utils .IsSnapshotCreated (snapshotObj ) &&  utils .IsSnapshotCreated (snapshotClone ) {
1150+ 			ctrl .metricsManager .RecordMetrics (createOperationKey , metrics .NewSnapshotOperationStatus (metrics .SnapshotStatusTypeSuccess ), driverName )
1151+ 		}
1152+ 
1153+ 		// Must meet the following criteria to emit a successful CreateSnapshotAndReady status 
1154+ 		// 1. Previous status was nil OR Previous status had a nil ReadyToUse OR Previous status had a false ReadyToUse 
1155+ 		// 2. New status must be non-nil with a ReadyToUse as true 
1156+ 		if  ! utils .IsSnapshotReady (snapshotObj ) &&  utils .IsSnapshotReady (snapshotClone ) {
1157+ 			createAndReadyOperation  :=  metrics .NewOperationKey (metrics .CreateSnapshotAndReadyOperationName , snapshot .UID )
1158+ 			ctrl .metricsManager .RecordMetrics (createAndReadyOperation , metrics .NewSnapshotOperationStatus (metrics .SnapshotStatusTypeSuccess ), driverName )
1159+ 		}
1160+ 
10981161		newSnapshotObj , err  :=  ctrl .clientset .SnapshotV1beta1 ().VolumeSnapshots (snapshotClone .Namespace ).UpdateStatus (context .TODO (), snapshotClone , metav1.UpdateOptions {})
10991162		if  err  !=  nil  {
11001163			return  nil , newControllerUpdateError (utils .SnapshotKey (snapshot ), err .Error ())
11011164		}
1165+ 
11021166		return  newSnapshotObj , nil 
11031167	}
11041168
@@ -1186,8 +1250,49 @@ func (ctrl *csiSnapshotCommonController) getSnapshotClass(className string) (*cr
11861250	return  class , nil 
11871251}
11881252
1189- // SetDefaultSnapshotClass is a helper function to figure out the default snapshot class from 
1190- // PVC/PV StorageClass and update VolumeSnapshot with this snapshot class name. 
1253+ // getSnapshotDriverName is a helper function to get snapshot driver from the VolumeSnapshot. 
1254+ // We try to get the driverName in multiple ways, as snapshot controller metrics depend on the correct driverName. 
1255+ func  (ctrl  * csiSnapshotCommonController ) getSnapshotDriverName (vs  * crdv1.VolumeSnapshot ) (string , error ) {
1256+ 	klog .V (5 ).Infof ("getSnapshotDriverName: VolumeSnapshot[%s]" , vs .Name )
1257+ 	var  driverName  string 
1258+ 
1259+ 	// Pre-Provisioned snapshots have contentName as source 
1260+ 	var  contentName  string 
1261+ 	if  vs .Spec .Source .VolumeSnapshotContentName  !=  nil  {
1262+ 		contentName  =  * vs .Spec .Source .VolumeSnapshotContentName 
1263+ 	}
1264+ 
1265+ 	// Get Driver name from SnapshotContent if we found a contentName 
1266+ 	if  contentName  !=  ""  {
1267+ 		content , err  :=  ctrl .contentLister .Get (contentName )
1268+ 		if  err  !=  nil  {
1269+ 			klog .Errorf ("getSnapshotDriverName: failed to get snapshotContent: %v" , contentName )
1270+ 		} else  {
1271+ 			driverName  =  content .Spec .Driver 
1272+ 		}
1273+ 
1274+ 		if  driverName  !=  ""  {
1275+ 			return  driverName , nil 
1276+ 		}
1277+ 	}
1278+ 
1279+ 	// Dynamic snapshots will have a snapshotclass with a driver 
1280+ 	if  vs .Spec .VolumeSnapshotClassName  !=  nil  {
1281+ 		class , err  :=  ctrl .getSnapshotClass (* vs .Spec .VolumeSnapshotClassName )
1282+ 		if  err  !=  nil  {
1283+ 			klog .Errorf ("getSnapshotDriverName: failed to get snapshotClass: %v" , * vs .Spec .VolumeSnapshotClassName )
1284+ 		} else  {
1285+ 			driverName  =  class .Driver 
1286+ 		}
1287+ 	}
1288+ 
1289+ 	return  driverName , nil 
1290+ }
1291+ 
1292+ // SetDefaultSnapshotClass is a helper function to figure out the default snapshot class. 
1293+ // For pre-provisioned case, it's an no-op. 
1294+ // For dynamic provisioning, it gets the default SnapshotClasses in the system if there is any(could be multiple), 
1295+ // and finds the one with the same CSI Driver as the PV from which a snapshot will be taken. 
11911296func  (ctrl  * csiSnapshotCommonController ) SetDefaultSnapshotClass (snapshot  * crdv1.VolumeSnapshot ) (* crdv1.VolumeSnapshotClass , * crdv1.VolumeSnapshot , error ) {
11921297	klog .V (5 ).Infof ("SetDefaultSnapshotClass for snapshot [%s]" , snapshot .Name )
11931298
0 commit comments