X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=resources%2Flibraries%2Fbash%2Ffunction%2Fcommon.sh;h=491b47fb481bb6692b0fe035f68ce14e9319e979;hb=a31a47b1b497efffbcbb92004d32885a84f4ff4f;hp=ae008869555b50986518655bc41c2aea1f7f3064;hpb=2228ac2b930b3218a53464509cbd0011a50373a1;p=csit.git diff --git a/resources/libraries/bash/function/common.sh b/resources/libraries/bash/function/common.sh index ae00886955..491b47fb48 100644 --- a/resources/libraries/bash/function/common.sh +++ b/resources/libraries/bash/function/common.sh @@ -167,17 +167,19 @@ function check_download_dir () { } -function cleanup_topo () { +function check_prerequisites () { - # Variables read: - # - WORKING_TOPOLOGY - Path to topology yaml file of the reserved testbed. - # - PYTHON_SCRIPTS_DIR - Path to directory holding the reservation script. + # Fail if prerequisites are not met. + # + # Functions called: + # - installed - Check if application is installed/present in system. + # - die - Print to stderr and exit. set -exuo pipefail - 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. + if ! installed sshpass; then + die "Please install sshpass before continue!" + fi } @@ -202,37 +204,44 @@ function common_dirs () { set -exuo pipefail - BASH_FUNCTION_DIR="$(dirname "$(readlink -e "${BASH_SOURCE[0]}")")" || { - die "Some error during localizing this source directory." + this_file=$(readlink -e "${BASH_SOURCE[0]}") || { + die "Some error during locating of this source file." + } + BASH_FUNCTION_DIR=$(dirname "${this_file}") || { + die "Some error during dirname call." } # Current working directory could be in a different repo, e.g. VPP. pushd "${BASH_FUNCTION_DIR}" || die "Pushd failed" - CSIT_DIR="$(readlink -e "$(git rev-parse --show-toplevel)")" || { - die "Readlink or git rev-parse failed." + relative_csit_dir=$(git rev-parse --show-toplevel) || { + die "Git rev-parse failed." } + CSIT_DIR=$(readlink -e "${relative_csit_dir}") || die "Readlink failed." popd || die "Popd failed." - TOPOLOGIES_DIR="$(readlink -e "${CSIT_DIR}/topologies/available")" || { + TOPOLOGIES_DIR=$(readlink -e "${CSIT_DIR}/topologies/available") || { + die "Readlink failed." + } + RESOURCES_DIR=$(readlink -e "${CSIT_DIR}/resources") || { die "Readlink failed." } - RESOURCES_DIR="$(readlink -e "${CSIT_DIR}/resources")" || { + TOOLS_DIR=$(readlink -e "${RESOURCES_DIR}/tools") || { die "Readlink failed." } - TOOLS_DIR="$(readlink -e "${RESOURCES_DIR}/tools")" || { + DOC_GEN_DIR=$(readlink -e "${TOOLS_DIR}/doc_gen") || { die "Readlink failed." } - PYTHON_SCRIPTS_DIR="$(readlink -e "${TOOLS_DIR}/scripts")" || { + PYTHON_SCRIPTS_DIR=$(readlink -e "${TOOLS_DIR}/scripts") || { die "Readlink failed." } - ARCHIVE_DIR="$(readlink -f "${CSIT_DIR}/archive")" || { + ARCHIVE_DIR=$(readlink -f "${CSIT_DIR}/archive") || { die "Readlink failed." } mkdir -p "${ARCHIVE_DIR}" || die "Mkdir failed." - DOWNLOAD_DIR="$(readlink -f "${CSIT_DIR}/download_dir")" || { + DOWNLOAD_DIR=$(readlink -f "${CSIT_DIR}/download_dir") || { die "Readlink failed." } mkdir -p "${DOWNLOAD_DIR}" || die "Mkdir failed." - GENERATED_DIR="$(readlink -f "${CSIT_DIR}/generated")" || { + GENERATED_DIR=$(readlink -f "${CSIT_DIR}/generated") || { die "Readlink failed." } mkdir -p "${GENERATED_DIR}" || die "Mkdir failed." @@ -448,6 +457,10 @@ function get_test_code () { NODENESS="3n" FLAVOR="skx" ;; + *"2n-clx"*) + NODENESS="2n" + FLAVOR="clx" + ;; *"2n-dnv"*) NODENESS="2n" FLAVOR="dnv" @@ -489,8 +502,8 @@ function get_test_tag_string () { *"device"*) # On parsing error, ${trigger} stays empty. trigger="$(echo "${GERRIT_EVENT_COMMENT_TEXT}" \ - | grep -oE '(devicetest$|devicetest[[:space:]].+$)')" \ - || true + | grep -oE '(devicetest$|devicetest[[:space:]].+$)' \ + || true)" # Set test tags as string. TEST_TAG_STRING="${trigger#$"devicetest"}" ;; @@ -516,6 +529,24 @@ function get_test_tag_string () { } +function installed () { + + # Check if the given utility is installed. Fail if not installed. + # + # Duplicate of common.sh function, as this file is also used standalone. + # + # Arguments: + # - ${1} - Utility to check. + # Returns: + # - 0 - If command is installed. + # - 1 - If command is not installed. + + set -exuo pipefail + + command -v "${1}" +} + + function reserve_and_cleanup_testbed () { # Reserve physical testbed, perform cleanup, register trap to unreserve. @@ -527,24 +558,22 @@ function reserve_and_cleanup_testbed () { # - PYTHON_SCRIPTS_DIR - Path to directory holding the reservation script. # - BUILD_TAG - Any string suitable as filename, identifying # test run executing this function. May be unset. - # - BUILD_URL - Any string suitable as URL, identifying - # test run executing this function. May be unset. # Variables set: # - TOPOLOGIES - Array of paths to topologies, with failed cleanups removed. # - WORKING_TOPOLOGY - Path to topology yaml file of the reserved testbed. # Functions called: # - die - Print to stderr and exit. + # - ansible_hosts - Perform an action using ansible, see ansible.sh # Traps registered: # - EXIT - Calls cancel_all for ${WORKING_TOPOLOGY}. set -exuo pipefail - while [[ ${TOPOLOGIES[@]} ]]; do + while true; do for topo in "${TOPOLOGIES[@]}"; do set +e scrpt="${PYTHON_SCRIPTS_DIR}/topo_reservation.py" opts=("-t" "${topo}" "-r" "${BUILD_TAG:-Unknown}") - opts+=("-u" "${BUILD_URL:-Unknown}") python "${scrpt}" "${opts[@]}" result="$?" set -e @@ -563,7 +592,7 @@ function reserve_and_cleanup_testbed () { } # Cleanup check. set +e - cleanup_topo + ansible_hosts "cleanup" result="$?" set -e if [[ "${result}" == "0" ]]; then @@ -571,39 +600,27 @@ function reserve_and_cleanup_testbed () { fi warn "Testbed cleanup failed: ${topo}" untrap_and_unreserve_testbed "Fail of unreserve after cleanup." - # WORKING_TOPOLOGY is now empty again. - # Build new topology array. - # TOPOLOGIES=("${TOPOLOGIES[@]/$topo}") - # does not really work, see: - # https://stackoverflow.com/questions/16860877/remove-an-element-from-a-bash-array - new_topologies=() - for item in "${TOPOLOGIES[@]}"; do - if [[ "${item}" != "${topo}" ]]; then - new_topologies+=("${item}") - fi - done - TOPOLOGIES=("${new_topologies[@]}") - break fi + # Else testbed is accessible but currently reserved, moving on. done if [[ -n "${WORKING_TOPOLOGY-}" ]]; then # Exit the infinite while loop if we made a reservation. + warn "Reservation and cleanup successful." break fi + if [[ "${#TOPOLOGIES[@]}" == "0" ]]; then + die "Run out of operational testbeds!" + fi + # Wait ~3minutes before next try. - sleep_time="$[ ( $RANDOM % 20 ) + 180 ]s" || { + sleep_time="$[ ( ${RANDOM} % 20 ) + 180 ]s" || { die "Sleep time calculation failed." } echo "Sleeping ${sleep_time}" sleep "${sleep_time}" || die "Sleep failed." done - if [[ ${TOPOLOGIES[@]} ]]; then - echo "Reservation and cleanup successful." - else - die "Run out of operational testbeds!" - fi } @@ -644,6 +661,51 @@ function run_pybot () { } +function select_arch_os () { + + # Set variables affected by local CPU architecture and operating system. + # + # Variables set: + # - VPP_VER_FILE - Name of file in CSIT dir containing vpp stable version. + # - IMAGE_VER_FILE - Name of file in CSIT dir containing the image name. + # - PKG_SUFFIX - Suffix of OS package file name, "rpm" or "deb." + + set -exuo pipefail + + os_id=$(grep '^ID=' /etc/os-release | cut -f2- -d= | sed -e 's/\"//g') || { + die "Get OS release failed." + } + + case "${os_id}" in + "ubuntu"*) + IMAGE_VER_FILE="VPP_DEVICE_IMAGE_UBUNTU" + VPP_VER_FILE="VPP_STABLE_VER_UBUNTU_BIONIC" + PKG_SUFFIX="deb" + ;; + "centos"*) + IMAGE_VER_FILE="VPP_DEVICE_IMAGE_CENTOS" + VPP_VER_FILE="VPP_STABLE_VER_CENTOS" + PKG_SUFFIX="rpm" + ;; + *) + die "Unable to identify distro or os from ${os_id}" + ;; + esac + + arch=$(uname -m) || { + die "Get CPU architecture failed." + } + + case "${arch}" in + "aarch64") + IMAGE_VER_FILE="${IMAGE_VER_FILE}_ARM" + ;; + *) + ;; + esac +} + + function select_tags () { # Variables read: @@ -682,11 +744,18 @@ function select_tags () { *"3n-tsh"*) default_nic="nic_intel-x520-da2" ;; + *"3n-skx"* | *"2n-skx"* | *"2n-clx"*) + default_nic="nic_intel-xxv710" + ;; + *"3n-hsw"* | *"mrr-daily-master") + default_nic="nic_intel-xl710" + ;; *) default_nic="nic_intel-x710" ;; esac + sed_nic_sub_cmd="sed s/\${default_nic}/${default_nic}/" # Tag file directory shorthand. tfd="${BASH_FUNCTION_DIR}" case "${TEST_CODE}" in @@ -695,8 +764,8 @@ function select_tags () { readarray -t test_tag_array < "${tfd}/mlr-weekly.txt" || die ;; *"mrr-daily"* ) - readarray -t test_tag_array < \ - "${tfd}/mrr-daily-${FLAVOR}.txt" || die + readarray -t test_tag_array <<< $(${sed_nic_sub_cmd} \ + ${tfd}/mrr-daily-${FLAVOR}.txt) || die ;; *"mrr-weekly"* ) readarray -t test_tag_array < "${tfd}/mrr-weekly.txt" || die @@ -731,6 +800,9 @@ function select_tags () { # Not enough nic_intel-xxv710 to support double link tests. test_tag_array+=("!3_node_double_link_topoANDnic_intel-xxv710") ;; + *"2n-clx"*) + test_tag_array+=("!ipsechw") + ;; *"2n-dnv"*) test_tag_array+=("!ipsechw") test_tag_array+=("!memif") @@ -747,11 +819,9 @@ function select_tags () { test_tag_array+=("!drv_avf") ;; *"3n-tsh"*) + # 3n-tsh only has x520 NICs which don't work with AVF + test_tag_array+=("!drv_avf") test_tag_array+=("!ipsechw") - test_tag_array+=("!memif") - test_tag_array+=("!srv6_proxy") - test_tag_array+=("!vhost") - test_tag_array+=("!vts") ;; *"3n-hsw"*) # TODO: Introduce NOIOMMU version of AVF tests. @@ -793,6 +863,12 @@ function select_tags () { if [[ "${tag}" == "!"* ]]; then # Exclude tags are not prefixed. TAGS+=("${tag}") + elif [[ "${tag}" == " "* || "${tag}" == *"perftest"* ]]; then + # Badly formed tag expressions can trigger way too much tests. + set -x + warn "The following tag expression hints at bad trigger: ${tag}" + warn "Possible cause: Multiple triggers in a single comment." + die "Aborting to avoid triggering too many tests." elif [[ "${tag}" != "" && "${tag}" != "#"* ]]; then # Empty and comment lines are skipped. # Other lines are normal tags, they are to be prefixed. @@ -803,82 +879,6 @@ function select_tags () { } -function select_vpp_device_tags () { - - # 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. - - set -exuo pipefail - - 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 devicetest 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_os () { - - # Variables set: - # - VPP_VER_FILE - Name of File in CSIT dir containing vpp stable version. - # - IMAGE_VER_FILE - Name of File in CSIT dir containing the image name. - # - PKG_SUFFIX - Suffix of OS package file name, "rpm" or "deb." - - set -exuo pipefail - - os_id=$(grep '^ID=' /etc/os-release | cut -f2- -d= | sed -e 's/\"//g') || { - die "Get OS release failed." - } - - case "${os_id}" in - "ubuntu"*) - IMAGE_VER_FILE="VPP_DEVICE_IMAGE_UBUNTU" - VPP_VER_FILE="VPP_STABLE_VER_UBUNTU_BIONIC" - PKG_SUFFIX="deb" - ;; - "centos"*) - IMAGE_VER_FILE="VPP_DEVICE_IMAGE_CENTOS" - VPP_VER_FILE="VPP_STABLE_VER_CENTOS" - PKG_SUFFIX="rpm" - ;; - *) - die "Unable to identify distro or os from ${OS}" - ;; - esac -} - - function select_topology () { # Variables read: @@ -914,6 +914,10 @@ function select_topology () { TOPOLOGIES=( "${TOPOLOGIES_DIR}"/*3n_skx*.yaml ) TOPOLOGIES_TAGS="3_node_*_link_topo" ;; + "2n_clx") + TOPOLOGIES=( "${TOPOLOGIES_DIR}"/*2n_clx*.yaml ) + TOPOLOGIES_TAGS="2_node_*_link_topo" + ;; "2n_dnv") TOPOLOGIES=( "${TOPOLOGIES_DIR}"/*2n_dnv*.yaml ) TOPOLOGIES_TAGS="2_node_single_link_topo" @@ -928,7 +932,7 @@ function select_topology () { ;; "3n_tsh") TOPOLOGIES=( "${TOPOLOGIES_DIR}"/*3n_tsh*.yaml ) - TOPOLOGIES_TAGS="3_node_*_link_topo" + TOPOLOGIES_TAGS="3_node_single_link_topo" ;; *) # No falling back to 3n_hsw default, that should have been done @@ -942,6 +946,65 @@ function select_topology () { } +function select_vpp_device_tags () { + + # 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. + + set -exuo pipefail + + case "${TEST_CODE}" in + # Select specific device 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 + + # Blacklisting certain tags per topology. + # + # Reasons for blacklisting: + # - avf - AVF is not possible to run on enic driver of VirtualBox. + # - vhost - VirtualBox does not support nesting virtualization on Intel CPU. + case "${TEST_CODE}" in + *"1n-vbox"*) + test_tag_array+=("!avf") + test_tag_array+=("!vhost") + ;; + *) + ;; + esac + + TAGS=() + + # We will prefix with devicetest 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 untrap_and_unreserve_testbed () { # Use this as a trap function to ensure testbed does not remain reserved. @@ -962,6 +1025,7 @@ function untrap_and_unreserve_testbed () { # - EXIT - Failure to untrap is reported, but ignored otherwise. # Functions called: # - die - Print to stderr and exit. + # - ansible_hosts - Perform an action using ansible, see ansible.sh set -xo pipefail set +eu # We do not want to exit early in a "teardown" function. @@ -971,7 +1035,7 @@ function untrap_and_unreserve_testbed () { set -eu warn "Testbed looks unreserved already. Trap removal failed before?" else - cleanup_topo || true + ansible_hosts "cleanup" || true python "${PYTHON_SCRIPTS_DIR}/topo_reservation.py" -c -t "${wt}" || { die "${1:-FAILED TO UNRESERVE, FIX MANUALLY.}" 2 }