diff options
Diffstat (limited to 'examples/historical/web/nms.gathering.org/showswitch.pl')
-rwxr-xr-x | examples/historical/web/nms.gathering.org/showswitch.pl | 249 |
1 files changed, 249 insertions, 0 deletions
diff --git a/examples/historical/web/nms.gathering.org/showswitch.pl b/examples/historical/web/nms.gathering.org/showswitch.pl new file mode 100755 index 0000000..e585841 --- /dev/null +++ b/examples/historical/web/nms.gathering.org/showswitch.pl @@ -0,0 +1,249 @@ +#! /usr/bin/perl +use CGI; +use DBI; +use Time::HiRes; +use POSIX ":sys_wait_h"; +use strict; +use warnings; +use lib '../../include'; +use nms; +use File::Basename; +my $cgi = CGI->new; +my $cwd = dirname($0); +my $switch = $cgi->param('id'); +my $width = $cgi->param('width'); +my $height = $cgi->param('height'); +my @pids = (); +my $resthtml = ""; + +$width = 500 unless (defined($width)); +$height = 250 unless (defined($height)); + +require "$cwd/mygraph.pl"; + +my $start = [Time::HiRes::gettimeofday]; +my $dbh = nms::db_connect(); + +sub filename($$$$) { + my ($switch, $last_port, $width, $height) = @_; + $last_port =~ y,/,_,; + return "$switch-$last_port-$width-$height.png"; +} + +# Fetch the name +my $ref = $dbh->selectrow_hashref('SELECT sysname,ip FROM switches WHERE switch=?', undef, $switch); + +print $cgi->header(-type=>'text/html; charset=utf-8'); +print <<"EOF"; +<html> + <head> + <title>snmp</title> + </head> + <body> + <h1>Switch $switch ($ref->{'sysname'} - $ref->{'ip'})</h1> +EOF + +my $q = $dbh->prepare('select ifname,\'Port \' || ifname as description,extract(epoch from time) as time,ifhcinoctets,ifhcoutoctets from switches natural join polls where time between now() - \'1 day\'::interval and now() and switch=? order by switch,ifname,time;') or die $dbh->errstr; +$q->execute($switch) or die $dbh->errstr; + +my (@totx, @toty1, @toty2) = (); + +my (@x, @y1, @y2) = (); +my $last_port; +my $portname = ""; +my $min_x = time; +my $max_x = time - 86400; +my ($min_y, $max_y, $prev_time, $prev_in, $prev_out); +my ($if,$of,$ifv,$ofv); +my $idx; +my ($min_ty,$max_ty) = (0, 10_000_000/8); + +$prev_time = -1; +my $last_totx; +# Buffer all the rows so we can fancy-sort them +my @rows; +while (my $ref = $q->fetchrow_hashref()) { + push @rows, $ref; +} +sub cmp_ports { + my @a = split(/(\d+)/, $_[0]); + my @b = split(/(\d+)/, $_[1]); + for (my $i = 0; $i < scalar @a; ++$i) { + last if $i >= scalar @b; + my $a = $a[$i]; + my $b = $b[$i]; + if ($a =~ /^\d+$/ && $a =~ /^\d+$/) { + return $a <=> $b if ($a != $b); + } else { + return $a cmp $b if ($a ne $b); + } + } + # None of the N first parts differed, this means the shortest one is first + return scalar @a <=> scalar @b; +} +sort { cmp_ports($a->{'ifname'}, $b->{'ifname'}) } @rows; +foreach my $ref (@rows) { + my $time = $ref->{'time'}; + my $in = $ref->{'ifhcinoctets'}; + my $out = $ref->{'ifhcoutoctets'}; + next if ($time == $prev_time); + if ($ref->{'ifname'} ne $last_port) { + if (defined $last_port) { + my $filename = filename($switch, $last_port, $width, $height); + + # reap children + waitpid(-1, WNOHANG); + + my $pid = fork(); + if ($pid == 0) { +# write out the graph + my $graph = makegraph($width, $height, $min_x, $max_x, $min_y, $max_y, 5); + plotseries($graph, \@x, \@y1, 255, 0, 0, $min_x, $max_y); + plotseries($graph, \@x, \@y2, 0, 0, 255, $min_x, $max_y); + + open GRAPH, ">$cwd/img/$filename" + or die "$cwd/img/$filename: $!"; + print GRAPH $graph->png; + close GRAPH; + exit; + } + + push @pids, $pid; + + $resthtml .= "<div style=\"float: left;\"><h2>$portname</h2>\n"; + $resthtml .= "<p><img src=\"img/$filename\" width=\"$width\" height=\"$height\" /></p></div>\n"; + } + + # Reset all the variables + @x = (); + @y1 = (); + @y2 = (); + ($min_y,$max_y) = (0, 10_000_000/8); + $prev_time = $ref->{'time'}; + $prev_in = $ref->{'ifhcinoctets'}; + $prev_out = $ref->{'ifhcoutoctets'}; + $last_port = $ref->{'ifname'}; + $portname = $ref->{'description'}; + ($if,$of,$ifv,$ofv) = (0,0,0,0); + ($prev_time,$prev_in,$prev_out) = ($time,$in,$out); + $idx = 0; + $last_totx = undef; + next; + } + + # Assume overflow (unless the switch has been down for >10 minutes) + my ($calc_in, $calc_out) = ($in, $out); + if ($in < $prev_in || $out < $prev_out) { + if ($prev_in < 4294967296 && $prev_out < 4294967296) { + # ick, heuristics + if ($prev_time - $time > 600 || ($in + 4294967296 - $prev_in) > 2147483648 || ($out + 4294967296 - $prev_out) > 2147483648) { + ($prev_time,$prev_in,$prev_out) = ($time,$in,$out); + next; + } + + $calc_in += 4294967296 if ($in < $prev_in); + $calc_out += 4294967296 if ($out < $prev_out); + } else { + $prev_in = 0; + $prev_out = 0; + } + } + + # Remove dupes + if ($in == $prev_in && $out == $prev_out) { + ($prev_time,$prev_in,$prev_out) = ($time,$in,$out); + next; + } + + # Find the current flow + my $if = ($calc_in - $prev_in) / ($time - $prev_time); + my $of = ($calc_out - $prev_out) / ($time - $prev_time); + + # Summarize (we don't care about the summed variance for now) + $min_x = $time if (!defined($min_x) || $time < $min_x); + $max_x = $time if (!defined($max_x) || $time > $max_x); + $min_y = $if if (!defined($min_y) || $if < $min_y); + $min_y = $of if ($of < $min_y); + $max_y = $if if (!defined($max_y) || $if > $max_y); + $max_y = $of if ($of > $max_y); + + my $pt = 0.5 * ($time + $prev_time); + + push @x, $pt; + push @y1, $if; + push @y2, $of; + + while ($idx < $#totx && $pt > $totx[$idx]) { + ++$idx; + } + if ($idx >= $#totx) { + push @totx, $pt; + push @toty1, $if; + push @toty2, $of; + ++$idx; + + $min_ty = $if if (!defined($min_ty) || $if < $min_ty); + $min_ty = $of if ($of < $min_ty); + $max_ty = $if if (!defined($max_ty) || $if > $max_ty); + $max_ty = $of if ($of > $max_ty); + } else { + if (!defined($last_totx) || $last_totx != $idx) { + $toty1[$idx] += $if; + $toty2[$idx] += $of; + } + $last_totx = $idx; + + $min_ty = $toty1[$idx] if (!defined($min_ty) || $toty1[$idx] < $min_ty); + $min_ty = $toty2[$idx] if ($toty2[$idx] < $min_ty); + $max_ty = $toty1[$idx] if (!defined($max_ty) || $toty1[$idx] > $max_ty); + $max_ty = $toty2[$idx] if ($toty2[$idx] > $max_ty); + } + + ($prev_time,$prev_in,$prev_out) = ($time,$in,$out); +} +$dbh->disconnect; + +# last graph +my $filename = filename($switch, $last_port, $width, $height); + +my $pid = fork(); +if ($pid == 0) { + my $graph = makegraph($width, $height, $min_x, $max_x, $min_y, $max_y, 5); + plotseries($graph, \@x, \@y1, 255, 0, 0, $min_x, $max_y); + plotseries($graph, \@x, \@y2, 0, 0, 255, $min_x, $max_y); + + open GRAPH, ">$cwd/img/$filename" + or die "img/$filename: $!"; + print GRAPH $graph->png; + close GRAPH; + exit; +} + +push @pids, $pid; + +$resthtml .= "<div style=\"float: left;\"><h2>$portname</h2>\n"; +$resthtml .= "<p><img src=\"img/$filename\" width=\"$width\" height=\"$height\" /></p></div>\n"; + +# total graph +my $graph = makegraph($width, $height, $min_x, $max_x, $min_ty, $max_ty, 5); +plotseries($graph, \@totx, \@toty1, 255, 0, 0, $min_x, $max_ty); +plotseries($graph, \@totx, \@toty2, 0, 0, 255, $min_x, $max_ty); + +$filename = "$switch-$width-$height.png"; +open GRAPH, ">$cwd/img/$filename" or die "img/$filename: $!"; +print GRAPH $graph->png; +close GRAPH; + +# Wait for all the other graphs to be done +while (waitpid(-1, 0) != -1) { + 1; +} + +print $resthtml; + +print "<div style=\"float: left;\"><h2>Total</h2>\n"; +print "<p><img src=\"img/$filename\" width=\"$width\" height=\"$height\" /></p></div>\n"; + +my $elapsed = Time::HiRes::tv_interval($start); +printf "<p style=\"clear: both;\">Page and all graphs generated in %.2f seconds.</p>\n", $elapsed; +print "</body>\n</html>\n"; |