Writing Munin Plugins pt3: some Stats about VMWare Fusion

In a project where we had the need for VMs being capable of doing CI for Java and also doing CI for iOS Application (using XCode Build Bots), we decided to go with a Mac OS Server as the Host Platform and using VMWare Fusion as the base Virtualisation System. We had several VMs there (Windows, Solaris, Linux and Mac OS). Doing a proper Monitoring for theses VMs was not that easy. We already had a working Munin Infrastructure, but no Plugin for displaying VMWare Fusion Stats existed.

The first approach was to use the included VMTools for gathering the information, since we already used them to start/stop/restart VMs via CLI/SSH:

#!/bin/bash

echo "starting VMS..."
VM_PATH=/Users/Shared/VMs
TOOL_PATH=/Applications/VMTools
$TOOL_PATH/vmrun -T fusion start $VM_PATH/Mac_OS_X_10.9.vmwarevm/Mac_OS_X_10.9.vmx nogui

or

#!/bin/bash

echo "starting VMS..."
VM_PATH=/Users/Shared/VMs
TOOL_PATH=/Applications/VMTools
$TOOL_PATH/vmrun -T fusion stop $VM_PATH/Mac_OS_X_10.9.vmwarevm/Mac_OS_X_10.9.vmx

But it was very hard to receive the interesting Data from the Log Files (statistica data is only really supported in VMWare ESXi). So we choose the direct way, to receive the live data, using ps. So this approach is also applicable for other Applications as well.

Our goal was to get at lease three Graphs (% of used CPU, % of used Memory and physically used Memory) sorted by VM Name.

ps -A | grep vmware-vmx

provides us with a list of all running vmware processes. Since we only need specific Data, we add some more filters:

ps -A -c -o pcpu,pmem,rss=,args,comm -r | grep vmware-vmx

29,4 14,0 2341436   J2EE.vmx                                                 vmware-vmx
1,7 12,9 2164200    macos109.vmx                                             vmware-vmx
1,4 17,0 2844044    windows.vmx                                              vmware-vmx
0,7  6,0 1002784    Jenkins.vmx                                              vmware-vmx
0,0  0,0    624     grep vmware-vmx      

where this is the description (man ps) of the used columns:

  • %cpu percentage CPU usage (alias pcpu)
  • %mem percentage memory usage (alias pmem)
  • rss the real memory (resident set) size of the process (in 1024 byte units).

You might see several things: First we have our data and the Name of each VM. Second, we have to get rid of the last line, since that is our grep process. Third, we might need to do some String Operations/Number Calculation to get some valid Data at the end.

Since Perl is a good choice if you need to do some String Operations, the Plugins is written in Perl :-).

Let’s have a look.
The Config Element is quite compact (e.g. for the physical mem):

my $cmd = "ps -A -c -o pcpu,pmem,rss=,args,comm -r | grep vmware-vmx";
my $output = `$cmd`;
my @lines=split(/\n/,$output);
...
if( $type eq "mem" ) {
    print $base_config;
    print "graph_args --base 1024 -r --lower-limit 0\n";    
    print "graph_title absolute Memory usage per VM\n";
    print "graph_vlabel Memory usage\n";
    print "graph_info The Graph shows the absolute Memory usage per VM\n";  
    foreach my $line(@lines) {
        if( $line  =~ /(?<!grep)$/ ) {  
            my @vm = ();
            my $count = 0;
            my @array=split(/ /,$line); 
            foreach my $entry(@array) {
                if( length($entry) > 2 ){
                    $vm[$count]=$entry;
                    $count++;
                }
            }
            $vm[3] = clean_vmname($vm[3]);  
            if( $vm[3] =~ /(?<!comm)$/) {           
                if( $lcount > 0 ){
                    print "$vm[3]_mem.draw STACK\n";
                } else {
                    print "$vm[3]_mem.draw AREA\n";
                }
                print "$vm[3]_mem.label $vm[3]\n";
                print "$vm[3]_mem.type GAUGE\n";            
                $lcount++;      
            }           
        }
    }                       
}

After the basic Setup (Category, Graph Type, Labels, etc. ) we go through each line of the output from the ps command, filtering the line containing grep.
We use the stacked Graph Method, so the first entry has to be the base Graph, the following ones will just be layer on top of the first. To get clean VM Names, we have a quite simple function clean_vmname:

sub clean_vmname {
    my $vm_name = $_[0];
    $vm_name =~ s/\.vmx//;
    $vm_name =~ s/\./\_/g;
    return $vm_name;
}

The Code, that delivers the Data looks similar. We just piping the values from the ps command to the output:

