2 # SPDX-License-Identifier: GPL-2.0+
4 # Run a series of tests on remote systems under KVM.
6 # Usage: kvm-remote.sh "systems" [ <kvm.sh args> ]
7 # kvm-remote.sh "systems" /path/to/old/run [ <kvm-again.sh args> ]
9 # Copyright (C) 2021 Facebook, Inc.
11 # Authors: Paul E. McKenney <paulmck@kernel.org>
16 if ! test -d tools/testing/selftests/rcutorture/bin
18 echo $scriptname must be run from top-level directory of kernel source tree.
22 KVM="`pwd`/tools/testing/selftests/rcutorture"; export KVM
23 PATH=${KVM}/bin:$PATH; export PATH
26 starttime="`get_starttime`"
31 echo $scriptname: Empty list of systems will go nowhere good, giving up.
37 # T: /tmp/kvm-remote.sh.$$
38 # resdir: /tmp/kvm-remote.sh.$$/res
39 # rundir: /tmp/kvm-remote.sh.$$/res/$ds ("-remote" suffix)
40 # oldrun: `pwd`/tools/testing/.../res/$otherds
43 # TD: kvm-remote.sh.$$
44 # ds: yyyy.mm.dd-hh.mm.ss-remote
52 ds=`date +%Y.%m.%d-%H.%M.%S`-remote
54 echo Results directory: $rundir
55 echo $scriptname $args
56 if echo $1 | grep -q '^--'
58 # Fresh build. Create a datestamp unless the caller supplied one.
59 datestamp="`echo "$@" | awk -v ds="$ds" '{
60 for (i = 1; i < NF; i++) {
61 if ($i == "--datestamp") {
67 print "--datestamp " ds;
69 kvm.sh --remote "$@" $datestamp --buildonly > $T/kvm.sh.out 2>&1
73 echo $scriptname: kvm.sh failed exit code $?
77 oldrun="`grep -m 1 "^Results directory: " $T/kvm.sh.out | awk '{ print $3 }'`"
78 touch "$oldrun/remote-log"
79 echo $scriptname $args >> "$oldrun/remote-log"
80 echo | tee -a "$oldrun/remote-log"
81 echo " ----" kvm.sh output: "(`date`)" | tee -a "$oldrun/remote-log"
82 cat $T/kvm.sh.out | tee -a "$oldrun/remote-log"
83 # We are going to run this, so remove the buildonly files.
84 rm -f "$oldrun"/*/buildonly
85 kvm-again.sh $oldrun --dryrun --remote --rundir "$rundir" > $T/kvm-again.sh.out 2>&1
89 echo $scriptname: kvm-again.sh failed exit code $? | tee -a "$oldrun/remote-log"
90 cat $T/kvm-again.sh.out | tee -a "$oldrun/remote-log"
96 if ! echo $oldrun | grep -q '^/'
98 oldrun="`pwd`/$oldrun"
101 touch "$oldrun/remote-log"
102 echo $scriptname $args >> "$oldrun/remote-log"
103 kvm-again.sh "$oldrun" "$@" --dryrun --remote --rundir "$rundir" > $T/kvm-again.sh.out 2>&1
107 echo $scriptname: kvm-again.sh failed exit code $? | tee -a "$oldrun/remote-log"
108 cat $T/kvm-again.sh.out | tee -a "$oldrun/remote-log"
111 cp -a "$rundir" "$KVM/res/"
112 oldrun="$KVM/res/$ds"
114 echo | tee -a "$oldrun/remote-log"
115 echo " ----" kvm-again.sh output: "(`date`)" | tee -a "$oldrun/remote-log"
116 cat $T/kvm-again.sh.out
117 echo | tee -a "$oldrun/remote-log"
118 echo Remote run directory: $rundir | tee -a "$oldrun/remote-log"
119 echo Local build-side run directory: $oldrun | tee -a "$oldrun/remote-log"
121 # Create the kvm-remote-N.sh scripts in the bin directory.
122 awk < "$rundir"/scenarios -v dest="$T/bin" -v rundir="$rundir" '
126 fn = dest "/kvm-remote-" n ".sh"
128 for (i = 2; i <= NF; i++)
129 scenarios = scenarios " " $i;
130 print "kvm-test-1-run-batch.sh" scenarios > fn;
131 print "rm " rundir "/remote.run" >> fn;
133 chmod +x $T/bin/kvm-remote-*.sh
134 ( cd "`dirname $T`"; tar -chzf $T/binres.tgz "$TD/bin" "$TD/res" )
136 # Check first to avoid the need for cleanup for system-name typos
139 ncpus="`ssh $i getconf _NPROCESSORS_ONLN 2> /dev/null`"
140 echo $i: $ncpus CPUs " " `date` | tee -a "$oldrun/remote-log"
144 echo System $i unreachable, giving up. | tee -a "$oldrun/remote-log"
145 exit 4 | tee -a "$oldrun/remote-log"
149 # Download and expand the tarball on all systems.
152 echo Downloading tarball to $i `date` | tee -a "$oldrun/remote-log"
153 cat $T/binres.tgz | ssh $i "cd /tmp; tar -xzf -"
157 echo Unable to download $T/binres.tgz to system $i, giving up. | tee -a "$oldrun/remote-log"
158 exit 10 | tee -a "$oldrun/remote-log"
162 # Function to check for presence of a file on the specified system.
163 # Complain if the system cannot be reached, and retry after a wait.
164 # Currently just waits forever if a machine disappears.
166 # Usage: checkremotefile system pathname
173 ssh $1 "test -f \"$2\""
175 if test "$ret" -ne 255
179 echo " ---" ssh failure to $1 checking for file $2, retry after $sleeptime seconds. `date`
184 # Function to start batches on idle remote $systems
186 # Usage: startbatches curbatch nbatches
188 # Batches are numbered starting at 1. Returns the next batch to start.
189 # Be careful to redirect all debug output to FD 2 (stderr).
195 # Each pass through the following loop examines one system.
198 if test "$curbatch" -gt "$nbatches"
200 echo $((nbatches + 1))
203 if checkremotefile "$i" "$resdir/$ds/remote.run" 1>&2
205 continue # System still running last test, skip.
207 ssh "$i" "cd \"$resdir/$ds\"; touch remote.run; PATH=\"$T/bin:$PATH\" nohup kvm-remote-$curbatch.sh > kvm-remote-$curbatch.sh.out 2>&1 &" 1>&2
211 echo ssh $i failed: exitcode $ret 1>&2
214 echo " ----" System $i Batch `head -n $curbatch < "$rundir"/scenarios | tail -1` `date` 1>&2
215 curbatch=$((curbatch + 1))
220 # Launch all the scenarios.
221 nbatches="`wc -l "$rundir"/scenarios | awk '{ print $1 }'`"
223 while test "$curbatch" -le "$nbatches"
225 startbatches $curbatch $nbatches > $T/curbatch 2> $T/startbatches.stderr
226 curbatch="`cat $T/curbatch`"
227 if test -s "$T/startbatches.stderr"
229 cat "$T/startbatches.stderr" | tee -a "$oldrun/remote-log"
231 if test "$curbatch" -le "$nbatches"
236 echo All batches started. `date`
238 # Wait for all remaining scenarios to complete and collect results.
241 while checkremotefile "$i" "$resdir/$ds/remote.run"
245 ( cd "$oldrun"; ssh $i "cd $rundir; tar -czf - kvm-remote-*.sh.out */console.log */kvm-test-1-run*.sh.out */qemu_pid */qemu-retval; rm -rf $T > /dev/null 2>&1" | tar -xzf - )
248 ( kvm-end-run-stats.sh "$oldrun" "$starttime"; echo $? > $T/exitcode ) | tee -a "$oldrun/remote-log"
249 exit "`cat $T/exitcode`"