2015-02-20 18:01:33 +00:00
/ *
2016-06-03 00:25:58 +00:00
Copyright 2015 The Kubernetes Authors .
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"
2016-11-01 00:57:13 +00:00
"os/exec"
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"
2017-01-25 13:13:07 +00:00
"k8s.io/apimachinery/pkg/api/resource"
2017-01-11 14:09:48 +00:00
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
2017-01-24 14:35:22 +00:00
"k8s.io/apimachinery/pkg/util/uuid"
2017-01-12 18:17:43 +00:00
"k8s.io/kubernetes/pkg/api"
2016-11-18 20:55:17 +00:00
"k8s.io/kubernetes/pkg/api/v1"
2016-12-14 01:18:17 +00:00
v1core "k8s.io/kubernetes/pkg/client/clientset_generated/clientset/typed/core/v1"
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"
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-05-30 02:22:22 +00:00
nodeStatusTimeout = 1 * time . Minute
nodeStatusPollTime = 1 * time . Second
2016-06-14 21:46:47 +00:00
gcePDRetryTimeout = 5 * time . Minute
gcePDRetryPollTime = 5 * time . Second
2016-10-11 20:22:06 +00:00
maxReadRetry = 3
2015-07-27 02:26:43 +00:00
)
2016-04-07 17:21:31 +00:00
var _ = framework . KubeDescribe ( "Pod Disks" , func ( ) {
2015-02-20 18:01:33 +00:00
var (
2016-11-18 20:55:17 +00:00
podClient v1core . PodInterface
nodeClient v1core . NodeInterface
2016-07-16 06:10:29 +00:00
host0Name types . NodeName
host1Name types . NodeName
2016-12-20 20:23:56 +00:00
nodes * v1 . NodeList
2015-02-20 18:01:33 +00:00
)
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-10-18 13:00:38 +00:00
podClient = f . ClientSet . Core ( ) . Pods ( f . Namespace . Name )
nodeClient = f . ClientSet . Core ( ) . Nodes ( )
2016-12-20 20:23:56 +00:00
nodes = framework . GetReadySchedulableNodesOrDie ( f . ClientSet )
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
2016-07-16 06:10:29 +00:00
host0Name = types . NodeName ( nodes . Items [ 0 ] . ObjectMeta . Name )
host1Name = types . NodeName ( 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
} )
2017-01-03 17:41:10 +00:00
It ( "should schedule a pod w/ a RW PD, ungracefully remove it, then schedule it on another host [Slow] [Volume]" , 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" )
2017-01-24 15:38:21 +00:00
podClient . Delete ( host0Pod . Name , metav1 . NewDeleteOptions ( 0 ) )
podClient . Delete ( host1Pod . Name , metav1 . NewDeleteOptions ( 0 ) )
2016-07-16 06:10:29 +00:00
detachAndDeletePDs ( diskName , [ ] types . NodeName { 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
2016-05-30 02:22:22 +00:00
// Verify that disk shows up for in node 1's VolumeInUse list
framework . ExpectNoError ( waitForPDInVolumesInUse ( nodeClient , diskName , host0Name , nodeStatusTimeout , true /* shouldExist */ ) )
2015-02-20 18:01:33 +00:00
By ( "deleting host0Pod" )
2016-06-28 20:32:57 +00:00
// Delete pod with 0 grace period
2017-01-24 15:38:21 +00:00
framework . ExpectNoError ( podClient . Delete ( host0Pod . Name , metav1 . 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 ) ) )
2016-05-30 02:22:22 +00:00
// Verify that disk is removed from node 1's VolumeInUse list
framework . ExpectNoError ( waitForPDInVolumesInUse ( nodeClient , diskName , host0Name , nodeStatusTimeout , false /* shouldExist */ ) )
2015-02-20 18:01:33 +00:00
By ( "deleting host1Pod" )
2017-01-24 15:38:21 +00:00
framework . ExpectNoError ( podClient . Delete ( host1Pod . Name , metav1 . NewDeleteOptions ( 0 ) ) , "Failed to delete host1Pod" )
2015-02-20 18:01:33 +00:00
2016-07-12 00:58:25 +00:00
By ( "Test completed successfully, waiting for PD to safely detach" )
waitForPDDetach ( diskName , host0Name )
waitForPDDetach ( diskName , host1Name )
2015-02-20 18:01:33 +00:00
return
} )
2017-01-03 17:41:10 +00:00
It ( "Should schedule a pod w/ a RW PD, gracefully remove it, then schedule it on another host [Slow] [Volume]" , func ( ) {
2016-06-28 20:32:57 +00:00
framework . SkipUnlessProviderIs ( "gce" , "gke" , "aws" )
By ( "creating PD" )
diskName , err := createPDWithRetry ( )
framework . ExpectNoError ( err , "Error creating PD" )
host0Pod := testPDPod ( [ ] string { diskName } , host0Name , false /* readOnly */ , 1 /* numContainers */ )
host1Pod := testPDPod ( [ ] string { diskName } , host1Name , false /* readOnly */ , 1 /* numContainers */ )
containerName := "mycontainer"
defer func ( ) {
// Teardown pods, PD. Ignore errors.
// Teardown should do nothing unless test failed.
By ( "cleaning up PD-RW test environment" )
2017-01-24 15:38:21 +00:00
podClient . Delete ( host0Pod . Name , & metav1 . DeleteOptions { } )
podClient . Delete ( host1Pod . Name , & metav1 . DeleteOptions { } )
2016-07-16 06:10:29 +00:00
detachAndDeletePDs ( diskName , [ ] types . NodeName { host0Name , host1Name } )
2016-06-28 20:32:57 +00:00
} ( )
By ( "submitting host0Pod to kubernetes" )
_ , err = podClient . Create ( host0Pod )
framework . ExpectNoError ( err , fmt . Sprintf ( "Failed to create host0Pod: %v" , err ) )
framework . ExpectNoError ( f . WaitForPodRunningSlow ( host0Pod . Name ) )
testFile := "/testpd1/tracker"
testFileContents := fmt . Sprintf ( "%v" , mathrand . Int ( ) )
framework . ExpectNoError ( f . WriteFileViaContainer ( host0Pod . Name , containerName , testFile , testFileContents ) )
framework . Logf ( "Wrote value: %v" , testFileContents )
// Verify that disk shows up for in node 1's VolumeInUse list
framework . ExpectNoError ( waitForPDInVolumesInUse ( nodeClient , diskName , host0Name , nodeStatusTimeout , true /* shouldExist */ ) )
By ( "deleting host0Pod" )
// Delete pod with default grace period 30s
2017-01-24 15:38:21 +00:00
framework . ExpectNoError ( podClient . Delete ( host0Pod . Name , & metav1 . DeleteOptions { } ) , "Failed to delete host0Pod" )
2016-06-28 20:32:57 +00:00
By ( "submitting host1Pod to kubernetes" )
_ , err = podClient . Create ( host1Pod )
framework . ExpectNoError ( err , "Failed to create host1Pod" )
framework . ExpectNoError ( f . WaitForPodRunningSlow ( host1Pod . Name ) )
v , err := f . ReadFileViaContainer ( host1Pod . Name , containerName , testFile )
framework . ExpectNoError ( err )
framework . Logf ( "Read value: %v" , v )
Expect ( strings . TrimSpace ( v ) ) . To ( Equal ( strings . TrimSpace ( testFileContents ) ) )
// Verify that disk is removed from node 1's VolumeInUse list
framework . ExpectNoError ( waitForPDInVolumesInUse ( nodeClient , diskName , host0Name , nodeStatusTimeout , false /* shouldExist */ ) )
By ( "deleting host1Pod" )
2017-01-24 15:38:21 +00:00
framework . ExpectNoError ( podClient . Delete ( host1Pod . Name , & metav1 . DeleteOptions { } ) , "Failed to delete host1Pod" )
2016-06-28 20:32:57 +00:00
2016-07-12 00:58:25 +00:00
By ( "Test completed successfully, waiting for PD to safely detach" )
waitForPDDetach ( diskName , host0Name )
waitForPDDetach ( diskName , host1Name )
2016-06-28 20:32:57 +00:00
return
} )
2017-01-03 17:41:10 +00:00
It ( "should schedule a pod w/ a readonly PD on two hosts, then remove both ungracefully. [Slow] [Volume]" , 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.
2017-01-24 15:38:21 +00:00
podClient . Delete ( rwPod . Name , metav1 . NewDeleteOptions ( 0 ) )
podClient . Delete ( host0ROPod . Name , metav1 . NewDeleteOptions ( 0 ) )
podClient . Delete ( host1ROPod . Name , metav1 . NewDeleteOptions ( 0 ) )
2016-07-16 06:10:29 +00:00
detachAndDeletePDs ( diskName , [ ] types . NodeName { 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 ) )
2016-06-28 20:32:57 +00:00
// Delete pod with 0 grace period
2017-01-24 15:38:21 +00:00
framework . ExpectNoError ( podClient . Delete ( rwPod . Name , metav1 . NewDeleteOptions ( 0 ) ) , "Failed to delete host0Pod" )
2016-04-07 17:21:31 +00:00
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" )
2017-01-24 15:38:21 +00:00
framework . ExpectNoError ( podClient . Delete ( host0ROPod . Name , metav1 . NewDeleteOptions ( 0 ) ) , "Failed to delete host0ROPod" )
2015-02-20 18:01:33 +00:00
By ( "deleting host1ROPod" )
2017-01-24 15:38:21 +00:00
framework . ExpectNoError ( podClient . Delete ( host1ROPod . Name , metav1 . NewDeleteOptions ( 0 ) ) , "Failed to delete host1ROPod" )
2016-07-12 00:58:25 +00:00
By ( "Test completed successfully, waiting for PD to safely detach" )
waitForPDDetach ( diskName , host0Name )
waitForPDDetach ( diskName , host1Name )
2015-02-20 18:01:33 +00:00
} )
2017-01-03 17:41:10 +00:00
It ( "Should schedule a pod w/ a readonly PD on two hosts, then remove both gracefully. [Slow] [Volume]" , func ( ) {
2016-06-28 20:32:57 +00:00
framework . SkipUnlessProviderIs ( "gce" , "gke" )
By ( "creating PD" )
diskName , err := createPDWithRetry ( )
framework . ExpectNoError ( err , "Error creating PD" )
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 */ )
defer func ( ) {
By ( "cleaning up PD-RO test environment" )
// Teardown pods, PD. Ignore errors.
// Teardown should do nothing unless test failed.
2017-01-24 15:38:21 +00:00
podClient . Delete ( rwPod . Name , & metav1 . DeleteOptions { } )
podClient . Delete ( host0ROPod . Name , & metav1 . DeleteOptions { } )
podClient . Delete ( host1ROPod . Name , & metav1 . DeleteOptions { } )
2016-07-16 06:10:29 +00:00
detachAndDeletePDs ( diskName , [ ] types . NodeName { host0Name , host1Name } )
2016-06-28 20:32:57 +00:00
} ( )
By ( "submitting rwPod to ensure PD is formatted" )
_ , err = podClient . Create ( rwPod )
framework . ExpectNoError ( err , "Failed to create rwPod" )
framework . ExpectNoError ( f . WaitForPodRunningSlow ( rwPod . Name ) )
// Delete pod with default grace period 30s
2017-01-24 15:38:21 +00:00
framework . ExpectNoError ( podClient . Delete ( rwPod . Name , & metav1 . DeleteOptions { } ) , "Failed to delete host0Pod" )
2016-06-28 20:32:57 +00:00
framework . ExpectNoError ( waitForPDDetach ( diskName , host0Name ) )
By ( "submitting host0ROPod to kubernetes" )
_ , err = podClient . Create ( host0ROPod )
framework . ExpectNoError ( err , "Failed to create host0ROPod" )
By ( "submitting host1ROPod to kubernetes" )
_ , err = podClient . Create ( host1ROPod )
framework . ExpectNoError ( err , "Failed to create host1ROPod" )
framework . ExpectNoError ( f . WaitForPodRunningSlow ( host0ROPod . Name ) )
framework . ExpectNoError ( f . WaitForPodRunningSlow ( host1ROPod . Name ) )
By ( "deleting host0ROPod" )
2017-01-24 15:38:21 +00:00
framework . ExpectNoError ( podClient . Delete ( host0ROPod . Name , & metav1 . DeleteOptions { } ) , "Failed to delete host0ROPod" )
2016-06-28 20:32:57 +00:00
By ( "deleting host1ROPod" )
2017-01-24 15:38:21 +00:00
framework . ExpectNoError ( podClient . Delete ( host1ROPod . Name , & metav1 . DeleteOptions { } ) , "Failed to delete host1ROPod" )
2016-07-12 00:58:25 +00:00
By ( "Test completed successfully, waiting for PD to safely detach" )
waitForPDDetach ( diskName , host0Name )
waitForPDDetach ( diskName , host1Name )
2016-06-28 20:32:57 +00:00
} )
2017-01-03 17:41:10 +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] [Volume]" , 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
2016-11-18 20:55:17 +00:00
var host0Pod * v1 . Pod
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.
2016-06-10 15:10:02 +00:00
if host0Pod != nil {
2017-01-24 15:38:21 +00:00
podClient . Delete ( host0Pod . Name , metav1 . NewDeleteOptions ( 0 ) )
2016-06-10 15:10:02 +00:00
}
2016-07-16 06:10:29 +00:00
detachAndDeletePDs ( diskName , [ ] types . NodeName { 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" )
2016-06-10 15:10:02 +00:00
host0Pod = testPDPod ( [ ] string { diskName } , host0Name , false /* readOnly */ , numContainers )
2015-07-20 02:00:10 +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-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" )
2017-01-24 15:38:21 +00:00
framework . ExpectNoError ( podClient . Delete ( host0Pod . Name , metav1 . NewDeleteOptions ( 0 ) ) , "Failed to delete host0Pod" )
2015-07-10 11:13:42 +00:00
}
2016-07-12 00:58:25 +00:00
By ( "Test completed successfully, waiting for PD to safely detach" )
waitForPDDetach ( diskName , host0Name )
2015-07-20 02:00:10 +00:00
} )
2015-09-23 22:08:11 +00:00
2017-01-03 17:41:10 +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] [Volume]" , 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" )
2016-11-18 20:55:17 +00:00
var host0Pod * v1 . Pod
2015-09-23 22:08:11 +00:00
defer func ( ) {
By ( "cleaning up PD-RW test environment" )
// Teardown pods, PD. Ignore errors.
// Teardown should do nothing unless test failed.
2016-06-10 15:10:02 +00:00
if host0Pod != nil {
2017-01-24 15:38:21 +00:00
podClient . Delete ( host0Pod . Name , metav1 . NewDeleteOptions ( 0 ) )
2016-06-10 15:10:02 +00:00
}
2016-07-16 06:10:29 +00:00
detachAndDeletePDs ( disk1Name , [ ] types . NodeName { host0Name } )
detachAndDeletePDs ( disk2Name , [ ] types . NodeName { 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" )
2016-06-10 15:10:02 +00:00
host0Pod = testPDPod ( [ ] string { disk1Name , disk2Name } , host0Name , false /* readOnly */ , 1 /* numContainers */ )
2015-09-23 22:08:11 +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-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" )
2017-01-24 15:38:21 +00:00
framework . ExpectNoError ( podClient . Delete ( host0Pod . Name , metav1 . NewDeleteOptions ( 0 ) ) , "Failed to delete host0Pod" )
2015-09-23 22:08:11 +00:00
}
2016-07-12 00:58:25 +00:00
By ( "Test completed successfully, waiting for PD to safely detach" )
waitForPDDetach ( disk1Name , host0Name )
waitForPDDetach ( disk2Name , host0Name )
2015-09-23 22:08:11 +00:00
} )
2016-11-01 00:57:13 +00:00
2017-01-03 17:41:10 +00:00
It ( "should be able to detach from a node which was deleted [Slow] [Disruptive] [Volume]" , func ( ) {
2016-11-01 00:57:13 +00:00
framework . SkipUnlessProviderIs ( "gce" )
initialGroupSize , err := GroupSize ( framework . TestContext . CloudConfig . NodeInstanceGroup )
framework . ExpectNoError ( err , "Error getting group size" )
By ( "Creating a pd" )
diskName , err := createPDWithRetry ( )
framework . ExpectNoError ( err , "Error creating a pd" )
host0Pod := testPDPod ( [ ] string { diskName } , host0Name , false , 1 )
containerName := "mycontainer"
defer func ( ) {
By ( "Cleaning up PD-RW test env" )
2017-01-24 15:38:21 +00:00
podClient . Delete ( host0Pod . Name , metav1 . NewDeleteOptions ( 0 ) )
2016-11-01 00:57:13 +00:00
detachAndDeletePDs ( diskName , [ ] types . NodeName { host0Name } )
} ( )
By ( "submitting host0Pod to kubernetes" )
_ , err = podClient . Create ( host0Pod )
framework . ExpectNoError ( err , fmt . Sprintf ( "Failed to create host0pod: %v" , err ) )
framework . ExpectNoError ( f . WaitForPodRunningSlow ( host0Pod . Name ) )
testFile := "/testpd1/tracker"
testFileContents := fmt . Sprintf ( "%v" , mathrand . Int ( ) )
framework . ExpectNoError ( f . WriteFileViaContainer ( host0Pod . Name , containerName , testFile , testFileContents ) )
framework . Logf ( "Wrote value: %v" , testFileContents )
// Verify that disk shows up in node 0's volumeInUse list
framework . ExpectNoError ( waitForPDInVolumesInUse ( nodeClient , diskName , host0Name , nodeStatusTimeout , true /* should exist*/ ) )
output , err := exec . Command ( "gcloud" , "compute" , "instances" , "list" ) . CombinedOutput ( )
framework . ExpectNoError ( err , fmt . Sprintf ( "Unable to get list of node instances %v" , err ) )
Expect ( true , strings . Contains ( string ( output ) , string ( host0Name ) ) )
By ( "deleting host0" )
output , err = exec . Command ( "gcloud" , "compute" , "instances" , "delete" , string ( host0Name ) , "--project=" + framework . TestContext . CloudConfig . ProjectID , "--zone=" + framework . TestContext . CloudConfig . Zone ) . CombinedOutput ( )
framework . ExpectNoError ( err , fmt . Sprintf ( "Failed to delete host0pod: %v" , err ) )
output , err = exec . Command ( "gcloud" , "compute" , "instances" , "list" ) . CombinedOutput ( )
framework . ExpectNoError ( err , fmt . Sprintf ( "Unable to get list of node instances %v" , err ) )
Expect ( false , strings . Contains ( string ( output ) , string ( host0Name ) ) )
// The disk should be detached from host0 on it's deletion
By ( "Waiting for pd to detach from host0" )
waitForPDDetach ( diskName , host0Name )
framework . ExpectNoError ( WaitForGroupSize ( framework . TestContext . CloudConfig . NodeInstanceGroup , int32 ( initialGroupSize ) ) , "Unable to get back the cluster to inital size" )
return
} )
2016-12-20 20:23:56 +00:00
2017-01-03 17:41:10 +00:00
It ( "should be able to detach from a node whose api object was deleted [Slow] [Disruptive] [Volume]" , func ( ) {
2016-12-20 20:23:56 +00:00
framework . SkipUnlessProviderIs ( "gce" )
initialGroupSize , err := GroupSize ( framework . TestContext . CloudConfig . NodeInstanceGroup )
framework . ExpectNoError ( err , "Error getting group size" )
By ( "Creating a pd" )
diskName , err := createPDWithRetry ( )
framework . ExpectNoError ( err , "Error creating a pd" )
host0Pod := testPDPod ( [ ] string { diskName } , host0Name , false , 1 )
originalCount := len ( nodes . Items )
containerName := "mycontainer"
nodeToDelete := & nodes . Items [ 0 ]
defer func ( ) error {
By ( "Cleaning up PD-RW test env" )
detachAndDeletePDs ( diskName , [ ] types . NodeName { host0Name } )
nodeToDelete . ObjectMeta . SetResourceVersion ( "0" )
// need to set the resource version or else the Create() fails
_ , err := nodeClient . Create ( nodeToDelete )
framework . ExpectNoError ( err , "Unable to re-create the deleted node" )
framework . ExpectNoError ( WaitForGroupSize ( framework . TestContext . CloudConfig . NodeInstanceGroup , int32 ( initialGroupSize ) ) , "Unable to get the node group back to the original size" )
framework . WaitForNodeToBeReady ( f . ClientSet , nodeToDelete . Name , nodeStatusTimeout )
if len ( nodes . Items ) != originalCount {
return fmt . Errorf ( "The node count is not back to original count" )
}
return nil
} ( )
By ( "submitting host0Pod to kubernetes" )
_ , err = podClient . Create ( host0Pod )
framework . ExpectNoError ( err , fmt . Sprintf ( "Failed to create host0pod: %v" , err ) )
framework . ExpectNoError ( f . WaitForPodRunningSlow ( host0Pod . Name ) )
testFile := "/testpd1/tracker"
testFileContents := fmt . Sprintf ( "%v" , mathrand . Int ( ) )
framework . ExpectNoError ( f . WriteFileViaContainer ( host0Pod . Name , containerName , testFile , testFileContents ) )
framework . Logf ( "Wrote value: %v" , testFileContents )
// Verify that disk shows up in node 0's volumeInUse list
framework . ExpectNoError ( waitForPDInVolumesInUse ( nodeClient , diskName , host0Name , nodeStatusTimeout , true /* should exist*/ ) )
By ( "deleting api object of host0" )
2017-01-24 15:38:21 +00:00
framework . ExpectNoError ( nodeClient . Delete ( string ( host0Name ) , metav1 . NewDeleteOptions ( 0 ) ) , "Unable to delete host0" )
2016-12-20 20:23:56 +00:00
By ( "deleting host0pod" )
2017-01-24 15:38:21 +00:00
framework . ExpectNoError ( podClient . Delete ( host0Pod . Name , metav1 . NewDeleteOptions ( 0 ) ) , "Unable to delete host0Pod" )
2016-12-20 20:23:56 +00:00
// The disk should be detached from host0 on its deletion
By ( "Waiting for pd to detach from host0" )
framework . ExpectNoError ( waitForPDDetach ( diskName , host0Name ) , "Timed out waiting for detach pd" )
} )
2015-07-20 02:00:10 +00:00
} )
2015-11-24 22:48:41 +00:00
func createPDWithRetry ( ) ( string , error ) {
newDiskName := ""
var err error
2016-06-14 21:46:47 +00:00
for start := time . Now ( ) ; time . Since ( start ) < gcePDRetryTimeout ; time . Sleep ( gcePDRetryPollTime ) {
2015-11-24 22:48:41 +00:00
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
2016-06-14 21:46:47 +00:00
for start := time . Now ( ) ; time . Since ( start ) < gcePDRetryTimeout ; time . Sleep ( gcePDRetryPollTime ) {
2015-07-20 02:00:10 +00:00
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 {
2016-10-11 20:22:06 +00:00
var value string
// Add a retry to avoid temporal failure in reading the content
for i := 0 ; i < maxReadRetry ; i ++ {
v , err := f . ReadFileViaContainer ( podName , containerName , filePath )
value = v
2016-10-03 22:44:40 +00:00
if err != nil {
framework . Logf ( "Error reading file: %v" , err )
}
2016-10-11 20:22:06 +00:00
framework . ExpectNoError ( err )
framework . Logf ( "Read file %q with content: %v (iteration %d)" , filePath , v , i )
if strings . TrimSpace ( v ) != strings . TrimSpace ( expectedContents ) {
framework . Logf ( "Warning: read content <%q> does not match execpted content <%q>." , v , expectedContents )
size , err := f . CheckFileSizeViaContainer ( podName , containerName , filePath )
if err != nil {
framework . Logf ( "Error checking file size: %v" , err )
}
framework . Logf ( "Check file %q size: %q" , filePath , size )
} else {
break
}
2016-10-03 22:44:40 +00:00
}
2016-10-11 20:22:06 +00:00
Expect ( strings . TrimSpace ( value ) ) . 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" {
2016-07-26 15:13:18 +00:00
pdName := fmt . Sprintf ( "%s-%s" , framework . TestContext . Prefix , string ( uuid . NewUUID ( ) ) )
2015-03-06 14:26:39 +00:00
2017-02-17 04:33:41 +00:00
gceCloud , err := framework . GetGCECloud ( )
2015-11-24 22:48:41 +00:00
if err != nil {
return "" , err
}
2016-01-27 14:16:05 +00:00
tags := map [ string ] string { }
2016-08-18 08:36:50 +00:00
err = gceCloud . CreateDisk ( pdName , gcecloud . DiskTypeSSD , 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" {
2017-02-17 04:33:41 +00:00
gceCloud , err := framework . GetGCECloud ( )
2015-11-24 22:48:41 +00:00
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
}
2016-07-16 06:10:29 +00:00
func detachPD ( nodeName types . NodeName , pdName string ) error {
2016-04-07 17:21:31 +00:00
if framework . TestContext . Provider == "gce" || framework . TestContext . Provider == "gke" {
2017-02-17 04:33:41 +00:00
gceCloud , err := framework . GetGCECloud ( )
2015-11-24 22:48:41 +00:00
if err != nil {
return err
}
2016-07-16 06:10:29 +00:00
err = gceCloud . DetachDisk ( pdName , nodeName )
2015-11-24 22:48:41 +00:00
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
}
2016-11-18 20:55:17 +00:00
func testPDPod ( diskNames [ ] string , targetNode types . NodeName , readOnly bool , numContainers int ) * v1 . Pod {
containers := make ( [ ] v1 . Container , numContainers )
2015-07-20 02:00:10 +00:00
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" }
2016-11-18 20:55:17 +00:00
containers [ i ] . VolumeMounts = make ( [ ] v1 . VolumeMount , len ( diskNames ) )
2015-09-23 22:08:11 +00:00
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
}
2016-11-18 20:55:17 +00:00
containers [ i ] . Resources . Limits = v1 . ResourceList { }
containers [ i ] . Resources . Limits [ v1 . ResourceCPU ] = * resource . NewQuantity ( int64 ( 0 ) , resource . DecimalSI )
2015-07-20 02:00:10 +00:00
}
2016-11-18 20:55:17 +00:00
pod := & v1 . Pod {
2016-12-03 18:57:26 +00:00
TypeMeta : metav1 . TypeMeta {
2015-02-20 18:01:33 +00:00
Kind : "Pod" ,
2017-01-12 18:17:43 +00:00
APIVersion : api . Registry . GroupOrDie ( v1 . GroupName ) . GroupVersion . String ( ) ,
2015-02-20 18:01:33 +00:00
} ,
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta {
2016-07-26 15:13:18 +00:00
Name : "pd-test-" + string ( uuid . NewUUID ( ) ) ,
2015-02-20 18:01:33 +00:00
} ,
2016-11-18 20:55:17 +00:00
Spec : v1 . PodSpec {
2015-07-20 02:00:10 +00:00
Containers : containers ,
2016-07-16 06:10:29 +00:00
NodeName : string ( targetNode ) ,
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" {
2016-11-18 20:55:17 +00:00
pod . Spec . Volumes = make ( [ ] v1 . Volume , len ( diskNames ) )
2015-09-23 22:08:11 +00:00
for k , diskName := range diskNames {
pod . Spec . Volumes [ k ] . Name = fmt . Sprintf ( "testpd%v" , k + 1 )
2016-11-18 20:55:17 +00:00
pod . Spec . Volumes [ k ] . VolumeSource = v1 . VolumeSource {
GCEPersistentDisk : & v1 . GCEPersistentDiskVolumeSource {
2015-09-23 22:08:11 +00:00
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" {
2016-11-18 20:55:17 +00:00
pod . Spec . Volumes = make ( [ ] v1 . Volume , len ( diskNames ) )
2015-09-23 22:08:11 +00:00
for k , diskName := range diskNames {
pod . Spec . Volumes [ k ] . Name = fmt . Sprintf ( "testpd%v" , k + 1 )
2016-11-18 20:55:17 +00:00
pod . Spec . Volumes [ k ] . VolumeSource = v1 . VolumeSource {
AWSElasticBlockStore : & v1 . AWSElasticBlockStoreVolumeSource {
2015-09-23 22:08:11 +00:00
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
2016-07-16 06:10:29 +00:00
func waitForPDDetach ( diskName string , nodeName types . NodeName ) error {
2016-04-07 17:21:31 +00:00
if framework . TestContext . Provider == "gce" || framework . TestContext . Provider == "gke" {
2016-07-16 06:10:29 +00:00
framework . Logf ( "Waiting for GCE PD %q to detach from node %q." , diskName , nodeName )
2017-02-17 04:33:41 +00:00
gceCloud , err := framework . GetGCECloud ( )
2015-11-24 22:48:41 +00:00
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 ) {
2016-07-16 06:10:29 +00:00
diskAttached , err := gceCloud . DiskIsAttached ( diskName , nodeName )
2015-07-27 02:26:43 +00:00
if err != nil {
2016-07-16 06:10:29 +00:00
framework . Logf ( "Error waiting for PD %q to detach from node %q. 'DiskIsAttached(...)' failed with %v" , diskName , nodeName , 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-07-16 06:10:29 +00:00
framework . Logf ( "GCE PD %q appears to have successfully detached from %q." , diskName , nodeName )
2015-07-27 02:26:43 +00:00
return nil
}
2016-07-16 06:10:29 +00:00
framework . Logf ( "Waiting for GCE PD %q to detach from %q." , diskName , nodeName )
2015-07-27 02:26:43 +00:00
}
2016-07-16 06:10:29 +00:00
return fmt . Errorf ( "Gave up waiting for GCE PD %q to detach from %q after %v" , diskName , nodeName , gcePDDetachTimeout )
2015-07-27 02:26:43 +00:00
}
return nil
}
2015-11-24 22:48:41 +00:00
2016-07-16 06:10:29 +00:00
func detachAndDeletePDs ( diskName string , hosts [ ] types . NodeName ) {
2015-11-24 22:48:41 +00:00
for _ , host := range hosts {
2016-07-12 00:58:25 +00:00
framework . Logf ( "Detaching GCE PD %q from node %q." , diskName , host )
2015-11-24 22:48:41 +00:00
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 )
}
2016-05-30 02:22:22 +00:00
func waitForPDInVolumesInUse (
2016-11-18 20:55:17 +00:00
nodeClient v1core . NodeInterface ,
2016-07-16 06:10:29 +00:00
diskName string ,
nodeName types . NodeName ,
2016-05-30 02:22:22 +00:00
timeout time . Duration ,
shouldExist bool ) error {
logStr := "to contain"
if ! shouldExist {
logStr = "to NOT contain"
}
framework . Logf (
"Waiting for node %s's VolumesInUse Status %s PD %q" ,
nodeName , logStr , diskName )
for start := time . Now ( ) ; time . Since ( start ) < timeout ; time . Sleep ( nodeStatusPollTime ) {
2016-12-07 14:40:26 +00:00
nodeObj , err := nodeClient . Get ( string ( nodeName ) , metav1 . GetOptions { } )
2016-05-30 02:22:22 +00:00
if err != nil || nodeObj == nil {
framework . Logf (
"Failed to fetch node object %q from API server. err=%v" ,
nodeName , err )
continue
}
exists := false
for _ , volumeInUse := range nodeObj . Status . VolumesInUse {
volumeInUseStr := string ( volumeInUse )
if strings . Contains ( volumeInUseStr , diskName ) {
if shouldExist {
framework . Logf (
"Found PD %q in node %q's VolumesInUse Status: %q" ,
diskName , nodeName , volumeInUseStr )
return nil
}
exists = true
}
}
if ! shouldExist && ! exists {
framework . Logf (
"Verified PD %q does not exist in node %q's VolumesInUse Status." ,
diskName , nodeName )
return nil
}
}
return fmt . Errorf (
"Timed out waiting for node %s VolumesInUse Status %s diskName %q" ,
nodeName , logStr , diskName )
}