foreach my $line(@lines) {
    if( $line  =~ /(?<!grep)$/ ) {
        my @vm = ();
        my $count = 0;
        my @array=split(/ /,$line); 
        foreach my $entry(@array) {
            if( length($entry) > 2 ){
                $vm[$count]=$entry;
                $count++;
            }
        }
        $vm[3] = clean_vmname($vm[3]);
        if( $vm[3] =~ /(?<!comm)$/) {   
            if( $type eq "pcpu" ) {
                print "$vm[3]_pcpu.value $vm[0]\n";
            }
            if( $type eq "pmem" ) {
                print "$vm[3]_pmem.value $vm[1]\n";
            }
            if( $type eq "mem" ) {
                my $value =  ($vm[2]*1024);
                print "$vm[3]_mem.value $value\n";
            }
        }
    }
}   

You can find the whole plugin here on GitHub.

Here are some example Graphs you will get as a result:

 

fusion_mem-month fusion_pcpu-month fusion_pmem-month

Adding Background Image to SVG Circles

If you want to create nifty Graphics and Animation in the web, you cannot avoid d3.js. D3.js uses SVG as the basic Displaying Technologie. And sometimes you know, why SVG had such a hard time persuading developers.

It is a simple task:
Creating a Circle with an image as a background. The everyday Web-Developer would just create a Circle Element and would try to add the Background Image via CSS.
But that did not work at all.
After asking friend Google for a while, i found the answer to this question over at stackoverflow.
So you need SVG patterns (never heard about them before). And reference the image-pattern via the ID.

So here is a brief example:


<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events" width="400" height="400">
    <defs>
        <pattern id="image" x="-32" y="-32" patternUnits="userSpaceOnUse" height="64" width="64">
            <image x="0" y="0" height="64" width="64" xlink:href="http://0.gravatar.com/avatar/902a4faaa4de6f6aebd6fd7a9fbab46a?s=64"/>
        </pattern>
    </defs>
    <line class="link" style="stroke: #9ecae1; stroke-width: 1;" x1="200" y1="0" x2="200" y2="400"/>
    <text dy=".35em" transform="translate(0 , 190)">0,200</text>
    <line class="link" style="stroke: #9ecae1; stroke-width: 1;" y1="200" x1="0" y2="200" x2="400"/>
    <text dy=".35em" transform="translate(200 , 10)">200,0</text>
    <circle id="top" transform="translate(200,200)" r="32" fill="url(#image)"/>
</svg>

test

We used that in our small project GitHubble (you may find the sources here).

Plotting UNIX Processes with DOT

Inspired by this Post, i started playing around with ps, nodejs and GraphViz.

After reading some ps man Pages, i found the necessary ps parameters.
For MacOS i used

ps -A -c -o pid,ppid,pcpu,comm,uid -r

For Linux i used

ps -A -o pid,ppid,pcpu,comm,uid

You then get some Output like:

    PID    PPID %CPU COMMAND           UID
      1       0  0.0 init                0
      2       1  0.0 kthreadd            0
      3       2  0.0 migration/0         0
      4       2  0.0 ksoftirqd/0         0
      5       2  0.0 migration/0         0
      6       2  0.0 watchdog/0          0

So you are getting the ProcessID, the Parent ProcessID, CPU Usage (i am not using for plotting atm), the Command and the UserID.
I created a simple Node Script, that you can run either directly under MacOS (for all other Unices you need to update the ps command).
Or you can give the script a previous generated ps output for parsing:

plotPS.sh /tmp/host.log > /tmp/host.dot

The resulting DOT Code is then Piped into a DOT File.

Here are some examples:

My MacOS Laptop:

MacBook Pro
bigger

A Sinlge Linux Host with Dovecot and Apache2/Passenger:

Apache2 / Mail Server
bigger

A Linux Host with OpenVZ and KVM Instances:

OpenVZ / KVM Host
bigger

In the original Post, there were also Dependencies between CPU Usage and Size of the Graphical Nodes, also it would be more useful to only plotting the processes of one VM from its inside.
But i guess for one evening the result is okay :-).

SVG – the lost son of formats

I was on the Chemnitz Linux Days last weekend. Besides great other talks a saw “Free your slides – Vortragsfolien im Browser anzeigen” from Sirko Kemter. He talked about a tiny tool called jessyink for creating Slides out of inkscape SVGs. I did a small SVG-Demo some months ago using RaphaelJS and a draft about this project exists since then. So instead of trying to complete this draft and published it, i decided to ask what area of SVG might be of interest here. Basic SVG elements? Animation? It might need some time, but i re-discovered what a great format SVG is and really want to create some posts for that.

 

Philipps 5 mins: Graph-Fun with AJAX and Canvas

I always searched for an efficient way add dynamic diagrams to a web-project without using flash or other plugin-based magic.
With the support of the canvas tag element in almost all mainstream browser, i thought it would be a good time for creating a short demo how things workout.
You will need at least two Parts for this demo. First of all you will need a Source JSON feed. For this demo i just hacked together a very basis PHP script:

