Docker container for Yardstick CI 01/2201/10
authorJo¶rgen Karlsson <jorgen.w.karlsson@ericsson.com>
Fri, 2 Oct 2015 08:18:17 +0000 (10:18 +0200)
committerJo¶rgen Karlsson <jorgen.w.karlsson@ericsson.com>
Wed, 14 Oct 2015 14:19:20 +0000 (16:19 +0200)
The Docker container is intended to be run by the CI pipeline but it
may also be used stand alone.

Building the docker image:
$ cd yardstick/ci/docker
$ make clean && make

Pushing image to docker hub:
$ docker login ... (credentials needed)
$ docker push opnfv/yardstick-ci (need to connect your account to opnfv)

The docker image must be manually built and pushed to the docker Hub.
This will probably be handled by gerrit triggers in the
future (including revision handling and tagging of images).

Example invocation:

            docker run \
               --privileged=true \
                -t \
                -e "INSTALLER_TYPE=fuel" \
                -e "INSTALLER_IP=10.20.0.2" \
                -e YARDSTICK_BRANCH="refs/changes/01/2201/7" \
                -e RELENG_BRANCH="master" \
                opnfv/yardstick-ci \
                run_benchmarks

Basic steps performed by the container:

    1. clone yardstick and releng repos
    2  setup OS credentials (releng scripts)
    3. install yardstick and dependencies
    4. build yardstick cloud image and upload it to glance
    5. upload cirros-0.3.3 cloud image to glance
    6. run yardstick test scenarios

If anything goes wrong in any of the steps above a non-zero exit
status is returned.

Some limitations:

Scenario results (yardstick.out) are currently discarded. A future
patch will take care of dumping the result to a database.

Currently the container only runs the ping sample scenario. Testsuite
execution (and selection) will be added in a future patch.

The container has only been tested against fuel installations.

Change-Id: I0bd29035082d3e283429c7392de8fc11b9fd777f
JIRA: YARDSTICK-136
Signed-off-by: Jo¶rgen Karlsson <jorgen.w.karlsson@ericsson.com>
ci/docker/Makefile [new file with mode: 0644]
ci/docker/yardstick-ci/Dockerfile [new file with mode: 0644]
ci/docker/yardstick-ci/run_benchmarks [new file with mode: 0755]
ci/run_tasks.sh [deleted file]
ci/yardstick-verify [new file with mode: 0755]
tools/ubuntu-server-cloudimg-modify.sh
tools/yardstick-img-modify

