We currently migrate to MediaWiki from our old installation, but not all content has been migrated yet. Take a look at the Wiki Team page for instructions how to help or browse through our new wiki at wiki.linux-vserver.org to find the information already migrated.

HowTo graph vserver activity with cacti through vserver-stat output

Introduction

This document is a HOWTO describing a way to graph vservers activity using the output of the vserver-stat command. This command shows the number of processes, the memory (RSS et VSZ) usage and CPU (system and user) consumption of the vservers hosted on a physical system. We will show only how to graph memory usage.

[Cacti] is a tool to graph values, based on [RRDTool]. It's a bit like [MRTG] or [cricket].

We assume cacti is already installed, on a host called cacti.dom.tld. This document is based on cacti version 0.8.6g. The machine hosting the vservers is vs-host.dom.tld, and the vserver-stat command comes from the vserver-util package version 0.30.208

Note

You might be interessted in a [vserver plugin] for [collectd], written by Sebastian "tokkee" Harl. See his [examples]for forther information.

Getting vserver-stat output

To graph values, cacti needs to fetch theses values. The "classical" way to do that is by SNMP. In our case, this is not possible, because vserver memory usage is not reported by snmp. So we will use the output of the vserver-stat command, and we must find a way to retrieve on cacti.dom.tld the output of a command executed on vs-host.dom.tld.

Many solutions are possible. Here is one solution (as secure as possible ?).

# useradd -u 0 -o -s /usr/local/sbin/vserver-stat -m vs-stat
# ssh-keygen -t dsa -f ~/.ssh/vs-stat
$ mkdir ~vs-stat/.ssh
$ scp root@cacti.dom.tld:.ssh/vs-stat.pub ~vs-stat/.ssh/authorized_keys
# ssh -i vs-stat vs-stat@vs-host.dom.tld
# mkdir ~apache/.ssh ~cacti/.ssh
# cp ~root/.ssh/{vs-stat*,known_hosts} ~apache/.ssh/
# chown -R apache ~apache/.ssh/
# cp ~root/.ssh/{vs-stat*,known_hosts} ~cacti/.ssh/
# chown -R cacti ~cacti/.ssh/

Cacti configuration

Now we can begin the real hard part. You must be connected as an administrator on the cacti web interface.

Create a new Data Template

Go on Data Template -> New

Click on the Create button. Again, go to the Data Source Item part -> New

Click on Save

Create a new graph template

Go on Graph Template -> New

Click on the Create button. Go to Graph Template Items -> Add

Click on the Create button. Again, go to Graph Template Items -> Add

Click on the Create button. Again, go to Graph Template Items -> Add

Click on the Create button. Again, go to Graph Template Items -> Add

You can also add items to gprint the average, min or max values.

Click on Save

Create a Data Query

Create the file <cacti_dir>/resource/script_queries/vs-stat.xml :

<query>
   <name>VServer stat</name>
   <description>Retrieve vserver-stat output.</description>
   <arg_prepend>|host_hostname|</arg_prepend>
   <script_path>bash |path_cacti|/scripts/vs-stat.sh</script_path>
   <arg_index>index</arg_index>
   <arg_query>query</arg_query>
   <arg_get>get</arg_get>
   <arg_num_indexes>num_indexes</arg_num_indexes>
   <output_delimeter>:</output_delimeter>
   <index_order>vsName</index_order>
   <index_order_type>alphabetic</index_order_type>
   <index_title_format>|chosen_order_field|</index_title_format>

   <fields>
      <vsName>
         <name>vserver name</name>
         <direction>input</direction>
         <query_name>vsName</query_name>
      </vsName>
      <vsCtx>
         <name>Context number</name>
         <direction>input</direction>
         <query_name>vsCtx</query_name>
      </vsCtx>
      <vsProc>
         <name>Number of processes</name>
         <direction>output</direction>
         <query_name>vsProc</query_name>
      </vsProc>
      <vsVsz>
         <name>Virtual memory used</name>
         <direction>output</direction>
         <query_name>vsVsz</query_name>
      </vsVsz>
      <vsRss>
         <name>Real memory used</name>
         <direction>output</direction>
         <query_name>vsRss</query_name>
      </vsRss>
      <vsUserTime>
         <name>CPU user time</name>
         <direction>output</direction>
         <query_name>vsUserTime</query_name>
      </vsUserTime>
      <vsSysTime>
         <name>CPU system time</name>
         <direction>output</direction>
         <query_name>vsSysTime</query_name>
      </vsSysTime>
   </fields>
