Add e2e iSCSI volume test.

The test container needs to run with --privileged, therefore it's disabled by
default.
This commit is contained in:
Jan Safranek 2015-08-03 13:35:51 +02:00
parent ebcc558734
commit adba474ffa
9 changed files with 331 additions and 1 deletions

View File

@ -0,0 +1,33 @@
# Copyright 2015 Google Inc. All rights reserved.
#
# 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.
FROM fedora
MAINTAINER Jan Safranek, jsafrane@redhat.com
RUN yum install -y iscsi-initiator-utils targetcli net-tools strace && yum clean all
ADD run_iscsid.sh /usr/local/bin/
ADD initiatorname.iscsi /etc/iscsi/
ADD block.tar.gz /
# This JSON file was generated by targetcli with these commands:
# /backstores/fileio create block /block
# /iscsi create
# # Enable demo mode (no authentication!):
# /iscsi/iqn.2003-01.org.linux-iscsi.f21.x8664:sn.4b0aae584f7c/tpg1 set attribute authentication=0 demo_mode_write_protect=0 generate_node_acls=1 cache_dynamic_acls=1
# /iscsi/iqn.2003-01.org.linux-iscsi.f21.x8664:sn.4b0aae584f7c/tpg1/luns create /backstores/fileio/block
# saveconfig
ADD saveconfig.json /etc/target/
EXPOSE 3260/tcp
ENTRYPOINT ["/usr/local/bin/run_iscsid.sh"]

View File

@ -0,0 +1,22 @@
all: push
TAG = 0.1
container:
# Build new image and automatically tag it as latest
docker build -t gcr.io/google_containers/volume-iscsi .
# Add the version tag to the latest image
docker tag gcr.io/google_containers/volume-iscsi gcr.io/google_containers/volume-iscsi:$(TAG)
block:
# Create block.tar.gz with ext2 block device with index.html inside.
# block.tar.gz is already available in git and users don't need to
# regenerate it, this target is here just for reference.
# Run as root!
./create_block.sh
push: container
# Push image tagged as latest to repository
gcloud docker push gcr.io/google_containers/volume-iscsi
# Push version tagged image to repository (since this image is already pushed it will simply create or update version tag)
gcloud docker push gcr.io/google_containers/volume-iscsi:$(TAG)

View File

@ -0,0 +1,14 @@
# iSCSI target container for testing.
Inspired by https://github.com/rvykydal/dockerfile-iscsid
* The container needs /lib/modules from the host to insert appropriate
kernel modules for iscsi. This assumes that these modules are installed
on the host!
* The container needs to run with docker --privileged
block.tar.gz is a small ext2 filesystem created by `make block` (run as root!)
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/contrib/for-tests/volumes-tester/iscsi/README.md?pixel)]()

Binary file not shown.

View File

@ -0,0 +1,46 @@
#!/bin/bash
# Copyright 2015 The Kubernetes Authors All rights reserved.
#
# 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.
# Exit on the first error.
set -e
MNTDIR=`mktemp -d`
cleanup()
{
# Make sure we return the right exit code
RET=$?
# Silently remove everything and ignore errors
set +e
/bin/umount $MNTDIR 2>/dev/null
/bin/rmdir $MNTDIR 2>/dev/null
/bin/rm block 2>/dev/null
exit $RET
}
trap cleanup TERM EXIT
# Create 1MB device with ext2
dd if=/dev/zero of=block count=1 bs=1M
mkfs.ext2 block
# Add index.html to it
mount -o loop block $MNTDIR
echo "Hello from iSCSI" > $MNTDIR/index.html
umount $MNTDIR
rm block.tar.gz 2>/dev/null || :
tar cfz block.tar.gz block

View File

@ -0,0 +1 @@
InitiatorName=iqn.1994-05.com.redhat:eb59fbe2c4c5

View File

