diff --git a/pkg/volume/util/operationexecutor/operation_generator.go b/pkg/volume/util/operationexecutor/operation_generator.go index 6fa0a684bbca..2aaf36f7d33f 100644 --- a/pkg/volume/util/operationexecutor/operation_generator.go +++ b/pkg/volume/util/operationexecutor/operation_generator.go @@ -1499,10 +1499,11 @@ func (og *operationGenerator) GenerateExpandVolumeFunc( klog.Infof("ExpandVolume.UpdatePV succeeded for volume %s", pvcWithResizeRequest.QualifiedName()) } + fsVolume, _ := util.CheckVolumeModeFilesystem(volumeSpec) // No Cloudprovider resize needed, lets mark resizing as done // Rest of the volume expand controller code will assume PVC as *not* resized until pvc.Status.Size // reflects user requested size. - if !volumePlugin.RequiresFSResize() { + if !volumePlugin.RequiresFSResize() || !fsVolume { klog.V(4).Infof("Controller resizing done for PVC %s", pvcWithResizeRequest.QualifiedName()) err := resizeMap.MarkAsResized(pvcWithResizeRequest, newSize) diff --git a/test/e2e/storage/testsuites/provisioning.go b/test/e2e/storage/testsuites/provisioning.go index f62672839976..2c034ce31596 100644 --- a/test/e2e/storage/testsuites/provisioning.go +++ b/test/e2e/storage/testsuites/provisioning.go @@ -53,7 +53,7 @@ type StorageClassTest struct { ClaimSize string ExpectedSize string PvCheck func(claim *v1.PersistentVolumeClaim) - VolumeMode *v1.PersistentVolumeMode + VolumeMode v1.PersistentVolumeMode AllowVolumeExpansion bool } diff --git a/test/e2e/storage/volume_expand.go b/test/e2e/storage/volume_expand.go index 6263ca247acc..db50b1c9eaa0 100644 --- a/test/e2e/storage/volume_expand.go +++ b/test/e2e/storage/volume_expand.go @@ -42,11 +42,11 @@ const ( var _ = utils.SIGDescribe("Volume expand", func() { var ( - c clientset.Interface - ns string - err error - pvc *v1.PersistentVolumeClaim - resizableSc *storage.StorageClass + c clientset.Interface + ns string + err error + pvc *v1.PersistentVolumeClaim + storageClassVar *storage.StorageClass ) f := framework.NewDefaultFramework("volume-expand") @@ -55,61 +55,58 @@ var _ = utils.SIGDescribe("Volume expand", func() { c = f.ClientSet ns = f.Namespace.Name framework.ExpectNoError(framework.WaitForAllNodesSchedulable(c, framework.TestContext.NodeSchedulableTimeout)) + }) + + setupFunc := func(allowExpansion bool, blockVolume bool) (*v1.PersistentVolumeClaim, *storage.StorageClass, error) { test := testsuites.StorageClassTest{ - Name: "default", - ClaimSize: "2Gi", - AllowVolumeExpansion: true, + Name: "default", + ClaimSize: "2Gi", } - resizableSc, err = createStorageClass(test, ns, "resizing", c) - framework.ExpectNoError(err, "Error creating resizable storage class") - Expect(resizableSc.AllowVolumeExpansion).NotTo(BeNil()) - Expect(*resizableSc.AllowVolumeExpansion).To(BeTrue()) - - pvc = newClaim(test, ns, "default") - pvc.Spec.StorageClassName = &resizableSc.Name - pvc, err = c.CoreV1().PersistentVolumeClaims(pvc.Namespace).Create(pvc) - framework.ExpectNoError(err, "Error creating pvc") - }) + if allowExpansion { + test.AllowVolumeExpansion = true + } + if blockVolume { + test.VolumeMode = v1.PersistentVolumeBlock + } + + sc, err := createStorageClass(test, ns, "resizing", c) + framework.ExpectNoError(err, "Error creating storage class for resizing") + + tPVC := newClaim(test, ns, "default") + tPVC.Spec.StorageClassName = &sc.Name + tPVC, err = c.CoreV1().PersistentVolumeClaims(tPVC.Namespace).Create(tPVC) + if err != nil { + return nil, sc, err + } + return tPVC, sc, nil + } AfterEach(func() { framework.ExpectNoError(framework.DeletePersistentVolumeClaim(c, pvc.Name, pvc.Namespace)) - framework.ExpectNoError(c.StorageV1().StorageClasses().Delete(resizableSc.Name, nil)) + framework.ExpectNoError(c.StorageV1().StorageClasses().Delete(storageClassVar.Name, nil)) }) It("should not allow expansion of pvcs without AllowVolumeExpansion property", func() { - test := testsuites.StorageClassTest{ - Name: "no-expansion", - ClaimSize: "2Gi", - } - regularSC, err := createStorageClass(test, ns, "noexpand", c) - framework.ExpectNoError(err, "Error creating non-expandable storage class") + pvc, storageClassVar, err = setupFunc(false /* allowExpansion */, false /*BlockVolume*/) + framework.ExpectNoError(err, "Error creating non-expandable PVC") - defer func() { - framework.ExpectNoError(c.StorageV1().StorageClasses().Delete(regularSC.Name, nil)) - }() - Expect(regularSC.AllowVolumeExpansion).To(BeNil()) + Expect(storageClassVar.AllowVolumeExpansion).To(BeNil()) - noExpandPVC := newClaim(test, ns, "noexpand") - noExpandPVC.Spec.StorageClassName = ®ularSC.Name - noExpandPVC, err = c.CoreV1().PersistentVolumeClaims(noExpandPVC.Namespace).Create(noExpandPVC) - framework.ExpectNoError(err, "Error creating pvc") - - defer func() { - framework.ExpectNoError(framework.DeletePersistentVolumeClaim(c, noExpandPVC.Name, noExpandPVC.Namespace)) - }() - - pvcClaims := []*v1.PersistentVolumeClaim{noExpandPVC} + pvcClaims := []*v1.PersistentVolumeClaim{pvc} pvs, err := framework.WaitForPVClaimBoundPhase(c, pvcClaims, framework.ClaimProvisionTimeout) framework.ExpectNoError(err, "Failed waiting for PVC to be bound %v", err) Expect(len(pvs)).To(Equal(1)) By("Expanding non-expandable pvc") newSize := resource.MustParse("6Gi") - noExpandPVC, err = expandPVCSize(noExpandPVC, newSize, c) + pvc, err = expandPVCSize(pvc, newSize, c) Expect(err).To(HaveOccurred(), "While updating non-expandable PVC") }) It("Verify if editing PVC allows resize", func() { + pvc, storageClassVar, err = setupFunc(true /* allowExpansion */, false /*BlockVolume*/) + framework.ExpectNoError(err, "Error creating non-expandable PVC") + By("Waiting for pvc to be in bound phase") pvcClaims := []*v1.PersistentVolumeClaim{pvc} pvs, err := framework.WaitForPVClaimBoundPhase(c, pvcClaims, framework.ClaimProvisionTimeout) @@ -166,6 +163,38 @@ var _ = utils.SIGDescribe("Volume expand", func() { pvcConditions := pvc.Status.Conditions Expect(len(pvcConditions)).To(Equal(0), "pvc should not have conditions") }) + + It("should allow expansion of block volumes", func() { + pvc, storageClassVar, err = setupFunc(true /*allowExpansion*/, true /*blockVolume*/) + + By("Waiting for pvc to be in bound phase") + pvcClaims := []*v1.PersistentVolumeClaim{pvc} + pvs, err := framework.WaitForPVClaimBoundPhase(c, pvcClaims, framework.ClaimProvisionTimeout) + framework.ExpectNoError(err, "Failed waiting for PVC to be bound %v", err) + Expect(len(pvs)).To(Equal(1)) + + By("Expanding current pvc") + newSize := resource.MustParse("6Gi") + pvc, err = expandPVCSize(pvc, newSize, c) + framework.ExpectNoError(err, "While updating pvc for more size") + Expect(pvc).NotTo(BeNil()) + + pvcSize := pvc.Spec.Resources.Requests[v1.ResourceStorage] + if pvcSize.Cmp(newSize) != 0 { + framework.Failf("error updating pvc size %q", pvc.Name) + } + + By("Waiting for cloudprovider resize to finish") + err = waitForControllerVolumeResize(pvc, c, totalResizeWaitPeriod) + framework.ExpectNoError(err, "While waiting for pvc resize to finish") + + By("Waiting for file system resize to finish") + pvc, err = waitForFSResize(pvc, c) + framework.ExpectNoError(err, "while waiting for fs resize to finish") + + pvcConditions := pvc.Status.Conditions + Expect(len(pvcConditions)).To(Equal(0), "pvc should not have conditions") + }) }) func createStorageClass(t testsuites.StorageClassTest, ns string, suffix string, c clientset.Interface) (*storage.StorageClass, error) { diff --git a/test/e2e/storage/volume_provisioning.go b/test/e2e/storage/volume_provisioning.go index cea75f5dc05f..947b47624c0a 100644 --- a/test/e2e/storage/volume_provisioning.go +++ b/test/e2e/storage/volume_provisioning.go @@ -1034,7 +1034,12 @@ func getClaim(claimSize string, ns string) *v1.PersistentVolumeClaim { } func newClaim(t testsuites.StorageClassTest, ns, suffix string) *v1.PersistentVolumeClaim { - return getClaim(t.ClaimSize, ns) + claim := getClaim(t.ClaimSize, ns) + if t.VolumeMode == v1.PersistentVolumeBlock { + blockVolumeMode := v1.PersistentVolumeBlock + claim.Spec.VolumeMode = &blockVolumeMode + } + return claim } func getDefaultPluginName() string {