2015-02-20 18:01:33 +00:00
/ *
2015-05-01 16:19:44 +00:00
Copyright 2015 The Kubernetes Authors All rights reserved .
2015-02-20 18:01:33 +00:00
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 e2e
import (
"fmt"
2015-10-19 21:08:35 +00:00
mathrand "math/rand"
2015-02-20 18:01:33 +00:00
"strings"
"time"
2015-12-15 09:18:00 +00:00
"google.golang.org/api/googleapi"
2016-03-12 10:57:59 +00:00
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/ec2"
2015-08-05 22:05:17 +00:00
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
2015-08-05 22:03:47 +00:00
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/resource"
2015-09-09 21:59:11 +00:00
"k8s.io/kubernetes/pkg/api/unversioned"
2016-01-13 22:40:56 +00:00
"k8s.io/kubernetes/pkg/apimachinery/registered"
2015-08-13 19:01:50 +00:00
client "k8s.io/kubernetes/pkg/client/unversioned"
2015-10-19 21:08:35 +00:00
awscloud "k8s.io/kubernetes/pkg/cloudprovider/providers/aws"
2015-11-24 22:48:41 +00:00
gcecloud "k8s.io/kubernetes/pkg/cloudprovider/providers/gce"
2015-08-05 22:03:47 +00:00
"k8s.io/kubernetes/pkg/util"
2016-04-07 17:21:31 +00:00
"k8s.io/kubernetes/test/e2e/framework"
2015-02-20 18:01:33 +00:00
)
2015-07-27 02:26:43 +00:00
const (
gcePDDetachTimeout = 10 * time . Minute
gcePDDetachPollTime = 10 * time . Second
)
2016-04-07 17:21:31 +00:00
var _ = framework . KubeDescribe ( "Pod Disks" , func ( ) {
2015-02-20 18:01:33 +00:00
var (
podClient client . PodInterface
host0Name string
host1Name string
)
2016-04-07 17:21:31 +00:00
f := framework . NewDefaultFramework ( "pod-disks" )
2015-02-20 18:01:33 +00:00
BeforeEach ( func ( ) {
2016-04-07 17:21:31 +00:00
framework . SkipUnlessNodeCountIsAtLeast ( 2 )
2015-06-22 21:14:54 +00:00
2016-04-07 17:21:31 +00:00
podClient = f . Client . Pods ( f . Namespace . Name )
nodes := framework . ListSchedulableNodesOrDie ( f . Client )
2015-02-20 18:01:33 +00:00
2015-06-22 21:14:54 +00:00
Expect ( len ( nodes . Items ) ) . To ( BeNumerically ( ">=" , 2 ) , "Requires at least 2 nodes" )
2015-04-22 21:01:27 +00:00
2015-06-22 21:14:54 +00:00
host0Name = nodes . Items [ 0 ] . ObjectMeta . Name
host1Name = nodes . Items [ 1 ] . ObjectMeta . Name
2015-07-20 02:00:10 +00:00
2015-10-19 21:08:35 +00:00
mathrand . Seed ( time . Now ( ) . UTC ( ) . UnixNano ( ) )
2015-02-20 18:01:33 +00:00
} )
2016-02-18 19:24:41 +00:00
It ( "should schedule a pod w/ a RW PD, remove it, then schedule it on another host [Slow]" , func ( ) {
2016-04-07 17:21:31 +00:00
framework . SkipUnlessProviderIs ( "gce" , "gke" , "aws" )
2015-04-22 21:01:27 +00:00
2015-03-06 14:26:39 +00:00
By ( "creating PD" )
2015-11-24 22:48:41 +00:00
diskName , err := createPDWithRetry ( )
2016-04-07 17:21:31 +00:00
framework . ExpectNoError ( err , "Error creating PD" )
2015-03-06 14:26:39 +00:00
2015-09-23 22:08:11 +00:00
host0Pod := testPDPod ( [ ] string { diskName } , host0Name , false /* readOnly */ , 1 /* numContainers */ )
host1Pod := testPDPod ( [ ] string { diskName } , host1Name , false /* readOnly */ , 1 /* numContainers */ )
containerName := "mycontainer"
2015-02-20 18:01:33 +00:00
defer func ( ) {
// Teardown pods, PD. Ignore errors.
// Teardown should do nothing unless test failed.
2015-11-24 22:48:41 +00:00
By ( "cleaning up PD-RW test environment" )
2015-08-20 02:09:57 +00:00
podClient . Delete ( host0Pod . Name , api . NewDeleteOptions ( 0 ) )
podClient . Delete ( host1Pod . Name , api . NewDeleteOptions ( 0 ) )
2015-11-24 22:48:41 +00:00
detachAndDeletePDs ( diskName , [ ] string { host0Name , host1Name } )
2015-02-20 18:01:33 +00:00
} ( )
By ( "submitting host0Pod to kubernetes" )
2015-03-06 14:26:39 +00:00
_ , err = podClient . Create ( host0Pod )
2016-04-07 17:21:31 +00:00
framework . ExpectNoError ( err , fmt . Sprintf ( "Failed to create host0Pod: %v" , err ) )
2015-02-20 18:01:33 +00:00
2016-04-07 17:21:31 +00:00
framework . ExpectNoError ( f . WaitForPodRunningSlow ( host0Pod . Name ) )
2015-02-20 18:01:33 +00:00
2015-09-23 22:08:11 +00:00
testFile := "/testpd1/tracker"
2015-10-19 21:08:35 +00:00
testFileContents := fmt . Sprintf ( "%v" , mathrand . Int ( ) )
2015-07-10 11:13:42 +00:00
2016-04-07 17:21:31 +00:00
framework . ExpectNoError ( f . WriteFileViaContainer ( host0Pod . Name , containerName , testFile , testFileContents ) )
framework . Logf ( "Wrote value: %v" , testFileContents )
2015-07-10 11:13:42 +00:00
2015-02-20 18:01:33 +00:00
By ( "deleting host0Pod" )
2016-04-07 17:21:31 +00:00
framework . ExpectNoError ( podClient . Delete ( host0Pod . Name , api . NewDeleteOptions ( 0 ) ) , "Failed to delete host0Pod" )
2015-02-20 18:01:33 +00:00
By ( "submitting host1Pod to kubernetes" )
_ , err = podClient . Create ( host1Pod )
2016-04-07 17:21:31 +00:00
framework . ExpectNoError ( err , "Failed to create host1Pod" )
2015-02-20 18:01:33 +00:00
2016-04-07 17:21:31 +00:00
framework . ExpectNoError ( f . WaitForPodRunningSlow ( host1Pod . Name ) )
2015-02-20 18:01:33 +00:00
2016-04-07 17:21:31 +00:00
v , err := f . ReadFileViaContainer ( host1Pod . Name , containerName , testFile )
framework . ExpectNoError ( err )
framework . Logf ( "Read value: %v" , v )
2015-07-10 11:13:42 +00:00
Expect ( strings . TrimSpace ( v ) ) . To ( Equal ( strings . TrimSpace ( testFileContents ) ) )
2015-02-20 18:01:33 +00:00
By ( "deleting host1Pod" )
2016-04-07 17:21:31 +00:00
framework . ExpectNoError ( podClient . Delete ( host1Pod . Name , api . NewDeleteOptions ( 0 ) ) , "Failed to delete host1Pod" )
2015-02-20 18:01:33 +00:00
return
} )
2016-02-18 19:24:41 +00:00
It ( "should schedule a pod w/ a readonly PD on two hosts, then remove both. [Slow]" , func ( ) {
2016-04-07 17:21:31 +00:00
framework . SkipUnlessProviderIs ( "gce" , "gke" )
2015-04-22 21:01:27 +00:00
2015-03-06 14:26:39 +00:00
By ( "creating PD" )
2015-11-24 22:48:41 +00:00
diskName , err := createPDWithRetry ( )
2016-04-07 17:21:31 +00:00
framework . ExpectNoError ( err , "Error creating PD" )
2015-03-06 14:26:39 +00:00
2015-09-23 22:08:11 +00:00
rwPod := testPDPod ( [ ] string { diskName } , host0Name , false /* readOnly */ , 1 /* numContainers */ )
host0ROPod := testPDPod ( [ ] string { diskName } , host0Name , true /* readOnly */ , 1 /* numContainers */ )
host1ROPod := testPDPod ( [ ] string { diskName } , host1Name , true /* readOnly */ , 1 /* numContainers */ )
2015-02-20 18:01:33 +00:00
defer func ( ) {
By ( "cleaning up PD-RO test environment" )
// Teardown pods, PD. Ignore errors.
// Teardown should do nothing unless test failed.
2015-08-20 02:09:57 +00:00
podClient . Delete ( rwPod . Name , api . NewDeleteOptions ( 0 ) )
podClient . Delete ( host0ROPod . Name , api . NewDeleteOptions ( 0 ) )
podClient . Delete ( host1ROPod . Name , api . NewDeleteOptions ( 0 ) )
2015-11-24 22:48:41 +00:00
detachAndDeletePDs ( diskName , [ ] string { host0Name , host1Name } )
2015-03-06 14:26:39 +00:00
} ( )
2015-02-20 18:01:33 +00:00
By ( "submitting rwPod to ensure PD is formatted" )
2015-03-06 14:26:39 +00:00
_ , err = podClient . Create ( rwPod )
2016-04-07 17:21:31 +00:00
framework . ExpectNoError ( err , "Failed to create rwPod" )
framework . ExpectNoError ( f . WaitForPodRunningSlow ( rwPod . Name ) )
framework . ExpectNoError ( podClient . Delete ( rwPod . Name , api . NewDeleteOptions ( 0 ) ) , "Failed to delete host0Pod" )
framework . ExpectNoError ( waitForPDDetach ( diskName , host0Name ) )
2015-02-20 18:01:33 +00:00
By ( "submitting host0ROPod to kubernetes" )
_ , err = podClient . Create ( host0ROPod )
2016-04-07 17:21:31 +00:00
framework . ExpectNoError ( err , "Failed to create host0ROPod" )
2015-02-20 18:01:33 +00:00
By ( "submitting host1ROPod to kubernetes" )
_ , err = podClient . Create ( host1ROPod )
2016-04-07 17:21:31 +00:00
framework . ExpectNoError ( err , "Failed to create host1ROPod" )
2015-02-20 18:01:33 +00:00
2016-04-07 17:21:31 +00:00
framework . ExpectNoError ( f . WaitForPodRunningSlow ( host0ROPod . Name ) )
2015-02-20 18:01:33 +00:00
2016-04-07 17:21:31 +00:00
framework . ExpectNoError ( f . WaitForPodRunningSlow ( host1ROPod . Name ) )
2015-02-20 18:01:33 +00:00
By ( "deleting host0ROPod" )
2016-04-07 17:21:31 +00:00
framework . ExpectNoError ( podClient . Delete ( host0ROPod . Name , api . NewDeleteOptions ( 0 ) ) , "Failed to delete host0ROPod" )
2015-02-20 18:01:33 +00:00
By ( "deleting host1ROPod" )
2016-04-07 17:21:31 +00:00
framework . ExpectNoError ( podClient . Delete ( host1ROPod . Name , api . NewDeleteOptions ( 0 ) ) , "Failed to delete host1ROPod" )
2015-02-20 18:01:33 +00:00
} )
2016-01-12 21:48:52 +00:00
It ( "should schedule a pod w/ a RW PD shared between multiple containers, write to PD, delete pod, verify contents, and repeat in rapid succession [Slow]" , func ( ) {
2016-04-07 17:21:31 +00:00
framework . SkipUnlessProviderIs ( "gce" , "gke" , "aws" )
2015-07-20 02:00:10 +00:00
By ( "creating PD" )
2015-11-24 22:48:41 +00:00
diskName , err := createPDWithRetry ( )
2016-04-07 17:21:31 +00:00
framework . ExpectNoError ( err , "Error creating PD" )
2015-07-20 02:00:10 +00:00
numContainers := 4
2015-07-10 11:13:42 +00:00
2015-09-23 22:08:11 +00:00
host0Pod := testPDPod ( [ ] string { diskName } , host0Name , false /* readOnly */ , numContainers )
2015-07-10 11:13:42 +00:00
2015-07-20 02:00:10 +00:00
defer func ( ) {
By ( "cleaning up PD-RW test environment" )
// Teardown pods, PD. Ignore errors.
// Teardown should do nothing unless test failed.
2015-08-19 15:35:00 +00:00
podClient . Delete ( host0Pod . Name , api . NewDeleteOptions ( 0 ) )
2015-11-24 22:48:41 +00:00
detachAndDeletePDs ( diskName , [ ] string { host0Name } )
2015-07-20 02:00:10 +00:00
} ( )
2015-07-10 11:13:42 +00:00
2015-07-20 02:00:10 +00:00
fileAndContentToVerify := make ( map [ string ] string )
for i := 0 ; i < 3 ; i ++ {
2016-04-07 17:21:31 +00:00
framework . Logf ( "PD Read/Writer Iteration #%v" , i )
2015-07-20 02:00:10 +00:00
By ( "submitting host0Pod to kubernetes" )
_ , err = podClient . Create ( host0Pod )
2016-04-07 17:21:31 +00:00
framework . ExpectNoError ( err , fmt . Sprintf ( "Failed to create host0Pod: %v" , err ) )
2015-07-20 02:00:10 +00:00
2016-04-07 17:21:31 +00:00
framework . ExpectNoError ( f . WaitForPodRunningSlow ( host0Pod . Name ) )
2015-07-20 02:00:10 +00:00
// randomly select a container and read/verify pd contents from it
2015-10-19 21:08:35 +00:00
containerName := fmt . Sprintf ( "mycontainer%v" , mathrand . Intn ( numContainers ) + 1 )
2016-04-07 17:21:31 +00:00
verifyPDContentsViaContainer ( f , host0Pod . Name , containerName , fileAndContentToVerify )
2015-07-20 02:00:10 +00:00
// Randomly select a container to write a file to PD from
2015-10-19 21:08:35 +00:00
containerName = fmt . Sprintf ( "mycontainer%v" , mathrand . Intn ( numContainers ) + 1 )
2015-09-23 22:08:11 +00:00
testFile := fmt . Sprintf ( "/testpd1/tracker%v" , i )
2015-10-19 21:08:35 +00:00
testFileContents := fmt . Sprintf ( "%v" , mathrand . Int ( ) )
2015-07-20 02:00:10 +00:00
fileAndContentToVerify [ testFile ] = testFileContents
2016-04-07 17:21:31 +00:00
framework . ExpectNoError ( f . WriteFileViaContainer ( host0Pod . Name , containerName , testFile , testFileContents ) )
framework . Logf ( "Wrote value: \"%v\" to PD %q from pod %q container %q" , testFileContents , diskName , host0Pod . Name , containerName )
2015-07-20 02:00:10 +00:00
// Randomly select a container and read/verify pd contents from it
2015-10-19 21:08:35 +00:00
containerName = fmt . Sprintf ( "mycontainer%v" , mathrand . Intn ( numContainers ) + 1 )
2016-04-07 17:21:31 +00:00
verifyPDContentsViaContainer ( f , host0Pod . Name , containerName , fileAndContentToVerify )
2015-07-20 02:00:10 +00:00
By ( "deleting host0Pod" )
2016-04-07 17:21:31 +00:00
framework . ExpectNoError ( podClient . Delete ( host0Pod . Name , api . NewDeleteOptions ( 0 ) ) , "Failed to delete host0Pod" )
2015-07-10 11:13:42 +00:00
}
2015-07-20 02:00:10 +00:00
} )
2015-09-23 22:08:11 +00:00
2016-01-12 21:48:52 +00:00
It ( "should schedule a pod w/two RW PDs both mounted to one container, write to PD, verify contents, delete pod, recreate pod, verify contents, and repeat in rapid succession [Slow]" , func ( ) {
2016-04-07 17:21:31 +00:00
framework . SkipUnlessProviderIs ( "gce" , "gke" , "aws" )
2015-09-23 22:08:11 +00:00
By ( "creating PD1" )
2015-11-24 22:48:41 +00:00
disk1Name , err := createPDWithRetry ( )
2016-04-07 17:21:31 +00:00
framework . ExpectNoError ( err , "Error creating PD1" )
2015-09-23 22:08:11 +00:00
By ( "creating PD2" )
2015-11-24 22:48:41 +00:00
disk2Name , err := createPDWithRetry ( )
2016-04-07 17:21:31 +00:00
framework . ExpectNoError ( err , "Error creating PD2" )
2015-09-23 22:08:11 +00:00
host0Pod := testPDPod ( [ ] string { disk1Name , disk2Name } , host0Name , false /* readOnly */ , 1 /* numContainers */ )
defer func ( ) {
By ( "cleaning up PD-RW test environment" )
// Teardown pods, PD. Ignore errors.
// Teardown should do nothing unless test failed.
podClient . Delete ( host0Pod . Name , api . NewDeleteOptions ( 0 ) )
2015-11-24 22:48:41 +00:00
detachAndDeletePDs ( disk1Name , [ ] string { host0Name } )
detachAndDeletePDs ( disk2Name , [ ] string { host0Name } )
2015-09-23 22:08:11 +00:00
} ( )
containerName := "mycontainer"
fileAndContentToVerify := make ( map [ string ] string )
for i := 0 ; i < 3 ; i ++ {
2016-04-07 17:21:31 +00:00
framework . Logf ( "PD Read/Writer Iteration #%v" , i )
2015-09-23 22:08:11 +00:00
By ( "submitting host0Pod to kubernetes" )
_ , err = podClient . Create ( host0Pod )
2016-04-07 17:21:31 +00:00
framework . ExpectNoError ( err , fmt . Sprintf ( "Failed to create host0Pod: %v" , err ) )
2015-09-23 22:08:11 +00:00
2016-04-07 17:21:31 +00:00
framework . ExpectNoError ( f . WaitForPodRunningSlow ( host0Pod . Name ) )
2015-09-23 22:08:11 +00:00
// Read/verify pd contents for both disks from container
2016-04-07 17:21:31 +00:00
verifyPDContentsViaContainer ( f , host0Pod . Name , containerName , fileAndContentToVerify )
2015-09-23 22:08:11 +00:00
// Write a file to both PDs from container
testFilePD1 := fmt . Sprintf ( "/testpd1/tracker%v" , i )
testFilePD2 := fmt . Sprintf ( "/testpd2/tracker%v" , i )
2015-10-19 21:08:35 +00:00
testFilePD1Contents := fmt . Sprintf ( "%v" , mathrand . Int ( ) )
testFilePD2Contents := fmt . Sprintf ( "%v" , mathrand . Int ( ) )
2015-09-23 22:08:11 +00:00
fileAndContentToVerify [ testFilePD1 ] = testFilePD1Contents
fileAndContentToVerify [ testFilePD2 ] = testFilePD2Contents
2016-04-07 17:21:31 +00:00
framework . ExpectNoError ( f . WriteFileViaContainer ( host0Pod . Name , containerName , testFilePD1 , testFilePD1Contents ) )
framework . Logf ( "Wrote value: \"%v\" to PD1 (%q) from pod %q container %q" , testFilePD1Contents , disk1Name , host0Pod . Name , containerName )
framework . ExpectNoError ( f . WriteFileViaContainer ( host0Pod . Name , containerName , testFilePD2 , testFilePD2Contents ) )
framework . Logf ( "Wrote value: \"%v\" to PD2 (%q) from pod %q container %q" , testFilePD2Contents , disk2Name , host0Pod . Name , containerName )
2015-09-23 22:08:11 +00:00
// Read/verify pd contents for both disks from container
2016-04-07 17:21:31 +00:00
verifyPDContentsViaContainer ( f , host0Pod . Name , containerName , fileAndContentToVerify )
2015-09-23 22:08:11 +00:00
By ( "deleting host0Pod" )
2016-04-07 17:21:31 +00:00
framework . ExpectNoError ( podClient . Delete ( host0Pod . Name , api . NewDeleteOptions ( 0 ) ) , "Failed to delete host0Pod" )
2015-09-23 22:08:11 +00:00
}
} )
2015-07-20 02:00:10 +00:00
} )
2015-11-24 22:48:41 +00:00
func createPDWithRetry ( ) ( string , error ) {
newDiskName := ""
var err error
for start := time . Now ( ) ; time . Since ( start ) < 180 * time . Second ; time . Sleep ( 5 * time . Second ) {
if newDiskName , err = createPD ( ) ; err != nil {
2016-04-07 17:21:31 +00:00
framework . Logf ( "Couldn't create a new PD. Sleeping 5 seconds (%v)" , err )
2015-11-24 22:48:41 +00:00
continue
}
2016-04-07 17:21:31 +00:00
framework . Logf ( "Successfully created a new PD: %q." , newDiskName )
2015-11-24 22:48:41 +00:00
break
}
return newDiskName , err
}
2015-07-20 02:00:10 +00:00
func deletePDWithRetry ( diskName string ) {
var err error
for start := time . Now ( ) ; time . Since ( start ) < 180 * time . Second ; time . Sleep ( 5 * time . Second ) {
if err = deletePD ( diskName ) ; err != nil {
2016-04-07 17:21:31 +00:00
framework . Logf ( "Couldn't delete PD %q. Sleeping 5 seconds (%v)" , diskName , err )
2015-07-20 02:00:10 +00:00
continue
}
2016-04-07 17:21:31 +00:00
framework . Logf ( "Successfully deleted PD %q." , diskName )
2015-07-20 02:00:10 +00:00
break
2015-07-10 11:13:42 +00:00
}
2016-04-07 17:21:31 +00:00
framework . ExpectNoError ( err , "Error deleting PD" )
2015-07-10 11:13:42 +00:00
}
2016-04-07 17:21:31 +00:00
func verifyPDContentsViaContainer ( f * framework . Framework , podName , containerName string , fileAndContentToVerify map [ string ] string ) {
2015-07-20 02:00:10 +00:00
for filePath , expectedContents := range fileAndContentToVerify {
v , err := f . ReadFileViaContainer ( podName , containerName , filePath )
if err != nil {
2016-04-07 17:21:31 +00:00
framework . Logf ( "Error reading file: %v" , err )
2015-07-20 02:00:10 +00:00
}
2016-04-07 17:21:31 +00:00
framework . ExpectNoError ( err )
framework . Logf ( "Read file %q with content: %v" , filePath , v )
2015-07-20 02:00:10 +00:00
Expect ( strings . TrimSpace ( v ) ) . To ( Equal ( strings . TrimSpace ( expectedContents ) ) )
2015-07-10 11:13:42 +00:00
}
}
2015-03-06 14:26:39 +00:00
func createPD ( ) ( string , error ) {
2016-04-07 17:21:31 +00:00
if framework . TestContext . Provider == "gce" || framework . TestContext . Provider == "gke" {
pdName := fmt . Sprintf ( "%s-%s" , framework . TestContext . Prefix , string ( util . NewUUID ( ) ) )
2015-03-06 14:26:39 +00:00
2015-11-24 22:48:41 +00:00
gceCloud , err := getGCECloud ( )
if err != nil {
return "" , err
}
2016-01-27 14:16:05 +00:00
tags := map [ string ] string { }
2016-04-07 17:21:31 +00:00
err = gceCloud . CreateDisk ( pdName , framework . TestContext . CloudConfig . Zone , 10 /* sizeGb */ , tags )
2015-03-06 14:26:39 +00:00
if err != nil {
return "" , err
}
return pdName , nil
2016-04-07 17:21:31 +00:00
} else if framework . TestContext . Provider == "aws" {
2016-03-12 10:57:59 +00:00
client := ec2 . New ( session . New ( ) )
request := & ec2 . CreateVolumeInput { }
request . AvailabilityZone = aws . String ( cloudConfig . Zone )
request . Size = aws . Int64 ( 10 )
request . VolumeType = aws . String ( awscloud . DefaultVolumeType )
response , err := client . CreateVolume ( request )
if err != nil {
return "" , err
2015-03-06 14:26:39 +00:00
}
2016-03-12 10:57:59 +00:00
az := aws . StringValue ( response . AvailabilityZone )
awsID := aws . StringValue ( response . VolumeId )
volumeName := "aws://" + az + "/" + awsID
return volumeName , nil
} else {
return "" , fmt . Errorf ( "Provider does not support volume creation" )
2015-03-06 14:26:39 +00:00
}
2015-02-20 18:01:33 +00:00
}
2015-03-06 14:26:39 +00:00
func deletePD ( pdName string ) error {
2016-04-07 17:21:31 +00:00
if framework . TestContext . Provider == "gce" || framework . TestContext . Provider == "gke" {
2015-11-24 22:48:41 +00:00
gceCloud , err := getGCECloud ( )
if err != nil {
return err
}
err = gceCloud . DeleteDisk ( pdName )
2015-03-06 14:26:39 +00:00
2015-06-18 05:13:34 +00:00
if err != nil {
2015-11-24 22:48:41 +00:00
if gerr , ok := err . ( * googleapi . Error ) ; ok && len ( gerr . Errors ) > 0 && gerr . Errors [ 0 ] . Reason == "notFound" {
// PD already exists, ignore error.
2015-09-30 01:00:40 +00:00
return nil
}
2016-04-07 17:21:31 +00:00
framework . Logf ( "Error deleting PD %q: %v" , pdName , err )
2015-06-18 05:13:34 +00:00
}
return err
2016-04-07 17:21:31 +00:00
} else if framework . TestContext . Provider == "aws" {
2016-03-12 10:57:59 +00:00
client := ec2 . New ( session . New ( ) )
tokens := strings . Split ( pdName , "/" )
awsVolumeID := tokens [ len ( tokens ) - 1 ]
request := & ec2 . DeleteVolumeInput { VolumeId : aws . String ( awsVolumeID ) }
_ , err := client . DeleteVolume ( request )
2015-10-20 02:06:33 +00:00
if err != nil {
2016-03-12 10:57:59 +00:00
if awsError , ok := err . ( awserr . Error ) ; ok && awsError . Code ( ) == "InvalidVolume.NotFound" {
2016-04-07 17:21:31 +00:00
framework . Logf ( "Volume deletion implicitly succeeded because volume %q does not exist." , pdName )
2016-03-12 10:57:59 +00:00
} else {
return fmt . Errorf ( "error deleting EBS volumes: %v" , err )
2015-10-20 02:06:33 +00:00
}
}
2016-03-12 10:57:59 +00:00
return nil
} else {
return fmt . Errorf ( "Provider does not support volume deletion" )
2015-03-06 14:26:39 +00:00
}
2015-02-20 18:01:33 +00:00
}
2015-03-06 14:26:39 +00:00
func detachPD ( hostName , pdName string ) error {
2016-04-07 17:21:31 +00:00
if framework . TestContext . Provider == "gce" || framework . TestContext . Provider == "gke" {
2015-03-06 14:26:39 +00:00
instanceName := strings . Split ( hostName , "." ) [ 0 ]
2015-11-24 22:48:41 +00:00
gceCloud , err := getGCECloud ( )
if err != nil {
return err
}
err = gceCloud . DetachDisk ( pdName , instanceName )
if err != nil {
if gerr , ok := err . ( * googleapi . Error ) ; ok && strings . Contains ( gerr . Message , "Invalid value for field 'disk'" ) {
// PD already detached, ignore error.
return nil
}
2016-04-07 17:21:31 +00:00
framework . Logf ( "Error detaching PD %q: %v" , pdName , err )
2015-11-24 22:48:41 +00:00
}
return err
2016-04-07 17:21:31 +00:00
} else if framework . TestContext . Provider == "aws" {
2016-03-12 10:57:59 +00:00
client := ec2 . New ( session . New ( ) )
2015-03-06 14:26:39 +00:00
2016-03-12 10:57:59 +00:00
tokens := strings . Split ( pdName , "/" )
awsVolumeID := tokens [ len ( tokens ) - 1 ]
request := ec2 . DetachVolumeInput {
VolumeId : aws . String ( awsVolumeID ) ,
2015-03-06 14:26:39 +00:00
}
2016-03-12 10:57:59 +00:00
_ , err := client . DetachVolume ( & request )
if err != nil {
return fmt . Errorf ( "error detaching EBS volume: %v" , err )
}
return nil
} else {
return fmt . Errorf ( "Provider does not support volume detaching" )
2015-03-06 14:26:39 +00:00
}
2015-02-20 18:01:33 +00:00
}
2015-09-23 22:08:11 +00:00
func testPDPod ( diskNames [ ] string , targetHost string , readOnly bool , numContainers int ) * api . Pod {
2015-07-20 02:00:10 +00:00
containers := make ( [ ] api . Container , numContainers )
for i := range containers {
2015-09-23 22:08:11 +00:00
containers [ i ] . Name = "mycontainer"
2015-07-20 02:00:10 +00:00
if numContainers > 1 {
2015-09-23 22:08:11 +00:00
containers [ i ] . Name = fmt . Sprintf ( "mycontainer%v" , i + 1 )
2015-07-20 02:00:10 +00:00
}
2016-02-08 23:28:55 +00:00
containers [ i ] . Image = "gcr.io/google_containers/busybox:1.24"
2015-07-20 02:00:10 +00:00
containers [ i ] . Command = [ ] string { "sleep" , "6000" }
2015-09-23 22:08:11 +00:00
containers [ i ] . VolumeMounts = make ( [ ] api . VolumeMount , len ( diskNames ) )
for k := range diskNames {
containers [ i ] . VolumeMounts [ k ] . Name = fmt . Sprintf ( "testpd%v" , k + 1 )
containers [ i ] . VolumeMounts [ k ] . MountPath = fmt . Sprintf ( "/testpd%v" , k + 1 )
2015-07-20 02:00:10 +00:00
}
containers [ i ] . Resources . Limits = api . ResourceList { }
containers [ i ] . Resources . Limits [ api . ResourceCPU ] = * resource . NewQuantity ( int64 ( 0 ) , resource . DecimalSI )
}
2015-03-06 14:26:39 +00:00
pod := & api . Pod {
2015-09-09 21:59:11 +00:00
TypeMeta : unversioned . TypeMeta {
2015-02-20 18:01:33 +00:00
Kind : "Pod" ,
2016-01-13 22:40:56 +00:00
APIVersion : registered . GroupOrDie ( api . GroupName ) . GroupVersion . String ( ) ,
2015-02-20 18:01:33 +00:00
} ,
ObjectMeta : api . ObjectMeta {
Name : "pd-test-" + string ( util . NewUUID ( ) ) ,
} ,
Spec : api . PodSpec {
2015-07-20 02:00:10 +00:00
Containers : containers ,
NodeName : targetHost ,
2015-02-20 18:01:33 +00:00
} ,
}
2015-03-06 14:26:39 +00:00
2016-04-07 17:21:31 +00:00
if framework . TestContext . Provider == "gce" || framework . TestContext . Provider == "gke" {
2015-09-23 22:08:11 +00:00
pod . Spec . Volumes = make ( [ ] api . Volume , len ( diskNames ) )
for k , diskName := range diskNames {
pod . Spec . Volumes [ k ] . Name = fmt . Sprintf ( "testpd%v" , k + 1 )
pod . Spec . Volumes [ k ] . VolumeSource = api . VolumeSource {
GCEPersistentDisk : & api . GCEPersistentDiskVolumeSource {
PDName : diskName ,
FSType : "ext4" ,
ReadOnly : readOnly ,
2015-03-06 14:26:39 +00:00
} ,
2015-09-23 22:08:11 +00:00
}
2015-03-06 14:26:39 +00:00
}
2016-04-07 17:21:31 +00:00
} else if framework . TestContext . Provider == "aws" {
2015-09-23 22:08:11 +00:00
pod . Spec . Volumes = make ( [ ] api . Volume , len ( diskNames ) )
for k , diskName := range diskNames {
pod . Spec . Volumes [ k ] . Name = fmt . Sprintf ( "testpd%v" , k + 1 )
pod . Spec . Volumes [ k ] . VolumeSource = api . VolumeSource {
AWSElasticBlockStore : & api . AWSElasticBlockStoreVolumeSource {
VolumeID : diskName ,
FSType : "ext4" ,
ReadOnly : readOnly ,
2015-03-06 14:26:39 +00:00
} ,
2015-09-23 22:08:11 +00:00
}
2015-03-06 14:26:39 +00:00
}
} else {
2016-04-07 17:21:31 +00:00
panic ( "Unknown provider: " + framework . TestContext . Provider )
2015-03-06 14:26:39 +00:00
}
return pod
2015-02-20 18:01:33 +00:00
}
2015-07-27 02:26:43 +00:00
// Waits for specified PD to to detach from specified hostName
func waitForPDDetach ( diskName , hostName string ) error {
2016-04-07 17:21:31 +00:00
if framework . TestContext . Provider == "gce" || framework . TestContext . Provider == "gke" {
2015-11-24 22:48:41 +00:00
gceCloud , err := getGCECloud ( )
if err != nil {
return err
}
2015-11-23 08:24:32 +00:00
2015-11-24 22:48:41 +00:00
for start := time . Now ( ) ; time . Since ( start ) < gcePDDetachTimeout ; time . Sleep ( gcePDDetachPollTime ) {
diskAttached , err := gceCloud . DiskIsAttached ( diskName , hostName )
2015-07-27 02:26:43 +00:00
if err != nil {
2016-04-07 17:21:31 +00:00
framework . Logf ( "Error waiting for PD %q to detach from node %q. 'DiskIsAttached(...)' failed with %v" , diskName , hostName , err )
2015-07-27 02:26:43 +00:00
return err
}
2015-11-24 22:48:41 +00:00
if ! diskAttached {
2015-07-27 02:26:43 +00:00
// Specified disk does not appear to be attached to specified node
2016-04-07 17:21:31 +00:00
framework . Logf ( "GCE PD %q appears to have successfully detached from %q." , diskName , hostName )
2015-07-27 02:26:43 +00:00
return nil
}
2016-04-07 17:21:31 +00:00
framework . Logf ( "Waiting for GCE PD %q to detach from %q." , diskName , hostName )
2015-07-27 02:26:43 +00:00
}
return fmt . Errorf ( "Gave up waiting for GCE PD %q to detach from %q after %v" , diskName , hostName , gcePDDetachTimeout )
}
return nil
}
2015-11-24 22:48:41 +00:00
func getGCECloud ( ) ( * gcecloud . GCECloud , error ) {
2016-04-07 17:21:31 +00:00
gceCloud , ok := framework . TestContext . CloudConfig . Provider . ( * gcecloud . GCECloud )
2015-11-24 22:48:41 +00:00
if ! ok {
2016-04-07 17:21:31 +00:00
return nil , fmt . Errorf ( "failed to convert CloudConfig.Provider to GCECloud: %#v" , framework . TestContext . CloudConfig . Provider )
2015-11-24 22:48:41 +00:00
}
return gceCloud , nil
}
func detachAndDeletePDs ( diskName string , hosts [ ] string ) {
for _ , host := range hosts {
detachPD ( host , diskName )
By ( fmt . Sprintf ( "Waiting for PD %q to detach from %q" , diskName , host ) )
waitForPDDetach ( diskName , host )
}
By ( fmt . Sprintf ( "Deleting PD %q" , diskName ) )
deletePDWithRetry ( diskName )
}