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 })