k8s.io/kubernetes@v1.29.3/test/e2e/storage/vsphere/vsphere_volume_ops_storm.go (about)

     1  /*
     2  Copyright 2017 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package vsphere
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"os"
    23  	"strconv"
    24  
    25  	"github.com/onsi/ginkgo/v2"
    26  	"github.com/onsi/gomega"
    27  	v1 "k8s.io/api/core/v1"
    28  	storagev1 "k8s.io/api/storage/v1"
    29  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    30  	clientset "k8s.io/client-go/kubernetes"
    31  	"k8s.io/kubernetes/test/e2e/feature"
    32  	"k8s.io/kubernetes/test/e2e/framework"
    33  	e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
    34  	e2epv "k8s.io/kubernetes/test/e2e/framework/pv"
    35  	e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper"
    36  	"k8s.io/kubernetes/test/e2e/storage/utils"
    37  	admissionapi "k8s.io/pod-security-admission/api"
    38  )
    39  
    40  /*
    41  	Test to perform Disk Ops storm.
    42  
    43  	Steps
    44      	1. Create storage class for thin Provisioning.
    45      	2. Create 30 PVCs using above storage class in annotation, requesting 2 GB files.
    46      	3. Wait until all disks are ready and all PVs and PVCs get bind. (CreateVolume storm)
    47      	4. Create pod to mount volumes using PVCs created in step 2. (AttachDisk storm)
    48      	5. Wait for pod status to be running.
    49      	6. Verify all volumes accessible and available in the pod.
    50      	7. Delete pod.
    51      	8. wait until volumes gets detached. (DetachDisk storm)
    52      	9. Delete all PVCs. This should delete all Disks. (DeleteVolume storm)
    53  		10. Delete storage class.
    54  */
    55  
    56  var _ = utils.SIGDescribe("Volume Operations Storm", feature.Vsphere, func() {
    57  	f := framework.NewDefaultFramework("volume-ops-storm")
    58  	f.NamespacePodSecurityLevel = admissionapi.LevelPrivileged
    59  	const defaultVolumeOpsScale = 30
    60  	var (
    61  		client            clientset.Interface
    62  		namespace         string
    63  		storageclass      *storagev1.StorageClass
    64  		pvclaims          []*v1.PersistentVolumeClaim
    65  		persistentvolumes []*v1.PersistentVolume
    66  		err               error
    67  		volumeOpsScale    int
    68  	)
    69  	ginkgo.BeforeEach(func(ctx context.Context) {
    70  		e2eskipper.SkipUnlessProviderIs("vsphere")
    71  		Bootstrap(f)
    72  		client = f.ClientSet
    73  		namespace = f.Namespace.Name
    74  		gomega.Expect(GetReadySchedulableNodeInfos(ctx, client)).NotTo(gomega.BeEmpty())
    75  		if scale := os.Getenv("VOLUME_OPS_SCALE"); scale != "" {
    76  			volumeOpsScale, err = strconv.Atoi(scale)
    77  			framework.ExpectNoError(err)
    78  		} else {
    79  			volumeOpsScale = defaultVolumeOpsScale
    80  		}
    81  		pvclaims = make([]*v1.PersistentVolumeClaim, volumeOpsScale)
    82  	})
    83  	ginkgo.AfterEach(func(ctx context.Context) {
    84  		ginkgo.By("Deleting PVCs")
    85  		for _, claim := range pvclaims {
    86  			_ = e2epv.DeletePersistentVolumeClaim(ctx, client, claim.Name, namespace)
    87  		}
    88  		ginkgo.By("Deleting StorageClass")
    89  		err = client.StorageV1().StorageClasses().Delete(ctx, storageclass.Name, metav1.DeleteOptions{})
    90  		framework.ExpectNoError(err)
    91  	})
    92  
    93  	ginkgo.It("should create pod with many volumes and verify no attach call fails", func(ctx context.Context) {
    94  		ginkgo.By(fmt.Sprintf("Running test with VOLUME_OPS_SCALE: %v", volumeOpsScale))
    95  		ginkgo.By("Creating Storage Class")
    96  		scParameters := make(map[string]string)
    97  		scParameters["diskformat"] = "thin"
    98  		storageclass, err = client.StorageV1().StorageClasses().Create(ctx, getVSphereStorageClassSpec("thinsc", scParameters, nil, ""), metav1.CreateOptions{})
    99  		framework.ExpectNoError(err)
   100  
   101  		ginkgo.By("Creating PVCs using the Storage Class")
   102  		count := 0
   103  		for count < volumeOpsScale {
   104  			pvclaims[count], err = e2epv.CreatePVC(ctx, client, namespace, getVSphereClaimSpecWithStorageClass(namespace, "2Gi", storageclass))
   105  			framework.ExpectNoError(err)
   106  			count++
   107  		}
   108  
   109  		ginkgo.By("Waiting for all claims to be in bound phase")
   110  		persistentvolumes, err = e2epv.WaitForPVClaimBoundPhase(ctx, client, pvclaims, f.Timeouts.ClaimProvision)
   111  		framework.ExpectNoError(err)
   112  
   113  		ginkgo.By("Creating pod to attach PVs to the node")
   114  		pod, err := e2epod.CreatePod(ctx, client, namespace, nil, pvclaims, f.NamespacePodSecurityLevel, "")
   115  		framework.ExpectNoError(err)
   116  
   117  		ginkgo.By("Verify all volumes are accessible and available in the pod")
   118  		verifyVSphereVolumesAccessible(ctx, client, pod, persistentvolumes)
   119  
   120  		ginkgo.By("Deleting pod")
   121  		framework.ExpectNoError(e2epod.DeletePodWithWait(ctx, client, pod))
   122  
   123  		ginkgo.By("Waiting for volumes to be detached from the node")
   124  		for _, pv := range persistentvolumes {
   125  			framework.ExpectNoError(waitForVSphereDiskToDetach(ctx, pv.Spec.VsphereVolume.VolumePath, pod.Spec.NodeName))
   126  		}
   127  	})
   128  })