Merge pull request #78000 from mkimuram/issue/77999

Move volume_expand tests to storage e2e testsuites
This commit is contained in:
Kubernetes Prow Robot 2019-07-19 14:25:11 -07:00 committed by GitHub
commit b1bea169f5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 433 additions and 383 deletions

View File

@ -23,7 +23,6 @@ go_library(
"pvc_protection.go", "pvc_protection.go",
"regional_pd.go", "regional_pd.go",
"subpath.go", "subpath.go",
"volume_expand.go",
"volume_limits.go", "volume_limits.go",
"volume_metrics.go", "volume_metrics.go",
"volume_provisioning.go", "volume_provisioning.go",

View File

@ -439,7 +439,7 @@ var _ = utils.SIGDescribe("CSI mock volume", func() {
ginkgo.By("Expanding current pvc") ginkgo.By("Expanding current pvc")
newSize := resource.MustParse("6Gi") 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") framework.ExpectNoError(err, "While updating pvc for more size")
gomega.Expect(pvc).NotTo(gomega.BeNil()) 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) e2elog.Failf("error updating pvc size %q", pvc.Name)
} }
if test.expectFailure { if test.expectFailure {
err = waitForResizingCondition(pvc, m.cs, csiResizingConditionWait) err = testsuites.WaitForResizingCondition(pvc, m.cs, csiResizingConditionWait)
framework.ExpectError(err, "unexpected resizing condition on PVC") framework.ExpectError(err, "unexpected resizing condition on PVC")
return return
} }
ginkgo.By("Waiting for persistent volume resize to finish") 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") framework.ExpectNoError(err, "While waiting for CSI PV resize to finish")
checkPVCSize := func() { checkPVCSize := func() {
ginkgo.By("Waiting for PVC 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 resize to finish") framework.ExpectNoError(err, "while waiting for PVC resize to finish")
pvcConditions := pvc.Status.Conditions pvcConditions := pvc.Status.Conditions
@ -530,7 +530,7 @@ var _ = utils.SIGDescribe("CSI mock volume", func() {
ginkgo.By("Expanding current pvc") ginkgo.By("Expanding current pvc")
newSize := resource.MustParse("6Gi") 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") framework.ExpectNoError(err, "While updating pvc for more size")
gomega.Expect(pvc).NotTo(gomega.BeNil()) 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") 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") framework.ExpectNoError(err, "While waiting for PV resize to finish")
ginkgo.By("Waiting for PVC 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") framework.ExpectNoError(err, "while waiting for PVC to finish")
pvcConditions := pvc.Status.Conditions pvcConditions := pvc.Status.Conditions

View File

@ -1157,6 +1157,8 @@ func InitGcePdDriver() testsuites.TestDriver {
testsuites.CapBlock: true, testsuites.CapBlock: true,
testsuites.CapExec: true, testsuites.CapExec: true,
testsuites.CapMultiPODs: true, testsuites.CapMultiPODs: true,
testsuites.CapControllerExpansion: true,
testsuites.CapNodeExpansion: true,
}, },
}, },
} }
@ -1532,6 +1534,8 @@ func InitAwsDriver() testsuites.TestDriver {
testsuites.CapBlock: true, testsuites.CapBlock: true,
testsuites.CapExec: true, testsuites.CapExec: true,
testsuites.CapMultiPODs: true, testsuites.CapMultiPODs: true,
testsuites.CapControllerExpansion: true,
testsuites.CapNodeExpansion: true,
}, },
}, },
} }

View File

