diff --git a/e2e/rbd.go b/e2e/rbd.go index 26abed41c..f65030653 100644 --- a/e2e/rbd.go +++ b/e2e/rbd.go @@ -761,7 +761,35 @@ var _ = Describe("RBD", func() { By("create a PVC-PVC clone and bind it to an app", func() { // pvc clone is only supported from v1.16+ if k8sVersionGreaterEquals(f.ClientSet, 1, 16) { - validatePVCClone(defaultCloneCount, pvcPath, appPath, pvcSmartClonePath, appSmartClonePath, false, f) + validatePVCClone(defaultCloneCount, pvcPath, appPath, pvcSmartClonePath, appSmartClonePath, noPVCValidation, f) + } + }) + + By("create a thick-provisioned PVC-PVC clone and bind it to an app", func() { + // pvc clone is only supported from v1.16+ + if !k8sVersionGreaterEquals(f.ClientSet, 1, 16) { + Skip("pvc clone is only supported from v1.16+") + } + + err := deleteResource(rbdExamplePath + "storageclass.yaml") + if err != nil { + e2elog.Failf("failed to delete storageclass with error %v", err) + } + err = createRBDStorageClass(f.ClientSet, f, defaultSCName, nil, map[string]string{ + "thickProvision": "true"}, deletePolicy) + if err != nil { + e2elog.Failf("failed to create storageclass with error %v", err) + } + + validatePVCClone(1, pvcPath, appPath, pvcSmartClonePath, appSmartClonePath, isThickPVC, f) + + err = deleteResource(rbdExamplePath + "storageclass.yaml") + if err != nil { + e2elog.Failf("failed to delete storageclass with error %v", err) + } + err = createRBDStorageClass(f.ClientSet, f, defaultSCName, nil, nil, deletePolicy) + if err != nil { + e2elog.Failf("failed to create storageclass with error %v", err) } }) @@ -813,7 +841,7 @@ var _ = Describe("RBD", func() { e2elog.Failf("failed to create storageclass with error %v", err) } - validatePVCClone(1, pvcPath, appPath, pvcSmartClonePath, appSmartClonePath, true, f) + validatePVCClone(1, pvcPath, appPath, pvcSmartClonePath, appSmartClonePath, isEncryptedPVC, f) err = deleteResource(rbdExamplePath + "storageclass.yaml") if err != nil { @@ -838,7 +866,7 @@ var _ = Describe("RBD", func() { } // pvc clone is only supported from v1.16+ if v.Major > "1" || (v.Major == "1" && v.Minor >= "16") { - validatePVCClone(defaultCloneCount, rawPvcPath, rawAppPath, pvcBlockSmartClonePath, appBlockSmartClonePath, false, f) + validatePVCClone(defaultCloneCount, rawPvcPath, rawAppPath, pvcBlockSmartClonePath, appBlockSmartClonePath, noPVCValidation, f) } }) By("create/delete multiple PVCs and Apps", func() { diff --git a/e2e/rbd_helper.go b/e2e/rbd_helper.go index c917a77cd..483c73ad1 100644 --- a/e2e/rbd_helper.go +++ b/e2e/rbd_helper.go @@ -414,7 +414,13 @@ func validateEncryptedPVCAndAppBinding(pvcPath, appPath, kms string, f *framewor return nil } -func validateEncryptedPVC(f *framework.Framework, pvc *v1.PersistentVolumeClaim, app *v1.Pod) error { +type validateFunc func(f *framework.Framework, pvc *v1.PersistentVolumeClaim, app *v1.Pod) error + +// noPVCValidation can be used to pass to validatePVCClone when no extra +// validation of the PVC is needed. +var noPVCValidation validateFunc = nil + +func isEncryptedPVC(f *framework.Framework, pvc *v1.PersistentVolumeClaim, app *v1.Pod) error { imageData, err := getImageInfoFromPVC(pvc.Namespace, pvc.Name, f) if err != nil { return err @@ -424,6 +430,16 @@ func validateEncryptedPVC(f *framework.Framework, pvc *v1.PersistentVolumeClaim, return validateEncryptedImage(f, rbdImageSpec, app) } +func isThickPVC(f *framework.Framework, pvc *v1.PersistentVolumeClaim, app *v1.Pod) error { + du, err := getRbdDu(f, pvc) + if err != nil { + return fmt.Errorf("failed to get allocations of RBD image: %w", err) + } else if du.UsedSize == 0 || du.UsedSize != du.ProvisionedSize { + return fmt.Errorf("backing RBD image is not thick-provisioned (%d/%d)", du.UsedSize, du.ProvisionedSize) + } + return nil +} + // validateEncryptedImage verifies that the RBD image is encrypted. The // following checks are performed: // - Metadata of the image should be set with the encryption state; diff --git a/e2e/utils.go b/e2e/utils.go index 65dfc3a17..a9ea9c350 100644 --- a/e2e/utils.go +++ b/e2e/utils.go @@ -522,7 +522,7 @@ func writeDataAndCalChecksum(app *v1.Pod, opt *metav1.ListOptions, f *framework. } // nolint:gocyclo,gocognit // reduce complexity -func validatePVCClone(totalCount int, sourcePvcPath, sourceAppPath, clonePvcPath, clonePvcAppPath string, validateEncryption bool, f *framework.Framework) { +func validatePVCClone(totalCount int, sourcePvcPath, sourceAppPath, clonePvcPath, clonePvcAppPath string, validatePVC validateFunc, f *framework.Framework) { var wg sync.WaitGroup wgErrs := make([]error, totalCount) chErrs := make([]error, totalCount) @@ -598,8 +598,8 @@ func validatePVCClone(totalCount int, sourcePvcPath, sourceAppPath, clonePvcPath e2elog.Logf("checksum didn't match. checksum=%s and checksumclone=%s", checkSum, checkSumClone) } } - if wgErrs[n] == nil && validateEncryption { - wgErrs[n] = validateEncryptedPVC(f, &p, &a) + if wgErrs[n] == nil && validatePVC != nil { + wgErrs[n] = validatePVC(f, &p, &a) } w.Done() }(&wg, i, *pvcClone, *appClone) @@ -791,7 +791,7 @@ func validatePVCSnapshot(totalCount int, pvcPath, appPath, snapshotPath, pvcClon } } if wgErrs[n] == nil && kms != "" { - wgErrs[n] = validateEncryptedPVC(f, &p, &a) + wgErrs[n] = isEncryptedPVC(f, &p, &a) } w.Done() }(&wg, i, *pvcClone, *appClone)