Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prepare CDI testing for the upcoming non-CSI lane #2730

Merged
merged 2 commits into from
Jun 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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