diff --git a/test/e2e/storage/BUILD b/test/e2e/storage/BUILD index 1fe5ea16350..488094990d3 100644 --- a/test/e2e/storage/BUILD +++ b/test/e2e/storage/BUILD @@ -23,7 +23,6 @@ go_library( "pvc_protection.go", "regional_pd.go", "subpath.go", - "volume_expand.go", "volume_limits.go", "volume_metrics.go", "volume_provisioning.go", diff --git a/test/e2e/storage/csi_mock_volume.go b/test/e2e/storage/csi_mock_volume.go index 8478c45d70d..8973f8f5691 100644 --- a/test/e2e/storage/csi_mock_volume.go +++ b/test/e2e/storage/csi_mock_volume.go @@ -439,7 +439,7 @@ var _ = utils.SIGDescribe("CSI mock volume", func() { ginkgo.By("Expanding current pvc") newSize := resource.MustParse("6Gi") - pvc, err = expandPVCSize(pvc, newSize, m.cs) + pvc, err = testsuites.ExpandPVCSize(pvc, newSize, m.cs) framework.ExpectNoError(err, "While updating pvc for more size") gomega.Expect(pvc).NotTo(gomega.BeNil()) @@ -448,18 +448,18 @@ var _ = utils.SIGDescribe("CSI mock volume", func() { e2elog.Failf("error updating pvc size %q", pvc.Name) } if test.expectFailure { - err = waitForResizingCondition(pvc, m.cs, csiResizingConditionWait) + err = testsuites.WaitForResizingCondition(pvc, m.cs, csiResizingConditionWait) framework.ExpectError(err, "unexpected resizing condition on PVC") return } ginkgo.By("Waiting for persistent volume resize to finish") - err = waitForControllerVolumeResize(pvc, m.cs, csiResizeWaitPeriod) + err = testsuites.WaitForControllerVolumeResize(pvc, m.cs, csiResizeWaitPeriod) framework.ExpectNoError(err, "While waiting for CSI PV resize to finish") checkPVCSize := func() { ginkgo.By("Waiting for PVC resize to finish") - pvc, err = waitForFSResize(pvc, m.cs) + pvc, err = testsuites.WaitForFSResize(pvc, m.cs) framework.ExpectNoError(err, "while waiting for PVC resize to finish") pvcConditions := pvc.Status.Conditions @@ -530,7 +530,7 @@ var _ = utils.SIGDescribe("CSI mock volume", func() { ginkgo.By("Expanding current pvc") newSize := resource.MustParse("6Gi") - pvc, err = expandPVCSize(pvc, newSize, m.cs) + pvc, err = testsuites.ExpandPVCSize(pvc, newSize, m.cs) framework.ExpectNoError(err, "While updating pvc for more size") gomega.Expect(pvc).NotTo(gomega.BeNil()) @@ -540,11 +540,11 @@ var _ = utils.SIGDescribe("CSI mock volume", func() { } ginkgo.By("Waiting for persistent volume resize to finish") - err = waitForControllerVolumeResize(pvc, m.cs, csiResizeWaitPeriod) + err = testsuites.WaitForControllerVolumeResize(pvc, m.cs, csiResizeWaitPeriod) framework.ExpectNoError(err, "While waiting for PV resize to finish") ginkgo.By("Waiting for PVC resize to finish") - pvc, err = waitForFSResize(pvc, m.cs) + pvc, err = testsuites.WaitForFSResize(pvc, m.cs) framework.ExpectNoError(err, "while waiting for PVC to finish") pvcConditions := pvc.Status.Conditions diff --git a/test/e2e/storage/drivers/in_tree.go b/test/e2e/storage/drivers/in_tree.go index f0e271ad358..5a51baf6c92 100644 --- a/test/e2e/storage/drivers/in_tree.go +++ b/test/e2e/storage/drivers/in_tree.go @@ -1152,11 +1152,13 @@ func InitGcePdDriver() testsuites.TestDriver { SupportedFsType: supportedTypes, SupportedMountOption: sets.NewString("debug", "nouid32"), Capabilities: map[testsuites.Capability]bool{ - testsuites.CapPersistence: true, - testsuites.CapFsGroup: true, - testsuites.CapBlock: true, - testsuites.CapExec: true, - testsuites.CapMultiPODs: true, + testsuites.CapPersistence: true, + testsuites.CapFsGroup: true, + testsuites.CapBlock: true, + testsuites.CapExec: true, + testsuites.CapMultiPODs: true, + testsuites.CapControllerExpansion: true, + testsuites.CapNodeExpansion: true, }, }, } @@ -1527,11 +1529,13 @@ func InitAwsDriver() testsuites.TestDriver { ), SupportedMountOption: sets.NewString("debug", "nouid32"), Capabilities: map[testsuites.Capability]bool{ - testsuites.CapPersistence: true, - testsuites.CapFsGroup: true, - testsuites.CapBlock: true, - testsuites.CapExec: true, - testsuites.CapMultiPODs: true, + testsuites.CapPersistence: true, + testsuites.CapFsGroup: true, + testsuites.CapBlock: true, + testsuites.CapExec: true, + testsuites.CapMultiPODs: true, + testsuites.CapControllerExpansion: true, + testsuites.CapNodeExpansion: true, }, }, } diff --git a/test/e2e/storage/external/external.go b/test/e2e/storage/external/external.go index d70012d0eb0..47f13741ff9 100644 --- a/test/e2e/storage/external/external.go +++ b/test/e2e/storage/external/external.go @@ -47,6 +47,7 @@ var csiTestSuites = []func() testsuites.TestSuite{ testsuites.InitVolumeIOTestSuite, testsuites.InitVolumeModeTestSuite, testsuites.InitVolumesTestSuite, + testsuites.InitVolumeExpandTestSuite, } func init() { diff --git a/test/e2e/storage/flexvolume_mounted_volume_resize.go b/test/e2e/storage/flexvolume_mounted_volume_resize.go index 310655e969d..b06626255a3 100644 --- a/test/e2e/storage/flexvolume_mounted_volume_resize.go +++ b/test/e2e/storage/flexvolume_mounted_volume_resize.go @@ -19,6 +19,7 @@ package storage import ( "fmt" "path" + "time" "github.com/onsi/ginkgo" "github.com/onsi/gomega" @@ -35,6 +36,11 @@ import ( "k8s.io/kubernetes/test/e2e/storage/utils" ) +const ( + // total time to wait for cloudprovider or file system resize to finish + totalResizeWaitPeriod = 5 * time.Minute +) + var _ = utils.SIGDescribe("Mounted flexvolume expand[Slow]", func() { var ( c clientset.Interface @@ -83,7 +89,7 @@ var _ = utils.SIGDescribe("Mounted flexvolume expand[Slow]", func() { Provisioner: "flex-expand", } - resizableSc, err = createStorageClass(test, ns, "resizing", c) + resizableSc, err = c.StorageV1().StorageClasses().Create(newStorageClass(test, ns, "resizing")) if err != nil { fmt.Printf("storage class creation error: %v\n", err) } @@ -151,7 +157,7 @@ var _ = utils.SIGDescribe("Mounted flexvolume expand[Slow]", func() { ginkgo.By("Expanding current pvc") newSize := resource.MustParse("6Gi") - pvc, err = expandPVCSize(pvc, newSize, c) + pvc, err = testsuites.ExpandPVCSize(pvc, newSize, c) framework.ExpectNoError(err, "While updating pvc for more size") gomega.Expect(pvc).NotTo(gomega.BeNil()) @@ -161,7 +167,7 @@ var _ = utils.SIGDescribe("Mounted flexvolume expand[Slow]", func() { } ginkgo.By("Waiting for cloudprovider resize to finish") - err = waitForControllerVolumeResize(pvc, c, totalResizeWaitPeriod) + err = testsuites.WaitForControllerVolumeResize(pvc, c, totalResizeWaitPeriod) framework.ExpectNoError(err, "While waiting for pvc resize to finish") ginkgo.By("Getting a pod from deployment") @@ -178,7 +184,7 @@ var _ = utils.SIGDescribe("Mounted flexvolume expand[Slow]", func() { framework.ExpectNoError(err, "While waiting for pod to be recreated") ginkgo.By("Waiting for file system resize to finish") - pvc, err = waitForFSResize(pvc, c) + pvc, err = testsuites.WaitForFSResize(pvc, c) framework.ExpectNoError(err, "while waiting for fs resize to finish") pvcConditions := pvc.Status.Conditions diff --git a/test/e2e/storage/flexvolume_online_resize.go b/test/e2e/storage/flexvolume_online_resize.go index e10262c9689..f7469302bc5 100644 --- a/test/e2e/storage/flexvolume_online_resize.go +++ b/test/e2e/storage/flexvolume_online_resize.go @@ -81,7 +81,7 @@ var _ = utils.SIGDescribe("Mounted flexvolume volume expand [Slow] [Feature:Expa Provisioner: "flex-expand", } - resizableSc, err = createStorageClass(test, ns, "resizing", c) + resizableSc, err = c.StorageV1().StorageClasses().Create(newStorageClass(test, ns, "resizing")) if err != nil { fmt.Printf("storage class creation error: %v\n", err) } @@ -155,7 +155,7 @@ var _ = utils.SIGDescribe("Mounted flexvolume volume expand [Slow] [Feature:Expa ginkgo.By("Expanding current pvc") newSize := resource.MustParse("6Gi") - pvc, err = expandPVCSize(pvc, newSize, c) + pvc, err = testsuites.ExpandPVCSize(pvc, newSize, c) framework.ExpectNoError(err, "While updating pvc for more size") gomega.Expect(pvc).NotTo(gomega.BeNil()) @@ -165,11 +165,11 @@ var _ = utils.SIGDescribe("Mounted flexvolume volume expand [Slow] [Feature:Expa } ginkgo.By("Waiting for cloudprovider resize to finish") - err = waitForControllerVolumeResize(pvc, c, totalResizeWaitPeriod) + err = testsuites.WaitForControllerVolumeResize(pvc, c, totalResizeWaitPeriod) framework.ExpectNoError(err, "While waiting for pvc resize to finish") ginkgo.By("Waiting for file system resize to finish") - pvc, err = waitForFSResize(pvc, c) + pvc, err = testsuites.WaitForFSResize(pvc, c) framework.ExpectNoError(err, "while waiting for fs resize to finish") pvcConditions := pvc.Status.Conditions diff --git a/test/e2e/storage/in_tree_volumes.go b/test/e2e/storage/in_tree_volumes.go index 183a142dd36..7897e8980ac 100644 --- a/test/e2e/storage/in_tree_volumes.go +++ b/test/e2e/storage/in_tree_volumes.go @@ -56,6 +56,7 @@ var testSuites = []func() testsuites.TestSuite{ testsuites.InitSubPathTestSuite, testsuites.InitProvisioningTestSuite, testsuites.InitMultiVolumeTestSuite, + testsuites.InitVolumeExpandTestSuite, } // This executes testSuites for in-tree volumes. diff --git a/test/e2e/storage/mounted_volume_resize.go b/test/e2e/storage/mounted_volume_resize.go index 33ff97e853a..a2ec64d30c6 100644 --- a/test/e2e/storage/mounted_volume_resize.go +++ b/test/e2e/storage/mounted_volume_resize.go @@ -81,7 +81,7 @@ var _ = utils.SIGDescribe("Mounted volume expand", func() { AllowVolumeExpansion: true, DelayBinding: true, } - resizableSc, err = createStorageClass(test, ns, "resizing", c) + resizableSc, err = c.StorageV1().StorageClasses().Create(newStorageClass(test, ns, "resizing")) framework.ExpectNoError(err, "Error creating resizable storage class") gomega.Expect(*resizableSc.AllowVolumeExpansion).To(gomega.BeTrue()) @@ -128,7 +128,7 @@ var _ = utils.SIGDescribe("Mounted volume expand", func() { ginkgo.By("Expanding current pvc") newSize := resource.MustParse("6Gi") - pvc, err = expandPVCSize(pvc, newSize, c) + pvc, err = testsuites.ExpandPVCSize(pvc, newSize, c) framework.ExpectNoError(err, "While updating pvc for more size") gomega.Expect(pvc).NotTo(gomega.BeNil()) @@ -138,7 +138,7 @@ var _ = utils.SIGDescribe("Mounted volume expand", func() { } ginkgo.By("Waiting for cloudprovider resize to finish") - err = waitForControllerVolumeResize(pvc, c, totalResizeWaitPeriod) + err = testsuites.WaitForControllerVolumeResize(pvc, c, totalResizeWaitPeriod) framework.ExpectNoError(err, "While waiting for pvc resize to finish") ginkgo.By("Getting a pod from deployment") @@ -155,7 +155,7 @@ var _ = utils.SIGDescribe("Mounted volume expand", func() { framework.ExpectNoError(err, "While waiting for pod to be recreated") ginkgo.By("Waiting for file system resize to finish") - pvc, err = waitForFSResize(pvc, c) + pvc, err = testsuites.WaitForFSResize(pvc, c) framework.ExpectNoError(err, "while waiting for fs resize to finish") pvcConditions := pvc.Status.Conditions diff --git a/test/e2e/storage/testpatterns/BUILD b/test/e2e/storage/testpatterns/BUILD index 1dfac5797e9..1374bf7e04c 100644 --- a/test/e2e/storage/testpatterns/BUILD +++ b/test/e2e/storage/testpatterns/BUILD @@ -7,6 +7,7 @@ go_library( visibility = ["//visibility:public"], deps = [ "//staging/src/k8s.io/api/core/v1:go_default_library", + "//staging/src/k8s.io/api/storage/v1:go_default_library", "//test/e2e/framework/volume:go_default_library", ], ) diff --git a/test/e2e/storage/testpatterns/testpattern.go b/test/e2e/storage/testpatterns/testpattern.go index f610ac5d9b9..335f5239388 100644 --- a/test/e2e/storage/testpatterns/testpattern.go +++ b/test/e2e/storage/testpatterns/testpattern.go @@ -18,6 +18,7 @@ package testpatterns import ( "k8s.io/api/core/v1" + storagev1 "k8s.io/api/storage/v1" "k8s.io/kubernetes/test/e2e/framework/volume" ) @@ -55,12 +56,14 @@ var ( // TestPattern represents a combination of parameters to be tested in a TestSuite type TestPattern struct { - Name string // Name of TestPattern - FeatureTag string // featureTag for the TestSuite - VolType TestVolType // Volume type of the volume - FsType string // Fstype of the volume - VolMode v1.PersistentVolumeMode // PersistentVolumeMode of the volume - SnapshotType TestSnapshotType // Snapshot type of the snapshot + Name string // Name of TestPattern + FeatureTag string // featureTag for the TestSuite + VolType TestVolType // Volume type of the volume + FsType string // Fstype of the volume + VolMode v1.PersistentVolumeMode // PersistentVolumeMode of the volume + SnapshotType TestSnapshotType // Snapshot type of the snapshot + BindingMode storagev1.VolumeBindingMode // VolumeBindingMode of the volume + AllowExpansion bool // AllowVolumeExpansion flag of the StorageClass } var ( @@ -195,7 +198,7 @@ var ( VolType: PreprovisionedPV, VolMode: v1.PersistentVolumeBlock, } - // BlockVolModeDynamicPV is TestPattern for "Dynamic PV (block)(immediate bind)" + // BlockVolModeDynamicPV is TestPattern for "Dynamic PV (block)" BlockVolModeDynamicPV = TestPattern{ Name: "Dynamic PV (block volmode)", VolType: DynamicPV, @@ -209,4 +212,22 @@ var ( Name: "Dynamic Snapshot", SnapshotType: DynamicCreatedSnapshot, } + + // Definitions for volume expansion case + + // DefaultFsDynamicPVAllowExpansion is TestPattern for "Dynamic PV (default fs)(allowExpansion)" + DefaultFsDynamicPVAllowExpansion = TestPattern{ + Name: "Dynamic PV (default fs)(allowExpansion)", + VolType: DynamicPV, + BindingMode: storagev1.VolumeBindingWaitForFirstConsumer, + AllowExpansion: true, + } + // BlockVolModeDynamicPVAllowExpansion is TestPattern for "Dynamic PV (block volmode)(allowExpansion)" + BlockVolModeDynamicPVAllowExpansion = TestPattern{ + Name: "Dynamic PV (block volmode)(allowExpansion)", + VolType: DynamicPV, + VolMode: v1.PersistentVolumeBlock, + BindingMode: storagev1.VolumeBindingWaitForFirstConsumer, + AllowExpansion: true, + } ) diff --git a/test/e2e/storage/testsuites/BUILD b/test/e2e/storage/testsuites/BUILD index 782146b02b6..a39fc31e64e 100644 --- a/test/e2e/storage/testsuites/BUILD +++ b/test/e2e/storage/testsuites/BUILD @@ -10,6 +10,7 @@ go_library( "snapshottable.go", "subpath.go", "testdriver.go", + "volume_expand.go", "volume_io.go", "volumemode.go", "volumes.go", diff --git a/test/e2e/storage/testsuites/base.go b/test/e2e/storage/testsuites/base.go index b269a2e5f2d..81a33ef88a9 100644 --- a/test/e2e/storage/testsuites/base.go +++ b/test/e2e/storage/testsuites/base.go @@ -186,23 +186,21 @@ func createGenericVolumeTestResource(driver TestDriver, config *PerTestConfig, p dInfo := driver.GetDriverInfo() f := config.Framework cs := f.ClientSet - fsType := pattern.FsType - volType := pattern.VolType // Create volume for pre-provisioned volume tests - r.volume = CreateVolume(driver, config, volType) + r.volume = CreateVolume(driver, config, pattern.VolType) - switch volType { + switch pattern.VolType { case testpatterns.InlineVolume: e2elog.Logf("Creating resource for inline volume") if iDriver, ok := driver.(InlineVolumeTestDriver); ok { - r.volSource = iDriver.GetVolumeSource(false, fsType, r.volume) + r.volSource = iDriver.GetVolumeSource(false, pattern.FsType, r.volume) r.volType = dInfo.Name } case testpatterns.PreprovisionedPV: e2elog.Logf("Creating resource for pre-provisioned PV") if pDriver, ok := driver.(PreprovisionedPVTestDriver); ok { - pvSource, volumeNodeAffinity := pDriver.GetPersistentVolumeSource(false, fsType, r.volume) + pvSource, volumeNodeAffinity := pDriver.GetPersistentVolumeSource(false, pattern.FsType, r.volume) if pvSource != nil { r.volSource, r.pv, r.pvc = createVolumeSourceWithPVCPV(f, dInfo.Name, pvSource, volumeNodeAffinity, false, pattern.VolMode) } @@ -212,7 +210,14 @@ func createGenericVolumeTestResource(driver TestDriver, config *PerTestConfig, p e2elog.Logf("Creating resource for dynamic PV") if dDriver, ok := driver.(DynamicPVTestDriver); ok { claimSize := dDriver.GetClaimSize() - r.sc = dDriver.GetDynamicProvisionStorageClass(r.config, fsType) + r.sc = dDriver.GetDynamicProvisionStorageClass(r.config, pattern.FsType) + + if pattern.BindingMode != "" { + r.sc.VolumeBindingMode = &pattern.BindingMode + } + if pattern.AllowExpansion != false { + r.sc.AllowVolumeExpansion = &pattern.AllowExpansion + } ginkgo.By("creating a StorageClass " + r.sc.Name) var err error @@ -226,11 +231,11 @@ func createGenericVolumeTestResource(driver TestDriver, config *PerTestConfig, p r.volType = fmt.Sprintf("%s-dynamicPV", dInfo.Name) } default: - e2elog.Failf("genericVolumeTestResource doesn't support: %s", volType) + e2elog.Failf("genericVolumeTestResource doesn't support: %s", pattern.VolType) } if r.volSource == nil { - framework.Skipf("Driver %s doesn't support %v -- skipping", dInfo.Name, volType) + framework.Skipf("Driver %s doesn't support %v -- skipping", dInfo.Name, pattern.VolType) } return &r @@ -239,10 +244,9 @@ func createGenericVolumeTestResource(driver TestDriver, config *PerTestConfig, p // cleanupResource cleans up genericVolumeTestResource func (r *genericVolumeTestResource) cleanupResource() { f := r.config.Framework - volType := r.pattern.VolType if r.pvc != nil || r.pv != nil { - switch volType { + switch r.pattern.VolType { case testpatterns.PreprovisionedPV: ginkgo.By("Deleting pv and pvc") if errs := framework.PVPVCCleanup(f.ClientSet, f.Namespace.Name, r.pv, r.pvc); len(errs) != 0 { diff --git a/test/e2e/storage/testsuites/testdriver.go b/test/e2e/storage/testsuites/testdriver.go index bb2cf5cf0b9..59a9d97a297 100644 --- a/test/e2e/storage/testsuites/testdriver.go +++ b/test/e2e/storage/testsuites/testdriver.go @@ -127,7 +127,9 @@ const ( // - NodeStageVolume in the spec CapMultiPODs Capability = "multipods" - CapRWX Capability = "RWX" // support ReadWriteMany access modes + CapRWX Capability = "RWX" // support ReadWriteMany access modes + CapControllerExpansion Capability = "controllerExpansion" // support volume expansion for controller + CapNodeExpansion Capability = "nodeExpansion" // support volume expansion for node ) // DriverInfo represents static information about a TestDriver. diff --git a/test/e2e/storage/testsuites/volume_expand.go b/test/e2e/storage/testsuites/volume_expand.go new file mode 100644 index 00000000000..d973be2febd --- /dev/null +++ b/test/e2e/storage/testsuites/volume_expand.go @@ -0,0 +1,344 @@ +/* +Copyright 2017 The Kubernetes Authors. + +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. +*/ + +package testsuites + +import ( + "fmt" + "time" + + "github.com/onsi/ginkgo" + "github.com/onsi/gomega" + + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/wait" + clientset "k8s.io/client-go/kubernetes" + "k8s.io/kubernetes/test/e2e/framework" + e2elog "k8s.io/kubernetes/test/e2e/framework/log" + "k8s.io/kubernetes/test/e2e/storage/testpatterns" +) + +const ( + resizePollInterval = 2 * time.Second + // total time to wait for cloudprovider or file system resize to finish + totalResizeWaitPeriod = 10 * time.Minute +) + +type volumeExpandTestSuite struct { + tsInfo TestSuiteInfo +} + +var _ TestSuite = &volumeExpandTestSuite{} + +// InitVolumeExpandTestSuite returns volumeExpandTestSuite that implements TestSuite interface +func InitVolumeExpandTestSuite() TestSuite { + return &volumeExpandTestSuite{ + tsInfo: TestSuiteInfo{ + name: "volume-expand", + testPatterns: []testpatterns.TestPattern{ + testpatterns.DefaultFsDynamicPV, + testpatterns.BlockVolModeDynamicPV, + testpatterns.DefaultFsDynamicPVAllowExpansion, + testpatterns.BlockVolModeDynamicPVAllowExpansion, + }, + }, + } +} + +func (v *volumeExpandTestSuite) getTestSuiteInfo() TestSuiteInfo { + return v.tsInfo +} + +func (v *volumeExpandTestSuite) defineTests(driver TestDriver, pattern testpatterns.TestPattern) { + type local struct { + config *PerTestConfig + testCleanup func() + + resource *genericVolumeTestResource + pod *v1.Pod + pod2 *v1.Pod + + intreeOps opCounts + migratedOps opCounts + } + var l local + + ginkgo.BeforeEach(func() { + // Check preconditions. + if !driver.GetDriverInfo().Capabilities[CapBlock] && pattern.VolMode == v1.PersistentVolumeBlock { + framework.Skipf("Driver %q does not support block volume mode - skipping", driver.GetDriverInfo().Name) + } + if !driver.GetDriverInfo().Capabilities[CapControllerExpansion] { + framework.Skipf("Driver %q does not support volume expansion - skipping", driver.GetDriverInfo().Name) + } + }) + + // This intentionally comes after checking the preconditions because it + // registers its own BeforeEach which creates the namespace. Beware that it + // also registers an AfterEach which renders f unusable. Any code using + // f must run inside an It or Context callback. + f := framework.NewDefaultFramework("volume-expand") + + init := func() { + l = local{} + + // Now do the more expensive test initialization. + l.config, l.testCleanup = driver.PrepareTest(f) + l.intreeOps, l.migratedOps = getMigrationVolumeOpCounts(f.ClientSet, driver.GetDriverInfo().InTreePluginName) + l.resource = createGenericVolumeTestResource(driver, l.config, pattern) + } + + cleanup := func() { + if l.pod != nil { + ginkgo.By("Deleting pod") + err := framework.DeletePodWithWait(f, f.ClientSet, l.pod) + framework.ExpectNoError(err, "while deleting pod") + l.pod = nil + } + + if l.pod2 != nil { + ginkgo.By("Deleting pod2") + err := framework.DeletePodWithWait(f, f.ClientSet, l.pod2) + framework.ExpectNoError(err, "while deleting pod2") + l.pod2 = nil + } + + if l.resource != nil { + l.resource.cleanupResource() + l.resource = nil + } + + if l.testCleanup != nil { + l.testCleanup() + l.testCleanup = nil + } + + validateMigrationVolumeOpCounts(f.ClientSet, driver.GetDriverInfo().InTreePluginName, l.intreeOps, l.migratedOps) + } + + if !pattern.AllowExpansion { + ginkgo.It("should not allow expansion of pvcs without AllowVolumeExpansion property", func() { + init() + defer cleanup() + + var err error + gomega.Expect(l.resource.sc.AllowVolumeExpansion).To(gomega.BeNil()) + ginkgo.By("Expanding non-expandable pvc") + currentPvcSize := l.resource.pvc.Spec.Resources.Requests[v1.ResourceStorage] + newSize := currentPvcSize.DeepCopy() + newSize.Add(resource.MustParse("1Gi")) + e2elog.Logf("currentPvcSize %v, newSize %v", currentPvcSize, newSize) + l.resource.pvc, err = ExpandPVCSize(l.resource.pvc, newSize, f.ClientSet) + framework.ExpectError(err, "While updating non-expandable PVC") + }) + } else { + ginkgo.It("Verify if offline PVC expansion works", func() { + init() + defer cleanup() + + var err error + ginkgo.By("Creating a pod with dynamically provisioned volume") + l.pod, err = framework.CreateSecPodWithNodeSelection(f.ClientSet, f.Namespace.Name, []*v1.PersistentVolumeClaim{l.resource.pvc}, false, "", false, false, framework.SELinuxLabel, nil, framework.NodeSelection{Name: l.config.ClientNodeName}, framework.PodStartTimeout) + defer func() { + err = framework.DeletePodWithWait(f, f.ClientSet, l.pod) + framework.ExpectNoError(err, "while cleaning up pod already deleted in resize test") + }() + framework.ExpectNoError(err, "While creating pods for resizing") + + ginkgo.By("Deleting the previously created pod") + err = framework.DeletePodWithWait(f, f.ClientSet, l.pod) + framework.ExpectNoError(err, "while deleting pod for resizing") + + // We expand the PVC while no pod is using it to ensure offline expansion + ginkgo.By("Expanding current pvc") + currentPvcSize := l.resource.pvc.Spec.Resources.Requests[v1.ResourceStorage] + newSize := currentPvcSize.DeepCopy() + newSize.Add(resource.MustParse("1Gi")) + e2elog.Logf("currentPvcSize %v, newSize %v", currentPvcSize, newSize) + l.resource.pvc, err = ExpandPVCSize(l.resource.pvc, newSize, f.ClientSet) + framework.ExpectNoError(err, "While updating pvc for more size") + gomega.Expect(l.resource.pvc).NotTo(gomega.BeNil()) + + pvcSize := l.resource.pvc.Spec.Resources.Requests[v1.ResourceStorage] + if pvcSize.Cmp(newSize) != 0 { + e2elog.Failf("error updating pvc size %q", l.resource.pvc.Name) + } + + ginkgo.By("Waiting for cloudprovider resize to finish") + err = WaitForControllerVolumeResize(l.resource.pvc, f.ClientSet, totalResizeWaitPeriod) + framework.ExpectNoError(err, "While waiting for pvc resize to finish") + + ginkgo.By("Checking for conditions on pvc") + l.resource.pvc, err = f.ClientSet.CoreV1().PersistentVolumeClaims(f.Namespace.Name).Get(l.resource.pvc.Name, metav1.GetOptions{}) + framework.ExpectNoError(err, "While fetching pvc after controller resize") + + if pattern.VolMode == v1.PersistentVolumeBlock || !l.resource.driver.GetDriverInfo().Capabilities[CapNodeExpansion] { + pvcConditions := l.resource.pvc.Status.Conditions + framework.ExpectEqual(len(pvcConditions), 0, "pvc should not have conditions") + } else { + inProgressConditions := l.resource.pvc.Status.Conditions + framework.ExpectEqual(len(inProgressConditions), 1, "pvc must have file system resize pending condition") + framework.ExpectEqual(inProgressConditions[0].Type, v1.PersistentVolumeClaimFileSystemResizePending, "pvc must have fs resizing condition") + } + + ginkgo.By("Creating a new pod with same volume") + l.pod2, err = framework.CreateSecPodWithNodeSelection(f.ClientSet, f.Namespace.Name, []*v1.PersistentVolumeClaim{l.resource.pvc}, false, "", false, false, framework.SELinuxLabel, nil, framework.NodeSelection{Name: l.config.ClientNodeName}, framework.PodStartTimeout) + defer func() { + err = framework.DeletePodWithWait(f, f.ClientSet, l.pod2) + framework.ExpectNoError(err, "while cleaning up pod before exiting resizing test") + }() + framework.ExpectNoError(err, "while recreating pod for resizing") + + ginkgo.By("Waiting for file system resize to finish") + l.resource.pvc, err = WaitForFSResize(l.resource.pvc, f.ClientSet) + framework.ExpectNoError(err, "while waiting for fs resize to finish") + + pvcConditions := l.resource.pvc.Status.Conditions + framework.ExpectEqual(len(pvcConditions), 0, "pvc should not have conditions") + }) + + ginkgo.It("should resize volume when PVC is edited while pod is using it", func() { + init() + defer cleanup() + + var err error + ginkgo.By("Creating a pod with dynamically provisioned volume") + l.pod, err = framework.CreateSecPodWithNodeSelection(f.ClientSet, f.Namespace.Name, []*v1.PersistentVolumeClaim{l.resource.pvc}, false, "", false, false, framework.SELinuxLabel, nil, framework.NodeSelection{Name: l.config.ClientNodeName}, framework.PodStartTimeout) + defer func() { + err = framework.DeletePodWithWait(f, f.ClientSet, l.pod) + framework.ExpectNoError(err, "while cleaning up pod already deleted in resize test") + }() + framework.ExpectNoError(err, "While creating pods for resizing") + + // We expand the PVC while no pod is using it to ensure offline expansion + ginkgo.By("Expanding current pvc") + currentPvcSize := l.resource.pvc.Spec.Resources.Requests[v1.ResourceStorage] + newSize := currentPvcSize.DeepCopy() + newSize.Add(resource.MustParse("1Gi")) + e2elog.Logf("currentPvcSize %v, newSize %v", currentPvcSize, newSize) + l.resource.pvc, err = ExpandPVCSize(l.resource.pvc, newSize, f.ClientSet) + framework.ExpectNoError(err, "While updating pvc for more size") + gomega.Expect(l.resource.pvc).NotTo(gomega.BeNil()) + + pvcSize := l.resource.pvc.Spec.Resources.Requests[v1.ResourceStorage] + if pvcSize.Cmp(newSize) != 0 { + e2elog.Failf("error updating pvc size %q", l.resource.pvc.Name) + } + + ginkgo.By("Waiting for cloudprovider resize to finish") + err = WaitForControllerVolumeResize(l.resource.pvc, f.ClientSet, totalResizeWaitPeriod) + framework.ExpectNoError(err, "While waiting for pvc resize to finish") + + ginkgo.By("Waiting for file system resize to finish") + l.resource.pvc, err = WaitForFSResize(l.resource.pvc, f.ClientSet) + framework.ExpectNoError(err, "while waiting for fs resize to finish") + + pvcConditions := l.resource.pvc.Status.Conditions + framework.ExpectEqual(len(pvcConditions), 0, "pvc should not have conditions") + }) + + } +} + +// ExpandPVCSize expands PVC size +func ExpandPVCSize(origPVC *v1.PersistentVolumeClaim, size resource.Quantity, c clientset.Interface) (*v1.PersistentVolumeClaim, error) { + pvcName := origPVC.Name + updatedPVC := origPVC.DeepCopy() + + waitErr := wait.PollImmediate(resizePollInterval, 30*time.Second, func() (bool, error) { + var err error + updatedPVC, err = c.CoreV1().PersistentVolumeClaims(origPVC.Namespace).Get(pvcName, metav1.GetOptions{}) + if err != nil { + return false, fmt.Errorf("error fetching pvc %q for resizing with %v", pvcName, err) + } + + updatedPVC.Spec.Resources.Requests[v1.ResourceStorage] = size + updatedPVC, err = c.CoreV1().PersistentVolumeClaims(origPVC.Namespace).Update(updatedPVC) + if err == nil { + return true, nil + } + e2elog.Logf("Error updating pvc %s with %v", pvcName, err) + return false, nil + }) + return updatedPVC, waitErr +} + +// WaitForResizingCondition waits for the pvc condition to be PersistentVolumeClaimResizing +func WaitForResizingCondition(pvc *v1.PersistentVolumeClaim, c clientset.Interface, duration time.Duration) error { + waitErr := wait.PollImmediate(resizePollInterval, duration, func() (bool, error) { + var err error + updatedPVC, err := c.CoreV1().PersistentVolumeClaims(pvc.Namespace).Get(pvc.Name, metav1.GetOptions{}) + + if err != nil { + return false, fmt.Errorf("error fetching pvc %q for checking for resize status : %v", pvc.Name, err) + } + + pvcConditions := updatedPVC.Status.Conditions + if len(pvcConditions) > 0 { + if pvcConditions[0].Type == v1.PersistentVolumeClaimResizing { + return true, nil + } + } + return false, nil + }) + return waitErr +} + +// WaitForControllerVolumeResize waits for the controller resize to be finished +func WaitForControllerVolumeResize(pvc *v1.PersistentVolumeClaim, c clientset.Interface, duration time.Duration) error { + pvName := pvc.Spec.VolumeName + return wait.PollImmediate(resizePollInterval, duration, func() (bool, error) { + pvcSize := pvc.Spec.Resources.Requests[v1.ResourceStorage] + + pv, err := c.CoreV1().PersistentVolumes().Get(pvName, metav1.GetOptions{}) + if err != nil { + return false, fmt.Errorf("error fetching pv %q for resizing %v", pvName, err) + } + + pvSize := pv.Spec.Capacity[v1.ResourceStorage] + + // If pv size is greater or equal to requested size that means controller resize is finished. + if pvSize.Cmp(pvcSize) >= 0 { + return true, nil + } + return false, nil + }) +} + +// WaitForFSResize waits for the filesystem in the pv to be resized +func WaitForFSResize(pvc *v1.PersistentVolumeClaim, c clientset.Interface) (*v1.PersistentVolumeClaim, error) { + var updatedPVC *v1.PersistentVolumeClaim + waitErr := wait.PollImmediate(resizePollInterval, totalResizeWaitPeriod, func() (bool, error) { + var err error + updatedPVC, err = c.CoreV1().PersistentVolumeClaims(pvc.Namespace).Get(pvc.Name, metav1.GetOptions{}) + + if err != nil { + return false, fmt.Errorf("error fetching pvc %q for checking for resize status : %v", pvc.Name, err) + } + + pvcSize := updatedPVC.Spec.Resources.Requests[v1.ResourceStorage] + pvcStatusSize := updatedPVC.Status.Capacity[v1.ResourceStorage] + + //If pvc's status field size is greater than or equal to pvc's size then done + if pvcStatusSize.Cmp(pvcSize) >= 0 { + return true, nil + } + return false, nil + }) + return updatedPVC, waitErr +} diff --git a/test/e2e/storage/volume_expand.go b/test/e2e/storage/volume_expand.go deleted file mode 100644 index 342b0f3ec9f..00000000000 --- a/test/e2e/storage/volume_expand.go +++ /dev/null @@ -1,334 +0,0 @@ -/* -Copyright 2017 The Kubernetes Authors. - -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. -*/ - -package storage - -import ( - "fmt" - "time" - - "github.com/onsi/ginkgo" - "github.com/onsi/gomega" - - v1 "k8s.io/api/core/v1" - storagev1 "k8s.io/api/storage/v1" - "k8s.io/apimachinery/pkg/api/resource" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/wait" - clientset "k8s.io/client-go/kubernetes" - "k8s.io/kubernetes/test/e2e/framework" - e2elog "k8s.io/kubernetes/test/e2e/framework/log" - "k8s.io/kubernetes/test/e2e/storage/testsuites" - "k8s.io/kubernetes/test/e2e/storage/utils" -) - -const ( - resizePollInterval = 2 * time.Second - // total time to wait for cloudprovider or file system resize to finish - totalResizeWaitPeriod = 20 * time.Minute -) - -var _ = utils.SIGDescribe("Volume expand", func() { - var ( - c clientset.Interface - ns string - err error - pvc *v1.PersistentVolumeClaim - storageClassVar *storagev1.StorageClass - ) - - f := framework.NewDefaultFramework("volume-expand") - ginkgo.BeforeEach(func() { - framework.SkipUnlessProviderIs("aws", "gce") - c = f.ClientSet - ns = f.Namespace.Name - framework.ExpectNoError(framework.WaitForAllNodesSchedulable(c, framework.TestContext.NodeSchedulableTimeout)) - }) - - setupFunc := func(allowExpansion bool, blockVolume bool) (*v1.PersistentVolumeClaim, *storagev1.StorageClass, error) { - test := testsuites.StorageClassTest{ - Name: "default", - ClaimSize: "2Gi", - } - 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 - } - - ginkgo.AfterEach(func() { - framework.ExpectNoError(framework.DeletePersistentVolumeClaim(c, pvc.Name, pvc.Namespace)) - framework.ExpectNoError(c.StorageV1().StorageClasses().Delete(storageClassVar.Name, nil)) - }) - - ginkgo.It("should not allow expansion of pvcs without AllowVolumeExpansion property", func() { - pvc, storageClassVar, err = setupFunc(false /* allowExpansion */, false /*BlockVolume*/) - framework.ExpectNoError(err, "Error creating non-expandable PVC") - - gomega.Expect(storageClassVar.AllowVolumeExpansion).To(gomega.BeNil()) - - pvcClaims := []*v1.PersistentVolumeClaim{pvc} - pvs, err := framework.WaitForPVClaimBoundPhase(c, pvcClaims, framework.ClaimProvisionTimeout) - framework.ExpectNoError(err, "Failed waiting for PVC to be bound %v", err) - framework.ExpectEqual(len(pvs), 1) - - ginkgo.By("Expanding non-expandable pvc") - newSize := resource.MustParse("6Gi") - pvc, err = expandPVCSize(pvc, newSize, c) - framework.ExpectError(err, "While updating non-expandable PVC") - }) - - ginkgo.It("Verify if offline PVC expansion works", func() { - pvc, storageClassVar, err = setupFunc(true /* allowExpansion */, false /*BlockVolume*/) - framework.ExpectNoError(err, "Error creating non-expandable PVC") - - ginkgo.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) - framework.ExpectEqual(len(pvs), 1) - - ginkgo.By("Creating a pod with dynamically provisioned volume") - pod, err := framework.CreatePod(c, ns, nil, pvcClaims, false, "") - framework.ExpectNoError(err, "While creating pods for resizing") - defer func() { - err = framework.DeletePodWithWait(f, c, pod) - framework.ExpectNoError(err, "while cleaning up pod already deleted in resize test") - }() - - ginkgo.By("Deleting the previously created pod") - err = framework.DeletePodWithWait(f, c, pod) - framework.ExpectNoError(err, "while deleting pod for resizing") - - // We expand the PVC while no pod is using it to ensure offline expansion - ginkgo.By("Expanding current pvc") - newSize := resource.MustParse("6Gi") - pvc, err = expandPVCSize(pvc, newSize, c) - framework.ExpectNoError(err, "While updating pvc for more size") - gomega.Expect(pvc).NotTo(gomega.BeNil()) - - pvcSize := pvc.Spec.Resources.Requests[v1.ResourceStorage] - if pvcSize.Cmp(newSize) != 0 { - e2elog.Failf("error updating pvc size %q", pvc.Name) - } - - ginkgo.By("Waiting for cloudprovider resize to finish") - err = waitForControllerVolumeResize(pvc, c, totalResizeWaitPeriod) - framework.ExpectNoError(err, "While waiting for pvc resize to finish") - - ginkgo.By("Checking for conditions on pvc") - pvc, err = c.CoreV1().PersistentVolumeClaims(ns).Get(pvc.Name, metav1.GetOptions{}) - framework.ExpectNoError(err, "While fetching pvc after controller resize") - - inProgressConditions := pvc.Status.Conditions - framework.ExpectEqual(len(inProgressConditions), 1, "pvc must have file system resize pending condition") - framework.ExpectEqual(inProgressConditions[0].Type, v1.PersistentVolumeClaimFileSystemResizePending, "pvc must have fs resizing condition") - - ginkgo.By("Creating a new pod with same volume") - pod2, err := framework.CreatePod(c, ns, nil, pvcClaims, false, "") - framework.ExpectNoError(err, "while recreating pod for resizing") - defer func() { - err = framework.DeletePodWithWait(f, c, pod2) - framework.ExpectNoError(err, "while cleaning up pod before exiting resizing test") - }() - - ginkgo.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 - framework.ExpectEqual(len(pvcConditions), 0, "pvc should not have conditions") - }) - - ginkgo.It("should resize volume when PVC is edited while pod is using it", func() { - pvc, storageClassVar, err = setupFunc(true /* allowExpansion */, false /*BlockVolume*/) - framework.ExpectNoError(err, "Error creating non-expandable PVC") - - ginkgo.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) - framework.ExpectEqual(len(pvs), 1) - - ginkgo.By("Creating a pod with dynamically provisioned volume") - pod, err := framework.CreatePod(c, ns, nil, pvcClaims, false, "") - framework.ExpectNoError(err, "While creating pods for resizing") - defer func() { - err = framework.DeletePodWithWait(f, c, pod) - framework.ExpectNoError(err, "while cleaning up pod already deleted in resize test") - }() - - // We expand the PVC while no pod is using it to ensure online expansion - ginkgo.By("Expanding current pvc") - newSize := resource.MustParse("6Gi") - pvc, err = expandPVCSize(pvc, newSize, c) - framework.ExpectNoError(err, "While updating pvc for more size") - gomega.Expect(pvc).NotTo(gomega.BeNil()) - - pvcSize := pvc.Spec.Resources.Requests[v1.ResourceStorage] - if pvcSize.Cmp(newSize) != 0 { - e2elog.Failf("error updating pvc size %q", pvc.Name) - } - - ginkgo.By("Waiting for cloudprovider resize to finish") - err = waitForControllerVolumeResize(pvc, c, totalResizeWaitPeriod) - framework.ExpectNoError(err, "While waiting for pvc resize to finish") - - ginkgo.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 - framework.ExpectEqual(len(pvcConditions), 0, "pvc should not have conditions") - }) - - ginkgo.It("should allow expansion of block volumes", func() { - pvc, storageClassVar, err = setupFunc(true /*allowExpansion*/, true /*blockVolume*/) - - ginkgo.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) - framework.ExpectEqual(len(pvs), 1) - - ginkgo.By("Expanding current pvc") - newSize := resource.MustParse("6Gi") - pvc, err = expandPVCSize(pvc, newSize, c) - framework.ExpectNoError(err, "While updating pvc for more size") - gomega.Expect(pvc).NotTo(gomega.BeNil()) - - pvcSize := pvc.Spec.Resources.Requests[v1.ResourceStorage] - if pvcSize.Cmp(newSize) != 0 { - e2elog.Failf("error updating pvc size %q", pvc.Name) - } - - ginkgo.By("Waiting for cloudprovider resize to finish") - err = waitForControllerVolumeResize(pvc, c, totalResizeWaitPeriod) - framework.ExpectNoError(err, "While waiting for pvc resize to finish") - - ginkgo.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 - framework.ExpectEqual(len(pvcConditions), 0, "pvc should not have conditions") - }) -}) - -func createStorageClass(t testsuites.StorageClassTest, ns string, suffix string, c clientset.Interface) (*storagev1.StorageClass, error) { - stKlass := newStorageClass(t, ns, suffix) - - var err error - stKlass, err = c.StorageV1().StorageClasses().Create(stKlass) - return stKlass, err -} - -func expandPVCSize(origPVC *v1.PersistentVolumeClaim, size resource.Quantity, c clientset.Interface) (*v1.PersistentVolumeClaim, error) { - pvcName := origPVC.Name - updatedPVC := origPVC.DeepCopy() - - waitErr := wait.PollImmediate(resizePollInterval, 30*time.Second, func() (bool, error) { - var err error - updatedPVC, err = c.CoreV1().PersistentVolumeClaims(origPVC.Namespace).Get(pvcName, metav1.GetOptions{}) - if err != nil { - return false, fmt.Errorf("error fetching pvc %q for resizing with %v", pvcName, err) - } - - updatedPVC.Spec.Resources.Requests[v1.ResourceStorage] = size - updatedPVC, err = c.CoreV1().PersistentVolumeClaims(origPVC.Namespace).Update(updatedPVC) - if err == nil { - return true, nil - } - e2elog.Logf("Error updating pvc %s with %v", pvcName, err) - return false, nil - }) - return updatedPVC, waitErr -} - -func waitForResizingCondition(pvc *v1.PersistentVolumeClaim, c clientset.Interface, duration time.Duration) error { - waitErr := wait.PollImmediate(resizePollInterval, duration, func() (bool, error) { - var err error - updatedPVC, err := c.CoreV1().PersistentVolumeClaims(pvc.Namespace).Get(pvc.Name, metav1.GetOptions{}) - - if err != nil { - return false, fmt.Errorf("error fetching pvc %q for checking for resize status : %v", pvc.Name, err) - } - - pvcConditions := updatedPVC.Status.Conditions - if len(pvcConditions) > 0 { - if pvcConditions[0].Type == v1.PersistentVolumeClaimResizing { - return true, nil - } - } - return false, nil - }) - return waitErr -} - -func waitForControllerVolumeResize(pvc *v1.PersistentVolumeClaim, c clientset.Interface, duration time.Duration) error { - pvName := pvc.Spec.VolumeName - return wait.PollImmediate(resizePollInterval, duration, func() (bool, error) { - pvcSize := pvc.Spec.Resources.Requests[v1.ResourceStorage] - - pv, err := c.CoreV1().PersistentVolumes().Get(pvName, metav1.GetOptions{}) - if err != nil { - return false, fmt.Errorf("error fetching pv %q for resizing %v", pvName, err) - } - - pvSize := pv.Spec.Capacity[v1.ResourceStorage] - - // If pv size is greater or equal to requested size that means controller resize is finished. - if pvSize.Cmp(pvcSize) >= 0 { - return true, nil - } - return false, nil - }) -} - -func waitForFSResize(pvc *v1.PersistentVolumeClaim, c clientset.Interface) (*v1.PersistentVolumeClaim, error) { - var updatedPVC *v1.PersistentVolumeClaim - waitErr := wait.PollImmediate(resizePollInterval, totalResizeWaitPeriod, func() (bool, error) { - var err error - updatedPVC, err = c.CoreV1().PersistentVolumeClaims(pvc.Namespace).Get(pvc.Name, metav1.GetOptions{}) - - if err != nil { - return false, fmt.Errorf("error fetching pvc %q for checking for resize status : %v", pvc.Name, err) - } - - pvcSize := updatedPVC.Spec.Resources.Requests[v1.ResourceStorage] - pvcStatusSize := updatedPVC.Status.Capacity[v1.ResourceStorage] - - //If pvc's status field size is greater than or equal to pvc's size then done - if pvcStatusSize.Cmp(pvcSize) >= 0 { - return true, nil - } - return false, nil - }) - return updatedPVC, waitErr -}