aboutsummaryrefslogtreecommitdiffstats
path: root/bootstrap-verify-perf.sh
blob: c72d6ec7ddd0e29da53605c699fe7fa65d435c26 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
#!/usr/bin/env bash
# Copyright (c) 2018 Cisco and/or its affiliates.
# 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.

set -xo pipefail

# FUNCTIONS
function warn () {
    # Prints the message to standard error.
    echo "$@" >&2
}

function die () {
    # Prints the message to standard error end exit with error code specified
    # by first argument.
    status="$1"
    shift
    warn "$@"
    exit "$status"
}

function help () {
    # Displays help message.
    die 1 "Usage: `basename $0` csit-[dpdk|vpp|ligato]-[2n-skx|3n-skx|3n-hsw]"
}

function cancel_all () {
    # Trap function to get into consistent state.
    python ${SCRIPT_DIR}/resources/tools/scripts/topo_cleanup.py -t $1 || {
        die 1 "Failure during execution of topology cleanup script!"
    }
    python ${SCRIPT_DIR}/resources/tools/scripts/topo_reservation.py -c -t $1 || {
        die 1 "Failure during execution of topology un-reservation script!"
    }
}

# VARIABLES
# Space separated list of available testbeds, described by topology files
TOPOLOGIES_3N_HSW=(topologies/available/lf_3n_hsw_testbed1.yaml
                   topologies/available/lf_3n_hsw_testbed2.yaml
                   topologies/available/lf_3n_hsw_testbed3.yaml)
TOPOLOGIES_2N_SKX=(topologies/available/lf_2n_skx_testbed21.yaml
                   topologies/available/lf_2n_skx_testbed24.yaml)
TOPOLOGIES_3N_SKX=(topologies/available/lf_3n_skx_testbed31.yaml
                   topologies/available/lf_3n_skx_testbed32.yaml)

SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
export PYTHONPATH=${SCRIPT_DIR}

RESERVATION_DIR="/tmp/reservation_dir"
DOWNLOAD_DIR="${SCRIPT_DIR}/download_dir"
ARCHIVE_DIR="${SCRIPT_DIR}/archive"

mkdir -p ${DOWNLOAD_DIR} || {
    die 1 "Failed to create download dir!"
}
mkdir -p ${ARCHIVE_DIR} || {
    die 1 "Failed to create archive dir!"
}

# Get test code.
TEST_CODE=${JOB_NAME-}
if [[ -z ${TEST_CODE} ]]; then
    TEST_CODE=${1}
    shift
fi

# TOPOLOGY SELECTION
case "$TEST_CODE" in
    *2n-skx*)
        TOPOLOGIES=${TOPOLOGIES_2N_SKX[@]}
        TOPOLOGIES_TAGS="2_node_*_link_topo"
        ;;
    *3n-skx*)
        TOPOLOGIES=${TOPOLOGIES_3N_SKX[@]}
        TOPOLOGIES_TAGS="3_node_*_link_topo"
        ;;
    *)
        # Fallback to 3-node Haswell by default (backward compatibility)
        TOPOLOGIES=${TOPOLOGIES_3N_HSW[@]}
        TOPOLOGIES_TAGS="3_node_*_link_topo"
        ;;
esac

if [[ -z "${TOPOLOGIES}" ]]; then
    die 1 "No applicable topology found!"
fi

