@@ -130,6 +130,7 @@ var _ = ginkgo.Describe("nvmeof", func() {
130130 ginkgo .Context ("Test NVMe CSI" , ginkgo .Ordered , func () {
131131
132132 pvcPath := nvmeofExamplePath + "pvc.yaml"
133+ pvcClonePath := nvmeofExamplePath + "pvc-clone.yaml"
133134 appPath := nvmeofExamplePath + "pod.yaml"
134135 rawPvcPath := nvmeofExamplePath + "raw-block-pvc.yaml"
135136 rawAppPath := nvmeofExamplePath + "raw-block-pod.yaml"
@@ -432,5 +433,70 @@ var _ = ginkgo.Describe("nvmeof", func() {
432433 validateRBDImageCount (f , 0 , nvmeofPool )
433434 validateOmapCount (f , 0 , rbdType , nvmeofPool , volumesType )
434435 })
436+
437+ ginkgo .It ("Cloning nvmeof PVC" , func () {
438+ // This test validates cloning of NVMe-oF PVCs.
439+ //
440+ // Test flow:
441+ // 1. Create a source PVC and bind it to an app
442+ // 2. Create a clone of the source PVC and bind it to an app
443+ // 3. Delete the clone app and PVC
444+ // 4. Delete the source app and PVC
445+
446+ ginkgo .By ("Creating a source PVC" )
447+ sourcePVC , err := loadPVC (pvcPath )
448+ Expect (err ).ShouldNot (HaveOccurred ())
449+
450+ sourcePVC .Namespace = f .UniqueName
451+ sourcePVC .Spec .StorageClassName = & nvmeofStorageClass
452+
453+ err = createPVCAndvalidatePV (f .ClientSet , sourcePVC , deployTimeout )
454+ Expect (err ).ShouldNot (HaveOccurred ())
455+
456+ ginkgo .By ("Binding source PVC to an application" )
457+ sourceApp , err := loadApp (appPath )
458+ Expect (err ).ShouldNot (HaveOccurred ())
459+
460+ sourceApp .Namespace = f .UniqueName
461+ sourceApp .Spec .Volumes [0 ].PersistentVolumeClaim .ClaimName = sourcePVC .Name
462+
463+ err = createApp (f .ClientSet , sourceApp , deployTimeout )
464+ Expect (err ).ShouldNot (HaveOccurred ())
465+
466+ ginkgo .By ("Creating a clone of the source PVC" )
467+ // Load clone PVC template with DataSource already configured
468+ clonePVC , err := loadPVC (pvcClonePath )
469+ Expect (err ).ShouldNot (HaveOccurred ())
470+
471+ clonePVC .Namespace = f .UniqueName
472+ clonePVC .Spec .StorageClassName = & nvmeofStorageClass
473+ clonePVC .Spec .DataSource .Name = sourcePVC .Name
474+
475+ err = createPVCAndvalidatePV (f .ClientSet , clonePVC , deployTimeout )
476+ Expect (err ).ShouldNot (HaveOccurred ())
477+
478+ ginkgo .By ("Binding clone PVC to an application" )
479+ cloneApp , err := loadApp (appPath )
480+ Expect (err ).ShouldNot (HaveOccurred ())
481+
482+ cloneApp .Name = sourceApp .Name + "-clone"
483+ cloneApp .Namespace = f .UniqueName
484+ cloneApp .Spec .Volumes [0 ].PersistentVolumeClaim .ClaimName = clonePVC .Name
485+
486+ err = createApp (f .ClientSet , cloneApp , deployTimeout )
487+ Expect (err ).ShouldNot (HaveOccurred ())
488+
489+ ginkgo .By ("Deleting the clone application and PVC" )
490+ err = deletePVCAndApp ("" , f , clonePVC , cloneApp )
491+ Expect (err ).ShouldNot (HaveOccurred ())
492+
493+ ginkgo .By ("Deleting the source application and PVC" )
494+ err = deletePVCAndApp ("" , f , sourcePVC , sourceApp )
495+ Expect (err ).ShouldNot (HaveOccurred ())
496+
497+ // validate all backend rbd images are cleaned up
498+ validateRBDImageCount (f , 0 , nvmeofPool )
499+ validateOmapCount (f , 0 , rbdType , nvmeofPool , volumesType )
500+ })
435501 })
436502})
0 commit comments