diff options
Diffstat (limited to 'web/nms.gathering.org')
22 files changed, 1984 insertions, 0 deletions
diff --git a/web/nms.gathering.org/apkart.pl b/web/nms.gathering.org/apkart.pl new file mode 100755 index 0000000..a89cb68 --- /dev/null +++ b/web/nms.gathering.org/apkart.pl @@ -0,0 +1,89 @@ +#! /usr/bin/perl +use CGI qw(fatalsToBrowser); +use GD; +use DBI; +use lib '../../include'; +use nms; +use strict; +use warnings; +my $cgi = CGI->new; + +#my $greentimeout = 7200; +my $greentimeout = 15*60; +my $maxtimeout = $greentimeout*9; + +my $dbh = nms::db_connect(); + +GD::Image->trueColor(1); + +my $img = GD::Image->new('bg07.png'); + +my $blk = $img->colorResolve(0, 0, 0); +my $red = $img->colorResolve(255, 0, 0); +my $grn = $img->colorResolve(0, 255, 0); +my $blu = $img->colorResolve(0, 0, 255); + +# Her ska' det bættre skrivas STORT jah! +my $title = new GD::Image(75,15); +$img->alphaBlending(1); +$title->alphaBlending(1); +my $titlebg = $title->colorResolve(255, 255, 255); +$title->fill(0,0,$titlebg); +$title->transparent($titlebg); +$title->string(gdGiantFont,7,0,"APEKART",$title->colorResolve(255, 0, 0)); +$img->copyResampled($title, 500, 0, 0, 0, 400, 100, 75, 15); +$img->copyResampled($title, 500, 550, 0, 0, 400, 100, 75, 15); + +$img->string(gdMediumBoldFont,0,0,"Access points",$blk); +$img->string(gdSmallFont,0,20,"Shows if a Cisco access point is plugged into the port",$blk); + +my %palette = ( 'notpolled' => $blu, 'missing' => $red, 'present' => $grn ); + +my @states = qw(present missing notpolled); + +for my $i (0..$#states) { + my $y = 60 + 20 * (4 - $i); + $img->filledRectangle(20, $y, 30, $y + 10, $palette{$states[$i]}); + $img->rectangle(20, $y, 30, $y + 10, $blk); + $img->stringFT($blk, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, $y + 10, $states[$i]); +} + +my $q = $dbh->prepare("select switch,sysname,model,last_poll < now() - '30 seconds'::interval as notpolled,placement from switches natural join placements natural join ap_poll order by zorder"); +$q->execute(); +while (my $ref = $q->fetchrow_hashref()) { + my $sysname = $ref->{'sysname'}; + my $model = $ref->{'model'}; + my $state; + if ($ref->{'notpolled'}) { + $state = 'notpolled'; + } elsif ($model =~ /^cisco AIR-/) { + $state = 'present'; + } else { + $state = 'missing'; + $sysname .= " $model"; + } + my $clr = $palette{$state}; + + $ref->{'placement'} =~ /\((\d+),(\d+)\),\((\d+),(\d+)\)/; + $img->filledRectangle($3,$4,$1,$2,$clr); + $img->rectangle($3,$4,$1,$2,$blk); + + my ($x2, $y2, $x1, $y1) = ($1, $2, $3, $4); + my $max_textlen = ($x2-$x1) > ($y2-$y1) ? $x2-$x1 : $y2-$y1; + while (length($sysname) * 6 > $max_textlen) { + # Try to abbreviate sysname if it is too long for the box + $sysname =~ s/^(.*)[a-z]~?([0-9]+)$/$1~$2/ or last; + } + if (($x2-$x1) > ($y2-$y1)) { + $img->string(gdSmallFont,$x1+2,$y1,$sysname,$blk); + } else { + $img->stringUp(gdSmallFont,$x1,$y2-3,$sysname,$blk); + } +} +$dbh->disconnect; + +if (!defined($ARGV[0])) { + print $cgi->header(-type=>'image/png', + -refresh=>'10; ' . CGI::url()); +} +print $img->png; diff --git a/web/nms.gathering.org/bg07.png b/web/nms.gathering.org/bg07.png Binary files differnew file mode 100644 index 0000000..ec54ad3 --- /dev/null +++ b/web/nms.gathering.org/bg07.png diff --git a/web/nms.gathering.org/dhcpkart.pl b/web/nms.gathering.org/dhcpkart.pl new file mode 100755 index 0000000..2af4272 --- /dev/null +++ b/web/nms.gathering.org/dhcpkart.pl @@ -0,0 +1,94 @@ +#! /usr/bin/perl +use CGI qw(fatalsToBrowser); +use GD; +use DBI; +use lib '../../include'; +use nms; +my $cgi = CGI->new; + +#my $greentimeout = 7200; +my $greentimeout = 15*60; +my $maxtimeout = $greentimeout*9; + +my $dbh = nms::db_connect(); + +GD::Image->trueColor(1); +my $map = 'bg07.png'; +die "$map does not exist" unless -e $map; +$img = GD::Image->new($map); + +my $blk = $img->colorResolve(0, 0, 0); + +$img->string(gdMediumBoldFont,0,0,"DHCP-lease status",$blk); +$img->string(gdSmallFont,0,20,"Last received DHCP-request",$blk); + +# first 1/5: green (<30 min) +# middle 3/5: yellow -> red (30 min - 6 hours) +# last 1/5: blue (>6 hours) +my $grn = $img->colorResolve(0, 255, 0); +my $blu = $img->colorResolve(0, 0, 255); + +my $l1 = 42 + (236 - 42)/5; +my $l2 = 236 - (236 - 42)/5; + +$img->filledRectangle(32, 42, 53, $l1, $grn); +$img->string(gdSmallFont,56,$l1-8,($greentimeout/60)." min",$blk); + +$img->filledRectangle(32, $l2, 53, 237, $blu); +$img->string(gdSmallFont,56,$l2-5,($maxtimeout/60)." min",$blk); + +for my $y ($l1..$l2) { + my $i = 1.0 - ($y - $l1) / ($l2 - $l1); + my $clr = get_color($i); + + $img->filledRectangle(32,$y,53,$y+1,$clr); +} + +my $q = $dbh->prepare('select switch,sysname,placement,EXTRACT(EPOCH FROM now() - last_ack) as age from switches natural join placements natural join dhcp order by sysname'); +$q->execute(); +while (my $ref = $q->fetchrow_hashref()) { + my $age = $ref->{'age'}; + if (!defined($age) || $age > $maxtimeout) { + $clr = $img->colorResolve(0, 0, 255); + } elsif ($age < $greentimeout) { + $clr = $img->colorResolve(0, 255, 0); + } else { + # 30 minutes = 0.0 + # 6 hours = 1.0 + + my $intensity = log($age / $greentimeout) / log($maxtimeout/$greentimeout); + $clr = get_color(1.0 - $intensity); + } + + my $sysname = $ref->{'sysname'}; + if ($sysname !~ m/d0/i) { # don't draw distro-switches + $ref->{'placement'} =~ /\((\d+),(\d+)\),\((\d+),(\d+)\)/; + $img->filledRectangle($3,$4,$1,$2,$clr); + $img->rectangle($3,$4,$1,$2,$blk); + + my ($x2, $y2, $x1, $y1) = ($1, $2, $3, $4); + my $max_textlen = ($x2-$x1) > ($y2-$y1) ? $x2-$x1 : $y2-$y1; + while (length($sysname) * 6 > $max_textlen) { + # Try to abbreviate sysname if it is too long for the box + $sysname =~ s/^(.*)[a-z]~?([0-9]+)$/$1~$2/ or last; + } + if (($x2-$x1) > ($y2-$y1)) { + $img->string(gdSmallFont,$x1+2,$y1,$sysname,$blk); + } else { + $img->stringUp(gdSmallFont,$x1,$y2-3,$sysname,$blk); + } + } +} +$dbh->disconnect; + +if (!defined($ARGV[0])) { + print $cgi->header(-type=>'image/png', + -refresh=>'10; ' . CGI::url()); +} +print $img->png; + +sub get_color { + my $intensity = shift; + my $gamma = 1.0/1.90; + return $img->colorResolve(255.0, 255.0 * ($intensity ** $gamma), 0); +} diff --git a/web/nms.gathering.org/index.html b/web/nms.gathering.org/index.html new file mode 100644 index 0000000..2857377 --- /dev/null +++ b/web/nms.gathering.org/index.html @@ -0,0 +1,92 @@ +<html> + <head> + <title>snmp</title> + </head> + <body> + <p>tg light & magic. :-)</p> + + <ul> + <li><a href="dhcpkart.pl">DHCP-kart</a> + <br /><i>Oversikt over DHCP-lease etter switch</i> + </li> + + <br /> + + <li><a href="nettkart-text.pl">Nettkart</a> + <br /><i>Trafikkoversikt</i> + </li> + + <br /> + + <li><a href="nettkart-telnet.pl">Nettkart</a> + <br /><i>Trafikkoversikt /m telnetlink</i> + </li> + + <br /> +<!-- Kun moderat nyttig når vi har disablet alle webinterfacene... + <li><a href="nettkart-web.pl">Nettkart</a> + <br /><i>Trafikkoversikt /m weblink</i> + </li> + + <br /> +--> + <li><a href="portkart.pl">Nettkart, per port</a> + <br /><i>Trafikkoversikt per port</i> + </li> + + <br /> + + <li><a href="uplinkkart.pl">Uplink-kart</a> + <br /><i>Hvilke switcher har ikke to uplinker</i> + </li> + + <br /> + + <li><a href="uplinktrafikkart.pl">Uplink-trafikkart</a> + <br /><i>Hvem burde hatt mer enn to uplinker</i> + </li> + + <br /> + + <li><a href="stromkart.pl">Strømkart</a> + <br /><i>Hvilke switcher har færre enn fem tilkoblede klienter</i> + </li> + + <br /> + + <li><a href="apkart.pl">Aksesspunkt-kart</a> + <br /><i>Hvilke aksesspunkter er plugget i</i> + </li> + + <br /> + + <!--<li><a href="overlay.pl">Overlay-nettkart</a> + <br /><i>Teh magic 3D!</i> + </li> + + <br /> --> + + <li><a href="smanagement.pl">Kommander switcher</a> + <br /><i>Konfigurer switchene</i> + </li> + + <br /> + + <li><a href="sshow.pl">Utførte og køede kommandoer</a> + <br /><i>Se og håndter kommandoer som er utført og fortsatt i køen</i> + </li> + + <br /> + + <!--<li><a href="stempmap.pl">Temperaturkart</a> + <br /><i>Temperaturkart for switchene</i> + </li> + + <br /> --> + + <li><a href="mbd-status.pl">MBD-status</a> + <br /><i>Hva spiller folk mest?</i> + </li> + </ul> + </body> +</html> diff --git a/web/nms.gathering.org/led.pl b/web/nms.gathering.org/led.pl new file mode 100755 index 0000000..a05041d --- /dev/null +++ b/web/nms.gathering.org/led.pl @@ -0,0 +1,20 @@ +#! /usr/bin/perl +use CGI; +use GD; +use DBI; +use lib '../../include'; +use nms; +my $cgi = CGI->new; + +my $dbh = nms::db_connect(); + +print $cgi->header(-type=>'text/plain', -expires=>'now'); + +my $q = $dbh->prepare('select * from ( SELECT switch,sysname,sum(bytes_in) AS bytes_in,sum(bytes_out) AS bytes_out from switches natural left join get_current_datarate() group by switch,sysname) t1 natural join placements order by zorder;'); +$q->execute(); +while (my $ref = $q->fetchrow_hashref()) { + my $sysname = $ref->{'sysname'}; + next unless $sysname =~ /e\d+-\d+/; + printf "%s %s\n", $sysname, (defined($ref->{'bytes_in'}) ? 'on' : 'off'); +} +$dbh->disconnect; diff --git a/web/nms.gathering.org/mbd-status.pl b/web/nms.gathering.org/mbd-status.pl new file mode 100755 index 0000000..d37781f --- /dev/null +++ b/web/nms.gathering.org/mbd-status.pl @@ -0,0 +1,44 @@ +#! /usr/bin/perl +use CGI; +use DBI; +use lib '../../include'; +use nms; +my $cgi = CGI->new; + +my $dbh = nms::db_connect(); +print $cgi->header(-type=>'text/html; charset=utf-8', -refresh=>'10; ' . CGI::url()); + +print <<"EOF"; +<html> + <head> + <title>MBD status</title> + </head> + <body> + <h1>MBD status</h1> + + <p>Spill søkt etter siste 15 minutter:</p> + + <table> + <tr> + <th>Beskrivelse</th> + <th>Aktive servere</th> + </tr> +EOF + +my $q = $dbh->prepare('select description,sum(active_servers) as active_servers from (select distinct on (game,port) * from mbd_log where ts >= now() - \'10 minutes\'::interval order by game,port,ts desc ) t1 group by description order by sum(active_servers) desc, description;'); +$q->execute(); +while (my $ref = $q->fetchrow_hashref()) { + print <<"EOF"; + <tr> + <td>$ref->{'description'}</td> + <td>$ref->{'active_servers'}</td> + </tr> +EOF +} +$dbh->disconnect; + +print <<"EOF"; + </table> + </body> +</html> +EOF diff --git a/web/nms.gathering.org/mygraph.pl b/web/nms.gathering.org/mygraph.pl new file mode 100755 index 0000000..64104aa --- /dev/null +++ b/web/nms.gathering.org/mygraph.pl @@ -0,0 +1,179 @@ +#! /usr/bin/perl -T +use strict; +use warnings; +use GD; +use POSIX; +use Time::Zone; + +sub blendpx { + my ($gd, $x, $y, $r, $g, $b, $frac) = @_; + my ($ro, $go, $bo) = $gd->rgb($gd->getPixel($x, $y)); + + # workaround for icky 256-color graphs + # $frac = int($frac * 32) / 32; + + my $rn = $ro * (1.0 - $frac) + $r * $frac; + my $gn = $go * (1.0 - $frac) + $g * $frac; + my $bn = $bo * (1.0 - $frac) + $b * $frac; + + $gd->setPixel($x, $y, $gd->colorResolve($rn, $gn, $bn)); +} + +# Standard implementation of Wu's antialiased line algorithm. +sub wuline { + my ($gd, $x1, $y1, $x2, $y2, $r, $g, $b, $a) = @_; + $x1 = POSIX::floor($x1); + $x2 = POSIX::floor($x2); + $y1 = POSIX::floor($y1); + $y2 = POSIX::floor($y2); + + if (abs($x2 - $x1) > abs($y2 - $y1)) { + # x-directional + if ($y2 < $y1) { + ($x2, $y2, $x1, $y1) = ($x1, $y1, $x2, $y2); + } + + my $y = POSIX::floor($y1); + my $frac = $y1 - $y; + my $dx = ($x2 > $x1) ? 1 : -1; + my $dy = ($y2 - $y1) / abs($x2 - $x1); + + for (my $x = $x1; $x != $x2 + $dx; $x += $dx) { + blendpx($gd, $x, $y, $r, $g, $b, $a * (1.0 - $frac)); + blendpx($gd, $x, $y + 1, $r, $g, $b, $a * $frac); + $frac += $dy; + if ($frac > 1) { + $frac -= 1; + ++$y; + } + } + } else { + # y-directional + if ($x2 < $x1) { + ($x2, $y2, $x1, $y1) = ($x1, $y1, $x2, $y2); + } + my $x = POSIX::floor($x1); + my $frac = $x1 - $x; + my $dy = ($y2 > $y1) ? 1 : -1; + my $dx = ($x2 - $x1) / abs($y2 - $y1); + + for (my $y = $y1; $y != $y2 + $dy; $y += $dy) { + blendpx($gd, $x, $y, $r, $g, $b, $a * (1.0 - $frac)); + blendpx($gd, $x + 1, $y, $r, $g, $b, $a * $frac); + $frac += $dx; + if ($frac > 1) { + $frac -= 1; + ++$x; + } + } + } +} + +sub makegraph { + my $xoffset = 70; + my ($width, $height, $min_x, $max_x, $min_y, $max_y, $tickgran) = @_; + + # Create our base graph + my $graph = new GD::Image($width, $height, 1); + my $white = $graph->colorAllocate(255, 255, 255); + my $gray = $graph->colorAllocate(230, 230, 255); + my $black = $graph->colorAllocate(0, 0, 0); + +# $graph->fill(0, 0, $white); + $graph->filledRectangle(0, 0, $width, $height, $white); # seems to work better + + $::xs = ($width - ($xoffset+2)) / ($max_x - $min_x); + $::ys = ($height - 33) / ($min_y - $max_y); + + # Hour marks + for my $i ($xoffset+1..$width-2) { + if (((($i-($xoffset+1)) / $::xs + $min_x) / 3600) % 2 == 1) { + $graph->line($i, 0, $i, $height - 1, $gray); + } + } + + # Hour text + for my $i (0..23) { + my @bounds = GD::Image::stringFT(undef, $black, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 0, 0, $i); + my $w = $bounds[2] - $bounds[0]; + + # Determine where the center of this will be + my $starthour = POSIX::fmod(($min_x + Time::Zone::tz_local_offset()) / 3600, 24); + my $diff = POSIX::fmod($i - $starthour + 24, 24); + + my $center = ($diff * 3600 + 1800) * $::xs; + + next if ($center - $w / 2 < 1 || $center + $w / 2 > $width - ($xoffset+2)); + $graph->stringFT($black, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, $xoffset + $center - $w / 2, $height - 6, $i); + } + + # + # Y lines; we want max 11 of them (zero-line, plus five on each side, or + # whatever) but we don't want the ticks to be on minimum 50 (or + # whatever $tickgran is set to). However, if there would be + # really really few lines, go down an order of magnitude and try + # again. + # + my $ytick; + do { + $ytick = ($max_y - $min_y) / 11; + $ytick = POSIX::ceil($ytick / $tickgran) * $tickgran; + $tickgran *= 0.1; + } while (($max_y - $min_y) / $ytick < 4); + + for my $i (-11..11) { + my $y = ($i * $ytick - $max_y) * $::ys + 10; + next if ($y < 2 || $y > $height - 18); + + if ($i == 0) { + wuline($graph, $xoffset, $y, $width - 1, $y, 0, 0, 0, 1.0); + wuline($graph, $xoffset, $y + 1, $width - 1, $y + 1, 0, 0, 0, 1.0); + } else { + wuline($graph, $xoffset, $y, $width - 1, $y, 0, 0, 0, 0.2); + } + + # text + my $traf = 8 * ($i * $ytick); + my $text; + if ($traf >= 500_000_000) { + $text = (sprintf "%.1f Gbit", ($traf/1_000_000_000)); + } elsif ($traf >= 500_000) { + $text = (sprintf "%.1f Mbit", ($traf/1_000_000)); + } else { + $text = (sprintf "%.1f kbit", ($traf/1_000)); + } + + my @bounds = GD::Image::stringFT(undef, $black, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 0, 0, $text); + my $w = $bounds[2] - $bounds[0]; + my $h = $bounds[1] - $bounds[5]; + + next if ($y - $h/2 < 2 || $y + $h/2 > $height - 12); + $graph->stringFT($black, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, ($xoffset - 4) - $w, $y + $h/2, $text); + } + + # Nice border(TM) + $graph->rectangle($xoffset, 0, $width - 1, $height - 1, $black); + + return $graph; +} + +sub plotseries { + my ($graph, $xvals, $yvals, $r, $g, $b, $min_x, $max_y) = @_; + my $xoffset = 70; + + my @xvals = @{$xvals}; + my @yvals = @{$yvals}; + + my $x = $xvals[0]; + my $y = $yvals[0]; + for my $i (1..$#xvals) { + next if ($::xs * ($xvals[$i] - $x) < 2 && $::ys * ($yvals[$i] - $y) > -2); + + wuline($graph, ($x-$min_x) * $::xs + $xoffset + 1, ($y-$max_y) * $::ys + 10, + ($xvals[$i]-$min_x) * $::xs + $xoffset + 1, ($yvals[$i]-$max_y) * $::ys + 10, $r, $g, $b, 1.0); + $x = $xvals[$i]; + $y = $yvals[$i]; + } +} + +1; diff --git a/web/nms.gathering.org/nettkart-continuous.html b/web/nms.gathering.org/nettkart-continuous.html new file mode 100644 index 0000000..e51eea0 --- /dev/null +++ b/web/nms.gathering.org/nettkart-continuous.html @@ -0,0 +1,31 @@ +<html> + <body> + <div id="d"></div> + <script type="text/javascript"> + <!-- + var existing_img = null; + + function load_new() { + var i = document.createElement('img'); + i.onload = function() { loaded(i); }; + i.style.display = 'none'; + i.src = '/nettkart.pl?random=' + (new Date()).getTime(); + document.getElementById('d').appendChild(i); + } + + function loaded(i) { + i.style.display = ''; + + if (existing_img) { + existing_img.parentElement.removeChild(existing_img); + } + existing_img = i; + + setTimeout(function() { load_new(); }, 10000); + } + + load_new(); + --> + </script> + </body> +</html> diff --git a/web/nms.gathering.org/nettkart-telnet.pl b/web/nms.gathering.org/nettkart-telnet.pl new file mode 100755 index 0000000..57cac19 --- /dev/null +++ b/web/nms.gathering.org/nettkart-telnet.pl @@ -0,0 +1,47 @@ +#! /usr/bin/perl +use CGI; +use DBI; +use lib '../../include'; +use nms; +my $cgi = CGI->new; + +my $dbh = nms::db_connect(); +print $cgi->header(-type=>'text/html; charset=utf-8', -refresh=>'45; ' . CGI::url()); + +print <<"EOF"; +<html> + <head> + <title>nettkart - telnet</title> + </head> + <body> + <map name="switches"> +EOF + +my $q = $dbh->prepare("select * from switches natural join placements where ip <> inet '127.0.0.1'"); +$q->execute(); +while (my $ref = $q->fetchrow_hashref()) { + $ref->{'placement'} =~ /\((\d+),(\d+)\),\((\d+),(\d+)\)/; + + my $traffic = 4.0 * $ref->{'bytes_in'} + $ref->{'bytes_out'}; # average and convert to bits (should be about the same in practice) + my $ttext; + if ($traffic >= 1_000_000_000) { + $ttext = sprintf "%.2f Gbit/port/sec", $traffic/1_000_000_000; + } elsif ($traffic => 1_000_000) { + $ttext = sprintf "%.2f Mbit/port/sec", $traffic/1_000_000; + } else { + $ttext = sprintf "%.2f kbit/port/sec", $traffic/1_000; + } + + printf " <area shape=\"rect\" coords=\"%u,%u,%u,%u\" target=\"blank\" href=\"telnet://$ref->{'ip'}\" alt=\"%s (%s)\" onmouseover=\"window.status='%s (%s)'; return true\" onmouseout=\"window.status=''\" />\n", + $3, $4, $1, $2, $ref->{'switch'}, $ref->{'sysname'}, + $ttext, $ref->{'sysname'}, $ttext; +} +$dbh->disconnect; + +print <<"EOF"; + </map> + + <p><img src="nettkart.pl" usemap="#switches" /></p> + </body> +</html> +EOF diff --git a/web/nms.gathering.org/nettkart-text.pl b/web/nms.gathering.org/nettkart-text.pl new file mode 100755 index 0000000..d3f4be7 --- /dev/null +++ b/web/nms.gathering.org/nettkart-text.pl @@ -0,0 +1,47 @@ +#! /usr/bin/perl +use CGI; +use DBI; +use lib '../../include'; +use nms; +my $cgi = CGI->new; + +my $dbh = nms::db_connect(); +print $cgi->header(-type=>'text/html; charset=utf-8', -refresh=>'10; ' . CGI::url()); + +print <<"EOF"; +<html> + <head> + <title>nettkart</title> + </head> + <body> + <map name="switches"> +EOF + +my $q = $dbh->prepare("select * from switches natural join placements where ip <> inet '127.0.0.1'"); +$q->execute(); +while (my $ref = $q->fetchrow_hashref()) { + $ref->{'placement'} =~ /\((\d+),(\d+)\),\((\d+),(\d+)\)/; + + my $traffic = 4.0 * $ref->{'bytes_in'} + $ref->{'bytes_out'}; # average and convert to bits (should be about the same in practice) + my $ttext; + if ($traffic >= 1_000_000_000) { + $ttext = sprintf "%.2f Gbit/port/sec", $traffic/1_000_000_000; + } elsif ($traffic => 1_000_000) { + $ttext = sprintf "%.2f Mbit/port/sec", $traffic/1_000_000; + } else { + $ttext = sprintf "%.2f kbit/port/sec", $traffic/1_000; + } + + printf " <area shape=\"rect\" coords=\"%u,%u,%u,%u\" href=\"showswitch.pl?id=%u\" alt=\"%s (%s)\" onmouseover=\"window.status='%s (%s)'; return true\" onmouseout=\"window.status=''\" />\n", + $3, $4, $1, $2, $ref->{'switch'}, $ref->{'sysname'}, + $ttext, $ref->{'sysname'}, $ttext; +} +$dbh->disconnect; + +print <<"EOF"; + </map> + + <p><img src="nettkart.pl" usemap="#switches" /></p> + </body> +</html> +EOF diff --git a/web/nms.gathering.org/nettkart-web.pl b/web/nms.gathering.org/nettkart-web.pl new file mode 100755 index 0000000..ce76c35 --- /dev/null +++ b/web/nms.gathering.org/nettkart-web.pl @@ -0,0 +1,47 @@ +#! /usr/bin/perl +use CGI; +use DBI; +use lib '../../include'; +use nms; +my $cgi = CGI->new; + +my $dbh = nms::db_connect(); +print $cgi->header(-type=>'text/html; charset=utf-8', -refresh=>'45; ' . CGI::url()); + +print <<"EOF"; +<html> + <head> + <title>nettkart - web</title> + </head> + <body> + <map name="switches"> +EOF + +my $q = $dbh->prepare("select * from switches natural join placements where ip <> inet '127.0.0.1'"); +$q->execute(); +while (my $ref = $q->fetchrow_hashref()) { + $ref->{'placement'} =~ /\((\d+),(\d+)\),\((\d+),(\d+)\)/; + + my $traffic = 4.0 * $ref->{'bytes_in'} + $ref->{'bytes_out'}; # average and convert to bits (should be about the same in practice) + my $ttext; + if ($traffic >= 1_000_000_000) { + $ttext = sprintf "%.2f Gbit/port/sec", $traffic/1_000_000_000; + } elsif ($traffic => 1_000_000) { + $ttext = sprintf "%.2f Mbit/port/sec", $traffic/1_000_000; + } else { + $ttext = sprintf "%.2f kbit/port/sec", $traffic/1_000; + } + + printf " <area shape=\"rect\" coords=\"%u,%u,%u,%u\" href=\"http://$ref->{'ip'}\" alt=\"%s (%s)\" onmouseover=\"window.status='%s (%s)'; return true\" onmouseout=\"window.status=''\" />\n", + $3, $4, $1, $2, $ref->{'switch'}, $ref->{'sysname'}, + $ttext, $ref->{'sysname'}, $ttext; +} +$dbh->disconnect; + +print <<"EOF"; + </map> + + <p><img src="nettkart.pl" usemap="#switches" /></p> + </body> +</html> +EOF diff --git a/web/nms.gathering.org/nettkart.pl b/web/nms.gathering.org/nettkart.pl new file mode 100755 index 0000000..b9517f8 --- /dev/null +++ b/web/nms.gathering.org/nettkart.pl @@ -0,0 +1,142 @@ +#! /usr/bin/perl +use CGI; +use GD; +use Image::Magick; +use DBI; +use lib '../../include'; +use nms; +my $cgi = CGI->new; + +# Sekrit night-mode +my $night = defined($cgi->param('night')); + +my $dbh = nms::db_connect(); + +GD::Image->trueColor(1); +my ($img, $text_img); + +my $img = GD::Image->new('bg07.png'); +if ($night) { + my ($width, $height) = ($img->width, $img->height); + + $img = GD::Image->new($width, $height, 1); + $img->alphaBlending(0); + $img->saveAlpha(1); + my $blank = $img->colorAllocateAlpha(0, 0, 0, 127); + $img->filledRectangle(0, 0, $img->width - 1, $img->height - 1, $blank); + + $text_img = GD::Image->new($width, $height, 1); + $text_img->alphaBlending(0); + $text_img->saveAlpha(1); + my $blank = $text_img->colorAllocateAlpha(0, 0, 0, 127); + $text_img->filledRectangle(0, 0, $text_img->width - 1, $text_img->height - 1, $blank); +} else { + $img = GD::Image->new('bg07.png'); + $text_img = $img; +} + +my $blk = $img->colorResolve(0, 0, 0); + +for my $y (42..236) { + my $i = 4.0 * ($y - 236.0) / (42.0 - 237.0); + my $clr = get_color($i); + + $img->filledRectangle(12, $y, 33, $y+1, $clr); + $text_img->filledRectangle(12, $y, 33, $y+1, $clr); +} + +$text_img->rectangle(12,42,33,236,$blk); + +my $tclr = $night ? $text_img->colorResolve(255, 255, 255) : $blk; +$text_img->stringFT($tclr, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*0.0/4.0, "100 Gbit/sec"); +$text_img->stringFT($tclr, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*1.0/4.0, "10 Gbit/sec"); +$text_img->stringFT($tclr, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*2.0/4.0, "1 Gbit/sec"); +$text_img->stringFT($tclr, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*3.0/4.0, "100 Mbit/sec"); +$text_img->stringFT($tclr, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*4.0/4.0, "10 Mbit/sec"); +$text_img->stringFT($tclr, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 1000, 700, "NMS (C) 2005-2012 Tech:Server"); + +my $q = $dbh->prepare("select * from ( SELECT switch,sysname,sum(bytes_in) AS bytes_in,sum(bytes_out) AS bytes_out from switches natural left join get_current_datarate() where ip <> inet '127.0.0.1' group by switch,sysname) t1 natural join placements order by zorder;"); +$q->execute(); +while (my $ref = $q->fetchrow_hashref()) { + + # for now: + # 10Mbit/switch = green + # 100Mbit/switch = yellow + # 1Gbit/switch = red + # 10Gbit/switch = white + + my $clr; + + if (defined($ref->{'bytes_in'})) { + my $intensity = 0.0; + my $traffic = 4.0 * ($ref->{'bytes_in'} + $ref->{'bytes_out'}); # average and convert to bits (should be about the same in practice) + + my $max = 100_000_000_000.0; # 100Gbit + my $min = 10_000_000.0; # 10Mbit + if ($traffic >= $min) { + $intensity = log($traffic / $min) / log(10); + $intensity = 4.0 if ($intensity > 4.0); + } + $clr = get_color($intensity); + } else { + $clr = $img->colorResolve(0, 0, 255); + } + + my $sysname = $ref->{'sysname'}; + $sysname =~ s/-sekrit//; + + $ref->{'placement'} =~ /\((\d+),(\d+)\),\((\d+),(\d+)\)/; + $img->filledRectangle($3,$4,$1,$2,$clr); + $text_img->filledRectangle($3,$4,$1,$2,$clr); + + $img->rectangle($3,$4,$1,$2,$blk); + $text_img->rectangle($3,$4,$1,$2,$blk); + my ($x2, $y2, $x1, $y1) = ($1, $2, $3, $4); + my $max_textlen = ($x2-$x1) > ($y2-$y1) ? $x2-$x1 : $y2-$y1; + while (length($sysname) * 6 > $max_textlen) { + # Try to abbreviate sysname if it is too long for the box + $sysname =~ s/^(.*)[a-z]~?([0-9]+)$/$1~$2/ or last; + } + if (($x2-$x1) > ($y2-$y1)) { + $text_img->string(gdSmallFont,$x1+2,$y1,$sysname,$blk); + } else { + $text_img->stringUp(gdSmallFont,$x1,$y2-3,$sysname,$blk); + } +} +$dbh->disconnect; + +print $cgi->header(-type=>'image/png', -expires=>'now'); +if ($night) { + my $magick = Image::Magick->new; + $magick->BlobToImage($img->png); + $magick->Blur(sigma=>10.0, channel=>'All'); + $magick->Gamma(gamma=>1.90); + + my $m2 = Image::Magick->new; + $m2->Read('bg07.png'); + $m2->Negate(); + $m2->Composite(image=>$magick, compose=>'Atop'); + + my $m3 = Image::Magick->new; + $m3->BlobToImage($text_img->png); + $m2->Composite(image=>$m3, compose=>'Atop'); + + $img = $m2->ImageToBlob(); + print $img; +} else { + print $img->png; +} + +sub get_color { + my $intensity = shift; + my $gamma = 1.0/1.90; + if ($intensity > 3.0) { + return $img->colorResolve(255.0 * ((4.0 - $intensity) ** $gamma), 255.0 * ((4.0 - $intensity) ** $gamma), 255.0 * ((4.0 - $intensity) ** $gamma)); + } elsif ($intensity > 2.0) { + return $img->colorResolve(255.0, 255.0 * (($intensity - 2.0) ** $gamma), 255.0 * (($intensity - 2.0) ** $gamma)); + } elsif ($intensity > 1.0) { + return $img->colorResolve(255.0, 255.0 * ((2.0 - $intensity) ** $gamma), 0); + } else { + return $img->colorResolve(255.0 * ($intensity ** $gamma), 255, 0); + } +} diff --git a/web/nms.gathering.org/portkart.pl b/web/nms.gathering.org/portkart.pl new file mode 100755 index 0000000..1269173 --- /dev/null +++ b/web/nms.gathering.org/portkart.pl @@ -0,0 +1,82 @@ +#! /usr/bin/perl +use CGI; +use GD; +use DBI; +use lib '../../include'; +use nms; +my $cgi = CGI->new; + +my $dbh = nms::db_connect(); + +GD::Image->trueColor(1); +$img = GD::Image->new('bg07.png'); + +my $blk = $img->colorResolve(0, 0, 0); + +for my $y (42..236) { + my $i = 3.0 * ($y - 236.0) / (42.0 - 237.0); + my $clr = get_color($i); + + $img->filledRectangle(12,$y,33,$y+1,$clr); +} + +$img->stringFT($blk, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*0.0/3.0, "1 Gbit/sec"); +$img->stringFT($blk, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*1.0/3.0, "100 Mbit/sec"); +$img->stringFT($blk, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*2.0/3.0, "10 Mbit/sec"); +$img->stringFT($blk, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*3.0/3.0, "1 Mbit/sec"); +$img->stringFT($blk, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 1000, 620, "NMS (C) 2005-2007 Tech:Server"); + +my $q = $dbh->prepare('select switch,port,bytes_in,bytes_out,placement,switchtype from switches natural join placements natural join get_datarate() where switchtype like \'%3100%\''); +$q->execute(); +while (my $ref = $q->fetchrow_hashref()) { + + # for now: + # 100kbit/port = all green + # 1gbit/port = all red + + my $clr; + + if (defined($ref->{'bytes_in'})) { + my $intensity = 0.0; + my $traffic = 4.0 * ($ref->{'bytes_in'} + $ref->{'bytes_out'}); # average and convert to bits (should be about the same in practice) + + my $max = 100_000_000_000.0; # 1Gbit + my $min = 1_000_000.0; # 1Mbit + if ($traffic >= $min) { + $intensity = log($traffic / $min) / log(10); + $intensity = 4.0 if ($intensity > 4.0); + } + $clr = get_color($intensity); + } else { + $clr = $img->colorResolve(0, 0, 255); + } + + $ref->{'placement'} =~ /\((\d+),(\d+)\),\((\d+),(\d+)\)/; + my $npo = 48; + my $f = ($ref->{'port'} - 1) % 2; + my $po = ($ref->{'port'} - 1 - $f)/2; + my $h = 2*($2-$4)/$npo; + my $w = ($1-$3)/2; + + $img->filledRectangle($3+$w*$f,$4+$po*$h,$3+$w+$w*$f,$4+$h*($po+1),$clr); +# $img->rectangle($3+$w*$f,$4+$po*$h,$3+$w+$w*$f,$4+$h*($po+1),$blk); + $img->rectangle($3,$4,$1,$2,$blk); +} +$dbh->disconnect; + +print $cgi->header(-type=>'image/png'); +print $img->png; + +sub get_color { + my $intensity = shift; + my $gamma = 1.0/1.90; + if ($intensity > 3.0) { + return $img->colorResolve(255.0 * ((4.0 - $intensity) ** $gamma), 255.0 * ((4.0 - $intensity) ** $gamma), 255.0 * ((4.0 - $intensity) ** $gamma)); + } elsif ($intensity > 2.0) { + return $img->colorResolve(255.0, 255.0 * (($intensity - 2.0) ** $gamma), 255.0 * (($intensity - 2.0) ** $gamma)); + } elsif ($intensity > 1.0) { + return $img->colorResolve(255.0, 255.0 * ((2.0 - $intensity) ** $gamma), 0); + } else { + return $img->colorResolve(255.0 * ($intensity ** $gamma), 255, 0); + } +} diff --git a/web/nms.gathering.org/showswitch.pl b/web/nms.gathering.org/showswitch.pl new file mode 100755 index 0000000..5ed0029 --- /dev/null +++ b/web/nms.gathering.org/showswitch.pl @@ -0,0 +1,221 @@ +#! /usr/bin/perl +use CGI; +use DBI; +use Time::HiRes; +use POSIX ":sys_wait_h"; +use strict; +use warnings; +use lib '../../include'; +use nms; +my $cgi = CGI->new; +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 './mygraph.pl'; + +my $start = [Time::HiRes::gettimeofday]; +my $dbh = nms::db_connect(); + +# Fetch the name +my $ref = $dbh->selectrow_hashref('SELECT sysname 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'})</h1> +EOF + +my $q = $dbh->prepare('select port,coalesce(description, \'Port \' || port) as description,extract(epoch from time) as time,bytes_in,bytes_out from switches natural left join portnames natural join polls where time between now() - \'1 day\'::interval and now() and switch=? order by switch,port,time;') or die $dbh->errstr; +$q->execute($switch) or die $dbh->errstr; + +my (@totx, @toty1, @toty2) = (); + +my (@x, @y1, @y2) = (); +my $last_port = -1; +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; +while (my $ref = $q->fetchrow_hashref()) { + my $time = $ref->{'time'}; + my $in = $ref->{'bytes_in'}; + my $out = $ref->{'bytes_out'}; + next if ($time == $prev_time); + + if ($ref->{'port'} != $last_port) { + if ($last_port != -1) { + my $filename = "$switch-$last_port-$width-$height.png"; + + # 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, ">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"; + } + + # Reset all the variables + @x = (); + @y1 = (); + @y2 = (); + ($min_y,$max_y) = (0, 10_000_000/8); + $prev_time = $ref->{'time'}; + $prev_in = $ref->{'bytes_in'}; + $prev_out = $ref->{'bytes_out'}; + $last_port = $ref->{'port'}; + $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 = "$switch-$last_port-$width-$height.png"; + +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, ">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, ">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"; diff --git a/web/nms.gathering.org/slide.html b/web/nms.gathering.org/slide.html new file mode 100644 index 0000000..046020d --- /dev/null +++ b/web/nms.gathering.org/slide.html @@ -0,0 +1,38 @@ +<!doctype html> +<html> + <body> + <iframe id="tgview" style="border: 0; width: 1536px; height: 864px"></iframe> + + <script> + (function() { + var urls = [ + 'http://onlineclock.net/', + 'http://nms.tg13.gathering.org/dhcpkart.pl', + 'http://nms.tg13.gathering.org/nettkart-text.pl', + 'http://nms.tg13.gathering.org/nettkart-text.pl', + 'http://nms.tg13.gathering.org/uplinkkart.pl', + 'http://nms.tg13.gathering.org/uplinktrafikkart.pl', + 'http://nms.tg13.gathering.org/apkart.pl', + 'http://stats.tg13.gathering.org/' + ]; + + var view = document.getElementById('tgview'); + var fload = function( frame, url ) { + frame.src = url; + }; + + var i = 0; + (function rotation() { + //if ( i != l-1 ) { + if ( i != urls.length-1 ) { + i++ + } else { + i = 0; + } + fload( view, urls[i] ); + setTimeout( arguments.callee, 10000 ); + })(); + })(); + </script> + </body> +</html> diff --git a/web/nms.gathering.org/smanagement.pl b/web/nms.gathering.org/smanagement.pl new file mode 100755 index 0000000..c01c52d --- /dev/null +++ b/web/nms.gathering.org/smanagement.pl @@ -0,0 +1,239 @@ +#!/usr/bin/perl +use warnings; +use strict; +use CGI; +use DBI; +use Data::Dumper; +use Switch; +use lib '../../include'; +use nms; + +# Grab from .htaccess-authentication +my $user = $ENV{'REMOTE_USER'}; + +my $dbh = nms::db_connect(); +$dbh->{AutoCommit} = 0; + +# Ugly casting, found no other way +my $sinsert = $dbh->prepare( "INSERT INTO squeue + (gid, added, priority, addr, sysname, cmd, author) + VALUES(?::text::int, timeofday()::timestamptz, ?::text::int, ?::text::inet, ?, ?, ?)") + or die "Could not prepare sinsert"; +my $sgetip = $dbh->prepare("SELECT ip FROM switches WHERE sysname = ?") + or die "Could not prepare sgetip"; +my $sgid = $dbh->prepare("SELECT nextval('squeue_group_sequence') as gid"); +my $all_switches = $dbh->prepare("SELECT sysname FROM switches ORDER BY sysname"); + +sub parse_range($) { + my $switches = $_; + my @range; + + my @rangecomma = split(/\s*,\s*/, $switches); + foreach (@rangecomma) { + my ($first, $last) = $_ =~ /(e\d+\-(?:sw)?[123456])\s*\-\s*(e\d+\-(?:sw)?[123456])?/; + if (!defined($first) && $_ =~ /e\d+\-(sw)?[123456]/) { + $first = $_; + } + if (!defined($first)) { + print "<font color=\"red\">Parse error in: $_</font><br>\n"; + next; + } + my ($rowstart, $placestart) = $first =~ /e(\d+)\-(?:sw)?([123456])/; + if (!defined($rowstart) || !defined($placestart)) { + print "<font color=\"red\">Parse error in: $_</font><br>\n"; + next; + } + my ($rowend, $placeend); + if (!defined($last)) { + $rowend = $rowstart; + $placeend = $placestart; + } + else { + ($rowend, $placeend) = $last =~ /e(\d+)\-(?:sw)?([123456])/; + } + if (!defined($rowend) || !defined($placeend)) { + print "<font color=\"red\">Parse error in: $_</font><br>\n"; + next; + } + #print "e $rowstart - $placestart to e $rowend - $placeend <br>\n"; + for (my $i = $rowstart; $i <= $rowend; $i++) { + my $dostart; + if ($rowstart != $i) { + $dostart = 1; + } + else { + $dostart = $placestart; + } + for (my $j = $dostart; $j <= 6; $j++) { + last if ($i == $rowend && $j > $placeend); + push(@range, "e$i-$j"); + } + } + } +# foreach (@range) { +# print ":: $_<br>\n"; +# } + return @range; +} + +sub get_addr_from_switchnum($) { + my ($sysname) = @_; + + $sgetip->execute($sysname); + if ($sgetip->rows() < 1) { + print "Could not get the ip for: ".$sysname; + return undef; + } + my $row = $sgetip->fetchrow_hashref(); + return $row->{'ip'}; +} + +my $cgi = new CGI; + +print $cgi->header(-type=>'text/html; charset=utf-8'); + +print << "EOF"; +<html> + <head> + <title>Switch managment</title> + </head> + <body> + <p>Du er logget inn som: $user</p> + <form method="POST" action="smanagement.pl"> + <table> + <tr> + <td>Alle switchene</td> + <td><input type="radio" name="rangetype" value="all" /></td> + <td></td> + <td></td> + </tr> + <tr> + <td>Switch</td> + <td><input type="radio" checked name="rangetype" value="switch" /></td> + <td><input type="text" name="range" /></td> + <td>e1-2, e3-3 - e10-2</td> + </tr> + <tr> + <td>Regexp</td> + <td><input type="radio" name="rangetype" value="regexp" /></td> + <td><input type="text" name="regexp" /></td> + <td>Regulært uttrykk</td> + </tr> + <tr> + <td>Rad</td> + <td><input type="radio" name="rangetype" value="row" /></td> + <td><input type="text" name="range" /></td> + <td>1,3-5 (Disabled)</td> + </tr> + <tr> + <td><hr /></td> + <td><hr /></td> + <td><hr /></td> + <td><hr /></td> + </tr> + <tr> + <td>Prioritet</td> + <td></td> + <td> + <select name="priority"> + <option value="1">1 (lavest)</option> + <option value="2">2</option> + <option selected value="3">3</option> + <option value="4">4</option> + <option value="5">5 (høyest)</option> + </select> + </td> + </tr> + <tr> + <td>Kommando(er):</td> + <td></td> + <td><textarea name="cmd" cols="80" rows="24"></textarea></td> + <td>En kommando per linje. Linjer som begynner med ! sørger for at nms ikke venter på normal prompt, men fyrer av gårde neste linje umiddelbart. Kjekt for kommandoer av typen "!save\\nY"</td> + </td> + <tr> + <td><hr /></td> + <td><hr /></td> + <td><hr /></td> + <td><hr /></td> + </tr> + </table> + <input type="submit" value="Execute!" /><br /> + </form> +EOF + +print "<br />\n"; + +my @switches = (); +switch ($cgi->param('rangetype')) { + case 'all' { + print "Sender `".$cgi->param('cmd')."` til alle switchene<br />"; + @switches = (); + $all_switches->execute(); + while (my $ref = $all_switches->fetchrow_hashref) { + push @switches, $ref->{'sysname'}; + } + } + case 'switch' { +# print "Sender `".$cgi->param('cmd')."` til switchene `" +# .$cgi->param('range')."`.<br />"; + $_ = $cgi->param('range'); + @switches = parse_range($_); + } + case 'regexp' { + @switches = (); + $all_switches->execute(); + while (my $ref = $all_switches->fetchrow_hashref) { + push @switches, $ref->{'sysname'} if $ref->{'sysname'} =~ $cgi->param('regexp'); + } + } + case 'row' { +# print "Sender `".$cgi->param('cmd')."` til radene `" +# .$cgi->param('range')."`.<br />"; +# print "This function does not work yet."; +# $_ = $cgi->param('range'); +# @switches = &parse_row_range($_); +# @switches = (); + print "<font color=\"red\">Slått av!</font>\n"; + } +} + +my $gid; +if (@switches > 0) { + $sgid->execute(); + my $row = $sgid->fetchrow_hashref(); + $gid = $row->{gid}; +} + +my $pri = $cgi->param('priority'); + +print "<pre>\n"; +foreach my $switch (@switches) { + my $addr = get_addr_from_switchnum($switch); + if (!defined($addr)) { + next; + } + my $cmd = $cgi->param('cmd'); + print "$switch got addr $addr <br>\n"; + print "Queuing commands for $switch:\n"; + my $result = $sinsert->execute($gid, $pri, $addr, $switch, $cmd, $user); + if (!$result) { + print "\t<font color=\"red\">" + ."Could not execute query." + ."</font>\n"; + print "\t".$dbh->errstr."\n"; + } + else { + print "\tQueued: $cmd\n"; + } + print "\n"; +} +$dbh->commit; +if (defined($gid)) { + print "<a href=\"sshow.pl?action=showgid&gid=".$gid."\">Vis resultat</a>\n"; +} +print "</pre>\n"; + +print << "EOF"; + </body> +</html> +EOF diff --git a/web/nms.gathering.org/ssendfile.pl b/web/nms.gathering.org/ssendfile.pl new file mode 100755 index 0000000..ec2ebb8 --- /dev/null +++ b/web/nms.gathering.org/ssendfile.pl @@ -0,0 +1,48 @@ +#!/usr/bin/perl +use warnings; +use strict; +use lib '../../include'; +use POSIX; + +my $delaytime = 30; +my $poll_frequency = 60; + +sub mylog { + my $msg = shift; + my $time = POSIX::ctime(time); + $time =~ s/\n.*$//; + printf STDERR "[%s] %s\n", $time, $msg; +} + +if ($#ARGV != 1) { + die("Error in arguments passed\n". + "./ssendfile.pl addr configfile\n"); +} + +my $conn = nms::switch_connect($ARGV[0]); +if (!defined($conn)) { + die("Could not connect to switch.\n"); +} + +open(CONFIG, $ARGV[1]); +while (<CONFIG>) { + my $cmd = $_; + $cmd =~ s/[\r\n]+//g; + print "Executing: `$cmd`\n"; +# if ($cmd =~ /ip ifconfig swif0 (\d{1-3}\.\d{1-3}\.\d{1-3}\.\d{1-3})/) { +# print "New ip: $1\n"; +# $conn->cmd( String => $cmd, +# Timeout => 3); +# $conn = nms::switch_connect($1); +# if (!defined($conn)) { +# die "Could not connect to new ip: $1\n"; +# } +# } +# else { + my @data = nms::switch_exec($cmd, $conn); + foreach my $line (@data) { + $line =~ s/[\r\n]+//g; + print "$line\n"; + } +# } +} diff --git a/web/nms.gathering.org/sshow.pl b/web/nms.gathering.org/sshow.pl new file mode 100755 index 0000000..f406b69 --- /dev/null +++ b/web/nms.gathering.org/sshow.pl @@ -0,0 +1,257 @@ +#!/usr/bin/perl +use lib '../../include'; +use nms; + +use warnings; +use strict; +use Switch; +use CGI; +use DBI; + +# Grab from .htaccess-authentication +my $user = $ENV{'REMOTE_USER'}; + +my $dbh = nms::db_connect(); +$dbh->{AutoCommit} = 0; + +my $sgetdone = $dbh->prepare( +"SELECT * +FROM squeue +WHERE processed = 't' +ORDER BY updated DESC, sysname +LIMIT ?::text::int") + or die "Could not prepare sgetdone"; + +my $sgetdonegid = $dbh->prepare( +"SELECT * +FROM squeue +WHERE processed = 't' AND gid = ?::text::int +ORDER BY updated DESC, sysname") + or die "Could not prepare sgetdonegid"; + +my $slistdonegid = $dbh->prepare( +"SELECT DISTINCT gid, cmd, author, added +FROM squeue +WHERE processed = 't' +ORDER BY gid") + or die "Could not prepare slistdonegid"; + +my $slistprocgid = $dbh->prepare( +"SELECT DISTINCT gid, cmd, author, added +FROM squeue +WHERE processed = 'f' +ORDER BY gid") + or die "Could not prepare slistdonegid"; + +my $sgetgid = $dbh->prepare( +"SELECT * +FROM squeue +WHERE gid = ?") + or die "Could not prepare sgetgid"; + +my $sgetprocessing = $dbh->prepare( +"SELECT * +FROM squeue +WHERE processed = 'f' +ORDER BY updated DESC, gid, sysname") + or die "Could not prepare sgetdone"; + +my $sgetnoconnect = $dbh->prepare( +"SELECT * +FROM squeue +WHERE result = 'Could not connect to switch, delaying...'") + or die "Could not prepare sgetnoconnect"; + +my $sdisablegid = $dbh->prepare(" +UPDATE squeue SET disabled = 't' +WHERE gid = ?::text::int") + or die "Could not prepare sdisablegid"; +my $senablegid = $dbh->prepare(" +UPDATE squeue SET disabled = 'f' +WHERE gid = ?::text::int") + or die "Could not prepare sdisablegid"; + + +my $cgi = new CGI; + +print $cgi->header(-type=>'text/html; charset=utf-8'); + +print << "EOF"; +<html> + <head> + <title>Switch managment</title> + </head> + <body> + <p>Du er logget inn som: $user</p> + <form method="POST" action="sshow.pl"> + <p> + Vis <input type="text" name="count" size="4" value="10" /> siste<br /> + Vis: <select name="action" /> + <option value="listgid">Grupper</option> + <option value="done">Ferdige</option> + <option value="processing">I kø</option> + </select> + <input type="submit" value="Vis" /><br /> + </p> + </form> + <br /> +EOF + +my $limit = $cgi->param('count'); +if (!defined($limit)) { + $limit = 10; +} +my $action = $cgi->param('action'); +if (!defined($action)) { + $action = 'listgid'; +} + +if (defined($cgi->param('agid'))) { + my $gid = $cgi->param('gid'); + if (!defined($gid)) { + print "<font color=\"red\">Du har ikke valgt en gid å slette.</font>\n"; + print "<p>gid: ".$cgi->param('gid')." har blitt disablet.\n"; + } + else { + $senablegid->execute($gid); + print "<p>gid: ".$cgi->param('gid')." har blitt enablet.\n"; + } + $dbh->commit(); +} + +if ($action eq 'noconnect') { + print "<h3>Kunne ikke koble til disse switchene:</h3>\n"; + $sgetnoconnect->execute(); + print "<pre>\n"; + while ((my $row = $sgetnoconnect->fetchrow_hashref())) { + print "$row->{'sysname'} : $row->{'cmd'} : Added: $row->{'added'} : Updated: $row->{'updated'}\n"; + } + print "</pre>\n"; +} + +if ($action eq 'listgid') { + print "<pre>\n"; + print "<a href=\"sshow.pl?action=noconnect\" />Kunne ikke koble til</a>\n\n\n"; + print "<b>Ferdige:</b>\n"; + $slistdonegid->execute(); + my ($gid, $author); + $gid = -1; + while ((my $row = $slistdonegid->fetchrow_hashref())) { + $author = $row->{author}; + if ($gid != $row->{gid}) { + $gid = $row->{gid}; + print "GID: <a href=\"sshow.pl?action=showgid&gid=$gid\">$gid</a>\n"; + print "Author: $author\n"; + print "Added: ".$row->{added}."\n"; + } + my $cmd = $row->{cmd}; + print "\t$cmd\n"; + } + print "\n\n"; + print "<b>I kø:</b>\n"; + $slistprocgid->execute(); + $gid = -1; + while ((my $row = $slistprocgid->fetchrow_hashref())) { + $author = $row->{author}; + if ($gid != $row->{gid}) { + $gid = $row->{gid}; + print "GID: <a href=\"sshow.pl?action=showgid&gid=$gid\">$gid</a>\n"; + print "Author: $author\n"; + print "Added: ".$row->{added}."\n"; + } + my $cmd = $row->{cmd}; + print "\t$cmd\n"; + } + $dbh->commit(); + print "</pre>\n"; +} + +if ($action eq 'showgid') { + print "<pre>\n"; + $sgetgid->execute($cgi->param('gid')); + my $row = $sgetgid->fetchrow_hashref(); + print "GID: ".$row->{gid}."\n"; + print "Author: ".$row->{author}."\n"; + do { + print " <b>Name: ".$row->{sysname}." Addr: ".$row->{addr}."</b>\n"; + print " `<b>".$row->{cmd}."`</b>\n"; + print " <i>Added: ".$row->{added}." executed ".$row->{updated}."</i>\n"; + my $data = $row->{result}; + if (!defined($data)) { + $data = "Not executed yet!"; + } + my @lines = split(/[\n\r]+/, $data); + foreach my $line (@lines) { + print "\t$line\n"; + } + } while (($row = $sgetgid->fetchrow_hashref())); + print "</pre>\n"; +} + +if ($action eq 'done') { + print "<h3>Done</h3>\n"; + print "<pre>\n"; + + my $squery; + if (defined($cgi->param('gid'))) { + my $gid = $cgi->param('gid'); + $sgetdonegid->execute($gid); + $squery = $sgetdonegid; + } + else { + $sgetdone->execute($limit); + $squery = $sgetdone; + } + my $sysname = ''; + while (my $row = $squery->fetchrow_hashref()) { + if ($sysname ne $row->{'sysname'}) { + $sysname = $row->{'sysname'}; + print "$sysname (".$row->{addr}."):\n"; + } + print " Author: ".$row->{author}."\n"; + print " Cmd: ".$row->{cmd}."\n"; + print " Added: ".$row->{added}." Updated: ".$row->{updated}."\n"; + print " gID: ".$row->{gid}."\n"; + my @result = split(/[\n\r]+/, $row->{result}); + foreach (@result) { + print "\t".$_."\n"; + } + print "\n"; + } + $dbh->commit(); + print "</pre>\n"; +} +elsif ($action eq 'processing') { + print "<h3>Processing</h3>\n"; + print "<pre>\n"; + $sgetprocessing->execute(); + while (my $row = $sgetprocessing->fetchrow_hashref()) { + my $sysname = $row->{'sysname'}; + print "$sysname (".$row->{addr}."):\n"; + print " Author: ".$row->{author}."\n"; + print " Cmd: ".$row->{cmd}."\n"; + my $updated; + if (defined($row->{updated})) { $updated = $row->{updated}; } + else { $updated = 'never'; } + print " Added: ".$row->{added}." Updated: ".$updated."\n"; + print " Disabled: ".$row->{disabled}."\n"; + print " Locked: ".$row->{locked}."\n"; + print " gID: ".$row->{gid}; + print " <form action=\"sshow.pl\" methos=\"POST\">"; + print "<input type=\"hidden\" name=\"gid\" value=\"".$row->{gid}."\">"; + print "<input type=\"hidden\" name=\"action\" value=\"processing\">"; + if ($row->{disabled} == 0) { + print "<input type=\"submit\" name=\"agid\" value=\"Disable\">\n"; + } + else { + print "<input type=\"submit\" name=\"agid\" value=\"Enable\">\n"; + } + } + $dbh->commit(); + print "</pre>\n"; +} + +print << "EOF"; + </body> +</html> +EOF diff --git a/web/nms.gathering.org/stromkart.pl b/web/nms.gathering.org/stromkart.pl new file mode 100755 index 0000000..0aef634 --- /dev/null +++ b/web/nms.gathering.org/stromkart.pl @@ -0,0 +1,69 @@ +#! /usr/bin/perl +use CGI qw(fatalsToBrowser); +use GD; +use DBI; +use lib '../../include'; +use nms; +use strict; +use warnings; +my $cgi = CGI->new; + +#my $greentimeout = 7200; +my $greentimeout = 15*60; +my $maxtimeout = $greentimeout*9; + +my $dbh = nms::db_connect(); + +GD::Image->trueColor(1); +my $img = GD::Image->new('bg07.png'); + +my $blk = $img->colorResolve(0, 0, 0); + +$img->string(gdMediumBoldFont,0,0,"Switch uplink status",$blk); +$img->string(gdSmallFont,0,20,"Number of ports with activity",$blk); + +my $red = $img->colorResolve(255, 0, 0); +my $yel = $img->colorResolve(255, 255, 0); +my $grn = $img->colorResolve(0, 255, 0); +my $wht = $img->colorResolve(255, 255, 255); +my $gry = $img->colorResolve(127, 127, 127); + +my $q = $dbh->prepare('select switch,sysname,(select placement from placements where placements.switch=switches.switch) as placement,count((bytes_in > 0 and bytes_out > 0) or null) as active_ports,(max(last_poll_time) >= current_timestamp - interval \'2 minutes\') as fresh from switches natural left join get_current_datarate() natural join placements where switchtype like \'dlink3100%\' group by switch,sysname'); +$q->execute(); +while (my $ref = $q->fetchrow_hashref()) { + my $ports = $ref->{'active_ports'}; + my $sysname = $ref->{'sysname'}; + my $clr; + if ($ports < 5) { + $clr = $red; + } else { + if (!$ref->{'fresh'}) { + $clr = $yel; + } else { + $clr = $grn; + } + } + + $ref->{'placement'} =~ /\((\d+),(\d+)\),\((\d+),(\d+)\)/; + $img->filledRectangle($3,$4,$1,$2,$clr); + $img->rectangle($3,$4,$1,$2,$blk); + + my ($x2, $y2, $x1, $y1) = ($1, $2, $3, $4); + my $max_textlen = ($x2-$x1) > ($y2-$y1) ? $x2-$x1 : $y2-$y1; + while (length($sysname) * 6 > $max_textlen) { + # Try to abbreviate sysname if it is too long for the box + $sysname =~ s/^(.*)[a-z]~?([0-9]+)$/$1~$2/ or last; + } + if (($x2-$x1) > ($y2-$y1)) { + $img->string(gdSmallFont,$x1+2,$y1,$sysname,$blk); + } else { + $img->stringUp(gdSmallFont,$x1,$y2-3,$sysname,$blk); + } +} +$dbh->disconnect; + +if (!defined($ARGV[0])) { + print $cgi->header(-type=>'image/png', + -refresh=>'10; ' . CGI::url()); +} +print $img->png; diff --git a/web/nms.gathering.org/uplinkkart-text.pl b/web/nms.gathering.org/uplinkkart-text.pl new file mode 100755 index 0000000..de91e92 --- /dev/null +++ b/web/nms.gathering.org/uplinkkart-text.pl @@ -0,0 +1,38 @@ +#! /usr/bin/perl +use CGI; +use DBI; +use lib '../../include'; +use nms; +my $cgi = CGI->new; + +my $dbh = nms::db_connect(); +print $cgi->header(-type=>'text/html; charset=utf-8', -refresh=>'10; ' . CGI::url()); + +print <<"EOF"; +<html> + <head> + <title>Uplinkkart</title> + </head> + <body> + <map name="switches"> +EOF + +my $q = $dbh->prepare("SELECT * FROM switches NATURAL JOIN placements WHERE switchtype = 'dlink3100'"); +$q->execute(); +while (my $ref = $q->fetchrow_hashref()) { + $ref->{'placement'} =~ /\((\d+),(\d+)\),\((\d+),(\d+)\)/; + + my $ttext = 'FIXME: Put something here'; + printf " <area shape=\"rect\" coords=\"%u,%u,%u,%u\" href=\"switchdiag.pl?id=%u\" alt=\"%s (%s)\" onmouseover=\"window.status='%s (%s)'; return true\" onmouseout=\"window.status=''\" />\n", + $3, $4, $1, $2, $ref->{'switch'}, $ref->{'sysname'}, + $ttext, $ref->{'sysname'}, $ttext; +} +$dbh->disconnect; + +print <<"EOF"; + </map> + + <p><img src="uplinkkart.pl" usemap="#switches" /></p> + </body> +</html> +EOF diff --git a/web/nms.gathering.org/uplinkkart.pl b/web/nms.gathering.org/uplinkkart.pl new file mode 100755 index 0000000..32581a6 --- /dev/null +++ b/web/nms.gathering.org/uplinkkart.pl @@ -0,0 +1,70 @@ +#! /usr/bin/perl +use CGI qw(fatalsToBrowser); +use GD; +use DBI; +use lib '../../include'; +use nms; +use strict; +use warnings; +my $cgi = CGI->new; + +#my $greentimeout = 7200; +my $greentimeout = 15*60; +my $maxtimeout = $greentimeout*9; + +my $dbh = nms::db_connect(); + +GD::Image->trueColor(1); +my $img = GD::Image->new('bg07.png'); + +my $blk = $img->colorResolve(0, 0, 0); + +$img->string(gdMediumBoldFont,0,0,"Switch uplink status",$blk); +$img->string(gdSmallFont,0,20,"Number of ports with activity",$blk); + +my $red = $img->colorResolve(255, 0, 0); +my $yel = $img->colorResolve(255, 255, 0); +my $grn = $img->colorResolve(0, 255, 0); +my $blu = $img->colorResolve(0, 0, 255); +my $wht = $img->colorResolve(255, 255, 255); +my $gry = $img->colorResolve(127, 127, 127); + +my @palette = ( $blu, $red, $yel, $grn, $wht ); + +for my $ports (0..4) { + my $y = 60 + 20 * (4 - $ports); + $img->filledRectangle(20, $y, 30, $y + 10, $palette[$ports]); + $img->rectangle(20, $y, 30, $y + 10, $blk); + $img->stringFT($blk, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, $y + 10, $ports); +} + +my $q = $dbh->prepare('select switch,sysname,(select placement from placements where placements.switch=switches.switch) as placement,count((bytes_in > 0 and bytes_out > 0) or null) as active_ports from switches natural left join get_current_datarate() natural join placements where port between 45 and 48 and switchtype like \'dlink3100%\' group by switch,sysname'); +$q->execute(); +while (my $ref = $q->fetchrow_hashref()) { + my $ports = $ref->{'active_ports'}; + my $sysname = $ref->{'sysname'}; + my $clr = $palette[$ports]; + + $ref->{'placement'} =~ /\((\d+),(\d+)\),\((\d+),(\d+)\)/; + $img->filledRectangle($3,$4,$1,$2,$clr); + $img->rectangle($3,$4,$1,$2,$blk); + + my ($x2, $y2, $x1, $y1) = ($1, $2, $3, $4); + my $max_textlen = ($x2-$x1) > ($y2-$y1) ? $x2-$x1 : $y2-$y1; + while (length($sysname) * 6 > $max_textlen) { + # Try to abbreviate sysname if it is too long for the box + $sysname =~ s/^(.*)[a-z]~?([0-9]+)$/$1~$2/ or last; + } + if (($x2-$x1) > ($y2-$y1)) { + $img->string(gdSmallFont,$x1+2,$y1,$sysname,$blk); + } else { + $img->stringUp(gdSmallFont,$x1,$y2-3,$sysname,$blk); + } +} +$dbh->disconnect; + +if (!defined($ARGV[0])) { + print $cgi->header(-type=>'image/png', + -refresh=>'10; ' . CGI::url()); +} +print $img->png; diff --git a/web/nms.gathering.org/uplinktrafikkart.pl b/web/nms.gathering.org/uplinktrafikkart.pl new file mode 100755 index 0000000..32869b3 --- /dev/null +++ b/web/nms.gathering.org/uplinktrafikkart.pl @@ -0,0 +1,90 @@ +#! /usr/bin/perl +use CGI qw(fatalsToBrowser); +use GD; +use DBI; +use lib '../../include'; +use nms; +use strict; +use warnings; +my $cgi = CGI->new; + +#my $greentimeout = 7200; +my $greentimeout = 15*60; +my $maxtimeout = $greentimeout*9; + +my $dbh = nms::db_connect(); + +GD::Image->trueColor(1); +my $img = GD::Image->new('bg07.png'); + +my $blk = $img->colorResolve(0, 0, 0); + +for my $y (42..236) { + my $i = 2.0 * ($y - 236.0) / (42.0 - 237.0); + my $clr = get_color($i); + + $img->filledRectangle(12, $y, 33, $y+1, $clr); +} + +$img->string(gdMediumBoldFont,0,0,"Switch uplink traffic",$blk); +$img->string(gdSmallFont,0,20,"max of bytes in/out",$blk); + +my $red = $img->colorResolve(255, 0, 0); +my $yel = $img->colorResolve(255, 255, 0); +my $grn = $img->colorResolve(0, 255, 0); +my $wht = $img->colorResolve(255, 255, 255); + +$img->rectangle(12,42,33,236,$blk); + +$img->stringFT($blk, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*0.0/2.0, "4 Gbit/sec"); +$img->stringFT($blk, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*1.0/2.0, "2 Gbit/sec"); +$img->stringFT($blk, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*2.0/2.0, "1 Gbit/sec"); +$img->stringFT($blk, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 1000, 700, "NMS (C) 2005-2012 Tech:Server"); + +my $q = $dbh->prepare('select switch,sysname,(select placement from placements where placements.switch=switches.switch) as placement,greatest(sum(bytes_in),sum(bytes_out)) as traffic from switches natural left join get_current_datarate() natural join placements where port between 45 and 48 and switchtype like \'dlink3100%\' group by switch,sysname'); +$q->execute(); +while (my $ref = $q->fetchrow_hashref()) { + my $traffic = $ref->{'traffic'} * 8.0; # convert to bits + my $sysname = $ref->{'sysname'}; + + my $max = 4_000_000_000.0; # 2Gbit + my $min = 1_000_000_000.0; # 1Gbit + $traffic = $max if ($traffic > $max); + $traffic = $min if ($traffic < $min); + my $intensity = log($traffic / $min) / log(2); + my $clr = get_color($intensity); + + $ref->{'placement'} =~ /\((\d+),(\d+)\),\((\d+),(\d+)\)/; + $img->filledRectangle($3,$4,$1,$2,$clr); + $img->rectangle($3,$4,$1,$2,$blk); + + my ($x2, $y2, $x1, $y1) = ($1, $2, $3, $4); + my $max_textlen = ($x2-$x1) > ($y2-$y1) ? $x2-$x1 : $y2-$y1; + while (length($sysname) * 6 > $max_textlen) { + # Try to abbreviate sysname if it is too long for the box + $sysname =~ s/^(.*)[a-z]~?([0-9]+)$/$1~$2/ or last; + } + if (($x2-$x1) > ($y2-$y1)) { + $img->string(gdSmallFont,$x1+2,$y1,$sysname,$blk); + } else { + $img->stringUp(gdSmallFont,$x1,$y2-3,$sysname,$blk); + } +} +$dbh->disconnect; + +if (!defined($ARGV[0])) { + print $cgi->header(-type=>'image/png', + -refresh=>'10; ' . CGI::url()); +} +print $img->png; + +sub get_color { + my $intensity = shift; + my $gamma = 1.0/1.90; + if ($intensity > 1.0) { + $intensity -= 1.0; + return $img->colorResolve(255.0, 255.0 * ($intensity ** $gamma), 255.0 * ($intensity ** $gamma)); + } else { + return $img->colorResolve(255.0 * ($intensity ** $gamma), 255.0 * (1.0 - ($intensity ** $gamma)), 0); + } +} |