Skip to content

Commit

Permalink
fix: Use storage class from annotation for host-assisted PVC operation
Browse files Browse the repository at this point in the history
modify the `getStorageClassCorrespondingToSnapClass` function to use the storage class from the annotation for host-assisted PVC operations.

Fixes: #3530

Signed-off-by: Sibasish Behera <[email protected]>
  • Loading branch information
TheRealSibasishBehera committed Jan 8, 2025
1 parent fe46b62 commit dcf7cfb
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 2 deletions.
3 changes: 3 additions & 0 deletions pkg/controller/common/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,9 @@ const (

// AnnSourceVolumeMode is the volume mode of the source PVC specified as an annotation on snapshots
AnnSourceVolumeMode = AnnAPIGroup + "/storage.import.sourceVolumeMode"
// AnnSnapshotRestoreStorageClass indicates the storage class to use for restoring snapshots.
// This annotation should be added to DataVolumes for the temporary host-assisted source PVC.
AnnSnapshotRestoreStorageClass = AnnAPIGroup + "/snapshot.restore.storageClass"

// AnnOpenShiftImageLookup is the annotation for OpenShift image stream lookup
AnnOpenShiftImageLookup = "alpha.image.policy.openshift.io/resolve-names"
Expand Down
9 changes: 7 additions & 2 deletions pkg/controller/datavolume/snapshot-clone-controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@ func (r *SnapshotCloneReconciler) createTempHostAssistedSourcePvc(dv *cdiv1.Data
if err := r.client.Get(context.TODO(), types.NamespacedName{Name: *snapshot.Spec.VolumeSnapshotClassName}, vsc); err != nil {
return err
}
sc, err := r.getStorageClassCorrespondingToSnapClass(vsc.Driver)
sc, err := r.getStorageClassCorrespondingToSnapClass(dv, vsc.Driver)
if err != nil {
return err
}
Expand Down Expand Up @@ -450,7 +450,12 @@ func (r *SnapshotCloneReconciler) createTempHostAssistedSourcePvc(dv *cdiv1.Data
return nil
}

func (r *SnapshotCloneReconciler) getStorageClassCorrespondingToSnapClass(driver string) (string, error) {
func (r *SnapshotCloneReconciler) getStorageClassCorrespondingToSnapClass(dv *cdiv1.DataVolume, driver string) (string, error) {
if sc, found := dv.Annotations[cc.AnnSnapshotRestoreStorageClass]; found {
r.log.V(3).Info("Using storage class from annotation for host-assisted source PVC operation", "storageClass.Name", sc)
return sc, nil
}

matches := []storagev1.StorageClass{}

storageClasses := &storagev1.StorageClassList{}
Expand Down
41 changes: 41 additions & 0 deletions pkg/controller/datavolume/snapshot-clone-controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,47 @@ var _ = Describe("All DataVolume Tests", func() {
Expect(err).ToNot(HaveOccurred())
})

It("Should use the storage class used in annotation AnnSnapshotRestoreStorageClass if present", func() {
dv := newCloneFromSnapshotDataVolume("test-dv")
scName := "testsc"
expectedSnapshotClass := "snap-class"
sc := CreateStorageClassWithProvisioner(scName, map[string]string{
AnnDefaultStorageClass: "true",
}, map[string]string{}, "csi-plugin")
targetScName := "targetsc"
scSameProvisioner := sc.DeepCopy()
scSameProvisioner.Name = "same-provisioner-as-source-sc"
scUsedInAnnotation := sc.DeepCopy()
scUsedInAnnotation.Name = "sc-used-in-annotation"
dv.Annotations[AnnSnapshotRestoreStorageClass] = scUsedInAnnotation.Name

tsc := CreateStorageClassWithProvisioner(targetScName, map[string]string{}, map[string]string{}, "another-csi-plugin")
sp := createStorageProfile(scName, []corev1.PersistentVolumeAccessMode{corev1.ReadOnlyMany}, BlockMode)
sp2 := createStorageProfile(targetScName, []corev1.PersistentVolumeAccessMode{corev1.ReadOnlyMany}, BlockMode)
sp3 := createStorageProfile(scSameProvisioner.Name, []corev1.PersistentVolumeAccessMode{corev1.ReadOnlyMany}, BlockMode)
sp4 := createStorageProfile(scUsedInAnnotation.Name, []corev1.PersistentVolumeAccessMode{corev1.ReadOnlyMany}, BlockMode)
dv.Spec.PVC.StorageClassName = &targetScName
snapshot := createSnapshotInVolumeSnapshotClass("test-snap", metav1.NamespaceDefault, &expectedSnapshotClass, nil, nil, true)
snapClass := createSnapshotClass(expectedSnapshotClass, nil, "csi-plugin")
reconciler = createSnapshotCloneReconciler(sc, scSameProvisioner, tsc, sp, sp2, sp3, sp4, dv, snapshot, snapClass, createDefaultVolumeSnapshotContent(), createVolumeSnapshotContentCrd(), createVolumeSnapshotClassCrd(), createVolumeSnapshotCrd())
_, err := reconciler.Reconcile(context.TODO(), reconcile.Request{NamespacedName: types.NamespacedName{Name: "test-dv", Namespace: metav1.NamespaceDefault}})
Expect(err).ToNot(HaveOccurred())
By("Verifying that temp host assisted source PVC is being created")
pvc := &corev1.PersistentVolumeClaim{}
tempPvcName := getTempHostAssistedSourcePvcName(dv)
err = reconciler.client.Get(context.TODO(), types.NamespacedName{Namespace: snapshot.Namespace, Name: tempPvcName}, pvc)
Expect(err).ToNot(HaveOccurred())
Expect(pvc.Labels[common.CDIComponentLabel]).To(Equal("cdi-clone-from-snapshot-source-host-assisted-fallback-pvc"))
Expect(pvc.Labels[common.AppKubernetesPartOfLabel]).To(Equal("testing"))
Expect(*pvc.Spec.StorageClassName).To(Equal(scUsedInAnnotation.Name))
By("Verifying that target host assisted PVC is being created")
err = reconciler.client.Get(context.TODO(), types.NamespacedName{Namespace: dv.Namespace, Name: dv.Name}, pvc)
Expect(err).ToNot(HaveOccurred())
Expect(pvc.Labels[common.AppKubernetesPartOfLabel]).To(Equal("testing"))
Expect(pvc.Annotations[AnnCloneRequest]).To(Equal(fmt.Sprintf("%s/%s", snapshot.Namespace, tempPvcName)))
Expect(*pvc.Spec.StorageClassName).To(Equal(targetScName))
})

It("Should clean up host assisted source temp PVC when done", func() {
dv := newCloneFromSnapshotDataVolume("test-dv")
dv.Status.Phase = cdiv1.Succeeded
Expand Down

0 comments on commit dcf7cfb

Please sign in to comment.