Skip to content

Commit

Permalink
tests: Add clone and restore tests with instancetypes
Browse files Browse the repository at this point in the history
Signed-off-by: Lee Yarwood <lyarwood@redhat.com>
  • Loading branch information
lyarwood committed Oct 27, 2022
1 parent 4bb122d commit 02e06d7
Show file tree
Hide file tree
Showing 2 changed files with 264 additions and 9 deletions.
130 changes: 130 additions & 0 deletions tests/storage/clone.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,16 @@ import (
"github.com/onsi/gomega/format"

k8sv1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/utils/pointer"

clonev1alpha1 "kubevirt.io/api/clone/v1alpha1"
virtv1 "kubevirt.io/api/core/v1"
instancetypev1alpha2 "kubevirt.io/api/instancetype/v1alpha2"
"kubevirt.io/client-go/kubecli"

virtconfig "kubevirt.io/kubevirt/pkg/virt-config"
Expand Down Expand Up @@ -447,6 +451,132 @@ var _ = SIGDescribe("[Serial]VirtualMachineClone Tests", func() {
Expect(err).To(HaveOccurred())
Expect(err.Error()).Should(ContainSubstring("does not support snapshots"))
})

Context("with instancetype and preferences", func() {

var (
instancetype *instancetypev1alpha2.VirtualMachineInstancetype
preference *instancetypev1alpha2.VirtualMachinePreference
)

BeforeEach(func() {
snapshotStorageClass, err := getSnapshotStorageClass(virtClient)
Expect(err).ToNot(HaveOccurred())

if snapshotStorageClass == "" {
Skip("Skipping test, no VolumeSnapshot support")
}

instancetype = &instancetypev1alpha2.VirtualMachineInstancetype{
ObjectMeta: metav1.ObjectMeta{
GenerateName: "vm-instancetype-",
Namespace: util.NamespaceTestDefault,
},
Spec: instancetypev1alpha2.VirtualMachineInstancetypeSpec{
CPU: instancetypev1alpha2.CPUInstancetype{
Guest: 1,
},
Memory: instancetypev1alpha2.MemoryInstancetype{
Guest: resource.MustParse("128Mi"),
},
},
}
instancetype, err := virtClient.VirtualMachineInstancetype(util.NamespaceTestDefault).Create(context.Background(), instancetype, metav1.CreateOptions{})
Expect(err).ToNot(HaveOccurred())

preference = &instancetypev1alpha2.VirtualMachinePreference{
ObjectMeta: metav1.ObjectMeta{
GenerateName: "vm-preference-",
Namespace: util.NamespaceTestDefault,
},
Spec: instancetypev1alpha2.VirtualMachinePreferenceSpec{
CPU: &instancetypev1alpha2.CPUPreferences{
PreferredCPUTopology: instancetypev1alpha2.PreferSockets,
},
},
}
preference, err := virtClient.VirtualMachinePreference(util.NamespaceTestDefault).Create(context.Background(), preference, metav1.CreateOptions{})
Expect(err).ToNot(HaveOccurred())

sourceVM = tests.NewRandomVMWithDataVolumeWithRegistryImport(
cd.DataVolumeImportUrlForContainerDisk(cd.ContainerDiskAlpine),
util.NamespaceTestDefault,
snapshotStorageClass,
k8sv1.ReadWriteOnce,
)

sourceVM.Spec.Template.Spec.Domain.Resources = virtv1.ResourceRequirements{}
sourceVM.Spec.Instancetype = &virtv1.InstancetypeMatcher{
Name: instancetype.Name,
Kind: "VirtualMachineInstanceType",
}
sourceVM.Spec.Preference = &virtv1.PreferenceMatcher{
Name: preference.Name,
Kind: "VirtualMachinePreference",
}

sourceVM, err = virtClient.VirtualMachine(sourceVM.Namespace).Create(sourceVM)
Expect(err).ToNot(HaveOccurred())

for _, dvt := range sourceVM.Spec.DataVolumeTemplates {
libstorage.EventuallyDVWith(sourceVM.Namespace, dvt.Name, 180, HaveSucceeded())
}

})

It("should create new ControllerRevisions for cloned VM", Label("instancetype", "clone"), func() {
By("Waiting until the source VM has instancetype and preference RevisionNames")
waitForVMInstanceTypeRevisionNames(sourceVM.Name, virtClient)

vmClone = generateClone()
createCloneAndWaitForFinish(vmClone)

By("Waiting until the targetVM has instancetype and preference RevisionNames")
waitForVMInstanceTypeRevisionNames(targetVMName, virtClient)

By("Asserting that the targetVM has new instancetype and preference controllerRevisions")
sourceVM, err := virtClient.VirtualMachine(util.NamespaceTestDefault).Get(sourceVM.Name, &metav1.GetOptions{})
Expect(err).ToNot(HaveOccurred())
targetVM, err := virtClient.VirtualMachine(util.NamespaceTestDefault).Get(targetVMName, &metav1.GetOptions{})
Expect(err).ToNot(HaveOccurred())

Expect(targetVM.Spec.Instancetype.RevisionName).ToNot(Equal(sourceVM.Spec.Instancetype.RevisionName), "source and target instancetype revision names should not be equal")
Expect(targetVM.Spec.Preference.RevisionName).ToNot(Equal(sourceVM.Spec.Preference.RevisionName), "source and target preference revision names should not be equal")

By("Asserting that the source and target ControllerRevisions contain the same Object")
Expect(ensureControllerRevisionObjectsEqual(sourceVM.Spec.Instancetype.RevisionName, targetVM.Spec.Instancetype.RevisionName, virtClient)).To(BeTrue(), "source and target instance type controller revisions are expected to be equal")
Expect(ensureControllerRevisionObjectsEqual(sourceVM.Spec.Preference.RevisionName, targetVM.Spec.Preference.RevisionName, virtClient)).To(BeTrue(), "source and target preference controller revisions are expected to be equal")
})
})
})
})
})

