# Common sh(1) procedures to be used in the Performance Co-Pilot # PMDA Install and Remove scripts # # Copyright (c) 1995-2001,2003 Silicon Graphics, Inc. All Rights Reserved. # Portions Copyright (c) 2008 Aconex. All Rights Reserved. # Portions Copyright (c) 2013-2014 Red Hat. # # 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. # source the PCP configuration environment variables . $PCP_DIR/etc/pcp.env tmp=`mktemp -d $PCP_TMPFILE_DIR/pmdaproc.XXXXXXXXX` || exit 1 pmdatmp=$tmp trap "rm -rf $pmdatmp $pcptmp; exit" 0 1 2 3 15 _setup_platform() { case "$PCP_PLATFORM" in mingw) uid=0 # no permissions we can usefully test here dso_suffix=dll default_pipe_opt=false default_socket_opt=true CHOWN=": skip chown" CHMOD=chmod ;; *) eval `id | sed -e 's/(.*//'` dso_suffix=so [ "$PCP_PLATFORM" = darwin ] && dso_suffix=dylib default_pipe_opt=true default_socket_opt=false CHOWN=chown CHMOD=chmod ;; esac } _setup_localhost() { # Try to catch some truly evil preconditions. If you cannot reach # localhost, all bets are off! # if which ping >/dev/null 2>&1 then __opt='' # Larry Wall style hunt for the version of ping that is first # on our path # ping --help >$tmp/hlp 2>&1 if grep '.-c count' $tmp/hlp >/dev/null 2>&1 then __opt='-c 1 localhost' elif grep '.-n count' $tmp/hlp >/dev/null 2>&1 then __opt='-n 1 localhost' elif grep 'host .*packetsize .*count' $tmp/hlp >/dev/null 2>&1 then __opt='localhost 56 1' elif grep 'host .*data_size.*npackets' $tmp/hlp >/dev/null 2>&1 then __opt='localhost 56 1' fi if [ -z "$__opt" ] then echo "Warning: can't find a ping(1) that I understand ... pushing on" else if ping $__opt >$tmp/hlp 2>&1 then : else # failing that, try 3 pings ... failure means all 3 were lost, # and so there is no hope of continuing # __opt=`echo "$__opt" | sed -e 's/1/3/'` if ping $__opt >/dev/null 2>&1 then : else echo "Error: no route to localhost, pmcd reconfiguration abandoned" exit 1 fi fi fi fi } _setup_localhost _setup_platform rm -rf $tmp # some useful common variables for Install/Remove scripts # # put your PMNS files here PMNSDIR=$PCP_VAR_DIR/pmns # pmcd and pcp log files here if [ ! -z "$PCP_LOGDIR" ] then # this is being discouraged and is no longer documented anywhere LOGDIR=$PCP_LOGDIR else if [ -d $PCP_LOG_DIR/pmcd ] then # the preferred naming scheme # LOGDIR=$PCP_LOG_DIR/pmcd else # backwards compatibility for IRIX # LOGDIR=$PCP_LOG_DIR fi fi # writeable root of PMNS NAMESPACE=${PMNS_DEFAULT-$PMNSDIR/root} PMNSROOT=`basename $NAMESPACE` # echo without newline - deprecated - use the $PCP_ECHO_* ones from # /etc/pcp.conf instead, however some old Install and Remove scripts may # still use $ECHONL, so keep it here # ECHONL="echo -n" # Install control variables # Can install as DSO? dso_opt=false # Can install as perl script? perl_opt=false # Can install as python script? python_opt=false # Can install as daemon? daemon_opt=true # If daemon, pipe? pipe_opt=$default_pipe_opt # If daemon, socket? and default for Internet sockets? socket_opt=$default_socket_opt socket_inet_def='' # IPC Protocol for daemon (binary only now) ipc_prot=binary # Need to force a restart of pmcd? forced_restart=true # Delay after install before checking (sec) check_delay=3 # Additional command line args to go in $PCP_PMCDCONF_PATH args="" # ditto for perl PMDAs perl_args="" # ditto for python PMDAS python_args="" # Source for the pmns pmns_source=pmns # Source for the helptext help_source=help # Assume libpcp_pmda.so.1 pmda_interface=1 # Full pathname to directory where PMDA is to be found ... # exectable and/or DSO, domain.h, pmns, control files, etc. pmda_dir="`pwd`" # Other variables and constants # prog=`basename $0` tmp=`mktemp -d $PCP_TMPFILE_DIR/pcp.XXXXXXXXX` || exit 1 pcptmp=$tmp do_pmda=true do_check=true __here=`pwd` __pmcd_is_dead=false __echo=false __verbose=false __ns_opt='' trap "rm -rf $tmp; exit" 0 1 2 3 15 # Parse command line args # while [ $# -gt 0 ] do case $1 in -e) # echo user input __echo=true ;; -N) # name space only do_pmda=false ;; -n) # alternate name space if [ $# -lt 2 ] then echo "$prog: -n requires a name space file option" exit 1 fi NAMESPACE=$2 PMNSROOT=`basename $NAMESPACE` PMNSDIR=`dirname $NAMESPACE` __ns_opt="-n $2" shift ;; -Q) # skip check for metrics going away do_check=false ;; -R) # $ROOT if [ "$prog" = "Remove" ] then echo "Usage: $prog [-eNQV] [-n namespace]" exit 1 fi if [ $# -lt 2 ] then echo "$prog: -R requires a directory option" exit 1 fi root=$2 shift ;; -V) # verbose __verbose=true ;; *) if [ "$prog" = "Install" ] then echo "Usage: $prog [-eNQV] [-n namespace] [-R rootdir]" else echo "Usage: $prog [-eNQV] [-n namespace]" fi exit 1 ;; esac shift done # wait for pmcd to be alive again # Usage: __wait_for_pmcd [can_wait] # __wait_for_pmcd() { # 60 seconds default seems like a reasonble max time to get going [ -z "$__can_wait" ] && __can_wait=${1-60} if pmcd_wait -t $__can_wait then : else echo "Arrgghhh ... PMCD failed to start after $__can_wait seconds" if [ -f $LOGDIR/pmcd.log ] then echo "Here is the PMCD logfile ($LOGDIR/pmcd.log):" ls -l $LOGDIR/pmcd.log cat $LOGDIR/pmcd.log else echo "No trace of the PMCD logfile ($LOGDIR/pmcd.log)!" fi __pmcd_is_dead=true fi } # try and put pmcd back the way it was # __restore_pmcd() { if [ -f $tmp/pmcd.conf.save ] then __pmcd_is_dead=false echo echo "Save current PMCD control file in $PCP_PMCDCONF_PATH.prev ..." rm -f $PCP_PMCDCONF_PATH.prev mv $PCP_PMCDCONF_PATH $PCP_PMCDCONF_PATH.prev echo "Restoring previous PMCD control file, and trying to restart PMCD ..." cp $tmp/pmcd.conf.save $PCP_PMCDCONF_PATH eval $CHOWN root $PCP_PMCDCONF_PATH eval $CHMOD 644 $PCP_PMCDCONF_PATH rm -f $tmp/pmcd.conf.save $PCP_RC_DIR/pcp start __wait_for_pmcd fi if $__pmcd_is_dead then echo echo "Sorry, failed to restart PMCD." fi } # __pmda_cull name domain # __pmda_cull() { # context and integrity checks # if [ $# -ne 2 ] then echo "pmdaproc.sh: internal botch: __pmda_cull() called with $# (instead of 2) arguments" exit 1 fi [ ! -f $PCP_PMCDCONF_PATH ] && return if eval $CHMOD u+w $PCP_PMCDCONF_PATH then : else echo "pmdaproc.sh: __pmda_cull: Unable to make $PCP_PMCDCONF_PATH writable" exit 1 fi if [ ! -w $PCP_PMCDCONF_PATH ] then echo "pmdaproc.sh: \"$PCP_PMCDCONF_PATH\" is not writeable" exit 1 fi # remove matching entry from $PCP_PMCDCONF_PATH if present # $PCP_AWK_PROG <$PCP_PMCDCONF_PATH >$tmp/pmcd.conf ' BEGIN { status = 0 } $1 == "'"$1"'" && $2 == "'"$2"'" { status = 1; next } { print } END { exit status }' if [ $? -eq 0 ] then # no match : else # log change to the PCP NOTICES file # $PCP_BINADM_DIR/pmpost "PMDA cull: from $PCP_PMCDCONF_PATH: $1 $2" # save pmcd.conf in case we encounter a problem, and then # install updated $PCP_PMCDCONF_PATH # cp $PCP_PMCDCONF_PATH $tmp/pmcd.conf.save cp $tmp/pmcd.conf $PCP_PMCDCONF_PATH eval $CHOWN root $PCP_PMCDCONF_PATH eval $CHMOD 644 $PCP_PMCDCONF_PATH # signal pmcd if it is running # if pminfo -v pmcd.version >/dev/null 2>&1 then pmsignal -a -s HUP pmcd >/dev/null 2>&1 # allow signal processing to be done before checking status sleep 2 __wait_for_pmcd if $__pmcd_is_dead then __restore_pmcd # give PMCD a chance to get back into original state sleep 3 __wait_for_pmcd fi fi fi rm -f $tmp/pmcd.conf # stop any matching PMDA that is still running # for __sig in TERM KILL do __pids=`_get_pids_by_name pmda$1` if [ ! -z "$__pids" ] then pmsignal -s $__sig $__pids >/dev/null 2>&1 # allow signal processing to be done sleep 2 else break fi done } # __pmda_add "entry for $PCP_PMCDCONF_PATH" # __pmda_add() { # context and integrity checks # if [ $# -ne 1 ] then echo "pmdaproc.sh: internal botch: __pmda_add() called with $# (instead of 1) arguments" exit 1 fi if eval $CHMOD u+w $PCP_PMCDCONF_PATH then : else echo "pmdaproc.sh: __pmda_add: Unable to make $PCP_PMCDCONF_PATH writable" exit 1 fi if [ ! -w $PCP_PMCDCONF_PATH ] then echo "pmdaproc.sh: \"$PCP_PMCDCONF_PATH\" is not writeable" exit 1 fi # save pmcd.conf in case we encounter a problem # cp $PCP_PMCDCONF_PATH $tmp/pmcd.conf.save myname=`echo $1 | $PCP_AWK_PROG '{print $1}'` mydomain=`echo $1 | $PCP_AWK_PROG '{print $2}'` # add entry to $PCP_PMCDCONF_PATH # echo >$tmp/pmcd.body echo >$tmp/pmcd.access $PCP_AWK_PROG <$PCP_PMCDCONF_PATH ' NF==0 { next } /^[ ]*\[[ ]*access[ ]*\]/ { state = 2 } state == 2 { print >"'$tmp/pmcd.access'"; next } $1=="'$myname'" && $2=="'$mydomain'" { next } { print >"'$tmp/pmcd.body'"; next }' ( cat $tmp/pmcd.body \ ; echo "$1" \ ; cat $tmp/pmcd.access \ ) >$PCP_PMCDCONF_PATH rm -f $tmp/pmcd.access $tmp/pmcd.body eval $CHOWN root $PCP_PMCDCONF_PATH eval $CHMOD 644 $PCP_PMCDCONF_PATH # log change to pcplog/NOTICES # $PCP_BINADM_DIR/pmpost "PMDA add: to $PCP_PMCDCONF_PATH: $1" # signal pmcd if it is running (and ok to do so), else start it # if ! $forced_restart && pminfo -v pmcd.version >/dev/null 2>&1 then pmsignal -a -s HUP pmcd >/dev/null 2>&1 # allow signal processing to be done before checking status sleep 2 __wait_for_pmcd $__pmcd_is_dead && __restore_pmcd else log=$LOGDIR/pmcd.log rm -f $log $PCP_RC_DIR/pcp start __wait_for_pmcd $__pmcd_is_dead && __restore_pmcd fi } # expect -R root or $ROOT not set in environment # __check_root() { if [ "X$root" != X ] then ROOT="$root" export ROOT else if [ "X$ROOT" != X -a "X$ROOT" != X/ ] then echo "Install: \$ROOT was set to \"$ROOT\"" echo " Use -R rootdir to install somewhere other than /" exit 1 fi fi } # should be able to extract default domain from domain.h # __check_domain() { if [ -f domain.h ] then __infile=domain.h elif [ -f domain.h.perl ] then __infile=domain.h.perl elif [ -f domain.h.python ] then __infile=domain.h.python else echo "Install: cannot find ./domain.h to determine the Performance Metrics Domain" exit 1 fi # $domain is for backwards compatibility, modern PMDAs # have something like # #define FOO 123 # domain='' eval `$PCP_AWK_PROG <$__infile ' /^#define/ && $3 ~ /^[0-9][0-9]*$/ { print $2 "=" $3 if (seen == 0) { print "domain=" $3 sub(/^PMDA/, "", $2) print "SYMDOM=" $2 seen = 1 } }'` if [ "X$domain" = X ] then echo "Install: cannot determine the Performance Metrics Domain from ./domain.h" exit 1 fi } # handle optional configuration files that maybe already given in an # $PCP_PMCDCONF_PATH line or user-supplied or some default or sample # file # # before calling _choose_configfile, optionally define the following # variables # # Name Default Use # # configdir $PCP_VAR_DIR/config/$iam directory for config ... assumed # name is $iam.conf in this directory # # configfile "" set if have a preferred choice, # e.g. from $PCP_PMCDCONF_PATH # this will be set on return if we've # found an acceptable config file # # default_configfile # "" if set, this is the default which # will be offered # # Note: # If the choice is aborted then $configfile will be set to empty. # Therefore, there should be a test for an empty $configfile after # the call to this function. # _choose_configfile() { configdir=${configdir-$PCP_VAR_DIR/config/$iam} if [ ! -d $configdir ] then mkdir -p $configdir fi while true do echo "Possible configuration files to choose from:" # List viable alternatives __i=0 # menu item number __filelist="" # list of configuration files __choice="" # the choice of configuration file __choice1="" # the menu item for the 1st possible choice __choice2="" # the menu item for the 2nd possible choice __choice3="" # the menu item for the 3rd possible choice if [ ! -z "$configfile" ] then if [ -f $configfile ] then __i=`expr $__i + 1` __choice1=$__i __filelist="$__filelist $configfile" echo "[$__i] $configfile" fi fi if [ -f $configdir/$iam.conf ] then if echo $__filelist | grep "$configdir/$iam.conf" >/dev/null then : else __i=`expr $__i + 1` __choice2=$__i __filelist="$__filelist $configdir/$iam.conf" echo "[$__i] $configdir/$iam.conf" fi fi if [ -f $default_configfile ] then if echo $__filelist | grep "$default_configfile" >/dev/null then : else __i=`expr $__i + 1` __choice3=$__i __filelist="$__filelist $default_configfile" echo "[$__i] $default_configfile" fi fi __i=`expr $__i + 1` __own_choice=$__i echo "[$__i] Specify your own configuration file." __i=`expr $__i + 1` __abort_choice=$__i echo "[$__i] None of the above (abandon configuration file selection)." $PCP_ECHO_PROG $PCP_ECHO_N "Which configuration file do you want to use ? [1] ""$PCP_ECHO_C" read __reply $__echo && echo "$__reply" # default if [ -z "$__reply" ] then __reply=1 fi # Process the reply from the user if [ $__reply = $__own_choice ] then $PCP_ECHO_PROG $PCP_ECHO_N "Enter the name of the existing configuration file: ""$PCP_ECHO_C" read __choice $__echo && echo "$__choice" if [ ! -f "$__choice" ] then echo "Cannot open \"$__choice\"." echo "" echo "Please choose another configuration file." __choice="" fi elif [ $__reply = $__abort_choice ] then echo "Abandoning configuration file selection." configfile="" return 0 elif [ "X$__reply" = "X$__choice1" -o "X$__reply" = "X$__choice2" -o "X$__reply" = "X$__choice3" ] then # extract nth field as the file __choice=`echo $__filelist | $PCP_AWK_PROG -v n=$__reply '{ print $n }'` else echo "Illegal choice: $__reply" echo "" echo "Please choose number between: 1 and $__i" fi if [ ! -z "$__choice" ] then echo echo "Contents of the selected configuration file:" echo "--------------- start $__choice ---------------" cat $__choice echo "--------------- end $__choice ---------------" echo $PCP_ECHO_PROG $PCP_ECHO_N "Use this configuration file? [y] ""$PCP_ECHO_C" read ans $__echo && echo "$ans" if [ ! -z "$ans" -a "X$ans" != Xy -a "X$ans" != XY ] then echo "" echo "Please choose another configuration file." else break fi fi done __dest=$configdir/$iam.conf if [ "$__choice" != "$__dest" ] then if [ -f $__dest ] then echo "Removing old configuration file \"$__dest\"" rm -f $__dest if [ -f $__dest ] then echo "Error: cannot remove old configuration file \"$__dest\"" exit 1 fi fi if cp $__choice $__dest then : else echo "Error: cannot install new configuration file \"$__dest\"" exit 1 fi __choice=$__dest fi configfile=$__choice } # choose correct PMDA installation mode # # make sure we are installing in the correct style of configuration # __choose_mode() { __def=m $do_pmda && __def=b echo \ 'You will need to choose an appropriate configuration for installation of the "'$iam'" Performance Metrics Domain Agent (PMDA). collector collect performance statistics on this system monitor allow this system to monitor local and/or remote systems both collector and monitor configuration for this system ' while true do $PCP_ECHO_PROG $PCP_ECHO_N 'Please enter c(ollector) or m(onitor) or b(oth) ['$__def'] '"$PCP_ECHO_C" read ans $__echo && echo "$ans" case "$ans" in "") break ;; c|collector|b|both) do_pmda=true break ;; m|monitor) do_pmda=false break ;; *) echo "Sorry, that is not acceptable response ..." ;; esac done } # choose an IPC method # __choose_ipc() { _dir=$1 ipc_type='' $pipe_opt && ipc_type=pipe $socket_opt && ipc_type=socket $pipe_opt && $socket_opt && ipc_type='' if [ -z "$ipc_type" ] then while true do $PCP_ECHO_PROG $PCP_ECHO_N "PMCD should communicate with the $iam daemon via a pipe or a socket? [pipe] ""$PCP_ECHO_C" read ipc_type $__echo && echo "$ipc_type" if [ "X$ipc_type" = Xpipe -o "X$ipc_type" = X ] then ipc_type=pipe break elif [ "X$ipc_type" = Xsocket ] then break else echo "Must choose one of \"pipe\" or \"socket\", please try again" fi done fi if [ $ipc_type = pipe ] then # This defaults to binary unless the Install file # specifies ipc_prot="binary notready" -- See pmcd(1) type="pipe $ipc_prot $_dir/$pmda_name" else while true do $PCP_ECHO_PROG $PCP_ECHO_N "Use Internet, IPv6 or Unix domain sockets? [Internet] ""$PCP_ECHO_C" read ans $__echo && echo "$ans" if [ "X$ans" = XInternet -o "X$ans" = XIPv6 -o "X$ans" = X ] then $PCP_ECHO_PROG $PCP_ECHO_N "Internet port number or service name? [$socket_inet_def] ""$PCP_ECHO_C" read port $__echo && echo "$port" [ "X$port" = X ] && port=$socket_inet_def case $port in [0-9]*) ;; *) if grep "^$port[ ]*[0-9]*/tcp" /etc/services >/dev/null 2>&1 then : else echo "Warning: there is no tcp service for \"$port\" in /etc/services!" fi ;; esac if [ "X$ans" = XInternet -o "X$ans" = X ] then type="socket inet $port $_dir/$pmda_name" args="-i $port $args" else type="socket ipv6 $port $_dir/$pmda_name" args="-6 $port $args" fi break elif [ "X$ans" = XUnix ] then $PCP_ECHO_PROG $PCP_ECHO_N "Unix FIFO name? ""$PCP_ECHO_C" read fifo $__echo && echo "$fifo" if [ "X$fifo" = X ] then echo "Must provide a name, please try again" else type="socket unix $fifo $_dir/$pmda_name" args="-u $fifo $args" break fi else echo "Must choose one of \"Unix\" or \"Internet\", please try again" fi done fi } # filter pmprobe -i output of the format: # postgresql.active.is_in_recovery -12351 Missing metric value(s) # postgresql.statio.sys_sequences.blks_hit 0 # disk.partitions.read 13 ?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9 ?10 ?11 ?12 # to produce a summary of metrics, values and warnings # __filter() { $PCP_AWK_PROG ' /^'$1'/ { metric++ if ($2 < 0) warn++ else value += $2 next } { warn++ } END { if (warn) printf "%d warnings, ",warn printf "%d metrics and %d values\n",metric,value }' } _setup() { # some more configuration controls pmns_name=${pmns_name-$iam} pmda_name=pmda$iam pmda_dso_name="${PCP_PMDAS_DIR}/${iam}/pmda_${iam}.${dso_suffix}" dso_name="${dso_name-$pmda_dso_name}" dso_entry=${iam}_init _check_userroot _check_directory # automatically generate files for those lazy Perl programmers # if $perl_opt then perl_name="${pmda_dir}/pmda${iam}.perl" [ -f "$perl_name" ] || perl_name="${pmda_dir}/pmda${iam}.pl" if [ -f "$perl_name" ] then perl_pmns="${pmda_dir}/pmns.perl" perl_dom="${pmda_dir}/domain.h.perl" perl -e 'use PCP::PMDA' 2>/dev/null if test $? -eq 0 then eval PCP_PERL_DOMAIN=1 perl "$perl_name" > "$perl_dom" eval PCP_PERL_PMNS=1 perl "$perl_name" > "$perl_pmns" elif $dso_opt || $daemon_opt then : # we have an alternative, so continue on else echo 'Perl PCP::PMDA module is not installed, install it and try again' exit 1 fi else if $dso_opt || $daemon_opt then : # we have an alternative, so continue on else echo "Neither pmda${iam}.perl nor pmda${iam}.pl found in ${pmda_dir}" echo "Error: no Perl PMDA to install" exit 1 fi fi fi # automatically generate files for the Python programmers too # if $python_opt then python_name="${pmda_dir}/pmda${iam}.python" [ -f "$python_name" ] || python_name="${pmda_dir}/pmda${iam}.py" if [ -f "$python_name" ] then python_pmns="${pmda_dir}/pmns.python" python_dom="${pmda_dir}/domain.h.python" python -c 'from pcp import pmda' 2>/dev/null if test $? -eq 0 then eval PCP_PYTHON_DOMAIN=1 python "$python_name" > "$python_dom" eval PCP_PYTHON_PMNS=1 python "$python_name" > "$python_pmns" elif $dso_opt || $daemon_opt then : # we have an alternative, so continue on else echo 'Python pcp.pmda module is not installed, install it and try again' exit 1 fi else if $dso_opt || $daemon_opt then : # we have an alternative, so continue on else echo "Neither pmda${iam}.python nor pmda${iam}.py found in ${pmda_dir}" echo "Error: no Python PMDA to install" exit 1 fi fi fi # Juggle pmns and domain.h in case perl/python pmda install was done here # last time # for file in pmns domain.h do [ -f $file.save ] && mv $file.save $file done # Set $domain and $SYMDOM from domain.h # __check_domain case $prog in *Install*) # Check that $ROOT is not set, we have a default domain value and # choose the installation mode (collector, monitor or both) # __check_root __choose_mode ;; esac } _install_views() { viewer="$1" have_views=false [ `echo *.$viewer` != "*.$viewer" ] && have_views=true if [ -d $PCP_VAR_DIR/config/$viewer ] then $have_views && echo "Installing $viewer view(s) ..." for __i in *.$viewer do if [ "$__i" != "*.$viewer" ] then __dest=$PCP_VAR_DIR/config/$viewer/`basename $__i .$viewer` rm -f $__dest cp $__i $__dest fi done else $have_views && \ echo "Skip installing $viewer view(s) ... no \"$PCP_VAR_DIR/config/$viewer\" directory" fi } # Configurable PMDA installation # # before calling _install, # 1. set $iam # 2. set one/some/all of $dso_opt, $perl_opt, $python_opt or $daemon_opt to true # (optional, $daemon_opt is true by default) # 3. if $daemon_opt set one or both of $pipe_opt or $socket_opt true # (optional, $pipe_opt is true by default) # 4. if $socket_opt and there is a default Internet socket, set # $socket_inet_def _install() { if [ -z "$iam" ] then echo 'Botch: must define $iam before calling _install()' exit 1 fi if $do_pmda then if $dso_opt || $perl_opt || $python_opt || $daemon_opt then : else echo 'Botch: must set at least one of $dso_opt, $perl_opt, $python_opt or $daemon_opt to "true"' exit 1 fi if $daemon_opt then if $pipe_opt || $socket_opt then : else echo 'Botch: must set at least one of $pipe_opt or $socket_opt to "true"' exit 1 fi fi # Select a PMDA style (dso/perl/python/deamon), and for daemons the # IPC method for communication between PMCD and the PMDA. # pmda_options='' pmda_default_option='' pmda_multiple_options=false if $dso_opt then pmda_options="dso" pmda_default_option="dso" fi if $perl_opt then pmda_default_option="perl" if test -n "$pmda_options" then pmda_options="perl or $pmda_options" pmda_multiple_options=true else pmda_options="perl" fi fi if $python_opt then pmda_default_option="python" if test -n "$pmda_options" then pmda_options="python or $pmda_options" pmda_multiple_options=true else pmda_options="python" fi fi if $daemon_opt then pmda_default_option="daemon" if test -n "$pmda_options" then pmda_options="daemon or $pmda_options" pmda_multiple_options=true else pmda_options="daemon" fi fi pmda_type="$pmda_default_option" if $pmda_multiple_options then while true do $PCP_ECHO_PROG $PCP_ECHO_N "Install $iam as a $pmda_options agent? [$pmda_default_option] ""$PCP_ECHO_C" read pmda_type $__echo && echo "$pmda_type" if [ "X$pmda_type" = Xdaemon -o "X$pmda_type" = X ] then pmda_type=daemon break elif [ "X$pmda_type" = Xdso ] then break elif [ "X$pmda_type" = Xperl ] then perl -e 'use PCP::PMDA' 2>/dev/null if test $? -ne 0 then echo 'Perl PCP::PMDA module is not installed, install it and try again' else break fi elif [ "X$pmda_type" = Xpython ] then python -c 'from pcp import pmda' 2>/dev/null if test $? -ne 0 then echo 'Python pcp pmda module is not installed, install it and try again' else break fi else echo "Must choose one of $pmda_options, please try again" fi done fi if [ "$pmda_type" = daemon ] then __choose_ipc $pmda_dir args="-d $domain $args" elif [ "$pmda_type" = perl ] then type="pipe binary perl $perl_name $perl_args" args="" elif [ "$pmda_type" = python ] then type="pipe binary python $python_name $python_args" args="" else type="dso $dso_entry $dso_name" args="" fi # Install binaries # if [ "$pmda_type" = perl -o "$pmda_type" = python ] then : # we can safely skip building binaries elif [ -f Makefile -o -f makefile -o -f GNUmakefile ] then # $PCP_MAKE_PROG may contain command line args ... executable # is first word # if [ ! -f "`echo $PCP_MAKE_PROG | sed -e 's/ .*//'`" -o ! -f "$PCP_INC_DIR/pmda.h" ] then echo "$prog: Arrgh, PCP devel environment required to install this PMDA" exit 1 fi echo "Installing files ..." if $PCP_MAKE_PROG install then : else echo "$prog: Arrgh, \"$PCP_MAKE_PROG install\" failed!" exit 1 fi fi # Fix domain in help for instance domains (if any) # if [ -f $help_source ] then case $pmda_interface in 1) help_version=1 ;; *) # PMDA_INTERFACE_2 or later help_version=2 ;; esac sed -e "/^@ $SYMDOM\./s/$SYMDOM\./$domain./" <$help_source \ | newhelp -n root -v $help_version -o $help_source fi fi if $do_pmda then if [ "X$pmda_type" = Xperl -o "X$pmda_type" = Xpython ] then # Juggle pmns and domain.h ... save originals and # use *.{perl,python} ones created earlier for file in pmns domain.h do if [ ! -f "$file.$pmda_type" ] then echo "Botch: $file.$pmda_type missing ... giving up" exit 1 fi if [ -f $file ] then if diff $file.$pmda_type $file >/dev/null then : else [ ! -f $file.save ] && mv $file $file.save mv $file.$pmda_type $file fi else mv $file.$pmda_type $file fi done fi else # Maybe PMNS only install, and only implementation may be # Perl or Python ones ... simpler juggling needed here. # for file in pmns domain.h do [ ! -f $file -a -f $file.perl ] && mv $file.perl $file [ ! -f $file -a -f $file.python ] && mv $file.python $file done fi $PCP_SHARE_DIR/lib/lockpmns $NAMESPACE trap "$PCP_SHARE_DIR/lib/unlockpmns \$NAMESPACE; rm -rf $pcptmp $pmdatmp; exit" 0 1 2 3 15 echo "Updating the Performance Metrics Name Space (PMNS) ..." # Install the namespace # if [ ! -f $NAMESPACE ] then # We may be installing an agent right after an install - # before pmcd startup, which has a pre-execution step of # rebuilding the namespace root. Do so now. if [ -x $PMNSDIR/Rebuild ] then echo "$prog: cannot Rebuild the PMNS for \"$NAMESPACE\"" exit 1 fi cd $PMNSDIR ./Rebuild -dus cd $__here forced_restart=true fi for __n in $pmns_name do if pminfo $__ns_opt $__n >/dev/null 2>&1 then cd $PMNSDIR if pmnsdel -n $PMNSROOT $__n >$tmp/base 2>&1 then pmsignal -a -s HUP pmcd >/dev/null 2>&1 # Make sure the PMNS timestamp will be different the next # time the PMNS is updated (for Linux only 1 sec resolution) sleep 2 else if grep 'Non-terminal "'"$__n"'" not found' $tmp/base >/dev/null then : elif grep 'Error: metricpath "'"$__n"'" not defined' $tmp/base >/dev/null then : else echo "$prog: failed to delete \"$__n\" from the PMNS" cat $tmp/base exit 1 fi fi cd $__here fi # Put the default domain number into the namespace file # # If there is only one namespace, then the pmns file will # be named "pmns". If there are multiple metric trees, # subsequent pmns files will be named "pmns." # # the string "pmns" can be overridden by the Install/Remove # scripts by altering $pmns_source # if [ "$__n" = "$iam" -o "$__n" = "$pmns_name" ] then __s=$pmns_source else __s=$pmns_source.$__n fi sed -e "s/$SYMDOM:/$domain:/" <$__s >$PMNSDIR/$__n cd $PMNSDIR if pmnsadd -n $PMNSROOT $__n then pmsignal -a -s HUP pmcd >/dev/null 2>&1 # Make sure the PMNS timestamp will be different the next # time the PMNS is updated (for Linux only 1 sec resolution) sleep 2 else echo "$prog: failed to add the PMNS entries for \"$__n\" ..." echo ls -l exit 1 fi cd $__here done trap "rm -rf $pcptmp $pmdatmp; exit" 0 1 2 3 15 $PCP_SHARE_DIR/lib/unlockpmns $NAMESPACE _install_views pmchart _install_views kmchart _install_views pmview if $do_pmda then # Terminate old PMDA # echo "Terminate PMDA if already installed ..." __pmda_cull $iam $domain # Rotate log files # if [ -f $PCP_LOG_DIR/pmcd/$iam.log ] then rm -f $PCP_LOG_DIR/pmcd/$iam.log.prev mv -f $PCP_LOG_DIR/pmcd/$iam.log $PCP_LOG_DIR/pmcd/$iam.log.prev fi # Add PMDA to pmcd's configuration file # echo "Updating the PMCD control file, and notifying PMCD ..." __pmda_add "$iam $domain $type $args" # Check that the agent is running OK # if $do_check then [ "$check_delay" -gt 5 ] && echo "Wait $check_delay seconds for the $iam agent to initialize ..." sleep $check_delay for __n in $pmns_name do $PCP_ECHO_PROG $PCP_ECHO_N "Check $__n metrics have appeared ... ""$PCP_ECHO_C" pmprobe -i $__ns_opt $__n | tee $tmp/verbose | __filter $__n if $__verbose then echo "pminfo output ..." cat $tmp/verbose fi done fi else echo "Skipping PMDA install and PMCD re-configuration" fi } _remove() { # Update the namespace # $PCP_SHARE_DIR/lib/lockpmns $NAMESPACE trap "$PCP_SHARE_DIR/lib/unlockpmns \$NAMESPACE; rm -rf $pcptmp $pmdatmp; exit" 0 1 2 3 15 echo "Culling the Performance Metrics Name Space ..." cd $PMNSDIR for __n in $pmns_name do $PCP_ECHO_PROG $PCP_ECHO_N "$__n ... ""$PCP_ECHO_C" if pmnsdel -n $PMNSROOT $__n >$tmp/base 2>&1 then rm -f $PMNSDIR/$__n pmsignal -a -s HUP pmcd >/dev/null 2>&1 sleep 2 echo "done" else if grep 'Non-terminal "'"$__n"'" not found' $tmp/base >/dev/null then echo "not found in Name Space, this is OK" elif grep 'Error: metricpath "'"$__n"'" not defined' $tmp/base >/dev/null then echo "not found in Name Space, this is OK" else echo "error" cat $tmp/base exit fi fi done # Remove the PMDA and help files # cd $__here if $do_pmda then echo "Updating the PMCD control file, and notifying PMCD ..." __pmda_cull $iam $domain if [ -f Makefile -o -f makefile -o -f GNUmakefile ] then echo "Removing files ..." $PCP_MAKE_PROG clobber >/dev/null fi for __i in *.pmchart do if [ "$__i" != "*.pmchart" ] then __dest=$PCP_VAR_DIR/config/pmchart/`basename $__i .pmchart` rm -f $__dest fi done for __i in *.kmchart do if [ "$__i" != "*.kmchart" ] then __dest=$PCP_VAR_DIR/config/kmchart/`basename $__i .kmchart` rm -f $__dest fi done if $do_check then for __n in $pmns_name do $PCP_ECHO_PROG $PCP_ECHO_N "Check $__n metrics have gone away ... ""$PCP_ECHO_C" if pminfo -n $NAMESPACE -f $__n >$tmp/base 2>&1 then echo "Arrgh, something has gone wrong!" cat $tmp/base else echo "OK" fi done fi else echo "Skipping PMDA removal and PMCD re-configuration" fi trap "rm -rf $pcptmp $pmdatmp; exit" 0 1 2 3 15 $PCP_SHARE_DIR/lib/unlockpmns $NAMESPACE } _check_userroot() { if [ "$uid" -ne 0 ] then if [ -n "$PCP_DIR" ] then : running in a non-default installation, do not need to be root else echo "Error: You must be root (uid 0) to update the PCP collector configuration." exit 1 fi fi } _check_directory() { case "$__here" in */pmdas/$iam) ;; *) echo "Error: expect current directory to be .../pmdas/$iam, not $__here" echo " (typical location is $PCP_PMDAS_DIR/$iam on this platform)" exit 1 ;; esac } # preferred public interfaces # pmdaSetup() { _setup } pmdaChooseConfigFile() { _choose_configfile } pmdaInstall() { _install } pmdaRemove() { _remove }