</query>

You also have to create the script <cacti_dir>/scripts/vs-stat.sh, in charge of getting and parsing the result of vserver-stat (you should probably rewrite this awfull script, perhaps in perl ...)

#!/bin/bash

log="/tmp/cacti-vs.log"
#log="/dev/null"
echo "== $(date) ; $(id) ; $*" >> $log
#
# stat_<nom variable>=<colonne de vserver-stat>
#
stat_vsCtx=1
stat_vsProc=2
stat_vsVsz=3
stat_vsRss=4
stat_vsUserTime=5
stat_vsSysTime=6
stat_vsUptime=7
stat_vsName=8
# Numero de colonne contenant l'index utilise par cacti
index="8"

hote=$1
shift
action=$1
shift

# Nom du pseudo-vserver qui reflete le total de tous les vservers
total="_total"

tmp=$(mktemp /tmp/vserver-stat-$hote-XXXXXX)
ssh -l vs-stat $hote | grep "^[0-9]" | sed -e 's/\r//g' > $tmp 2>>$log
echo "Contenu de vserver-stat : " >> $log
cat $tmp >> $log

get_val () {
        col=$1
        vs=$2
        n=$(eval echo \$stat_$col)
        echo "get_val $col pour $vs (index=$index stat_$col=$n)" >> $log
        if [ "$vs" != $total ]; then
                echo " debug : awk \'\$$index \~ /^$vs\$/ {print \$$n}\' $tmp" >> $log
                valeur=$(eval awk \'\$$index \~ /^$vs\$/ {print \$$n}\' $tmp)
        else
                [ $col = "vsName" ] && { echo "$total"; return; }
                [ $col = "vsCtx" ] && { echo "-1"; return; }
                valeur=0
                for vs in $(get_indexes)
                do
                    echo "(query $col) Appel de get_val $col pour $vs" >> $log
                    let valeur+=$(get_val $col $vs)
                done
        fi
        echo " valeur brute lue : $valeur"  >> $log
        case $col in
        "vsVsz"|"vsRss")
                e=$(echo $valeur | sed -e 's/M/ * 1024 * 1024 /' -e 's/G/ * 1024 * 1024 * 1024/')
                echo " calcul memoire : $e" >> $log
                valeur=$(echo "scale=0; $e / 1" | bc) # / 1 : truc pour obtenir la partie entiere
                ;;
        "vsUserTime"|"vsSysTime"|"vsUptime")
                e=$(echo $valeur | sed  -e 's/^\([0-9]*\)d\([0-9]*\)h\([0-9]*\)$/\1 \\* 24 \\* 3600 + \2 \\* 3600 + \3 \\* 60/' \
                                        -e 's/^\([0-9]*\)h\([0-9]*\)m\([0-9]*\)$/\1 \\* 3600 + \2 \\* 60 + \3/' \
                                        -e 's/^\([0-9]*\)m\([0-9]*\)s\([0-9]*\)$/\1 \\* 60 + \2/')
                valeur=$(eval expr $e)
        esac
        echo $valeur
}

get_indexes () {
        awk -v i=${index} '{print $i}' $tmp
}

case "$action" in
"index")
        echo " => INDEX $(get_indexes)" >> $log
        echo $total
        get_indexes
        s=$?
        ;;
"query")
        echo " => QUERY" >> $log
        col=$1
        if eval test -z \$stat_$col
        then
                echo "Erreur, colonne \`$col' inconnue."
                exit 1
        fi
        for vs in $(get_indexes) $total
        do
                echo "(query $col) Appel de get_val $col pour $vs" >> $log
                valeur=$(get_val $col $vs)
                echo $vs:$valeur
        done
        ;;
"get")
        col=$1
        vs=$2
        echo $(get_val $col $vs)
        ;;
*)
        echo "Erreur";
        s=1
        ;;
esac

rm $tmp >> $log 2>&1
exit $s

Go to Data Query -> Add

Click on Create

Select the newly created query template vs-stat and go to Associated Graph Templates -> Add

Click on Save

Modify Host template

Go in the Host template part

Create a Device

Go in the Devices part -> Add

Now, click on Create Graphs for this Host

Make the graph appear in the graph tree

Go in the Graph Trees part