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 MG |
12 | $UPSGRAPH::host = ""; |
13 | $UPSGRAPH::rrdfile = ""; | |
14 | $UPSGRAPH::outdir = ""; | |
15 | $UPSGRAPH::community = "public"; | |
16 | $UPSGRAPH::step = 60; | |
e5da3876 | 17 | $UPSGRAPH::keep = (370*24*60*60)/$UPSGRAPH::step; |
1c9fb9df MG |
18 | @UPSGRAPH::fields = (); |
19 | $UPSGRAPH::vars = {}; | |
e18c93b3 | 20 | |
1c9fb9df | 21 | do $ARGV[0] or die "can't read config: $!"; |
e18c93b3 | 22 | |
1c9fb9df MG |
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; | |
e5da3876 | 28 | my $keep = $UPSGRAPH::keep; |
1c9fb9df MG |
29 | my @fields = @UPSGRAPH::fields; |
30 | my $vars = $UPSGRAPH::vars; | |
e18c93b3 | 31 | |
e5da3876 | 32 | sub rrdcreate(@) { |
21377f43 MG |
33 | my $newrrd = shift; |
34 | my $field = shift; | |
e5da3876 MG |
35 | my $start = shift; |
36 | ||
21377f43 | 37 | my @cmd = ("${newrrd}", "--step=${step}"); |
e5da3876 MG |
38 | |
39 | if (defined($start)) { | |
40 | push @cmd, "--start=${start}"; | |
41 | } | |
42 | ||
21377f43 MG |
43 | push @cmd, "DS:${field}:GAUGE:600:" . |
44 | $vars->{$field}->{'min'} . ":" . | |
45 | $vars->{$field}->{'max'} . " "; | |
46 | ||
e5da3876 MG |
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 | ||
af4abf85 | 56 | if ($> == 0) { |
1c9fb9df | 57 | if (@ARGV != 2) { |
e5da3876 | 58 | print STDERR "Running as root, please provide UID as 2th argument!\n"; |
af4abf85 MG |
59 | exit(1); |
60 | } | |
61 | ||
c6f0760e | 62 | print "Running as root, switching to ".$ARGV[1]."\n"; |
1c9fb9df | 63 | $< = $> = $ARGV[1]; |
af4abf85 MG |
64 | } |
65 | ||
21377f43 MG |
66 | if (-e "${rrdfile}") { |
67 | print "Reading old ${rrdfile} to preserve data...\n"; | |
e5da3876 | 68 | |
21377f43 MG |
69 | my $rrdinfo = RRDs::info("${rrdfile}"); |
70 | if (RRDs::error) { | |
71 | print "Error while getting info: " . RRDs::error . "\n"; | |
72 | exit 1; | |
73 | } | |
e5da3876 MG |
74 | |
75 | (my $start, my $ostep, my $names, my $data) = | |
76 | RRDs::fetch("${rrdfile}", | |
21377f43 MG |
77 | "-s " . (time() - ($rrdinfo->{'rra[0].rows'} * $rrdinfo->{'step'})), |
78 | "AVERAGE"); | |
e5da3876 MG |
79 | |
80 | if (RRDs::error) { | |
81 | print "Error while fetching data: " . RRDs::error . "\n"; | |
82 | exit 1; | |
e18c93b3 | 83 | } |
e18c93b3 | 84 | |
21377f43 MG |
85 | foreach my $field (@$names) { |
86 | if (! -e "${rrdfile}.${field}") { | |
87 | rrdcreate("${rrdfile}.${field}","${field}",(${start}-${ostep})); | |
88 | } | |
89 | } | |
e5da3876 MG |
90 | |
91 | my $pos = $start; | |
92 | foreach my $line (@$data) { | |
21377f43 MG |
93 | foreach my $field (@$names) { |
94 | my $val = shift (@$line); | |
95 | next if (!defined($val)); | |
e5da3876 | 96 | |
21377f43 MG |
97 | RRDs::update("${rrdfile}.${field}", "${pos}:${val}"); |
98 | if (RRDs::error) { | |
99 | print "Can't insert data: " . RRDs::error . "\n"; | |
100 | exit 1; | |
101 | } | |
e5da3876 | 102 | |
e5da3876 | 103 | } |
21377f43 | 104 | |
e5da3876 MG |
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"; | |
21377f43 | 113 | } |
e5da3876 | 114 | |
21377f43 MG |
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}"); | |
e5da3876 MG |
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) { | |
21377f43 MG |
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 | } | |
e5da3876 | 179 | } |
e18c93b3 MG |
180 | } |
181 | ||
6aa53fc5 MG |
182 | my $child = fork(); |
183 | ||
184 | die "fork failed!" if (!defined($child)); | |
185 | ||
186 | exit 0 if ($child != 0); | |
187 | ||
e18c93b3 MG |
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 | ||
e18c93b3 MG |
210 | foreach my $var (@fields) { |
211 | if (!(defined($vars->{$var}->{'value'}))) { | |
212 | $vars->{$var}->{'value'} = 'U'; | |
213 | } | |
21377f43 | 214 | RRDs::update("${rrdfile}.${var}", "N:" . $vars->{$var}->{'value'}); |
e5da3876 | 215 | } |
e5da3876 MG |
216 | if (RRDs::error) { |
217 | print "Error while updating: " . RRDs::error . "\n"; | |
e18c93b3 | 218 | } |
e18c93b3 MG |
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) { | |
21377f43 | 226 | my @graphdef = ("-t", $vars->{$var}->{'name'}, "DEF:${var}=${rrdfile}.${var}:${var}:AVERAGE", "LINE1:${var}#FF0000"); |
e5da3876 MG |
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 | ||
58c56c83 MG |
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 | ||
e5da3876 MG |
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 | } | |
e18c93b3 | 289 | |
e5da3876 | 290 | print HTML2 "<img src=\"${var}.year.png\" width=\"${width}\" height=\"${height}\"><br>"; |
e18c93b3 | 291 | |
e5da3876 MG |
292 | print HTML2 "</body></html>\n"; |
293 | close(HTML2); | |
294 | rename("${outdir}/${var}.html.new", "${outdir}/${var}.html"); | |
e18c93b3 MG |
295 | } |
296 | ||
297 | print HTML "</body></html>\n"; | |
298 | print HTML "<br>Generated on: " . localtime(time()); | |
863e62dc | 299 | print HTML ' by <a href="http://git.zerfleddert.de/cgi-bin/gitweb.cgi/upsgraph">upsgraph</a>.'; |
e18c93b3 MG |
300 | |
301 | close(HTML); | |
302 | ||
303 | rename("${outdir}/index.html.new", "${outdir}/index.html"); | |
304 | ||
305 | sleep(${step}/2); | |
306 | } |