root/n2rrd.pl

Revision 1, 6.8 kB (checked in by root, 3 years ago)

Initial load

  • Property svn:executable set to
Line 
1 #!@BIN_PERL@ -w
2
3 #
4 #    Short description: Creates/Updates RRA archives, from nagios performance data
5 #    Copyright (C) 2006  Badri Prasad Pillai
6 #
7 #    This program is free software; you can redistribute it and/or modify
8 #    it under the terms of the GNU General Public License as published by
9 #    the Free Software Foundation; either version 2 of the License, or
10 #    (at your option) any later version.
11 #
12 #    This program is distributed in the hope that it will be useful,
13 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
14 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 #    GNU General Public License for more details.
16 #
17 #    You should have received a copy of the GNU General Public License
18 #    along with this program; if not, write to the Free Software
19 #    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
20
21 #
22 #    Contact details:
23 #               Badri(at)DigLinks.COM
24 #   
25
26
27
28 use strict;
29
30 use RRDs;
31 use Getopt::Std;
32
33 sub log_msg($);
34 sub usage();
35
36 my $opt = {};
37 my $rrderror = "";
38
39 #options
40 getopts("c:dhH:T:o:s:", $opt);
41
42 usage  if $opt->{h};
43
44 #
45 # Exit if there is no configuration file
46 usage  if ! $opt->{c};
47
48 #
49 # If can't read configuration file then just abort
50 #
51 open(CONF, "<$opt->{c}")
52   or die "Can't open configuration file -> \"$opt->{c}\":$!\n";
53
54 my %config = ();
55 my $line   = 0;
56 #
57 # Parse configuration file
58 while (<CONF>) {
59     chop;    # Remove newline character
60     $line++;
61     s/ //g;    # remove spaces
62     next if /^#/;    # Skip comments
63     next if /^$/;    # Skip empty lines
64     s/#.*//;         # Remove partial comments
65
66     if (/^(.*)=(.*)$/) {
67         if ($1 eq "CONF_DIR") {
68             $config{$1} = $2;
69         }
70         elsif ($1 eq "RRA_DIR") {
71             $config{$1} = $2;
72         }
73         elsif ($1 eq "TEMPLATES_DIR") {
74             $config{$1} = $2;
75         }
76         elsif ($1 eq "SERVICE_NAME_MAPS") {
77             $config{$1} = $2;
78         }
79         elsif ($1 eq "LOGFILE") {
80             $config{$1} = $2;
81         }
82         else {    # A warning should be ok
83             log_msg "WARNING: Unknown global variable declaration in line $line:\"$1 = $2\"\n";
84         }
85     }
86 }
87 close(CONF);
88
89
90 #
91 # Sanity check: if RRA directory exists
92 log_msg "Direcotry rra_dir = \"$config{CONF_DIR}\" doesn't exists"
93     and exit 1
94             if ! -d $config{CONF_DIR};
95
96 #
97 # Sanity check: if RRA directory exists
98 log_msg "Direcotry templates_dir = \"$config{TEMPLATES_DIR}\" doesn't exists"
99     and exit 1
100             if ! -d $config{TEMPLATES_DIR};
101 #
102 # All three arguments are required
103 #
104 usage if ! $opt->{H};
105 usage if ! $opt->{s};
106 usage if ! $opt->{o};
107
108 if ( $opt->{d} ) {
109         my $s = "Host = $opt->{H}, Service name = $opt->{s}, Check result = $opt->{o}\n";
110         log_msg $s if $opt->{d};
111 }
112 #
113 # assume delimiter between service name is '_'
114 my @parse_service_str = split /_/, $opt->{s};
115 my $service = "";
116
117 if ( $#parse_service_str <= 0 ) {
118    open S_MAPS,"< $config{SERVICE_NAME_MAPS}"
119                 or log_msg "Can't open service maps file \"$config{SERVICE_NAME_MAPS}\"\n"
120                         and exit 1;
121
122    log_msg "Searching map in file \"$config{SERVICE_NAME_MAPS}\" for service \"$opt->{s}\" \n"
123             if $opt->{d};
124
125    while(<S_MAPS>) {
126         next if /^#/;    # Skip comments
127         next if /^$/;    # Skip empty lines
128         s/#.*//;         # Remove partial comments
129         chomp; 
130
131         $service = $1 if /$opt->{s}:\s+(\S+)/i;
132    }
133 }
134 else {
135     #
136     # The last word after terminator carachter "_"
137         $service = $parse_service_str[$#parse_service_str];
138 }
139 #
140 # assume delimiter between ds_name and ds_value is '='
141
142 my @data = ();
143 # HOST check, works for PING and FPING output
144 if ( $opt->{o} =~ /PING.*?(\d+)%.+?([.\d]+)\sms/) {
145         push @data, "loss=$1";
146         push @data, "rta=$2";
147 }
148 else {
149         #
150         # remove spaces before and/or after "=" character
151         $opt->{o} =~ s/\s+=/=/g;
152         $opt->{o} =~ s/=\s+/=/g;
153         @data = ($opt->{o} =~ /(\S+=[0-9\.]+)/g);
154 }
155
156 log_msg "Missing ds_name in: $opt->{o}\n" and exit 1 if ! @data;
157
158 my $ds_name  = "";
159 my $ds_value = "";
160
161 foreach my $kv (@data) {
162         my ($key, $val) = split /=/, $kv;
163         $ds_name       .= "$key:" if $key;
164         $ds_value      .= "$val:";
165 }
166 $ds_name     =~ s/:$//;
167 $ds_value    =~ s/:$//;
168
169 my %ds_rewrite = ();
170
171 my $rrd_file =
172         "$config{RRA_DIR}/$opt->{H}_${service}.rrd";
173
174 #
175 # Check if a rewrite rules exist
176 #
177 if ( -f "$config{TEMPLATES_DIR}/rewrite/$opt->{H}_${service}_rewrite" ) {
178
179 #
180 #       print "Rewrite file detected for: $opt->{H}_${service}\n";
181         open REWRITE, "<$config{TEMPLATES_DIR}/rewrite/$opt->{H}_${service}_rewrite"
182                         or log_msg "Can't open rewrite rules file for $opt->{H}"
183                                 and exit 1;
184
185         my $ds_name_tmp = "";
186
187         while(<REWRITE>) {
188                next if /^#/;    # Skip comments
189                next if /^$/;    # Skip empty lines
190                s/#.*//;         # Remove partial comments
191                chomp;   
192        
193                $rrd_file = $1 if /^rrd_file\s+(\S+)/;
194                $ds_name_tmp .= "$2:" and $ds_rewrite{$1} = $2 if /^ds_name\s+(\S+)\s+(\S+)/;   
195         }
196         #print "rrd_file = $rrd_file\n";
197         if ($ds_name_tmp) {
198                 $ds_name_tmp =~ s/:$//;
199                 $ds_name = $ds_name_tmp;
200         }
201 }
202
203 unless ( -e $rrd_file ) {
204         #
205         # First check for template with hostname
206         my $rrd_create_template =
207                 "$config{TEMPLATES_DIR}/rra/$opt->{H}_${service}.t";
208
209         if ( ! -f $rrd_create_template ) {
210
211                 #
212                 # Else look for default template
213                 $rrd_create_template = "$config{TEMPLATES_DIR}/rra/${service}.t";
214                 if ( ! -f $rrd_create_template ) {
215                         log_msg "Missing template \"$rrd_create_template\"\n";
216                         exit 1;
217                 }
218         }
219
220         open T, "<$rrd_create_template"
221                 or log_msg "can't open file \"$rrd_create_template\""
222         and exit 1;
223
224         my @t_params = ();
225
226         while (<T>){
227                 next if /^#/;    # Skip comments
228                 next if /^$/;    # Skip empty lines
229                 s/#.*//;         # Remove partial comments
230
231                 chomp;
232
233             #
234             # if there are ds_name rewrites needed
235             foreach my $k (keys %ds_rewrite) {
236                 s/:$k:/:$ds_rewrite{$k}:/;
237             }
238
239                 push @t_params, "$_";
240         }
241         log_msg "Creating RRD file: $rrd_file\n" if $opt->{d};
242         RRDs::create(
243             $rrd_file,
244             @t_params
245         );
246         $rrderror = RRDs::error;
247         log_msg "Problem while creating rrd: $rrderror\n" and exit 1 if ($rrderror);
248    
249             exit 0;
250 }
251
252 #
253 # If everything went well until now, then try to update rrd database
254
255 #
256 # If not time given
257 my $time = $opt->{T} || "N";
258
259 log_msg "Filtered ds_names: $ds_name, ds_values: $ds_value\n" if $opt->{d};
260 RRDs::update ("$rrd_file", "--template", "$ds_name", "$time:$ds_value");
261 $rrderror = RRDs::error;
262 log_msg "ERROR while updating $rrd_file: $rrderror\n" and exit 1 if $rrderror;
263
264
265
266 exit 0;
267
268 sub log_msg ($) {
269         my $str = shift;
270
271         open L,">>$config{LOGFILE}" or die "Can't open logfile \"$config{LOGFILE}\"";
272
273         print L "$str";
274
275         close L;
276 }
277
278 sub usage () {
279         print "$0 [-h] -c <path>/config-file-name -T time -H hostname -s servicename -o service_check_output\n";
280         exit 0;
281 }
Note: See TracBrowser for help on using the browser.