use RRDs perl module, keep samples a year
[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 $rrdfile = shift;
34 my $start = shift;
35
36 my @cmd = ("${rrdfile}", "--step=${step}");
37
38 if (defined($start)) {
39 push @cmd, "--start=${start}";
40 }
41
42 foreach my $var (@fields) {
43 push @cmd, "DS:${var}:GAUGE:600:" .
44 $vars->{$var}->{'min'} . ":" .
45 $vars->{$var}->{'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 "Creating ${rrdfile}...\n";
68 rrdcreate("${rrdfile}");
69 }
70
71 my $rrdinfo = RRDs::info("${rrdfile}");
72 if (RRDs::error) {
73 print "Error while getting info: " . RRDs::error . "\n";
74 exit 1;
75 }
76
77 if ($rrdinfo->{'rra[0].rows'} != $keep) {
78 print "Resizing ${rrdfile} from " . $rrdinfo->{'rra[0].rows'} .
79 " to ${keep} samples.\n";
80
81 (my $start, my $ostep, my $names, my $data) =
82 RRDs::fetch("${rrdfile}",
83 "-s " . (time() - ($rrdinfo->{'rra[0].rows'} * $rrdinfo->{'step'})),
84 "AVERAGE");
85
86 if (RRDs::error) {
87 print "Error while fetching data: " . RRDs::error . "\n";
88 exit 1;
89 }
90
91 rrdcreate("${rrdfile}.new", (${start}-${ostep}));
92
93 print "Preserving data since " . localtime($start) . "\n";
94
95 my $pos = $start;
96 foreach my $line (@$data) {
97 my $vline = "${pos}";
98
99 foreach my $val (@$line) {
100 $val = 'U' if (!defined($val));
101 $vline .= ":${val}";
102 }
103 RRDs::update("${rrdfile}.new", $vline) or die "Can't insert data\n";
104
105 if (RRDs::error) {
106 print "Error while updating: " . RRDs::error . "\n";
107 exit 1;
108 }
109 $pos += $ostep;
110
111 if ((($pos-$start)/$ostep) == $#$data) {
112 last;
113 }
114 }
115
116 rename("${rrdfile}", "${rrdfile}.old") or die "Can't rename old file: $!\n";
117 rename("${rrdfile}.new", "${rrdfile}") or die "Can't rename new file: $!\n";
118
119 $rrdinfo = RRDs::info("${rrdfile}");
120 if (RRDs::error) {
121 print "Error while getting info: " . RRDs::error . "\n";
122 exit 1;
123 }
124
125 if ($rrdinfo->{'rra[0].rows'} != $keep) {
126 print "Failed!\n";
127 exit 1;
128 }
129 }
130
131 my $child = fork();
132
133 die "fork failed!" if (!defined($child));
134
135 exit 0 if ($child != 0);
136
137 while(1) {
138 ($session,$error) = Net::SNMP->session(Hostname => $host,
139 Community => $community);
140
141 die "session error: $error" unless ($session);
142
143 $session->translate(0);
144
145 foreach my $var (@fields) {
146 delete $vars->{$var}->{'value'};
147
148 my $result = $session->get_request($vars->{$var}->{'oid'});
149 next unless (defined $result);
150
151 $vars->{$var}->{'value'} = $result->{$vars->{$var}->{'oid'}};
152 if (defined($vars->{$var}->{'factor'})) {
153 $vars->{$var}->{'value'} *= $vars->{$var}->{'factor'};
154 }
155 }
156
157 $session->close;
158
159 my $vline = "N";
160 foreach my $var (@fields) {
161 if (!(defined($vars->{$var}->{'value'}))) {
162 $vars->{$var}->{'value'} = 'U';
163 }
164 $vline .= ":" . $vars->{$var}->{'value'};
165 }
166 RRDs::update("${rrdfile}", $vline);
167 if (RRDs::error) {
168 print "Error while updating: " . RRDs::error . "\n";
169 }
170
171 open(HTML, ">${outdir}/index.html.new");
172
173 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>';
174 print HTML '<body bgcolor="#ffffff">';
175
176 foreach my $var (@fields) {
177 my @graphdef = ("-t", $vars->{$var}->{'name'}, "DEF:${var}=${rrdfile}:${var}:AVERAGE", "LINE1:${var}#FF0000");
178 (my $averages, my $width, my $height) =
179 RRDs::graph("${outdir}/${var}.png.new",
180 "-w", "720", @graphdef);
181
182 if (RRDs::error) {
183 print "Error while graphing: " . RRDs::error . "\n";
184 } else {
185 rename("${outdir}/${var}.png.new", "${outdir}/${var}.png");
186 }
187
188 print HTML "<a href=\"${var}.html\"><img src=\"${var}.png\" width=\"${width}\" height=\"${height}\" border=\"0\"></a>";
189
190 open (HTML2, ">${outdir}/${var}.html.new");
191 print HTML2 "<html><head><title>" . $vars->{$var}->{'name'} . "</title></head>";
192 print HTML2 '<body bgcolor="#ffffff">';
193
194 ($averages, $width, $height) =
195 RRDs::graph("${outdir}/${var}.long.png.new",
196 "-w", "1008", @graphdef);
197
198 if (RRDs::error) {
199 print "Error while graphing: " . RRDs::error . "\n";
200 } else {
201 rename("${outdir}/${var}.long.png.new", "${outdir}/${var}.long.png");
202 }
203
204 print HTML2 "<img src=\"${var}.long.png\" width=\"${width}\" height=\"${height}\"><br>";
205
206 ($averages, $width, $height) =
207 RRDs::graph("${outdir}/${var}.week.png.new",
208 "-w", "1008", "-e", "now", "-s", "end-1w", @graphdef);
209
210 if (RRDs::error) {
211 print "Error while graphing: " . RRDs::error . "\n";
212 } else {
213 rename("${outdir}/${var}.week.png.new", "${outdir}/${var}.week.png");
214 }
215
216 print HTML2 "<img src=\"${var}.week.png\" width=\"${width}\" height=\"${height}\"><br>";
217
218 ($averages, $width, $height) =
219 RRDs::graph("${outdir}/${var}.year.png.new",
220 "-w", "1008", "-e", "now", "-s", "end-1y", @graphdef);
221
222 if (RRDs::error) {
223 print "Error while graphing: " . RRDs::error . "\n";
224 } else {
225 rename("${outdir}/${var}.year.png.new", "${outdir}/${var}.year.png");
226 }
227
228 print HTML2 "<img src=\"${var}.year.png\" width=\"${width}\" height=\"${height}\"><br>";
229
230 print HTML2 "</body></html>\n";
231 close(HTML2);
232 rename("${outdir}/${var}.html.new", "${outdir}/${var}.html");
233 }
234
235 print HTML "</body></html>\n";
236 print HTML "<br>Generated on: " . localtime(time());
237 print HTML ' by <a href="http://git.zerfleddert.de/cgi-bin/gitweb.cgi/upsgraph">upsgraph</a>.';
238
239 close(HTML);
240
241 rename("${outdir}/index.html.new", "${outdir}/index.html");
242
243 sleep(${step}/2);
244 }
Impressum, Datenschutz