]>
Commit | Line | Data |
---|---|---|
e18c93b3 MG |
1 | #!/usr/bin/perl -w |
2 | ||
1c9fb9df MG |
3 | if ((@ARGV != 1) && (@ARGV != 2)) { |
4 | print STDERR "Syntax: ${0} configfile [uid]\n"; | |
e18c93b3 MG |
5 | exit(1); |
6 | } | |
7 | ||
1c9fb9df | 8 | use Net::SNMP; |
e5da3876 MG |
9 | use RRDs; |
10 | use Data::Dumper; | |
e18c93b3 | 11 | |
1c9fb9df | 12 | $UPSGRAPH::outdir = ""; |
1c9fb9df | 13 | $UPSGRAPH::step = 60; |
e5da3876 | 14 | $UPSGRAPH::keep = (370*24*60*60)/$UPSGRAPH::step; |
6c1071ee | 15 | $UPSGRAPH::hosts = (); |
e18c93b3 | 16 | |
1c9fb9df | 17 | do $ARGV[0] or die "can't read config: $!"; |
e18c93b3 | 18 | |
1c9fb9df | 19 | my $outdir = $UPSGRAPH::outdir; |
1c9fb9df | 20 | my $step = $UPSGRAPH::step; |
e5da3876 | 21 | my $keep = $UPSGRAPH::keep; |
6c1071ee | 22 | my $hosts = $UPSGRAPH::hosts; |
e18c93b3 | 23 | |
e5da3876 | 24 | sub rrdcreate(@) { |
21377f43 MG |
25 | my $newrrd = shift; |
26 | my $field = shift; | |
6c1071ee | 27 | my $vars = shift; |
e5da3876 MG |
28 | my $start = shift; |
29 | ||
21377f43 | 30 | my @cmd = ("${newrrd}", "--step=${step}"); |
e5da3876 MG |
31 | |
32 | if (defined($start)) { | |
33 | push @cmd, "--start=${start}"; | |
34 | } | |
35 | ||
21377f43 MG |
36 | push @cmd, "DS:${field}:GAUGE:600:" . |
37 | $vars->{$field}->{'min'} . ":" . | |
38 | $vars->{$field}->{'max'} . " "; | |
39 | ||
e5da3876 MG |
40 | push @cmd, "RRA:AVERAGE:0.5:1:${keep}"; |
41 | ||
42 | RRDs::create(@cmd); | |
43 | if (RRDs::error) { | |
44 | print "Error while creating: " . RRDs::error . "\n"; | |
45 | exit 1; | |
46 | } | |
47 | } | |
48 | ||
6c1071ee MG |
49 | sub fetch_snmp(@) { |
50 | my $address = shift; | |
51 | my $community = shift; | |
52 | my $oid = shift; | |
e5da3876 | 53 | |
6c1071ee MG |
54 | (my $session, my $error) = Net::SNMP->session(Hostname => $address, |
55 | Community => $community); | |
e18c93b3 | 56 | |
6c1071ee | 57 | die "session error: $error" unless ($session); |
e5da3876 | 58 | |
6c1071ee | 59 | $session->translate(0); |
e5da3876 | 60 | |
6c1071ee | 61 | my $val = $session->get_request($oid); |
e5da3876 | 62 | |
6c1071ee | 63 | $session->close; |
21377f43 | 64 | |
6c1071ee MG |
65 | $val; |
66 | } | |
e5da3876 | 67 | |
6c1071ee MG |
68 | if ($> == 0) { |
69 | if (@ARGV != 2) { | |
70 | print STDERR "Running as root, please provide UID as 2th argument!\n"; | |
71 | exit(1); | |
e5da3876 MG |
72 | } |
73 | ||
6c1071ee MG |
74 | print "Running as root, switching to ".$ARGV[1]."\n"; |
75 | $< = $> = $ARGV[1]; | |
21377f43 | 76 | } |
e5da3876 | 77 | |
6c1071ee MG |
78 | foreach my $host (@$hosts) { |
79 | my $rrdfile = $host->{'rrdfile'}; | |
21377f43 | 80 | |
6c1071ee MG |
81 | if (-e "${rrdfile}") { |
82 | print "Reading old ${rrdfile} to preserve data...\n"; | |
e5da3876 | 83 | |
6c1071ee MG |
84 | my $rrdinfo = RRDs::info("${rrdfile}"); |
85 | if (RRDs::error) { | |
86 | print "Error while getting info: " . RRDs::error . "\n"; | |
87 | exit 1; | |
88 | } | |
21377f43 MG |
89 | |
90 | (my $start, my $ostep, my $names, my $data) = | |
6c1071ee | 91 | RRDs::fetch("${rrdfile}", |
21377f43 MG |
92 | "-s " . (time() - ($rrdinfo->{'rra[0].rows'} * $rrdinfo->{'step'})), |
93 | "AVERAGE"); | |
94 | ||
95 | if (RRDs::error) { | |
96 | print "Error while fetching data: " . RRDs::error . "\n"; | |
97 | exit 1; | |
98 | } | |
99 | ||
6c1071ee MG |
100 | foreach my $field (@$names) { |
101 | if (! -e "${rrdfile}.${field}") { | |
102 | rrdcreate("${rrdfile}.${field}", | |
103 | "${field}", | |
104 | $host->{'vars'}, | |
105 | (${start}-${ostep})); | |
106 | } | |
107 | } | |
21377f43 MG |
108 | |
109 | my $pos = $start; | |
110 | foreach my $line (@$data) { | |
6c1071ee MG |
111 | foreach my $field (@$names) { |
112 | my $val = shift (@$line); | |
21377f43 | 113 | $val = 'U' if (!defined($val)); |
21377f43 | 114 | |
6c1071ee MG |
115 | RRDs::update("${rrdfile}.${field}", "${pos}:${val}"); |
116 | if (RRDs::error) { | |
117 | print "Can't insert data: " . RRDs::error . "\n"; | |
118 | exit 1; | |
119 | } | |
120 | ||
21377f43 | 121 | } |
6c1071ee | 122 | |
21377f43 MG |
123 | $pos += $ostep; |
124 | ||
125 | if ((($pos-$start)/$ostep) == $#$data) { | |
126 | last; | |
127 | } | |
128 | } | |
129 | ||
6c1071ee MG |
130 | rename("${rrdfile}", "${rrdfile}.old") or die "Can't rename old file: $!\n"; |
131 | } | |
21377f43 | 132 | |
6c1071ee MG |
133 | foreach my $field (@{$host->{'fields'}}) { |
134 | if (! -e "${rrdfile}.${field}") { | |
135 | print "Creating ${rrdfile}.${field}...\n"; | |
136 | rrdcreate("${rrdfile}.${field}", | |
137 | "${field}", | |
138 | $host->{'vars'}); | |
139 | } | |
140 | ||
141 | my $rrdinfo = RRDs::info("${rrdfile}.${field}"); | |
21377f43 MG |
142 | if (RRDs::error) { |
143 | print "Error while getting info: " . RRDs::error . "\n"; | |
144 | exit 1; | |
145 | } | |
146 | ||
147 | if ($rrdinfo->{'rra[0].rows'} != $keep) { | |
6c1071ee MG |
148 | print "Resizing ${rrdfile}.${field} from " . $rrdinfo->{'rra[0].rows'} . |
149 | " to ${keep} samples.\n"; | |
e18c93b3 | 150 | |
6c1071ee MG |
151 | (my $start, my $ostep, my $names, my $data) = |
152 | RRDs::fetch("${rrdfile}.${field}", | |
153 | "-s " . (time() - ($rrdinfo->{'rra[0].rows'} * $rrdinfo->{'step'})), | |
154 | "AVERAGE"); | |
6aa53fc5 | 155 | |
6c1071ee MG |
156 | if (RRDs::error) { |
157 | print "Error while fetching data: " . RRDs::error . "\n"; | |
158 | exit 1; | |
159 | } | |
6aa53fc5 | 160 | |
6c1071ee MG |
161 | rrdcreate("${rrdfile}.${field}.new", |
162 | "${field}", | |
163 | $host->{'vars'}, | |
164 | (${start}-${ostep})); | |
6aa53fc5 | 165 | |
6c1071ee | 166 | print "Preserving data since " . localtime($start) . "\n"; |
e18c93b3 | 167 | |
6c1071ee MG |
168 | my $pos = $start; |
169 | foreach my $line (@$data) { | |
170 | my $vline = "${pos}"; | |
e18c93b3 | 171 | |
6c1071ee MG |
172 | foreach my $val (@$line) { |
173 | $val = 'U' if (!defined($val)); | |
174 | $vline .= ":${val}"; | |
175 | } | |
176 | RRDs::update("${rrdfile}.${field}.new", $vline) or die "Can't insert data\n"; | |
e18c93b3 | 177 | |
6c1071ee MG |
178 | if (RRDs::error) { |
179 | print "Error while updating: " . RRDs::error . "\n"; | |
180 | exit 1; | |
181 | } | |
182 | $pos += $ostep; | |
e18c93b3 | 183 | |
6c1071ee MG |
184 | if ((($pos-$start)/$ostep) == $#$data) { |
185 | last; | |
186 | } | |
187 | } | |
e18c93b3 | 188 | |
6c1071ee MG |
189 | rename("${rrdfile}.${field}", "${rrdfile}.${field}.old") or die "Can't rename old file: $!\n"; |
190 | rename("${rrdfile}.${field}.new", "${rrdfile}.${field}") or die "Can't rename new file: $!\n"; | |
e18c93b3 | 191 | |
6c1071ee MG |
192 | $rrdinfo = RRDs::info("${rrdfile}.${field}"); |
193 | if (RRDs::error) { | |
194 | print "Error while getting info: " . RRDs::error . "\n"; | |
195 | exit 1; | |
196 | } | |
e18c93b3 | 197 | |
6c1071ee MG |
198 | if ($rrdinfo->{'rra[0].rows'} != $keep) { |
199 | print "Failed!\n"; | |
200 | exit 1; | |
201 | } | |
e18c93b3 | 202 | } |
e18c93b3 | 203 | } |
6c1071ee MG |
204 | } |
205 | ||
206 | my $child = fork(); | |
e18c93b3 | 207 | |
6c1071ee MG |
208 | die "fork failed!" if (!defined($child)); |
209 | ||
210 | exit 0 if ($child != 0); | |
211 | ||
212 | while(1) { | |
e18c93b3 MG |
213 | open(HTML, ">${outdir}/index.html.new"); |
214 | ||
215 | print HTML '<html><head><meta http-equiv="refresh" content="60"/><meta http-equiv="cache-control" content="no-cache"/><meta http-equiv="pragma" content="no-cache"/><meta http_equiv="expires" content="Sat, 26 Jul 1997 05:00:00 GMT"/><title>USV status</title></head>'; | |
216 | print HTML '<body bgcolor="#ffffff">'; | |
217 | ||
6c1071ee MG |
218 | foreach my $host (@$hosts) { |
219 | my $vars = $host->{'vars'}; | |
220 | my $rrdfile = $host->{'rrdfile'}; | |
221 | my $hostname = $host->{'name'}; | |
222 | ||
223 | foreach my $var (@{$host->{'fields'}}) { | |
224 | delete $vars->{$var}->{'value'}; | |
e5da3876 | 225 | |
6c1071ee MG |
226 | my $result = fetch_snmp($host->{'address'}, $host->{'community'}, $vars->{$var}->{'oid'}); |
227 | next unless (defined $result); | |
228 | ||
229 | $vars->{$var}->{'value'} = $result->{$vars->{$var}->{'oid'}}; | |
230 | if (defined($vars->{$var}->{'factor'})) { | |
231 | $vars->{$var}->{'value'} *= $vars->{$var}->{'factor'}; | |
232 | } | |
233 | } | |
234 | ||
235 | foreach my $var (@{$host->{'fields'}}) { | |
236 | if (!(defined($vars->{$var}->{'value'}))) { | |
237 | $vars->{$var}->{'value'} = 'U'; | |
238 | } | |
239 | RRDs::update("${rrdfile}.${var}", "N:" . $vars->{$var}->{'value'}); | |
240 | } | |
e5da3876 | 241 | if (RRDs::error) { |
6c1071ee | 242 | print "Error while updating: " . RRDs::error . "\n"; |
e5da3876 MG |
243 | } |
244 | ||
6c1071ee MG |
245 | foreach my $var (@{$host->{'fields'}}) { |
246 | my @graphdef = ("-t", $hostname." - ".$vars->{$var}->{'name'}, "DEF:${var}=${rrdfile}.${var}:${var}:AVERAGE", "LINE1:${var}#FF0000"); | |
247 | (my $averages, my $width, my $height) = | |
248 | RRDs::graph("${outdir}/${hostname}.${var}.png.new", | |
249 | "-w", "720", @graphdef); | |
e5da3876 | 250 | |
6c1071ee MG |
251 | if (RRDs::error) { |
252 | print "Error while graphing: " . RRDs::error . "\n"; | |
253 | } else { | |
254 | rename("${outdir}/${hostname}.${var}.png.new", "${outdir}/${hostname}.${var}.png"); | |
255 | } | |
e5da3876 | 256 | |
6c1071ee | 257 | print HTML "<a href=\"${hostname}.${var}.html\"><img src=\"${hostname}.${var}.png\" width=\"${width}\" height=\"${height}\" border=\"0\"></a>"; |
58c56c83 | 258 | |
6c1071ee MG |
259 | open (HTML2, ">${outdir}/${hostname}.${var}.html.new"); |
260 | print HTML2 "<html><head><title>" . $vars->{$var}->{'name'} . "</title></head>"; | |
261 | print HTML2 '<body bgcolor="#ffffff">'; | |
58c56c83 | 262 | |
58c56c83 | 263 | |
6c1071ee MG |
264 | push @graphdef, "VDEF:min=${var},MINIMUM"; |
265 | push @graphdef, "GPRINT:min:Minimum\\: %.2lf"; | |
58c56c83 | 266 | |
6c1071ee MG |
267 | push @graphdef, "VDEF:avg=${var},AVERAGE"; |
268 | push @graphdef, "GPRINT:avg:Average\\: %.2lf"; | |
58c56c83 | 269 | |
6c1071ee MG |
270 | push @graphdef, "VDEF:max=${var},MAXIMUM"; |
271 | push @graphdef, "GPRINT:max:Maximum\\: %.2lf"; | |
e5da3876 | 272 | |
6c1071ee MG |
273 | push @graphdef, "VDEF:cur=${var},LAST"; |
274 | push @graphdef, "GPRINT:cur:Current\\: %.2lf"; | |
e5da3876 | 275 | |
6c1071ee MG |
276 | ($averages, $width, $height) = |
277 | RRDs::graph("${outdir}/${hostname}.${var}.long.png.new", | |
278 | "-w", "1008", @graphdef); | |
e5da3876 | 279 | |
6c1071ee MG |
280 | if (RRDs::error) { |
281 | print "Error while graphing: " . RRDs::error . "\n"; | |
282 | } else { | |
283 | rename("${outdir}/${hostname}.${var}.long.png.new", "${outdir}/${hostname}.${var}.long.png"); | |
284 | } | |
e5da3876 | 285 | |
6c1071ee MG |
286 | print HTML2 "<img src=\"${hostname}.${var}.long.png\" width=\"${width}\" height=\"${height}\"><br>"; |
287 | ||
288 | ($averages, $width, $height) = | |
289 | RRDs::graph("${outdir}/${hostname}.${var}.week.png.new", | |
290 | "-w", "1008", "-e", "now", "-s", "end-1w", @graphdef); | |
291 | ||
292 | if (RRDs::error) { | |
293 | print "Error while graphing: " . RRDs::error . "\n"; | |
294 | } else { | |
295 | rename("${outdir}/${hostname}.${var}.week.png.new", "${outdir}/${hostname}.${var}.week.png"); | |
296 | } | |
e5da3876 | 297 | |
6c1071ee | 298 | print HTML2 "<img src=\"${hostname}.${var}.week.png\" width=\"${width}\" height=\"${height}\"><br>"; |
e5da3876 | 299 | |
6c1071ee MG |
300 | ($averages, $width, $height) = |
301 | RRDs::graph("${outdir}/${hostname}.${var}.year.png.new", | |
302 | "-w", "1008", "-e", "now", "-s", "end-1y", @graphdef); | |
e5da3876 | 303 | |
6c1071ee MG |
304 | if (RRDs::error) { |
305 | print "Error while graphing: " . RRDs::error . "\n"; | |
306 | } else { | |
307 | rename("${outdir}/${hostname}.${var}.year.png.new", "${outdir}/${hostname}.${var}.year.png"); | |
308 | } | |
e18c93b3 | 309 | |
6c1071ee | 310 | print HTML2 "<img src=\"${hostname}.${var}.year.png\" width=\"${width}\" height=\"${height}\"><br>"; |
e18c93b3 | 311 | |
6c1071ee MG |
312 | print HTML2 "</body></html>\n"; |
313 | close(HTML2); | |
314 | rename("${outdir}/${hostname}.${var}.html.new", "${outdir}/${hostname}.${var}.html"); | |
315 | } | |
e18c93b3 MG |
316 | } |
317 | ||
318 | print HTML "</body></html>\n"; | |
319 | print HTML "<br>Generated on: " . localtime(time()); | |
863e62dc | 320 | print HTML ' by <a href="http://git.zerfleddert.de/cgi-bin/gitweb.cgi/upsgraph">upsgraph</a>.'; |
e18c93b3 MG |
321 | |
322 | close(HTML); | |
323 | ||
324 | rename("${outdir}/index.html.new", "${outdir}/index.html"); | |
325 | ||
326 | sleep(${step}/2); | |
327 | } |