From b702515df1abb9d4d300a002936babb33c1a7225 Mon Sep 17 00:00:00 2001 From: Vitalii Yerys Date: Wed, 27 Jul 2016 19:07:59 +0300 Subject: [PATCH] Created base testing folder structure. Added fuel-qa folder as a submodule. Change-Id: I64932a41c3c65e8ec159b4918cb1cadd3acb7274 --- .gitmodules | 4 + plugin_test/__init__.py | 13 + plugin_test/fuel-qa | 1 + plugin_test/helpers/__init__.py | 13 + plugin_test/helpers/gcs_base.py | 50 +++ plugin_test/helpers/gcs_settings.py | 35 ++ plugin_test/run_tests.py | 73 ++++ plugin_test/tests/__init__.py | 13 + plugin_test/tests/test_gcs_smoke_bvt.py | 150 +++++++ plugin_test/utils/jenkins/system_tests.sh | 487 ++++++++++++++++++++++ 10 files changed, 839 insertions(+) create mode 100644 .gitmodules create mode 100644 plugin_test/__init__.py create mode 160000 plugin_test/fuel-qa create mode 100644 plugin_test/helpers/__init__.py create mode 100644 plugin_test/helpers/gcs_base.py create mode 100644 plugin_test/helpers/gcs_settings.py create mode 100644 plugin_test/run_tests.py create mode 100644 plugin_test/tests/__init__.py create mode 100644 plugin_test/tests/test_gcs_smoke_bvt.py create mode 100644 plugin_test/utils/jenkins/system_tests.sh diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..21587e0 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "plugin_test/fuel-qa"] + path = plugin_test/fuel-qa + url = https://github.com/openstack/fuel-qa.git + branch = stable/mitaka diff --git a/plugin_test/__init__.py b/plugin_test/__init__.py new file mode 100644 index 0000000..3a1366d --- /dev/null +++ b/plugin_test/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2016 Mirantis, Inc. + +# 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. \ No newline at end of file diff --git a/plugin_test/fuel-qa b/plugin_test/fuel-qa new file mode 160000 index 0000000..c8642a7 --- /dev/null +++ b/plugin_test/fuel-qa @@ -0,0 +1 @@ +Subproject commit c8642a7c1d49c9c69eb934171ca3d63c0825d430 diff --git a/plugin_test/helpers/__init__.py b/plugin_test/helpers/__init__.py new file mode 100644 index 0000000..be8cd8f --- /dev/null +++ b/plugin_test/helpers/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2016 Mirantis, Inc. + +# 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 +# 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. diff --git a/plugin_test/helpers/gcs_base.py b/plugin_test/helpers/gcs_base.py new file mode 100644 index 0000000..3f9607e --- /dev/null +++ b/plugin_test/helpers/gcs_base.py @@ -0,0 +1,50 @@ +# Copyright 2016 Mirantis, Inc. + +# 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. + +"""Base module which classes and methods will be used in test cases.""" + +import os + +from fuelweb_test.tests.base_test_case import TestBasic +from fuelweb_test import logger +from fuelweb_test.helpers import utils + + +class GcsTestBase(TestBasic): + """GcsTestBase. + + Base class for GCS verification testing, methods in this class will be used + by test cases. + """ + + # TODO(unknown) documentation + + def get_remote(self, node): + """Method designed to get remote credentials.""" + logger.info('Getting a remote to {0}'.format(node)) + if node == 'master': + environment = self.env + remote = environment.d_env.get_admin_remote() + else: + remote = self.fuel_web.get_ssh_for_node(node) + return remote + + def install_plugin(self): + """Method designed to install plugin on cluster.""" + master_remote = self.get_remote('master') + utils.upload_tarball(master_remote.host, + os.environ['GCS_PLUGIN_RPM'], + '/var') + utils.install_plugin_check_code( + master_remote.host, os.path.basename(os.environ['GCS_PLUGIN_RPM'])) diff --git a/plugin_test/helpers/gcs_settings.py b/plugin_test/helpers/gcs_settings.py new file mode 100644 index 0000000..9ec8d53 --- /dev/null +++ b/plugin_test/helpers/gcs_settings.py @@ -0,0 +1,35 @@ +# Copyright 2016 Mirantis, Inc. + +# 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. + +"""Module with GCS plugin settings.""" + +import os + +plugin_name = 'fuel-plugin-cinder-gcs' +plugin_version = '1.0.0' + +default_tenant = 'gcs' +default_user = 'gcs' +default_user_pass = 'gcs123GCS' + +options = { + 'backup_gcs_bucket_location/value': os.environ['GCS_LOCATION'], + 'backup_gcs_bucket/value': os.environ['GCS_BUCKET_NAME'], + 'backup_gcs_project_id/value': os.environ['GCS_PROJECT_ID'], + 'gcs_private_key/value': os.environ['GCS_PRIVATE_KEY'], + 'gcs_private_key_id/value': os.environ['GCS_KEY_ID'], + 'gcs_client_x509_cert_url/value': os.environ['GCS_CERT_URL'], + 'gcs_client_email/value': os.environ['GCS_CLIENT_EMAIL'], + 'gcs_client_id/value': os.environ['GCS_CLIENT_ID'] +} diff --git a/plugin_test/run_tests.py b/plugin_test/run_tests.py new file mode 100644 index 0000000..eec2602 --- /dev/null +++ b/plugin_test/run_tests.py @@ -0,0 +1,73 @@ +# Copyright 2016 Mirantis, Inc. + +# 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 +# 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. + + +import sys + +import os +import re +from nose.plugins import Plugin +from paramiko.transport import _join_lingering_threads + + +class CloseSSHConnectionsPlugin(Plugin): + """Closes all paramiko's ssh connections after each test case. + Plugin fixes proboscis disability to run cleanup of any kind. + 'afterTest' calls _join_lingering_threads function from paramiko, + which stops all threads (set the state to inactive and joins for 10s) + """ + + name = 'closesshconnections' + + def options(self, parser, env=os.environ): + """Options.""" + super(CloseSSHConnectionsPlugin, self).options(parser, env=env) + + def configure(self, options, conf): + """Configure env.""" + super(CloseSSHConnectionsPlugin, self).configure(options, conf) + self.enabled = True + + def afterTest(self, *args, **kwargs): + """After_Test. + After_Test calls _join_lingering_threads function from paramiko, + which stops all threads (set the state to inactive and joins for 10s). + """ + _join_lingering_threads() + + +def import_tests(): + """Import test suite of project.""" + from tests import test_gcs_smoke_bvt + + +def run_tests(): + """Run test cases.""" + from proboscis import TestProgram # noqa + import_tests() + + # Run Proboscis and exit. + TestProgram( + addplugins=[CloseSSHConnectionsPlugin()] + ).run_and_exit() + + +if __name__ == '__main__': + sys.path.append(sys.path[0] + "/fuel-qa") + import_tests() + from fuelweb_test.helpers.patching import map_test + if any(re.search(r'--group=patching_master_tests', arg) + for arg in sys.argv): + map_test('master') + elif any(re.search(r'--group=patching.*', arg) for arg in sys.argv): + map_test('environment') + run_tests() \ No newline at end of file diff --git a/plugin_test/tests/__init__.py b/plugin_test/tests/__init__.py new file mode 100644 index 0000000..be8cd8f --- /dev/null +++ b/plugin_test/tests/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2016 Mirantis, Inc. + +# 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 +# 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. diff --git a/plugin_test/tests/test_gcs_smoke_bvt.py b/plugin_test/tests/test_gcs_smoke_bvt.py new file mode 100644 index 0000000..a2b7181 --- /dev/null +++ b/plugin_test/tests/test_gcs_smoke_bvt.py @@ -0,0 +1,150 @@ +# Copyright 2016 Mirantis, Inc. + +# 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. + +"""Module with set of basic test cases.""" + +from proboscis.asserts import assert_equal +from proboscis import test + +from fuelweb_test.helpers.decorators import log_snapshot_after_test +from fuelweb_test.tests.base_test_case import SetupEnvironment +from helpers.gcs_base import GcsTestBase +from helpers import gcs_settings +from fuelweb_test.settings import DEPLOYMENT_MODE +from fuelweb_test import logger + + +@test(groups=["test_gcs_all"]) +class GcsTestClass(GcsTestBase): + """GcsTestBase.""" # TODO(unknown) documentation + + @test(depends_on=[SetupEnvironment.prepare_slaves_3], + groups=["gcs_deploy_smoke"]) + @log_snapshot_after_test + def gcs_deploy_smoke(self): + """Deploy non HA cluster with GCS plugin installed and enabled. + + Scenario: + 1. Create cluster + 2. Add 1 node with controller role + 3. Add 1 node with compute role + 4. Add 1 node with cinder role + 5. Install GCS plugin + 6. Deploy the cluster + """ + self.env.revert_snapshot("ready_with_3_slaves") + + logger.info('Creating GCS HA cluster...') + segment_type = 'vlan' + cluster_id = self.fuel_web.create_cluster( + name=self.__class__.__name__, + mode=DEPLOYMENT_MODE, + settings={ + "net_provider": 'neutron', + "net_segment_type": segment_type, + 'tenant': gcs_settings.default_tenant, + 'user': gcs_settings.default_user, + 'password': gcs_settings.default_user_pass, + 'assign_to_all_nodes': True + } + ) + + self.fuel_web.update_nodes( + cluster_id, + { + 'slave-01': ['controller'], + 'slave-02': ['compute'], + 'slave-03': ['cinder'] + } + ) + + self.install_plugin() + self.fuel_web.update_plugin_settings(cluster_id, + gcs_settings.plugin_name, + gcs_settings.plugin_version, + gcs_settings.options) + + self.fuel_web.deploy_cluster_wait( + cluster_id, + check_services=False + ) + + self.env.make_snapshot("gcs_deploy_smoke") + + @test(depends_on=[SetupEnvironment.prepare_slaves_5], + groups=["gcs_deploy_bvt"]) + @log_snapshot_after_test + def gcs_deploy_bvt(self): + """Deploy HA cluster with GCS plugin installed and enabled. + + Scenario: + 1. Create cluster + 2. Add 3 node with controller role + 3. Add 1 node with compute role + 4. Add 1 node with cinder role + 5. Install GCS plugin + 6. Deploy the cluster + 7. Run network verification + 8. Run OSTF + """ + self.env.revert_snapshot("ready_with_5_slaves") + + logger.info('Creating GCS HA cluster...') + segment_type = 'vlan' + cluster_id = self.fuel_web.create_cluster( + name=self.__class__.__name__, + mode=DEPLOYMENT_MODE, + settings={ + "net_provider": 'neutron', + "net_segment_type": segment_type, + 'tenant': gcs_settings.default_tenant, + 'user': gcs_settings.default_user, + 'password': gcs_settings.default_user_pass, + 'assign_to_all_nodes': True + } + ) + + self.fuel_web.update_nodes( + cluster_id, + { + 'slave-01': ['controller'], + 'slave-02': ['controller'], + 'slave-03': ['controller'], + 'slave-04': ['compute'], + 'slave-05': ['cinder'] + } + ) + + self.install_plugin() + self.fuel_web.update_plugin_settings(cluster_id, + gcs_settings.plugin_name, + gcs_settings.plugin_version, + gcs_settings.options) + + cluster = self.fuel_web.client.get_cluster(cluster_id) + assert_equal(str(cluster['net_provider']), 'neutron') + self.fuel_web.verify_network(cluster_id) + + self.fuel_web.deploy_cluster_wait( + cluster_id, + check_services=False + ) + + self.fuel_web.security.verify_firewall(cluster_id) + + self.fuel_web.run_ostf( + cluster_id=cluster_id, + test_sets=['smoke', 'sanity', 'ha', 'tests_platform', + 'cloudvalidation']) + self.env.make_snapshot("gcs_deploy_bvt") diff --git a/plugin_test/utils/jenkins/system_tests.sh b/plugin_test/utils/jenkins/system_tests.sh new file mode 100644 index 0000000..214d2fc --- /dev/null +++ b/plugin_test/utils/jenkins/system_tests.sh @@ -0,0 +1,487 @@ +#!/bin/sh +PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + +# functions + +INVALIDOPTS_ERR=100 +NOJOBNAME_ERR=101 +NOISOPATH_ERR=102 +NOTASKNAME_ERR=103 +NOWORKSPACE_ERR=104 +DEEPCLEAN_ERR=105 +MAKEISO_ERR=106 +NOISOFOUND_ERR=107 +COPYISO_ERR=108 +SYMLINKISO_ERR=109 +CDWORKSPACE_ERR=110 +ISODOWNLOAD_ERR=111 +INVALIDTASK_ERR=112 + +# Defaults + +export REBOOT_TIMEOUT=${REBOOT_TIMEOUT:-5000} +export ALWAYS_CREATE_DIAGNOSTIC_SNAPSHOT=${ALWAYS_CREATE_DIAGNOSTIC_SNAPSHOT:-true} + +# Export specified settings +if [ -z "$OPENSTACK_RELEASE" ]; then export OPENSTACK_RELEASE=Ubuntu; fi +if [ -z "$ENV_NAME" ]; then export ENV_NAME="gcs"; fi +if [ -z "$ADMIN_NODE_MEMORY" ]; then export ADMIN_NODE_MEMORY=4096; fi +if [ -z "$ADMIN_NODE_CPU" ]; then export ADMIN_NODE_CPU=4; fi +if [ -z "$SLAVE_NODE_MEMORY" ]; then export SLAVE_NODE_MEMORY=4096; fi +if [ -z "$SLAVE_NODE_CPU" ]; then export SLAVE_NODE_CPU=4; fi + +# Init and update submodule +git submodule update --init --recursive --remote + +sudo /sbin/iptables -F +sudo /sbin/iptables -t nat -F +sudo /sbin/iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE + + +ShowHelp() { +cat << EOF +System Tests Script + +It can perform several actions depending on Jenkins JOB_NAME it's ran from +or it can take names from exported environment variables or command line options +if you do need to override them. +-w (dir) - Path to workspace where fuelweb git repository was checked out. + Uses Jenkins' WORKSPACE if not set +-e (name) - Directly specify environment name used in tests + Uses ENV_NAME variable is set. +-j (name) - Name of this job. Determines ISO name, Task name and used by tests. + Uses Jenkins' JOB_NAME if not set +-v - Do not use virtual environment +-V (dir) - Path to python virtual environment +-i (file) - Full path to ISO file to build or use for tests. + Made from iso dir and name if not set. +-t (name) - Name of task this script should perform. Should be one of defined ones. + Taken from Jenkins' job's suffix if not set. +-o (str) - Allows you any extra command line option to run test job if you + want to use some parameters. +-a (str) - Allows you to path NOSE_ATTR to the test job if you want + to use some parameters. +-A (str) - Allows you to path NOSE_EVAL_ATTR if you want to enter attributes + as python expressions. +-m (name) - Use this mirror to build ISO from. + Uses 'srt' if not set. +-U - ISO URL for tests. + Null by default. +-r (yes/no) - Should built ISO file be places with build number tag and + symlinked to the last build or just copied over the last file. +-b (num) - Allows you to override Jenkins' build number if you need to. +-l (dir) - Path to logs directory. Can be set by LOGS_DIR evironment variable. + Uses WORKSPACE/logs if not set. +-d - Dry run mode. Only show what would be done and do nothing. + Useful for debugging. +-k - Keep previously created test environment before tests run +-K - Keep test environment after tests are finished +-h - Show this help page + +Most variables uses guesing from Jenkins' job name but can be overriden +by exported variable before script is run or by one of command line options. +You can override following variables using export VARNAME="value" before running this script +WORKSPACE - path to directory where Fuelweb repository was checked out by Jenkins or manually +JOB_NAME - name of Jenkins job that determines which task should be done and ISO file name. +If task name is "iso" it will make iso file +Other defined names will run Nose tests using previously built ISO file. +ISO file name is taken from job name prefix +Task name is taken from job name suffix +Separator is one dot '.' +For example if JOB_NAME is: +mytest.somestring.iso +ISO name: mytest.iso +Task name: iso +If ran with such JOB_NAME iso file with name mytest.iso will be created +If JOB_NAME is: +mytest.somestring.node +ISO name: mytest.iso +Task name: node +If script was run with this JOB_NAME node tests will be using ISO file mytest.iso. +First you should run mytest.somestring.iso job to create mytest.iso. +Then you can ran mytest.somestring.node job to start tests using mytest.iso and other tests too. +EOF +} +GlobalVariables() { + # where built iso's should be placed + # use hardcoded default if not set before by export + ISO_DIR="${ISO_DIR:=/var/www/fuelweb-iso}" + + # name of iso file + # taken from jenkins job prefix + # if not set before by variable export + if [ -z "${ISO_NAME}" ]; then + ISO_NAME="${JOB_NAME%.*}.iso" + fi + + # full path where iso file should be placed + # make from iso name and path to iso shared directory + # if was not overriden by options or export + if [ -z "${ISO_PATH}" ]; then + ISO_PATH="${ISO_DIR}/${ISO_NAME}" + fi + + # what task should be ran + # it's taken from jenkins job name suffix if not set by options + if [ -z "${TASK_NAME}" ]; then + TASK_NAME="${JOB_NAME##*.}" + fi + + # do we want to keep iso's for each build or just copy over single file + ROTATE_ISO="${ROTATE_ISO:=yes}" + + # choose mirror to build iso from. Default is 'srt' for Saratov's mirror + # you can change mirror by exporting USE_MIRROR variable before running this script + USE_MIRROR="${USE_MIRROR:=srt}" + + # only show what commands would be executed but do nothing + # this feature is usefull if you want to debug this script's behaviour + DRY_RUN="${DRY_RUN:=no}" + + VENV="${VENV:=yes}" +} + +GetoptsVariables() { + while getopts ":w:j:i:t:o:a:A:m:U:r:b:V:l:dkKe:v:h" opt; do + case $opt in + w) + WORKSPACE="${OPTARG}" + ;; + j) + JOB_NAME="${OPTARG}" + ;; + i) + ISO_PATH="${OPTARG}" + ;; + t) + TASK_NAME="${OPTARG}" + ;; + o) + TEST_OPTIONS="${TEST_OPTIONS} ${OPTARG}" + ;; + a) + NOSE_ATTR="${OPTARG}" + ;; + A) + NOSE_EVAL_ATTR="${OPTARG}" + ;; + m) + USE_MIRROR="${OPTARG}" + ;; + U) + ISO_URL="${OPTARG}" + ;; + r) + ROTATE_ISO="${OPTARG}" + ;; + b) + BUILD_NUMBER="${OPTARG}" + ;; + V) + VENV_PATH="${OPTARG}" + ;; + l) + LOGS_DIR="${OPTARG}" + ;; + k) + KEEP_BEFORE="yes" + ;; + K) + KEEP_AFTER="yes" + ;; + e) + ENV_NAME="${OPTARG}" + ;; + d) + DRY_RUN="yes" + ;; + v) + VENV="no" + ;; + h) + ShowHelp + exit 0 + ;; + \?) + echo "Invalid option: -$OPTARG" + ShowHelp + exit $INVALIDOPTS_ERR + ;; + :) + echo "Option -$OPTARG requires an argument." + ShowHelp + exit $INVALIDOPTS_ERR + ;; + esac + done +} + +CheckVariables() { + + if [ -z "${JOB_NAME}" ]; then + echo "Error! JOB_NAME is not set!" + exit $NOJOBNAME_ERR + fi + + if [ -z "${ISO_PATH}" ]; then + echo "Error! ISO_PATH is not set!" + exit $NOISOPATH_ERR + fi + + if [ -z "${TASK_NAME}" ]; then + echo "Error! TASK_NAME is not set!" + exit $NOTASKNAME_ERR + fi + + if [ -z "${WORKSPACE}" ]; then + echo "Error! WORKSPACE is not set!" + exit $NOWORKSPACE_ERR + fi +} + +MakeISO() { + # Create iso file to be used in tests + + # clean previous garbage + if [ "${DRY_RUN}" = "yes" ]; then + echo make deep_clean + else + make deep_clean + fi + ec="${?}" + + if [ "${ec}" -gt "0" ]; then + echo "Error! Deep clean failed!" + exit $DEEPCLEAN_ERR + fi + + # create ISO file + export USE_MIRROR + if [ "${DRY_RUN}" = "yes" ]; then + echo make iso + else + make iso + fi + ec=$? + + if [ "${ec}" -gt "0" ]; then + echo "Error making ISO!" + exit $MAKEISO_ERR + fi + + if [ "${DRY_RUN}" = "yes" ]; then + ISO="${WORKSPACE}/build/iso/fuel.iso" + else + ISO="$(find "${WORKSPACE}/build/iso/"*".iso" | head -n 1)" + # check that ISO file exists + if [ ! -f "${ISO}" ]; then + echo "Error! ISO file not found!" + exit $NOISOFOUND_ERR + fi + fi + + # copy ISO file to storage dir + # if rotation is enabled and build number is aviable + # save iso to tagged file and symlink to the last build + # if rotation is not enabled just copy iso to iso_dir + + if [ "${ROTATE_ISO}" = "yes" -a "${BUILD_NUMBER}" != "" ]; then + # copy iso file to shared dir with revision tagged name + NEW_BUILD_ISO_PATH="${ISO_PATH#.iso}_${BUILD_NUMBER}.iso" + if [ "${DRY_RUN}" = "yes" ]; then + echo cp "${ISO}" "${NEW_BUILD_ISO_PATH}" + else + cp "${ISO}" "${NEW_BUILD_ISO_PATH}" + fi + ec=$? + + if [ "${ec}" -gt "0" ]; then + echo "Error! Copy ${ISO} to ${NEW_BUILD_ISO_PATH} failed!" + exit $COPYISO_ERR + fi + + # create symlink to the last built ISO file + if [ "${DRY_RUN}" = "yes" ]; then + echo ln -sf "${NEW_BUILD_ISO_PATH}" "${ISO_PATH}" + else + ln -sf "${NEW_BUILD_ISO_PATH}" "${ISO_PATH}" + fi + ec=$? + + if [ "${ec}" -gt "0" ]; then + echo "Error! Create symlink from ${NEW_BUILD_ISO_PATH} to ${ISO_PATH} failed!" + exit $SYMLINKISO_ERR + fi + else + # just copy file to shared dir + if [ "${DRY_RUN}" = "yes" ]; then + echo cp "${ISO}" "${ISO_PATH}" + else + cp "${ISO}" "${ISO_PATH}" + fi + ec=$? + + if [ "${ec}" -gt "0" ]; then + echo "Error! Copy ${ISO} to ${ISO_PATH} failed!" + exit $COPYISO_ERR + fi + fi + + if [ "${ec}" -gt "0" ]; then + echo "Error! Copy ISO from ${ISO} to ${ISO_PATH} failed!" + exit $COPYISO_ERR + fi + echo "Finished building ISO: ${ISO_PATH}" + exit 0 +} + +CdWorkSpace() { + # chdir into workspace or fail if could not + if [ "${DRY_RUN}" != "yes" ]; then + cd "${WORKSPACE}" + ec=$? + + if [ "${ec}" -gt "0" ]; then + echo "Error! Cannot cd to WORKSPACE!" + exit $CDWORKSPACE_ERR + fi + else + echo cd "${WORKSPACE}" + fi +} + +RunTest() { + # Run test selected by task name + + # check if iso file exists + if [ ! -f "${ISO_PATH}" ]; then + if [ -z "${ISO_URL}" -a "${DRY_RUN}" != "yes" ]; then + echo "Error! File ${ISO_PATH} not found and no ISO_URL (-U key) for downloading!" + exit $NOISOFOUND_ERR + else + if [ "${DRY_RUN}" = "yes" ]; then + echo wget -c "${ISO_URL}" -O "${ISO_PATH}" + else + echo "No ${ISO_PATH} found. Trying to download file." + wget -c "${ISO_URL}" -O "${ISO_PATH}" + rc=$? + if [ $rc -ne 0 ]; then + echo "Failed to fetch ISO from ${ISO_URL}" + exit $ISODOWNLOAD_ERR + fi + fi + fi + fi + + if [ -z "${VENV_PATH}" ]; then + VENV_PATH="/home/jenkins/venv-nailgun-tests" + fi + + # run python virtualenv + if [ "${VENV}" = "yes" ]; then + if [ "${DRY_RUN}" = "yes" ]; then + echo . $VENV_PATH/bin/activate + else + . $VENV_PATH/bin/activate + fi + fi + + if [ "${ENV_NAME}" = "" ]; then + ENV_NAME="${JOB_NAME}_system_test" + fi + + if [ "${LOGS_DIR}" = "" ]; then + LOGS_DIR="${WORKSPACE}/logs" + fi + + if [ ! -f "$LOGS_DIR" ]; then + mkdir -p "$LOGS_DIR" + fi + + export ENV_NAME + export LOGS_DIR + export ISO_PATH + + if [ "${KEEP_BEFORE}" != "yes" ]; then + # remove previous environment + if [ "${DRY_RUN}" = "yes" ]; then + echo dos.py erase "${ENV_NAME}" + else + if dos.py list | grep "^${ENV_NAME}\$"; then + dos.py erase "${ENV_NAME}" + fi + fi + fi + + # gather additional option for this nose test run + OPTS="" + if [ -n "${NOSE_ATTR}" ]; then + OPTS="${OPTS} -a ${NOSE_ATTR}" + fi + if [ -n "${NOSE_EVAL_ATTR}" ]; then + OPTS="${OPTS} -A ${NOSE_EVAL_ATTR}" + fi + if [ -n "${TEST_OPTIONS}" ]; then + OPTS="${OPTS} ${TEST_OPTIONS}" + fi + + # run python test set to create environments, deploy and test product + if [ "${DRY_RUN}" = "yes" ]; then + echo export PYTHONPATH="${PYTHONPATH:+${PYTHONPATH}:}${WORKSPACE}" + echo python plugin_test/run_tests.py -q --nologcapture --with-xunit ${OPTS} + else + export PYTHONPATH="${PYTHONPATH:+${PYTHONPATH}:}${WORKSPACE}" + echo "${PYTHONPATH}" + python plugin_test/run_tests.py -q --nologcapture --with-xunit ${OPTS} + + fi + ec=$? + + if [ "${KEEP_AFTER}" != "yes" ]; then + # remove environment after tests + if [ "${DRY_RUN}" = "yes" ]; then + echo dos.py destroy "${ENV_NAME}" + else + dos.py destroy "${ENV_NAME}" + fi + fi + + exit "${ec}" +} + +RouteTasks() { + # this selector defines task names that are recognised by this script + # and runs corresponding jobs for them + # running any jobs should exit this script + + case "${TASK_NAME}" in + test) + RunTest + ;; + iso) + MakeISO + ;; + *) + echo "Unknown task: ${TASK_NAME}!" + exit $INVALIDTASK_ERR + ;; + esac + exit 0 +} + +# MAIN + +# first we want to get variable from command line options +GetoptsVariables "${@}" + +# then we define global variables and there defaults when needed +GlobalVariables + +# check do we have all critical variables set +CheckVariables + +# first we chdir into our working directory unless we dry run +CdWorkSpace + +# finally we can choose what to do according to TASK_NAME +RouteTasks