mirror of
https://github.com/kubevirt/containerized-data-importer.git
synced 2025-06-03 06:30:22 +00:00

- Added oVirt STDCI configuration files. Signed-off-by: Alexander Wels <awels@redhat.com>
152 lines
5.6 KiB
Go
152 lines
5.6 KiB
Go
package tests
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
. "github.com/onsi/ginkgo"
|
|
. "github.com/onsi/gomega"
|
|
|
|
"k8s.io/api/core/v1"
|
|
|
|
"kubevirt.io/containerized-data-importer/pkg/common"
|
|
"kubevirt.io/containerized-data-importer/pkg/controller"
|
|
"kubevirt.io/containerized-data-importer/tests/framework"
|
|
"kubevirt.io/containerized-data-importer/tests/utils"
|
|
)
|
|
|
|
const (
|
|
testSuiteName = "Cloner Test Suite"
|
|
namespacePrefix = "cloner"
|
|
sourcePodFillerName = "fill-source"
|
|
sourcePVCName = "source-pvc"
|
|
fillData = "123456789012345678901234567890123456789012345678901234567890"
|
|
testFile = utils.DefaultPvcMountPath + "/source.txt"
|
|
fillCommand = "echo \"" + fillData + "\" >> " + testFile
|
|
assertionPollInterval = 2 * time.Second
|
|
cloneCompleteTimeout = 60 * time.Second
|
|
testCompleteTimeout = 300 * time.Second
|
|
)
|
|
|
|
var _ = Describe(testSuiteName, func() {
|
|
f, err := framework.NewFramework(namespacePrefix, framework.Config{})
|
|
if err != nil {
|
|
Fail("Unable to create framework struct")
|
|
}
|
|
|
|
var sourcePvc *v1.PersistentVolumeClaim
|
|
|
|
BeforeEach(func() {
|
|
sourcePvc = createAndPopulateSourcePVC(f)
|
|
})
|
|
|
|
AfterEach(func() {
|
|
if sourcePvc != nil {
|
|
By("[AfterEach] Clean up target PVC")
|
|
err = f.DeletePVC(sourcePvc)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
}
|
|
})
|
|
|
|
Context("A valid source and target given", func() {
|
|
It("Should clone data within same name space", func() {
|
|
doCloneTest(f, f.Namespace)
|
|
})
|
|
|
|
It("Should clone data across different namespaces", func() {
|
|
targetNs, err := f.CreateNamespace(f.NsPrefix, map[string]string{
|
|
framework.NsPrefixLabel: f.NsPrefix,
|
|
})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
f.AddNamespaceToDelete(targetNs)
|
|
doCloneTest(f, targetNs)
|
|
})
|
|
})
|
|
|
|
})
|
|
|
|
func createAndPopulateSourcePVC(f *framework.Framework) *v1.PersistentVolumeClaim {
|
|
// Create the source PVC and populate it with a file, so we can verify the clone.
|
|
By("[BeforeEach] Creating the source PVC")
|
|
sourcePvc, err := f.CreatePVCFromDefinition(utils.NewPVCDefinition(sourcePVCName, "1G", nil, nil))
|
|
Expect(err).ToNot(HaveOccurred())
|
|
By("[BeforeEach] Populating the source PVC with data")
|
|
pod, err := f.CreatePod(utils.NewPodWithPVC(sourcePodFillerName, fillCommand, sourcePvc))
|
|
Expect(err).ToNot(HaveOccurred())
|
|
err = f.WaitTimeoutForPodStatus(pod.Name, v1.PodSucceeded, utils.PodWaitForTime)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
return sourcePvc
|
|
}
|
|
|
|
func doCloneTest(f *framework.Framework, targetNs *v1.Namespace) {
|
|
// Create targetPvc in new NS.
|
|
targetPvc, err := utils.CreatePVCFromDefinition(f.K8sClient, targetNs.Name, utils.NewPVCDefinition(
|
|
"target-pvc",
|
|
"1G",
|
|
map[string]string{controller.AnnCloneRequest: f.Namespace.Name + "/" + sourcePVCName},
|
|
nil))
|
|
Expect(err).ToNot(HaveOccurred())
|
|
err = utils.WaitForPersistentVolumeClaimPhase(f.K8sClient, targetNs.Name, v1.ClaimBound, targetPvc.Name)
|
|
|
|
By("Find cloner pods")
|
|
sourcePod, err := f.FindPodByPrefix(common.CLONER_SOURCE_PODNAME)
|
|
if err != nil {
|
|
PrintControllerLog(f)
|
|
}
|
|
Expect(err).ToNot(HaveOccurred())
|
|
targetPod, err := utils.FindPodByPrefix(f.K8sClient, targetNs.Name, common.CLONER_TARGET_PODNAME, common.CDI_LABEL_SELECTOR)
|
|
if err != nil {
|
|
PrintControllerLog(f)
|
|
}
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
By("Verifying that the source and target pods are scheduled on the same node")
|
|
Eventually(func() bool {
|
|
srcNode, err := utils.PodGetNode(f.K8sClient, sourcePod.Name, sourcePod.Namespace)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
tgtNode, err := utils.PodGetNode(f.K8sClient, targetPod.Name, targetPod.Namespace)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
fmt.Fprintf(GinkgoWriter, "INFO: Source POD host %s\n", srcNode)
|
|
fmt.Fprintf(GinkgoWriter, "INFO: Target POD host %s\n", tgtNode)
|
|
return srcNode == tgtNode
|
|
}, cloneCompleteTimeout, assertionPollInterval).Should(BeTrue())
|
|
|
|
err = f.WaitTimeoutForPodStatus(sourcePod.Name, v1.PodSucceeded, cloneCompleteTimeout)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
err = utils.WaitTimeoutForPodStatus(f.K8sClient, targetPod.Name, targetNs.Name, v1.PodSucceeded, cloneCompleteTimeout)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
By("Verify the clone annotation is on the target PVC")
|
|
_, cloneAnnotationFound, err := utils.WaitForPVCAnnotation(f.K8sClient, targetNs.Name, targetPvc, controller.AnnCloneOf)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(cloneAnnotationFound).To(BeTrue())
|
|
|
|
By("Verify the clone status is success on the target PVC")
|
|
Eventually(func() string {
|
|
status, phaseAnnotation, err := utils.WaitForPVCAnnotation(f.K8sClient, targetNs.Name, targetPvc, controller.AnnClonePodPhase)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(phaseAnnotation).To(BeTrue())
|
|
return status
|
|
}, cloneCompleteTimeout, assertionPollInterval).Should(BeEquivalentTo(v1.PodSucceeded))
|
|
|
|
// Clone is completed, verify the content matches the source.
|
|
Expect(verifyTargetContent(f, targetNs, targetPvc)).To(BeTrue())
|
|
// Clean up PVC, the AfterEach will also clean it up, through the Namespace delete.
|
|
if targetPvc != nil {
|
|
err = utils.DeletePVC(f.K8sClient, targetNs.Name, targetPvc)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
}
|
|
}
|
|
|
|
func verifyTargetContent(f *framework.Framework, namespace *v1.Namespace, pvc *v1.PersistentVolumeClaim) bool {
|
|
By("Verify target PVC content matches source PVC")
|
|
executorPod, err := utils.CreateExecutorPodWithPVC(f.K8sClient, "verify-pvc-content", namespace.Name, pvc)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
err = utils.WaitTimeoutForPodReady(f.K8sClient, executorPod.Name, namespace.Name, utils.PodWaitForTime)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
output := f.ExecShellInPod(executorPod.Name, namespace.Name, "cat "+testFile)
|
|
f.DeletePod(executorPod)
|
|
return strings.Compare(fillData, output) == 0
|
|
}
|