Skip to content

Commit

Permalink
Prepare CDI testing for the upcoming non-CSI lane (kubevirt#2730)
Browse files Browse the repository at this point in the history
* Update functional tests to skip incompatible default storage classes

Signed-off-by: Alvaro Romero <alromero@redhat.com>

* Enable the use of non-csi HPP in testing lanes

This commit modifies several scripts to allow the usage of classic HPP as the default SC in tests.

This allows us to test our non-populator flow with a non-csi provisioner.

Signed-off-by: Alvaro Romero <alromero@redhat.com>

---------

Signed-off-by: Alvaro Romero <alromero@redhat.com>
  • Loading branch information
alromeros authored and awels committed Jun 21, 2023
1 parent 6fa3117 commit b26d4fc
Show file tree
Hide file tree
Showing 9 changed files with 102 additions and 22 deletions.
25 changes: 25 additions & 0 deletions automation/non-csi-hpp.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/bin/bash
#
# This file is part of the KubeVirt project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Copyright 2023 Red Hat, Inc.
#

set -ex
export TARGET=k8s-1.26-centos9
export KUBEVIRT_STORAGE=hpp
export HPP_CLASSIC=true
export CDI_E2E_SKIP=Destructive
automation/test.sh
13 changes: 12 additions & 1 deletion cluster-sync/ephemeral_provider.sh
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,18 @@ function configure_hpp() {
_kubectl apply -f https://github.com/kubevirt/hostpath-provisioner-operator/releases/download/$HPP_RELEASE/storageclass-wffc-legacy-csi.yaml
echo "Waiting for hostpath provisioner to be available"
_kubectl wait hostpathprovisioners.hostpathprovisioner.kubevirt.io/hostpath-provisioner --for=condition=Available --timeout=480s
_kubectl patch storageclass hostpath-csi -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
}

function configure_hpp_classic() {
# Configure hpp and default to classic non-csi hostpath-provisioner
configure_hpp
_kubectl patch storageclass hostpath-provisioner -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
}

function configure_hpp_csi() {
# Configure hpp and default to hostpath-csi
configure_hpp
_kubectl patch storageclass hostpath-csi -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
}

function configure_nfs() {
Expand Down
6 changes: 5 additions & 1 deletion cluster-sync/kubevirtci/provider.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ function configure_storage() {
fi
elif [[ $KUBEVIRT_STORAGE == "hpp" ]] ; then
echo "Installing hostpath provisioner storage"
configure_hpp
if [[ $HPP_CLASSIC == "true" ]] ; then
configure_hpp_classic
else
configure_hpp_csi
fi
elif [[ $KUBEVIRT_STORAGE == "nfs" ]] ; then
echo "Installing NFS CSI dynamic storage"
configure_nfs_csi
Expand Down
34 changes: 26 additions & 8 deletions tests/cloner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,9 @@ var _ = Describe("all clone tests", func() {
})

It("[posneg:negative][test_id:6612]Clone with CSI as PVC source with target name that already exists", func() {
if utils.DefaultStorageClassCsiDriver == nil {
Skip("No CSI driver found")
}
if cloneType == "copy" {
Skip("Cannot simulate target pvc name conflict for host-assisted clone ")
}
Expand Down Expand Up @@ -1596,7 +1599,7 @@ var _ = Describe("all clone tests", func() {
}

By("Create the clone before the source PVC")
cloneDV := utils.NewDataVolumeForImageCloningAndStorageSpec("clone-dv", "1Mi", f.Namespace.Name, dataVolumeName, nil, &blockVM)
cloneDV := utils.NewDataVolumeForImageCloningAndStorageSpec("clone-dv", "1Mi", f.Namespace.Name, dataVolumeName, &f.BlockSCName, &blockVM)
_, err := utils.CreateDataVolumeFromDefinition(f.CdiClient, f.Namespace.Name, cloneDV)
Expect(err).ToNot(HaveOccurred())
// Check if the NoSourceClone annotation exists in target PVC
Expand Down Expand Up @@ -2680,6 +2683,9 @@ var _ = Describe("all clone tests", func() {
if crossNamespace && f.IsBindingModeWaitForFirstConsumer(&defaultSc) {
Skip("only host assisted is applicable with WFFC cross namespace")
}
if !f.IsSnapshotStorageClassAvailable() {
Skip("Clone from volumesnapshot does not work without snapshot capable storage")
}

targetNs := f.Namespace
if crossNamespace {
Expand All @@ -2688,10 +2694,10 @@ var _ = Describe("all clone tests", func() {
targetNs = targetNamespace
}
size := "1Gi"
createSnapshot(size, nil, volumeMode)
createSnapshot(size, &f.SnapshotSCName, volumeMode)

for i = 0; i < repeat; i++ {
dataVolume := utils.NewDataVolumeForSnapshotCloningAndStorageSpec(fmt.Sprintf("clone-from-snap-%d", i), size, snapshot.Namespace, snapshot.Name, nil, &volumeMode)
dataVolume := utils.NewDataVolumeForSnapshotCloningAndStorageSpec(fmt.Sprintf("clone-from-snap-%d", i), size, snapshot.Namespace, snapshot.Name, &f.SnapshotSCName, &volumeMode)
dataVolume.Labels = map[string]string{"test-label-1": "test-label-value-1"}
dataVolume.Annotations = map[string]string{"test-annotation-1": "test-annotation-value-1"}
By(fmt.Sprintf("Create new datavolume %s which will clone from volumesnapshot", dataVolume.Name))
Expand Down Expand Up @@ -2855,18 +2861,21 @@ var _ = Describe("all clone tests", func() {

Context("Clone without a source snapshot", func() {
It("[test_id:9718] Should finish the clone after creating the source snapshot", func() {
if !f.IsSnapshotStorageClassAvailable() {
Skip("Clone from volumesnapshot does not work without snapshot capable storage")
}
size := "1Gi"
volumeMode := v1.PersistentVolumeMode(v1.PersistentVolumeFilesystem)
By("Create the clone before the source snapshot")
cloneDV := utils.NewDataVolumeForSnapshotCloningAndStorageSpec("clone-from-snap", size, f.Namespace.Name, "snap-"+dataVolumeName, nil, &volumeMode)
cloneDV := utils.NewDataVolumeForSnapshotCloningAndStorageSpec("clone-from-snap", size, f.Namespace.Name, "snap-"+dataVolumeName, &f.SnapshotSCName, &volumeMode)
cloneDV, err := utils.CreateDataVolumeFromDefinition(f.CdiClient, f.Namespace.Name, cloneDV)
Expect(err).ToNot(HaveOccurred())
// Check if the NoSourceClone annotation exists in target PVC
// By("Check the expected event")
// f.ExpectEvent(f.Namespace.Name).Should(ContainSubstring(dvc.CloneWithoutSource))

By("Create source snapshot")
createSnapshot(size, nil, volumeMode)
createSnapshot(size, &f.SnapshotSCName, volumeMode)

clonePvc, err := utils.WaitForPVC(f.K8sClient, cloneDV.Namespace, cloneDV.Name)
Expect(err).ToNot(HaveOccurred())
Expand All @@ -2889,13 +2898,17 @@ var _ = Describe("all clone tests", func() {

Context("Validate source snapshot", func() {
It("[test_id:9719] Should reject when input size is lower than recommended restore size", func() {
if !f.IsSnapshotStorageClassAvailable() {
Skip("Clone from volumesnapshot does not work without snapshot capable storage")
}

recommendedSnapSize := "2Gi"
volumeMode := v1.PersistentVolumeMode(v1.PersistentVolumeFilesystem)

By("Create source snapshot")
createSnapshot(recommendedSnapSize, nil, volumeMode)
createSnapshot(recommendedSnapSize, &f.SnapshotSCName, volumeMode)

cloneDV := utils.NewDataVolumeForSnapshotCloningAndStorageSpec("clone-from-snap", "500Mi", f.Namespace.Name, "snap-"+dataVolumeName, nil, &volumeMode)
cloneDV := utils.NewDataVolumeForSnapshotCloningAndStorageSpec("clone-from-snap", "500Mi", f.Namespace.Name, "snap-"+dataVolumeName, &f.SnapshotSCName, &volumeMode)
_, err := utils.CreateDataVolumeFromDefinition(f.CdiClient, f.Namespace.Name, cloneDV)
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("target resources requests storage size is smaller than the source"))
Expand All @@ -2904,16 +2917,21 @@ var _ = Describe("all clone tests", func() {

Context("sourceRef support", func() {
It("[test_id:9758] Should clone data from SourceRef snapshot DataSource", func() {
if !f.IsSnapshotStorageClassAvailable() {
Skip("Clone from volumesnapshot does not work without snapshot capable storage")
}

size := "1Gi"
volumeMode := v1.PersistentVolumeMode(v1.PersistentVolumeFilesystem)
createSnapshot(size, nil, volumeMode)
createSnapshot(size, &f.SnapshotSCName, volumeMode)

targetDS := utils.NewSnapshotDataSource("test-datasource", snapshot.Namespace, snapshot.Name, snapshot.Namespace)
By(fmt.Sprintf("Create new datasource %s", targetDS.Name))
targetDataSource, err := f.CdiClient.CdiV1beta1().DataSources(snapshot.Namespace).Create(context.TODO(), targetDS, metav1.CreateOptions{})
Expect(err).ToNot(HaveOccurred())

targetDV := utils.NewDataVolumeWithSourceRef("target-dv", size, targetDataSource.Namespace, targetDataSource.Name)
targetDV.Spec.PVC.StorageClassName = &f.SnapshotSCName
By(fmt.Sprintf("Create new target datavolume %s", targetDV.Name))
targetDataVolume, err := utils.CreateDataVolumeFromDefinition(f.CdiClient, f.Namespace.Name, targetDV)
Expect(err).ToNot(HaveOccurred())
Expand Down
19 changes: 14 additions & 5 deletions tests/datavolume_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1750,11 +1750,12 @@ var _ = Describe("[vendor:cnv-qe@redhat.com][level:component]DataVolume tests",

updateStorageProfileSpec := func(client client.Client, name string, spec cdiv1.StorageProfileSpec) {
storageProfile := &cdiv1.StorageProfile{}
err := client.Get(context.TODO(), types.NamespacedName{Name: name}, storageProfile)
Expect(err).ToNot(HaveOccurred())
storageProfile.Spec = spec
err = client.Update(context.TODO(), storageProfile)
Expect(err).ToNot(HaveOccurred())
Eventually(func() error {
err := client.Get(context.TODO(), types.NamespacedName{Name: name}, storageProfile)
Expect(err).ToNot(HaveOccurred())
storageProfile.Spec = spec
return client.Update(context.TODO(), storageProfile)
}, 15*time.Second, time.Second).Should(BeNil())
}

configureStorageProfile := func(client client.Client,
Expand Down Expand Up @@ -2378,6 +2379,10 @@ var _ = Describe("[vendor:cnv-qe@redhat.com][level:component]DataVolume tests",
})

table.DescribeTable("import DV using StorageSpec without AccessModes, PVC is created only when", func(scName string, scFunc func(string)) {
if utils.IsDefaultSCNoProvisioner() {
Skip("Default storage class has no provisioner. The new storage class won't work")
}

By(fmt.Sprintf("verifying no storage class %s", testScName))
_, err := f.K8sClient.StorageV1().StorageClasses().Get(context.TODO(), scName, metav1.GetOptions{})
Expect(err).To(HaveOccurred())
Expand Down Expand Up @@ -2444,6 +2449,10 @@ var _ = Describe("[vendor:cnv-qe@redhat.com][level:component]DataVolume tests",
}

table.DescribeTable("import DV with AccessModes, PVC is pending until", func(scName string, scFunc func(string), dvFunc func(string) *cdiv1.DataVolume) {
if utils.IsDefaultSCNoProvisioner() {
Skip("Default storage class has no provisioner. The new storage class won't work")
}

By(fmt.Sprintf("verifying no storage class %s", testScName))
_, err := f.K8sClient.StorageV1().StorageClasses().Get(context.TODO(), scName, metav1.GetOptions{})
Expect(err).To(HaveOccurred())
Expand Down
14 changes: 8 additions & 6 deletions tests/external_population_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,15 +139,15 @@ var _ = Describe("Population tests", func() {
})

It("Should provision storage with any volume data source", func() {
if !f.IsCSIVolumeCloneStorageClassAvailable() {
Skip("No CSI drivers available - Population not supported")
if utils.DefaultStorageClassCsiDriver == nil {
Skip("No CSI drivers available in default SC - Population not supported")
}
if !isAnyVolumeDataSourceEnabled() {
Skip("No AnyVolumeDataSource feature gate")
}

By(fmt.Sprintf("Creating new datavolume %s", dataVolumeName))
dataVolume := utils.NewDataVolumeWithExternalPopulationAndStorageSpec(dataVolumeName, "100Mi", f.CsiCloneSCName, corev1.PersistentVolumeMode(corev1.PersistentVolumeBlock), nil, dataSourceRef)
dataVolume := utils.NewDataVolumeWithExternalPopulationAndStorageSpec(dataVolumeName, "100Mi", utils.DefaultStorageClass.Name, corev1.PersistentVolumeMode(corev1.PersistentVolumeFilesystem), nil, dataSourceRef)
controller.AddAnnotation(dataVolume, controller.AnnDeleteAfterCompletion, "false")
dataVolume, err := utils.CreateDataVolumeFromDefinition(f.CdiClient, f.Namespace.Name, dataVolume)
Expect(err).ToNot(HaveOccurred())
Expand All @@ -163,7 +163,8 @@ var _ = Describe("Population tests", func() {
f.ExpectEvent(dataVolume.Namespace).Should(ContainSubstring(dvc.ExternalPopulationSucceeded))
expectetHash := []byte(expectedContent)
expectedHashString := fmt.Sprintf("%x", md5.Sum(expectetHash))
md5, err := f.GetMD5(f.Namespace, pvc, utils.DefaultPvcMountPath, int64(len(expectedContent)))
filePath := fmt.Sprintf("%s/%s", utils.DefaultPvcMountPath, fileName)
md5, err := f.GetMD5(f.Namespace, pvc, filePath, int64(len(expectedContent)))
Expect(err).ToNot(HaveOccurred())
Expect(md5).To(Equal(expectedHashString))

Expand Down Expand Up @@ -218,8 +219,7 @@ var _ = Describe("Population tests", func() {
}

By(fmt.Sprintf("Creating new datavolume %s", dataVolumeName))
dataVolume := utils.NewDataVolumeWithExternalPopulationAndStorageSpec(dataVolumeName, "100Mi", scName, corev1.PersistentVolumeMode(corev1.PersistentVolumeFilesystem), nil, dataSourceRef)
controller.AddAnnotation(dataVolume, controller.AnnDeleteAfterCompletion, "false")
dataVolume := utils.NewDataVolumeWithExternalPopulationAndStorageSpec(dataVolumeName, "100Mi", scName, corev1.PersistentVolumeMode(corev1.PersistentVolumeFilesystem), nil, dummySourceRef)
dataVolume, err := utils.CreateDataVolumeFromDefinition(f.CdiClient, f.Namespace.Name, dataVolume)
Expect(err).ToNot(HaveOccurred())

Expand Down Expand Up @@ -257,6 +257,7 @@ var _ = Describe("Population tests", func() {

By(fmt.Sprintf("Creating target datavolume %s", dataVolumeName))
dataVolume := utils.NewDataVolumeWithExternalPopulationAndStorageSpec(dataVolumeName, "100Mi", f.CsiCloneSCName, corev1.PersistentVolumeMode(corev1.PersistentVolumeFilesystem), dataSource, nil)
dataVolume.Spec.Storage.StorageClassName = nil
controller.AddAnnotation(dataVolume, controller.AnnDeleteAfterCompletion, "false")
dataVolume, err := utils.CreateDataVolumeFromDefinition(f.CdiClient, f.Namespace.Name, dataVolume)
Expect(err).ToNot(HaveOccurred())
Expand Down Expand Up @@ -299,6 +300,7 @@ var _ = Describe("Population tests", func() {
By("Creating source PVC")
pvcDef := utils.NewPVCDefinition(sourcePVCName, "80Mi", nil, nil)
pvcDef.Namespace = f.Namespace.Name
pvcDef.Spec.StorageClassName = &f.SnapshotSCName
sourcePvc := f.CreateAndPopulateSourcePVC(pvcDef, sourcePodFillerName, fillCommand+testFile+"; chmod 660 "+testBaseDir+testFile)

By("Creating Snapshot")
Expand Down
3 changes: 3 additions & 0 deletions tests/import_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1559,6 +1559,9 @@ var _ = Describe("Import populator", func() {
}

BeforeEach(func() {
if utils.DefaultStorageClassCsiDriver == nil {
Skip("No CSI driver found")
}
verifyCleanup(pvc)
})

Expand Down
3 changes: 3 additions & 0 deletions tests/upload_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,9 @@ var _ = Describe("[rfe_id:138][crit:high][vendor:cnv-qe@redhat.com][level:compon
}

BeforeEach(func() {
if utils.DefaultStorageClassCsiDriver == nil {
Skip("No CSI driver found")
}
verifyCleanup(pvc)
})

Expand Down
7 changes: 6 additions & 1 deletion tests/utils/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,9 +156,14 @@ func IsNfs() bool {
return strings.Contains(DefaultStorageClass.GetName(), "nfs")
}

// IsDefaultSCNoProvisioner return true if the default storage class has no provisioner
func IsDefaultSCNoProvisioner() bool {
return DefaultStorageClass.Provisioner == "kubernetes.io/no-provisioner"
}

// IsStaticNfs returns true if the default storage class is the static nfs storage class with no provisioner
func IsStaticNfs() bool {
return IsNfs() && DefaultStorageClass.Provisioner == "kubernetes.io/no-provisioner"
return IsNfs() && IsDefaultSCNoProvisioner()
}

// IsStaticNfsWithInternalClusterServer returns true if the default storage class is the static nfs storage class with no provisioner
Expand Down

0 comments on commit b26d4fc

Please sign in to comment.