summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorNiko Tyni <ntyni@iki.fi>2005-02-20 22:40:58 +0100
committerNiko Tyni <ntyni@iki.fi>2005-02-20 22:40:58 +0100
commit2d8297b72b98005b7220c1ab47e9eeeb68711ac6 (patch)
treeba0e1772fe8a7f988e853379fd1a2923d6f8a480 /lib
parent41b34e09a8692d9253d39d893ad09fdbfec0353c (diff)
downloadsmokeping-2d8297b72b98005b7220c1ab47e9eeeb68711ac6.tar.gz
smokeping-2d8297b72b98005b7220c1ab47e9eeeb68711ac6.tar.xz
* check at startup that existing RRD files conform to the config specifications -- niko
- new Smokeping::RRDtools module - note in CHANGES and smokeping_upgrade
Diffstat (limited to 'lib')
-rw-r--r--lib/Smokeping.pm10
-rw-r--r--lib/Smokeping/RRDtools.pm169
2 files changed, 177 insertions, 2 deletions
diff --git a/lib/Smokeping.pm b/lib/Smokeping.pm
index 65ac92b..82113a3 100644
--- a/lib/Smokeping.pm
+++ b/lib/Smokeping.pm
@@ -16,6 +16,7 @@ setlogsock('unix')
if grep /^ $^O $/xo, ("linux", "openbsd", "freebsd", "netbsd");
use File::Basename;
use Smokeping::Examples;
+use Smokeping::RRDtools;
# globale persistent variables for speedy
use vars qw($cfg $probes $VERSION $havegetaddrinfo $cgimode);
@@ -359,8 +360,7 @@ sub init_target_tree ($$$$) {
}
my $pings = $probeobj->_pings($tree);
- if (not -f $name.".rrd"){
- my @create =
+ my @create =
($name.".rrd", "--step",$step,
"DS:uptime:GAUGE:".(2*$step).":0:U",
"DS:loss:GAUGE:".(2*$step).":0:".$pings,
@@ -369,10 +369,16 @@ sub init_target_tree ($$$$) {
(map { "DS:ping${_}:GAUGE:".(2*$step).":0:180" }
1..$pings),
(map { "RRA:".(join ":", @{$_}) } @{$cfg->{Database}{_table}} ));
+ if (not -f $name.".rrd"){
do_debuglog("Calling RRDs::create(@create)");
RRDs::create(@create);
my $ERROR = RRDs::error();
do_log "RRDs::create ERROR: $ERROR\n" if $ERROR;
+ } else {
+ shift @create; # remove the filename
+ my $comparison = Smokeping::RRDtools::compare($name.".rrd", \@create);
+ die("Error: RRD parameter mismatch ('$comparison'). You must delete $name.rrd or fix the configuration parameters.\n")
+ if $comparison;
}
}
}
diff --git a/lib/Smokeping/RRDtools.pm b/lib/Smokeping/RRDtools.pm
new file mode 100644
index 0000000..7260cca
--- /dev/null
+++ b/lib/Smokeping/RRDtools.pm
@@ -0,0 +1,169 @@
+package Smokeping::RRDtools;
+
+=head1 NAME
+
+Smokeping::RRDtools - Tools for RRD file handling
+
+=head1 SYNOPSYS
+
+ use Smokeping::RRDtools;
+ use RRDs;
+
+ my $file = '/path/to/file.rrd';
+
+ # get the create arguments that $file was created with
+ my $create = Smokeping::RRDtools::info2create($file);
+
+ # use them to create a new file
+ RRDs::create('/path/to/file2.rrd', @$create);
+
+ # or compare them against another create list
+ my @create = ('--step', 60, 'DS:ds0:GAUGE:120:0:U', 'RRA:AVERAGE:0.5:1:1008');
+ my $comparison = Smokeping::RRDtools::compare($file, \@create);
+ print "Create arguments didn't match: $comparison\n" if $comparison;
+
+=head1 DESCRIPTION
+
+This module offers two functions, C<info2create> and C<compare>.
+The first can be used to recreate the arguments that an RRD file
+was created with. The second checks if an RRD file was created
+with the given arguments.
+
+The function C<info2create> must be called with one argument:
+the path to the interesting RRD file. It will return an array
+reference of the argument list that can be fed to C<RRDs::create>.
+Note that this list will never contain the C<start> parameter,
+but it B<will> contain the C<step> parameter.
+
+The function C<compare> must be called with two arguments: the path
+to the interesting RRD file, and a reference to an argument list that
+could be fed to C<RRDs::create>. The function will then simply compare
+the result of C<info2create> with this argument list. It will return
+C<undef> if the arguments matched, and a string indicating the difference
+if a discrepancy was found. Note that if there is a C<start> parameter in
+the argument list, C<compare> disregards it. If C<step> isn't specified,
+C<compare> will use the C<rrdtool> default of 300 seconds.
+
+=head1 NOTES
+
+This module is not particularly specific to Smokeping, it is just
+distributed with it.
+
+=head1 BUGS
+
+Probably.
+
+=head1 COPYRIGHT
+
+Copyright (c) 2005 by Niko Tyni.
+
+=head1 LICENSE
+
+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.
+
+You should have received a copy of the GNU General Public
+License along with this program; if not, write to the Free
+Software Foundation, Inc., 675 Mass Ave, Cambridge, MA
+02139, USA.
+
+=head1 SEE ALSO
+
+RRDs(3)
+
+=cut
+
+use strict;
+use RRDs;
+
+# take an RRD file and make a create list out of it
+sub info2create {
+ my $file = shift;
+ my @create;
+ my $info = RRDs::info($file);
+ my $error = RRDs::error;
+ die("RRDs::info $file: ERROR: $error") if $error;
+ die("$file: unknown RRD version: $info->{rrd_version}")
+ unless $info->{rrd_version} eq '0001';
+ my $cf = $info->{"rra[0].cf"};
+ die("$file: no RRAs found?")
+ unless defined $cf;
+ my @fetch = RRDs::fetch($file, $cf);
+ $error = RRDs::error;
+ die("RRDs::fetch $file $cf: ERROR: $error") if $error;
+ my @ds = @{$fetch[2]};
+
+ push @create, '--step', $info->{step};
+ for my $ds (@ds) {
+ my @s = ("DS", $ds);
+ for (qw(type minimal_heartbeat min max)) {
+ die("$file: missing $_ for DS $ds?")
+ unless exists $info->{"ds[$ds].$_"};
+ my $val = $info->{"ds[$ds].$_"};
+ push @s, defined $val ? $val : "U";
+ }
+ push @create, join(":", @s);
+ }
+ for (my $i=0; exists $info->{"rra[$i].cf"}; $i++) {
+ my @s = ("RRA", $info->{"rra[$i].cf"});
+ for (qw(xff pdp_per_row rows)) {
+ die("$file: missing $_ for RRA $i")
+ unless exists $info->{"rra[$i].$_"};
+ push @s, $info->{"rra[$i].$_"};
+ }
+ push @create, join(":", @s);
+ }
+ return \@create;
+}
+
+sub compare {
+ my $file = shift;
+ my $create = shift;
+ my @create2 = @{info2create($file)};
+ my @create = @$create; # copy because we change it
+ # we don't compare the '--start' param
+ if ($create[0] eq '--start') {
+ shift @create;
+ shift @create;
+ }
+ # special check for the optional 'step' parameter
+ die("Internal error: didn't get the step parameter from info2create?")
+ unless ("--step" eq shift @create2);
+ my $step = shift @create2;
+ my $step2;
+ if ($create[0] eq '--step') {
+ shift @create;
+ $step2 = shift @create;
+ } else {
+ $step2 = 300; # default value
+ }
+ return "Wrong value of step: $file has $step, create string has $step2"
+ unless $step == $step2;
+
+ my $dscount = grep /^DS/, @create;
+ my $dscount2 = grep /^DS/, @create2;
+ return "Different number of data sources: $file has $dscount2, create string has $dscount"
+ unless $dscount == $dscount2;
+ my $rracount = grep /^RRA/, @create;
+ my $rracount2 = grep /^RRA/, @create2;
+ return "Different number of RRAs: $file has $rracount2, create string has $rracount"
+ unless $rracount == $rracount2;
+
+ while (my $arg = shift @create) {
+ my $arg2 = shift @create2;
+ return "Different arguments: $file has $arg2, create string has $arg"
+ unless $arg eq $arg2;
+ }
+ return undef;
+}
+
+1;