Skip to content

Commit

Permalink
fix(vmclone): add e2e test for wffc binding mode
Browse files Browse the repository at this point in the history
If a pvc associated to a vm clone is using a storage class
with wffc binding mode, the vmrestore and the vm snapshot
resources should be deleted only after the target pvc are
bound. This commit cover this case with an e2e test.

Signed-off-by: fossedihelm <ffossemo@redhat.com>
  • Loading branch information
fossedihelm committed Jan 19, 2024
1 parent dd2088b commit 40100b8
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 0 deletions.
65 changes: 65 additions & 0 deletions tests/clone_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"strings"
"time"

"k8s.io/apimachinery/pkg/api/errors"

"kubevirt.io/kubevirt/tests/decorators"
"kubevirt.io/kubevirt/tests/testsuite"

Expand Down Expand Up @@ -526,6 +528,10 @@ var _ = Describe("[Serial]VirtualMachineClone Tests", Serial, func() {
vm, err := virtClient.VirtualMachine(vm.Namespace).Create(context.Background(), vm)
Expect(err).ToNot(HaveOccurred())

if !running && libstorage.IsStorageClassBindingModeWaitForFirstConsumer(storageClass) {
return vm
}

for _, dvt := range vm.Spec.DataVolumeTemplates {
libstorage.EventuallyDVWith(vm.Namespace, dvt.Name, 180, HaveSucceeded())
}
Expand Down Expand Up @@ -744,6 +750,65 @@ var _ = Describe("[Serial]VirtualMachineClone Tests", Serial, func() {
expectEqualTemplateAnnotations(targetVMCloneFromClone, sourceVM)
})

Context("with WaitForFirstConsumer binding mode", func() {
BeforeEach(func() {
snapshotStorageClass, err = libstorage.GetWFFCStorageSnapshotClass(virtClient)
Expect(err).ToNot(HaveOccurred())
Expect(snapshotStorageClass).ToNot(BeEmpty(), "no storage class with snapshot support and wffc binding mode")
})

It("should not delete the vmsnapshot and vmrestore until all the pvc(s) are bound", func() {
addCloneAnnotationAndLabelFilters := func(vmClone *clonev1alpha1.VirtualMachineClone) {
filters := []string{"somekey/*"}
vmClone.Spec.LabelFilters = filters
vmClone.Spec.AnnotationFilters = filters
vmClone.Spec.Template.LabelFilters = filters
vmClone.Spec.Template.AnnotationFilters = filters
}
generateCloneWithFilters := func(sourceVM *virtv1.VirtualMachine, targetVMName string) *clonev1alpha1.VirtualMachineClone {
vmclone := generateCloneFromVMWithParams(sourceVM, targetVMName)
addCloneAnnotationAndLabelFilters(vmclone)
return vmclone
}

sourceVM = createVMWithStorageClass(snapshotStorageClass, true)
vmClone = generateCloneWithFilters(sourceVM, targetVMName)
StopVirtualMachine(sourceVM)

createCloneAndWaitForFinish(vmClone)

By(fmt.Sprintf("Getting the target VM %s", targetVMName))
targetVM, err = virtClient.VirtualMachine(sourceVM.Namespace).Get(context.Background(), targetVMName, &v1.GetOptions{})
Expect(err).ShouldNot(HaveOccurred())

vmClone, err = virtClient.VirtualMachineClone(vmClone.Namespace).Get(context.Background(), vmClone.Name, v1.GetOptions{})
Expect(err).ShouldNot(HaveOccurred())
Expect(vmClone.Status.SnapshotName).ShouldNot(BeNil())
vmSnapshotName := vmClone.Status.SnapshotName
Expect(vmClone.Status.RestoreName).ShouldNot(BeNil())
vmRestoreName := vmClone.Status.RestoreName
Consistently(func(g Gomega) {
vmSnapshot, err := virtClient.VirtualMachineSnapshot(vmClone.Namespace).Get(context.Background(), *vmSnapshotName, v1.GetOptions{})
g.Expect(err).ShouldNot(HaveOccurred())
g.Expect(vmSnapshot).ShouldNot(BeNil())
vmRestore, err := virtClient.VirtualMachineRestore(vmClone.Namespace).Get(context.Background(), *vmRestoreName, v1.GetOptions{})
g.Expect(err).ShouldNot(HaveOccurred())
g.Expect(vmRestore).ShouldNot(BeNil())
}, 30*time.Second).Should(Succeed(), "vmsnapshot and vmrestore should not be deleted until the pvc is bound")

By(fmt.Sprintf("Starting the target VM %s", targetVMName))
err = virtClient.VirtualMachine(testsuite.GetTestNamespace(targetVM)).Start(context.Background(), targetVMName, &virtv1.StartOptions{Paused: false})
Expect(err).ToNot(HaveOccurred())
Eventually(func(g Gomega) {
_, err := virtClient.VirtualMachineSnapshot(vmClone.Namespace).Get(context.Background(), *vmSnapshotName, v1.GetOptions{})
g.Expect(errors.IsNotFound(err)).Should(BeTrue())
_, err = virtClient.VirtualMachineRestore(vmClone.Namespace).Get(context.Background(), *vmRestoreName, v1.GetOptions{})
g.Expect(errors.IsNotFound(err)).Should(BeTrue())
}, 1*time.Minute).Should(Succeed(), "vmsnapshot and vmrestore should be deleted once the pvc is bound")
})

})

})
})
})
Expand Down
49 changes: 49 additions & 0 deletions tests/libstorage/storageclass.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,55 @@ func GetSnapshotClass(scName string, client kubecli.KubevirtClient) (string, err
return "", nil
}

func GetWFFCStorageSnapshotClass(client kubecli.KubevirtClient) (string, error) {
crd, err := client.
ExtensionsClient().
ApiextensionsV1().
CustomResourceDefinitions().
Get(context.Background(), "volumesnapshotclasses.snapshot.storage.k8s.io", metav1.GetOptions{})
if err != nil {
if errors.IsNotFound(err) {
return "", nil
}

return "", err
}

hasV1 := false
for _, v := range crd.Spec.Versions {
if v.Name == "v1" && v.Served {
hasV1 = true
}
}

if !hasV1 {
return "", nil
}

volumeSnapshotClasses, err := client.KubernetesSnapshotClient().SnapshotV1().VolumeSnapshotClasses().List(context.Background(), metav1.ListOptions{})
if err != nil {
return "", err
}
if len(volumeSnapshotClasses.Items) == 0 {
return "", nil
}
storageClasses, err := client.StorageV1().StorageClasses().List(context.Background(), metav1.ListOptions{})
if err != nil {
return "", err
}
for _, storageClass := range storageClasses.Items {
if *storageClass.VolumeBindingMode == storagev1.VolumeBindingWaitForFirstConsumer {
for _, volumeSnapshot := range volumeSnapshotClasses.Items {
if storageClass.Provisioner == volumeSnapshot.Driver {
return storageClass.Name, nil
}
}
}
}

return "", nil
}

func GetRWXFileSystemStorageClass() (string, bool) {
storageRWXFileSystem := Config.StorageRWXFileSystem
return storageRWXFileSystem, storageRWXFileSystem != ""
Expand Down

0 comments on commit 40100b8

Please sign in to comment.