func checkForVMInstancetypeRevisionNames(vmName string, virtClient kubecli.KubevirtClient) func() error {
return func() error {
vm, err := virtClient.VirtualMachine(util.NamespaceTestDefault).Get(vmName, &metav1.GetOptions{})
if err != nil {
return err
}
if vm.Spec.Instancetype.RevisionName == "" {
return fmt.Errorf("instancetype revision name is expected to not be empty")
}

if vm.Spec.Preference.RevisionName == "" {
return fmt.Errorf("preference revision name is expected to not be empty")
}
return nil
}
}

func waitForVMInstanceTypeRevisionNames(vmName string, virtClient kubecli.KubevirtClient) {
Eventually(checkForVMInstancetypeRevisionNames(vmName, virtClient), 300*time.Second, 1*time.Second).ShouldNot(HaveOccurred())
}

func ensureControllerRevisionObjectsEqual(crNameA, crNameB string, virtClient kubecli.KubevirtClient) bool {
crA, err := virtClient.AppsV1().ControllerRevisions(util.NamespaceTestDefault).Get(context.Background(), crNameA, v1.GetOptions{})
Expect(err).ToNot(HaveOccurred())
crB, err := virtClient.AppsV1().ControllerRevisions(util.NamespaceTestDefault).Get(context.Background(), crNameB, v1.GetOptions{})
Expect(err).ToNot(HaveOccurred())
return equality.Semantic.DeepEqual(crA.Data.Object, crB.Data.Object)
}
143 changes: 134 additions & 9 deletions tests/storage/restore.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import (
clonev1alpha1 "kubevirt.io/api/clone/v1alpha1"
"kubevirt.io/api/core"
v1 "kubevirt.io/api/core/v1"
virtv1 "kubevirt.io/api/core/v1"
instancetypev1alpha2 "kubevirt.io/api/instancetype/v1alpha2"
snapshotv1 "kubevirt.io/api/snapshot/v1alpha1"
"kubevirt.io/client-go/kubecli"
cdiv1 "kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1"
Expand Down Expand Up @@ -246,6 +248,14 @@ var _ = SIGDescribe("VirtualMachineRestore Tests", func() {
Context("With simple VM", func() {
var vm *v1.VirtualMachine

expectNewVMCreation := func(vmName string) (createdVM *v1.VirtualMachine) {
Eventually(func() error {
createdVM, err = virtClient.VirtualMachine(vm.Namespace).Get(vmName, &metav1.GetOptions{})
return err
}, 90*time.Second, 5*time.Second).ShouldNot(HaveOccurred(), fmt.Sprintf("new VM (%s) is not being created", vmName))
return createdVM
}

BeforeEach(func() {
vm = tests.NewRandomVirtualMachine(
libvmi.NewCirros(
Expand Down Expand Up @@ -481,15 +491,6 @@ var _ = SIGDescribe("VirtualMachineRestore Tests", func() {
restore = createRestoreDef(newVmName, snapshot.Name)
})

expectNewVMCreation := func(vmName string) (createdVM *v1.VirtualMachine) {
Eventually(func() error {
createdVM, err = virtClient.VirtualMachine(vm.Namespace).Get(vmName, &metav1.GetOptions{})
return err
}, 90*time.Second, 5*time.Second).ShouldNot(HaveOccurred(), fmt.Sprintf("new VM (%s) is not being created", newVmName))

return createdVM
}

waitRestoreComplete := func(r *snapshotv1.VirtualMachineRestore, vm *v1.VirtualMachine) *snapshotv1.VirtualMachineRestore {
r = waitRestoreComplete(r, vm.Name, &vm.UID)
Expect(r.Status.Restores).To(BeEmpty())
Expand Down Expand Up @@ -543,6 +544,130 @@ var _ = SIGDescribe("VirtualMachineRestore Tests", func() {

})
})
Context("with instancetype and preferences", func() {

var (
instancetype *instancetypev1alpha2.VirtualMachineInstancetype
preference *instancetypev1alpha2.VirtualMachinePreference
snapshot *snapshotv1.VirtualMachineSnapshot
restore *snapshotv1.VirtualMachineRestore
)

BeforeEach(func() {
snapshotStorageClass, err := getSnapshotStorageClass(virtClient)
Expect(err).ToNot(HaveOccurred())

if snapshotStorageClass == "" {
Skip("Skipping test, no VolumeSnapshot support")
}

instancetype = &instancetypev1alpha2.VirtualMachineInstancetype{
ObjectMeta: metav1.ObjectMeta{
GenerateName: "vm-instancetype-",
Namespace: util.NamespaceTestDefault,
},
Spec: instancetypev1alpha2.VirtualMachineInstancetypeSpec{
CPU: instancetypev1alpha2.CPUInstancetype{
Guest: 1,
},
Memory: instancetypev1alpha2.MemoryInstancetype{
Guest: resource.MustParse("128Mi"),
},
},
}
instancetype, err := virtClient.VirtualMachineInstancetype(util.NamespaceTestDefault).Create(context.Background(), instancetype, metav1.CreateOptions{})
Expect(err).ToNot(HaveOccurred())

preference = &instancetypev1alpha2.VirtualMachinePreference{
ObjectMeta: metav1.ObjectMeta{
GenerateName: "vm-preference-",
Namespace: util.NamespaceTestDefault,
},
Spec: instancetypev1alpha2.VirtualMachinePreferenceSpec{
CPU: &instancetypev1alpha2.CPUPreferences{
PreferredCPUTopology: instancetypev1alpha2.PreferSockets,
},
},
}
preference, err := virtClient.VirtualMachinePreference(util.NamespaceTestDefault).Create(context.Background(), preference, metav1.CreateOptions{})
Expect(err).ToNot(HaveOccurred())

vm.Spec.Template.Spec.Domain.Resources = virtv1.ResourceRequirements{}
vm.Spec.Instancetype = &virtv1.InstancetypeMatcher{
Name: instancetype.Name,
Kind: "VirtualMachineInstanceType",
}
vm.Spec.Preference = &virtv1.PreferenceMatcher{
Name: preference.Name,
Kind: "VirtualMachinePreference",
}

vm, err = virtClient.VirtualMachine(util.NamespaceTestDefault).Create(vm)
Expect(err).ToNot(HaveOccurred())

By("Waiting until the VM has instancetype and preference RevisionNames")
waitForVMInstanceTypeRevisionNames(vm.Name, virtClient)

for _, dvt := range vm.Spec.DataVolumeTemplates {
libstorage.EventuallyDVWith(vm.Namespace, dvt.Name, 180, HaveSucceeded())
}
})

It("should use existing ControllerRevisions for an existing VM restore", Label("instancetype", "preference", "restore"), func() {
originalVM, err := virtClient.VirtualMachine(util.NamespaceTestDefault).Get(vm.Name, &metav1.GetOptions{})
Expect(err).ToNot(HaveOccurred())

By("Creating a VirtualMachineSnapshot")
snapshot = createSnapshot(vm)

By("Creating a VirtualMachineRestore")
restore = createRestoreDef(vm.Name, snapshot.Name)

restore, err = virtClient.VirtualMachineRestore(vm.Namespace).Create(context.Background(), restore, metav1.CreateOptions{})
Expect(err).ToNot(HaveOccurred())

By("Waiting until the restore completes")
restore = waitRestoreComplete(restore, vm.Name, &vm.UID)

By("Asserting that the restored VM has the same instancetype and preference controllerRevisions")
vm, err := virtClient.VirtualMachine(util.NamespaceTestDefault).Get(vm.Name, &metav1.GetOptions{})
Expect(err).ToNot(HaveOccurred())

Expect(vm.Spec.Instancetype.RevisionName).To(Equal(originalVM.Spec.Instancetype.RevisionName))
Expect(vm.Spec.Preference.RevisionName).To(Equal(originalVM.Spec.Preference.RevisionName))
})

It("should create new ControllerRevisions for newly restored VM", Label("instancetype", "preference", "restore"), func() {
By("Creating a VirtualMachineSnapshot")
snapshot = createSnapshot(vm)

By("Creating a VirtualMachineRestore")
restoreVMName := vm.Name + "-new"
restore = createRestoreDef(restoreVMName, snapshot.Name)

restore, err = virtClient.VirtualMachineRestore(vm.Namespace).Create(context.Background(), restore, metav1.CreateOptions{})
Expect(err).ToNot(HaveOccurred())

By("Waiting until the targetVM is finally created")
_ = expectNewVMCreation(restoreVMName)

By("Waiting until the restoreVM has instancetype and preference RevisionNames")
waitForVMInstanceTypeRevisionNames(restoreVMName, virtClient)

By("Asserting that the restoreVM has new instancetype and preference controllerRevisions")
sourceVM, err := virtClient.VirtualMachine(util.NamespaceTestDefault).Get(vm.Name, &metav1.GetOptions{})
Expect(err).ToNot(HaveOccurred())
restoreVM, err := virtClient.VirtualMachine(util.NamespaceTestDefault).Get(restoreVMName, &metav1.GetOptions{})
Expect(err).ToNot(HaveOccurred())

Expect(restoreVM.Spec.Instancetype.RevisionName).ToNot(Equal(sourceVM.Spec.Instancetype.RevisionName))
Expect(restoreVM.Spec.Preference.RevisionName).ToNot(Equal(sourceVM.Spec.Preference.RevisionName))

By("Asserting that the source and target ControllerRevisions contain the same Object")
Expect(ensureControllerRevisionObjectsEqual(sourceVM.Spec.Instancetype.RevisionName, restoreVM.Spec.Instancetype.RevisionName, virtClient)).To(BeTrue(), "source and target instance type controller revisions are expected to be equal")
Expect(ensureControllerRevisionObjectsEqual(sourceVM.Spec.Preference.RevisionName, restoreVM.Spec.Preference.RevisionName, virtClient)).To(BeTrue(), "source and target preference controller revisions are expected to be equal")
})
})
})

Context("[storage-req]", func() {
Expand Down

0 comments on commit 02e06d7

Please sign in to comment.