1
package Smokeping::RRDtools;
5
Smokeping::RRDtools - Tools for RRD file handling
9
use Smokeping::RRDtools;
12
my $file = '/path/to/file.rrd';
14
# get the create arguments that $file was created with
15
my $create = Smokeping::RRDtools::info2create($file);
17
# use them to create a new file
18
RRDs::create('/path/to/file2.rrd', @$create);
20
# or compare them against another create list
21
my @create = ('--step', 60, 'DS:ds0:GAUGE:120:0:U', 'RRA:AVERAGE:0.5:1:1008');
22
my ($fatal, $comparison) = Smokeping::RRDtools::compare($file, \@create);
23
print "Fatal: " if $fatal;
24
print "Create arguments didn't match: $comparison\n" if $comparison;
26
Smokeping::RRDtools::tuneds($file, \@create);
30
This module offers three functions, C<info2create>, C<compare> and
31
C<tuneds>. The first can be used to recreate the arguments that an RRD file
32
was created with. The second checks if an RRD file was created with the
33
given arguments. The thirds tunes the DS parameters according to the
34
supplied create string.
36
The function C<info2create> must be called with one argument:
37
the path to the interesting RRD file. It will return an array
38
reference of the argument list that can be fed to C<RRDs::create>.
39
Note that this list will never contain the C<start> parameter,
40
but it B<will> contain the C<step> parameter.
42
The function C<compare> must be called with two arguments: the path to the
43
interesting RRD file, and a reference to an argument list that could be fed
44
to C<RRDs::create>. The function will then simply compare the result of
45
C<info2create> with this argument list. It will return an array of two values:
46
C<(fatal, text)> where C<fatal> is 1 if it found a fatal difference, and 0 if not.
47
The C<text> will contain an error message if C<fatal == 1> and a possible warning
48
message if C<fatal == 0>. If C<fatal == 0> and C<text> is C<undef>, all the
51
Note that if there is a C<start> parameter in the argument list,
52
C<compare> disregards it. If C<step> isn't specified, C<compare> will use
53
the C<rrdtool> default of 300 seconds. C<compare> ignores non-matching DS
54
parameters since C<tuneds> will fix them.
56
C<tuneds> talks on stderr about the parameters it fixes.
60
This module is not particularly specific to Smokeping, it is just
69
Copyright (c) 2005 by Niko Tyni.
73
Niko Tyni <ntyni@iki.fi>
77
This program is free software; you can redistribute it
78
and/or modify it under the terms of the GNU General Public
79
License as published by the Free Software Foundation; either
80
version 2 of the License, or (at your option) any later
83
This program is distributed in the hope that it will be
84
useful, but WITHOUT ANY WARRANTY; without even the implied
85
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
86
PURPOSE. See the GNU General Public License for more
89
You should have received a copy of the GNU General Public
90
License along with this program; if not, write to the Free
91
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA
103
# take an RRD file and make a create list out of it
108
# check for Perl version 5.8.0, it's buggy
110
my $buggy_perl_version = 1 if abs($] - 5.008000) < .0000005;
112
my $info = RRDs::info($file);
113
my $error = RRDs::error;
114
die("RRDs::info $file: ERROR: $error") if $error;
115
die("$file: unknown RRD version: $info->{rrd_version}")
116
unless $info->{rrd_version} eq '0001'
117
or $info->{rrd_version} eq '0003';
118
my $cf = $info->{"rra[0].cf"};
119
die("$file: no RRAs found?")
121
my @fetch = RRDs::fetch($file, $cf);
122
$error = RRDs::error;
123
die("RRDs::fetch $file $cf: ERROR: $error") if $error;
124
my @ds = @{$fetch[2]};
126
push @create, '--step', $info->{step};
129
for (qw(type minimal_heartbeat min max)) {
130
die("$file: missing $_ for DS $ds?")
131
unless exists $info->{"ds[$ds].$_"}
132
or $buggy_perl_version;
133
my $val = $info->{"ds[$ds].$_"};
134
push @s, defined $val ? $val : "U";
136
push @create, join(":", @s);
138
for (my $i=0; exists $info->{"rra[$i].cf"}; $i++) {
139
my @s = ("RRA", $info->{"rra[$i].cf"});
140
for (qw(xff pdp_per_row rows)) {
141
die("$file: missing $_ for RRA $i")
142
unless exists $info->{"rra[$i].$_"}
143
or $buggy_perl_version;
144
push @s, $info->{"rra[$i].$_"};
146
push @create, join(":", @s);
154
my @create2 = @{info2create($file)};
155
my @create = @$create; # copy because we change it
156
# we don't compare the '--start' param
157
if ($create[0] eq '--start') {
161
# special check for the optional 'step' parameter
162
die("Internal error: didn't get the step parameter from info2create?")
163
unless ("--step" eq shift @create2);
164
my $step = shift @create2;
166
if ($create[0] eq '--step') {
168
$step2 = shift @create;
170
$step2 = 300; # default value
172
return (1, "Wrong value of step: $file has $step, create string has $step2")
173
unless $step == $step2;
175
my $dscount = grep /^DS/, @create;
176
my $dscount2 = grep /^DS/, @create2;
177
return (1, "Different number of data sources: $file has $dscount2, create string has $dscount")
178
unless $dscount == $dscount2;
179
my $rracount = grep /^RRA/, @create;
180
my $rracount2 = grep /^RRA/, @create2;
181
return (1, "Different number of RRAs: $file has $rracount2, create string has $rracount")
182
unless $rracount == $rracount2;
185
while (my $arg = shift @create) {
186
my $arg2 = shift @create2;
187
my @ds = split /:/, $arg;
188
my @ds2 = split /:/, $arg2;
189
next if $ds[0] eq 'DS' and $ds[0] eq $ds2[0] and $ds[1] eq $ds2[1] and $ds[2] eq $ds2[2];
191
if ($ds[0] eq 'RRA' and $ds[0] eq $ds2[0] and $ds[1] eq $ds2[1]) {
192
# non-fatal: CF is the same, but xff/steps/rows differ
193
$warning .= "Different RRA parameters: $file has $arg2, create string has $arg";
195
return (1, "Different arguments: $file has $arg2, create string has $arg");
199
return (0, $warning);
205
my @create2 = sort grep /^DS/, @{info2create($file)};
206
my @create = sort grep /^DS/, @$create;
208
my @ds = split /:/, shift @create;
209
my @ds2 = split /:/, shift @create2;
210
next unless $ds[1] eq $ds2[1] and $ds[2] eq $ds[2];
211
if ($ds[3] ne $ds2[3]){
212
warn "## Updating $file DS:$ds[1] heartbeat $ds2[3] -> $ds[3]\n";
213
RRDs::tune $file,"--hearbeat","$ds[1]:$ds[3]" unless $ds[3] eq $ds2[3];
215
if ($ds[4] ne $ds2[4]){
216
warn "## Updating $file DS:$ds[1] minimum $ds2[4] -> $ds[4]\n";
217
RRDs::tune $file,"--minimum","$ds[1]:$ds[4]" unless $ds[4] eq $ds2[4];
219
if ($ds[5] ne $ds2[5]){
220
warn "## Updating $file DS:$ds[1] maximum $ds2[5] -> $ds[5]\n";
221
RRDs::tune $file,"--maximum","$ds[1]:$ds[5]" unless $ds[5] eq $ds2[5];