ixia: Fix VLAN support by IxNet class
[vswitchperf.git] / ci / build-vsperf.sh
1 #!/bin/bash
2 #
3 # Copyright 2015-2016 Intel Corporation.
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 #   http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 # VSPERF nightly build execution script
18
19 # Usage:
20 #       build-vsperf.sh job_type
21 #   where job_type is one of "verify", "merge", "daily"
22
23 #
24 # exit codes
25 #
26
27 EXIT=0
28 EXIT_TC_FAILED=1
29 EXIT_SANITY_TC_FAILED=2
30 EXIT_PYLINT_FAILED=4
31 EXIT_NO_RESULTS=128
32 EXIT_NO_TEST_REPORT_LOG_DIR=256
33
34 #
35 # configuration
36 #
37
38 VSPERF_BIN='./vsperf'
39 LOG_FILE_PREFIX="/tmp/vsperf_build"
40 DATE=$(date -u +"%Y-%m-%d_%H-%M-%S")
41 BRANCH=${GIT_BRANCH##*/}
42 VSPERFENV_DIR="$HOME/vsperfenv"
43
44 # CI job specific configuration
45 # VERIFY - run basic set of TCs with default settings
46 TESTCASES_VERIFY="vswitch_add_del_bridge vswitch_add_del_bridges vswitch_add_del_vport vswitch_add_del_vports vswitch_vports_add_del_flow"
47 TESTPARAM_VERIFY="--integration"
48 # MERGE - run selected TCs with default settings
49 TESTCASES_MERGE="vswitch_add_del_bridge vswitch_add_del_bridges vswitch_add_del_vport vswitch_add_del_vports vswitch_vports_add_del_flow"
50 TESTPARAM_MERGE="--integration"
51 # DAILY - run selected TCs for defined packet sizes
52 TESTCASES_DAILY='phy2phy_tput back2back phy2phy_tput_mod_vlan phy2phy_scalability pvp_tput pvp_back2back pvvp_tput pvvp_back2back'
53 TESTPARAM_DAILY='--test-params TRAFFICGEN_PKT_SIZES=(64,128,512,1024,1518)'
54 TESTCASES_SRIOV='pvp_tput'
55 TESTPARAM_SRIOV='--test-params TRAFFICGEN_PKT_SIZES=(64,128,512,1024,1518)'
56 # check if user config file exists if not then we will use default settings
57 if [ -f $HOME/vsperf-${BRANCH}.conf ] ; then
58     # branch specific config was found
59     CONF_FILE="--conf-file ${HOME}/vsperf-${BRANCH}.conf"
60 else
61     if [ -f $HOME/vsperf.conf ] ; then
62         CONF_FILE="--conf-file ${HOME}/vsperf.conf"
63     else
64         CONF_FILE=""
65     fi
66 fi
67 # check if sriov specific config file exists if not then use default configuration
68 if [ -f $HOME/vsperf-${BRANCH}.conf.sriov ] ; then
69     CONF_FILE_SRIOV="${CONF_FILE}.sriov"
70 else
71     CONF_FILE_SRIOV=$CONF_FILE
72 fi
73
74 # Test report related configuration
75 TEST_REPORT_PARTIAL="*_test_report.rst"
76 TEST_REPORT_DIR="${WORKSPACE}/docs/results"
77 TEST_REPORT_INDEX="${TEST_REPORT_DIR}/index.rst"
78 TEST_REPORT_LINK_OLD="https://wiki.opnfv.org/wiki/vsperf_results"
79 TEST_REPORT_FILE="${WORKSPACE}/docs_output/results/index.html"
80 TEST_REPORT_TARBALL="vswitchperf_logs_${DATE}.tar.gz"
81
82 if [[ "x${BRANCH}" == "xmaster" ]]; then
83     TEST_REPORT_LINK_NEW="https://artifacts.opnfv.org/logs/$PROJECT/$NODE_NAME/$DATE/${TEST_REPORT_TARBALL}"
84 else
85     TEST_REPORT_LINK_NEW="https://artifacts.opnfv.org/logs/$PROJECT/$NODE_NAME/$BRANCH/$DATE/${TEST_REPORT_TARBALL}"
86 fi
87
88 TEST_REPORT_LOG_DIR="${HOME}/opnfv/$PROJECT/results/$BRANCH"
89
90 #
91 # functions
92 #
93
94 # terminate vsperf and all its utilities
95 # it is expected that vsperf is the only python3 app
96 # and no other ovs or qemu instances are running
97 # at CI machine
98 # parameters:
99 #   none
100 function terminate_vsperf() {
101     sudo pkill stress &> /dev/null
102     sudo pkill python3 &> /dev/null
103     sudo killall -9 qemu-system-x86_64 &> /dev/null
104
105     # sometimes qemu resists to terminate, so wait a bit and kill it again
106     if pgrep qemu-system-x86_64 &> /dev/null ; then
107         sleep 5
108         sudo killall -9 qemu-system-x86_64 &> /dev/null
109         sleep 5
110     fi
111
112     sudo pkill ovs-vswitchd &> /dev/null
113     sleep 1
114     sudo pkill ovsdb-server &> /dev/null
115     sleep 1
116 }
117
118 # check and print testcase execution status
119 # parameters:
120 #   $1 - directory with results
121 function print_results() {
122     for i in $TESTCASES ; do
123         RES_FILE=`ls -1 $1 | egrep "result_${i}_[0-9a-zA-Z\-]+.csv"`
124
125         if [ "x$RES_FILE" != "x" -a -e "${1}/${RES_FILE}" ]; then
126             if grep ^FAILED "${1}/${RES_FILE}" &> /dev/null ; then
127                 printf "    %-70s %-6s\n" "result_${i}" "FAILED"
128                 EXIT=$EXIT_TC_FAILED
129             else
130                 printf "    %-70s %-6s\n" "result_${i}" "OK"
131             fi
132         else
133             printf "    %-70s %-6s\n" "result_${i}" "FAILED"
134             EXIT=$EXIT_TC_FAILED
135         fi
136     done
137 }
138
139 # execute tests and display results
140 # parameters:
141 #   $1 - vswitch and vnf combination, one of OVS_vanilla, OVS_with_DPDK_and_vHost_User
142 #   $2 - CI job type, one of verify, merge, daily
143 function execute_vsperf() {
144     OPNFVPOD=""
145     # figure out list of TCs and execution parameters
146     case $2 in
147         "verify")
148             TESTPARAM=$TESTPARAM_VERIFY
149             TESTCASES=$TESTCASES_VERIFY
150             ;;
151         "merge")
152             TESTPARAM=$TESTPARAM_MERGE
153             TESTCASES=$TESTCASES_MERGE
154             ;;
155         *)
156             # by default use daily build and upload results to the OPNFV databse
157             TESTPARAM=$TESTPARAM_DAILY
158             TESTCASES=$TESTCASES_DAILY
159             OPNFVPOD="--opnfvpod=$NODE_NAME"
160             ;;
161     esac
162
163     # execute testcases
164     echo -e "\nExecution of VSPERF for $1"
165
166     DATE_SUFFIX=$(date -u +"%Y-%m-%d_%H-%M-%S")
167
168     case $1 in
169         "SRIOV")
170             # use SRIOV specific TCs and configuration
171             TESTPARAM=$TESTPARAM_SRIOV
172             TESTCASES=$TESTCASES_SRIOV
173             # figure out log file name
174             LOG_SUBDIR="SRIOV"
175             LOG_FILE="${LOG_FILE_PREFIX}_${LOG_SUBDIR}_${DATE_SUFFIX}.log"
176
177             echo "    $VSPERF_BIN --vswitch none --vnf QemuPciPassthrough $CONF_FILE_SRIOV $TESTPARAM $TESTCASES &> $LOG_FILE"
178             $VSPERF_BIN --vswitch none --vnf QemuPciPassthrough $CONF_FILE_SRIOV $TESTPARAM $TESTCASES &> $LOG_FILE
179             ;;
180         "OVS_vanilla")
181             # figure out log file name
182             LOG_SUBDIR="OvsVanilla"
183             LOG_FILE="${LOG_FILE_PREFIX}_${LOG_SUBDIR}_${DATE_SUFFIX}.log"
184
185             echo "    $VSPERF_BIN $OPNFVPOD --vswitch OvsVanilla --vnf QemuVirtioNet $CONF_FILE $TESTPARAM $TESTCASES &> $LOG_FILE"
186             $VSPERF_BIN $OPNFVPOD --vswitch OvsVanilla --vnf QemuVirtioNet $CONF_FILE $TESTPARAM $TESTCASES &> $LOG_FILE
187             ;;
188         *)
189             # figure out log file name
190             LOG_SUBDIR="OvsDpdkVhost"
191             LOG_FILE="${LOG_FILE_PREFIX}_${LOG_SUBDIR}_${DATE_SUFFIX}.log"
192
193             hugepages_info > $LOG_FILE
194             echo "    $VSPERF_BIN $OPNFVPOD --vswitch OvsDpdkVhost --vnf QemuDpdkVhostUser $CONF_FILE $TESTPARAM $TESTCASES > $LOG_FILE"
195             $VSPERF_BIN $OPNFVPOD --vswitch OvsDpdkVhost --vnf QemuDpdkVhostUser $CONF_FILE $TESTPARAM $TESTCASES &>> $LOG_FILE
196             hugepages_info >> $LOG_FILE
197             ;;
198     esac
199
200     # evaluation of results
201     echo -e "\nResults for $1"
202     RES_DIR="/$(grep "Creating result directory" $LOG_FILE | cut -d'/' -f2-)"
203     if [[ "/" == "${RES_DIR}" ]] ; then
204         echo "FAILURE: Results are not available."
205         echo "-------------------------------------------------------------------"
206         cat $LOG_FILE
207         echo "-------------------------------------------------------------------"
208         exit $EXIT_NO_RESULTS
209     else
210         print_results "${RES_DIR}"
211         if [ $(($EXIT & $EXIT_TC_FAILED)) -gt 0 ] ; then
212             echo "-------------------------------------------------------------------"
213             cat $LOG_FILE
214             echo "-------------------------------------------------------------------"
215         fi
216     fi
217
218     # show detailed result figures
219     for md_file in $(grep '\.md"$' $LOG_FILE | cut -d'"' -f2); do
220         # TC resut file header
221         echo -e "\n-------------------------------------------------------------------"
222         echo -e " $md_file"
223         echo -e "-------------------------------------------------------------------\n"
224         # TC details
225         sed -n '/^- Test ID/,/Bidirectional/{/Packet size/b;p;/Bidirectional/q};/Results\/Metrics Collected/,/Statistics collected/{/^$/p;/^|/p}' $md_file
226         # TC results
227         sed -n '/Results\/Metrics Collected/,/Statistics collected/{/^$/p;/^|/p}' $md_file | grep -v "Unknown" | cat -s
228     done
229
230     # add test results into the final doc template
231     for report in ${RES_DIR}/${TEST_REPORT_PARTIAL} ; do
232         # modify link to the artifactory with test report and logs
233         if [ -f $report ] ; then
234             sed -i -e "s,$TEST_REPORT_LINK_OLD,$TEST_REPORT_LINK_NEW," "$report"
235             cp $report $TEST_REPORT_DIR
236             echo "   $(basename $report)" >> $TEST_REPORT_INDEX
237         fi
238     done
239
240     # copy logs into dedicated directory
241     mkdir ${TEST_REPORT_LOG_DIR}/${LOG_SUBDIR}
242     [ -f "$LOG_FILE" ] && cp -a "${LOG_FILE}" "${TEST_REPORT_LOG_DIR}/${LOG_SUBDIR}" &> /dev/null
243     [ -d "$RES_DIR" ] && cp -ar "$RES_DIR" "${TEST_REPORT_LOG_DIR}/${LOG_SUBDIR}" &> /dev/null
244 }
245
246 # generates final test_report in PDF and HTML formats
247 function generate_report() {
248
249     # prepare final tarball with all logs...
250     tar --exclude "${TEST_REPORT_TARBALL}" -czf "${TEST_REPORT_LOG_DIR}/${TEST_REPORT_TARBALL}" $(find "${TEST_REPORT_LOG_DIR}" -mindepth 1 -maxdepth 1 -type d)
251     # ...and remove original log files
252     find "${TEST_REPORT_LOG_DIR}" -mindepth 1 -maxdepth 1 -type d -exec rm -rf \{\} \;
253
254     # clone opnfvdocs repository
255     echo "Cloning opnfvdocs repository..."
256     [ -d opnfvdocs ] && rm -rf opnfvdocs
257     git clone https://gerrit.opnfv.org/gerrit/opnfvdocs &> /dev/null
258
259     # generate final docs with test results
260     echo "Generating test report..."
261     sed -ie 's,python ,python2 ,g' ./opnfvdocs/scripts/docs-build.sh
262     OPNFVDOCS_DIR='./opnfvdocs' ./opnfvdocs/scripts/docs-build.sh &> /dev/null
263
264     # store HTML report with test results into dedicated directory
265     if [ -f $TEST_REPORT_FILE ] ; then
266         cp -ar $TEST_REPORT_FILE $(dirname $TEST_REPORT_FILE)/_static $TEST_REPORT_LOG_DIR
267         echo "Final test report has been created."
268     else
269         echo "FAILURE: Generation of final test report has failed."
270     fi
271 }
272
273 # pushes test report and logs collected during test execution into artifactory
274 function push_results_to_artifactory() {
275     # clone releng repository
276     echo "Cloning releng repository..."
277     [ -d releng ] && rm -rf releng
278     git clone https://gerrit.opnfv.org/gerrit/releng &> /dev/null
279
280     echo "Pushing results and logs into artifactory..."
281     . ./releng/utils/push-test-logs.sh "$DATE"
282
283     # enter workspace as it could be modified by 3rd party script
284     cd $WORKSPACE
285 }
286
287 # removes any local changes of repository
288 function cleanup() {
289     echo "Cleaning up..."
290     git stash -u
291 }
292
293 # prepares directory for logs collection and removes old logs
294 function initialize_logdir() {
295     if [[ "x$TEST_REPORT_LOG_DIR" == "x" ]] ; then
296         echo "FAILURE: Logging directory is not defined. Logs and report cannot be published!"
297         exit $EXIT_NO_TEST_REPORT_LOG_DIR
298     else
299         # remove TEST_REPORT_LOG_DIR if it exists
300         if [ -e $TEST_REPORT_LOG_DIR ] ; then
301             if [ -f $TEST_REPORT_LOG_DIR ] ; then
302                 rm $TEST_REPORT_LOG_DIR
303             else
304                 rm -rf ${TEST_REPORT_LOG_DIR}
305             fi
306         fi
307         # create TEST_REPORT_LOG_DIR
308         mkdir -p $TEST_REPORT_LOG_DIR
309     fi
310 }
311
312 # verify basic vsperf functionality
313 function execute_vsperf_sanity() {
314     DATE_SUFFIX=$(date -u +"%Y-%m-%d_%H-%M-%S")
315     LOG_FILE="${LOG_FILE_PREFIX}_sanity_${DATE_SUFFIX}.log"
316     echo "Execution of VSPERF sanity checks:"
317     for PARAM in '--version' '--help' '--list-trafficgens' '--list-collectors' '--list-vswitches' '--list-fwdapps' '--list-vnfs' '--list-settings' '--list' '--integration --list'; do
318         echo -e "-------------------------------------------------------------------" >> $LOG_FILE
319         echo "$VSPERF_BIN $PARAM $CONF_FILE" >> $LOG_FILE
320         echo -e "-------------------------------------------------------------------" >> $LOG_FILE
321         $VSPERF_BIN $PARAM $CONF_FILE &>> $LOG_FILE
322         if $VSPERF_BIN $PARAM $CONF_FILE &>> $LOG_FILE ; then
323             printf "    %-70s %-6s\n" "$VSPERF_BIN $PARAM" "OK"
324         else
325             printf "    %-70s %-6s\n" "$VSPERF_BIN $PARAM" "FAILED"
326             EXIT=$EXIT_SANITY_TC_FAILED
327         fi
328         echo >> $LOG_FILE
329     done
330     echo "Sanity log file $LOG_FILE"
331     if [ $(($EXIT & $EXIT_SANITY_TC_FAILED)) -gt 0 ] ; then
332         echo "-------------------------------------------------------------------"
333         cat $LOG_FILE
334         echo "-------------------------------------------------------------------"
335     fi
336 }
337
338 # execute pylint to check code quality
339 function execute_vsperf_pylint_check() {
340     if ! ./check -b ; then
341         EXIT=$EXIT_PYLINT_FAILED
342     fi
343 }
344
345 # check and install required packages at nodes running VERIFY and MERGE jobs
346 function dependencies_check() {
347     . /etc/os-release
348     if [ $ID == "ubuntu" ] ; then
349         echo "Dependencies check"
350         echo "=================="
351         # install system packages
352         for PACKAGE in "python3-tk" "sysstat" "bc" ; do
353             if dpkg -s $PACKAGE &> /dev/null ; then
354                 printf "    %-70s %-6s\n" $PACKAGE "OK"
355             else
356                 printf "    %-70s %-6s\n" $PACKAGE "missing"
357                 sudo apt-get install -y $PACKAGE
358             fi
359         done
360         # install additional python packages into python environment
361         for PACKAGE in "pylint" ; do
362             if pip show $PACKAGE &> /dev/null ; then
363                 printf "    %-70s %-6s\n" $PACKAGE "OK"
364             else
365                 printf "    %-70s %-6s\n" $PACKAGE "missing"
366                 pip install $PACKAGE
367             fi
368         done
369         echo
370     fi
371 }
372
373 # configure hugepages
374 function configure_hugepages() {
375     sudo bash -c "echo 2048 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages"
376     sudo bash -c "echo 0 > /sys/devices/system/node/node1/hugepages/hugepages-2048kB/nr_hugepages"
377 }
378
379 # dump hugepages configuration
380 function hugepages_info() {
381     echo "-------------------------------------------------------------------"
382     head /sys/devices/system/node/node*/hugepages/hugepages*/*
383     echo "-------------------------------------------------------------------"
384 }
385
386 #
387 # main
388 #
389
390 echo
391
392 # enter workspace dir
393 cd $WORKSPACE
394
395 # create virtualenv if needed
396 if [ ! -e $VSPERFENV_DIR ] ; then
397     echo "Create VSPERF environment"
398     echo "========================="
399     virtualenv --python=python3 "$VSPERFENV_DIR"
400     echo
401 fi
402
403 # acivate and update virtualenv
404 echo "Update VSPERF environment"
405 echo "========================="
406 source "$VSPERFENV_DIR"/bin/activate
407 pip install -r ./requirements.txt
408 echo
409
410 # VERFIY&MERGE job specific - check if required packages are installed
411 dependencies_check
412
413 # initialization
414 initialize_logdir
415
416 # configure hugepages
417 configure_hugepages
418
419 # execute job based on passed parameter
420 case $1 in
421     "verify")
422         echo "================="
423         echo "VSPERF verify job"
424         echo "================="
425
426         execute_vsperf_pylint_check
427         terminate_vsperf
428         execute_vsperf_sanity
429         terminate_vsperf
430         execute_vsperf OVS_with_DPDK_and_vHost_User $1
431         terminate_vsperf
432         execute_vsperf OVS_vanilla $1
433
434         exit $EXIT
435         ;;
436     "merge")
437         echo "================"
438         echo "VSPERF merge job"
439         echo "================"
440
441         execute_pylint_check
442         terminate_vsperf
443         execute_vsperf_sanity
444         terminate_vsperf
445         execute_vsperf OVS_with_DPDK_and_vHost_User $1
446         terminate_vsperf
447         execute_vsperf OVS_vanilla $1
448
449         exit $EXIT
450         ;;
451     *)
452         echo "================"
453         echo "VSPERF daily job"
454         echo "================"
455
456         terminate_vsperf
457         execute_vsperf OVS_with_DPDK_and_vHost_User $1
458         terminate_vsperf
459         execute_vsperf OVS_vanilla $1
460         terminate_vsperf
461         execute_vsperf SRIOV $1
462         terminate_vsperf
463
464         generate_report
465
466         push_results_to_artifactory
467
468         cleanup
469
470         exit $EXIT
471         ;;
472 esac
473
474 exit $EXIT
475
476 #
477 # end
478 #