munin-contrib/plugins/xen/xen_cpu_v2

194 lines
4.3 KiB
Perl
Executable File

#!/usr/bin/perl -w
#
# xen_cpu_v2.pl 1.00
# Script to minitor the CPU usage of Xen domains
# Zoltan HERPAI (c) 2009, wigyori@uid0.hu
#
# Based loosely on Adam Crews' xen_cpu script
#
# This script tries to measure the CPU usage of the Xen guests
# accurately.
# The problem with the current monitoring script is that these
# scripts use the CPU output of xentop or xm list, which might be
# inaccurate due to the resources used up at the time of the query by
# the xm or xentop command.
#
# This script stores the previous value of the CPU sec value of the given
# guests in a tempfile, then does some simple calculations to get the real
# CPU usage percentage of the guests.
#
#%# family=auto
#%# capabilities=autoconf
use strict;
use POSIX;
# Define where to find xm tools
my $XM = '/usr/sbin/xm';
my $XMTOP = '/usr/sbin/xentop';
my $curtime = time();
my $basename = `/usr/bin/basename $0`; chop ($basename);
my $TEMPFILE = "/tmp/$basename";
my $debug = 0;
##############
# You should not need to edit anything below here
#
$ENV{PATH} = '/bin:/usr/bin:/usr/sbin';
my $arg;
if ( defined($ARGV[0]) )
{
if ( $ARGV[0] eq 'config' )
{
$arg = 'config';
}
if ( $ARGV[0] eq 'autoconf' )
{
$arg = 'autoconf';
}
if ( $arg eq 'autoconf')
{
if ( -e $XM && -e $XMTOP )
{
print "yes\n";
exit 0;
}
else
{
print "no ($XM and/or $XMTOP not found\n";
exit 1;
}
}
if ( $arg eq 'config' )
{
my %cnf;
%cnf = (
'graph_title' => 'Xen Domain CPU Usage v2',
'graph_args' => '--base 1000 -l 0 --upper-limit 100 --rigid',
'graph_vlabel' => 'Percent (%)',
'graph_category' => 'virtualization',
'graph_info' => 'Display the % of CPU Usage for each domain',
);
my @domains = `$XM list`;
my $cnt = 0;
shift(@domains); # we dont need the header line
foreach my $domain ( @domains )
{
my ($dom,undef) = split(/\s/, $domain, 2);
$dom =~ s/[-.]/_/g;
$cnf{ "$dom" . '.label' } = "$dom";
$cnf{ "$dom" . '.draw' } = 'STACK';
$cnf{ "$dom" . '.min' } = '0';
$cnf{ "$dom" . '.max' } = '100';
$cnf{ "$dom" . '.info' } = '% CPU used for ' . "$dom";
# $cnf{ "$dom" . '.draw' } = 'AREA';
if ( $cnt == 0 )
{
$cnf{ "$dom" . '.draw' } = 'AREA';
}
$cnt++;
}
foreach my $key (sort(keys(%cnf)))
{
print "$key $cnf{$key}\n";
}
exit 0;
}
}
my @xmlist = `$XM list`;
shift (@xmlist);
my %dom; my $name; my $oldtime;
# Read old data
if ( -e $TEMPFILE )
{
open(FH, "<", $TEMPFILE) or die $!;
$oldtime = <FH>;
if ( $debug )
{
print "Oldtime: $oldtime\n";
}
while (<FH>)
{
# Get the guest name and its CPU usage, and store it in $dom
$_ =~ /(\S+)\s+\S+\s+\S+\s+\d+\s+\S+\s+(\S+)/;
$dom{$1}->{'oldtime'} = $2;
}
close FH;
}
my $diff; my $cpusum = 0;
foreach my $domain ( @xmlist )
{
# Get the domains' name and current CPU usage, store it in $dom
$domain =~ /(\S+)\s+\S+\s+\S+\s+\d+\s+\S+\s+(\S+)/;
$dom{$1}->{'newtime'} = $2;
$diff = $dom{$1}->{'newtime'} - $dom{$1}->{'oldtime'};
$diff = sprintf("%.2f", $diff);
# Calc the diff between old and new cputime, or reset the counter
if ( $diff < 0 )
{
$diff = $dom{$1}->{'newtime'};
}
$dom{$1}->{'diff'} = $diff;
# Calc a sum CPU usage
$cpusum = $cpusum + $diff;
}
my $numcpus = `$XM info |grep nr_cpus |cut -d \: -f 2`;
my $timediff = $curtime - $oldtime;
my $tcpuavail = $numcpus * $timediff;
if ( $debug )
{
print "UsedCPUtime sum: $cpusum\n";
print "CPUs: $numcpus\n";
print "Timediff: $timediff\n";
print "Total CPU time available: $tcpuavail\n";
}
my $key; my $value;
while (($key, $value) = each %dom)
{
# Calc a percentage based on the used CPU time sum
my $tmp = 0;
$tmp = ( $dom{$key}->{'diff'} / $cpusum ) * 100;
$dom{$key}->{'pc_time'} = sprintf("%.2f", $tmp);
# Calc a percentage based on the _total_ available CPU time
$tmp = 0;
if ($tcpuavail != 0) {
$tmp = ( $dom{$key}->{'diff'} / $tcpuavail ) * 100;
$dom{$key}->{'pc_tcpu'} = sprintf("%.2f", $tmp);
} else {
$dom{$key}->{'pc_tcpu'} = "U";
}
if ( $debug )
{
print "$key newtime: ".$dom{$key}->{'newtime'}.", oldtime: ".$dom{$key}->{'oldtime'}.", diff: ".$dom{$key}->{'diff'}.", pc_bytime ".$dom{$key}->{'pc_time'}.", pc_bytcpu ".$dom{$key}->{'pc_tcpu'}."\n";
}
print "$key.value ".$dom{$key}->{'pc_tcpu'}."\n";
}
# We'll need to log out the current "xm list" output, and the current time also.
open(FH, ">", $TEMPFILE) or die $!;
print FH $curtime."\n";
print FH @xmlist;
close FH;