diff --git a/ci/docker/Makefile b/ci/docker/Makefile
new file mode 100644 (file)
index 0000000..8118996
--- /dev/null
@@ -0,0 +1,27 @@
+##############################################################################
+# Copyright (c) 2015 Ericsson AB and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+
+SHELL = /bin/bash
+
+IMAGE = opnfv/yardstick-ci
+
+.PHONY: all
+all: .docker
+
+.docker:
+       /usr/bin/docker build --rm=true --no-cache=true -t $(IMAGE):14.04 yardstick-ci
+       /usr/bin/docker tag -f $(IMAGE):14.04 $(IMAGE)
+       touch .docker
+
+.PHONY:        clean
+clean:
+       docker ps | grep $(IMAGE) | awk '{print $$1}' | xargs -r docker stop
+       docker ps -a | grep $(IMAGE) | awk '{print $$1}' | xargs -r docker rm
+       docker images -a | grep $(IMAGE) | awk '{print $$3}' | sort | uniq | xargs -r docker rmi
+       rm -f .docker
diff --git a/ci/docker/yardstick-ci/Dockerfile b/ci/docker/yardstick-ci/Dockerfile
new file mode 100644 (file)
index 0000000..15b0f62
--- /dev/null
@@ -0,0 +1,34 @@
+##############################################################################
+# Copyright (c) 2015 Ericsson AB and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+
+FROM ubuntu:14.04
+
+LABEL image=opnfv/yardstick-ci
+
+ENV YARDSTICK_REPO_DIR /home/yardstick
+
+RUN apt-get update && apt-get install -y \
+    wget \
+    git \
+    sshpass \
+    qemu-utils \
+    kpartx \
+    libffi-dev \
+    libssl-dev \
+    python \
+    python-dev \
+    python-setuptools && \
+    easy_install -U setuptools
+
+RUN apt-get -y autoremove && \
+    apt-get clean
+
+RUN git clone https://gerrit.opnfv.org/gerrit/yardstick ${YARDSTICK_REPO_DIR}
+
+COPY ./run_benchmarks /usr/local/bin/
diff --git a/ci/docker/yardstick-ci/run_benchmarks b/ci/docker/yardstick-ci/run_benchmarks
new file mode 100755 (executable)
index 0000000..391ee63
--- /dev/null
@@ -0,0 +1,60 @@
+#!/bin/bash
+##############################################################################
+# Copyright (c) 2015 Ericsson AB and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+
+set -e
+
+: ${YARDSTICK_REPO:='https://gerrit.opnfv.org/gerrit/yardstick'}
+: ${YARDSTICK_REPO_DIR:='/home/yardstick'}
+: ${YARDSTICK_BRANCH:='master'}
+
+: ${RELENG_REPO:='https://gerrit.opnfv.org/gerrit/releng'}
+: ${RELENG_REPO_DIR:='/home/releng'}
+: ${RELENG_BRANCH:='master'}
+
+: ${INSTALLER_TYPE:='fuel'}
+: ${INSTALLER_IP:='10.20.0.2'}
+
+: ${EXTERNAL_NET_ID:='net04_ext'}
+
+# clone releng
+if [ ! -d $RELENG_REPO_DIR ]; then
+    git clone $RELENG_REPO $RELENG_REPO_DIR
+fi
+cd $RELENG_REPO_DIR
+git fetch --tags --progress $RELENG_REPO $RELENG_BRANCH
+git checkout FETCH_HEAD
+
+# clone yardstick
+if [ ! -d $YARDSTICK_REPO_DIR ]; then
+    git clone YARDSTICK_REPO $YARDSTICK_REPO_DIR
+fi
+cd $YARDSTICK_REPO_DIR
+git fetch --tags --progress $YARDSTICK_REPO $YARDSTICK_BRANCH
+git checkout FETCH_HEAD
+
+# Create openstack credentials
+$RELENG_REPO_DIR/utils/fetch_os_creds.sh \
+    -d /tmp/openrc \
+    -i ${INSTALLER_TYPE} -a ${INSTALLER_IP}
+
+source /tmp/openrc
+
+# FIXME: Temporary OPNFV playground hack
+if [ "$INSTALLER_TYPE" == "fuel" ]; then
+    ssh_opts="-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"
+    if sshpass -p r00tme ssh 2>/dev/null $ssh_opts root@${INSTALLER_IP} \
+        fuel environment --env 1 | grep opnfv-virt; then
+        export OS_ENDPOINT_TYPE='publicURL'
+    fi
+fi
+
+export EXTERNAL_NET_ID
+
+$YARDSTICK_REPO_DIR/ci/yardstick-verify
diff --git a/ci/run_tasks.sh b/ci/run_tasks.sh
deleted file mode 100644 (file)
index 27ccb3a..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/bin/bash
-
-##############################################################################
-# Copyright (c) 2015 Ericsson AB and others.
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-##############################################################################
-
-# Run yardstick tasks back-to-back
-# This script is called from yardstick-{pod} job and decides which tasks
-# are executed as part of that job.
-
-
-# verify that virtual environment is activated
-# assumes the virtual environment has been created as described in README.rst
-if [[ ! $(which python | grep venv) ]]; then
-    echo "Unable to activate venv...Exiting"
-    exit 1
-fi
-
-EXIT_CODE=0
-
-# Define tasks to be run
-TASK_FILE_NAMES[0]='samples/ping.yaml'
-TASK_FILE_NAMES[1]='samples/iperf3.yaml'
-TASK_FILE_NAMES[2]='samples/pktgen.yaml'
-TASK_FILE_NAMES[3]='samples/fio.yaml'
-
-# Execute tasks
-for TASK_FILE in ${TASK_FILE_NAMES[@]}
-do
-    echo "Executing task from file: $TASK_FILE"
-    yardstick -d task start $TASK_FILE
-
-    if [ $? -ne 0 ]; then
-        EXIT_CODE=1
-    fi
-done
-
-exit $EXIT_CODE
\ No newline at end of file
diff --git a/ci/yardstick-verify b/ci/yardstick-verify
new file mode 100755 (executable)
index 0000000..c940213
--- /dev/null
@@ -0,0 +1,182 @@
+#!/bin/bash
+##############################################################################
+# Copyright (c) 2015 Ericsson AB and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+
+YARDSTICK_IMAGE_ID=
+CIRROS_IMAGE_ID=
+
+QCOW_IMAGE="/tmp/workspace/yardstick/yardstick-trusty-server.img"
+
+cleanup()
+{
+    echo
+    echo "========== Cleanup =========="
+
+    if ! glance image-list; then
+        return
+    fi
+
+    for image in $(glance image-list | grep -e cirros-0.3.3 -e yardstick-trusty-server | awk '{print $2}'); do
+        echo "Deleting image $image..."
+        glance image-delete $image || true
+    done
+}
+
+exitcode=""
+
+error_exit()
+{
+    local rc=$?
+
+    if [ -z "$exitcode" ]; then
+        # In case of recursive traps (!?)
+        exitcode=$rc
+    fi
+
+    cleanup
+
+    echo "Exiting with RC=$exitcode"
+
+    exit $exitcode
+}
+
+set -o errexit
+set -o pipefail
+
+install_yardstick()
+{
+    echo
+    echo "========== Installing yardstick =========="
+
+    if ! sudo python setup.py install; then
+        echo 'Yardstick installation failed!'
+        exit 1
+    fi
+}
+
+build_yardstick_image()
+{
+    echo
+    echo "========== Build yardstick cloud image =========="
+
+    sudo $(which yardstick-img-modify) $(pwd)/tools/ubuntu-server-cloudimg-modify.sh
+    if [ ! -f $QCOW_IMAGE ]; then
+        echo "Failed building QCOW image"
+        exit 1
+    fi
+}
+
+load_cirros_image()
+{
+    echo
+    echo "========== Loading cirros cloud image =========="
+
+    local image_file=
+
+    wget http://download.cirros-cloud.net/0.3.3/cirros-0.3.3-x86_64-disk.img -O /tmp/cirros.img
+
+    output=$(glance image-create \
+        --name  cirros-0.3.3 \
+        --disk-format qcow2 \
+        --container-format bare \
+        --file /tmp/cirros.img)
+    echo "$output"
+
+    CIRROS_IMAGE_ID=$(echo "$output" | grep " id " | awk '{print $(NF-1)}')
+    if [ -z "$CIRROS_IMAGE_ID" ]; then
+        echo 'Failed uploading cirros image to cloud'.
+        exit 1
+    fi
+
+    echo "Cirros image id: $CIRROS_IMAGE_ID"
+}
+
+load_yardstick_image()
+{
+    echo
+    echo "========== Loading yardstick cloud image =========="
+
+    output=$(glance --os-image-api-version 1 image-create \
+        --name yardstick-trusty-server \
+        --is-public true --disk-format qcow2 \
+        --container-format bare \
+        --file $QCOW_IMAGE)
+    echo "$output"
+
+    GLANCE_IMAGE_ID=$(echo "$output" | grep " id " | awk '{print $(NF-1)}')
+
+    if [ -z "$GLANCE_IMAGE_ID" ]; then
+        echo 'Failed uploading image to cloud'.
+        exit 1
+    fi
+
+    sudo rm -f $QCOW_IMAGE
+
+    echo "Glance image id: $GLANCE_IMAGE_ID"
+}
+
+run_test()
+{
+    echo
+    echo "========== Running yardstick test suite =========="
+
+    # Just run sample ping for now.
+    if ! yardstick -d task start samples/ping.yaml; then
+        echo "Yardstick test FAILED"
+        exit 1
+    fi
+}
+
+main()
+{
+    GITROOT=$(cd $(dirname $0) && git rev-parse --show-toplevel)
+
+    cd $GITROOT
+
+    # install yardstick
+    install_yardstick
+
+    # check if some necessary variables is set
+    if [ -z "$OS_AUTH_URL" ]; then
+        echo "OS_AUTH_URL is unset or empty"
+        exit 1
+    fi
+
+    # extract auth ip
+    ip=$(echo $OS_AUTH_URL | grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+')
+
+    # check if the auth port is open
+    echo "Checking if tcp port $ip:5000 is open..."
+    nc -zv -w 10 $ip 5000; rc=$?;
+    if [ $rc -eq 0 ]; then
+        echo "$ip:5000 is open for tcp connections"
+    else
+        echo "$ip:5000 is closed"
+        exit 1
+    fi
+
+    # check if the api is up
+    echo "Checking if OS API is working..."
+    if ! glance image-list > /dev/null; then
+        echo "OS API is down"
+        exit 1
+    fi
+
+    cleanup
+
+    trap "error_exit" EXIT SIGTERM
+
+    build_yardstick_image
+    load_yardstick_image
+    load_cirros_image
+
+    run_test
+}
+
+main
index ac43d28..6e750e0 100755 (executable)
@@ -27,7 +27,7 @@ grep trusty /etc/apt/sources.list && \
     echo "deb http://archive.ubuntu.com/ubuntu/ trusty-backports main restricted universe multiverse" >> /etc/apt/sources.list
 
 # Workaround for building on CentOS (apt-get is not working with http sources)
-sed -i 's/http/ftp/' /etc/apt/sources.list
+sed -i 's/http/ftp/' /etc/apt/sources.list
 
 # Force apt to use ipv4 due to build problems on LF POD.
 echo 'Acquire::ForceIPv4 "true";' > /etc/apt/apt.conf.d/99force-ipv4
index c900272..48462b8 100755 (executable)
@@ -47,6 +47,7 @@ md5sums_path="${release}/current/MD5SUMS"
 md5sums_url=${MD5SUMS_URL:-"https://${host}/${md5sums_path}"}
 
 imgfile="${workspace}/yardstick-${release}-server.img"
+raw_imgfile="${workspace}/yardstick-${release}-server.raw"
 filename=$(basename $image_url)
 
 # download and checksum base image, conditionally if local copy is outdated
@@ -62,26 +63,23 @@ download() {
         wget -nc $image_url
         grep $filename MD5SUMS | md5sum -c
     fi
-    cp $filename $imgfile
+    qemu-img convert $filename $raw_imgfile
     cd -
 }
 
 # mount image
 setup() {
     mkdir -p $mountdir
-    if [ -f /etc/centos-release ]; then
-        # CentOS, mount image using guestmount.
-        # (needs libguestfs-tools installed)
-        export LIBGUESTFS_BACKEND=direct
-        guestmount -a $imgfile -i --rw $mountdir
-    else
-        # mount image using qemu-nbd
-        modprobe nbd max_part=16
-        qemu-nbd -c /dev/nbd0 $imgfile
-        partprobe /dev/nbd0
-
-        mount /dev/nbd0p1 $mountdir
-    fi
+
+    for i in $(seq 0 9); do
+        [ -a /dev/loop$i ] || mknod -m 660 /dev/loop$i b 7 $i
+    done
+
+    loopdevice=$(kpartx -l $raw_imgfile | head -1 | cut -f1 -d ' ')
+
+    kpartx -a $raw_imgfile
+    mount /dev/mapper/$loopdevice $mountdir
+
     cp $cmd $mountdir/$(basename $cmd)
 }
 
@@ -90,20 +88,26 @@ modify() {
     # resolv.conf does not exist in base image, pass nameserver value from host
     nameserver_ip=$(grep -m 1 '^nameserver' \
         /etc/resolv.conf | awk '{ print $2 '})
+
     chroot $mountdir /$(basename $cmd) $nameserver_ip
+
+    umount $mountdir
+    qemu-img convert -c -o compat=0.10 -O qcow2 $raw_imgfile $imgfile
 }
 
 # cleanup (umount) the image
 cleanup() {
     # designed to be idempotent
     mount | grep $mountdir && umount $mountdir
-    test -b /dev/nbd0 && partprobe /dev/nbd0
-    pgrep qemu-nbd && qemu-nbd -d /dev/nbd0
+    if [ -f $raw_imgfile ]; then
+        kpartx -d $raw_imgfile || true
+    fi
+    rm -f $raw_imgfile
     rm -rf $mountdir
-    killall qemu-nbd 2> /dev/null || true
-    lsmod | grep nbd && rmmod nbd || true
 }
 
+set -x
+
 main() {
     cleanup
     download