cd ${DOWNLOAD_DIR}
case "$TEST_CODE" in
    *hc2vpp*)
        DUT="hc2vpp"
        ;;
    *vpp*)
        DUT="vpp"

        case "$TEST_CODE" in
            csit-vpp-*)
                # Use downloaded packages with specific version
                if [[ "$TEST_CODE" == *daily* ]] || \
                   [[ "$TEST_CODE" == *weekly* ]] || \
                   [[ "$TEST_CODE" == *timed* ]];
                then
                    echo Downloading latest VPP packages from NEXUS...
                    bash ${SCRIPT_DIR}/resources/tools/scripts/download_install_vpp_pkgs.sh \
                        --skip-install || {
                        die 1 "Failed to get VPP packages!"
                    }
                else
                    echo Downloading VPP packages of specific version from NEXUS...
                    DPDK_STABLE_VER=$(cat ${SCRIPT_DIR}/DPDK_STABLE_VER)
                    VPP_STABLE_VER=$(cat ${SCRIPT_DIR}/VPP_STABLE_VER_UBUNTU)
                    bash ${SCRIPT_DIR}/resources/tools/scripts/download_install_vpp_pkgs.sh \
                        --skip-install --vpp ${VPP_STABLE_VER} --dkms ${DPDK_STABLE_VER} || {
                        die 1 "Failed to get VPP packages!"
                    }
                fi
                ;;
            vpp-csit-*)
                # Use local built packages.
                mv ../${DUT}*.deb ${DOWNLOAD_DIR}/
                ;;
            *)
                die 1 "Unable to identify job type from: ${TEST_CODE}!"
                ;;
        esac
        ;;
    *ligato*)
        DUT="kubernetes"

        case "$TEST_CODE" in
            csit-*)
                # Use downloaded packages with specific version
                if [[ "$TEST_CODE" == *daily* ]] || \
                   [[ "$TEST_CODE" == *weekly* ]] || \
                   [[ "$TEST_CODE" == *timed* ]];
                then
                    echo Downloading latest VPP packages from NEXUS...
                    bash ${SCRIPT_DIR}/resources/tools/scripts/download_install_vpp_pkgs.sh \
                        --skip-install || {
                        die 1 "Failed to get VPP packages!"
                    }
                else
                    echo Downloading VPP packages of specific version from NEXUS...
                    DPDK_STABLE_VER=$(cat ${SCRIPT_DIR}/DPDK_STABLE_VER)
                    VPP_STABLE_VER=$(cat ${SCRIPT_DIR}/VPP_STABLE_VER_UBUNTU)
                    bash ${SCRIPT_DIR}/resources/tools/scripts/download_install_vpp_pkgs.sh \
                        --skip-install --vpp ${VPP_STABLE_VER} --dkms ${DPDK_STABLE_VER} || {
                        die 1 "Failed to get VPP packages!"
                    }
                fi
                ;;
            vpp-csit-*)
                # Use local builded packages.
                mv ../${DUT}*.deb ${DOWNLOAD_DIR}/
                ;;
            *)
                die 1 "Unable to identify job type from: ${TEST_CODE}!"
                ;;
        esac
        # Extract VPP API to specific folder
        dpkg -x ${DOWNLOAD_DIR}/vpp_*.deb /tmp/vpp || {
            die 1 "Failed to extract ${DUT} package!"
        }

        LIGATO_REPO_URL="https://github.com/ligato/"
        VPP_AGENT_STABLE_VER=$(cat ${SCRIPT_DIR}/VPP_AGENT_STABLE_VER)
        DOCKER_DEB="docker-ce_18.03.0~ce-0~ubuntu_amd64.deb"

        # Clone & checkout stable vnf-agent
        cd ../..
        git clone -b ${VPP_AGENT_STABLE_VER} --single-branch \
            ${LIGATO_REPO_URL}/vpp-agent vpp-agent || {
            die 1 "Failed to run: git clone ${LIGATO_REPO_URL}/vpp-agent!"
        }
        cd vpp-agent

        # Install Docker
        wget -q https://download.docker.com/linux/ubuntu/dists/xenial/pool/stable/amd64/${DOCKER_DEB} || {
            die 1 "Failed to download Docker package!"
        }

        sudo dpkg -i ${DOCKER_DEB} || {
            die 1 "Failed to install Docker!"
        }

        # Pull ligato/dev_vpp_agent docker image and re-tag as local
        sudo docker pull ligato/dev-vpp-agent:${VPP_AGENT_STABLE_VER} || {
            die 1 "Failed to pull Docker image!"
        }

        sudo docker tag ligato/dev-vpp-agent:${VPP_AGENT_STABLE_VER}\
            dev_vpp_agent:latest || {
            die 1 "Failed to tag Docker image!"
        }

        # Start dev_vpp_agent container as daemon
        sudo docker run --rm -itd --name agentcnt dev_vpp_agent bash || {
            die 1 "Failed to run Docker image!"
        }

        # Copy latest vpp api into running container
        sudo docker cp /tmp/vpp/usr/share/vpp/api agentcnt:/usr/share/vpp || {
            die 1 "Failed to copy files Docker image!"
        }

        for f in ${DOWNLOAD_DIR}/*; do
            sudo docker cp $f agentcnt:/opt/vpp-agent/dev/vpp/build-root/ || {
                die 1 "Failed to copy files Docker image!"
            }
        done

        # Recompile vpp-agent
        sudo docker exec -i agentcnt \
            script -qec '. ~/.bashrc; cd /go/src/github.com/ligato/vpp-agent && make generate && make install' || {
            die 1 "Failed to build vpp-agent in Docker image!"
        }
        # Save container state
        sudo docker commit `sudo docker ps -q` dev_vpp_agent:latest || {
            die 1 "Failed to commit state of Docker image!"
        }

        # Build prod_vpp_agent docker image
        cd docker/prod/ &&\
            sudo docker build --tag prod_vpp_agent --no-cache . || {
                die 1 "Failed to build Docker image!"
            }
        # Export Docker image
        sudo docker save prod_vpp_agent | gzip > prod_vpp_agent.tar.gz || {
            die 1 "Failed to save Docker image!"
        }
        DOCKER_IMAGE="$( readlink -f prod_vpp_agent.tar.gz | tr '\n' ' ' )"
        rm -r ${DOWNLOAD_DIR}/vpp*
        mv ${DOCKER_IMAGE} ${DOWNLOAD_DIR}/
        ;;
    *dpdk*)
        DUT="dpdk"

        DPDK_REPO='https://fast.dpdk.org/rel/'
        # Use downloaded packages with specific version
        if [[ "$TEST_CODE" == *daily* ]] || \
           [[ "$TEST_CODE" == *weekly* ]] || \
           [[ "$TEST_CODE" == *timed* ]];
        then
            echo "Downloading latest DPDK packages from repo..."
            DPDK_STABLE_VER=$(wget --no-check-certificate --quiet -O - ${DPDK_REPO} | \
                grep -v '2015' | grep -Eo 'dpdk-[^\"]+xz' | tail -1)
        else
            echo "Downloading DPDK packages of specific version from repo..."
            DPDK_STABLE_VER='dpdk-18.05.tar.xz'
        fi
        if [[ ! -f ${DPDK_STABLE_VER} ]]; then
            wget --no-check-certificate ${DPDK_REPO}${DPDK_STABLE_VER} || {
                die 1 "Failed to get DPDK package from ${DPDK_REPO}!"
            }
        fi
        ;;
    *)
        die 1 "Unable to identify DUT type from: ${TEST_CODE}!"
        ;;
esac
cd ${SCRIPT_DIR}

if [[ ! "$(ls -A ${DOWNLOAD_DIR})" ]]; then
    die 1 "No artifacts downloaded!"
fi

# ENVIRONMENT PREPARATION
rm -rf env

pip install virtualenv || {
    die 1 "Failed to install virtual env!"
}
virtualenv --system-site-packages env || {
    die 1 "Failed to create virtual env!"
}
source env/bin/activate || {
    die 1 "Failed to activate virtual env!"
}
pip install -r requirements.txt || {
    die 1 "Failed to install requirements to virtual env!"
}

# We iterate over available topologies and wait until we reserve topology.
while :; do
    for TOPOLOGY in ${TOPOLOGIES};
    do
        python ${SCRIPT_DIR}/resources/tools/scripts/topo_reservation.py -t ${TOPOLOGY}
        if [ $? -eq 0 ]; then
            WORKING_TOPOLOGY=${TOPOLOGY}
            echo "Reserved: ${WORKING_TOPOLOGY}"
            # On script exit we clean testbed.
            trap "cancel_all ${WORKING_TOPOLOGY}" EXIT
            break
        fi
    done

    if [ -n "${WORKING_TOPOLOGY}" ]; then
        # Exit the infinite while loop if we made a reservation.
        break
    fi

    # Wait ~3minutes before next try.
    SLEEP_TIME=$[ ( $RANDOM % 20 ) + 180 ]s
    echo "Sleeping ${SLEEP_TIME}"
    sleep ${SLEEP_TIME}
done

# Clean testbed before execution.
python ${SCRIPT_DIR}/resources/tools/scripts/topo_cleanup.py -t ${WORKING_TOPOLOGY} || {
    die 1 "Failed to cleanup topologies!"
}

# CSIT EXECUTION
PYBOT_ARGS="--outputdir ${ARCHIVE_DIR} --loglevel TRACE --variable TOPOLOGY_PATH:${WORKING_TOPOLOGY} --suite tests.${DUT}.perf"

# NIC SELECTION
# All topologies NICs
TOPOLOGIES_NICS=($(grep -hoPR "model: \K.*" topologies/available/* | sort -u))
# Selected topology NICs
TOPOLOGY_NICS=($(grep -hoPR "model: \K.*" ${WORKING_TOPOLOGY} | sort -u))
# All topologies NICs - Selected topology NICs
EXCLUDE_NICS=($(comm -13 <(printf '%s\n' "${TOPOLOGY_NICS[@]}") <(printf '%s\n' "${TOPOLOGIES_NICS[@]}")))

case "$TEST_CODE" in
    # Select specific performance tests based on jenkins job type variable.
    *ndrpdr-weekly* )
        TEST_TAG_ARRAY=(ndrpdrAND64bAND1c
                        ndrpdrAND78bAND1c)
        ;;
    *mrr-daily* | *mrr-weekly* )
        TEST_TAG_ARRAY=(mrrAND64bAND1c
                        mrrAND64bAND2c
                        mrrAND64bAND4c
                        mrrAND78bAND1c
                        mrrAND78bAND2c
                        mrrAND78bAND4c
                        mrrANDimixAND1cANDvhost
                        mrrANDimixAND2cANDvhost
                        mrrANDimixAND4cANDvhost
                        mrrANDimixAND1cANDmemif
                        mrrANDimixAND2cANDmemif
                        mrrANDimixAND4cANDmemif)
        ;;
    * )
        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=(mrrANDnic_intel-x710AND1cAND64bANDip4base
                            mrrANDnic_intel-x710AND1cAND78bANDip6base
                            mrrANDnic_intel-x710AND1cAND64bANDl2bdbase)
        else
            # If trigger contains tags, split them into array.
            TEST_TAG_ARRAY=(${TEST_TAG_STRING//:/ })
        fi
        ;;
esac

# We will add excluded NICs.
TEST_TAG_ARRAY+=("${EXCLUDE_NICS[@]/#/!NIC_}")

TAGS=()

# We will prefix with perftest to prevent running other tests (e.g. Functional).
prefix="perftestAND"
if [[ ${TEST_CODE} == vpp-* ]]; then
    # Automatic prefixing for VPP jobs to limit the NIC used and
    # traffic evaluation to MRR.
    prefix="${prefix}mrrANDnic_intel-x710AND"
fi
for TAG in "${TEST_TAG_ARRAY[@]}"; do
    if [[ ${TAG} == "!"* ]]; then
        # Exclude tags are not prefixed.
        TAGS+=("${TAG}")
    else
        TAGS+=("$prefix${TAG}")
    fi
done

# Catenate TAG selections
EXPANDED_TAGS=()
for TAG in "${TAGS[@]}"; do
    if [[ ${TAG} == "!"* ]]; then
        EXPANDED_TAGS+=(" --exclude ${TAG#$"!"} ")
    else
        EXPANDED_TAGS+=(" --include ${TOPOLOGIES_TAGS}AND${TAG} ")
    fi
done

# Execute the test
pybot ${PYBOT_ARGS}${EXPANDED_TAGS[@]} tests/
RETURN_STATUS=$(echo $?)

# We will create additional archive if workspace variable is set. This way if
# script is running in jenkins all will be automatically archived to logs.fd.io.
if [[ -n ${WORKSPACE-} ]]; then
    cp -r ${ARCHIVE_DIR}/ $WORKSPACE/archives/
fi

exit ${RETURN_STATUS}