#! /bin/sh # # Output a list of hosts from the "qa_hosts" file which meet certain # criteria specified by the options (see _usage). # The list of QA hosts can be overridden by setting the environment # variable QA_HOSTS. # # Allows QA tests to get hostnames of particular configurations # that they need. # # Copyright (c) 1997-2002 Silicon Graphics, Inc. All Rights Reserved. # . ./common.rc tmp=/tmp/$$ tmp=`pwd`/tmp rm -rf $tmp.* status=1 # failure is the default! trap "rm -f $tmp.*; exit \$status" 0 1 2 3 15 HOSTS=qa_hosts SSH_USER=pcpqa _usage() { echo >&2 'Usage: getpmcdhosts [options] Options: -a {pmda} pmda connected to pmcd -b 32|64 kernel binary format -D debug/trace (see also -V) -e big|little endianess -h hostfile name of host file, default is qa_hosts -L do not consider localhost -m {metric}{value} satisfies metric value predicate -n num match first num hosts -P return host running a primary pmlogger -p multi|single multi or single processor -s system operating system (uname -s) -v {item}{ver} version of item -V verbose diagnostics (see also -D) Legal item: ipc inter-process protocol (deprecated) libpcp shared library (deprecated) pcp PCP version installed is one of =, >, >=, <, <= or != Most options may be used together but not repeated. The environment variable QA_STS overrides the default host file and -h ' exit 1 } # # _checkpmcdhost moomba _ 64 _ multi 2 _ _ _ # # Parameters: # host name # agent name | _ # binfmt 32 | n32 | 64 | _ # primary true | false # proc multi | single | _ # pcp 1 | 2 | _ # msg true | false | _ # system irix | linux | _ # endian big | small | _ # _checkpmcdhost() { HOST=$1 AGENT=$2 BINFMT=$3 PRIMARY=$4 PROC=$5 PCP=$6 MSG=$7 SYSTEM=${8} ENDIAN=${9} ERROR=0 # check that host has a running pmcd # if pminfo -h $HOST -f pmcd.agent.status >/dev/null 2>&1 then : else $MSG && echo "$HOST: No running pmcd" >&2 return 1 fi # check for running agent # if [ "$AGENT" != "_" ] then if pmprobe -h $HOST -I pmcd.agent.type 2>/dev/null | grep $AGENT >/dev/null 2>&1 then : else $MSG && echo "$HOST: $AGENT not running" >&2 return 1 fi fi # check binfmt # if [ "$BINFMT" != "_" ] then # only want 32 or 64 (not ia32 or n32 etc...) # if want to be specific then use "-m pmcd.simabi=ia32" objfmt=`pmprobe -h $HOST -v pmcd.simabi 2>/dev/null \ | sed -e 's/\"//g' \ | $PCP_AWK_PROG 'NF > 2 { for (i = 3; i <= NF; i++) printf "%s ",$i }' \ | sed -e 's/.*x86-64/64/g' \ -e 's/.*x86_64/64/g' \ -e 's/IA-64/64/g' \ -e 's/ $//' \ -e 's/[a-zA-Z]//g' ` if [ "$objfmt" != $BINFMT ] then $MSG && echo "$HOST: binary format $BINFMT != $objfmt" >&2 return 1 fi fi # check operating system name # if [ "$SYSTEM" != "_" ] then osname=`ssh -q $SSH_USER@$HOST uname -s` if echo $osname | grep -i $SYSTEM >/dev/null 2>&1 then : else $MSG && echo "$HOST: system $SYSTEM no match with $osname " >&2 return 1; fi fi # check that host is running primary pmlogger # if $PRIMARY then if pminfo -h $HOST -f pmcd.pmlogger.host | grep primary > /dev/null 2>&1 then : else $MSG && echo "$HOST: is _not_ running primary pmlogger" >&2 return 1 fi fi # check number of processors # if [ "$PROC" != "_" ] then $VERBOSE && echo "+ pmprobe -h $HOST -v hinv.ncpu | sed ..." ncpu=`pmprobe -h $HOST -v hinv.ncpu 2>/dev/null \ | sed -e 's/\"//g' \ | $PCP_AWK_PROG 'NF == 3 && $3 ~ /^[0-9][0-9]*$/ { print $3 }'` $VERBOSE && echo "-> |$ncpu|" if [ -z "$ncpu" -o "$ncpu" = 0 ] then if $MSG then echo "$HOST: Unknown number of processors, pmprobe -> `pmprobe -h $HOST -v hinv.ncpu 2>&1`" >&2 fi return 1 fi if [ "$ncpu" -gt 1 -a "$PROC" = "single" ] then $MSG && echo "$HOST: Has $ncpu processors" >&2 return 1 elif [ "$ncpu" -eq 1 -a "$PROC" = "multi" ] then $MSG && echo "$HOST: Has only one processor" >&2 return 1 fi fi # check endianess # if [ "$ENDIAN" != "_" ] then $VERBOSE && echo "+ echo a | ssh -q $SSH_USER@$HOST od -x" check=`echo a | ssh -q $SSH_USER@$HOST "od -x" 2>&1 | sed -e 's/^0[^ ]* *//' -e 's/[ ]*$//' -e '/^$/d'` $VERBOSE && echo "-> |$check|" case "$check" in 0a61) if [ "$ENDIAN" = big ] then $MSG && echo "$HOST: little endian" >&2 return 1 fi ;; 610a) if [ "$ENDIAN" = little ] then $MSG && echo "$HOST: big endian" >&2 return 1 fi ;; *) echo "$0: INTERNAL BOTCH: expecting 0a61 or 610a, got \"$check\"" >&2 exit 1 ;; esac fi # check the item value pairs # if [ -s "$tmp.items" ] then cat $tmp.items \ | while read item op value do case "$item" in pcp) if pmprobe -h $HOST -v pmcd.version >$tmp.probe 2>$tmp.err then : else rm -f $tmp.probe fi ;; *) echo "$0: INTERNAL BOTCH item=\"$item\" not expected here!" exit 1 ;; esac if [ -s $tmp.probe ] then satisfies=`sed -e 's/"//g' $tmp.probe \ | $PCP_AWK_PROG ' BEGIN { op = "'"$op"'"; value="'"$value"'" } NF >=3 { if ( $2 < 0 ) { print "0"; exit; } # got a value if (op == "=") { if ($3 == value) print "1"; else print "0"; } else if (op == "<") { if ($3 < value) print "1"; else print "0"; } else if (op == "<=") { if ($3 <= value) print "1"; else print "0"; } else if (op == ">") { if ($3 > value) print "1"; else print "0"; } else if (op == ">=") { if ($3 >= value) print "1"; else print "0"; } else if (op == "!=") { if ($3 != value) print "1"; else print "0"; } else { print "2"; } exit; } { print "0" }'` if [ $satisfies -ne 1 ] then $MSG && echo "$HOST: does not satisfy predicate $metric $op $value" >&2 return 1 fi else $MSG && echo "$HOST: pmprobe failed `cat $tmp.errs`" >&2 return 1 fi done [ $? -eq 1 ] && return 1 fi # check the metric value pairs # if [ -s "$tmp.metrics" ] then cat $tmp.metrics \ | while read metric op value do if pmprobe -h $HOST -v $metric >$tmp.probe 2>$tmp.errs then satisfies=`sed -e 's/"//g' $tmp.probe \ | $PCP_AWK_PROG ' BEGIN { op = "'"$op"'"; value="'"$value"'" } NF >=3 { if ( $2 < 0 ) { print "0"; exit; } # got a value if (op == "=") { if ($3 == value) print "1"; else print "0"; } else if (op == "<") { if ($3 < value) print "1"; else print "0"; } else if (op == "<=") { if ($3 <= value) print "1"; else print "0"; } else if (op == ">") { if ($3 > value) print "1"; else print "0"; } else if (op == ">=") { if ($3 >= value) print "1"; else print "0"; } else if (op == "!=") { if ($3 != value) print "1"; else print "0"; } else { print "2"; } exit; } { print "0" }'` if [ $satisfies -ne 1 ] then $MSG && echo "$HOST: does not satisfy predicate $metric $op $value" >&2 return 1 fi else $MSG && echo "$HOST: pmprobe failed `cat $tmp.errs`" >&2 return 1 fi done [ $? -eq 1 ] && return 1 fi return 0 } # Go thru table of hosts and see which meet the # given criteria and return either the first one # or a list of them if need be. # # set defaults AGENT="_" BINFMT="_" PROC="_" PCP="_" SYSTEM="_" ENDIAN="_" PRIMARY=false LOCAL=false LIST=true MSG=false COUNT=0 VERBOSE=false while getopts "a:b:De:h:Lm:n:Pp:s:v:V" c do case $c in a) AGENT=$OPTARG ;; b) BINFMT=$OPTARG ;; D) MSG=true ;; e) ENDIAN=$OPTARG case "$ENDIAN" in big|little) ;; small) # synonym for little ENDIAN=little ;; *) echo "$0: Illegal endianess $ENDIAN" >&2 _usage #NOTREACHED ;; esac ;; h) HOSTS=$OPTARG if [ ! -f $OPTARG ] then echo "$0: Cannot open hostfile $OPTARG" >&2 _usage #NOTREACHED fi ;; L) LOCAL=true ;; m) metric=`echo $OPTARG | sed -e 's/[ ]*//' -e 's/[=<>!].*//'` value=`echo $OPTARG | sed -e 's/[ ]*//' -e 's/.*[=<>!]//'` op=`echo $OPTARG | sed -e 's/[ ]*//' -e "s/$metric//" -e "s/$value//"` case "$op" in '='|'<'|'<='|'>'|'>='|'!=') ;; *) echo "$0: Illegal metric argument: $OPTARG" >&2 _usage #NOTREACHED ;; esac echo "$metric $op $value" >> $tmp.metrics $MSG && echo "---tmp.metrics---" >&2 $MSG && cat $tmp.metrics >&2 ;; n) COUNT=$OPTARG if [ $COUNT -eq 1 ] then LIST=false fi ;; P) PRIMARY=true ;; p) PROC=$OPTARG ;; s) SYSTEM=$OPTARG ;; v) item=`echo $OPTARG | sed -e 's/[ ]*//' -e 's/[=<>!].*//'` value=`echo $OPTARG | sed -e 's/[ ]*//' -e 's/.*[=<>!]//'` op=`echo $OPTARG | sed -e 's/[ ]*//' -e "s/$item//" -e "s/$value//"` case "$item" in "ipc"|"libpcp") echo "$0: Deprecated item \"$item\", ignored" >&2 continue ;; "pcp") value=`echo "$value" | sed -e 's/\./ /g' | $PCP_AWK_PROG ' NF==1 { print $0 ".0.0" } NF==2 { print $0 ".0" } NF>2 { print $0 }' | sed -e 's/ /./g'` ;; *) echo "$0: Illegal item $item" >&2 _usage #NOTREACHED esac case "$op" in '='|'<'|'<='|'>'|'>='|'!=') ;; *) echo "$0: Illegal metric argument: $OPTARG" >&2 _usage #NOTREACHED ;; esac echo "$item $op $value" >> $tmp.items $MSG && echo "---tmp.items---" >&2 $MSG && cat $tmp.items >&2 ;; V) VERBOSE=true ;; *) _usage #NOTREACHED ;; esac done if [ $# -ne `expr $OPTIND - 1` ] then _usage #NOTREACHED fi # Verify the options # err=0 if [ "$BINFMT" != "_" -a "$BINFMT" != 32 -a "$BINFMT" != 64 ] then echo "$0: -b option takes 32 or 64" >&2 err=1 fi if [ "$PROC" != "_" -a "$PROC" != "multi" -a "$PROC" != "single" ] then echo "$0: -p options takes multi or single" >&2 err=1 fi if [ $err -eq 1 ] then _usage exit 1 fi # Use qa_hosts file if environment variable $QA_HOSTS is not set (or null) # if [ -z "$QA_HOSTS" ] then if [ ! -f $HOSTS ] then if [ -f GNUmakefile.install ] then # running QA in the tree ${MAKE:-make} -f GNUmakefile.install $HOSTS >$tmp.make.out 2>&1 else ${MAKE:-make} $HOSTS >$tmp.make.out 2>&1 fi if [ $? -ne 0 ] then : else cat $tmp.make.out >&2 echo "$0: Unable to make \"$HOSTS\"" >&2 exit 1 fi fi QA_HOSTS=`cat $HOSTS` fi # Remove the localhost if requested # if $LOCAL then localhost=`hostname | sed -e 's/\..*//'` QA_HOSTS=`echo $QA_HOSTS | sed \ -e 's/$/ /' \ -e "s/$localhost\.[^ ]* //g" \ -e "s/$localhost //g"` fi $MSG && ( echo "Checking hosts:"; echo "$QA_HOSTS"; echo ) >&2 # Iterate through hosts # i=0 for HOST in $QA_HOSTS do if _checkpmcdhost $HOST $AGENT $BINFMT $PRIMARY $PROC $PCP $MSG $SYSTEM $ENDIAN then if $LIST then if $MSG then echo "-> $HOST" >&2 else $PCP_ECHO_PROG $PCP_ECHO_N "$HOST ""$PCP_ECHO_C" fi else echo "$HOST" fi i=`expr $i + 1` fi if [ $COUNT -gt 0 -a $i -ge $COUNT ] then break fi done # if been using \c then do final \n # $LIST && echo if [ $i -lt $COUNT ] then echo "$0: unable to get $COUNT host(s) with options: \"$@\"" >&2 exit fi status=0 exit