]> git.sesse.net Git - nms/blob - web/ext/showswitch.pl
c0150054e271d89c605af1c110cc7e50868996fe
[nms] / web / ext / showswitch.pl
1 #!/usr/bin/perl
2 use CGI;
3 use DBI;
4 use Time::HiRes;
5 use POSIX ":sys_wait_h";
6 use strict;
7 use warnings;
8
9 use mygraph;
10 require 'glue.pl';
11
12 my $cgi = CGI->new;
13 my $switch = $cgi->param('id');
14 my $width = $cgi->param('width');
15 my $height = $cgi->param('height');
16 my @pids = ();
17 my $resthtml = "";
18
19 $width = 500 unless (defined($width));
20 $height = 250 unless (defined($height));
21
22 my $graph = mygraph::mygraph_new($width, $height);
23
24 my $start = [Time::HiRes::gettimeofday];
25 my $dbh = DBI->connect("dbi:Pg:dbname=tg", "tg", "tg06")
26     or die "Couldn't connect to database";
27
28 # Fetch the name
29 my $ref = $dbh->selectrow_hashref('SELECT sysname FROM switches WHERE switch=?', undef, $switch);
30
31 print $cgi->header(-type=>'text/html; charset=utf-8');
32 print <<"EOF";
33 <html>
34   <head>
35     <title>snmp</title>
36   </head>
37   <body>
38     <h1>Switch $switch ($ref->{'sysname'})</h1>
39 EOF
40
41 my $q = $dbh->prepare('select port,coalesce(description, \'Port \' || port) as description,extract(epoch from time) as time,bytes_in,bytes_out from polls natural join switches natural left join portnames where time between \'2005-03-23 05:17:36+01\' and  \'2005-03-24 05:17:36+01\' and switch=? order by switch,port,time;');
42 $q->execute($switch);
43
44 my (@totx, @toty1, @toty2) = ();
45
46 my (@x, @y1, @y2) = ();
47 my $last_port = -1;
48 my $portname = "";
49 my $min_x = time;
50 my $max_x = time - 86400;
51 my ($min_y, $max_y, $prev_time, $prev_in, $prev_out);
52 my ($if,$of,$ifv,$ofv);
53 my $idx;
54 my ($min_ty,$max_ty) = (0, 10_000_000/8);
55
56 $prev_time = -1;
57 my $last_totx;
58 while (my $ref = $q->fetchrow_hashref()) {
59     my $time = $ref->{'time'};
60     my $in = $ref->{'bytes_in'};
61     my $out = $ref->{'bytes_out'};
62     next if ($time == $prev_time);
63
64     if ($ref->{'port'} != $last_port) {
65         if ($last_port != -1) {
66             my $filename = "$switch-$last_port-$width-$height.png";
67
68             # reap children
69             waitpid(-1, WNOHANG);
70
71             my $numpids = 0;
72
73             my $pid = fork();
74             if ($pid == 0) {
75                 # write out the graph
76                 # print "$width, $height, $min_x, $max_x, $min_y, $max_y, 5<br/>\n";
77
78                 my $x_c = create_array(@x);
79                 my $y1_c = create_array(@y1);
80                 my $y2_c = create_array(@y2);
81
82 #               my $startthis = [Time::HiRes::gettimeofday];
83                 mygraph::mygraph_make_graph($graph, $min_x, $max_x, $min_y, $max_y, 5);
84                 mygraph::mygraph_plot_series($graph, $x_c, $y1_c, $#x, 255, 0, 0);
85                 mygraph::mygraph_plot_series($graph, $x_c, $y2_c, $#x, 0, 0, 255);
86                 mygraph::mygraph_to_file($graph, "img/$filename");
87 #               mygraph::mygraph_cleanup ($graph);
88 #               my $elapsedthis = Time::HiRes::tv_interval($startthis); 
89 #               printf "$elapsedthis seconds<br/>\n";
90
91                 exit;
92             }
93
94             push @pids, $pid;
95
96             $resthtml .= "<div style=\"float: left;\"><h2>$portname</h2>\n";
97             $resthtml .= "<p><img src=\"img/$filename\" width=\"$width\" height=\"$height\" /></p></div>\n";
98         }
99
100         # Reset all the variables
101         @x = ();
102         @y1 = ();
103         @y2 = ();
104         ($min_y,$max_y) = (0, 10_000_000/8);
105         $prev_time = $ref->{'time'};
106         $prev_in = $ref->{'bytes_in'};
107         $prev_out = $ref->{'bytes_out'};
108         $last_port = $ref->{'port'};
109         $portname = $ref->{'description'};
110         ($if,$of,$ifv,$ofv) = (0,0,0,0);
111         ($prev_time,$prev_in,$prev_out) = ($time,$in,$out);
112         $idx = 0;
113         $last_totx = undef;
114         next;
115     }
116
117     # Assume overflow (unless the switch has been down for >10 minutes)
118     my ($calc_in, $calc_out) = ($in, $out);
119     if ($in < $prev_in || $out < $prev_out) {
120         # ick, heuristics
121         if ($prev_time - $time > 600 || ($in + 4294967296 - $prev_in) > 2147483648 || ($out + 4294967296 - $prev_out) > 2147483648) {
122             ($prev_time,$prev_in,$prev_out) = ($time,$in,$out);
123             next;
124         }
125
126         $calc_in += 4294967296 if ($in < $prev_in);
127         $calc_out += 4294967296 if ($out < $prev_out);
128     }
129
130     # Remove dupes
131     if ($in == $prev_in && $out == $prev_out) {
132         ($prev_time,$prev_in,$prev_out) = ($time,$in,$out);
133         next;
134     }
135
136     # Find the current flow
137     my $if = ($calc_in - $prev_in) / ($time - $prev_time);
138     my $of = ($calc_out - $prev_out) / ($time - $prev_time);
139
140     # Summarize (we don't care about the summed variance for now)       
141     $min_x = $time if (!defined($min_x) || $time < $min_x);
142     $max_x = $time if (!defined($max_x) || $time > $max_x);
143     $min_y = $if if (!defined($min_y) || $if < $min_y);
144     $min_y = $of if ($of < $min_y);
145     $max_y = $if if (!defined($max_y) || $if > $max_y);
146     $max_y = $of if ($of > $max_y);
147
148     my $pt = 0.5 * ($time + $prev_time);
149
150     push @x, $pt;
151     push @y1, $if;
152     push @y2, $of;
153
154     while ($idx < $#totx && $pt > $totx[$idx]) {
155         ++$idx;
156     }
157     if ($idx >= $#totx) {
158         push @totx, $pt;
159         push @toty1, $if;
160         push @toty2, $of;
161         ++$idx;
162
163         $min_ty = $if if (!defined($min_ty) || $if < $min_ty);
164         $min_ty = $of if ($of < $min_ty);
165         $max_ty = $if if (!defined($max_ty) || $if > $max_ty);
166         $max_ty = $of if ($of > $max_ty);
167     } else {
168         if (!defined($last_totx) || $last_totx != $idx) {
169             $toty1[$idx] += $if;
170             $toty2[$idx] += $of;
171         }
172         $last_totx = $idx;
173
174         $min_ty = $toty1[$idx] if (!defined($min_ty) || $toty1[$idx] < $min_ty);
175         $min_ty = $toty2[$idx] if ($toty2[$idx] < $min_ty);
176         $max_ty = $toty1[$idx] if (!defined($max_ty) || $toty1[$idx] > $max_ty);
177         $max_ty = $toty2[$idx] if ($toty2[$idx] > $max_ty);
178     }
179
180     ($prev_time,$prev_in,$prev_out) = ($time,$in,$out);
181 }
182 $dbh->disconnect;
183
184 # last graph
185 my $filename = "$switch-$last_port-$width-$height.png";
186
187 my $pid = fork();
188 if ($pid == 0) {
189     my $x_c = create_array(@x);
190     my $y1_c = create_array(@y1);
191     my $y2_c = create_array(@y2);
192
193 #    my $startthis = [Time::HiRes::gettimeofday];
194     mygraph::mygraph_make_graph($graph, $min_x, $max_x, $min_y, $max_y, 5);
195     mygraph::mygraph_plot_series($graph, $x_c, $y1_c, $#x, 255, 0, 0);
196     mygraph::mygraph_plot_series($graph, $x_c, $y2_c, $#x, 0, 0, 255);
197     mygraph::mygraph_to_file($graph, "img/$filename");
198 #    mygraph::mygraph_cleanup ($graph);
199 #    my $elapsedthis = Time::HiRes::tv_interval($startthis); 
200 #    printf "$elapsedthis seconds<br/>\n";
201
202     exit;
203 }
204
205 push @pids, $pid;
206
207 $resthtml .= "<div style=\"float: left;\"><h2>$portname</h2>\n";
208 $resthtml .= "<p><img src=\"img/$filename\" width=\"$width\" height=\"$height\" /></p></div>\n";
209
210 # total graph
211 $filename = "$switch-$width-$height.png";
212 my $x_c = create_array(@totx);
213 my $y1_c = create_array(@toty1);
214 my $y2_c = create_array(@toty2);
215
216 # my $startthis = [Time::HiRes::gettimeofday];
217 mygraph::mygraph_make_graph($graph, $min_x, $max_x, $min_y, $max_y, 5);
218 mygraph::mygraph_plot_series($graph, $x_c, $y1_c, $#totx, 255, 0, 0);
219 mygraph::mygraph_plot_series($graph, $x_c, $y2_c, $#totx, 0, 0, 255);
220 mygraph::mygraph_to_file($graph, "img/$filename");
221
222 mygraph::mygraph_cleanup ($graph);
223 # my $elapsedthis = Time::HiRes::tv_interval($startthis); 
224 # printf "$elapsedthis seconds<br/>\n";
225
226 # Wait for all the other graphs to be done
227 while (waitpid(-1, 0) != -1) {
228     1;
229 }
230
231 print $resthtml;
232
233 print "<div style=\"float: left;\"><h2>Total</h2>\n";
234 print "<p><img src=\"img/$filename\" width=\"$width\" height=\"$height\" /></p></div>\n";
235
236 my $elapsed = Time::HiRes::tv_interval($start); 
237 printf "<p style=\"clear: both;\">Page and all graphs generated in %.2f seconds.</p>\n", $elapsed;
238 print "</body>\n</html>\n";