#!/bin/sh # # Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation. # # This program is distributed in the hope that it would be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write the Free Software Foundation, # Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # # automatic qa system. 31/08/00 dxm@sgi.com # # Usage: auto_qa start-state [stop-state] # Do auto_qa from start-state up to stop-state inclusive # or if no stop-state given then do it until reach "done" state. # _log() { echo "$*" >&2 echo "$*" >> $LOG sync } _fail() { if [ "$started" = "1" ] then echo "auto-qa stopped" | wall started=0 fi _log "$*" # send special email if a cron'd qa run fails case $state in cron*) mail -s "XFS QA status report" $EMAIL < $LOG 2>&1 ;; esac status=1 exit 1 } _get_kernel_version() { [ -x "$KWORKAREA" ] || return [ -r "$KWORKAREA/Makefile" ] \ || _fail "can't read kernel makefile $KWORKAREA/Makefile" eval `awk ' BEGIN { FS = "[ \t=]+" } /^VERSION =/ { a=$2 } /^PATCHLEVEL =/ { b=$2 } /^SUBLEVEL =/ { c=$2 } /^EXTRAVERSION =/ { d=$2 } END { print "VERSION=" a "." b "." c d " ; SVERSION=" a "." b "." c } ' < $KWORKAREA/Makefile` } # this should be constant ROOT="$HOME/qa" HOST=`hostname -s` if [ ! -z "$CVSROOT" ]; then export WORKAREA="$ROOT/xfs-cmds" else [ -z "$WORKAREA" ] && export WORKAREA="$ROOT/xfs-cmds" fi export PATH="/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin/ptools:/usr/local/bin" STATE=$ROOT/qa.state QADIR="$WORKAREA/xfstests" SUDO="su -c" CONFIG="$ROOT/$HOST.config" COMMON_CONFIG="$QADIR/common.config" SH="/bin/sh" LOG="$ROOT/qa.log" # do some cleanup on exit _cleanup() { umount $SCRATCH_DEV &> /dev/null umount $TEST_DEV &> /dev/null if [ "$started" = 1 ] then echo "auto-qa stopped" | wall started=0 fi } status=1 trap "_cleanup; exit \$status" 0 1 2 3 15 # clean exit _success() { status=0 exit 0 } _get_state() { state=`cat $STATE` } _set_state() { echo $1 > $STATE _get_state } _change_state() { new=$1 # if have state XXXX-state then preserve XXXX-newstate case $state in *-*) case $new in *-*) _set_state $new ;; *) _set_state `echo $state | sed "s/-.*$/-$new/"` ;; esac ;; *) _set_state $new ;; esac } _sudo() { $ROOT/su -c "$*" < /dev/null ;# HACK - we need a hacked su at the mo } _restart() { exec $ROOT/su -c "(shutdown -r now \"auto-qa rebooting\" )&" < /dev/null } _update_workarea() { if [ -z "$CVSROOT" ]; then _log " *** p_tupdate" cd "$1" WORKAREA="$1" p_tupdate 2>&1 \ || _fail " !!! p_tupdate failed" _log " *** non-trunk files" cd "$1" WORKAREA="$1" p_list -c 2>&1 \ || _fail " !!! p_list failed" else _log " *** cvs update" cd "$1" cvs -z3 update -d fi } _test_mkfs_xfs() { TEST_OPTIONS="" [ "$USE_EXTERNAL" = yes -a ! -z "$TEST_RTDEV" ] && \ TEST_OPTIONS="$TEST_OPTIONS -rrtdev=$TEST_RTDEV" [ "$USE_EXTERNAL" = yes -a ! -z "$TEST_LOGDEV" ] && \ TEST_OPTIONS="$TEST_OPTIONS -llogdev=$TEST_LOGDEV" _sudo /sbin/mkfs.xfs -f $TEST_OPTIONS $MKFS_OPTIONS $* $TEST_DEV mkfs_status=$? if [ "$USE_BIG_LOOPFS" = yes ]; then [ -z "$RETAIN_AG_BYTES" ] && RETAIN_AG_BYTES=0 _sudo $QADIR/tools/ag-wipe -q -r $RETAIN_AG_BYTES $TEST_DEV fi return $mkfs_status } _test_mount() { TEST_OPTIONS="" [ "$USE_EXTERNAL" = yes -a ! -z "$TEST_RTDEV" ] && \ TEST_OPTIONS="$TEST_OPTIONS -ortdev=$TEST_RTDEV" [ "$USE_EXTERNAL" = yes -a ! -z "$TEST_LOGDEV" ] && \ TEST_OPTIONS="$TEST_OPTIONS -ologdev=$TEST_LOGDEV" _sudo mount -t xfs $TEST_OPTIONS $MOUNT_OPTIONS $* $TEST_DEV $TEST_DIR } _i386_install() { _sudo cp -f "$KWORKAREA/arch/i386/boot/bzImage" "$IMAGE" 2>&1 \ || _fail " !!! install kernel failed" _sudo cp -f "$KWORKAREA/System.map" "$SYSTEMMAP" 2>&1 \ || _fail " !!! install kernel failed" if [ -z "$KMODULES" -o "$KMODULES" = yes ]; then _sudo make EXTRAVERSION=-$EXTRA modules_install 2>&1 \ || _fail " !!! install modules failed" fi if [ -z "$KINSTALL" -o "$KINSTALL" = lilo ]; then _log " *** reinit lilo" _sudo /sbin/lilo 2>&1 \ || _fail " !!! reinit lilo failed" fi } _i386_restart() { if [ -z "$KINSTALL" -o "$KINSTALL" = lilo ]; then _sudo /sbin/lilo -R $EXTRA $KERNEL_OPTIONS 2>&1 \ || _fail " !!! lilo failed" fi } _ia64_install() { echo not yet implemented } _ia64_restart() { echo not yet implemented } _check_kernel() { [ -d "$KWORKAREA" ] || _fail " !!! QA kernel workarea \"$KWORKAREA\" not found" [ -r "$CONFIG" ] || _fail " !!! Can't read config file $CONFIG" } _log "*** XFS QA (`date`)" _get_state # check preconditions for starting state case $1 in cron-init) case $state in *done) ;; *) _fail " !!! cron-init while not in \"*done\" state" ;; esac ;; cron-restarted) # we don't auto restart after reboot, but cron the restart # to happen a bit later - it's much easier and safer that way if [ "$state" != "cron-restarted" ] then _fail " !!! cron-restarted while not in \"cron-restarted\" state" fi ;; esac [ -n "$1" ] && _set_state $1 [ -n "$2" ] && stop_state=$2 [ "$UID" -eq 0 ] && _fail " !!! QA most be run as a normal user" [ -d "$ROOT" ] || _fail " !!! QA root \"$ROOT\" not found" [ -d "$WORKAREA" ] || _fail " !!! QA workarea \"$WORKAREA\" not found" cd $QADIR . "$COMMON_CONFIG" || _fail " !!! Couldn't source $COMMON_CONFIG" _get_kernel_version IMAGE="$BOOT/vmlinuz-$EXTRA" SYSTEMMAP="$BOOT/System.map-$VERSION-$EXTRA" MODULES="/lib/modules/$SVERSION" cd $ROOT started=1 echo "auto-qa started" | wall while true do _get_state _log " *** state $state start (`date`)" _log " (user=$USER, host=$HOST)" new_state="" start_state=$state case $state in *init) echo "" > $ROOT/qa.log echo "" > $ROOT/qa.full _log "******************************************************" _log "QA init $VERSION (`date`)" _log "******************************************************" new_state="updatetools" ;; *updatetools) _update_workarea "$WORKAREA" new_state="cleantools" ;; *cleantools) # we need to configure or else we might fail to clean for pkg in attr acl xfsprogs dmapi xfsdump xfstests do [ -d $WORKAREA/$pkg ] || continue cd $WORKAREA/$pkg _log " *** clean $pkg tools" make realclean 2>&1 \ || _fail " !!! clean $pkg failed" done new_state="buildtools" ;; *buildtools) _log " *** build and install tools" for pkg in attr acl xfsprogs dmapi xfsdump xfstests do [ -d $WORKAREA/$pkg ] || continue cd $WORKAREA/$pkg # use e-fence - but this will only take effect on configure make configure 2>&1 \ || _fail " !!! configure $pkg failed" make default 2>&1 \ || _fail " !!! build $pkg failed" _sudo make install install-dev 2>&1 \ || _fail " !!! install $pkg failed" # attr and acl now have install-lib targets as well [ "$pkg" = "attr" -o "$pkg" = "acl" ] || continue _sudo make install-lib 2>&1 \ || _fail " !!! install $pkg failed" done new_state="updatekernel" ;; *updatekernel) _check_kernel _update_workarea "$KWORKAREA" new_state="cleankernel" ;; *cleankernel) _check_kernel _log " *** clean kernel" cd "$KWORKAREA" make mrproper 2>&1 \ || _fail " !!! clean kernel failed" _log " *** install configuration file" cp -f $CONFIG "$KWORKAREA/.config" 2>&1 \ || _fail " !!! failed to install config" _log " *** remove version file" rm -f include/linux/version.h 2>&1 \ || _fail " !!! failed to clean version" new_state="reconfig" ;; *reconfig) _check_kernel _log " *** reconfig kernel" # we better start from scratch if this fails _change_state "cleankernel" cd "$KWORKAREA" # we want to use default options for any new config options. echo -e "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n" | \ make EXTRAVERSION=-$EXTRA oldconfig 2>&1 \ || _fail " !!! reconfig oldconfig failed" make EXTRAVERSION=-$EXTRA dep 2>&1 \ || _fail " !!! reconfig dep failed" new_state="buildkernel" ;; *buildkernel) _check_kernel _log " *** build kernel" _log " --- kernel ($IMAGE)" [ -z "$KMODULES" -o "$KMODULES" = yes ] && \ _log " --- modules ($MODULES)" _change_state "cleankernel" ; # we better start from scratch if this fails cd "$KWORKAREA" [ -z "$KTARGET" ] && KTARGET=bzImage [ -z "$KMODULES" -o "$KMODULES" = yes ] && \ KTARGET="$KTARGET modules" make -j4 EXTRAVERSION=-$EXTRA $KTARGET 2>&1 \ || _fail " !!! build $KTARGET failed" new_state="install" ;; *install) _check_kernel _log " *** blat old modules" _sudo rm -rf $MODULES _log " *** install kernel" cd "$KWORKAREA" case `uname -m` in i386|i686) _i386_install ;; ia64) _ia64_install ;; esac new_state="restart" ;; *restart) _log " *** select qa kernel" case `uname -m` in i386|i686) _i386_restart ;; ia64) _ia64_restart ;; esac _log " *** prepare to restart" _change_state "restarted" _log " *** restarting" _restart # doesn't return ;; *restarted) _log " *** QA reentered after restart" new_state="check" ;; *check) uname=`uname -a` _log " *** uname $uname" if [ "$MODULAR" -eq 0 ]; then new_state="reset" else new_state="probe" fi ;; *probe) _log " *** modules dependencies" _sudo depmod -a 2>&1 \ || _fail " !!! failed to depmod -a" _log " *** unmounting XFS mounts" _sudo umount -a -t xfs 2>&1 _log " *** removing modules" for m in xfsidbg xfs kdbm_pg kdbm_vm do _sudo rmmod $m 2> /dev/null done _log " *** installing modules" _sudo modprobe xfs 2>&1 \ || _fail " !!! failed to modprobe xfs" new_state="reset" ;; *reset) _log " *** unmounting TEST_DEV" _sudo umount $TEST_DEV 2>&1 _log " *** unmounting SCRATCH_DEV" _sudo umount $SCRATCH_DEV 2>&1 _log " *** clean TEST_DEV" _test_mkfs_xfs 2>&1 \ || _fail " !!! failed to mkfs TEST_DEV" _log " *** mounting TEST_DEV" _test_mount 2>&1 \ || _fail " !!! failed to mount" new_state="run" ;; soak-run) cd $QADIR _log " *** run soak test" _sudo ./soak $SOAK_PASSES $SOAK_STRESS $SOAK_PROC \ || _fail " !!! failed to run soak test" new_state="done" ;; bench-run) cd $QADIR # $BENCHMARK is typically unset, which equates to "all" # _log " *** run benchmarks" _sudo ./bench $BENCH_PASSES `id -nu && id -ng` $BENCHMARK \ || _fail " !!! failed to run benchmarks" _log "" _log " *** send results mail" mail -s "XFS QA benchmark results" $EMAIL < $QADIR/bench.out 2>&1 new_state="done" ;; *run) cd $QADIR _log " *** run tests ($CHECK_OPTIONS)" _sudo ./check -l $CHECK_OPTIONS 2>&1 | tee $ROOT/qa.out _log "" _log " *** send status mail" mail -s "XFS QA status report" $EMAIL < $ROOT/qa.out 2>&1 new_state="done" ;; *done) _log "*** requested QA state transitions complete" _success ;; *nothing) new_state="done" _log " *** do nothing" ;; *) _fail " !!! unknown state $state" ;; esac _log " *** state $state done (`date`)" [ "$new_state" = "" ] && _fail " !!! no new state set" if [ -n "$stop_state" ] then # remove hyphen prefixes s1=`echo $start_state | sed 's/.*-//'` s2=`echo $stop_state | sed 's/.*-//'` if [ $s1 = $s2 ] then # we have been requested to stop here and not go on new_state="done" fi fi _change_state $new_state done