]>
Commit | Line | Data |
---|---|---|
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 | } |