diff --git a/e2e/rbd.go b/e2e/rbd.go index c8b71817b..d07370e39 100644 --- a/e2e/rbd.go +++ b/e2e/rbd.go @@ -3552,7 +3552,7 @@ var _ = Describe("RBD", func() { validateRBDImageCount(f, 1, defaultRBDPool) validateOmapCount(f, 1, rbdType, defaultRBDPool, volumesType) for i := 0; i < snapChainDepth; i++ { - var pvcClone *v1.PersistentVolumeClaim + var pvcClone, smartClonePVC *v1.PersistentVolumeClaim snap := getSnapshot(snapshotPath) snap.Name = fmt.Sprintf("%s-%d", snap.Name, i) snap.Namespace = f.UniqueName @@ -3609,6 +3609,41 @@ var _ = Describe("RBD", func() { validateOmapCount(f, 1, rbdType, defaultRBDPool, volumesType) validateOmapCount(f, 0, rbdType, defaultRBDPool, snapsType) + // create pvc-pvc clone to validate pvc-pvc clone creation + // of child PVC created from a snapshot which no longer exits. + // Snapshot-> restore PVC -> delete Snapshot -> PVC-PVC clone. + smartClonePVC, err = loadPVC(pvcSmartClonePath) + if err != nil { + framework.Failf("failed to load smart clone PVC: %v", err) + } + + smartClonePVC.Name = fmt.Sprintf("%s-%d", smartClonePVC.Name, i) + smartClonePVC.Namespace = f.UniqueName + smartClonePVC.Spec.DataSource.Name = pvcClone.Name + err = createPVCAndvalidatePV(f.ClientSet, smartClonePVC, deployTimeout) + if err != nil { + framework.Failf("failed to create smart clone PVC %q: %v", + smartClonePVC.Name, err) + } + + // validate created backend rbd images = clone + smart clone + temp image + totalImages = 3 + validateRBDImageCount(f, totalImages, defaultRBDPool) + validateOmapCount(f, 2, rbdType, defaultRBDPool, volumesType) + validateOmapCount(f, 0, rbdType, defaultRBDPool, snapsType) + + err = deletePVCAndValidatePV(f.ClientSet, smartClonePVC, deployTimeout) + if err != nil { + framework.Failf("failed to delete smart clone PVC %q: %v", + smartClonePVC.Name, err) + } + + // validate created backend rbd images = clone + totalImages = 1 + validateRBDImageCount(f, totalImages, defaultRBDPool) + validateOmapCount(f, 1, rbdType, defaultRBDPool, volumesType) + validateOmapCount(f, 0, rbdType, defaultRBDPool, snapsType) + app.Spec.Volumes[0].PersistentVolumeClaim.ClaimName = pvcClone.Name // create application err = createApp(f.ClientSet, app, deployTimeout) diff --git a/internal/rbd/rbd_util.go b/internal/rbd/rbd_util.go index 31b330b4d..b654db4d2 100644 --- a/internal/rbd/rbd_util.go +++ b/internal/rbd/rbd_util.go @@ -146,6 +146,8 @@ type rbdImage struct { // Set metadata on volume EnableMetadata bool + // ParentInTrash indicates the parent image is in trash. + ParentInTrash bool } // rbdVolume represents a CSI volume and its RBD image specifics. @@ -1613,6 +1615,7 @@ func (ri *rbdImage) getImageInfo() error { } else { ri.ParentName = parentInfo.Image.ImageName ri.ParentPool = parentInfo.Image.PoolName + ri.ParentInTrash = parentInfo.Image.Trash } // Get image creation time tm, err := image.GetCreateTimestamp() @@ -1631,7 +1634,9 @@ func (ri *rbdImage) getParent() (*rbdImage, error) { if err != nil { return nil, err } - if ri.ParentName == "" { + // The image may not have a parent or the parent maybe in trash. + // Return nil in both the cases. + if ri.ParentName == "" || ri.ParentInTrash { return nil, nil }