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