@ -47,6 +47,7 @@ var csiTestSuites = []func() testsuites.TestSuite{
testsuites.InitVolumeIOTestSuite, testsuites.InitVolumeIOTestSuite,
testsuites.InitVolumeModeTestSuite, testsuites.InitVolumeModeTestSuite,
testsuites.InitVolumesTestSuite, testsuites.InitVolumesTestSuite,
testsuites.InitVolumeExpandTestSuite,
} }
func init() { func init() {

View File

@ -19,6 +19,7 @@ package storage
import ( import (
"fmt" "fmt"
"path" "path"
"time"
"github.com/onsi/ginkgo" "github.com/onsi/ginkgo"
"github.com/onsi/gomega" "github.com/onsi/gomega"
@ -35,6 +36,11 @@ import (
"k8s.io/kubernetes/test/e2e/storage/utils" "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 _ = utils.SIGDescribe("Mounted flexvolume expand[Slow]", func() {
var ( var (
c clientset.Interface c clientset.Interface
@ -83,7 +89,7 @@ var _ = utils.SIGDescribe("Mounted flexvolume expand[Slow]", func() {
Provisioner: "flex-expand", Provisioner: "flex-expand",
} }
resizableSc, err = createStorageClass(test, ns, "resizing", c) resizableSc, err = c.StorageV1().StorageClasses().Create(newStorageClass(test, ns, "resizing"))
if err != nil { if err != nil {
fmt.Printf("storage class creation error: %v\n", err) 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") ginkgo.By("Expanding current pvc")
newSize := resource.MustParse("6Gi") 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") framework.ExpectNoError(err, "While updating pvc for more size")
gomega.Expect(pvc).NotTo(gomega.BeNil()) 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") 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") framework.ExpectNoError(err, "While waiting for pvc resize to finish")
ginkgo.By("Getting a pod from deployment") 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") framework.ExpectNoError(err, "While waiting for pod to be recreated")
ginkgo.By("Waiting for file system 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") framework.ExpectNoError(err, "while waiting for fs resize to finish")
pvcConditions := pvc.Status.Conditions pvcConditions := pvc.Status.Conditions

View File

@ -81,7 +81,7 @@ var _ = utils.SIGDescribe("Mounted flexvolume volume expand [Slow] [Feature:Expa
Provisioner: "flex-expand", Provisioner: "flex-expand",
} }
resizableSc, err = createStorageClass(test, ns, "resizing", c) resizableSc, err = c.StorageV1().StorageClasses().Create(newStorageClass(test, ns, "resizing"))
if err != nil { if err != nil {
fmt.Printf("storage class creation error: %v\n", err) 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") ginkgo.By("Expanding current pvc")
newSize := resource.MustParse("6Gi") 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") framework.ExpectNoError(err, "While updating pvc for more size")
gomega.Expect(pvc).NotTo(gomega.BeNil()) 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") 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") framework.ExpectNoError(err, "While waiting for pvc resize to finish")
ginkgo.By("Waiting for file system 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") framework.ExpectNoError(err, "while waiting for fs resize to finish")
pvcConditions := pvc.Status.Conditions pvcConditions := pvc.Status.Conditions

View File

@ -56,6 +56,7 @@ var testSuites = []func() testsuites.TestSuite{
testsuites.InitSubPathTestSuite, testsuites.InitSubPathTestSuite,
testsuites.InitProvisioningTestSuite, testsuites.InitProvisioningTestSuite,
testsuites.InitMultiVolumeTestSuite, testsuites.InitMultiVolumeTestSuite,
testsuites.InitVolumeExpandTestSuite,
} }
// This executes testSuites for in-tree volumes. // This executes testSuites for in-tree volumes.

View File

@ -81,7 +81,7 @@ var _ = utils.SIGDescribe("Mounted volume expand", func() {
AllowVolumeExpansion: true, AllowVolumeExpansion: true,
DelayBinding: 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") framework.ExpectNoError(err, "Error creating resizable storage class")
gomega.Expect(*resizableSc.AllowVolumeExpansion).To(gomega.BeTrue()) gomega.Expect(*resizableSc.AllowVolumeExpansion).To(gomega.BeTrue())
@ -128,7 +128,7 @@ var _ = utils.SIGDescribe("Mounted volume expand", func() {
ginkgo.By("Expanding current pvc") ginkgo.By("Expanding current pvc")
newSize := resource.MustParse("6Gi") 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") framework.ExpectNoError(err, "While updating pvc for more size")
gomega.Expect(pvc).NotTo(gomega.BeNil()) 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") 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") framework.ExpectNoError(err, "While waiting for pvc resize to finish")
ginkgo.By("Getting a pod from deployment") 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") framework.ExpectNoError(err, "While waiting for pod to be recreated")
ginkgo.By("Waiting for file system 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") framework.ExpectNoError(err, "while waiting for fs resize to finish")
pvcConditions := pvc.Status.Conditions pvcConditions := pvc.Status.Conditions

View File

@ -7,6 +7,7 @@ go_library(
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
deps = [ deps = [
"//staging/src/k8s.io/api/core/v1:go_default_library", "//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", "//test/e2e/framework/volume:go_default_library",
], ],
) )

View File

@ -18,6 +18,7 @@ package testpatterns
import ( import (
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
storagev1 "k8s.io/api/storage/v1"
"k8s.io/kubernetes/test/e2e/framework/volume" "k8s.io/kubernetes/test/e2e/framework/volume"
) )
@ -61,6 +62,8 @@ type TestPattern struct {
FsType string // Fstype of the volume FsType string // Fstype of the volume
VolMode v1.PersistentVolumeMode // PersistentVolumeMode of the volume VolMode v1.PersistentVolumeMode // PersistentVolumeMode of the volume
SnapshotType TestSnapshotType // Snapshot type of the snapshot SnapshotType TestSnapshotType // Snapshot type of the snapshot
BindingMode storagev1.VolumeBindingMode // VolumeBindingMode of the volume
AllowExpansion bool // AllowVolumeExpansion flag of the StorageClass
} }
var ( var (
@ -195,7 +198,7 @@ var (
VolType: PreprovisionedPV, VolType: PreprovisionedPV,
VolMode: v1.PersistentVolumeBlock, VolMode: v1.PersistentVolumeBlock,
} }
// BlockVolModeDynamicPV is TestPattern for "Dynamic PV (block)(immediate bind)" // BlockVolModeDynamicPV is TestPattern for "Dynamic PV (block)"
BlockVolModeDynamicPV = TestPattern{ BlockVolModeDynamicPV = TestPattern{
Name: "Dynamic PV (block volmode)", Name: "Dynamic PV (block volmode)",
VolType: DynamicPV, VolType: DynamicPV,
@ -209,4 +212,22 @@ var (
Name: "Dynamic Snapshot", Name: "Dynamic Snapshot",
SnapshotType: DynamicCreatedSnapshot, 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,
}
) )

View File

@ -10,6 +10,7 @@ go_library(
"snapshottable.go", "snapshottable.go",
"subpath.go", "subpath.go",
"testdriver.go", "testdriver.go",
"volume_expand.go",
"volume_io.go", "volume_io.go",
"volumemode.go", "volumemode.go",
"volumes.go", "volumes.go",

View File

@ -186,23 +186,21 @@ func createGenericVolumeTestResource(driver TestDriver, config *PerTestConfig, p
dInfo := driver.GetDriverInfo() dInfo := driver.GetDriverInfo()
f := config.Framework f := config.Framework
cs := f.ClientSet cs := f.ClientSet
fsType := pattern.FsType
volType := pattern.VolType
// Create volume for pre-provisioned volume tests // 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: case testpatterns.InlineVolume:
e2elog.Logf("Creating resource for inline volume") e2elog.Logf("Creating resource for inline volume")
if iDriver, ok := driver.(InlineVolumeTestDriver); ok { 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 r.volType = dInfo.Name
} }
case testpatterns.PreprovisionedPV: case testpatterns.PreprovisionedPV:
e2elog.Logf("Creating resource for pre-provisioned PV") e2elog.Logf("Creating resource for pre-provisioned PV")
if pDriver, ok := driver.(PreprovisionedPVTestDriver); ok { 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 { if pvSource != nil {
r.volSource, r.pv, r.pvc = createVolumeSourceWithPVCPV(f, dInfo.Name, pvSource, volumeNodeAffinity, false, pattern.VolMode) 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") e2elog.Logf("Creating resource for dynamic PV")
if dDriver, ok := driver.(DynamicPVTestDriver); ok { if dDriver, ok := driver.(DynamicPVTestDriver); ok {
claimSize := dDriver.GetClaimSize() 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) ginkgo.By("creating a StorageClass " + r.sc.Name)
var err error var err error
@ -226,11 +231,11 @@ func createGenericVolumeTestResource(driver TestDriver, config *PerTestConfig, p
r.volType = fmt.Sprintf("%s-dynamicPV", dInfo.Name) r.volType = fmt.Sprintf("%s-dynamicPV", dInfo.Name)
} }
default: default:
e2elog.Failf("genericVolumeTestResource doesn't support: %s", volType) e2elog.Failf("genericVolumeTestResource doesn't support: %s", pattern.VolType)
} }
if r.volSource == nil { 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 return &r
@ -239,10 +244,9 @@ func createGenericVolumeTestResource(driver TestDriver, config *PerTestConfig, p
// cleanupResource cleans up genericVolumeTestResource // cleanupResource cleans up genericVolumeTestResource
func (r *genericVolumeTestResource) cleanupResource() { func (r *genericVolumeTestResource) cleanupResource() {
f := r.config.Framework f := r.config.Framework
volType := r.pattern.VolType
if r.pvc != nil || r.pv != nil { if r.pvc != nil || r.pv != nil {
switch volType { switch r.pattern.VolType {
case testpatterns.PreprovisionedPV: case testpatterns.PreprovisionedPV:
ginkgo.By("Deleting pv and pvc") ginkgo.By("Deleting pv and pvc")
if errs := framework.PVPVCCleanup(f.ClientSet, f.Namespace.Name, r.pv, r.pvc); len(errs) != 0 { if errs := framework.PVPVCCleanup(f.ClientSet, f.Namespace.Name, r.pv, r.pvc); len(errs) != 0 {

View File

@ -128,6 +128,8 @@ const (
CapMultiPODs Capability = "multipods" 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. // DriverInfo represents static information about a TestDriver.

View File

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

View File

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