CSIT-1327 Migrate from vpp-dkms-dpdk to vpp-ext-deps
[csit.git] / resources / libraries / bash / function / per_patch.sh
1 # Copyright (c) 2018 Cisco and/or its affiliates.
2 # Licensed under the Apache License, Version 2.0 (the "License");
3 # you may not use this file except in compliance with the License.
4 # You may obtain a copy of the License at:
5 #
6 #     http://www.apache.org/licenses/LICENSE-2.0
7 #
8 # Unless required by applicable law or agreed to in writing, software
9 # distributed under the License is distributed on an "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 # See the License for the specific language governing permissions and
12 # limitations under the License.
13
14 set -exuo pipefail
15
16 # This library defines functions used mainly by "per_patch_perf.sh" entry script.
17 # Generally, the functions assume "common.sh" library has been sourced already.
18
19 # Keep functions ordered alphabetically, please.
20
21 # TODO: Add a link to bash style guide.
22
23
24 function build_vpp_ubuntu_amd64 () {
25
26     set -exuo pipefail
27
28     # TODO: Make sure whether this works on other distros/archs too.
29
30     # Arguments:
31     # - ${1} - String identifier for echo, can be unset.
32     # Variables read:
33     # - VPP_DIR - Path to existing directory, parent to accessed directories.
34     # Directories updated:
35     # - ${VPP_DIR} - Whole subtree, many files (re)created by the build process.
36     # - ${VPP_DIR}/build-root - Final build artifacts for CSIT end up here.
37     # - ${VPP_DIR}/dpdk - The dpdk artifact is built, but moved to build-root/.
38     # Functions called:
39     # - die - Print to stderr and exit, defined in common.sh
40
41     cd "${VPP_DIR}" || die "Change directory command failed."
42     echo 'Building using "make build-root/vagrant/build.sh"'
43     # TODO: Do we want to support "${DRYRUN}" == "True"?
44     make UNATTENDED=yes install-dep || die "Make install-dep failed."
45     # The per_patch script calls this function twice, first for the new commit,
46     # then for its parent commit. On Jenkins, no dpdk is installed at first,
47     # locally it might have been installed. New dpdk is installed second call.
48     # If make detects installed vpp-ext-deps with matching version,
49     # it skips building vpp-ext-deps entirely, but we need that file.
50     # On the other hand, if parent uses different dpdk version,
51     # The new vpp-ext-deps is built, but the old one is not removed
52     # from the build directory if present. (Further functions move both,
53     # and during test dpkg decides on its own which version gets installed.)
54     # As per_patch is too dumb (yet) to detect any of that,
55     # the only safe solution is to clean build directory and force rebuild.
56     # TODO: Make this function smarter and skip DPDK rebuilds if possible.
57     cmd=("dpkg-query" "--showformat='$${Version}'" "--show" "vpp-ext-deps")
58     installed_deb_ver="$(sudo "${cmd[@]}" || true)"
59     if [[ -n "${installed_deb_ver}" ]]; then
60         sudo dpkg --purge "vpp-ext-deps" || {
61             die "DPDK package uninstalation failed."
62         }
63     fi
64     make UNATTENDED=yes install-ext-deps || {
65         die "Make install-ext-deps failed."
66     }
67     build-root/vagrant/"build.sh" || die "Vagrant VPP build script failed."
68     # CSIT also needs the external dependency artifacts, which is not in
69     # build-root.
70     mv -v "build/external/vpp-ext-deps"*".deb" "build-root"/ || {
71         die "*.deb move failed."
72     }
73
74     echo "*******************************************************************"
75     echo "* VPP ${1-} BUILD SUCCESSFULLY COMPLETED" || {
76         die "Argument not found."
77     }
78     echo "*******************************************************************"
79 }
80
81
82 function compare_test_results () {
83
84     set -exuo pipefail
85
86     # Variables read:
87     # - VPP_DIR - Path to directory with VPP git repo (at least built parts).
88     # - ARCHIVE_DIR - Path to where robot result files are created in.
89     # - PYTHON_SCRIPTS_DIR - Path to directory holding comparison utility.
90     # Directories recreated:
91     # - csit_parent - Sibling to csit directory, for holding results
92     #   of parent build.
93     # Functions called:
94     # - die - Print to stderr and exit, defined in common.sh
95     # - parse_bmrr_results - See definition in this file.
96     # Exit code:
97     # - 0 - If the comparison utility sees no regression (nor data error).
98     # - 1 - If the comparison utility sees a regression (or data error).
99
100     cd "${VPP_DIR}" || die "Change directory operation failed."
101     rm -rf "csit_parent" || die "Remove operation failed."
102     mkdir -p "csit_parent" || die "Directory creation failed."
103     for filename in "output.xml" "log.html" "report.html"; do
104         mv "${ARCHIVE_DIR}/${filename}" "csit_parent/${filename}" || {
105             die "Attempt to move '${filename}' failed."
106         }
107     done
108     parse_bmrr_results "csit_parent" || {
109         die "The function should have died on error."
110     }
111
112     # Reusing CSIT main virtualenv.
113     pip install -r "${PYTHON_SCRIPTS_DIR}/perpatch_requirements.txt" || {
114         die "Perpatch Python requirements installation failed."
115     }
116     python "${PYTHON_SCRIPTS_DIR}/compare_perpatch.py"
117     # The exit code determines the vote result.
118 }
119
120
121 function download_builds () {
122
123     set -exuo pipefail
124
125     # This is mostly useful only for Sandbox testing, to avoid recompilation.
126     #
127     # Arguments:
128     # - ${1} - URL to download VPP builds from.
129     # Variables read:
130     # - VPP_DIR - Path to WORKSPACE, parent of created directories.
131     # - DOWNLOAD_DIR - Path to directory pybot takes the build to test from.
132     # Directories created:
133     # - archive - Ends up empty, not to be confused with ${ARCHIVE_DIR}.
134     # - build_new - Holding built artifacts of the patch under test (PUT).
135     # - built_parent - Holding built artifacts of parent of PUT.
136     # - csit_new - (Re)set to a symlink to archive robot results on failure.
137     # Functions called:
138     # - die - Print to stderr and exit, defined in common.sh
139
140     cd "${VPP_DIR}" || die "Change directory operation failed."
141     rm -rf "build-root" "build_parent" "build_new" "archive" "csit_new" || {
142         die "Directory removal failed."
143     }
144     wget -N --progress=dot:giga "${1}" || die "Wget download failed."
145     unzip "archive.zip" || die "Archive extraction failed."
146     mv "archive/build_parent" ./ || die "Move operation failed."
147     mv "archive/build_new" ./ || die "Move operation failed."
148     cp -r "build_new"/*".deb" "${DOWNLOAD_DIR}" || {
149         die "Copy operation failed."
150     }
151     # Create symlinks so that if job fails on robot, results can be archived.
152     ln -s "${ARCHIVE_DIR}" "csit_new" || die "Symbolic link creation failed."
153 }
154
155
156 function parse_bmrr_results () {
157
158     set -exuo pipefail
159
160     # Currently "parsing" is just two greps.
161     # TODO: Re-use PAL parsing code, make parsing more general and centralized.
162     #
163     # Arguments:
164     # - ${1} - Path to (existing) directory holding robot output.xml result.
165     # Files read:
166     # - output.xml - From argument location.
167     # Files updated:
168     # - results.txt - (Re)created, in argument location.
169     # Functions called:
170     # - die - Print to stderr and exit, defined in common.sh
171
172     rel_dir="$(readlink -e "${1}")" || die "Readlink failed."
173     in_file="${rel_dir}/output.xml"
174     out_file="${rel_dir}/results.txt"
175
176     # TODO: Do we need to check echo exit code explicitly?
177     echo "Parsing ${in_file} putting results into ${out_file}"
178     echo "TODO: Re-use parts of PAL when they support subsample test parsing."
179
180     pattern='Maximum Receive Rate trial results in packets'
181     pattern+=' per second: .*\]</status>'
182     grep -o "${pattern}" "${in_file}" | grep -o '\[.*\]' > "${out_file}" || {
183         die "Some parsing grep command has failed."
184     }
185 }
186
187
188 function prepare_build_parent () {
189
190     set -exuo pipefail
191
192     # Variables read:
193     # - VPP_DIR - Path to existing directory, parent to accessed directories.
194     # Directories read:
195     # - build-root - Existing directory with built VPP artifacts (also DPDK).
196     # Directories updated:
197     # - ${VPP_DIR} - A local git repository, parent commit gets checked out.
198     # - build_new - Old contents removed, content of build-root copied here.
199     # Functions called:
200     # - die - Print to stderr and exit, defined in common.sh
201
202     cd "${VPP_DIR}" || die "Change directory operation failed."
203     rm -rf "build_new" || die "Remove operation failed."
204     mkdir -p "build_new" || die "Directory creation failed."
205     mv "build-root"/*".deb" "build_new"/ || die "Move operation failed."
206     # The previous build could have left some incompatible leftovers,
207     # e.g. DPDK artifacts of different version.
208     # "make -C dpdk clean" does not actually remove such .deb file.
209     # Also, there usually is a copy of dpdk artifact in build-root.
210     git clean -dffx "dpdk"/ "build-root"/ || die "Git clean operation failed."
211     # Finally, check out the parent commit.
212     git checkout HEAD~ || die "Git checkout operation failed."
213     # Display any other leftovers.
214     git status || die "Git status operation failed."
215 }
216
217
218 function prepare_test_new () {
219
220     set -exuo pipefail
221
222     # Variables read:
223     # - VPP_DIR - Path to existing directory, parent of accessed directories.
224     # - DOWNLOAD_DIR - Path to directory where Robot takes builds to test from.
225     # - ARCHIVE_DIR - Path to where robot result files are created in.
226     # Directories read:
227     # - build-root - Existing directory with built VPP artifacts (also DPDK).
228     # Directories updated:
229     # - build_parent - Old directory removed, build-root moved to become this.
230     # - ${DOWNLOAD_DIR} - Old content removed, files from build_new copied here.
231     # - csit_new - Currently a symlink to to archive robot results on failure.
232     # Functions called:
233     # - die - Print to stderr and exit, defined in common.sh
234
235     cd "${VPP_DIR}" || die "Change directory operationf failed."
236     rm -rf "build_parent" "csit_new" "${DOWNLOAD_DIR}"/* || die "Remove failed."
237     mkdir -p "build_parent" || die "Directory creation operation failed."
238     mv "build-root"/*".deb" "build_parent"/ || die "Move operation failed."
239     cp "build_new"/*".deb" "${DOWNLOAD_DIR}" || die "Copy operation failed."
240     # Create symlinks so that if job fails on robot, results can be archived.
241     ln -s "${ARCHIVE_DIR}" "csit_new" || die "Symbolic link creation failed."
242 }
243
244
245 function prepare_test_parent () {
246
247     set -exuo pipefail
248
249     # Variables read:
250     # - VPP_DIR - Path to existing directory, parent of accessed directories.
251     # - CSIT_DIR - Path to existing root of local CSIT git repository.
252     # - ARCHIVE_DIR and DOWNLOAD_DIR - Paths to directories to update.
253     # Directories read:
254     # - build_parent - Build artifacts (to test next) are copied from here.
255     # Directories updated:
256     # - csit_new - Deleted, then recreated and latest robot results copied here.
257     # - ${CSIT_DIR} - Subjected to git reset and git clean.
258     # - ${ARCHIVE_DIR} - Created if not existing (if deleted by git clean).
259     # - ${DOWNLOAD_DIR} - Created after git clean, parent build copied here.
260     # - csit_parent - Currently a symlink to csit/ to archive robot results.
261     # Functions called:
262     # - die - Print to stderr and exit, defined in common.sh
263     # - parse_bmrr_results - See definition in this file.
264
265     cd "${VPP_DIR}" || die "Change directory operation failed."
266     rm -rf "csit_new" "csit_parent" || die "Remove operation failed."
267     mkdir -p "csit_new" || die "Create directory operation failed."
268     for filename in "output.xml" "log.html" "report.html"; do
269         mv "${ARCHIVE_DIR}/${filename}" "csit_new/${filename}" || {
270             die "Move operation of '${filename}' failed."
271         }
272     done
273     parse_bmrr_results "csit_new" || {
274         die "The function should have died on error."
275     }
276
277     pushd "${CSIT_DIR}" || die "Change directory operation failed."
278     git reset --hard HEAD || die "Git reset operation failed."
279     git clean -dffx || die "Git clean operation failed."
280     popd || die "Change directory operation failed."
281     mkdir -p "${ARCHIVE_DIR}" "${DOWNLOAD_DIR}" || die "Dir creation failed."
282
283     cp "build_parent"/*".deb" "${DOWNLOAD_DIR}"/ || die "Copy failed."
284     # Create symlinks so that if job fails on robot, results can be archived.
285     ln -s "${ARCHIVE_DIR}" "csit_parent" || die "Symlink creation failed."
286 }
287
288
289 function set_perpatch_dut () {
290
291     set -exuo pipefail
292
293     # Variables set:
294     # - DUT - CSIT test/ subdirectory containing suites to execute.
295
296     # TODO: Detect DUT from job name, when we have more than just VPP perpatch.
297
298     DUT="vpp"
299 }
300
301
302 function set_perpatch_vpp_dir () {
303
304     set -exuo pipefail
305
306     # Variables read:
307     # - CSIT_DIR - Path to existing root of local CSIT git repository.
308     # Variables set:
309     # - VPP_DIR - Path to existing root of local VPP git repository.
310     # Functions called:
311     # - die - Print to stderr and exit, defined in common.sh
312
313     # In perpatch, CSIT is cloned inside VPP clone.
314     VPP_DIR="$(readlink -e "${CSIT_DIR}/..")" || die "Readlink failed."
315 }