Commit c81e99d9 authored by Kubernetes Submit Queue's avatar Kubernetes Submit Queue Committed by GitHub

Merge pull request #41728 from vmware/e2eTestsUpdate-v3

Automatic merge from submit-queue (batch tested with PRs 41728, 42231) Adding new tests to e2e/vsphere_volume_placement.go **What this PR does / why we need it**: Adding new tests to e2e/vsphere_volume_placement.go Below is the tests description and test steps. **Test Back-to-back pod creation/deletion with different volume sources on the same worker node** 1. Create volumes - vmdk2, vmdk1 is created in the test setup. 2. Create pod Spec - pod-SpecA with volume path of vmdk1 and NodeSelector set to label assigned to node1. 3. Create pod Spec - pod-SpecB with volume path of vmdk2 and NodeSelector set to label assigned to node1. 4. Create pod-A using pod-SpecA and wait for pod to become ready. 5. Create pod-B using pod-SpecB and wait for POD to become ready. 6. Verify volumes are attached to the node. 7. Create empty file on the volume to make sure volume is accessible. (Perform this step on pod-A and pod-B) 8. Verify file created in step 5 is present on the volume. (perform this step on pod-A and pod-B) 9. Delete pod-A and pod-B 10. Repeatedly (5 times) perform step 4 to 9 and verify associated volume's content is matching. 11. Wait for vmdk1 and vmdk2 to be detached from node. 12. Delete vmdk1 and vmdk2 **Test multiple volumes from different datastore within the same pod** 1. Create volumes - vmdk2 on non default shared datastore. 2. Create pod Spec with volume path of vmdk1 (vmdk1 is created in test setup on default datastore) and vmdk2. 3. Create pod using spec created in step-2 and wait for pod to become ready. 4. Verify both volumes are attached to the node on which pod are created. Write some data to make sure volume are accessible. 5. Delete pod. 6. Wait for vmdk1 and vmdk2 to be detached from node. 7. Create pod using spec created in step-2 and wait for pod to become ready. 8. Verify both volumes are attached to the node on which PODs are created. Verify volume contents are matching with the content written in step 4. 9. Delete POD. 10. Wait for vmdk1 and vmdk2 to be detached from node. 11. Delete vmdk1 and vmdk2 **Test multiple volumes from same datastore within the same pod** 1. Create volumes - vmdk2, vmdk1 is created in testsetup 2. Create pod Spec with volume path of vmdk1 (vmdk1 is created in test setup) and vmdk2. 3. Create pod using spec created in step-2 and wait for pod to become ready. 4. Verify both volumes are attached to the node on which pod are created. Write some data to make sure volume are accessible. 5. Delete pod. 6. Wait for vmdk1 and vmdk2 to be detached from node. 7. Create pod using spec created in step-2 and wait for pod to become ready. 8. Verify both volumes are attached to the node on which PODs are created. Verify volume contents are matching with the content written in step 4. 9. Delete POD. 10. Wait for vmdk1 and vmdk2 to be detached from node. 11. Delete vmdk1 and vmdk2 **Which issue this PR fixes** fixes # **Special notes for your reviewer**: Executed tests against K8S v1.5.3 release **Release note**: ```release-note NONE ``` cc: @kerneltime @abrarshivani @BaluDontu @tusharnt @pdhamdhere
parents 5c2a8c25 57754d6c
...@@ -100,7 +100,7 @@ func PVPVCMapCleanup(c clientset.Interface, ns string, pvols PVMap, claims PVCMa ...@@ -100,7 +100,7 @@ func PVPVCMapCleanup(c clientset.Interface, ns string, pvols PVMap, claims PVCMa
func DeletePersistentVolume(c clientset.Interface, pvName string) { func DeletePersistentVolume(c clientset.Interface, pvName string) {
if c != nil && len(pvName) > 0 { if c != nil && len(pvName) > 0 {
Logf("Deleting PersistentVolume %v", pvName) Logf("Deleting PersistentVolume %v", pvName)
err := c.Core().PersistentVolumes().Delete(pvName, nil) err := c.CoreV1().PersistentVolumes().Delete(pvName, nil)
if err != nil && !apierrs.IsNotFound(err) { if err != nil && !apierrs.IsNotFound(err) {
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
} }
...@@ -111,7 +111,7 @@ func DeletePersistentVolume(c clientset.Interface, pvName string) { ...@@ -111,7 +111,7 @@ func DeletePersistentVolume(c clientset.Interface, pvName string) {
func DeletePersistentVolumeClaim(c clientset.Interface, pvcName string, ns string) { func DeletePersistentVolumeClaim(c clientset.Interface, pvcName string, ns string) {
if c != nil && len(pvcName) > 0 { if c != nil && len(pvcName) > 0 {
Logf("Deleting PersistentVolumeClaim %v", pvcName) Logf("Deleting PersistentVolumeClaim %v", pvcName)
err := c.Core().PersistentVolumeClaims(ns).Delete(pvcName, nil) err := c.CoreV1().PersistentVolumeClaims(ns).Delete(pvcName, nil)
if err != nil && !apierrs.IsNotFound(err) { if err != nil && !apierrs.IsNotFound(err) {
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
} }
...@@ -128,7 +128,7 @@ func DeletePVCandValidatePV(c clientset.Interface, ns string, pvc *v1.Persistent ...@@ -128,7 +128,7 @@ func DeletePVCandValidatePV(c clientset.Interface, ns string, pvc *v1.Persistent
DeletePersistentVolumeClaim(c, pvc.Name, ns) DeletePersistentVolumeClaim(c, pvc.Name, ns)
// Check that the PVC is really deleted. // Check that the PVC is really deleted.
pvc, err := c.Core().PersistentVolumeClaims(ns).Get(pvc.Name, metav1.GetOptions{}) pvc, err := c.CoreV1().PersistentVolumeClaims(ns).Get(pvc.Name, metav1.GetOptions{})
Expect(apierrs.IsNotFound(err)).To(BeTrue()) Expect(apierrs.IsNotFound(err)).To(BeTrue())
// Wait for the PV's phase to return to be `expectPVPhase` // Wait for the PV's phase to return to be `expectPVPhase`
...@@ -137,7 +137,7 @@ func DeletePVCandValidatePV(c clientset.Interface, ns string, pvc *v1.Persistent ...@@ -137,7 +137,7 @@ func DeletePVCandValidatePV(c clientset.Interface, ns string, pvc *v1.Persistent
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
// examine the pv's ClaimRef and UID and compare to expected values // examine the pv's ClaimRef and UID and compare to expected values
pv, err = c.Core().PersistentVolumes().Get(pv.Name, metav1.GetOptions{}) pv, err = c.CoreV1().PersistentVolumes().Get(pv.Name, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
cr := pv.Spec.ClaimRef cr := pv.Spec.ClaimRef
if expectPVPhase == v1.VolumeAvailable { if expectPVPhase == v1.VolumeAvailable {
...@@ -162,7 +162,7 @@ func DeletePVCandValidatePVGroup(c clientset.Interface, ns string, pvols PVMap, ...@@ -162,7 +162,7 @@ func DeletePVCandValidatePVGroup(c clientset.Interface, ns string, pvols PVMap,
var boundPVs, deletedPVCs int var boundPVs, deletedPVCs int
for pvName := range pvols { for pvName := range pvols {
pv, err := c.Core().PersistentVolumes().Get(pvName, metav1.GetOptions{}) pv, err := c.CoreV1().PersistentVolumes().Get(pvName, metav1.GetOptions{})
Expect(apierrs.IsNotFound(err)).To(BeFalse()) Expect(apierrs.IsNotFound(err)).To(BeFalse())
cr := pv.Spec.ClaimRef cr := pv.Spec.ClaimRef
// if pv is bound then delete the pvc it is bound to // if pv is bound then delete the pvc it is bound to
...@@ -173,7 +173,7 @@ func DeletePVCandValidatePVGroup(c clientset.Interface, ns string, pvols PVMap, ...@@ -173,7 +173,7 @@ func DeletePVCandValidatePVGroup(c clientset.Interface, ns string, pvols PVMap,
pvcKey := makePvcKey(ns, cr.Name) pvcKey := makePvcKey(ns, cr.Name)
_, found := claims[pvcKey] _, found := claims[pvcKey]
Expect(found).To(BeTrue()) Expect(found).To(BeTrue())
pvc, err := c.Core().PersistentVolumeClaims(ns).Get(cr.Name, metav1.GetOptions{}) pvc, err := c.CoreV1().PersistentVolumeClaims(ns).Get(cr.Name, metav1.GetOptions{})
Expect(apierrs.IsNotFound(err)).To(BeFalse()) Expect(apierrs.IsNotFound(err)).To(BeFalse())
DeletePVCandValidatePV(c, ns, pvc, pv, expectPVPhase) DeletePVCandValidatePV(c, ns, pvc, pv, expectPVPhase)
delete(claims, pvcKey) delete(claims, pvcKey)
...@@ -186,7 +186,7 @@ func DeletePVCandValidatePVGroup(c clientset.Interface, ns string, pvols PVMap, ...@@ -186,7 +186,7 @@ func DeletePVCandValidatePVGroup(c clientset.Interface, ns string, pvols PVMap,
// create the PV resource. Fails test on error. // create the PV resource. Fails test on error.
func createPV(c clientset.Interface, pv *v1.PersistentVolume) *v1.PersistentVolume { func createPV(c clientset.Interface, pv *v1.PersistentVolume) *v1.PersistentVolume {
pv, err := c.Core().PersistentVolumes().Create(pv) pv, err := c.CoreV1().PersistentVolumes().Create(pv)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
return pv return pv
} }
...@@ -194,7 +194,7 @@ func createPV(c clientset.Interface, pv *v1.PersistentVolume) *v1.PersistentVolu ...@@ -194,7 +194,7 @@ func createPV(c clientset.Interface, pv *v1.PersistentVolume) *v1.PersistentVolu
// create the PVC resource. Fails test on error. // create the PVC resource. Fails test on error.
func CreatePVC(c clientset.Interface, ns string, pvc *v1.PersistentVolumeClaim) *v1.PersistentVolumeClaim { func CreatePVC(c clientset.Interface, ns string, pvc *v1.PersistentVolumeClaim) *v1.PersistentVolumeClaim {
pvc, err := c.Core().PersistentVolumeClaims(ns).Create(pvc) pvc, err := c.CoreV1().PersistentVolumeClaims(ns).Create(pvc)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
return pvc return pvc
} }
...@@ -316,11 +316,11 @@ func WaitOnPVandPVC(c clientset.Interface, ns string, pv *v1.PersistentVolume, p ...@@ -316,11 +316,11 @@ func WaitOnPVandPVC(c clientset.Interface, ns string, pv *v1.PersistentVolume, p
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
// Re-get the pv and pvc objects // Re-get the pv and pvc objects
pv, err = c.Core().PersistentVolumes().Get(pv.Name, metav1.GetOptions{}) pv, err = c.CoreV1().PersistentVolumes().Get(pv.Name, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
// Re-get the pvc and // Re-get the pvc and
pvc, err = c.Core().PersistentVolumeClaims(ns).Get(pvc.Name, metav1.GetOptions{}) pvc, err = c.CoreV1().PersistentVolumeClaims(ns).Get(pvc.Name, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
// The pv and pvc are both bound, but to each other? // The pv and pvc are both bound, but to each other?
...@@ -354,7 +354,7 @@ func WaitAndVerifyBinds(c clientset.Interface, ns string, pvols PVMap, claims PV ...@@ -354,7 +354,7 @@ func WaitAndVerifyBinds(c clientset.Interface, ns string, pvols PVMap, claims PV
} }
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
pv, err := c.Core().PersistentVolumes().Get(pvName, metav1.GetOptions{}) pv, err := c.CoreV1().PersistentVolumes().Get(pvName, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
if cr := pv.Spec.ClaimRef; cr != nil && len(cr.Name) > 0 { if cr := pv.Spec.ClaimRef; cr != nil && len(cr.Name) > 0 {
// Assert bound pvc is a test resource. Failing assertion could // Assert bound pvc is a test resource. Failing assertion could
...@@ -391,7 +391,7 @@ func DeletePodWithWait(f *Framework, c clientset.Interface, pod *v1.Pod) { ...@@ -391,7 +391,7 @@ func DeletePodWithWait(f *Framework, c clientset.Interface, pod *v1.Pod) {
return return
} }
Logf("Deleting pod %v", pod.Name) Logf("Deleting pod %v", pod.Name)
err := c.Core().Pods(pod.Namespace).Delete(pod.Name, nil) err := c.CoreV1().Pods(pod.Namespace).Delete(pod.Name, nil)
if err != nil { if err != nil {
if apierrs.IsNotFound(err) { if apierrs.IsNotFound(err) {
return // assume pod was deleted already return // assume pod was deleted already
...@@ -418,7 +418,7 @@ func CreateWaitAndDeletePod(f *Framework, c clientset.Interface, ns string, clai ...@@ -418,7 +418,7 @@ func CreateWaitAndDeletePod(f *Framework, c clientset.Interface, ns string, clai
pod := MakeWritePod(ns, claimName) pod := MakeWritePod(ns, claimName)
// Instantiate pod (Create) // Instantiate pod (Create)
runPod, err := c.Core().Pods(ns).Create(pod) runPod, err := c.CoreV1().Pods(ns).Create(pod)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
Expect(runPod).NotTo(BeNil()) Expect(runPod).NotTo(BeNil())
...@@ -575,13 +575,13 @@ func MakePod(ns string, pvcName string, isPrivileged bool, command string) *v1.P ...@@ -575,13 +575,13 @@ func MakePod(ns string, pvcName string, isPrivileged bool, command string) *v1.P
// Define and create a pod with a mounted PV. Pod runs infinite loop until killed. // Define and create a pod with a mounted PV. Pod runs infinite loop until killed.
func CreateClientPod(c clientset.Interface, ns string, pvc *v1.PersistentVolumeClaim) *v1.Pod { func CreateClientPod(c clientset.Interface, ns string, pvc *v1.PersistentVolumeClaim) *v1.Pod {
clientPod := MakePod(ns, pvc.Name, true, "") clientPod := MakePod(ns, pvc.Name, true, "")
clientPod, err := c.Core().Pods(ns).Create(clientPod) clientPod, err := c.CoreV1().Pods(ns).Create(clientPod)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
// Verify the pod is running before returning it // Verify the pod is running before returning it
err = WaitForPodRunningInNamespace(c, clientPod) err = WaitForPodRunningInNamespace(c, clientPod)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
clientPod, err = c.Core().Pods(ns).Get(clientPod.Name, metav1.GetOptions{}) clientPod, err = c.CoreV1().Pods(ns).Get(clientPod.Name, metav1.GetOptions{})
Expect(apierrs.IsNotFound(err)).To(BeFalse()) Expect(apierrs.IsNotFound(err)).To(BeFalse())
return clientPod return clientPod
} }
......
...@@ -5484,3 +5484,9 @@ func (f *Framework) NewTestPod(name string, requests v1.ResourceList, limits v1. ...@@ -5484,3 +5484,9 @@ func (f *Framework) NewTestPod(name string, requests v1.ResourceList, limits v1.
}, },
} }
} }
// create empty file at given path on the pod.
func CreateEmptyFileOnPod(namespace string, podName string, filePath string) error {
_, err := RunKubectl("exec", fmt.Sprintf("--namespace=%s", namespace), podName, "--", "/bin/sh", "-c", fmt.Sprintf("touch %s", filePath))
return err
}
...@@ -26,6 +26,7 @@ import ( ...@@ -26,6 +26,7 @@ import (
"k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/uuid"
"k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/util/wait"
"k8s.io/kubernetes/pkg/api/v1" "k8s.io/kubernetes/pkg/api/v1"
storage "k8s.io/kubernetes/pkg/apis/storage/v1beta1" storage "k8s.io/kubernetes/pkg/apis/storage/v1beta1"
...@@ -223,6 +224,7 @@ func getVSphereClaimSpecWithStorageClassAnnotation(ns string, storageclass *stor ...@@ -223,6 +224,7 @@ func getVSphereClaimSpecWithStorageClassAnnotation(ns string, storageclass *stor
return claim return claim
} }
// func to get pod spec with given volume claim, node selector labels and command
func getVSpherePodSpecWithClaim(claimName string, nodeSelectorKV map[string]string, command string) *v1.Pod { func getVSpherePodSpecWithClaim(claimName string, nodeSelectorKV map[string]string, command string) *v1.Pod {
pod := &v1.Pod{ pod := &v1.Pod{
TypeMeta: metav1.TypeMeta{ TypeMeta: metav1.TypeMeta{
...@@ -266,3 +268,67 @@ func getVSpherePodSpecWithClaim(claimName string, nodeSelectorKV map[string]stri ...@@ -266,3 +268,67 @@ func getVSpherePodSpecWithClaim(claimName string, nodeSelectorKV map[string]stri
} }
return pod return pod
} }
// func to get pod spec with given volume paths, node selector lables and container commands
func getVSpherePodSpecWithVolumePaths(volumePaths []string, keyValuelabel map[string]string, commands []string) *v1.Pod {
var volumeMounts []v1.VolumeMount
var volumes []v1.Volume
for index, volumePath := range volumePaths {
name := fmt.Sprintf("volume%v", index+1)
volumeMounts = append(volumeMounts, v1.VolumeMount{Name: name, MountPath: "/mnt/" + name})
vsphereVolume := new(v1.VsphereVirtualDiskVolumeSource)
vsphereVolume.VolumePath = volumePath
vsphereVolume.FSType = "ext4"
volumes = append(volumes, v1.Volume{Name: name})
volumes[index].VolumeSource.VsphereVolume = vsphereVolume
}
if commands == nil || len(commands) == 0 {
commands = []string{
"/bin/sh",
"-c",
"while true; do sleep 2; done",
}
}
pod := &v1.Pod{
TypeMeta: metav1.TypeMeta{
Kind: "Pod",
APIVersion: "v1",
},
ObjectMeta: metav1.ObjectMeta{
GenerateName: "vsphere-e2e-",
},
Spec: v1.PodSpec{
Containers: []v1.Container{
{
Name: "vsphere-e2e-container-" + string(uuid.NewUUID()),
Image: "gcr.io/google_containers/busybox:1.24",
Command: commands,
VolumeMounts: volumeMounts,
},
},
RestartPolicy: v1.RestartPolicyNever,
Volumes: volumes,
},
}
if keyValuelabel != nil {
pod.Spec.NodeSelector = keyValuelabel
}
return pod
}
func verifyFilesExistOnVSphereVolume(namespace string, podName string, filePaths []string) {
for _, filePath := range filePaths {
_, err := framework.RunKubectl("exec", fmt.Sprintf("--namespace=%s", namespace), podName, "--", "/bin/ls", filePath)
Expect(err).NotTo(HaveOccurred(), fmt.Sprintf("failed to verify file: %q on the pod: %q", filePath, podName))
}
}
func createEmptyFilesOnVSphereVolume(namespace string, podName string, filePaths []string) {
for _, filePath := range filePaths {
err := framework.CreateEmptyFileOnPod(namespace, podName, filePath)
Expect(err).NotTo(HaveOccurred())
}
}
...@@ -88,19 +88,19 @@ var _ = framework.KubeDescribe("Volume Disk Format [Volumes]", func() { ...@@ -88,19 +88,19 @@ var _ = framework.KubeDescribe("Volume Disk Format [Volumes]", func() {
It("verify disk format type - eagerzeroedthick is honored for dynamically provisioned pv using storageclass", func() { It("verify disk format type - eagerzeroedthick is honored for dynamically provisioned pv using storageclass", func() {
By("Invoking Test for diskformat: eagerzeroedthick") By("Invoking Test for diskformat: eagerzeroedthick")
invokeTest(client, namespace, nodeName, nodeKeyValueLabel, "eagerzeroedthick") invokeTest(f, client, namespace, nodeName, nodeKeyValueLabel, "eagerzeroedthick")
}) })
It("verify disk format type - zeroedthick is honored for dynamically provisioned pv using storageclass", func() { It("verify disk format type - zeroedthick is honored for dynamically provisioned pv using storageclass", func() {
By("Invoking Test for diskformat: zeroedthick") By("Invoking Test for diskformat: zeroedthick")
invokeTest(client, namespace, nodeName, nodeKeyValueLabel, "zeroedthick") invokeTest(f, client, namespace, nodeName, nodeKeyValueLabel, "zeroedthick")
}) })
It("verify disk format type - thin is honored for dynamically provisioned pv using storageclass", func() { It("verify disk format type - thin is honored for dynamically provisioned pv using storageclass", func() {
By("Invoking Test for diskformat: thin") By("Invoking Test for diskformat: thin")
invokeTest(client, namespace, nodeName, nodeKeyValueLabel, "thin") invokeTest(f, client, namespace, nodeName, nodeKeyValueLabel, "thin")
}) })
}) })
func invokeTest(client clientset.Interface, namespace string, nodeName string, nodeKeyValueLabel map[string]string, diskFormat string) { func invokeTest(f *framework.Framework, client clientset.Interface, namespace string, nodeName string, nodeKeyValueLabel map[string]string, diskFormat string) {
framework.Logf("Invoking Test for DiskFomat: %s", diskFormat) framework.Logf("Invoking Test for DiskFomat: %s", diskFormat)
scParameters := make(map[string]string) scParameters := make(map[string]string)
...@@ -152,8 +152,11 @@ func invokeTest(client clientset.Interface, namespace string, nodeName string, n ...@@ -152,8 +152,11 @@ func invokeTest(client clientset.Interface, namespace string, nodeName string, n
Expect(framework.WaitForPodNameRunningInNamespace(client, pod.Name, namespace)).To(Succeed()) Expect(framework.WaitForPodNameRunningInNamespace(client, pod.Name, namespace)).To(Succeed())
Expect(verifyDiskFormat(nodeName, pv.Spec.VsphereVolume.VolumePath, diskFormat)).To(BeTrue(), "DiskFormat Verification Failed") Expect(verifyDiskFormat(nodeName, pv.Spec.VsphereVolume.VolumePath, diskFormat)).To(BeTrue(), "DiskFormat Verification Failed")
var volumePaths []string
volumePaths = append(volumePaths, pv.Spec.VsphereVolume.VolumePath)
By("Delete pod and wait for volume to be detached from node") By("Delete pod and wait for volume to be detached from node")
deletePodAndWaitForVolumeToDetach(client, namespace, vsp, nodeName, pod, pv.Spec.VsphereVolume.VolumePath) deletePodAndWaitForVolumeToDetach(f, client, pod, vsp, nodeName, volumePaths)
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment