Dockerfile for Functest
authorjose.lausuch <jose.lausuch@ericsson.com>
Wed, 30 Sep 2015 13:29:04 +0000 (15:29 +0200)
committerjose.lausuch <jose.lausuch@ericsson.com>
Wed, 7 Oct 2015 08:07:22 +0000 (10:07 +0200)
Includes also:
  - script to trigger Functest automatically within the container
  - common requirements file to install python modules
  - added new parameters in the config_functest.yaml
  - other small adjustements
JIRA: FUNCTEST-29

Change-Id: I230631e43e5f7e14938b35903ecec1b17db0f88a
Signed-off-by: jose.lausuch <jose.lausuch@ericsson.com>
docker/Dockerfile [new file with mode: 0644]
docker/requirements.pip [new file with mode: 0644]
docker/start.sh [new file with mode: 0644]
testcases/config_functest.py
testcases/config_functest.yaml
testcases/functest_utils.py

diff --git a/docker/Dockerfile b/docker/Dockerfile
new file mode 100644 (file)
index 0000000..49d9edf
--- /dev/null
@@ -0,0 +1,50 @@
+########################################
+#   Docker container for FUNCTEST
+########################################
+# Purpose: run all the tests against the POD
+#          from a pre-installed docker image
+#
+# Maintained by Jose Lausuch
+# Build:
+#    $ docker build -t opnfv/functest:tag .
+#
+# Execution:
+#    $ docker run -t -i -e "INSTALLER_TYPE=fuel/foreman" \
+#      -e "INSTALLER_IP=10.20.0.2/172.30.10.73" opnfv/functest
+#
+
+
+FROM ubuntu:14.04
+MAINTAINER Jose Lausuch <jose.lausuch@ericsson.com>
+LABEL version="0.1" description="OPNFV Functest Docker container"
+
+ENV repos_dir /home/opnfv/repos
+
+# Packaged dependencies
+RUN apt-get update && apt-get install -y \
+ssh \
+sshpass \
+git \
+gcc \
+wget \
+python-dev \
+python-pip \
+postgresql \
+libxslt-dev \
+libssl-dev \
+libgmp3-dev \
+libxml2-dev \
+libffi-dev \
+crudini \
+--no-install-recommends
+
+
+RUN mkdir -p ${repos_dir}
+
+RUN git config --global http.sslVerify false
+RUN git clone https://gerrit.opnfv.org/gerrit/functest ${repos_dir}/functest
+RUN git clone https://gerrit.opnfv.org/gerrit/releng ${repos_dir}/releng
+RUN git clone https://github.com/openstack/rally.git ${repos_dir}/rally
+
+RUN pip install -r ${repos_dir}/functest/docker/requirements.pip
+RUN chmod 744  ${repos_dir}/functest/docker/start.sh
\ No newline at end of file
diff --git a/docker/requirements.pip b/docker/requirements.pip
new file mode 100644 (file)
index 0000000..22c8199
--- /dev/null
@@ -0,0 +1,9 @@
+pyyaml==3.10
+gitpython==1.0.1
+python-neutronclient==2.6.0
+python-novaclient==2.28.1
+python-glanceclient==1.1.0
+python-keystoneclient==1.6.0
+cloudify==3.2.1
+virtualenv==1.11.4
+pexpect==4.0
\ No newline at end of file
diff --git a/docker/start.sh b/docker/start.sh
new file mode 100644 (file)
index 0000000..bd2308c
--- /dev/null
@@ -0,0 +1,142 @@
+#!/bin/bash
+
+#
+# Author: Jose Lausuch (jose.lausuch@ericsson.com)
+#
+# Installs the Functest framework within the Docker container
+# and run the tests automatically
+#
+
+
+config_file=$(find / -name config_functest.yaml)
+
+REPOS_DIR=$(cat $config_file | grep -w dir_repos | awk 'END {print $NF}')
+FUNCTEST_REPO_DIR=$(cat $config_file | grep -w dir_repo_functest | awk 'END {print $NF}')
+RALLY_REPO_DIR=$(cat $config_file | grep -w dir_repo_rally | awk 'END {print $NF}')
+RELENG_REPO_DIR=$(cat $config_file | grep -w dir_repo_releng | awk 'END {print $NF}')
+
+FUNCTEST_DIR=$(cat $config_file | grep -w dir_functest | awk 'END {print $NF}')
+FUNCTEST_RESULTS_DIR=$(cat $config_file | grep -w dir_results | awk 'END {print $NF}')
+FUNCTEST_CONF_DIR=$(cat $config_file | grep -w dir_functest_conf | awk 'END {print $NF}')
+FUNCTEST_DATA_DIR=$(cat $config_file | grep -w dir_functest_data | awk 'END {print $NF}')
+RALLY_VENV=$(cat $config_file | grep -w dir_rally_inst | awk 'END {print $NF}')
+RALLY_COMMIT=$(cat $config_file | grep -w rally_stable_commit | awk 'END {print $NF}')
+
+
+echo "REPOS_DIR=${REPOS_DIR}"
+echo "FUNCTEST_REPO_DIR=${FUNCTEST_REPO_DIR}"
+echo "RALLY_REPO_DIR=${RALLY_REPO_DIR}"
+echo "RELENG_REPO_DIR=${RELENG_REPO_DIR}"
+echo "FUNCTEST_DIR=${FUNCTEST_DIR}"
+echo "FUNCTEST_RESULTS_DIR=${FUNCTEST_RESULTS_DIR}"
+echo "FUNCTEST_CONF_DIR=${FUNCTEST_CONF_DIR}"
+echo "FUNCTEST_DATA_DIR=${FUNCTEST_DATA_DIR}"
+echo "RALLY_VENV=${RALLY_VENV}"
+echo "RALLY_COMMIT=${RALLY_COMMIT}"
+
+
+info ()  {
+    logger -s -t "start.info" "$*"
+}
+
+
+error () {
+    logger -s -t "start.error" "$*"
+    exit 1
+}
+
+# Check if environment variables are set
+if [ -z ${INSTALLER_TYPE} ]; then
+    error "Environment variable 'INSTALLER_TYPE' is not defined."
+elif [ "${INSTALLER_TYPE}" != "fuel" ] && [ "${INSTALLER_TYPE}" != "foreman" ]; then
+    error "Invalid environment variable INSTALLER_TYPE=${INSTALLER_TYPE}"
+fi
+
+if [ -z ${INSTALLER_IP} ]; then
+    error "Environment variable 'INSTALLER_IP' is not defined."
+fi
+
+
+# Update repos
+cd ${FUNCTEST_REPO_DIR}
+git pull
+cd ${RELENG_REPO_DIR}
+git pull
+cd ${RALLY_REPO_DIR}
+git reset --hard ${RALLY_COMMIT}
+
+
+# Create directories
+mkdir -p ${FUNCTEST_CONF_DIR}
+mkdir -p ${FUNCTEST_DATA_DIR}
+mkdir -p ${FUNCTEST_RESULTS_DIR}/ODL
+
+# Detect type of installer
+# NOTE: this is tricky, since the IPs will have to be the same ALWAYS
+
+
+# Create Openstack credentials file
+${REPOS_DIR}/releng/utils/fetch_os_creds.sh -d ${FUNCTEST_CONF_DIR}/openstack.creds \
+    -i ${INSTALLER_TYPE} -a ${INSTALLER_IP}
+retval=$?
+if [ $retval != 0 ]; then
+    echo "Cannot retrieve credentials file from installation. Check logs."
+    exit $retval
+fi
+
+
+# Source credentials
+source ${FUNCTEST_CONF_DIR}/openstack.creds
+
+
+# Prepare Functest Environment
+echo "Functest: prepare Functest environment"
+python ${FUNCTEST_REPO_DIR}/testcases/config_functest.py --debug ${FUNCTEST_REPO_DIR}/ start
+retval=$?
+if [ $retval != 0 ]; then
+    echo "Error when configuring Functest environment"
+    exit $retval
+fi
+
+# vPing
+echo "Functest: run vPing"
+python ${FUNCTEST_REPO_DIR}/testcases/vPing/CI/libraries/vPing.py --debug ${FUNCTEST_REPO_DIR}/ -r
+
+# ODL
+echo "Functest: run ODL suite"
+
+if [ $INSTALLER_TYPE == "fuel" ]; then
+    odl_ip=$(keystone catalog --service network | grep publicURL | cut -f3 -d"/" | cut -f1 -d":")
+    neutron_ip=$(keystone catalog --service identity | grep publicURL | cut -f3 -d"/" | cut -f1 -d":")
+    usr_name=$(env | grep OS | grep OS_USERNAME | cut -f2 -d'=')
+    pass=$(env | grep OS | grep OS_PASSWORD | cut -f2 -d'=')
+    odl_port=8181
+    ODL_PORT=$odl_port ODL_IP=$odl_ip NEUTRON_IP=$neutron_ip USR_NAME=$usr_name PASS=$pass \
+    ${FUNCTEST_REPO_DIR}/testcases/Controllers/ODL/CI/start_tests.sh
+elif [ $INSTALLER_TYPE == "foreman" ]; then
+    #odl_port=8081
+    ${FUNCTEST_REPO_DIR}/testcases/Controllers/ODL/CI/start_tests.sh
+else
+    echo "INSTALLER_TYPE not valid."
+    exit 1
+fi
+
+# rally
+echo "Functest: run Functest Rally Bench suites"
+python ${FUNCTEST_REPO_DIR}/testcases/VIM/OpenStack/CI/libraries/run_rally.py --debug ${FUNCTEST_REPO_DIR}/ all
+
+# tempest
+echo "Functest: run Tempest suite"
+rally verify start smoke
+rally verify list
+
+# collect results
+echo "Functest: copy results and clean Functest environment"
+
+# save ODL results
+cp -Rf ${FUNCTEST_REPO_DIR}/testcases/Controllers/ODL/CI/logs ${FUNCTEST_RESULTS_DIR}/ODL
+
+# save tempest.conf for further troubleshooting
+cp $RALLY_VENV/tempest/for-deployment-*/tempest.conf ${FUNCTEST_CONF_DIR}
+
+
index e209a3b..8bc632c 100755 (executable)
@@ -51,35 +51,31 @@ f.close()
 
 """ global variables """
 # Directories
-HOME = os.environ['HOME']+"/"
 REPO_PATH = args.repo_path
 RALLY_DIR = REPO_PATH + functest_yaml.get("general").get("directories").get("dir_rally")
-RALLY_REPO_DIR = HOME + functest_yaml.get("general").get("directories").get("dir_rally_repo")
-RALLY_INSTALLATION_DIR = HOME + functest_yaml.get("general").get("directories").get("dir_rally_inst")
-RALLY_RESULT_DIR = HOME + functest_yaml.get("general").get("directories").get("dir_rally_res")
+RALLY_REPO_DIR = functest_yaml.get("general").get("directories").get("dir_repo_rally")
+RALLY_INSTALLATION_DIR = functest_yaml.get("general").get("directories").get("dir_rally_inst")
+RALLY_RESULT_DIR = functest_yaml.get("general").get("directories").get("dir_rally_res")
 VPING_DIR = REPO_PATH + functest_yaml.get("general").get("directories").get("dir_vping")
 ODL_DIR = REPO_PATH + functest_yaml.get("general").get("directories").get("dir_odl")
+IMAGE_DIR = functest_yaml.get("general").get("directories").get("dir_functest_data")
 
 # Tempest/Rally configuration details
 DEPLOYMENT_MAME = "opnfv-rally"
+RALLY_COMMIT = functest_yaml.get("general").get("openstack").get("rally_stable_commit")
 
 #GLANCE image parameters
 IMAGE_URL = functest_yaml.get("general").get("openstack").get("image_url")
 IMAGE_DISK_FORMAT = functest_yaml.get("general").get("openstack").get("image_disk_format")
 IMAGE_NAME = functest_yaml.get("general").get("openstack").get("image_name")
 IMAGE_FILE_NAME = IMAGE_URL.rsplit('/')[-1]
-IMAGE_DIR = HOME + functest_yaml.get("general").get("openstack").get("image_download_path")
-IMAGE_PATH = IMAGE_DIR + IMAGE_FILE_NAME
+IMAGE_PATH = IMAGE_DIR + "/" + IMAGE_FILE_NAME
 
 
 def action_start():
     """
     Start the functest environment installation
     """
-    if not check_permissions():
-        logger.error("Bad Python cache directory ownership.")
-        exit(-1)
-
     if not functest_utils.check_internet_connectivity():
         logger.error("There is no Internet connectivity. Please check the network configuration.")
         exit(-1)
@@ -93,11 +89,6 @@ def action_start():
         logger.debug("Cleaning possible functest environment leftovers.")
         action_clean()
 
-        logger.info("Installing needed libraries on the host")
-        cmd = "sudo yum -y install gcc libffi-devel python-devel openssl-devel gmp-devel libxml2-devel libxslt-devel postgresql-devel git wget crudini"
-        if not functest_utils.execute_command(cmd, logger):
-            logger.error("There has been a problem while installing software packages.")
-            exit(-1)
 
         logger.info("Installing ODL environment...")
         if not install_odl():
@@ -142,11 +133,11 @@ def action_check():
     Check if the functest environment is properly installed
     """
     errors_all = False
-
+    errors = False
     logger.info("Checking current functest configuration...")
 
     logger.debug("Checking script directories...")
-    errors = False
+
     dirs = [RALLY_DIR, RALLY_INSTALLATION_DIR, VPING_DIR, ODL_DIR]
     for dir in dirs:
         if not os.path.exists(dir):
@@ -197,11 +188,7 @@ def action_check():
         logger.debug("...FAIL")
 
     #TODO: check OLD environment setup
-    if errors_all:
-        return False
-    else:
-        return True
-
+    return not errors_all
 
 
 
@@ -214,11 +201,6 @@ def action_clean():
         logger.debug("Removing Rally installation directory %s" % RALLY_INSTALLATION_DIR)
         shutil.rmtree(RALLY_INSTALLATION_DIR,ignore_errors=True)
 
-    if os.path.exists(RALLY_REPO_DIR):
-        logger.debug("Removing Rally repository %s" % RALLY_REPO_DIR)
-        cmd = "sudo rm -rf " + RALLY_REPO_DIR #need to be sudo, not possible with rmtree
-        functest_utils.execute_command(cmd,logger)
-
     if os.path.exists(IMAGE_PATH):
         logger.debug("Deleting image")
         os.remove(IMAGE_PATH)
@@ -240,30 +222,12 @@ def action_clean():
 
 
 
-def check_permissions():
-    current_user = getpass.getuser()
-    cache_dir = HOME+".cache/pip"
-    logger.info("Checking permissions of '%s'..." %cache_dir)
-    logger.debug("Current user is '%s'" %current_user)
-    cache_user = getpwuid(stat(cache_dir).st_uid).pw_name
-    logger.debug("Cache directory owner is '%s'" %cache_user)
-    if cache_user != current_user:
-        logger.info("The owner of '%s' is '%s'. Please run 'sudo chown -R %s %s'." %(cache_dir, cache_user, current_user, cache_dir))
-        return False
-
-    return True
-
-
 def install_rally():
     if check_rally():
         logger.info("Rally is already installed.")
     else:
-        logger.debug("Cloning repository...")
-        url = "https://git.openstack.org/openstack/rally"
-        Repo.clone_from(url, RALLY_REPO_DIR)
-
         logger.debug("Executing %s./install_rally.sh..." %RALLY_REPO_DIR)
-        install_script = RALLY_REPO_DIR + "install_rally.sh --yes"
+        install_script = RALLY_REPO_DIR + "/install_rally.sh --yes"
         cmd = 'sudo ' + install_script
         functest_utils.execute_command(cmd,logger)
 
@@ -311,7 +275,7 @@ def configure_tempest():
         return False
 
     logger.debug("Finding tempest.conf file...")
-    tempest_conf_file = RALLY_INSTALLATION_DIR+"tempest/for-deployment-" \
+    tempest_conf_file = RALLY_INSTALLATION_DIR+"/tempest/for-deployment-" \
                         +deployment_uuid+"/tempest.conf"
 
     logger.debug("  Updating fixed_network_name...")
@@ -359,7 +323,8 @@ def create_glance_image(path,name,disk_format):
     """
     Create a glance image given the absolute path of the image, its name and the disk format
     """
-    cmd = "glance image-create --name "+name+" --is-public true --disk-format "+disk_format+" --container-format bare --file "+path
+    cmd = ("glance image-create --name "+name+"  --visibility public "
+    "--disk-format "+disk_format+" --container-format bare --file "+path)
     functest_utils.execute_command(cmd,logger)
     return True
 
index e8ee6d9..e5a6a93 100644 (file)
@@ -6,17 +6,26 @@ general:
         dir_rally:      testcases/VIM/OpenStack/CI/libraries/
         dir_rally_scn:  testcases/VIM/OpenStack/CI/suites/
         dir_vIMS:       testcases/vIMS/CI/
-        # Relative to $HOME:
-        dir_vIMS_data: functest/vIMS_data/ # $HOME/functest/vIMS_data/
-        dir_rally_res:  functest/results/ # $HOME/functest/results
-        dir_rally_repo: functest/Rally_repo/ # $HOME/Rally_repo/
-        dir_rally_inst: .rally/  # $HOME/.rally/ usually
+
+        # Absolute path
+        dir_repos:          /home/opnfv/repos
+        dir_repo_functest:  /home/opnfv/repos/functest
+        dir_repo_rally:     /home/opnfv/repos/rally
+        dir_repo_releng:    /home/opnfv/repos/releng
+        dir_functest:       /home/opnfv/functest
+        dir_results:        /home/opnfv/functest/results
+        dir_functest_conf:  /home/opnfv/functest/conf
+        dir_rally_res:      /home/opnfv/functest/results/rally
+        dir_functest_data:  /home/opnfv/functest/data
+        dir_vIMS_data:      /home/opnfv/functest/data/vIMS
+        dir_rally_inst:     /root/.rally
 
     openstack:
         image_name: functest-img
         image_url:  http://download.cirros-cloud.net/0.3.4/cirros-0.3.4-x86_64-disk.img
         image_disk_format:  qcow2
-        image_download_path:    functest/ # $HOME/functest/
+        rally_stable_commit:    9a17d8490e7fb4afee2f5629e6db41eabe4bc4d4
+
         #Public network. Optional
         neutron_public_net_name: net04_ext
         neutron_public_subnet_name: net04_ext__subnet
@@ -88,4 +97,4 @@ vIMS:
             external_network_name: ''
             public_domain: clearwater.opnfv
 results:
-    test_db_url: http://213.77.62.197
\ No newline at end of file
+    test_db_url: http://213.77.62.197
index 6d60fbc..c2e4bc6 100644 (file)
@@ -344,7 +344,7 @@ def download_url(url, dest_path):
     Download a file to a destination path given a URL
     """
     name = url.rsplit('/')[-1]
-    dest = dest_path + name
+    dest = dest_path + "/" + name
     try:
         response = urllib2.urlopen(url)
     except (urllib2.HTTPError, urllib2.URLError):