Merge pull request #11054 from jsafrane/devel/iscsi-test
Add e2e RBD and iSCSI volume tests.
This commit is contained in:
@@ -63,7 +63,8 @@ var _ = Describe("[Skipped] persistentVolumes", func() {
|
||||
volumeTestCleanup(c, config)
|
||||
}()
|
||||
|
||||
serverIP := startVolumeServer(c, config)
|
||||
pod := startVolumeServer(c, config)
|
||||
serverIP := pod.Status.PodIP
|
||||
Logf("NFS server IP address: %v", serverIP)
|
||||
|
||||
pv := makePersistentVolume(serverIP)
|
||||
|
@@ -35,7 +35,6 @@ import (
|
||||
"fmt"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/client"
|
||||
"k8s.io/kubernetes/pkg/util"
|
||||
"time"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
@@ -53,18 +52,19 @@ type VolumeTestConfig struct {
|
||||
serverImage string
|
||||
// Ports to export from the server pod. TCP only.
|
||||
serverPorts []int
|
||||
// Volumes needed to be mounted to the server container from the host
|
||||
// map <host (source) path> -> <container (dst.) path>
|
||||
volumes map[string]string
|
||||
}
|
||||
|
||||
// Starts a container specified by config.serverImage and exports all
|
||||
// config.serverPorts from it via a service. The function returns IP
|
||||
// address of the service.
|
||||
func startVolumeServer(client *client.Client, config VolumeTestConfig) string {
|
||||
// config.serverPorts from it. The returned pod should be used to get the server
|
||||
// IP address and create appropriate VolumeSource.
|
||||
func startVolumeServer(client *client.Client, config VolumeTestConfig) *api.Pod {
|
||||
podClient := client.Pods(config.namespace)
|
||||
serviceClient := client.Services(config.namespace)
|
||||
|
||||
portCount := len(config.serverPorts)
|
||||
serverPodPorts := make([]api.ContainerPort, portCount)
|
||||
servicePorts := make([]api.ServicePort, portCount)
|
||||
|
||||
for i := 0; i < portCount; i++ {
|
||||
portName := fmt.Sprintf("%s-%d", config.prefix, i)
|
||||
@@ -74,12 +74,25 @@ func startVolumeServer(client *client.Client, config VolumeTestConfig) string {
|
||||
ContainerPort: config.serverPorts[i],
|
||||
Protocol: api.ProtocolTCP,
|
||||
}
|
||||
servicePorts[i] = api.ServicePort{
|
||||
Name: portName,
|
||||
Protocol: "TCP",
|
||||
Port: config.serverPorts[i],
|
||||
TargetPort: util.NewIntOrStringFromInt(config.serverPorts[i]),
|
||||
}
|
||||
|
||||
volumeCount := len(config.volumes)
|
||||
volumes := make([]api.Volume, volumeCount)
|
||||
mounts := make([]api.VolumeMount, volumeCount)
|
||||
|
||||
i := 0
|
||||
for src, dst := range config.volumes {
|
||||
mountName := fmt.Sprintf("path%d", i)
|
||||
volumes[i].Name = mountName
|
||||
volumes[i].VolumeSource.HostPath = &api.HostPathVolumeSource{
|
||||
Path: src,
|
||||
}
|
||||
|
||||
mounts[i].Name = mountName
|
||||
mounts[i].ReadOnly = false
|
||||
mounts[i].MountPath = dst
|
||||
|
||||
i++
|
||||
}
|
||||
|
||||
By(fmt.Sprint("creating ", config.prefix, " server pod"))
|
||||
@@ -105,9 +118,11 @@ func startVolumeServer(client *client.Client, config VolumeTestConfig) string {
|
||||
SecurityContext: &api.SecurityContext{
|
||||
Privileged: privileged,
|
||||
},
|
||||
Ports: serverPodPorts,
|
||||
Ports: serverPodPorts,
|
||||
VolumeMounts: mounts,
|
||||
},
|
||||
},
|
||||
Volumes: volumes,
|
||||
},
|
||||
}
|
||||
_, err := podClient.Create(serverPod)
|
||||
@@ -115,26 +130,13 @@ func startVolumeServer(client *client.Client, config VolumeTestConfig) string {
|
||||
|
||||
expectNoError(waitForPodRunningInNamespace(client, serverPod.Name, config.namespace))
|
||||
|
||||
By(fmt.Sprint("creating ", config.prefix, " service"))
|
||||
service := &api.Service{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: config.prefix + "-server",
|
||||
},
|
||||
Spec: api.ServiceSpec{
|
||||
Selector: map[string]string{
|
||||
"role": config.prefix + "-server",
|
||||
},
|
||||
Ports: servicePorts,
|
||||
},
|
||||
}
|
||||
createdService, err := serviceClient.Create(service)
|
||||
expectNoError(err, "Failed to create %s service: %v", service.Name, err)
|
||||
By("locating the server pod")
|
||||
pod, err := podClient.Get(serverPod.Name)
|
||||
expectNoError(err, "Cannot locate the server pod %v: %v", serverPod.Name, err)
|
||||
|
||||
By("sleeping a bit to give the server time to start")
|
||||
time.Sleep(20 * time.Second)
|
||||
|
||||
ip := createdService.Spec.ClusterIP
|
||||
return ip
|
||||
return pod
|
||||
}
|
||||
|
||||
// Clean both server and client pods.
|
||||
@@ -144,11 +146,9 @@ func volumeTestCleanup(client *client.Client, config VolumeTestConfig) {
|
||||
defer GinkgoRecover()
|
||||
|
||||
podClient := client.Pods(config.namespace)
|
||||
serviceClient := client.Services(config.namespace)
|
||||
|
||||
// ignore all errors, the pods may not be even created
|
||||
podClient.Delete(config.prefix+"-client", nil)
|
||||
serviceClient.Delete(config.prefix + "-server")
|
||||
podClient.Delete(config.prefix+"-server", nil)
|
||||
}
|
||||
|
||||
@@ -261,7 +261,8 @@ var _ = Describe("Volumes", func() {
|
||||
volumeTestCleanup(c, config)
|
||||
}
|
||||
}()
|
||||
serverIP := startVolumeServer(c, config)
|
||||
pod := startVolumeServer(c, config)
|
||||
serverIP := pod.Status.PodIP
|
||||
Logf("NFS server IP address: %v", serverIP)
|
||||
|
||||
volume := api.VolumeSource{
|
||||
@@ -297,9 +298,49 @@ var _ = Describe("Volumes", func() {
|
||||
volumeTestCleanup(c, config)
|
||||
}
|
||||
}()
|
||||
serverIP := startVolumeServer(c, config)
|
||||
pod := startVolumeServer(c, config)
|
||||
serverIP := pod.Status.PodIP
|
||||
Logf("Gluster server IP address: %v", serverIP)
|
||||
|
||||
// create Endpoints for the server
|
||||
endpoints := api.Endpoints{
|
||||
TypeMeta: api.TypeMeta{
|
||||
Kind: "Endpoints",
|
||||
APIVersion: "v1",
|
||||
},
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: config.prefix + "-server",
|
||||
},
|
||||
Subsets: []api.EndpointSubset{
|
||||
{
|
||||
Addresses: []api.EndpointAddress{
|
||||
{
|
||||
IP: serverIP,
|
||||
},
|
||||
},
|
||||
Ports: []api.EndpointPort{
|
||||
{
|
||||
Name: "gluster",
|
||||
Port: 24007,
|
||||
Protocol: api.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
endClient := c.Endpoints(config.namespace)
|
||||
|
||||
defer func() {
|
||||
if clean {
|
||||
endClient.Delete(config.prefix + "-server")
|
||||
}
|
||||
}()
|
||||
|
||||
if _, err := endClient.Create(&endpoints); err != nil {
|
||||
Failf("Failed to create endpoints for Gluster server: %v", err)
|
||||
}
|
||||
|
||||
volume := api.VolumeSource{
|
||||
Glusterfs: &api.GlusterfsVolumeSource{
|
||||
EndpointsName: config.prefix + "-server",
|
||||
@@ -312,4 +353,130 @@ var _ = Describe("Volumes", func() {
|
||||
testVolumeClient(c, config, volume, "Hello from GlusterFS!")
|
||||
})
|
||||
})
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// iSCSI
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Marked with [Skipped] to skip the test by default (see driver.go),
|
||||
// the test needs privileged containers, which are disabled by default.
|
||||
// Also, make sure that iscsiadm utility and iscsi target kernel modules
|
||||
// are installed on all nodes!
|
||||
// Run the test with "go run hack/e2e.go ... --ginkgo.focus=iSCSI"
|
||||
|
||||
Describe("[Skipped] iSCSI", func() {
|
||||
It("should be mountable", func() {
|
||||
config := VolumeTestConfig{
|
||||
namespace: namespace.Name,
|
||||
prefix: "iscsi",
|
||||
serverImage: "gcr.io/google_containers/volume-iscsi",
|
||||
serverPorts: []int{3260},
|
||||
volumes: map[string]string{
|
||||
// iSCSI container needs to insert modules from the host
|
||||
"/lib/modules": "/lib/modules",
|
||||
},
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if clean {
|
||||
volumeTestCleanup(c, config)
|
||||
}
|
||||
}()
|
||||
pod := startVolumeServer(c, config)
|
||||
serverIP := pod.Status.PodIP
|
||||
Logf("iSCSI server IP address: %v", serverIP)
|
||||
|
||||
volume := api.VolumeSource{
|
||||
ISCSI: &api.ISCSIVolumeSource{
|
||||
TargetPortal: serverIP + ":3260",
|
||||
// from contrib/for-tests/volumes-tester/iscsi/initiatorname.iscsi
|
||||
IQN: "iqn.2003-01.org.linux-iscsi.f21.x8664:sn.4b0aae584f7c",
|
||||
Lun: 0,
|
||||
FSType: "ext2",
|
||||
ReadOnly: true,
|
||||
},
|
||||
}
|
||||
// Must match content of contrib/for-tests/volumes-tester/iscsi/block.tar.gz
|
||||
testVolumeClient(c, config, volume, "Hello from iSCSI")
|
||||
})
|
||||
})
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Ceph RBD
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Marked with [Skipped] to skip the test by default (see driver.go),
|
||||
// the test needs privileged containers, which are disabled by default.
|
||||
// Run the test with "go run hack/e2e.go ... --ginkgo.focus=RBD"
|
||||
|
||||
// Run the test with "go run hack/e2e.go ... --ginkgo.focus=Volume"
|
||||
Describe("[Skipped] Ceph RBD", func() {
|
||||
It("should be mountable", func() {
|
||||
config := VolumeTestConfig{
|
||||
namespace: namespace.Name,
|
||||
prefix: "rbd",
|
||||
serverImage: "gcr.io/google_containers/volume-rbd",
|
||||
serverPorts: []int{6789},
|
||||
volumes: map[string]string{
|
||||
// iSCSI container needs to insert modules from the host
|
||||
"/lib/modules": "/lib/modules",
|
||||
"/sys": "/sys",
|
||||
},
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if clean {
|
||||
volumeTestCleanup(c, config)
|
||||
}
|
||||
}()
|
||||
pod := startVolumeServer(c, config)
|
||||
serverIP := pod.Status.PodIP
|
||||
Logf("Ceph server IP address: %v", serverIP)
|
||||
|
||||
// create secrets for the server
|
||||
secret := api.Secret{
|
||||
TypeMeta: api.TypeMeta{
|
||||
Kind: "Secret",
|
||||
APIVersion: "v1",
|
||||
},
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: config.prefix + "-secret",
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
// from contrib/for-tests/volumes-tester/rbd/keyring
|
||||
"key": []byte("AQDRrKNVbEevChAAEmRC+pW/KBVHxa0w/POILA=="),
|
||||
},
|
||||
}
|
||||
|
||||
secClient := c.Secrets(config.namespace)
|
||||
|
||||
defer func() {
|
||||
if clean {
|
||||
secClient.Delete(config.prefix + "-secret")
|
||||
}
|
||||
}()
|
||||
|
||||
if _, err := secClient.Create(&secret); err != nil {
|
||||
Failf("Failed to create secrets for Ceph RBD: %v", err)
|
||||
}
|
||||
|
||||
volume := api.VolumeSource{
|
||||
RBD: &api.RBDVolumeSource{
|
||||
CephMonitors: []string{serverIP},
|
||||
RBDPool: "rbd",
|
||||
RBDImage: "foo",
|
||||
RadosUser: "admin",
|
||||
SecretRef: &api.LocalObjectReference{
|
||||
Name: config.prefix + "-secret",
|
||||
},
|
||||
FSType: "ext2",
|
||||
ReadOnly: true,
|
||||
},
|
||||
}
|
||||
// Must match content of contrib/for-tests/volumes-tester/gluster/index.html
|
||||
testVolumeClient(c, config, volume, "Hello from RBD")
|
||||
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
|
Reference in New Issue
Block a user