prepare for testing in native mode
[build.git] / vbuild-nightly.sh
1 #!/bin/bash
2 REVISION=$(echo '$Revision$' | sed -e 's,\$,,g' -e 's,^\w*:\s,,' )
3
4 COMMANDPATH=$0
5 COMMAND=$(basename $0)
6
7 # default values, tunable with command-line options
8 DEFAULT_FCDISTRO=f7
9 DEFAULT_PLDISTRO=planetlab
10 DEFAULT_PERSONALITY=linux32
11 DEFAULT_BASE="@DATE@--@PLDISTRO@-@FCDISTRO@-@PERSONALITY@"
12 DEFAULT_SVNPATH="http://svn.planet-lab.org/svn/build/trunk"
13
14 # NOTE: do not think we want to put email addresses into scripts
15 # that can be harvested by spambots. --mef
16 DEFAULT_MAILTO="onelab-build@one-lab.org"
17
18 # web publishing results
19 DEFAULT_WEBPATH="/build/@PLDISTRO@/"
20
21 # for the test part
22 TESTBUILDURL="http://build.one-lab.org/"
23 TESTBOX=onelab-test.inria.fr
24 TESTBOXSSH=root@onelab-test.inria.fr
25 TESTSVNPATH="http://svn.planet-lab.org/svn/tests/trunk/system/"
26 TESTSCRIPT=TestMain.py
27 ####################
28 # assuming vserver runs in UTC
29 DATE=$(date +'%Y.%m.%d')
30
31 # temporary - wrap a quick summary of suspicious stuff
32 # this is to focus on installation that go wrong
33 # use with care, a *lot* of other things can go bad as well
34 function summary () {
35     from=$1; shift
36     echo "******************** BEG SUMMARY" 
37     python - $from <<EOF
38 # read a full log and tries to extract the interesting stuff
39
40 import sys,re
41 m_show_line=re.compile(".* BEG (RPM|VSERVER).*|.*'boot'.*|\* .*")
42 m_installing_any=re.compile('\r  (Installing:[^\]]*]) ')
43 m_installing_err=re.compile('\r  (Installing:[^\]]*])(..+)')
44 m_installing_end=re.compile('Installed:.*')
45 m_installing_doc=re.compile(".*such file or directory for /usr/share/info.*")
46
47 def scan_log (filename):
48
49     try:
50         if filename=="-":
51             filename="stdin"
52             f=sys.stdin
53         else:
54             f=open(filename)
55         echo=False
56         for line in f.xreadlines():
57             if m_show_line.match(line):
58                 print line,
59             elif m_installing_err.match(line):
60                 (installing,error)=m_installing_err.match(line).groups()
61                 print installing
62                 print error
63                 echo=True
64             elif m_installing_end.match(line):
65                 echo=False
66             elif m_installing_any.match(line):
67                 if echo: 
68                     installing=m_installing_any.match(line).group(1)
69                     print installing
70                 echo=False
71             else:
72                 if echo: print line,
73         f.close()
74     except:
75         print 'Failed to analyze',filename
76
77 for arg in sys.argv[1:]:
78     scan_log(arg)
79 EOF
80     echo "******************** END SUMMARY" 
81 }
82
83
84 # Notify recipient of failure or success, manage various stamps 
85 function failure() {
86     set -x
87     WEBLOG=${WEBPATH}/${BASE}.log.txt
88     cp $LOG ${WEBLOG}
89     summary $LOG >> ${WEBLOG}
90     (echo -n "============================== $COMMAND: failure at " ; date ; tail -c 20k $WEBLOG) > ${WEBLOG}.ko
91     if [ -n "$MAILTO" ] ; then
92         tail -c 20k ${WEBPATH}/${BASE}.log.txt | mail -s "Failures for build ${BASE}" $MAILTO
93     fi
94     exit 1
95 }
96
97 function success () {
98     set -x
99     WEBLOG=${WEBPATH}/${BASE}.log.txt
100     cp $LOG ${WEBLOG}
101     summary $LOG >> ${WEBLOG}
102     touch ${WEBLOG}.ok
103     if [ -n "$MAILTO" ] ; then
104         (echo "$PLDISTRO ($BASE) build for $FCDISTRO completed on $(date)" ) | mail -s "Successfull build for ${BASE}" $MAILTO
105     fi
106     exit 0
107 }
108
109 # run in the vserver - do not manage success/failure, will be done from the root ctx
110 function build () {
111     set -x
112     set -e
113
114     echo -n "============================== Starting $COMMAND:build on "
115     date
116
117     cd /build
118   # if TAGSRELEASE specified : update PLDISTROTAGS with this tag
119     if [ -n "$TAGSRELEASE" ] ; then
120         svn up -r $TAGSRELEASE $PLDISTROTAGS
121     fi
122
123     show_env
124     
125     echo "Running make IN $(pwd)"
126     # stage1
127     make -C /build "${MAKEOPTS[@]}" PLDISTROTAGS=${PLDISTROTAGS} PLDISTRO=${PLDISTRO} "${MAKEVARS[@]}" stage1=true 
128     # versions
129     make -C /build "${MAKEOPTS[@]}" PLDISTROTAGS=${PLDISTROTAGS} PLDISTRO=${PLDISTRO} "${MAKEVARS[@]}" NIGHTLY_BASE=${BASE} versions
130     # actual stuff
131     make -C /build "${MAKEOPTS[@]}" PLDISTROTAGS=${PLDISTROTAGS} PLDISTRO=${PLDISTRO} "${MAKEVARS[@]}" $MAKETARGETS
132
133 }
134
135 # this was formerly run in the myplc-devel chroot but now is run in the root context,
136 # this is so that the .ssh config gets done manually, and once and for all
137 function runtest () {
138     set -x
139     set -e
140     trap failure ERR INT
141
142     echo -n "============================== Starting $COMMAND:runtest on $(date)"
143
144     ### the URL to the myplc package
145     rpm=$( (cd /vservers/$BASE/build/RPMS/i386 ; ls myplc-[0-9]*.rpm) )
146     if [ ${#rpm[@]} != 1 ] ; then
147         echo "$COMMAND: Cannot locate rpm for testing"
148         failure
149         exit 1
150     fi
151     rpms_url=${TESTBUILDURL}${PLDISTRO}/${BASE}/RPMS/
152     url=${TESTBUILDURL}${PLDISTRO}/${BASE}/RPMS/i386/${rpm}
153
154     # compute test directory name on test box
155     testdir=test-${BASE}
156     # clean it
157     ssh ${TESTBOXSSH} rm -rf ${testdir}
158     # check it out
159     ssh ${TESTBOXSSH} svn co ${TESTSVNPATH} ${testdir}
160     # store the myplc http url in the newly created test dir - for testing in chroot mode
161     echo ${url} | ssh ${TESTBOXSSH} "cat > ${testdir}/MYPLC-URL"
162     # store the build svn path in the newly created test dir - so it can perform myplc-init-vserver
163     echo ${SVNPATH} | ssh ${TESTBOXSSH} "cat > ${testdir}/BUILD-URL"
164     # store the rpms http url in the newly created test dir - for passing to myplc-init-vserver
165     echo ${rpms_url} | ssh ${TESTBOXSSH} "cat > ${testdir}/RPMS-URL"
166     # invoke test on testbox
167     ssh 2>&1 ${TESTBOXSSH} python -u ${testdir}/${TESTSCRIPT} ${url} 
168     # still missing - need to populate /var/www/html/install-rpms on the myplc
169         
170     if [ "$?" != 0 ] ; then
171         failure
172     fi
173     
174     echo -n "============================== End $COMMAND:runtest on $(date)"
175 }
176
177 function show_env () {
178     set +x
179     echo FCDISTRO=$FCDISTRO
180     echo PLDISTRO=$PLDISTRO
181     echo BASE=$BASE
182     echo SVNPATH=$SVNPATH
183     echo MAKEVARS="${MAKEVARS[@]}"
184     echo MAKEOPTS="${MAKEOPTS[@]}"
185     echo PLDISTROTAGS="$PLDISTROTAGS"
186     echo TAGSRELEASE="$TAGSRELEASE"
187     echo -n "(might be unexpanded)"
188     echo WEBPATH="$WEBPATH"
189     if [ -d /vservers ] ; then
190         echo PLDISTROTAGS="$PLDISTROTAGS"
191     else
192         echo "XXXXXXXXXXXXXXXXXXXX Contents of tags definition file /build/$PLDISTROTAGS"
193         cat /build/$PLDISTROTAGS
194         echo "XXXXXXXXXXXXXXXXXXXX end tags definition"
195     fi
196     set -x
197 }
198
199 function usage () {
200     echo "Usage: $COMMAND [option] make-targets"
201     echo "This is $REVISION"
202     echo "Supported options"
203     echo " -n dry-run : -n passed to make - vserver gets created though - no mail sent"
204     echo " -f fcdistro - defaults to $DEFAULT_FCDISTRO"
205     echo " -d pldistro - defaults to $DEFAULT_PLDISTRO"
206     echo " -p personality - defaults to $DEFAULT_PERSONALITY"
207     echo " -b base - defaults to $DEFAULT_BASE"
208     echo "    @NAME@ replaced as appropriate"
209     echo " -t pldistrotags - defaults to \${PLDISTRO}-tags.mk"
210     echo " -r tagsrelease - a release number that refers to PLDISTROTAGS - defaults to HEAD"
211     echo " -s svnpath - where to fetch the build module"
212     echo " -o : overwrite - re-run in base directory, do not create vserver"
213     echo " -m mailto"
214     echo " -a makevar=value - space in values are not supported"
215     echo " -w webpath - defaults to $DEFAULT_WEBPATH"
216     echo " -B : run build only"
217     echo " -T : run test only"
218     echo " -v : be verbose"
219     echo " -7 : uses weekday-@FCDISTRO@ as base"
220     exit 1
221 }
222
223 function main () {
224
225     set -e
226
227     # preserve arguments for passing them again later
228     declare -a argv
229     for arg in "$@"; do argv=(${argv[@]} "$arg") ; done
230     
231     # parse arguments
232     MAKEVARS=()
233     MAKEOPTS=()
234     DO_BUILD=true
235     DO_TEST=true
236     while getopts "nf:d:b:p:t:r:s:om:a:w:BTvh7" opt ; do
237         case $opt in
238             n) DRY_RUN="true" ; MAKEOPTS=(${MAKEOPTS[@]} -n) ;;
239             f) FCDISTRO=$OPTARG ;;
240             d) PLDISTRO=$OPTARG ;;
241             p) PERSONALITY=$OPTARG ;;
242             b) BASE=$OPTARG ;;
243             t) PLDISTROTAGS=$OPTARG ;;
244             r) TAGSRELEASE=$OPTARG ;;
245             s) SVNPATH=$OPTARG ;;
246             o) OVERWRITEMODE=true ;;
247             m) MAILTO=$OPTARG ;;
248             a) MAKEVARS=(${MAKEVARS[@]} "$OPTARG") ;;
249             w) WEBPATH=$OPTARG ;;
250             B) DO_TEST= ;;
251             T) DO_BUILD= ; OVERWRITEMODE=true ;;
252             v) set -x ;;
253             7) BASE="$(date +%a|tr A-Z a-z)-@FCDISTRO@" ;;
254             h|*) usage ;;
255         esac
256     done
257         
258     shift $(($OPTIND - 1))
259     MAKETARGETS="$@"
260     
261     # set defaults
262     [ -z "$FCDISTRO" ] && FCDISTRO=$DEFAULT_FCDISTRO
263     [ -z "$PLDISTRO" ] && PLDISTRO=$DEFAULT_PLDISTRO
264     [ -z "$PERSONALITY" ] && PERSONALITY=$DEFAULT_PERSONALITY
265     [ -z "$PLDISTROTAGS" ] && PLDISTROTAGS="${PLDISTRO}-tags.mk"
266     [ -z "$BASE" ] && BASE="$DEFAULT_BASE"
267     [ -z "$WEBPATH" ] && WEBPATH="$DEFAULT_WEBPATH"
268     [ -z "$SVNPATH" ] && SVNPATH="$DEFAULT_SVNPATH"
269
270     # NOTE: suggest that by default no email is sent and that the user
271     # should explicitly invoke this script with the -m arg to pass in
272     # the appropriate email address. --mef
273     if [ "$PLDISTRO" = "onelab" ] ; then
274         [ -z "$MAILTO" ] && MAILTO="$DEFAULT_MAILTO"
275     fi
276     [ -n "$DRY_RUN" ] && MAILTO=""
277         
278     ### set BASE from DISTRO, if unspecified
279     sedargs="-e s,@DATE@,${DATE},g -e s,@FCDISTRO@,${FCDISTRO},g -e s,@PLDISTRO@,${PLDISTRO},g -e s,@PERSONALITY@,${PERSONALITY},g"
280     BASE=$(echo ${BASE} | sed $sedargs)
281     WEBPATH=$(echo ${WEBPATH} | sed $sedargs)
282
283     if [ ! -d /vservers ] ; then
284         # in the vserver
285         echo "==================== Within vserver BEG $(date)"
286         build
287         echo "==================== Within vserver END $(date)"
288
289     else
290         trap failure ERR INT
291         # we run in the root context : 
292         # (*) create or check for the vserver to use
293         # (*) copy this command in the vserver
294         # (*) invoke it
295         
296         if [ -n "$OVERWRITEMODE" ] ; then
297             ### Re-use a vserver (finish an unfinished build..)
298             if [ ! -d /vservers/${BASE} ] ; then
299                 echo $COMMAND : cannot find vserver $BASE
300                 exit 1
301             fi
302             # manage LOG - beware it might be a symlink so nuke it first
303             LOG=/vservers/${BASE}.log.txt
304             rm -f $LOG
305             exec > $LOG 2>&1
306             set -x
307             echo "XXXXXXXXXX $COMMAND: using existing vserver $BASE" $(date)
308             show_env
309             # update build
310             vserver ${BASE} exec svn update /build
311         else
312             # create vserver: check it does not exist yet
313             i=
314             while [ -d /vservers/${BASE}${i} ] ; do
315                 # we name subsequent builds <base>-n<i> so the logs and builds get sorted properly
316                 [ -z ${i} ] && BASE=${BASE}-n
317                 i=$((${i}+1))
318                 if [ $i -gt 100 ] ; then
319                     echo "$COMMAND: Failed to create build vserver /vservers/${BASE}${i}"
320                     exit 1
321                 fi
322             done
323             BASE=${BASE}${i}
324             # need update
325             # manage LOG - beware it might be a symlink so nuke it first
326             LOG=/vservers/${BASE}.log.txt
327             rm -f $LOG
328             exec > $LOG 2>&1 
329             set -x
330             echo "XXXXXXXXXX $COMMAND: creating vserver $BASE" $(date)
331             show_env
332
333             ### extract the whole build - much simpler
334             tmpdir=/tmp/$COMMAND-$$
335             svn export $SVNPATH $tmpdir
336             # Create vserver
337             cd $tmpdir
338             ./vbuild-init-vserver.sh -f ${FCDISTRO} -d ${PLDISTRO} -p ${PERSONALITY} ${BASE}
339             # cleanup
340             cd -
341             rm -rf $tmpdir
342             # Extract build again - in the vserver
343             vserver ${BASE} exec svn checkout ${SVNPATH} /build
344         fi
345         echo "XXXXXXXXXX $COMMAND: preparation of vserver $BASE done" $(date)
346
347         # The log inside the vserver contains everything
348         LOG2=/vservers/${BASE}/log.txt
349         (echo "==================== BEG VSERVER Transcript of vserver creation" ; \
350          cat $LOG ; \
351          echo "==================== END VSERVER Transcript of vserver creation" ; \
352          echo "xxxxxxxxxx Messing with logs, symlinking $LOG2 to $LOG" ) >> $LOG2
353         ### not too nice : nuke the former log, symlink it to the new one
354         rm $LOG; ln -s $LOG2 $LOG
355         LOG=$LOG2
356         # redirect log again
357         exec >> $LOG 2>&1 
358
359         if [ -n "$DO_BUILD" ] ; then 
360
361             cp $COMMANDPATH /vservers/${BASE}/build/
362
363             # invoke this command in the vserver for building (-T)
364             vserver ${BASE} exec chmod +x /build/$COMMAND
365             vserver ${BASE} exec /build/$COMMAND "${argv[@]}" -b "${BASE}"
366         fi
367
368         # publish to the web so runtest can find them
369         rm -rf $WEBPATH/$BASE ; mkdir -p $WEBPATH/$BASE/{RPMS,SRPMS}
370         rsync --archive --delete --verbose /vservers/$BASE/build/RPMS/ $WEBPATH/$BASE/RPMS/
371         rsync --archive --delete --verbose /vservers/$BASE/build/SRPMS/ $WEBPATH/$BASE/SRPMS/
372         
373         if [ -n "$DO_TEST" ] ; then 
374             runtest
375         fi
376
377         success 
378         
379     fi
380
381 }  
382
383 ##########
384 main "$@"