summaryrefslogtreecommitdiff
path: root/src/pmsnap/pmsnap.sh
diff options
context:
space:
mode:
Diffstat (limited to 'src/pmsnap/pmsnap.sh')
-rwxr-xr-xsrc/pmsnap/pmsnap.sh457
1 files changed, 457 insertions, 0 deletions
diff --git a/src/pmsnap/pmsnap.sh b/src/pmsnap/pmsnap.sh
new file mode 100755
index 0000000..87434a5
--- /dev/null
+++ b/src/pmsnap/pmsnap.sh
@@ -0,0 +1,457 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Aconex. All Rights Reserved.
+# Copyright (c) 1995-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; either version 2 of the License, or (at your
+# option) any later version.
+#
+# This program is distributed in the hope that it will 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 to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+#
+
+. $PCP_DIR/etc/pcp.env
+
+tmp=`mktemp -d /tmp/pcp.XXXXXXXXX` || exit 1
+trap "rm -rf $tmp; exit 0" 0 1 2 3 15
+prog=`basename $0`
+
+LOCALHOST=`pmhostname`
+CONFIGDIR=$PCP_VAR_DIR/config/pmsnap
+CONTROL=$CONFIGDIR/control
+[ -z "$PCP_PMSNAPCONTROL_PATH" ] || CONTROL="$PCP_PMSNAPCONTROL_PATH"
+
+_usage()
+{
+ cat << EOF
+Usage: $prog [-dNV] [-C dir] [-c regex] [-f format] [-n regex] [-o dir]
+ -C alternate directory for control file(s)
+ -c matches the Config field in the pmsnap control file
+ -f output image format (default png)
+ -N show me, but do not execute commands
+ -n matches the Name field in the pmsnap control file
+ -o default directory for output images (default ".")
+ -V verbose trace of actions (for debugging)
+ -- pass all following options directly to pmchart
+
+If no patterns are given then all lines in the pmsnap control file
+ $CONTROL
+will be processed. If any patterns are given then only lines which
+match all patterns will be processed.
+
+Patterns are full regular expressions, see egrep(1) and may require
+appropriate quotes to avoid shell meta character expansion.
+EOF
+ exit 1
+}
+
+_fixpath()
+{
+ echo $1 $2 |\
+ $PCP_AWK_PROG '{
+ if (substr($2, 1, 1) == "/")
+ print $2
+ else
+ printf "%s/%s\n", $1, $2
+ }'
+}
+
+_warning()
+{
+ echo
+ echo "$prog: $CONTROL[$line]:"
+ echo "$*" | fmt \
+| sed -e '1{
+s/^/Warning: /
+n
+}' -e 's/^/ /'
+}
+
+_error()
+{
+ echo
+ echo "$prog: $CONTROL[$line]:"
+ echo "$*" | fmt \
+| sed -e '1{
+s/^/Error: /
+n
+}' -e 's/^/ /'
+}
+
+_debug()
+{
+ echo
+ echo "$prog: $CONTROL[$line]:"
+ echo "$*" | fmt \
+| sed -e '1{
+s/^/Debug: /
+n
+}' -e 's/^/ /'
+}
+
+serverId()
+{
+ id=42
+ while [ -f /tmp/.X$id-lock ]; do
+ id=`expr $id + 1`
+ done
+ echo $id
+}
+
+startXvfb()
+{
+ [ -x /usr/bin/Xvfb ] || return
+
+ geom="2048x2048"
+ args="-nolisten tcp -screen 0 ${geom}x8"
+ server=`serverId`
+ cookie=`mcookie`
+ XAUTHORITY=$tmp/xauth xauth add ":$server" . "$cookie" >/dev/null 2>&1
+ XAUTHORITY=$tmp/xauth /usr/bin/Xvfb ":$server" $args >/dev/null 2>&1 &
+ pid=$?
+ pmsleep 0.2
+ kill -0 $pid 2>/dev/null || return
+ export XAUTHORITY=$tmp/xauth
+ export DISPLAY=":$server"
+ echo $pid
+}
+
+stopXvfb()
+{
+ pid="$1"
+ [ -z "$pid" -o "$pid" -le 0 ] && return
+ kill $pid
+}
+
+line=0
+archives=""
+configs='.*'
+names='.*'
+dir="."
+format="png"
+verbose=false
+passthru=false
+version="1.0"
+
+# option parsing
+#
+SHOWME=false
+PMLC="echo flush | pmlc >/dev/null 2>&1"
+while getopts a:C:c:f:Nn:o:V-? c
+do
+ case $c
+ in
+ C) CONFIGDIR="$OPTARG"
+ ;;
+ c) configs="$OPTARG"
+ ;;
+ f) format="$OPTARG"
+ ;;
+ o) dir="$OPTARG"
+ ;;
+ N) SHOWME=true
+ PMLC="echo '+ echo flush | pmlc'"
+ ;;
+ n) names="$OPTARG"
+ ;;
+ V) verbose=true
+ ;;
+ -) passthru=true
+ ;;
+ ?) _usage
+ ;;
+ esac
+ [ $passthru = true ] && break
+done
+
+if [ $passthru = false ]
+then
+ shift `expr $OPTIND - 1`
+ [ $# -ne 0 ] && _usage
+fi
+commonargs="$commonargs $@"
+
+CONTROL=$CONFIGDIR/control
+if [ ! -f "$CONTROL" ]
+then
+ echo "$prog: Error: cannot find control file \"$CONTROL\""
+ exit 1
+fi
+
+if [ ! -d "$dir" ]
+then
+ echo "$prog: Error: directory \"$dir\" does not exist"
+ exit 1
+fi
+cd $dir
+dir=`pwd`
+$SHOWME && echo "+ cd $dir"
+
+$SHOWME || xvfb=`startXvfb`
+
+# escape / in patterns so $PCP_AWK_PROG is not confused
+#
+names=`echo "$names" | sed -e 's;/;\\\\/;g'`
+configs=`echo "$configs" | sed -e 's;/;\\\\/;g'`
+
+sed -e 's/LOCALHOSTNAME/'$LOCALHOST'/g' < $CONTROL \
+| $PCP_AWK_PROG '
+/^\#/ || /^\$/ || NF < 4 {
+ print
+ next
+}
+{
+ if ($1 ~ /'$names'/ && $3 ~ /'$configs'/) {
+ printf "%s %s %s '\''", $1, $2, $3
+ for (i=4; i<= NF; i++)
+ printf "%s ", $i
+ printf "'\''\n"
+ }
+}' \
+| while read aname afolio aview args
+do
+ line=`expr $line + 1`
+ case "$aname"
+ in
+ \#*|'') # comment or empty
+ continue
+ ;;
+
+ \$*) # in-line variable assignment
+ $SHOWME && echo "# $aname $afolio $aview $args"
+ cmd=`echo "$aname $afolio $aview $args" \
+ | sed -n \
+ -e "/='/s/\(='[^']*'\).*/\1/" \
+ -e '/="/s/\(="[^"]*"\).*/\1/' \
+ -e '/=[^"'"'"']/s/[;&<>|].*$//' \
+ -e '/^\\$[A-Za-z][A-Za-z0-9_]*=/{
+s/^\\$//
+s/^\([A-Za-z][A-Za-z0-9_]*\)=/export \1; \1=/p
+}'`
+ if [ -z "$cmd" ]
+ then
+ # in-line command, not a variable assignment
+ _warning "in-line command is not a variable assignment, line ignored"
+ else
+ case "$cmd"
+ in
+ 'export PATH;'*)
+ _warning "cannot change \$PATH, line ignored"
+ ;;
+ 'export IFS;'*)
+ _warning "cannot change \$IFS, line ignored"
+ ;;
+ *)
+ $SHOWME && echo "+ $cmd"
+ eval $cmd
+ ;;
+ esac
+ fi
+ continue
+ ;;
+ esac
+
+ if [ -z "$afolio" -o -z "$aview" -o -z "$args" ]
+ then
+ _error "insufficient fields in control file record"
+ continue
+ fi
+
+ # strip first and last single quote added by awk prior to read
+ #
+ args=`echo $args | sed -e "s/^'//" -e "s/'$//"`
+
+ name=`_fixpath $dir $aname`
+ if [ -d $PCP_LOG_DIR/pmlogger ]; then
+ folio=`_fixpath $PCP_LOG_DIR/pmlogger $afolio`
+ fi
+ view=`_fixpath $dir $aview`
+
+ # make sure output directory exists
+ #
+ outdir=`dirname $name`
+ if [ ! -d $outdir ]
+ then
+ if $SHOWME
+ then
+ echo "+ mkdir -p $outdir"
+ else
+ mkdir -p $outdir
+ if [ ! -d $outdir ]
+ then
+ _error "cannot create directory \"$outdir\" for output file"
+ else
+ $verbose && _debug "created image output directory \"$outdir\""
+ fi
+ fi
+ fi
+
+ if $SHOWME
+ then
+ :
+ else
+ if [ ! -w $outdir ]
+ then
+ _error "cannot write in directory \"$outdir\" to create output file"
+ exit 1
+ fi
+ fi
+
+ if $verbose
+ then
+ echo
+ _debug "name=\"$name\""
+ _debug "folio=\"$folio\""
+ _debug "view=\"$view\""
+ _debug "args=\"$args\""
+ _debug "commonargs=\"$commonargs\""
+ fi
+
+ if [ ! -f "$view" ]
+ then
+ if [ ! -f $CONFIGDIR/$aview ]
+ then
+ if [ ! -f $PCP_VAR_DIR/config/pmchart/$aview ]
+ then
+ if [ ! -f $PCP_VAR_DIR/config/kmchart/$aview ]
+ then
+ _warning "could not find \"$view\", \"$CONFIGDIR/$aview\", \"$PCP_VAR_DIR/config/pmchart/$aview, or \"$PCP_VAR_DIR/config/kmchart/$aview\""
+ continue
+ else
+ view=$PCP_VAR_DIR/config/kmchart/$aview
+ fi
+ else
+ view=$PCP_VAR_DIR/config/pmchart/$aview
+ fi
+ else
+ view=$CONFIGDIR/$aview
+ fi
+ fi
+
+ if [ ! -f $folio ]
+ then
+ # oops, no folio
+ _error "cannot find archive folio \"$folio\""
+ echo "Skipping entry from control file ..."
+ continue
+ fi
+
+ f=$folio
+ $SHOWME && echo "+ pmafm $f selection"
+ pmafm "$f" selection >$tmp/out 2>&1
+
+ if [ $? -ne 0 ]
+ then
+ if [ ! -f $folio.meta ]
+ then
+ _warning "\"$folio\" is neither a PCP folio nor a PCP archive"
+ ls -l $folio
+ continue
+ else
+ contents=$folio
+ fi
+ else
+ contents=`sed -n -e '/Archive:/s///gp' <$tmp/out`
+ if [ -z "$contents" ]
+ then
+ _warning "cannot determine archive name from PCP folio \"$folio\""
+ continue
+ fi
+ fi
+
+ arch=""
+
+ for c in $contents
+ do
+ if [ -f $c.meta ]
+ then
+ host=`pminfo -f -a $c pmcd.pmlogger.host \
+ | sed -e 's/"//g' -e 's/\[//g' \
+ | $PCP_AWK_PROG '$1=="inst" {print $6; exit}'`
+
+ port=`pminfo -f -a $c pmcd.pmlogger.port \
+ | sed -e 's/"//g' -e 's/\[//g' \
+ | $PCP_AWK_PROG '$1=="inst" {print $6; exit}'`
+
+ if [ ! -z "$host" -a ! -z "$port" ]
+ then
+ echo "$host $port" >> $tmp/flush
+ else
+ if $verbose
+ then
+ _warning "could not extract host and pmlogger control port from archive \"$c\" ... this archive may not be flushed"
+ fi
+ fi
+
+ if [ -z "$arch" ]
+ then
+ arch=$c
+ else
+ arch=$arch","$c
+ fi
+ else
+ _warning "cannot find or open archive \"$c\""
+ fi
+ done
+
+ if [ -z "$arch" ]
+ then
+ _warning "no archives could be found for \"$contents\""
+ continue
+ fi
+
+ sort -u $tmp/flush | while read host port
+ do
+ eval $PMLC -h $host -p $port
+ done
+
+ if $SHOWME
+ then
+ echo "+ pmchart -c $view -o $name.$format -a $arch $commonargs $args"
+ else
+ eval pmchart -c "$view" -o "$tmp/name.$format" -a "$arch" $commonargs $args > $tmp/err 2>&1
+ sts=$?
+
+ if [ $sts -eq 0 -a -f $tmp/name.$format ]
+ then
+ # success, update the image
+ mv $tmp/name.$format $name.$format
+ $verbose && _debug "created \"$name.$format\""
+ if [ -s "$tmp/err" ]
+ then
+ _warning "the output image \"$name.$format\" was created but there were warning messages from pmchart, as follows:"
+ cat $tmp/err
+ echo "-------------"
+ fi
+ elif grep 'too short to satisfy the requested starting alignment' $tmp/err >/dev/null
+ then
+ # archive's duration is too short for chart configuration ...
+ # silently ignore this one, as we'll probably succeed next time
+ # or soon thereafter
+ if $verbose
+ then
+ _debug "archive \"$arch\" too short for pmchart args \"$args\""
+ fi
+ else
+ # failed, remove the image and report the error
+ _warning "the output image \"$name.$format\" was not created. There were error messages from pmchart, as follows:"
+ cat $tmp/err
+ echo "-------------"
+ rm -f $name.$format
+ fi
+ fi
+
+ rm -f $tmp/err
+done
+
+$SHOWME || stopXvfb "$xvfb"
+
+exit $status