<?php
header('Content-type: application/json');
echo'{';
echo '"value":"' . rand(0, 60) . '"';
echo '}';
?>

The result is something like:

{"value":"34"}

Secondly you need a Webpage, where you want to insert your canvas element, load the data from the json feed and draw the changing values to the canvas element.
For a better performance, we will implementing pulling the data and drawing the data within two parallel cycles. The Common data Storage will be an array of 300 value (for our diagram with a width of 300px).
We are using two additional JS Files. The first we need for creating our XHTTPRequest Object and handling the response within a callback method. The second script is for parsing the JSON Feed as a Javascript Object in a safe way (an ordinary eval works, but is to unsecury).
Our main-script works in several steps:
First we initialize an array with empty elements:

function init(){
    for(var i=0; i < 300; i++){
        randomValues[i] = 0;
    }
}

 


This step is optional, but then you have a nice “zero line” at the beginning.

Secondly we have a method, that pushes a new value to the existing array, and drops the first entry, if the length of the array is greater than 300.

function addValue(arr, value){
    if(arr.push(value) > 300){
        arr.shift();
    }
}

 


The next two methods are necessary for sending our ajax-request and for handling the response in a callback method.
Basically the callback method just calls the addValue method.

The timeout variable is set to 200 ms. So the script calls our backend periodically every 200 ms and then adds a new value to our array.

function pullValue(){
    sendRequest('random.php',handleRandomRequest);
    setTimeout(pullValue, timeout);
}

function handleRandomRequest(req) {
    var text = JSON.parse(req.responseText);
    addValue(randomValues, text.value);
}

The last method is for the drawing functionality:

function draw(){
    ctx.clearRect(0, 0, 300, 60);
    ctx.fillStyle = "rgba(101,101,101, 0.5)";
    ctx.fillRect (0, 0, 300, 60);
    ctx.lineWidth = 1;
    ctx.strokeStyle = 'blue';
    ctx.beginPath();
    ctx.moveTo(1, 60-parseInt(randomValues[0]));
    for (var i=1; i<randomValues.length; i++){
        value = 60-parseInt(randomValues[i]);
        ctx.lineTo(i,value);
    }
    ctx.stroke();
    setTimeout(draw, timeout);
}

ctx is a 2d context of the canvas element.
On every call of the draw method, all elements of the array are painted. The first element is always the start point.
Because the canvas coordinate system has the point 0,0 in the upper left corner but the 0,0 point of our diagram should be in the lower left corner, you have to subtract the array-values from 60 to get the right drawing coordinate.
This method also runs periodically every 200 ms. But it also works for two times for pulling the data an drawing it.

Here you can see the script in action

Splines mit dem HTML Canvas Tag

Splines innerhalb eines Canvas Tags sind mit ein wenig Javascript recht schnell machbar! (drumherum dann noch den ganzen HTML-Kram denken):

<canvas width=”150″ height=”150″ id=”myCanvas1″></canvas>
<script type=”text/javascript”>
function draw1(){
    var myCanvas1 = document.getElementById(‘myCanvas1′);
    myCanvas1.style.border = “1px black dashed”;   

    var ctx = myCanvas1.getContext(’2d’);

    ctx.beginPath();   
    ctx.strokeStyle = “#dedede”;
    for (i=1;i<15;i++){
        ctx.moveTo(i10,0);
        ctx.lineTo(i10,150);
    }
    for(j=1;j<15;j++){
        ctx.moveTo(0,j10);
        ctx.lineTo(150,j10);
    }
    ctx.stroke();   

    //Steuerpunkte malen (nur zur Verdeutlichung)
    ctx.beginPath();
    ctx.lineWidth = 2;
    ctx.strokeStyle = “rgb(0,200,0)”;
    ctx.moveTo(0,135);
    ctx.lineTo(60, 130);
    ctx.arc(60,130,3,0,360, false);
    ctx.lineTo(75,75);
    ctx.lineTo(90,20);
    ctx.arc(90,20,3,0,360, false);
    ctx.lineTo(150, 15);
    ctx.stroke();

    //quadraticCurveTo malen
    ctx.beginPath();
    ctx.strokeStyle = “#000000″;
    ctx.moveTo(0,135);
    ctx.lineWidth = 4;
    ctx.quadraticCurveTo(60, 130, 75, 75);
    ctx.moveTo(75,75);
    ctx.quadraticCurveTo(90, 20, 150, 15);
    ctx.stroke();

}
draw1();
 </script>

Das macht einem dann ein:

Das ganze funktioniert mit Firefox ab Version 1.5 (aber erst ab 2.x gehen auch quadratic Splines), Opera 9 und neueren Safaries.
Infos hier:

Die grünen Linien habe ich nur gemacht, damit man die Stützpunkte der Splines besser sehen kann.
Ach was war die CG-Vorlesung doch schön 😀

Blogged with the Flock Browser