Add trigger fro DPDK tests
[csit.git] / resources / libraries / bash / function / common.sh
index bc8ffe9..f2931b3 100644 (file)
@@ -21,6 +21,71 @@ set -exuo pipefail
 #   the code might become more readable (but longer).
 
 
+function activate_docker_topology () {
+    # Create virtual vpp-device topology. Output of the function is topology
+    # file describing created environment saved to a file.
+    #
+    # Variables read:
+    # - BASH_FUNCTION_DIR - Path to existing directory this file is located in.
+    # - TOPOLOGIES - Available topologies.
+    # - NODENESS - Node multiplicity of desired testbed.
+    # - FLAVOR - Node flavor string, usually describing the processor.
+    # Variables set:
+    # - WORKING_TOPOLOGY - Path to topology file.
+
+    set -exuo pipefail
+
+    source "${BASH_FUNCTION_DIR}/device.sh" || {
+        die "Source failed!"
+    }
+
+    device_image="$(< ${CSIT_DIR}/VPP_DEVICE_IMAGE)"
+    case_text="${NODENESS}_${FLAVOR}"
+    case "${case_text}" in
+        "1n_skx")
+            # We execute reservation over csit-shim-dcr (ssh) which runs sourced
+            # script's functions. Env variables are read from ssh output
+            # back to localhost for further processing.
+            hostname=$(grep search /etc/resolv.conf | cut -d' ' -f3)
+            ssh="ssh root@${hostname} -p 6022"
+            run="activate_wrapper ${NODENESS} ${FLAVOR} ${device_image}"
+            env_vars=$(${ssh} "$(declare -f); ${run}") || {
+                die "Topology reservation via shim-dcr failed!"
+            }
+            set -a
+            source <(echo "$env_vars" | grep -v /usr/bin/docker) || {
+                die "Source failed!"
+            }
+            set +a
+            ;;
+        "1n_vbox")
+            # We execute reservation on localhost. Sourced script automatially
+            # sets environment variables for further processing.
+            activate_wrapper "${NODENESS}" "${FLAVOR}" "${device_image}" || die
+            ;;
+        *)
+            die "Unknown specification: ${case_text}!"
+    esac
+
+    trap 'deactivate_docker_topology' EXIT || {
+         die "Trap attempt failed, please cleanup manually. Aborting!"
+    }
+
+    # Replace all variables in template with those in environment.
+    source <(echo 'cat <<EOF >topo.yml'; cat ${TOPOLOGIES[0]}; echo EOF;) || {
+        die "Topology file create failed!"
+    }
+
+    WORKING_TOPOLOGY="/tmp/topology.yaml"
+    mv topo.yml "${WORKING_TOPOLOGY}" || {
+        die "Topology move failed!"
+    }
+    cat ${WORKING_TOPOLOGY} | grep -v password || {
+        die "Topology read failed!"
+    }
+}
+
+
 function activate_virtualenv () {
 
     set -exuo pipefail
@@ -47,7 +112,7 @@ function activate_virtualenv () {
     pip install --upgrade virtualenv || {
         die "Virtualenv package install failed."
     }
-    virtualenv --system-site-packages "${ENV_DIR}" || {
+    virtualenv "${ENV_DIR}" || {
         die "Virtualenv creation failed."
     }
     set +u
@@ -82,6 +147,20 @@ function check_download_dir () {
 }
 
 
+function cleanup_topo () {
+
+    set -exuo pipefail
+
+    # Variables read:
+    # - WORKING_TOPOLOGY - Path to topology yaml file of the reserved testbed.
+    # - PYTHON_SCRIPTS_DIR - Path to directory holding the reservation script.
+
+    python "${PYTHON_SCRIPTS_DIR}/topo_cleanup.py" -t "${WORKING_TOPOLOGY}"
+    # Not using "|| die" as some callers might want to ignore errors,
+    # e.g. in teardowns, such as unreserve.
+}
+
+
 function common_dirs () {
 
     set -exuo pipefail
@@ -140,13 +219,28 @@ function compose_pybot_arguments () {
     # - DUT - CSIT test/ subdirectory, set while processing tags.
     # - TAGS - Array variable holding selected tag boolean expressions.
     # - TOPOLOGIES_TAGS - Tag boolean expression filtering tests for topology.
+    # - TEST_CODE - The test selection string from environment or argument.
     # Variables set:
     # - PYBOT_ARGS - String holding part of all arguments for pybot.
     # - EXPANDED_TAGS - Array of strings pybot arguments compiled from tags.
 
     # No explicit check needed with "set -u".
-    PYBOT_ARGS=("--loglevel" "TRACE" "--variable" "TOPOLOGY_PATH:${WORKING_TOPOLOGY}")
-    PYBOT_ARGS+=("--suite" "tests.${DUT}.perf")
+    PYBOT_ARGS=("--loglevel" "TRACE")
+    PYBOT_ARGS+=("--variable" "TOPOLOGY_PATH:${WORKING_TOPOLOGY}")
+
+    case "${TEST_CODE}" in
+        *"device"*)
+            PYBOT_ARGS+=("--suite" "tests.${DUT}.device")
+            ;;
+        *"func"*)
+            PYBOT_ARGS+=("--suite" "tests.${DUT}.func")
+            ;;
+        *"perf"*)
+            PYBOT_ARGS+=("--suite" "tests.${DUT}.perf")
+            ;;
+        *)
+            die "Unknown specification: ${TEST_CODE}"
+    esac
 
     EXPANDED_TAGS=()
     for tag in "${TAGS[@]}"; do
@@ -178,11 +272,43 @@ function copy_archives () {
     # automatically archived to logs.fd.io.
     if [[ -n "${WORKSPACE-}" ]]; then
         mkdir -p "${WORKSPACE}/archives/" || die "Archives dir create failed."
-        cp -r "${ARCHIVE_DIR}"/* "${WORKSPACE}/archives" || die "Copy failed."
+        cp -rf "${ARCHIVE_DIR}"/* "${WORKSPACE}/archives" || die "Copy failed."
     fi
 }
 
 
+function deactivate_docker_topology () {
+    # Deactivate virtual vpp-device topology by removing containers.
+    #
+    # Variables read:
+    # - NODENESS - Node multiplicity of desired testbed.
+    # - FLAVOR - Node flavor string, usually describing the processor.
+
+    set -exuo pipefail
+
+    case_text="${NODENESS}_${FLAVOR}"
+    case "${case_text}" in
+        "1n_skx")
+            hostname=$(grep search /etc/resolv.conf | cut -d' ' -f3)
+            ssh="ssh root@${hostname} -p 6022"
+            env_vars="$(env | grep CSIT_ | tr '\n' ' ' )"
+            ${ssh} "$(declare -f); deactivate_wrapper ${env_vars}" || {
+                die "Topology cleanup via shim-dcr failed!"
+            }
+            ;;
+        "1n_vbox")
+            enter_mutex || die
+            clean_environment || {
+                die "Topology cleanup locally failed!"
+            }
+            exit_mutex || die
+            ;;
+        *)
+            die "Unknown specification: ${case_text}!"
+    esac
+}
+
+
 function die () {
     # Print the message to standard error end exit with error code specified
     # by the second argument.
@@ -237,6 +363,14 @@ function get_test_code () {
     fi
 
     case "${TEST_CODE}" in
+        *"1n-vbox"*)
+            NODENESS="1n"
+            FLAVOR="vbox"
+            ;;
+        *"1n-skx"*)
+            NODENESS="1n"
+            FLAVOR="skx"
+            ;;
         *"2n-skx"*)
             NODENESS="2n"
             FLAVOR="skx"
@@ -261,6 +395,7 @@ function get_test_tag_string () {
     # Variables read:
     # - GERRIT_EVENT_TYPE - Event type set by gerrit, can be unset.
     # - GERRIT_EVENT_COMMENT_TEXT - Comment text, read for "comment-added" type.
+    # - TEST_CODE - The test selection string from environment or argument.
     # Variables set:
     # - TEST_TAG_STRING - The string following "perftest" in gerrit comment,
     #   or empty.
@@ -269,12 +404,27 @@ function get_test_tag_string () {
 
     trigger=""
     if [[ "${GERRIT_EVENT_TYPE-}" == "comment-added" ]]; then
-        # On parsing error, ${trigger} stays empty.
-        trigger="$(echo "${GERRIT_EVENT_COMMENT_TEXT}" \
-            | grep -oE '(perftest$|perftest[[:space:]].+$)')" || true
+        case "${TEST_CODE}" in
+            *"device"*)
+                # On parsing error, ${trigger} stays empty.
+                trigger="$(echo "${GERRIT_EVENT_COMMENT_TEXT}" \
+                    | grep -oE '(devicetest$|devicetest[[:space:]].+$)')" \
+                    || true
+                # Set test tags as string.
+                TEST_TAG_STRING="${trigger#$"devicetest"}"
+                ;;
+            *"perf"*)
+                # On parsing error, ${trigger} stays empty.
+                trigger="$(echo "${GERRIT_EVENT_COMMENT_TEXT}" \
+                    | grep -oE '(perftest$|perftest[[:space:]].+$)')" \
+                    || true
+                # Set test tags as string.
+                TEST_TAG_STRING="${trigger#$"perftest"}"
+                ;;
+            *)
+                die "Unknown specification: ${TEST_CODE}"
+        esac
     fi
-    # Set test tags as string.
-    TEST_TAG_STRING="${trigger#$"perftest"}"
 }
 
 
@@ -310,7 +460,7 @@ function reserve_testbed () {
                     }
                     die "Trap attempt failed, unreserve succeeded. Aborting."
                 }
-                python "${PYTHON_SCRIPTS_DIR}/topo_cleanup.py" -t "${topo}" || {
+                cleanup_topo || {
                     die "Testbed cleanup failed."
                 }
                 break
@@ -406,21 +556,95 @@ function select_tags () {
                             "ndrpdrAND78bAND1c")
             ;;
         *"mrr-daily"* | *"mrr-weekly"* )
-            test_tag_array=("mrrAND64bAND1c"
-                            "mrrAND64bAND2c"
-                            "mrrAND64bAND4c"
-                            "mrrAND78bAND1c"
-                            "mrrAND78bAND2c"
-                            "mrrAND78bAND4c"
-                            "mrrAND114bAND1c"
-                            "mrrAND114bAND2c"
-                            "mrrAND114bAND4c"
-                            "mrrANDimixAND1cANDvhost"
-                            "mrrANDimixAND2cANDvhost"
-                            "mrrANDimixAND4cANDvhost"
-                            "mrrANDimixAND1cANDmemif"
-                            "mrrANDimixAND2cANDmemif"
-                            "mrrANDimixAND4cANDmemif")
+            test_tag_array=(# vic
+                            "mrrANDnic_cisco-vic-1227AND64b"
+                            "mrrANDnic_cisco-vic-1385AND64b"
+                            # memif
+                            "mrrANDmemifANDethAND64b"
+                            "mrrANDmemifANDethANDimix"
+                            # crypto
+                            "mrrANDipsecAND64b"
+                            # ip4 base
+                            "mrrANDip4baseAND64b"
+                            # ip4 scale FIB 2M
+                            "mrrANDip4fwdANDfib_2mAND64b"
+                            # ip4 scale FIB 200k
+                            "mrrANDip4fwdANDfib_200kANDnic_intel-*710AND64b"
+                            # ip4 scale FIB 20k
+                            "mrrANDip4fwdANDfib_20kANDnic_intel-*710AND64b"
+                            # ip4 scale ACL
+                            "mrrANDip4fwdANDacl1AND10k_flowsAND64b"
+                            "mrrANDip4fwdANDacl50AND10k_flowsAND64b"
+                            # ip4 scale NAT44
+                            "mrrANDip4fwdANDnat44ANDbaseAND64b"
+                            "mrrANDip4fwdANDnat44ANDsrc_user_4000AND64b"
+                            # ip4 features
+                            "mrrANDip4fwdANDfeatureANDnic_intel-*710AND64b"
+                            # TODO: Remove when tags in
+                            # tests/vpp/perf/ip4/*-ipolicemarkbase-*.robot
+                            # are fixed
+                            "mrrANDip4fwdANDpolice_markANDnic_intel-*710AND64b"
+                            # ip4 tunnels
+                            "mrrANDip4fwdANDencapANDip6unrlayANDip4ovrlayANDnic_intel-x520-da2AND64b"
+                            "mrrANDip4fwdANDencapANDnic_intel-*710AND64b"
+                            "mrrANDl2ovrlayANDencapANDnic_intel-*710AND64b"
+                            # ip6 base
+                            "mrrANDip6baseANDethAND78b"
+                            # ip6 features
+                            "mrrANDip6fwdANDfeatureANDnic_intel-*710AND78b"
+                            # ip6 scale FIB 2M
+                            "mrrANDip6fwdANDfib_2mANDnic_intel-*710AND78b"
+                            # ip6 scale FIB 200k
+                            "mrrANDip6fwdANDfib_200kANDnic_intel-*710AND78b"
+                            # ip6 scale FIB 20k
+                            "mrrANDip6fwdANDfib_20kANDnic_intel-*710AND78b"
+                            # ip6 tunnels
+                            "mrrANDip6fwdANDencapANDnic_intel-x520-da2AND78b"
+                            # l2xc base
+                            "mrrANDl2xcfwdANDbaseAND64b"
+                            # l2xc scale ACL
+                            "mrrANDl2xcANDacl1AND10k_flowsAND64b"
+                            "mrrANDl2xcANDacl50AND10k_flowsAND64b"
+                            # l2xc scale FIB 2M
+                            "mrrANDl2xcANDfib_2mAND64b"
+                            # l2xc scale FIB 200k
+                            "mrrANDl2xcANDfib_200kANDnic_intel-*710AND64b"
+                            # l2xc scale FIB 20k
+                            "mrrANDl2xcANDfib_20kANDnic_intel-*710AND64b"
+                            # l2bd base
+                            "mrrANDl2bdmaclrnANDbaseAND64b"
+                            # l2bd scale ACL
+                            "mrrANDl2bdmaclrnANDacl1AND10k_flowsAND64b"
+                            "mrrANDl2bdmaclrnANDacl50AND10k_flowsAND64b"
+                            # l2bd scale FIB 2M
+                            "mrrANDl2bdmaclrnANDfib_1mAND64b"
+                            # l2bd scale FIB 200k
+                            "mrrANDl2bdmaclrnANDfib_100kANDnic_intel-*710AND64b"
+                            # l2bd scale FIB 20k
+                            "mrrANDl2bdmaclrnANDfib_10kANDnic_intel-*710AND64b"
+                            # l2 patch base
+                            "mrrANDl2patchAND64b"
+                            # srv6
+                            "mrrANDsrv6ANDnic_intel-x520-da2AND78b"
+                            # vts
+                            "mrrANDvtsANDnic_intel-x520-da2AND114b"
+                            # vm vhost l2xc base
+                            "mrrANDvhostANDl2xcfwdANDbaseAND64b"
+                            "mrrANDvhostANDl2xcfwdANDbaseANDimix"
+                            # vm vhost l2bd base
+                            "mrrANDvhostANDl2bdmaclrnANDbaseAND64b"
+                            "mrrANDvhostANDl2bdmaclrnANDbaseANDimix"
+                            # vm vhost ip4 base
+                            "mrrANDvhostANDip4fwdANDbaseAND64b"
+                            "mrrANDvhostANDip4fwdANDbaseANDimix"
+                            # DPDK
+                            "mrrANDdpdkAND64b"
+                            # Exclude
+                            "!mrrANDip6baseANDdot1qAND78b"
+                            "!vhost_256ANDnic_intel-x520-da2"
+                            "!vhostANDnic_intel-xl710"
+                            "!cfs_opt"
+                            "!lbond_dpdk")
             ;;
         * )
             if [[ -z "${TEST_TAG_STRING-}" ]]; then
@@ -479,6 +703,52 @@ function select_tags () {
 }
 
 
+function select_vpp_device_tags () {
+
+    set -exuo pipefail
+
+    # Variables read:
+    # - TEST_CODE - String affecting test selection, usually jenkins job name.
+    # - TEST_TAG_STRING - String selecting tags, from gerrit comment.
+    #   Can be unset.
+    # Variables set:
+    # - TAGS - Array of processed tag boolean expressions.
+
+    case "${TEST_CODE}" in
+        # Select specific performance tests based on jenkins job type variable.
+        * )
+            if [[ -z "${TEST_TAG_STRING-}" ]]; then
+                # If nothing is specified, we will run pre-selected tests by
+                # following tags. Items of array will be concatenated by OR
+                # in Robot Framework.
+                test_tag_array=()
+            else
+                # If trigger contains tags, split them into array.
+                test_tag_array=(${TEST_TAG_STRING//:/ })
+            fi
+            ;;
+    esac
+
+    TAGS=()
+
+    # We will prefix with perftest to prevent running other tests
+    # (e.g. Functional).
+    prefix="devicetestAND"
+    if [[ "${TEST_CODE}" == "vpp-"* ]]; then
+        # Automatic prefixing for VPP jobs to limit testing.
+        prefix="${prefix}"
+    fi
+    for tag in "${test_tag_array[@]}"; do
+        if [[ ${tag} == "!"* ]]; then
+            # Exclude tags are not prefixed.
+            TAGS+=("${tag}")
+        else
+            TAGS+=("${prefix}${tag}")
+        fi
+    done
+}
+
+
 function select_topology () {
 
     set -exuo pipefail
@@ -487,7 +757,7 @@ function select_topology () {
     # - NODENESS - Node multiplicity of testbed, either "2n" or "3n".
     # - FLAVOR - Node flavor string, currently either "hsw" or "skx".
     # - CSIT_DIR - Path to existing root of local CSIT git repository.
-    # - TOPOLOGIES_DIR - Path to existing directory with available tpologies.
+    # - TOPOLOGIES_DIR - Path to existing directory with available topologies.
     # Variables set:
     # - TOPOLOGIES - Array of paths to suitable topology yaml files.
     # - TOPOLOGIES_TAGS - Tag expression selecting tests for the topology.
@@ -496,13 +766,17 @@ function select_topology () {
 
     case_text="${NODENESS}_${FLAVOR}"
     case "${case_text}" in
-        "3n_hsw")
+        "1n_vbox")
             TOPOLOGIES=(
-                        "${TOPOLOGIES_DIR}/lf_3n_hsw_testbed1.yaml"
-                        "${TOPOLOGIES_DIR}/lf_3n_hsw_testbed2.yaml"
-                        "${TOPOLOGIES_DIR}/lf_3n_hsw_testbed3.yaml"
+                        "${TOPOLOGIES_DIR}/vpp_device.template"
                        )
-            TOPOLOGIES_TAGS="3_node_single_link_topo"
+            TOPOLOGIES_TAGS="2_node_single_link_topo"
+            ;;
+        "1n_skx")
+            TOPOLOGIES=(
+                        "${TOPOLOGIES_DIR}/vpp_device.template"
+                       )
+            TOPOLOGIES_TAGS="2_node_single_link_topo"
             ;;
         "2n_skx")
             TOPOLOGIES=(
@@ -520,6 +794,14 @@ function select_topology () {
                        )
             TOPOLOGIES_TAGS="3_node_*_link_topo"
             ;;
+        "3n_hsw")
+            TOPOLOGIES=(
+                        "${TOPOLOGIES_DIR}/lf_3n_hsw_testbed1.yaml"
+                        "${TOPOLOGIES_DIR}/lf_3n_hsw_testbed2.yaml"
+                        "${TOPOLOGIES_DIR}/lf_3n_hsw_testbed3.yaml"
+                       )
+            TOPOLOGIES_TAGS="3_node_single_link_topo"
+            ;;
         *)
             # No falling back to 3n_hsw default, that should have been done
             # by the function which has set NODENESS and FLAVOR.
@@ -558,9 +840,9 @@ function untrap_and_unreserve_testbed () {
     wt="${WORKING_TOPOLOGY}"  # Just to avoid too long lines.
     if [[ -z "${wt-}" ]]; then
         set -eu
-        echo "Testbed looks unreserved already. Trap removal failed before?"
+        warn "Testbed looks unreserved already. Trap removal failed before?"
     else
-        python "${PYTHON_SCRIPTS_DIR}/topo_cleanup.py" -t "${wt}" || true
+        cleanup_topo || true
         python "${PYTHON_SCRIPTS_DIR}/topo_reservation.py" -c -t "${wt}" || {
             die "${1:-FAILED TO UNRESERVE, FIX MANUALLY.}" 2
         }