@ -0,0 +1,41 @@
#!/bin/bash
# Copyright 2015 The Kubernetes Authors All rights reserved.
#
# 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.
function start()
{
targetcli restoreconfig
iscsid
echo "iscsid started"
}
function stop()
{
echo "Stopping iscsid"
kill $( cat /var/run/iscsid.pid )
targetcli clearconfig confirm=True
echo "iscsid stopped"
exit 0
}
trap stop TERM
start
while true; do
sleep 5
done

View File

@ -0,0 +1,102 @@
{
"fabric_modules": [],
"storage_objects": [
{
"attributes": {
"block_size": 512,
"emulate_3pc": 1,
"emulate_caw": 1,
"emulate_dpo": 0,
"emulate_fua_read": 0,
"emulate_fua_write": 1,
"emulate_model_alias": 1,
"emulate_rest_reord": 0,
"emulate_tas": 1,
"emulate_tpu": 0,
"emulate_tpws": 0,
"emulate_ua_intlck_ctrl": 0,
"emulate_write_cache": 1,
"enforce_pr_isids": 1,
"force_pr_aptpl": 0,
"is_nonrot": 0,
"max_unmap_block_desc_count": 1,
"max_unmap_lba_count": 8192,
"max_write_same_len": 4096,
"optimal_sectors": 16384,
"pi_prot_format": 0,
"pi_prot_type": 0,
"queue_depth": 128,
"unmap_granularity": 1,
"unmap_granularity_alignment": 0
},
"dev": "block",
"name": "block",
"plugin": "fileio",
"size": 1048576,
"write_back": true,
"wwn": "521c57aa-9d9b-4e5d-ab1a-527487f92a33"
}
],
"targets": [
{
"fabric": "iscsi",
"tpgs": [
{
"attributes": {
"authentication": 0,
"cache_dynamic_acls": 1,
"default_cmdsn_depth": 64,
"default_erl": 0,
"demo_mode_discovery": 1,
"demo_mode_write_protect": 0,
"generate_node_acls": 1,
"login_timeout": 15,
"netif_timeout": 2,
"prod_mode_write_protect": 0,
"t10_pi": 0
},
"enable": true,
"luns": [
{
"index": 0,
"storage_object": "/backstores/fileio/block"
}
],
"node_acls": [],
"parameters": {
"AuthMethod": "CHAP,None",
"DataDigest": "CRC32C,None",
"DataPDUInOrder": "Yes",
"DataSequenceInOrder": "Yes",
"DefaultTime2Retain": "20",
"DefaultTime2Wait": "2",
"ErrorRecoveryLevel": "0",
"FirstBurstLength": "65536",
"HeaderDigest": "CRC32C,None",
"IFMarkInt": "2048~65535",
"IFMarker": "No",
"ImmediateData": "Yes",
"InitialR2T": "Yes",
"MaxBurstLength": "262144",
"MaxConnections": "1",
"MaxOutstandingR2T": "1",
"MaxRecvDataSegmentLength": "8192",
"MaxXmitDataSegmentLength": "262144",
"OFMarkInt": "2048~65535",
"OFMarker": "No",
"TargetAlias": "LIO Target"
},
"portals": [
{
"ip_address": "0.0.0.0",
"iser": false,
"port": 3260
}
],
"tag": 1
}
],
"wwn": "iqn.2003-01.org.linux-iscsi.f21.x8664:sn.4b0aae584f7c"
}
]
}

View File

@ -52,6 +52,9 @@ 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
@ -73,6 +76,25 @@ func startVolumeServer(client *client.Client, config VolumeTestConfig) *api.Pod
}
}
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"))
privileged := new(bool)
*privileged = true
@ -96,9 +118,11 @@ func startVolumeServer(client *client.Client, config VolumeTestConfig) *api.Pod
SecurityContext: &api.SecurityContext{
Privileged: privileged,
},
Ports: serverPodPorts,
Ports: serverPodPorts,
VolumeMounts: mounts,
},
},
Volumes: volumes,
},
}
_, err := podClient.Create(serverPod)
@ -329,4 +353,51 @@ 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")
})
})
})