[mrtg-developers] mrtg 3 ... a mockup configuration file

Todd Caine todd_caine at eli.net
Mon May 1 20:48:56 MEST 2000


Hello,

I personally like the idea of a Perl module used to build
the configuration file for a monitorable network device. 
Although, I don't think that it would be a good idea to base
a leaf(or graph) on an IP address.  The chance of an IP
address changing on an interface is fairly high.  The
question is when will the IP address change?  The interface
name would probably be a better solution, as long as you
compare the ifIndex.  

I've been working on a Perl configuration file which could
be used by a generic grapher to build a webpage of graphs
for a given device.  Maybe this will give you some ideas of
what you might want to do or don't do in MRTG-3.  

The configuration file can incorporate a list of interfaces,
chassis data, or aggregates of like RRDs.  Here is a short
example of the configuration file for router interfaces
which is generated by a script every half hour(from a CRON
job) by doing snmpbulkwalks on the ifOperStatus, ifSpeed,
ifIndex, ifName, and ifAlias oids.  

#!/usr/local/bin/perl -w

#  Targets.pl  -  configuration file for generic grapher

use strict;

#
# (DSS) Data Source constants for anonymous array indices
#

use constant NAME       => 0;
use constant N2BITS     => 1;	#  Number to multiply the data
source value by to convert to
				#  bits.  Use 1 if no conversion is necessary
use constant LEGEND     => 2;
use constant GRAPH      => 3;

#
# A list of graphs
#

our @graphs = ({
  vert_label    => 'bits per second',
  rrds          => [{
                        file_path       =>
'/usr/local/rrd/router/cr01-wash/srp20.rrd',
                        dss             => [['ds0', 8,
'#00cc00:Input', 'AREA'],
                                            ['ds1', 8,
'#0000FF:Output', 'LINE1']],
                   }]  
},{
  vert_label    => 'bits per second',
  rrds          => [{
                        file_path       =>
'/usr/local/rrd/router/cr01-wash/pos100.rrd',
                        dss             => [['ds0', 8,
'#00cc00:Input', 'AREA'],
                                            ['ds1', 8,
'#0000FF:Output', 'LINE1']],
                   }]  
},);


#
# A list of targets
#

our @targets = ({
    name        => 'SRP2/0',
    description => 'SRP2/0: _BB_, SRP RING',
    maximum     => 622000000,
    index       => 2,
    graph_name  => '/usr/local/rrd-cache/cr01-scrl_srp20'
  },{
    name        => 'POS10/0',
    description => 'POS10/0: _BB_, Backbone link',
    maximum     => 622000000,
    index       => 4,
    graph_name  => '/usr/local/rrd-cache/cr01-scrl_pos100'
  },);


#
#  subroutines
#

sub num_graphs
{
  return scalar(@graphs);
}

sub vertical_label
{
  my ($graph_index) = shift;
  return $graphs[$graph_index]->{vert_label};
}

sub num_rrds
{
  my ($graph_index) = shift;
  return @{$graphs[$graph_index]->{rrds}};
}

sub num_dss
{
  my ($graph_index, $rrd_index) = @_;
  return
scalar(@{${$graphs[$graph_index]->{rrds}}[$rrd_index]{dss}});
}

sub file_path
{
  my ($graph_index, $rrd_index) = @_;
  return
${$graphs[$graph_index]->{rrds}}[$rrd_index]{file_path};
}

sub dss
{
  my ($graph_index, $rrd_index) = @_;
  return
@{${$graphs[$graph_index]->{rrds}}[$rrd_index]{dss}};
}

sub ds_name
{
  my ($graph_index, $rrd_index, $ds_index) = @_;
  #  darn that was nasty to write
  return
${${${$graphs[$graph_index]->{rrds}}[$rrd_index]{dss}}[$ds_index]}[NAME];
}

sub n2bits
{
  my ($graph_index, $rrd_index, $ds_index) = @_;
  return
${${${$graphs[$graph_index]->{rrds}}[$rrd_index]{dss}}[$ds_index]}[N2BITS];
}

sub legend
{
  my ($graph_index, $rrd_index, $ds_index) = @_;
  return
${${${$graphs[$graph_index]->{rrds}}[$rrd_index]{dss}}[$ds_index]}[LEGEND];
}

sub graph
{
  my ($graph_index, $rrd_index, $ds_index) = @_;
  return
${${${$graphs[$graph_index]->{rrds}}[$rrd_index]{dss}}[$ds_index]}[GRAPH];
}

sub description
{
  my $graph_index = shift;
  return ${$targets[$graph_index]}{description};
}

sub maximum
{
  my $graph_index = shift;
  return ${$targets[$graph_index]}{maximum};
}

sub graph_name
{
  my $graph_index = shift;
  return ${$targets[$graph_index]}{graph_name};
}

#  index() was already taken by perl, so cindex() returns
the interfaces index
sub cindex {
    my $index = shift;
    foreach my $target (@targets) {
      if (${$target}{index} == $index) {
        return ${$target}{name};
      }
    }
    return;
}


1;  

##############################################################################

Notice the subroutines are generated with the config file to
give easy access
to the data stuctures contained within the config file.  Any
suggestions?

Here is example code for how someone could use this?

use RRDs;
use CGI;

my $cgi = new CGI;
my $device = $cgi->param('device');

#  graph the correct config file
require "$base_dir/$device/interfaces/Targets.pl";

#  grapher() returns a list of lists containing graph
arguments and a list of graph names
#  grapher() actually uses most of the subroutines generated
for the Targets.pl file
my (@graph_args, @graph_names) = grapher($device);

#  build the graphs
foreach my $graph_args (@graph_args) {
  RRDs::graph(@{$graph_args});
}

print $cgi->header,
      $cgi->start_html;

foreach (0 .. $#graph_args){
   print qq{
     <P ALIGN="center"><IMG
SRC="$url_dir/$graph_names[$_]"><BR>
   };  
}

print $cgi->end_html;

##############################################################################

The generic grapher uses both the @graph array and the
@targets array to build a simple webpage of graphs with
labels and legends, etc...  The interfaces collector that I
wrote uses the @targets array to compare the interface name
with the interface index.  It also checks to see if the
maximum speed is over 100M to determine whether or not to
collect data from the 32bit register(ifInOctets) or the 64
bit register(ifHCInOctets).


So here is the breakdown of the data collection process:
1.  Every half hour the target files are generated for each
device.
2.  Once a day, a script performs an RRD::tune on each RRD
to adjust the 
    rrd-max based on the max(ifSpeed) found in the targets
file.
3.  The collector runs every 5 minutes to query devices and
update the RRDs.
4.  The grapher only runs when a form is submitted and
builds a unique filename
    to avoid erroneous caching.  i.e..
cr01-wash_srp200_998404980.png


If anyone is interested in what the grapher() subroutine
actually looks like, let me know.  Any comments, criticism
(constructive only please) would be greatly appreciated.


<!--	Todd Caine - tcaine at eli.net
	Electric Lightwave, Inc.
	4400 NE 77th Avenue
	Vancouver, WA	98662
	Direct Dial: (360) 816-4344	 //-->

--
Unsubscribe mailto:mrtg-developers-request at list.ee.ethz.ch?subject=unsubscribe
Help        mailto:mrtg-developers-request at list.ee.ethz.ch?subject=help
Archive     http://www.ee.ethz.ch/~slist/mrtg-developers



More information about the mrtg-developers mailing list