]> git.sesse.net Git - nms/commitdiff
initial import
authorSteinar H. Gunderson <sesse@samfundet.no>
Wed, 29 Mar 2006 12:22:57 +0000 (12:22 +0000)
committerSteinar H. Gunderson <sesse@samfundet.no>
Wed, 29 Mar 2006 12:22:57 +0000 (12:22 +0000)
(automatically generated log message)

29 files changed:
clients/dhcptail.pl [new file with mode: 0755]
clients/makeplace.pl [new file with mode: 0644]
clients/smanagrun.pl [new file with mode: 0755]
clients/snmp.sql [new file with mode: 0644]
clients/snmpfetch.pl [new file with mode: 0755]
clients/switchfix.pl [new file with mode: 0755]
clients/switchport.pl [new file with mode: 0755]
web/dhcpkart.pl [new file with mode: 0755]
web/index.html [new file with mode: 0644]
web/make-switches.pl [new file with mode: 0644]
web/mygraph.pl [new file with mode: 0755]
web/nettkart-telnet.pl [new file with mode: 0755]
web/nettkart-text.pl [new file with mode: 0755]
web/nettkart-web.pl [new file with mode: 0755]
web/nettkart.pl [new file with mode: 0755]
web/nms.sql [new file with mode: 0644]
web/overlay.pl [new file with mode: 0755]
web/portkart.pl [new file with mode: 0755]
web/sendsms.pl [new file with mode: 0755]
web/showswitch.pl [new file with mode: 0755]
web/smanagement.pl [new file with mode: 0755]
web/snmp-bg.png [new file with mode: 0644]
web/ssendfile.pl [new file with mode: 0755]
web/sshow.pl [new file with mode: 0755]
web/stemp-bg5.png [new file with mode: 0644]
web/stempmap-ptn.pl [new file with mode: 0755]
web/stempmap.pl [new file with mode: 0755]
web/streaming.pl [new file with mode: 0755]
web/tempfetch.pl [new file with mode: 0644]

diff --git a/clients/dhcptail.pl b/clients/dhcptail.pl
new file mode 100755 (executable)
index 0000000..044c817
--- /dev/null
@@ -0,0 +1,40 @@
+#! /usr/bin/perl
+use DBI;
+use POSIX;
+use strict;
+use warnings;
+
+# WARNING: CHANGE THIS! :-P
+my $year = 2005;
+
+my %months = (
+       Jan => 1,
+       Feb => 2,
+       Mar => 3,
+       Apr => 4,
+       May => 5,
+       Jun => 6,
+       Jul => 7,
+       Aug => 8,
+       Sep => 9,
+       Oct => 10,
+       Nov => 11,
+       Dec => 12
+);
+
+my ($dbh, $q);
+while (<>) {
+       /(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s+(\d+)\s+(\d+:\d+:\d+).*DHCPACK on (\d+\.\d+\.\d+\.\d+)/ or next;
+       my $date = $year . "-" . $months{$1} . "-" . $2 . " " . $3;
+
+       if (!defined($dbh) || !$dbh->ping) {
+               $dbh = DBI->connect("dbi:Pg:dbname=snmpfetch;host=violet.tg05.gathering.org", "snmpfetch", "removed")
+                       or die "Couldn't connect to database";
+               $q = $dbh->prepare("UPDATE dhcp SET last_ack=? WHERE inet ? << network AND ( last_ack < ? OR last_ack IS NULL )")
+                       or die "Couldn't prepare query";
+       }
+
+       print STDERR "$date $4\n";
+       $q->execute($date, $4, $date)
+               or die "Couldn't push $1 into database";
+}
diff --git a/clients/makeplace.pl b/clients/makeplace.pl
new file mode 100644 (file)
index 0000000..5c20d09
--- /dev/null
@@ -0,0 +1,25 @@
+#! /usr/bin/perl
+
+my $x = 308;
+my $y = 385;
+my $done = 0;
+
+while (<>) {
+       chomp (my $switch = $_);
+       print "DELETE FROM placements WHERE switch=$switch;\n";
+       printf "INSERT INTO placements VALUES ( $switch, '(%u,%u,%u,%u)');\n",
+               $x, $y, $x + 14, $y + 51;
+       $y += 51;
+       if ($y > 500) {
+               $y = 385;
+               $x += 18;
+               if ($x > 410 && $done == 0) {
+                       $x += 13;
+                       $done = 1;
+               }
+               if ($x > 570 && $done == 1) {
+                       $x += 12;
+                       $done = 2;
+               }
+       }
+}
diff --git a/clients/smanagrun.pl b/clients/smanagrun.pl
new file mode 100755 (executable)
index 0000000..e66cfd2
--- /dev/null
@@ -0,0 +1,149 @@
+#!/usr/bin/perl
+#
+#
+
+use warnings;
+use strict;
+use Net::Telnet;
+use DBI;
+use POSIX;
+
+# Tweak and check
+my $password = 'removed';
+my $timeout = 15;
+my $delaytime = 30;
+my $poll_frequency = 60;
+
+my $dbh = DBI->connect("dbi:Pg:dbname=snmpfetch;host=violet.tg05.gathering.org",
+                       "snmpfetch", "removed")
+       or die "Couldn't connect to database";
+$dbh->{AutoCommit} = 0;
+
+my $spoll = $dbh->prepare("
+SELECT
+  addr,
+  sysname
+FROM
+  squeue
+WHERE
+  processed = 'f' AND
+  disabled = 'f' AND
+  (locked='f' OR now() - updated > '3 minutes'::interval) AND
+  (delay IS NULL OR delay - now() < 0)
+ORDER BY
+  priority DESC,
+  added
+LIMIT 1");
+my $sgetallpoll = $dbh->prepare("
+SELECT
+  id,
+  gid,
+  addr,
+  sysname,
+  cmd
+FROM
+  squeue
+WHERE
+  sysname = ? AND
+  disabled = 'f' AND
+  processed = 'f'
+ORDER BY
+  priority DESC,
+  added");
+
+my $slock = $dbh->prepare("UPDATE squeue SET locked = 't', updated=now() WHERE sysname = ?")
+       or die "Unable to prepare slock";
+my $sunlock = $dbh->prepare("UPDATE squeue SET locked = 'f', updated=now() WHERE sysname = ?")
+       or die "Unable to prepare sunlock";
+my $sresult = $dbh->prepare("UPDATE squeue SET updated = now(), result = ?,
+                            processed = 't' WHERE id = ?")
+       or die "Unable to prepare sresult";
+my $sdelay = $dbh->prepare("UPDATE squeue SET delay = now() + delaytime, updated=now(), result = ? WHERE sysname = ?")
+       or die "Unable to prepae sdelay";
+
+# Send a command to switch and return the data recvied from the switch
+sub switch_exec($$) {
+       my ($cmd, $conn) = @_;
+
+       # Send the command and get data from switch
+       my @data = $conn->cmd($cmd);
+       my @lines = ();
+       foreach my $line (@data) {
+               # Remove escape-7 sequence
+               $line =~ s/\x1b\x37//g;
+               push (@lines, $line);
+       }
+
+       return @data;
+}
+
+sub switch_connect($) {
+       my ($ip) = @_;
+
+       my $conn = new Net::Telnet(     Timeout => $timeout,
+                                       Dump_Log => '/tmp/dumplog-queue',
+                                       Errmode => 'return',
+                                       Prompt => '/es(\-)?3024|e\d+\-\dsw>/i');
+       my $ret = $conn->open(  Host => $ip);
+       if (!$ret || $ret != 1) {
+               return (undef);
+       }
+       # XXX: Just send the password as text, I did not figure out how to
+       # handle authentication with only password through $conn->login().
+       #$conn->login(»·Prompt => '/password[: ]*$/i',
+       #               Name => $password,
+       #               Password => $password);
+       $conn->cmd($password);
+       # Get rid of banner
+       $conn->get;
+       return ($conn);
+}
+
+sub mylog {
+       my $msg = shift;
+       my $time = POSIX::ctime(time);
+       $time =~ s/\n.*$//;
+       printf STDERR "[%s] %s\n", $time, $msg;
+}
+
+while (1) {
+       $spoll->execute() or die "Could not execute spoll";
+       my $switch = $spoll->fetchrow_hashref();
+       if (!defined($switch)) {
+               $dbh->commit;
+               mylog("No available switches in pool, sleeping.");
+               sleep 60;
+               next;
+       }
+       $slock->execute($switch->{sysname});
+       $dbh->commit();
+
+       if ($switch->{'locked'}) {
+               mylog("WARNING: Lock timed out on $switch->{'ip'}, breaking lock");
+       }
+
+       my $conn = switch_connect($switch->{addr});
+       if (!defined($conn)) {
+               mylog("Could not connect to ".$switch->{sysname})."(".$switch->{addr}.")";
+               $sdelay->execute("Could not connect to switch, delaying...", $switch->{sysname});
+               $sunlock->execute($switch->{sysname});
+               $dbh->commit();
+               next;
+       }
+       my $error;
+       $error = $sgetallpoll->execute($switch->{sysname});
+       if (!$error) {
+               print "Could not execute sgetallpoll\n".$dbh->errstr();
+               $conn->close;
+               next;
+       }
+       while (my $row = $sgetallpoll->fetchrow_hashref()) {
+               print "sysname: ".$row->{sysname}." cmd: ".$row->{cmd}."\n";
+               my @data = switch_exec($row->{cmd}, $conn);
+               my $result = join("\n", @data);
+               $sresult->execute($result, $row->{id});
+       }
+       $conn->close();
+       $sunlock->execute($switch->{sysname});
+}
+
diff --git a/clients/snmp.sql b/clients/snmp.sql
new file mode 100644 (file)
index 0000000..47b4458
--- /dev/null
@@ -0,0 +1,24 @@
+create table switchtypes (
+       switchtype varchar not null primary key,
+       ports varchar not null
+);
+
+create table switches (
+       switch serial not null primary key,
+       ip inet not null,
+       sysname varchar not null,
+       switchtype varchar not null references switchtypes,
+       last_updated timestamp,
+       locked boolean not null default 'f'
+);
+
+create table poll (
+       time timestamp not null,
+       switch integer not null references switches,
+       port integer not null,
+       bytes_in bigint not null,
+       bytes_out bigint not null,
+
+       primary key ( time, switch, port )
+);
+create index poll_switch_port on poll ( switch, port );
diff --git a/clients/snmpfetch.pl b/clients/snmpfetch.pl
new file mode 100755 (executable)
index 0000000..fa50f60
--- /dev/null
@@ -0,0 +1,275 @@
+#! /usr/bin/perl
+use BER;
+use DBI;
+use POSIX;
+use Time::HiRes;
+use Net::Telnet;
+use strict;
+use warnings;
+require 'SNMP_Session.pm';
+
+my $password = 'removed';
+my $timeout = 15;
+
+my $dbh = DBI->connect("dbi:Pg:dbname=nms;host=localhost", "nms", "nms")
+       or die "Couldn't connect to database";
+$dbh->{AutoCommit} = 0;
+
+# normal mode: fetch switches from the database
+# instant mode: poll the switches specified on the command line
+my $instant = (defined($ARGV[0]));
+my $qualification;
+if ($instant) {
+       $qualification = "sysname=?";
+} else {
+       $qualification = <<"EOF";
+  (last_updated IS NULL OR now() - last_updated > poll_frequency)
+  AND (locked='f' OR now() - last_updated > '15 minutes'::interval)
+EOF
+}
+
+my $qswitch = $dbh->prepare(<<"EOF")
+SELECT 
+  *,
+  DATE_TRUNC('second', now() - last_updated - poll_frequency) AS overdue
+FROM
+  switches
+  NATURAL LEFT JOIN switchtypes
+WHERE $qualification
+ORDER BY
+  priority DESC,
+  overdue DESC
+LIMIT 1
+FOR UPDATE OF switches
+EOF
+       or die "Couldn't prepare qswitch";
+my $qlock = $dbh->prepare("UPDATE switches SET locked='t', last_updated=now() WHERE switch=?")
+       or die "Couldn't prepare qlock";
+my $qunlock = $dbh->prepare("UPDATE switches SET locked='f', last_updated=now() WHERE switch=?")
+       or die "Couldn't prepare qunlock";
+my $qpoll = $dbh->prepare("INSERT INTO polls (time, switch, port, bytes_in, bytes_out) VALUES (timeofday()::timestamp,?,?,?,?)")
+       or die "Couldn't prepare qpoll";
+my $qtemppoll = $dbh->prepare("INSERT INTO temppoll (time, switch, temp) VALUES (timeofday()::timestamp,?::text::int,?::text::float)")
+        or die "Couldn't prepare qtemppoll";
+my $qcpupoll = $dbh->prepare("INSERT INTO cpuloadpoll (time, switch, entity, value) VALUES (timeofday()::timestamp,?::text::int,?,?)")
+        or die "Couldn't prepare qtemppoll";
+
+while (1) {
+       my $sysname;
+       if ($instant) {
+               $sysname = shift @ARGV;
+               exit if (!defined($sysname));
+               $qswitch->execute($sysname)
+                       or die "Couldn't get switch";
+       } else {
+               # Find a switch to grab
+               $qswitch->execute()
+                       or die "Couldn't get switch";
+       }
+       my $switch = $qswitch->fetchrow_hashref();
+
+       if (!defined($switch)) {
+               $dbh->commit;
+
+               if ($instant) {
+                       mylog("No such switch $sysname available, quitting.");
+                       exit;
+               } else {        
+                       mylog("No available switches in pool, sleeping.");
+                       sleep 60;
+                       next;
+               }
+       }
+
+       $qlock->execute($switch->{'switch'})
+               or die "Couldn't lock switch";
+       $dbh->commit;
+
+       if ($switch->{'locked'}) {
+               mylog("WARNING: Lock timed out on $switch->{'ip'}, breaking lock");
+       }
+
+       my $msg;
+       if (defined($switch->{'overdue'})) {
+               $msg = sprintf "Polling ports %s on %s (%s), %s overdue.",
+                       $switch->{'ports'}, $switch->{'ip'}, $switch->{'sysname'}, $switch->{'overdue'};
+       } else {
+               $msg = sprintf "Polling ports %s on %s (%s), never polled before.",
+                       $switch->{'ports'}, $switch->{'ip'}, $switch->{'sysname'};
+       }
+       mylog($msg);
+
+       my $ip = $switch->{'ip'};
+
+       if ($ip eq '127.0.0.1') {
+               mylog("Polling disabled for this switch, skipping.");
+               $qunlock->execute($switch->{'switch'})
+                       or die "Couldn't unlock switch";
+               $dbh->commit;
+               next;
+       }
+
+       my $community = $switch->{'community'};
+       my $start = [Time::HiRes::gettimeofday];
+       eval {
+               my $session;
+               if ($switch->{'wide_counters'}) {
+                       $session = SNMPv2c_Session->open($ip, $community, 161)
+                               or die "Couldn't talk to switch";
+               } else {
+                       $session = SNMP_Session->open($ip, $community, 161)
+                               or die "Couldn't talk to switch";
+               }
+               my @ports = expand_ports($switch->{'ports'});
+
+               for my $port (@ports) {
+                       my $in = fetch_data($session, $port, 0, $switch->{'wide_counters'});
+                       my $out = fetch_data($session, $port, 1, $switch->{'wide_counters'});
+
+                       $qpoll->execute($switch->{'switch'}, $port, $in, $out);
+               }
+                my $conn = switch_connect($ip);
+                if (!defined($conn)) {
+                        print "Could not connect to switch ".$switch->{'switch'}."\n";
+                } elsif ($switch->{'switchtype'} eq 'es3024') { 
+                       my @data = switch_exec('sys monitor status', $conn);
+                       my @fields = split(/\s+/, $data[2]);
+                       # The temp fields are 6, 7, 8
+                       print "$fields[7] + $fields[8] + $fields[9]\n";
+                       my $avgtemp = ($fields[7] + $fields[8] + $fields[9]) / 3;
+                       print $avgtemp." avgtemp\n";
+                       $qtemppoll->execute($switch->{'switch'},
+                                       $avgtemp) or die "Could not exec qtemppoll";
+                } elsif ($switch->{'switchtype'} eq 'cisco6509') {
+                       for my $i (1..5) {
+                               # find the ID
+                               my $oid = BER::encode_oid(1, 3, 6, 1, 4, 1, 9, 9, 109, 1, 1, 1, 1, 2, $i);
+                               my $entity = fetch_snmp($session, $oid);
+
+                               next if (!defined($entity));
+                       
+                               # last-minute load for the given entity
+                               $oid = BER::encode_oid(1, 3, 6, 1, 4, 1, 9, 9, 109, 1, 1, 1, 1, 4, $i);
+                               my $value = fetch_snmp($session, $oid);
+                               
+                               $qcpupoll->execute($switch->{'switch'}, $entity, $value)
+                                       or die "Could not exec qcpupoll";
+                       }
+               }
+               $session->close;
+       };
+       if ($@) {
+               mylog("ERROR: $@ (during poll of $ip)");
+               $dbh->rollback;
+       }
+       
+       my $elapsed = Time::HiRes::tv_interval($start);
+       $msg = sprintf "Polled $switch->{'ip'} in %5.3f seconds.", $elapsed;            
+       mylog($msg);
+
+       $qunlock->execute($switch->{'switch'})
+               or die "Couldn't unlock switch";
+       $dbh->commit;
+}
+
+sub fetch_data {
+       my ($session, $port, $out, $wide_counters) = @_;
+       
+       my $oid;
+       if ($wide_counters) {
+               if ($out) {
+                       $oid = BER::encode_oid(1, 3, 6, 1, 2, 1, 31, 1, 1, 1, 10, $port);  # interfaces.ifTable.ifEntry.ifHCOutOctets
+               } else {
+                       $oid = BER::encode_oid(1, 3, 6, 1, 2, 1, 31, 1, 1, 1, 6, $port);  # interfaces.ifTable.ifEntry.ifHCInOctets
+               }
+       } else {
+               if ($out) {
+                       $oid = BER::encode_oid(1, 3, 6, 1, 2, 1, 2, 2, 1, 16, $port);  # interfaces.ifTable.ifEntry.ifOutOctets
+               } else {
+                       $oid = BER::encode_oid(1, 3, 6, 1, 2, 1, 2, 2, 1, 10, $port);  # interfaces.ifTable.ifEntry.ifInOctets
+               }
+       }
+
+       return fetch_snmp($session, $oid);
+}
+       
+sub fetch_snmp {
+       my ($session, $oid) = @_;
+
+       if ($session->get_request_response($oid)) {
+               my ($bindings) = $session->decode_get_response ($session->{pdu_buffer});
+               my $binding;
+               while ($bindings ne '') {
+                       ($binding,$bindings) = &decode_sequence ($bindings);
+                       my ($oid,$value) = &decode_by_template ($binding, "%O%@");
+                       return BER::pretty_print($value);
+               }
+       }
+       die "Couldn't get info from switch";
+}
+
+sub expand_ports {
+       my $in = shift;
+       my @ranges = split /,/, $in;
+       my @ret = ();
+
+       for my $range (@ranges) {
+               if ($range =~ /^\d+$/) {
+                       push @ret, $range;
+               } elsif ($range =~ /^(\d+)-(\d+)$/) {
+                       for my $i ($1..$2) {
+                               push @ret, $i;
+                       }
+               } else {
+                       die "Couldn't understand '$range' in ports";
+               }
+       }
+
+       return (sort { $a <=> $b } @ret); 
+}
+
+sub mylog {
+       my $msg = shift;
+       my $time = POSIX::ctime(time);
+       $time =~ s/\n.*$//;
+       printf STDERR "[%s] %s\n", $time, $msg;
+}
+
+sub switch_exec {
+       my ($cmd, $conn) = @_;
+
+       # Send the command and get data from switch
+#      $conn->dump_log(*STDOUT);
+       my @data = $conn->cmd($cmd);
+       my @lines = ();
+       foreach my $line (@data) {
+               # Remove escape-7 sequence
+               $line =~ s/\x1b\x37//g;
+               push @lines, $line;
+       }
+
+       return @lines;
+}
+
+sub switch_connect {
+       my ($ip) = @_;
+
+       my $conn = new Net::Telnet(     Timeout => $timeout,
+                                       Dump_Log => '/tmp/dumplog-tempfetch',
+                                       Errmode => 'return',
+                                       Prompt => '/es-3024|e(\-)?\d+\-\dsw>/i');
+       my $ret = $conn->open(  Host => $ip);
+       if (!$ret || $ret != 1) {
+               return (0);
+       }
+       # XXX: Just send the password as text, I did not figure out how to
+       # handle authentication with only password through $conn->login().
+       #$conn->login(  Prompt => '/password[: ]*$/i',
+       #              Name => $password,
+       #              Password => $password);
+       my @data = $conn->cmd($password);
+       # Get rid of banner
+       $conn->get;
+       return $conn;
+}
+
diff --git a/clients/switchfix.pl b/clients/switchfix.pl
new file mode 100755 (executable)
index 0000000..536e868
--- /dev/null
@@ -0,0 +1,98 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+use DBI;
+use Getopt::Long;
+use LWP::UserAgent;
+{
+       package RequestAgent;
+       our @ISA = qw(LWP::UserAgent);
+
+       sub new {
+               return LWP::UserAgent::new(@_);
+       }
+
+       sub get_basic_credentials {
+               return ("admin", "removed");
+       }
+}
+
+# CONFIG
+my $read = 0;
+my $write = 0;
+GetOptions ("read|r" => \$read, "write|w" => \$write);
+my $target_mask = $ARGV[0] ? $ARGV[0] : 'e%-%sw';
+
+
+# ACTION
+my $dbh = DBI->connect("dbi:Pg:dbname=snmpfetch;host=violet.tg05.gathering.org",
+                       "snmpfetch", "removed")
+        or die "Couldn't connect to database";
+
+my $sth = $dbh->prepare("SELECT sysname,ip FROM switches WHERE sysname LIKE ? ORDER BY ip");
+$sth->execute($target_mask);
+
+while (my ($sysname,$ip) = $sth->fetchrow_array) {
+       my ($gw, $mgmnt);
+
+       # Autodefine
+       if ($ip =~ /(\d+\.\d+\.\d*)(\d)\.\d+/) {
+               $gw = $1.$2.".1";
+               $mgmnt = "90$2";
+       } else {
+               print "$sysname\t($ip):\tAieeh! IP parsing fuckup!\n";
+               next;
+       }
+
+       # Define
+       my $url = "http://$ip/Forms/rpip_1";
+       my %shit = (
+                       "rpip_RpgDHCP" => "1",
+                       "rpip_IptIPAddr" => "$ip",
+                       "rpip_IptSubnetMask" => "255.255.255.0",
+                       "rpip_IptDefaultGateway" => "$gw",
+                       "rpip_IptDNS" => "0.0.0.0",
+                       "rpip_IptVID" => "$mgmnt",
+                       "rpip_HidBtnNum" => "1"
+                  );
+
+       # Check 
+       my $found = 0;
+       open(NMAP, "nmap -p80 $ip|");
+       while(<NMAP>) {
+               if(/^80\/tcp\s+open/) {
+                       $found = 1;
+               }
+       }
+       if(!$found) {
+               print "$sysname\t($ip):\tNo reply on port 80\n";
+               next;
+       }
+
+       # Read
+       if ($read) {
+               print "$sysname\t($ip):\t";
+               
+               my $ua = RequestAgent->new;
+               my $res = $ua->get("http://$ip/rpip.html");
+               if ($res->is_success) {
+                       foreach (split("\n", $res->content)) {
+                               if (/.*rpip_IptDefaultGateway" .* VALUE="([^"]+)">/) {
+                                       print "default route $1\n";
+                               }
+                       }
+               }  else {
+                       print $res->status_line, "\n";
+               }
+       }
+       
+       # Rape
+       if ($write) {
+               print "$sysname\t($ip):\t";
+               
+               my $ua = RequestAgent->new;
+               my $res = $ua->post($url, \%shit);
+               
+               print $res->status_line, "\n";
+       }
+}
diff --git a/clients/switchport.pl b/clients/switchport.pl
new file mode 100755 (executable)
index 0000000..3802509
--- /dev/null
@@ -0,0 +1,75 @@
+#!/usr/bin/perl
+#
+#
+
+use warnings;
+use strict;
+use Net::Telnet;
+
+# Tweak and check
+my $password = 'removed';
+my $timeout = 15;
+
+sub switch_exec($$) {
+       my ($cmd, $conn) = @_;
+
+       # Send the command and get data from switch
+       my @data = $conn->cmd($cmd);
+       my @lines = ();
+       foreach my $line (@data) {
+               # Remove escape-7 sequence
+               $line =~ s/\x1b\x37//g;
+               push (@lines, $line);
+       }
+
+       return @data;
+}
+
+sub switch_connect($) {
+       my ($ip) = @_;
+
+#                                      Errmode => 'return',
+       my $conn = new Net::Telnet(     Timeout => $timeout,
+                                       Dump_Log => 'dumplog',
+                                       Prompt => '/es(\-)?3024|e(\-)?\d+\-\dsw>/i');
+       my $ret = $conn->open(  Host => $ip);
+       if (!$ret || $ret != 1) {
+               return (undef);
+       }
+       # XXX: Just send the password as text, I did not figure out how to
+       # handle authentication with only password through $conn->login().
+       #$conn->login(»·Prompt => '/password[: ]*$/i',
+       #              Name => $password,
+       #              Password => $password);
+       $conn->cmd($password);
+       # Get rid of banner
+       $conn->get;
+       return ($conn);
+}
+
+sub switch_get_arp($) {
+       my ($conn) = @_;
+
+       my @data = switch_exec('ip arp status', $conn);
+       foreach (@data) {
+# 81.162.241.1    Ethernet       300   00:e0:2b:e0:f3:00 41   swif0 swp24
+               $_ =~ /(\d+\.\d+\.\d+\.\d+)\s+\w+\s+\d+\s+(\w\w:\w\w:\w\w:\w\w:\w\w:\w\w)\s+\d+\s+\w+\s+(\w+)/;
+               next if (!defined($1));
+               next if ($3 eq "NULL");
+               print "$1 $2 $3\n";     
+       }
+       return @data;
+}
+
+my $conn = switch_connect($ARGV[0]);
+if (!defined($conn)) {
+       die "something went wrong!";
+}
+my @data = switch_exec('sys monitor status', $conn);
+my @fields = split(/\s+/, $data[2]);
+# The temp fields are 6, 7, 8
+print "$fields[7] + $fields[8] + $fields[9]\n";
+my $avgtemp = ($fields[7] + $fields[8] + $fields[9]) / 3;
+print $avgtemp." avgtemp\n";
+$conn->close();
+
diff --git a/web/dhcpkart.pl b/web/dhcpkart.pl
new file mode 100755 (executable)
index 0000000..2558fb9
--- /dev/null
@@ -0,0 +1,80 @@
+#! /usr/bin/perl
+use CGI;
+use GD;
+use DBI;
+my $cgi = CGI->new;
+
+my $greentimeout = 900;
+my $maxtimeout = $greentimeout*9;
+
+my $dbh = DBI->connect("dbi:Pg:dbname=snmpfetch;host=violet.tg05.gathering.org", "snmpfetch", "removed")
+        or die "Couldn't connect to database";
+
+GD::Image->trueColor(1);
+$img = GD::Image->new('snmp-bg.png');
+
+my $blk = $img->colorResolve(0, 0, 0);
+
+$img->string(gdMediumBoldFont,0,0,"TG05 - DHCP-lease status",$blk);
+$img->string(gdSmallFont,0,20,"Last recieved 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');
+$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);
+       }
+       
+       $_ = $ref->{'sysname'};
+       if (!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);
+
+               $img->stringUp(gdSmallFont,$3,$2-3,$ref->{'sysname'},$blk);
+       }
+}
+$dbh->disconnect;
+
+if (!defined($ARGV[0])) {
+       print $cgi->header(-type=>'image/png',
+                          -refresh=>'10; http://nms.tg05.gathering.org/dhcpkart.pl');
+}
+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/index.html b/web/index.html
new file mode 100644 (file)
index 0000000..5036d8c
--- /dev/null
@@ -0,0 +1,62 @@
+<html>
+  <head>
+    <title>snmp</title>
+  </head>
+  <body>
+    <p>tg light &amp; 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 />
+
+      <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="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>
+    </ul>
+  </body>
+</html>
diff --git a/web/make-switches.pl b/web/make-switches.pl
new file mode 100644 (file)
index 0000000..a728ec2
--- /dev/null
@@ -0,0 +1,85 @@
+#! /usr/bin/perl
+
+print "delete from temppoll;\n";
+print "delete from placements;\n";
+print "delete from dhcp;\n";
+print "delete from switches;\n";
+print "SELECT pg_catalog.setval('switches_switch_seq', 1, false);\n";
+print "SELECT pg_catalog.setval('polls_poll_seq', 1, false);\n";
+
+my $cc = 241;
+my $dd = 0;
+
+my $i = 1;
+for $e (1..73) {
+       next if ($e % 2 == 0);
+
+       for $s (1..6) {
+               next if ($s <  4 && $e < 5);
+               next if ($s >= 4 && $e > 72);
+
+               next if ($e >= 69 && ($s == 1 || $s == 6));
+       
+               my $x = int(285 + $e * 9.45);
+               my $y;
+
+               $x += 7 if ($e >= 19);
+               $x += 14 if ($e >= 35);
+               $x += 9 if ($e >= 51);
+               $x += 9 if ($e >= 68 && $s < 4);
+               
+               my ($c, $d);
+               if ($s <= 3) {
+                       $c = $e;
+                       $d = ($s - 1) * 64;
+
+                       $y = 470 - $s * 48;
+               } else {
+                       $c = $e + 1;
+                       $d = ($s - 4) * 64;
+                       
+                       $y = 450 - $s * 48 - ($s - 3) * 2;
+               }
+
+               my $xx = $x + 12;
+               my $yy = $y + (($s > 3) ? 50 : 48);
+       
+               $dk = $dd + 7 + ($cc - 241) * 42;
+
+               # lasses magic-factor =)
+               $dk += 4;
+               if ($dk > 13) {
+                       $dk += 3;
+               }       
+
+               print "insert into switches (ip, sysname, switchtype) values ('81.162.$cc.$dk', 'e$e-${s}sw', 'es3024');\n";
+               print "insert into placements (switch, placement) values ($i, box '(($x,$y),($xx,$yy))');\n";
+               print "insert into dhcp (switch, network) values ($i, '81.162.$c.$d/26');\n";
+               $i++;
+
+               $dd++;
+               if ($dd == 42) {
+                       $cc++;
+                       $dd = 0;
+               }
+       }
+}
+
+my @k = qw(
+           81.162.212.0/24|81.162.212.1|game|es3024|((1100,200),(1125,225))
+           81.162.250.0/24|81.162.250.1|noc|es3024|((630,520),(680,550))
+           81.162.252.0/24|81.162.252.1|presse|es3024|((560,520),(610,550))
+           81.162.203.0/24|81.162.203.1|info-desk|es3024|((270,350),(305,385))
+           81.162.213.0/24|81.162.213.1|logistics|es3024|((800,75),(900,100))
+           81.162.213.0/24|81.162.213.1|logistics|es3024|((800,75),(900,100))
+           81.162.200.0/24|81.162.200.1|vision|es3024|((170,240),(200,270))
+           81.162.202.0/24|81.162.202.1|vision-sponsor|es3024|((220,150),(250,180))
+         );
+          
+for my $x (@k) {
+       my ($net,$mip,$sysname,$switchtype,$box) = split /\|/, $x;
+       print "insert into switches (ip, sysname, switchtype) values ('$mip', '$sysname', '$switchtype');\n";
+       print "insert into placements (switch, placement) values ($i, box '$box');\n";
+       print "insert into dhcp (switch, network) values ($i, '$net');\n";
+       $i++;
+}
diff --git a/web/mygraph.pl b/web/mygraph.pl
new file mode 100755 (executable)
index 0000000..9861264
--- /dev/null
@@ -0,0 +1,178 @@
+#! /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);
+       $graph->fill(0, 0, $white);
+
+       my $gray = $graph->colorAllocate(230, 230, 255);
+       my $black = $graph->colorAllocate(0, 0, 0);
+
+       $::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/nettkart-telnet.pl b/web/nettkart-telnet.pl
new file mode 100755 (executable)
index 0000000..fd32044
--- /dev/null
@@ -0,0 +1,49 @@
+#! /usr/bin/perl
+use CGI;
+use DBI;
+my $cgi = CGI->new;
+
+my $dbh = DBI->connect("dbi:Pg:dbname=snmpfetch;host=violet.tg05.gathering.org", "snmpfetch", "removed")
+        or die "Couldn't connect to database";
+print $cgi->header(-type=>'text/html', -refresh=>'45; http://nms.tg05.gathering.org/nettkart-telnet.pl');
+
+print <<"EOF";
+<html>
+  <head>
+    <title>nettkart - telnet</title>
+  </head>
+  <body>
+    <map name="switches">
+EOF
+
+my $q = $dbh->prepare('select * from switches natural join placements natural left join
+( select switch,sum(bytes_in)/count(*) as
+bytes_in,sum(bytes_out)/count(*) as bytes_out from get_datarate() group
+by switch ) t1');
+$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/nettkart-text.pl b/web/nettkart-text.pl
new file mode 100755 (executable)
index 0000000..6ac1d9f
--- /dev/null
@@ -0,0 +1,49 @@
+#! /usr/bin/perl
+use CGI;
+use DBI;
+my $cgi = CGI->new;
+
+my $dbh = DBI->connect("dbi:Pg:dbname=snmpfetch;host=violet.tg05.gathering.org", "snmpfetch", "removed")
+        or die "Couldn't connect to database";
+print $cgi->header(-type=>'text/html', -refresh=>'10; http://nms.tg05.gathering.org/nettkart-text.pl');
+
+print <<"EOF";
+<html>
+  <head>
+    <title>nettkart</title>
+  </head>
+  <body>
+    <map name="switches">
+EOF
+
+my $q = $dbh->prepare('select * from switches natural join placements natural left join
+( select switch,sum(bytes_in)/count(*) as
+bytes_in,sum(bytes_out)/count(*) as bytes_out from get_datarate() group
+by switch ) t1');
+$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/nettkart-web.pl b/web/nettkart-web.pl
new file mode 100755 (executable)
index 0000000..3da5fe5
--- /dev/null
@@ -0,0 +1,49 @@
+#! /usr/bin/perl
+use CGI;
+use DBI;
+my $cgi = CGI->new;
+
+my $dbh = DBI->connect("dbi:Pg:dbname=snmpfetch;host=violet.tg05.gathering.org", "snmpfetch", "removed")
+        or die "Couldn't connect to database";
+print $cgi->header(-type=>'text/html', -refresh=>'45; http://nms.tg05.gathering.org/nettkart-web.pl');
+
+print <<"EOF";
+<html>
+  <head>
+    <title>nettkart - web</title>
+  </head>
+  <body>
+    <map name="switches">
+EOF
+
+my $q = $dbh->prepare('select * from switches natural join placements natural left join
+( select switch,sum(bytes_in)/count(*) as
+bytes_in,sum(bytes_out)/count(*) as bytes_out from get_datarate() group
+by switch ) t1');
+$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/nettkart.pl b/web/nettkart.pl
new file mode 100755 (executable)
index 0000000..ac88162
--- /dev/null
@@ -0,0 +1,68 @@
+#! /usr/bin/perl
+use CGI;
+use GD;
+use DBI;
+my $cgi = CGI->new;
+
+my $dbh = DBI->connect("dbi:Pg:dbname=snmpfetch;host=violet.tg05.gathering.org", "snmpfetch", "removed")
+        or die "Couldn't connect to database";
+
+GD::Image->trueColor(1);
+$img = GD::Image->new('snmp-bg.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(32,$y,53,$y+1,$clr);
+}
+
+my $q = $dbh->prepare('select * from switches natural join placements natural left join
+( select switch,sum(bytes_in)/count(*) as
+bytes_in,sum(bytes_out)/count(*) as bytes_out from get_datarate() group
+by switch ) t1 where ip<>\'127.0.0.1\'');
+$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 = 20_000_000.0;   # 10mbit
+               my $min =    100_000.0;   # 100kbit
+               if ($traffic >= $min) {
+                       $intensity = 2.0 * (log($traffic / $min) / log(10)) / (log($max / $min) / log(10));
+                       $intensity = 2.0 if ($intensity > 2.0);
+               }       
+               $clr = get_color($intensity);
+       } else {
+               $clr = $img->colorResolve(0, 0, 255);
+       }
+       
+       $ref->{'placement'} =~ /\((\d+),(\d+)\),\((\d+),(\d+)\)/;
+       $img->filledRectangle($3,$4,$1,$2,$clr);
+       $img->rectangle($3,$4,$1,$2,$blk);
+        $img->stringUp(gdSmallFont,$3,$2-3,$ref->{'sysname'},$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 > 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.sql b/web/nms.sql
new file mode 100644 (file)
index 0000000..7974cd1
--- /dev/null
@@ -0,0 +1,1369 @@
+--
+-- NOTE: the PL/SQL in this file should probably not be trusted, it is rather
+--       wrong at places, especially when it comes to wraparound. -sesse
+--
+
+--
+-- Name: plpgsql_call_handler(); Type: FUNCTION; Schema: public; Owner: postgres
+--
+
+CREATE FUNCTION plpgsql_call_handler() RETURNS language_handler
+    AS '$libdir/plpgsql', 'plpgsql_call_handler'
+    LANGUAGE c;
+
+
+ALTER FUNCTION public.plpgsql_call_handler() OWNER TO postgres;
+
+--
+-- Name: plpgsql; Type: PROCEDURAL LANGUAGE; Schema: public; Owner: 
+--
+
+CREATE TRUSTED PROCEDURAL LANGUAGE plpgsql HANDLER plpgsql_call_handler;
+
+CREATE TABLE polls (
+    "time" timestamp with time zone NOT NULL,
+    switch integer NOT NULL,
+    port integer NOT NULL,
+    bytes_in bigint NOT NULL,
+    bytes_out bigint NOT NULL
+);
+ALTER TABLE ONLY polls ALTER COLUMN "time" SET STATISTICS 100;
+
+
+ALTER TABLE public.polls OWNER TO postgres;
+
+--
+-- Name: datarate; Type: TYPE; Schema: public; Owner: sesse
+--
+
+CREATE TYPE datarate AS (
+       switch integer,
+       port integer,
+       bytes_in double precision,
+       bytes_out double precision
+);
+
+
+ALTER TYPE public.datarate OWNER TO sesse;
+
+--
+-- Name: get_current_datarate(); Type: FUNCTION; Schema: public; Owner: nms
+--
+
+CREATE FUNCTION get_current_datarate() RETURNS SETOF datarate
+    AS $$
+DECLARE
+        num_entries INTEGER;
+        poll polls;
+        first_poll polls;
+        last_poll polls;
+        timediff float;
+        ret datarate;
+BEGIN
+        num_entries := 0;
+        last_poll.switch := -1;
+
+        FOR poll IN select * from polls where time >= now() - '15 minutes'::interval and time < now() order by switch,port,time LOOP
+                IF poll.switch <> last_poll.switch OR poll.port <> last_poll.port THEN
+                        IF num_entries >= 2 THEN
+                                timediff := EXTRACT(epoch from last_poll.time - first_poll.time);
+                                ret.switch := last_poll.switch;
+                                ret.port := last_poll.port;
+
+                                IF last_poll.bytes_in >= first_poll.bytes_in AND last_poll.bytes_out >= first_poll.bytes_out THEN
+                                        ret.bytes_in := (last_poll.bytes_in - first_poll.bytes_in) / timediff;
+                                        ret.bytes_out := (last_poll.bytes_out - first_poll.bytes_out) / timediff;
+                                        return next ret; 
+                                END IF;
+                        END IF;
+                        num_entries := 0;
+                ELSE
+                        -- reset if we have wraparound
+                        IF last_poll.bytes_in < first_poll.bytes_in OR
+                           last_poll.bytes_out < first_poll.bytes_out THEN
+                                num_entries := 0;
+                        END IF;
+                END IF;
+
+                num_entries := num_entries + 1;
+                IF num_entries = 1 THEN
+                        first_poll.switch := poll.switch;
+                        first_poll.port := poll.port;
+                        first_poll.time := poll.time;
+                        first_poll.bytes_in := poll.bytes_in;
+                        first_poll.bytes_out := poll.bytes_out;
+                END IF;
+
+                last_poll.switch := poll.switch;
+                last_poll.port := poll.port;
+                last_poll.time := poll.time;
+                last_poll.bytes_in := poll.bytes_in;
+                last_poll.bytes_out := poll.bytes_out;
+        END LOOP;
+
+        -- last
+        IF num_entries >= 2 THEN
+                timediff := EXTRACT(epoch from last_poll.time - first_poll.time);
+                ret.switch := last_poll.switch;
+                ret.port := last_poll.port;
+
+                IF last_poll.bytes_in >= first_poll.bytes_in AND
+                   last_poll.bytes_out >= first_poll.bytes_out THEN
+                        ret.bytes_in := (last_poll.bytes_in - first_poll.bytes_in) / timediff;
+                        ret.bytes_out := (last_poll.bytes_out - first_poll.bytes_out) / timediff;
+                        return next ret; 
+                END IF;
+        END IF;
+
+        RETURN;
+END;
+$$
+    LANGUAGE plpgsql;
+
+
+ALTER FUNCTION public.get_current_datarate() OWNER TO nms;
+
+--
+-- Name: get_datarate(); Type: FUNCTION; Schema: public; Owner: postgres
+--
+
+CREATE FUNCTION get_datarate() RETURNS SETOF datarate
+    AS $$
+DECLARE
+        num_entries INTEGER;
+        poll polls;
+        second_last_poll polls;
+        last_poll polls;
+        timediff float;
+        ret datarate;
+BEGIN
+        num_entries := 0;
+        last_poll.switch = -1;
+
+        FOR poll IN select * from polls where time >= now() - '15 minutes'::interval and time < now() order by switch,port,time LOOP
+                IF poll.switch <> last_poll.switch OR poll.port <> last_poll.port THEN
+                        IF num_entries >= 2 THEN
+                                timediff := EXTRACT(epoch from last_poll.time - second_last_poll.time);
+                                ret.switch := last_poll.switch;
+                                ret.port := last_poll.port;
+                                
+                                IF last_poll.bytes_in < second_last_poll.bytes_in THEN
+                                        second_last_poll.bytes_in = 0;
+                                END IF;
+                                IF last_poll.bytes_out < second_last_poll.bytes_out THEN
+                                        second_last_poll.bytes_out = 0;
+                                END IF;
+
+                                ret.bytes_in := (last_poll.bytes_in - second_last_poll.bytes_in) / timediff;
+                                ret.bytes_out := (last_poll.bytes_out - second_last_poll.bytes_out) / timediff;
+                                return next ret;
+                        ELSIF num_entries = 1 THEN
+                                ret.switch := last_poll.switch;
+                                ret.port := last_poll.port;
+                                ret.bytes_in := -1;
+                                ret.bytes_out := -1;
+                                return next ret;
+                        END IF;
+                        num_entries := 1;
+                ELSE
+                        num_entries := num_entries + 1;
+                END IF;
+                second_last_poll.switch := last_poll.switch;
+                second_last_poll.port := last_poll.port;
+                second_last_poll.time := last_poll.time;
+                second_last_poll.bytes_in := last_poll.bytes_in;
+                second_last_poll.bytes_out := last_poll.bytes_out;
+                last_poll.switch := poll.switch;
+                last_poll.port := poll.port;
+                last_poll.time := poll.time;
+                last_poll.bytes_in := poll.bytes_in;
+                last_poll.bytes_out := poll.bytes_out;
+        END LOOP;
+       -- pah, and once more, for the last switch/port...
+        IF num_entries >= 2 THEN
+                timediff := EXTRACT(epoch from last_poll.time - second_last_poll.time);
+                ret.switch := last_poll.switch;
+                ret.port := last_poll.port;
+                
+                IF last_poll.bytes_in < second_last_poll.bytes_in THEN
+                        second_last_poll.bytes_in = 0;
+                END IF;
+                IF last_poll.bytes_out < second_last_poll.bytes_out THEN
+                        second_last_poll.bytes_out = 0;
+                END IF;
+
+                ret.bytes_in := (last_poll.bytes_in - second_last_poll.bytes_in) / timediff;
+                ret.bytes_out := (last_poll.bytes_out - second_last_poll.bytes_out) / timediff;
+                return next ret;
+        ELSIF num_entries = 1 THEN
+                ret.switch := last_poll.switch;
+                ret.port := last_poll.port;
+                ret.bytes_in := -1;
+                ret.bytes_out := -1;
+                return next ret;
+        END IF;
+        
+        RETURN;
+END;
+$$
+    LANGUAGE plpgsql;
+
+
+ALTER FUNCTION public.get_datarate() OWNER TO postgres;
+
+SET default_tablespace = '';
+
+SET default_with_oids = false;
+
+--
+-- Name: dhcp; Type: TABLE; Schema: public; Owner: sesse; Tablespace: 
+--
+
+CREATE TABLE dhcp (
+    switch integer NOT NULL,
+    network cidr NOT NULL,
+    last_ack timestamp without time zone
+);
+
+
+ALTER TABLE public.dhcp OWNER TO sesse;
+
+--
+-- Name: placements; Type: TABLE; Schema: public; Owner: postgres; Tablespace: 
+--
+
+CREATE TABLE placements (
+    switch integer NOT NULL,
+    placement box NOT NULL
+);
+
+
+ALTER TABLE public.placements OWNER TO postgres;
+
+SET default_with_oids = true;
+
+--
+-- Name: polls; Type: TABLE; Schema: public; Owner: postgres; Tablespace: 
+--
+
+
+--
+-- Name: polls_poll_seq; Type: SEQUENCE; Schema: public; Owner: postgres
+--
+
+CREATE SEQUENCE polls_poll_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MAXVALUE
+    NO MINVALUE
+    CACHE 1;
+
+
+ALTER TABLE public.polls_poll_seq OWNER TO postgres;
+
+--
+-- Name: polls_poll_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres
+--
+
+SELECT pg_catalog.setval('polls_poll_seq', 1, false);
+
+
+--
+-- Name: portnames; Type: TABLE; Schema: public; Owner: postgres; Tablespace: 
+--
+
+CREATE TABLE portnames (
+    switchtype character varying NOT NULL,
+    port integer NOT NULL,
+    description character varying NOT NULL
+);
+
+
+ALTER TABLE public.portnames OWNER TO postgres;
+
+--
+-- Name: squeue; Type: TABLE; Schema: public; Owner: nms; Tablespace: 
+--
+
+CREATE TABLE squeue (
+    id integer DEFAULT nextval('squeue_sequence'::text) NOT NULL,
+    gid integer NOT NULL,
+    added timestamp with time zone NOT NULL,
+    updated timestamp with time zone,
+    addr inet,
+    cmd character varying NOT NULL,
+    locked boolean DEFAULT false NOT NULL,
+    processed boolean DEFAULT false NOT NULL,
+    disabled boolean DEFAULT false NOT NULL,
+    priority integer DEFAULT 3,
+    sysname character varying NOT NULL,
+    author character varying NOT NULL,
+    result character varying,
+    delay timestamp with time zone,
+    delaytime interval DEFAULT '00:01:00'::interval
+);
+
+
+ALTER TABLE public.squeue OWNER TO nms;
+
+--
+-- Name: squeue_group_sequence; Type: SEQUENCE; Schema: public; Owner: nms
+--
+
+CREATE SEQUENCE squeue_group_sequence
+    INCREMENT BY 1
+    NO MAXVALUE
+    NO MINVALUE
+    CACHE 1;
+
+
+ALTER TABLE public.squeue_group_sequence OWNER TO nms;
+
+--
+-- Name: squeue_group_sequence; Type: SEQUENCE SET; Schema: public; Owner: nms
+--
+
+SELECT pg_catalog.setval('squeue_group_sequence', 21, true);
+
+
+--
+-- Name: squeue_sequence; Type: SEQUENCE; Schema: public; Owner: nms
+--
+
+CREATE SEQUENCE squeue_sequence
+    INCREMENT BY 1
+    NO MAXVALUE
+    NO MINVALUE
+    CACHE 1;
+
+
+ALTER TABLE public.squeue_sequence OWNER TO nms;
+
+--
+-- Name: squeue_sequence; Type: SEQUENCE SET; Schema: public; Owner: nms
+--
+
+SELECT pg_catalog.setval('squeue_sequence', 901, true);
+
+
+--
+-- Name: stemppoll_sequence; Type: SEQUENCE; Schema: public; Owner: nms
+--
+
+CREATE SEQUENCE stemppoll_sequence
+    INCREMENT BY 1
+    NO MAXVALUE
+    NO MINVALUE
+    CACHE 1;
+
+
+ALTER TABLE public.stemppoll_sequence OWNER TO nms;
+
+--
+-- Name: stemppoll_sequence; Type: SEQUENCE SET; Schema: public; Owner: nms
+--
+
+SELECT pg_catalog.setval('stemppoll_sequence', 182534, true);
+
+
+SET default_with_oids = false;
+
+--
+-- Name: switches; Type: TABLE; Schema: public; Owner: postgres; Tablespace: 
+--
+
+CREATE TABLE switches (
+    switch integer DEFAULT nextval('"switches_switch_seq"'::text) NOT NULL,
+    ip inet NOT NULL,
+    sysname character varying NOT NULL,
+    switchtype character varying NOT NULL,
+    last_updated timestamp with time zone,
+    locked boolean DEFAULT false NOT NULL,
+    priority integer DEFAULT 0 NOT NULL,
+    poll_frequency interval DEFAULT '00:05:00'::interval NOT NULL,
+    community character varying DEFAULT 'public'::character varying NOT NULL
+);
+
+
+ALTER TABLE public.switches OWNER TO postgres;
+
+--
+-- Name: switches_switch_seq; Type: SEQUENCE; Schema: public; Owner: postgres
+--
+
+CREATE SEQUENCE switches_switch_seq
+    INCREMENT BY 1
+    NO MAXVALUE
+    NO MINVALUE
+    CACHE 1;
+
+
+ALTER TABLE public.switches_switch_seq OWNER TO postgres;
+
+--
+-- Name: switches_switch_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres
+--
+
+SELECT pg_catalog.setval('switches_switch_seq', 225, true);
+
+
+--
+-- Name: switchtypes; Type: TABLE; Schema: public; Owner: postgres; Tablespace: 
+--
+
+CREATE TABLE switchtypes (
+    switchtype character varying NOT NULL,
+    ports character varying NOT NULL
+);
+
+
+ALTER TABLE public.switchtypes OWNER TO postgres;
+
+SET default_with_oids = true;
+
+--
+-- Name: temppoll; Type: TABLE; Schema: public; Owner: postgres; Tablespace: 
+--
+
+CREATE TABLE temppoll (
+    id integer DEFAULT nextval('stemppoll_sequence'::text) NOT NULL,
+    "time" timestamp without time zone NOT NULL,
+    switch integer NOT NULL,
+    "temp" double precision
+);
+
+
+ALTER TABLE public.temppoll OWNER TO postgres;
+
+--
+-- Data for Name: dhcp; Type: TABLE DATA; Schema: public; Owner: sesse
+--
+
+COPY dhcp (switch, network, last_ack) FROM stdin;
+151    81.162.53.0/26  2005-03-27 11:53:29
+41     81.162.16.64/26 2005-03-27 11:53:35
+164    81.162.57.64/26 2005-03-27 11:53:39
+20     81.162.9.64/26  2005-03-27 11:54:27
+4      81.162.4.0/26   2005-03-27 11:55:33
+44     81.162.17.64/26 2005-03-27 11:56:37
+194    81.162.67.64/26 2005-03-27 11:56:38
+139    81.162.49.0/26  2005-03-27 11:57:08
+46     81.162.18.0/26  2005-03-27 11:57:27
+193    81.162.67.0/26  2005-03-27 11:57:36
+27     81.162.11.128/26        2005-03-27 11:58:07
+107    81.162.38.64/26 2005-03-27 11:58:31
+133    81.162.47.0/26  2005-03-27 11:58:52
+99     81.162.35.128/26        2005-03-27 11:59:09
+79     81.162.29.0/26  2005-03-27 11:59:18
+34     81.162.14.0/26  2005-03-27 11:59:28
+51     81.162.19.128/26        2005-03-27 11:59:34
+160    81.162.56.0/26  2005-03-27 12:00:01
+196    81.162.68.0/26  2005-03-27 12:00:11
+184    81.162.64.0/26  2005-03-27 12:01:48
+9      81.162.5.128/26 2005-03-27 12:01:54
+195    81.162.67.128/26        2005-03-27 12:02:18
+123    81.162.43.128/26        2005-03-27 12:02:46
+192    81.162.66.128/26        2005-03-27 12:03:09
+212    81.162.203.0/24 2005-03-27 12:04:12
+5      81.162.4.64/26  2005-03-27 12:04:14
+113    81.162.40.64/26 2005-03-27 12:05:01
+191    81.162.66.64/26 2005-03-27 12:05:01
+119    81.162.42.64/26 2005-03-27 12:06:01
+3      81.162.2.128/26 2005-03-27 12:06:03
+74     81.162.27.64/26 2005-03-27 12:06:12
+201    81.162.70.0/26  2005-03-27 12:06:25
+86     81.162.31.64/26 2005-03-27 12:07:56
+50     81.162.19.64/26 2005-03-27 12:08:36
+59     81.162.22.64/26 2005-03-27 12:08:59
+43     81.162.17.0/26  2005-03-27 12:09:02
+80     81.162.29.64/26 2005-03-27 12:09:14
+106    81.162.38.0/26  2005-03-27 12:09:15
+52     81.162.20.0/26  2005-03-27 12:09:22
+205    81.162.72.0/26  2005-03-27 12:10:08
+82     81.162.30.0/26  2005-03-27 12:10:10
+128    81.162.45.64/26 2005-03-27 12:10:38
+112    81.162.40.0/26  2005-03-27 12:11:16
+202    81.162.70.64/26 2005-03-27 12:12:30
+6      81.162.4.128/26 2005-03-27 12:12:49
+95     81.162.34.64/26 2005-03-27 12:13:02
+178    81.162.62.0/26  2005-03-27 12:13:10
+145    81.162.51.0/26  2005-03-27 12:13:15
+84     81.162.30.128/26        2005-03-27 12:13:34
+28     81.162.12.0/26  2005-03-27 12:13:58
+22     81.162.10.0/26  2005-03-27 12:14:40
+122    81.162.43.64/26 2005-03-27 12:14:57
+85     81.162.31.0/26  2005-03-27 12:15:21
+18     81.162.8.128/26 2005-03-27 12:15:24
+105    81.162.37.128/26        2005-03-27 12:15:24
+81     81.162.29.128/26        2005-03-27 12:15:36
+77     81.162.28.64/26 2005-03-27 12:15:47
+146    81.162.51.64/26 2005-03-27 12:17:09
+24     81.162.10.128/26        2005-03-27 12:17:10
+190    81.162.66.0/26  2005-03-27 12:17:10
+33     81.162.13.128/26        2005-03-27 12:17:17
+150    81.162.52.128/26        2005-03-27 12:17:27
+57     81.162.21.128/26        2005-03-27 12:17:37
+17     81.162.8.64/26  2005-03-27 12:17:39
+54     81.162.20.128/26        2005-03-27 12:18:24
+94     81.162.34.0/26  2005-03-27 12:18:24
+69     81.162.25.128/26        2005-03-27 12:18:26
+141    81.162.49.128/26        2005-03-27 12:18:43
+154    81.162.54.0/26  2005-03-27 12:19:25
+177    81.162.61.128/26        2005-03-27 12:20:17
+29     81.162.12.64/26 2005-03-27 12:20:37
+91     81.162.33.0/26  2005-03-27 12:20:53
+83     81.162.30.64/26 2005-03-27 12:20:57
+47     81.162.18.64/26 2005-03-27 12:21:10
+170    81.162.59.64/26 2005-03-27 12:22:01
+78     81.162.28.128/26        2005-03-27 12:22:26
+155    81.162.54.64/26 2005-03-27 12:23:11
+35     81.162.14.64/26 2005-03-27 12:23:12
+32     81.162.13.64/26 2005-03-27 12:23:55
+199    81.162.69.64/26 2005-03-27 12:24:13
+63     81.162.23.128/26        2005-03-27 12:24:33
+90     81.162.32.128/26        2005-03-27 12:25:31
+114    81.162.40.128/26        2005-03-27 12:26:04
+75     81.162.27.128/26        2005-03-27 12:26:06
+42     81.162.16.128/26        2005-03-27 12:26:26
+87     81.162.31.128/26        2005-03-27 12:26:42
+67     81.162.25.0/26  2005-03-27 12:27:31
+204    81.162.71.128/26        2005-03-27 12:34:04
+200    81.162.69.128/26        2005-03-27 12:37:19
+207    81.162.73.64/26 2005-03-27 12:41:57
+203    81.162.71.64/26 2005-03-27 12:58:48
+214    81.162.213.0/24 2005-03-27 13:02:26
+213    81.162.213.0/24 2005-03-27 13:02:26
+209    81.162.212.0/24 2005-03-27 13:16:02
+215    81.162.200.0/24 2005-03-27 13:16:14
+210    81.162.250.0/24 2005-03-27 13:18:02
+211    81.162.252.0/24 2005-03-27 12:39:02
+129    81.162.45.128/26        2005-03-27 10:44:11
+110    81.162.39.64/26 2005-03-27 08:19:17
+10     81.162.6.0/26   2005-03-27 08:35:15
+171    81.162.59.128/26        2005-03-27 08:42:52
+167    81.162.58.64/26 2005-03-27 09:07:47
+180    81.162.62.128/26        2005-03-27 09:22:15
+140    81.162.49.64/26 2005-03-27 09:41:51
+103    81.162.37.0/26  2005-03-27 09:42:30
+55     81.162.21.0/26  2005-03-27 09:42:54
+137    81.162.48.64/26 2005-03-27 09:47:06
+62     81.162.23.64/26 2005-03-27 09:51:30
+158    81.162.55.64/26 2005-03-27 09:51:55
+70     81.162.26.0/26  2005-03-27 09:52:09
+159    81.162.55.128/26        2005-03-27 10:05:56
+165    81.162.57.128/26        2005-03-27 10:09:30
+125    81.162.44.64/26 2005-03-27 10:10:14
+169    81.162.59.0/26  2005-03-27 10:10:29
+89     81.162.32.64/26 2005-03-27 10:11:14
+168    81.162.58.128/26        2005-03-27 10:11:42
+39     81.162.15.128/26        2005-03-27 10:11:49
+134    81.162.47.64/26 2005-03-27 10:12:00
+144    81.162.50.128/26        2005-03-27 10:15:46
+61     81.162.23.0/26  2005-03-27 10:19:36
+186    81.162.64.128/26        2005-03-27 10:24:08
+97     81.162.35.0/26  2005-03-27 10:26:13
+124    81.162.44.0/26  2005-03-27 10:28:37
+162    81.162.56.128/26        2005-03-27 10:36:33
+76     81.162.28.0/26  2005-03-27 10:38:20
+156    81.162.54.128/26        2005-03-27 10:41:07
+93     81.162.33.128/26        2005-03-27 10:42:16
+58     81.162.22.0/26  2005-03-27 10:42:50
+23     81.162.10.64/26 2005-03-27 10:43:27
+132    81.162.46.128/26        2005-03-27 10:46:35
+118    81.162.42.0/26  2005-03-27 10:47:16
+16     81.162.8.0/26   2005-03-27 10:47:53
+182    81.162.63.64/26 2005-03-27 10:47:58
+88     81.162.32.0/26  2005-03-27 10:49:28
+126    81.162.44.128/26        2005-03-27 10:50:02
+130    81.162.46.0/26  2005-03-27 10:50:46
+15     81.162.7.128/26 2005-03-27 10:54:20
+12     81.162.6.128/26 2005-03-27 10:54:40
+98     81.162.35.64/26 2005-03-27 10:55:15
+104    81.162.37.64/26 2005-03-27 10:57:11
+100    81.162.36.0/26  2005-03-27 10:58:55
+45     81.162.17.128/26        2005-03-27 11:02:32
+131    81.162.46.64/26 2005-03-27 11:04:23
+175    81.162.61.0/26  2005-03-27 11:04:47
+72     81.162.26.128/26        2005-03-27 11:04:50
+148    81.162.52.0/26  2005-03-27 11:05:19
+198    81.162.68.128/26        2005-03-27 11:06:42
+68     81.162.25.64/26 2005-03-27 11:06:55
+115    81.162.41.0/26  2005-03-27 11:08:58
+157    81.162.55.0/26  2005-03-27 11:10:30
+111    81.162.39.128/26        2005-03-27 11:11:10
+120    81.162.42.128/26        2005-03-27 10:14:01
+21     81.162.9.128/26 2005-03-27 10:39:11
+64     81.162.24.0/26  2005-03-27 11:14:54
+7      81.162.5.0/26   2005-03-27 11:15:07
+163    81.162.57.0/26  2005-03-27 11:18:50
+208    81.162.73.128/26        2005-03-27 11:18:53
+189    81.162.65.128/26        2005-03-27 11:20:12
+197    81.162.68.64/26 2005-03-27 11:20:46
+31     81.162.13.0/26  2005-03-27 11:22:31
+19     81.162.9.0/26   2005-03-27 11:22:48
+13     81.162.7.0/26   2005-03-27 11:24:35
+147    81.162.51.128/26        2005-03-27 11:27:37
+135    81.162.47.128/26        2005-03-27 11:28:43
+121    81.162.43.0/26  2005-03-27 11:28:58
+136    81.162.48.0/26  2005-03-27 11:31:04
+66     81.162.24.128/26        2005-03-27 11:32:10
+166    81.162.58.0/26  2005-03-27 09:25:55
+138    81.162.48.128/26        2005-03-27 10:08:33
+56     81.162.21.64/26 2005-03-27 11:32:34
+143    81.162.50.64/26 2005-03-27 11:33:03
+176    81.162.61.64/26 2005-03-27 11:33:36
+65     81.162.24.64/26 2005-03-27 11:33:40
+102    81.162.36.128/26        2005-03-27 11:34:00
+116    81.162.41.64/26 2005-03-27 11:34:56
+183    81.162.63.128/26        2005-03-27 11:36:02
+109    81.162.39.0/26  2005-03-27 11:36:45
+25     81.162.11.0/26  2005-03-27 11:37:44
+174    81.162.60.128/26        2005-03-27 11:38:11
+216    81.162.202.0/24 2005-03-27 11:39:03
+40     81.162.16.0/26  2005-03-27 11:39:31
+152    81.162.53.64/26 2005-03-27 11:39:47
+14     81.162.7.64/26  2005-03-27 11:39:59
+92     81.162.33.64/26 2005-03-27 11:40:05
+173    81.162.60.64/26 2005-03-27 11:40:28
+48     81.162.18.128/26        2005-03-27 11:40:28
+8      81.162.5.64/26  2005-03-27 11:40:45
+108    81.162.38.128/26        2005-03-27 11:42:43
+11     81.162.6.64/26  2005-03-27 08:50:50
+188    81.162.65.64/26 2005-03-27 08:55:21
+117    81.162.41.128/26        2005-03-27 09:23:35
+26     81.162.11.64/26 2005-03-27 11:43:18
+172    81.162.60.0/26  2005-03-27 11:43:21
+71     81.162.26.64/26 2005-03-27 11:43:51
+38     81.162.15.64/26 2005-03-27 11:44:11
+153    81.162.53.128/26        2005-03-27 11:45:51
+53     81.162.20.64/26 2005-03-27 11:46:24
+1      81.162.2.0/26   2005-03-27 11:47:03
+2      81.162.2.64/26  2005-03-27 11:47:10
+149    81.162.52.64/26 2005-03-27 11:48:35
+37     81.162.15.0/26  2005-03-27 11:49:04
+127    81.162.45.0/26  2005-03-27 11:49:22
+179    81.162.62.64/26 2005-03-27 11:49:48
+185    81.162.64.64/26 2005-03-27 11:50:36
+142    81.162.50.0/26  2005-03-27 11:51:18
+36     81.162.14.128/26        2005-03-27 11:51:19
+30     81.162.12.128/26        2005-03-27 11:51:20
+60     81.162.22.128/26        2005-03-27 11:52:08
+49     81.162.19.0/26  2005-03-27 10:22:15
+73     81.162.27.0/26  2005-03-27 11:27:55
+96     81.162.34.128/26        2005-03-27 11:32:26
+101    81.162.36.64/26 2005-03-27 11:40:47
+181    81.162.63.0/26  2005-03-27 11:52:55
+187    81.162.65.0/26  2005-03-27 11:53:23
+161    81.162.56.64/26 2005-03-27 08:54:44
+\.
+
+
+--
+-- Data for Name: placements; Type: TABLE DATA; Schema: public; Owner: postgres
+--
+
+COPY placements (switch, placement) FROM stdin;
+221    (375,325),(350,300)
+222    (550,325),(525,300)
+224    (775,325),(750,300)
+223    (875,325),(850,300)
+225    (675,325),(650,300)
+218    (980,550),(930,520)
+1      (306,306),(294,256)
+2      (306,256),(294,206)
+3      (306,206),(294,156)
+4      (325,306),(313,256)
+5      (325,256),(313,206)
+6      (325,206),(313,156)
+7      (344,470),(332,422)
+8      (344,422),(332,374)
+9      (344,374),(332,326)
+10     (344,306),(332,256)
+11     (344,256),(332,206)
+12     (344,206),(332,156)
+13     (363,470),(351,422)
+14     (363,422),(351,374)
+15     (363,374),(351,326)
+16     (363,306),(351,256)
+17     (363,256),(351,206)
+18     (363,206),(351,156)
+19     (382,470),(370,422)
+20     (382,422),(370,374)
+21     (382,374),(370,326)
+22     (382,306),(370,256)
+23     (382,256),(370,206)
+24     (382,206),(370,156)
+25     (400,470),(388,422)
+26     (400,422),(388,374)
+27     (400,374),(388,326)
+28     (400,306),(388,256)
+29     (400,256),(388,206)
+30     (400,206),(388,156)
+31     (419,470),(407,422)
+32     (419,422),(407,374)
+33     (419,374),(407,326)
+34     (419,306),(407,256)
+35     (419,256),(407,206)
+36     (419,206),(407,156)
+37     (438,470),(426,422)
+38     (438,422),(426,374)
+39     (438,374),(426,326)
+40     (438,306),(426,256)
+41     (438,256),(426,206)
+42     (438,206),(426,156)
+43     (457,470),(445,422)
+44     (457,422),(445,374)
+45     (457,374),(445,326)
+46     (457,306),(445,256)
+47     (457,256),(445,206)
+48     (457,206),(445,156)
+49     (483,470),(471,422)
+50     (483,422),(471,374)
+51     (483,374),(471,326)
+52     (483,306),(471,256)
+53     (483,256),(471,206)
+54     (483,206),(471,156)
+55     (502,470),(490,422)
+56     (502,422),(490,374)
+57     (502,374),(490,326)
+58     (502,306),(490,256)
+59     (502,256),(490,206)
+60     (502,206),(490,156)
+61     (521,470),(509,422)
+62     (521,422),(509,374)
+63     (521,374),(509,326)
+64     (521,306),(509,256)
+65     (521,256),(509,206)
+66     (521,206),(509,156)
+67     (540,470),(528,422)
+68     (540,422),(528,374)
+69     (540,374),(528,326)
+70     (540,306),(528,256)
+71     (540,256),(528,206)
+72     (540,206),(528,156)
+73     (559,470),(547,422)
+74     (559,422),(547,374)
+75     (559,374),(547,326)
+76     (559,306),(547,256)
+77     (559,256),(547,206)
+78     (559,206),(547,156)
+79     (578,470),(566,422)
+80     (578,422),(566,374)
+81     (578,374),(566,326)
+82     (578,306),(566,256)
+83     (578,256),(566,206)
+84     (578,206),(566,156)
+85     (596,470),(584,422)
+86     (596,422),(584,374)
+87     (596,374),(584,326)
+88     (596,306),(584,256)
+89     (596,256),(584,206)
+90     (596,206),(584,156)
+91     (615,470),(603,422)
+92     (615,422),(603,374)
+93     (615,374),(603,326)
+94     (615,306),(603,256)
+95     (615,256),(603,206)
+96     (615,206),(603,156)
+97     (648,470),(636,422)
+98     (648,422),(636,374)
+99     (648,374),(636,326)
+100    (648,306),(636,256)
+101    (648,256),(636,206)
+102    (648,206),(636,156)
+103    (667,470),(655,422)
+104    (667,422),(655,374)
+105    (667,374),(655,326)
+106    (667,306),(655,256)
+107    (667,256),(655,206)
+108    (667,206),(655,156)
+109    (686,470),(674,422)
+110    (686,422),(674,374)
+111    (686,374),(674,326)
+112    (686,306),(674,256)
+113    (686,256),(674,206)
+114    (686,206),(674,156)
+115    (705,470),(693,422)
+116    (705,422),(693,374)
+117    (705,374),(693,326)
+118    (705,306),(693,256)
+119    (705,256),(693,206)
+120    (705,206),(693,156)
+121    (724,470),(712,422)
+122    (724,422),(712,374)
+123    (724,374),(712,326)
+124    (724,306),(712,256)
+125    (724,256),(712,206)
+126    (724,206),(712,156)
+127    (743,470),(731,422)
+128    (743,422),(731,374)
+129    (743,374),(731,326)
+130    (743,306),(731,256)
+131    (743,256),(731,206)
+132    (743,206),(731,156)
+133    (762,470),(750,422)
+134    (762,422),(750,374)
+135    (762,374),(750,326)
+136    (762,306),(750,256)
+137    (762,256),(750,206)
+138    (762,206),(750,156)
+139    (781,470),(769,422)
+140    (781,422),(769,374)
+141    (781,374),(769,326)
+142    (781,306),(769,256)
+143    (781,256),(769,206)
+144    (781,206),(769,156)
+145    (808,470),(796,422)
+146    (808,422),(796,374)
+147    (808,374),(796,326)
+148    (808,306),(796,256)
+149    (808,256),(796,206)
+150    (808,206),(796,156)
+151    (827,470),(815,422)
+152    (827,422),(815,374)
+153    (827,374),(815,326)
+154    (827,306),(815,256)
+155    (827,256),(815,206)
+156    (827,206),(815,156)
+157    (846,470),(834,422)
+158    (846,422),(834,374)
+159    (846,374),(834,326)
+160    (846,306),(834,256)
+161    (846,256),(834,206)
+162    (846,206),(834,156)
+163    (865,470),(853,422)
+164    (865,422),(853,374)
+165    (865,374),(853,326)
+166    (865,306),(853,256)
+167    (865,256),(853,206)
+168    (865,206),(853,156)
+169    (884,470),(872,422)
+170    (884,422),(872,374)
+171    (884,374),(872,326)
+172    (884,306),(872,256)
+173    (884,256),(872,206)
+174    (884,206),(872,156)
+175    (903,470),(891,422)
+176    (903,422),(891,374)
+177    (903,374),(891,326)
+178    (903,306),(891,256)
+179    (903,256),(891,206)
+180    (903,206),(891,156)
+181    (922,470),(910,422)
+182    (922,422),(910,374)
+183    (922,374),(910,326)
+184    (922,306),(910,256)
+185    (922,256),(910,206)
+186    (922,206),(910,156)
+187    (941,470),(929,422)
+188    (941,422),(929,374)
+189    (941,374),(929,326)
+190    (941,306),(929,256)
+191    (941,256),(929,206)
+192    (941,206),(929,156)
+193    (960,470),(948,422)
+194    (960,422),(948,374)
+195    (960,374),(948,326)
+196    (960,306),(948,256)
+197    (960,256),(948,206)
+198    (960,206),(948,156)
+199    (988,422),(976,374)
+200    (988,374),(976,326)
+201    (979,306),(967,256)
+202    (979,256),(967,206)
+203    (1006,422),(994,374)
+204    (1006,374),(994,326)
+205    (997,306),(985,256)
+207    (1025,422),(1013,374)
+208    (1025,374),(1013,326)
+209    (1125,225),(1100,200)
+210    (680,550),(630,520)
+211    (610,550),(560,520)
+212    (305,385),(270,350)
+213    (900,100),(800,75)
+214    (900,100),(800,75)
+215    (200,270),(170,240)
+216    (250,180),(220,150)
+\.
+
+
+--
+-- Data for Name: polls; Type: TABLE DATA; Schema: public; Owner: postgres
+--
+
+\.
+
+
+--
+-- Data for Name: portnames; Type: TABLE DATA; Schema: public; Owner: postgres
+--
+
+COPY portnames (switchtype, port, description) FROM stdin;
+blackdiamond   1001    BD6808/G8Xi-Port 1:1
+blackdiamond   1002    BD6808/G8Xi-Port 1:2
+blackdiamond   1003    BD6808/G8Xi-Port 1:3
+blackdiamond   1004    BD6808/G8Xi-Port 1:4
+blackdiamond   1005    BD6808/G8Xi-Port 1:5
+blackdiamond   1006    BD6808/G8Xi-Port 1:6
+blackdiamond   1007    BD6808/G8Xi-Port 1:7
+blackdiamond   4001    BD6808/G16X3-Port 4:1
+blackdiamond   4002    BD6808/G16X3-Port 4:2
+blackdiamond   4003    BD6808/G16X3-Port 4:3
+blackdiamond   4004    BD6808/G16X3-Port 4:4
+blackdiamond   4005    BD6808/G16X3-Port 4:5
+blackdiamond   4006    BD6808/G16X3-Port 4:6
+blackdiamond   4007    BD6808/G16X3-Port 4:7
+blackdiamond   4008    BD6808/G16X3-Port 4:8
+blackdiamond   4009    BD6808/G16X3-Port 4:9
+blackdiamond   4010    BD6808/G16X3-Port 4:10
+blackdiamond   4011    BD6808/G16X3-Port 4:11
+blackdiamond   4012    BD6808/G16X3-Port 4:12
+blackdiamond   4013    BD6808/G16X3-Port 4:13
+blackdiamond   4014    BD6808/G16X3-Port 4:14
+blackdiamond   4015    BD6808/G16X3-Port 4:15
+blackdiamond   4016    BD6808/G16X3-Port 4:16
+blackdiamond   5001    BD6808/G24T3-Port 5:1
+blackdiamond   5002    BD6808/G24T3-Port 5:2
+blackdiamond   5003    BD6808/G24T3-Port 5:3
+blackdiamond   5004    BD6808/G24T3-Port 5:4
+blackdiamond   5005    BD6808/G24T3-Port 5:5
+blackdiamond   5006    BD6808/G24T3-Port 5:6
+blackdiamond   5007    BD6808/G24T3-Port 5:7
+blackdiamond   5008    BD6808/G24T3-Port 5:8
+blackdiamond   5009    BD6808/G24T3-Port 5:9
+blackdiamond   5010    BD6808/G24T3-Port 5:10
+blackdiamond   5011    BD6808/G24T3-Port 5:11
+blackdiamond   5012    BD6808/G24T3-Port 5:12
+blackdiamond   5013    BD6808/G24T3-Port 5:13
+blackdiamond   5014    BD6808/G24T3-Port 5:14
+blackdiamond   5015    BD6808/G24T3-Port 5:15
+blackdiamond   5016    BD6808/G24T3-Port 5:16
+blackdiamond   5017    BD6808/G24T3-Port 5:17
+blackdiamond   5018    BD6808/G24T3-Port 5:18
+blackdiamond   5019    BD6808/G24T3-Port 5:19
+blackdiamond   5020    BD6808/G24T3-Port 5:20
+blackdiamond   5021    BD6808/G24T3-Port 5:21
+blackdiamond   5022    BD6808/G24T3-Port 5:22
+blackdiamond   5023    BD6808/G24T3-Port 5:23
+blackdiamond   5024    BD6808/G24T3-Port 5:24
+blackdiamond   6001    BD6808/F48Ti-Port 6:1
+blackdiamond   6002    BD6808/F48Ti-Port 6:2
+blackdiamond   6003    BD6808/F48Ti-Port 6:3
+blackdiamond   6004    BD6808/F48Ti-Port 6:4
+blackdiamond   6005    BD6808/F48Ti-Port 6:5
+blackdiamond   6006    BD6808/F48Ti-Port 6:6
+blackdiamond   6007    BD6808/F48Ti-Port 6:7
+blackdiamond   6008    BD6808/F48Ti-Port 6:8
+blackdiamond   6009    BD6808/F48Ti-Port 6:9
+blackdiamond   6010    BD6808/F48Ti-Port 6:10
+blackdiamond   6011    BD6808/F48Ti-Port 6:11
+blackdiamond   6012    BD6808/F48Ti-Port 6:12
+blackdiamond   6013    BD6808/F48Ti-Port 6:13
+blackdiamond   6014    BD6808/F48Ti-Port 6:14
+blackdiamond   6015    BD6808/F48Ti-Port 6:15
+blackdiamond   6016    BD6808/F48Ti-Port 6:16
+blackdiamond   6017    BD6808/F48Ti-Port 6:17
+blackdiamond   6018    BD6808/F48Ti-Port 6:18
+blackdiamond   6019    BD6808/F48Ti-Port 6:19
+blackdiamond   6020    BD6808/F48Ti-Port 6:20
+blackdiamond   6021    BD6808/F48Ti-Port 6:21
+blackdiamond   6022    BD6808/F48Ti-Port 6:22
+blackdiamond   6023    BD6808/F48Ti-Port 6:23
+blackdiamond   6024    BD6808/F48Ti-Port 6:24
+blackdiamond   6025    BD6808/F48Ti-Port 6:25
+blackdiamond   6026    BD6808/F48Ti-Port 6:26
+blackdiamond   6027    BD6808/F48Ti-Port 6:27
+blackdiamond   6028    BD6808/F48Ti-Port 6:28
+blackdiamond   6029    BD6808/F48Ti-Port 6:29
+blackdiamond   6030    BD6808/F48Ti-Port 6:30
+blackdiamond   6031    BD6808/F48Ti-Port 6:31
+blackdiamond   6032    BD6808/F48Ti-Port 6:32
+blackdiamond   6033    BD6808/F48Ti-Port 6:33
+blackdiamond   6034    BD6808/F48Ti-Port 6:34
+blackdiamond   6035    BD6808/F48Ti-Port 6:35
+blackdiamond   6036    BD6808/F48Ti-Port 6:36
+blackdiamond   6037    BD6808/F48Ti-Port 6:37
+blackdiamond   6038    BD6808/F48Ti-Port 6:38
+blackdiamond   6039    BD6808/F48Ti-Port 6:39
+blackdiamond   6040    BD6808/F48Ti-Port 6:40
+blackdiamond   6041    BD6808/F48Ti-Port 6:41
+blackdiamond   6042    BD6808/F48Ti-Port 6:42
+blackdiamond   6043    BD6808/F48Ti-Port 6:43
+blackdiamond   6044    BD6808/F48Ti-Port 6:44
+blackdiamond   6045    BD6808/F48Ti-Port 6:45
+blackdiamond   6046    BD6808/F48Ti-Port 6:46
+blackdiamond   6047    BD6808/F48Ti-Port 6:47
+blackdiamond   6048    BD6808/F48Ti-Port 6:48
+cisco6509      1       GigabitEthernet1/1
+cisco6509      2       GigabitEthernet1/2
+cisco6509      3       GigabitEthernet1/3
+cisco6509      4       GigabitEthernet1/4
+cisco6509      5       GigabitEthernet1/5
+cisco6509      6       GigabitEthernet1/6
+cisco6509      7       GigabitEthernet1/7
+cisco6509      8       GigabitEthernet1/8
+cisco6509      9       GigabitEthernet1/9
+cisco6509      10      GigabitEthernet1/10
+cisco6509      11      GigabitEthernet1/11
+cisco6509      12      GigabitEthernet1/12
+cisco6509      13      GigabitEthernet1/13
+cisco6509      14      GigabitEthernet1/14
+cisco6509      15      GigabitEthernet1/15
+cisco6509      16      GigabitEthernet1/16
+cisco6509      17      GigabitEthernet1/17
+cisco6509      18      GigabitEthernet1/18
+cisco6509      19      GigabitEthernet1/19
+cisco6509      20      GigabitEthernet1/20
+cisco6509      21      GigabitEthernet1/21
+cisco6509      22      GigabitEthernet1/22
+cisco6509      23      GigabitEthernet1/23
+cisco6509      24      GigabitEthernet1/24
+cisco6509      25      GigabitEthernet1/25
+cisco6509      26      GigabitEthernet1/26
+cisco6509      27      GigabitEthernet1/27
+cisco6509      28      GigabitEthernet1/28
+cisco6509      29      GigabitEthernet1/29
+cisco6509      30      GigabitEthernet1/30
+cisco6509      31      GigabitEthernet1/31
+cisco6509      32      GigabitEthernet1/32
+cisco6509      33      GigabitEthernet1/33
+cisco6509      34      GigabitEthernet1/34
+cisco6509      35      GigabitEthernet1/35
+cisco6509      36      GigabitEthernet1/36
+cisco6509      37      GigabitEthernet1/37
+cisco6509      38      GigabitEthernet1/38
+cisco6509      39      GigabitEthernet1/39
+cisco6509      40      GigabitEthernet1/40
+cisco6509      41      GigabitEthernet1/41
+cisco6509      42      GigabitEthernet1/42
+cisco6509      43      GigabitEthernet1/43
+cisco6509      44      GigabitEthernet1/44
+cisco6509      45      GigabitEthernet1/45
+cisco6509      46      GigabitEthernet1/46
+cisco6509      47      GigabitEthernet1/47
+cisco6509      48      GigabitEthernet1/48
+cisco6509      49      GigabitEthernet2/1
+cisco6509      50      GigabitEthernet2/2
+cisco6509      51      GigabitEthernet2/3
+cisco6509      52      GigabitEthernet2/4
+cisco6509      53      GigabitEthernet2/5
+cisco6509      54      GigabitEthernet2/6
+cisco6509      55      GigabitEthernet2/7
+cisco6509      56      GigabitEthernet2/8
+cisco6509      57      GigabitEthernet2/9
+cisco6509      58      GigabitEthernet2/10
+cisco6509      59      GigabitEthernet2/11
+cisco6509      60      GigabitEthernet2/12
+cisco6509      61      GigabitEthernet2/13
+cisco6509      62      GigabitEthernet2/14
+cisco6509      63      GigabitEthernet2/15
+cisco6509      64      GigabitEthernet2/16
+cisco6509      65      FastEthernet4/1
+cisco6509      66      FastEthernet4/2
+cisco6509      67      FastEthernet4/3
+cisco6509      68      FastEthernet4/4
+cisco6509      69      FastEthernet4/5
+cisco6509      70      FastEthernet4/6
+cisco6509      71      FastEthernet4/7
+cisco6509      72      FastEthernet4/8
+cisco6509      73      FastEthernet4/9
+cisco6509      74      FastEthernet4/10
+cisco6509      75      FastEthernet4/11
+cisco6509      76      FastEthernet4/12
+cisco6509      77      FastEthernet4/13
+cisco6509      78      FastEthernet4/14
+cisco6509      79      FastEthernet4/15
+cisco6509      80      FastEthernet4/16
+cisco6509      81      FastEthernet4/17
+cisco6509      82      FastEthernet4/18
+cisco6509      83      FastEthernet4/19
+cisco6509      84      FastEthernet4/20
+cisco6509      85      FastEthernet4/21
+cisco6509      86      FastEthernet4/22
+cisco6509      87      FastEthernet4/23
+cisco6509      88      FastEthernet4/24
+cisco6509      89      FastEthernet4/25
+cisco6509      90      FastEthernet4/26
+cisco6509      91      FastEthernet4/27
+cisco6509      92      FastEthernet4/28
+cisco6509      93      FastEthernet4/29
+cisco6509      94      FastEthernet4/30
+cisco6509      95      FastEthernet4/31
+cisco6509      96      FastEthernet4/32
+cisco6509      97      FastEthernet4/33
+cisco6509      98      FastEthernet4/34
+cisco6509      99      FastEthernet4/35
+cisco6509      100     FastEthernet4/36
+cisco6509      101     FastEthernet4/37
+cisco6509      102     FastEthernet4/38
+cisco6509      103     FastEthernet4/39
+cisco6509      104     FastEthernet4/40
+cisco6509      105     FastEthernet4/41
+cisco6509      106     FastEthernet4/42
+cisco6509      107     FastEthernet4/43
+cisco6509      108     FastEthernet4/44
+cisco6509      109     FastEthernet4/45
+cisco6509      110     FastEthernet4/46
+cisco6509      111     FastEthernet4/47
+cisco6509      112     FastEthernet4/48
+cisco6509      113     GigabitEthernet5/1
+cisco6509      114     GigabitEthernet5/2
+cisco6509      115     GigabitEthernet8/1
+cisco6509      116     GigabitEthernet8/2
+cisco6509      117     GigabitEthernet8/3
+cisco6509      118     GigabitEthernet8/4
+cisco6509      119     GigabitEthernet8/5
+cisco6509      120     GigabitEthernet8/6
+cisco6509      121     GigabitEthernet8/7
+cisco6509      122     GigabitEthernet8/8
+cisco6509      123     GigabitEthernet8/9
+\.
+
+
+--
+-- Data for Name: switches; Type: TABLE DATA; Schema: public; Owner: postgres
+--
+
+COPY switches (switch, ip, sysname, switchtype, last_updated, locked, priority, poll_frequency, community) FROM stdin;
+107    81.162.243.120  e37-5sw es3024  2005-03-27 13:17:34.571591+02   f       0       00:05:00        removed
+82     81.162.242.95   e29-4sw es3024  2005-03-27 13:16:26.93166+02    f       0       00:05:00        removed
+104    81.162.243.117  e37-2sw es3024  2005-03-27 13:17:56.76605+02    f       0       00:05:00        removed
+54     81.162.242.67   e19-6sw es3024  2005-03-27 13:18:06.955298+02   f       0       00:05:00        removed
+112    81.162.243.125  e39-4sw es3024  2005-03-27 13:18:08.119358+02   f       0       00:05:00        removed
+99     81.162.243.112  e35-3sw es3024  2005-03-27 13:18:18.138712+02   f       0       00:05:00        removed
+96     81.162.243.109  e33-6sw es3024  2005-03-27 13:19:12.471088+02   f       0       00:05:00        removed
+189    81.162.245.202  e65-3sw es3024  2005-03-27 13:19:14.973227+02   f       0       00:05:00        removed
+22     81.162.241.35   e9-4sw  es3024  2005-03-27 13:20:32.530723+02   f       0       00:05:00        removed
+11     81.162.241.24   e5-5sw  es3024  2005-03-27 13:20:41.845068+02   f       0       00:05:00        removed
+168    81.162.244.181  e57-6sw es3024  2005-03-27 13:20:42.537996+02   f       0       00:05:00        removed
+21     81.162.241.34   e9-3sw  es3024  2005-03-27 13:21:34.547743+02   t       0       00:05:00        removed
+45     81.162.242.58   e17-3sw es3024  2005-03-27 13:21:35.095512+02   t       0       00:05:00        removed
+171    81.162.245.184  e59-3sw es3024  2005-03-27 13:21:42.545292+02   t       0       00:05:00        removed
+191    81.162.245.204  e65-5sw es3024  2005-03-27 13:16:31.123889+02   f       0       00:05:00        removed
+209    127.0.0.1       game    es3024  2005-03-27 13:17:24.559535+02   f       0       00:05:00        removed
+213    127.0.0.1       logistics       es3024  2005-03-27 13:17:24.565673+02   f       0       00:05:00        removed
+65     81.162.242.78   e23-5sw es3024  2005-03-27 13:17:46.939821+02   f       0       00:05:00        removed
+170    81.162.245.183  e59-2sw es3024  2005-03-27 13:18:04.978308+02   f       0       00:05:00        removed
+27     81.162.241.40   e11-3sw es3024  2005-03-27 13:18:17.760774+02   f       0       00:05:00        removed
+29     81.162.241.42   e11-5sw es3024  2005-03-27 13:18:31.402994+02   f       0       00:05:00        removed
+190    81.162.245.203  e65-4sw es3024  2005-03-27 13:18:36.97826+02    f       0       00:05:00        removed
+198    81.162.245.211  e67-6sw es3024  2005-03-27 13:18:46.960978+02   f       0       00:05:00        removed
+94     81.162.243.107  e33-4sw es3024  2005-03-27 13:18:54.836293+02   f       0       00:05:00        removed
+167    81.162.244.180  e57-5sw es3024  2005-03-27 13:18:59.347337+02   f       0       00:05:00        removed
+207    81.162.245.220  e73-2sw es3024  2005-03-27 13:16:31.90388+02    f       0       00:05:00        removed
+121    81.162.243.134  e43-1sw es3024  2005-03-27 13:17:32.374414+02   f       0       00:05:00        removed
+35     81.162.241.48   e13-5sw es3024  2005-03-27 13:17:36.647606+02   f       0       00:05:00        removed
+48     81.162.242.61   e17-6sw es3024  2005-03-27 13:17:37.509652+02   f       0       00:05:00        removed
+39     81.162.241.52   e15-3sw es3024  2005-03-27 13:17:46.961826+02   f       0       00:05:00        removed
+28     81.162.241.41   e11-4sw es3024  2005-03-27 13:17:46.6959+02     f       0       00:05:00        removed
+109    81.162.243.122  e39-1sw es3024  2005-03-27 13:17:56.906062+02   f       0       00:05:00        removed
+25     81.162.241.38   e11-1sw es3024  2005-03-27 13:18:31.344059+02   f       0       00:05:00        removed
+72     81.162.242.85   e25-6sw es3024  2005-03-27 13:18:52.027008+02   f       0       00:05:00        removed
+155    81.162.244.168  e53-5sw es3024  2005-03-27 13:19:11.997064+02   f       0       00:05:00        removed
+19     81.162.241.32   e9-1sw  es3024  2005-03-27 13:20:23.30851+02    f       0       00:05:00        removed
+42     81.162.241.55   e15-6sw es3024  2005-03-27 13:20:23.334654+02   f       0       00:05:00        removed
+180    81.162.245.193  e61-6sw es3024  2005-03-27 13:20:37.173987+02   f       0       00:05:00        removed
+200    81.162.245.213  e69-3sw es3024  2005-03-27 13:20:47.20716+02    f       0       00:05:00        removed
+224    81.162.239.24   d04     summit400       2005-03-27 13:21:24.972747+02   f       5       00:00:20        removed
+219    81.162.240.61   game-gw summit48        2005-03-27 13:21:33.484975+02   t       5       00:00:20        removed
+88     81.162.243.101  e31-4sw es3024  2005-03-27 13:16:26.527548+02   f       0       00:05:00        removed
+113    81.162.243.126  e39-5sw es3024  2005-03-27 13:18:06.543322+02   f       0       00:05:00        removed
+64     81.162.242.77   e23-4sw es3024  2005-03-27 13:18:26.656294+02   f       0       00:05:00        removed
+81     81.162.242.94   e29-3sw es3024  2005-03-27 13:17:35.445561+02   f       0       00:05:00        removed
+101    81.162.243.114  e35-5sw es3024  2005-03-27 13:17:36.945531+02   f       0       00:05:00        removed
+16     81.162.241.29   e7-4sw  es3024  2005-03-27 13:17:45.453891+02   f       0       00:05:00        removed
+43     81.162.242.56   e17-1sw es3024  2005-03-27 13:17:55.459964+02   f       0       00:05:00        removed
+122    81.162.243.135  e43-2sw es3024  2005-03-27 13:18:05.467243+02   f       0       00:05:00        removed
+133    81.162.244.146  e47-1sw es3024  2005-03-27 13:18:41.709491+02   f       0       00:05:00        removed
+32     81.162.241.45   e13-2sw es3024  2005-03-27 13:19:11.73096+02    f       0       00:05:00        removed
+4      81.162.241.17   e3-4sw  es3024  2005-03-27 13:19:21.737736+02   f       0       00:05:00        removed
+80     81.162.242.93   e29-2sw es3024  2005-03-27 13:20:34.240028+02   f       0       00:05:00        removed
+62     81.162.242.75   e23-2sw es3024  2005-03-27 13:21:31.873108+02   f       0       00:05:00        removed
+214    127.0.0.1       logistics       es3024  2005-03-27 13:21:31.924796+02   f       0       00:05:00        removed
+215    127.0.0.1       vision  es3024  2005-03-27 13:21:31.930782+02   f       0       00:05:00        removed
+57     81.162.242.70   e21-3sw es3024  2005-03-27 13:21:40.84502+02    f       0       00:05:00        removed
+146    81.162.244.159  e51-2sw es3024  2005-03-27 13:17:45.214911+02   f       0       00:05:00        removed
+47     81.162.242.60   e17-5sw es3024  2005-03-27 13:17:51.983994+02   f       0       00:05:00        removed
+140    81.162.244.153  e49-2sw es3024  2005-03-27 13:18:28.990817+02   f       0       00:05:00        removed
+186    81.162.245.199  e63-6sw es3024  2005-03-27 13:18:38.997342+02   f       0       00:05:00        removed
+152    81.162.244.165  e53-2sw es3024  2005-03-27 13:18:49.281799+02   f       0       00:05:00        removed
+108    81.162.243.121  e37-6sw es3024  2005-03-27 13:19:01.723458+02   f       0       00:05:00        removed
+158    81.162.244.171  e55-2sw es3024  2005-03-27 13:19:09.602985+02   f       0       00:05:00        removed
+178    81.162.245.191  e61-4sw es3024  2005-03-27 13:19:19.609527+02   f       0       00:05:00        removed
+85     81.162.243.98   e31-1sw es3024  2005-03-27 13:20:29.849688+02   f       0       00:05:00        removed
+70     81.162.242.83   e25-4sw es3024  2005-03-27 13:20:39.869994+02   f       0       00:05:00        removed
+75     81.162.242.88   e27-3sw es3024  2005-03-27 13:20:49.343969+02   f       0       00:05:00        removed
+223    81.162.245.2    d05     summit400       2005-03-27 13:21:36.931022+02   t       5       00:00:20        removed
+61     81.162.242.74   e23-1sw es3024  2005-03-27 13:16:26.916608+02   f       0       00:05:00        removed
+149    81.162.244.162  e51-5sw es3024  2005-03-27 13:17:41.922862+02   f       0       00:05:00        removed
+157    81.162.244.170  e55-1sw es3024  2005-03-27 13:18:18.9515+02     f       0       00:05:00        removed
+63     81.162.242.76   e23-3sw es3024  2005-03-27 13:18:27.768739+02   f       0       00:05:00        removed
+141    81.162.244.154  e49-3sw es3024  2005-03-27 13:18:31.991117+02   f       0       00:05:00        removed
+84     81.162.242.97   e29-6sw es3024  2005-03-27 13:18:37.040327+02   f       0       00:05:00        removed
+18     81.162.241.31   e7-6sw  es3024  2005-03-27 13:18:41.999541+02   f       0       00:05:00        removed
+97     81.162.243.110  e35-1sw es3024  2005-03-27 13:18:45.253797+02   f       0       00:05:00        removed
+195    81.162.245.208  e67-3sw es3024  2005-03-27 13:18:51.715929+02   f       0       00:05:00        removed
+127    81.162.244.140  e45-1sw es3024  2005-03-27 13:19:02.072477+02   f       0       00:05:00        removed
+98     81.162.243.111  e35-2sw es3024  2005-03-27 13:19:04.918692+02   f       0       00:05:00        removed
+150    81.162.244.163  e51-6sw es3024  2005-03-27 13:20:32.007722+02   f       0       00:05:00        removed
+23     81.162.241.36   e9-5sw  es3024  2005-03-27 13:20:41.903998+02   f       0       00:05:00        removed
+201    81.162.245.214  e69-4sw es3024  2005-03-27 13:20:49.876993+02   f       0       00:05:00        removed
+30     81.162.241.43   e11-6sw es3024  2005-03-27 13:17:56.948002+02   f       0       00:05:00        removed
+87     81.162.243.100  e31-3sw es3024  2005-03-27 13:17:58.687121+02   f       0       00:05:00        removed
+86     81.162.243.99   e31-2sw es3024  2005-03-27 13:18:05.554204+02   f       0       00:05:00        removed
+14     81.162.241.27   e7-2sw  es3024  2005-03-27 13:18:08.944334+02   f       0       00:05:00        removed
+10     81.162.241.23   e5-4sw  es3024  2005-03-27 13:18:16.601602+02   f       0       00:05:00        removed
+17     81.162.241.30   e7-5sw  es3024  2005-03-27 13:18:28.157952+02   f       0       00:05:00        removed
+9      81.162.241.22   e5-3sw  es3024  2005-03-27 13:18:36.939248+02   f       0       00:05:00        removed
+67     81.162.242.80   e25-1sw es3024  2005-03-27 13:18:51.943995+02   f       0       00:05:00        removed
+7      81.162.241.20   e5-1sw  es3024  2005-03-27 13:18:58.991329+02   f       0       00:05:00        removed
+92     81.162.243.105  e33-2sw es3024  2005-03-27 13:19:06.989323+02   f       0       00:05:00        removed
+71     81.162.242.84   e25-5sw es3024  2005-03-27 13:19:09.011272+02   f       0       00:05:00        removed
+179    81.162.245.192  e61-5sw es3024  2005-03-27 13:20:29.194747+02   f       0       00:05:00        removed
+124    81.162.243.137  e43-4sw es3024  2005-03-27 13:20:39.258962+02   f       0       00:05:00        removed
+162    81.162.244.175  e55-6sw es3024  2005-03-27 13:20:42.061636+02   f       0       00:05:00        removed
+78     81.162.242.91   e27-6sw es3024  2005-03-27 13:16:29.572827+02   f       0       00:05:00        removed
+176    81.162.245.189  e61-2sw es3024  2005-03-27 13:17:32.393394+02   f       0       00:05:00        removed
+105    81.162.243.118  e37-3sw es3024  2005-03-27 13:17:45.539842+02   f       0       00:05:00        removed
+116    81.162.243.129  e41-2sw es3024  2005-03-27 13:17:42.437966+02   f       0       00:05:00        removed
+119    81.162.243.132  e41-5sw es3024  2005-03-27 13:18:07.716339+02   f       0       00:05:00        removed
+31     81.162.241.44   e13-1sw es3024  2005-03-27 13:18:44.72174+02    f       0       00:05:00        removed
+203    81.162.245.216  e71-2sw es3024  2005-03-27 13:20:52.126954+02   f       0       00:05:00        removed
+217    81.162.239.1    inet-gw cisco3550       2005-03-27 13:21:34.339813+02   f       5       00:00:20        removed
+221    81.162.241.2    d01     summit400       2005-03-27 13:21:38.690758+02   f       5       00:00:20        removed
+220    81.162.240.7    info-gw summit48        2005-03-27 13:21:38.74123+02    t       5       00:00:20        removed
+37     81.162.241.50   e15-1sw es3024  2005-03-27 13:21:42.323351+02   t       0       00:05:00        removed
+53     81.162.242.66   e19-5sw es3024  2005-03-27 13:17:44.668027+02   f       0       00:05:00        removed
+192    81.162.245.205  e65-6sw es3024  2005-03-27 13:19:11.969024+02   f       0       00:05:00        removed
+46     81.162.242.59   e17-4sw es3024  2005-03-27 13:20:43.449971+02   f       0       00:05:00        removed
+204    81.162.245.217  e71-3sw es3024  2005-03-27 13:20:52.107916+02   f       0       00:05:00        removed
+161    81.162.244.174  e55-5sw es3024  2005-03-27 13:21:35.234881+02   t       0       00:05:00        removed
+142    81.162.244.155  e49-4sw es3024  2005-03-27 13:21:41.936852+02   f       0       00:05:00        removed
+143    81.162.244.156  e49-5sw es3024  2005-03-27 13:21:42.169429+02   t       0       00:05:00        removed
+165    81.162.244.178  e57-3sw es3024  2005-03-27 13:17:57.668107+02   f       0       00:05:00        removed
+2      81.162.241.12   e1-5sw  es3024  2005-03-27 13:18:06.980239+02   f       0       00:05:00        removed
+182    81.162.245.195  e63-2sw es3024  2005-03-27 13:16:31.752876+02   f       0       00:05:00        removed
+147    81.162.244.160  e51-3sw es3024  2005-03-27 13:17:58.091146+02   f       0       00:05:00        removed
+193    81.162.245.206  e67-1sw es3024  2005-03-27 13:18:35.580223+02   f       0       00:05:00        removed
+83     81.162.242.96   e29-5sw es3024  2005-03-27 13:18:36.721338+02   f       0       00:05:00        removed
+194    81.162.245.207  e67-2sw es3024  2005-03-27 13:18:38.974352+02   f       0       00:05:00        removed
+6      81.162.241.19   e3-6sw  es3024  2005-03-27 13:18:47.075003+02   f       0       00:05:00        removed
+49     81.162.242.62   e19-1sw es3024  2005-03-27 13:19:01.806447+02   f       0       00:05:00        removed
+211    127.0.0.1       presse  es3024  2005-03-27 13:17:25.438397+02   f       0       00:05:00        removed
+90     81.162.243.103  e31-6sw es3024  2005-03-27 13:17:36.889596+02   f       0       00:05:00        removed
+52     81.162.242.65   e19-4sw es3024  2005-03-27 13:18:26.931818+02   f       0       00:05:00        removed
+136    81.162.244.149  e47-4sw es3024  2005-03-27 13:18:38.226473+02   f       0       00:05:00        removed
+5      81.162.241.18   e3-5sw  es3024  2005-03-27 13:18:42.447575+02   f       0       00:05:00        removed
+183    81.162.245.196  e63-3sw es3024  2005-03-27 13:18:48.289809+02   f       0       00:05:00        removed
+169    81.162.245.182  e59-1sw es3024  2005-03-27 13:18:51.524996+02   f       0       00:05:00        removed
+137    81.162.244.150  e47-5sw es3024  2005-03-27 13:18:58.34439+02    f       0       00:05:00        removed
+111    81.162.243.124  e39-3sw es3024  2005-03-27 13:19:08.389862+02   f       0       00:05:00        removed
+126    81.162.243.139  e43-6sw es3024  2005-03-27 13:19:18.396631+02   f       0       00:05:00        removed
+115    81.162.243.128  e41-1sw es3024  2005-03-27 13:20:21.794673+02   f       0       00:05:00        removed
+144    81.162.244.157  e49-6sw es3024  2005-03-27 13:20:27.601697+02   f       0       00:05:00        removed
+205    81.162.245.218  e71-4sw es3024  2005-03-27 13:20:37.610991+02   f       0       00:05:00        removed
+103    81.162.243.116  e37-1sw es3024  2005-03-27 13:17:35.19156+02    f       0       00:05:00        removed
+160    81.162.244.173  e55-4sw es3024  2005-03-27 13:17:46.897831+02   f       0       00:05:00        removed
+177    81.162.245.190  e61-3sw es3024  2005-03-27 13:18:15.475485+02   f       0       00:05:00        removed
+79     81.162.242.92   e29-1sw es3024  2005-03-27 13:18:36.728294+02   f       0       00:05:00        removed
+208    81.162.245.221  e73-3sw es3024  2005-03-27 13:19:22.036778+02   f       0       00:05:00        removed
+24     81.162.241.37   e9-6sw  es3024  2005-03-27 13:20:32.103714+02   f       0       00:05:00        removed
+76     81.162.242.89   e27-4sw es3024  2005-03-27 13:20:42.111557+02   f       0       00:05:00        removed
+44     81.162.242.57   e17-2sw es3024  2005-03-27 13:17:41.971894+02   f       0       00:05:00        removed
+66     81.162.242.79   e23-6sw es3024  2005-03-27 13:17:56.972013+02   f       0       00:05:00        removed
+41     81.162.241.54   e15-5sw es3024  2005-03-27 13:18:21.393627+02   f       0       00:05:00        removed
+8      81.162.241.21   e5-2sw  es3024  2005-03-27 13:18:28.967927+02   f       0       00:05:00        removed
+15     81.162.241.28   e7-3sw  es3024  2005-03-27 13:18:36.799213+02   f       0       00:05:00        removed
+1      81.162.241.11   e1-4sw  es3024  2005-03-27 13:18:42.522553+02   f       0       00:05:00        removed
+123    81.162.243.136  e43-3sw es3024  2005-03-27 13:18:51.995005+02   f       0       00:05:00        removed
+129    81.162.244.142  e45-3sw es3024  2005-03-27 13:18:54.851215+02   f       0       00:05:00        removed
+56     81.162.242.69   e21-2sw es3024  2005-03-27 13:19:02.014465+02   f       0       00:05:00        removed
+181    81.162.245.194  e63-1sw es3024  2005-03-27 13:19:12.059112+02   f       0       00:05:00        removed
+33     81.162.241.46   e13-3sw es3024  2005-03-27 13:19:12.08011+02    f       0       00:05:00        removed
+68     81.162.242.81   e25-2sw es3024  2005-03-27 13:20:22.092638+02   f       0       00:05:00        removed
+139    81.162.244.152  e49-1sw es3024  2005-03-27 13:21:32.131187+02   f       0       00:05:00        removed
+166    81.162.244.179  e57-4sw es3024  2005-03-27 13:21:42.167871+02   f       0       00:05:00        removed
+55     81.162.242.68   e21-1sw es3024  2005-03-27 13:18:27.760928+02   f       0       00:05:00        removed
+187    81.162.245.200  e65-1sw es3024  2005-03-27 13:18:37.783633+02   f       0       00:05:00        removed
+135    81.162.244.148  e47-3sw es3024  2005-03-27 13:18:47.790825+02   f       0       00:05:00        removed
+69     81.162.242.82   e25-3sw es3024  2005-03-27 13:19:01.960433+02   f       0       00:05:00        removed
+114    81.162.243.127  e39-6sw es3024  2005-03-27 13:19:07.807795+02   f       0       00:05:00        removed
+185    81.162.245.198  e63-5sw es3024  2005-03-27 13:19:21.979734+02   f       0       00:05:00        removed
+163    81.162.244.176  e57-1sw es3024  2005-03-27 13:20:37.80015+02    f       0       00:05:00        removed
+222    81.162.242.2    d02     summit400       2005-03-27 13:21:26.058745+02   f       5       00:00:20        removed
+120    81.162.243.133  e41-6sw es3024  2005-03-27 13:21:30.769149+02   f       0       00:05:00        removed
+128    81.162.244.141  e45-2sw es3024  2005-03-27 13:17:36.931503+02   f       0       00:05:00        removed
+174    81.162.245.187  e59-6sw es3024  2005-03-27 13:18:16.963474+02   f       0       00:05:00        removed
+148    81.162.244.161  e51-4sw es3024  2005-03-27 13:18:26.970802+02   f       0       00:05:00        removed
+110    81.162.243.123  e39-2sw es3024  2005-03-27 13:18:47.000886+02   f       0       00:05:00        removed
+77     81.162.242.90   e27-5sw es3024  2005-03-27 13:19:11.815032+02   f       0       00:05:00        removed
+145    81.162.244.158  e51-1sw es3024  2005-03-27 13:21:33.428323+02   f       0       00:05:00        removed
+218    81.162.239.11   telematics-gw   summit7i        2005-03-27 13:21:40.916277+02   t       5       00:00:20        removed
+153    81.162.244.166  e53-3sw es3024  2005-03-27 13:17:44.926073+02   f       0       00:05:00        removed
+3      81.162.241.13   e1-6sw  es3024  2005-03-27 13:19:01.621559+02   f       0       00:05:00        removed
+175    81.162.245.188  e61-1sw es3024  2005-03-27 13:19:21.726775+02   f       0       00:05:00        removed
+159    81.162.244.172  e55-3sw es3024  2005-03-27 13:20:47.807065+02   f       0       00:05:00        removed
+13     81.162.241.26   e7-1sw  es3024  2005-03-27 13:20:48.110995+02   f       0       00:05:00        removed
+210    81.162.239.10   noc     cisco6509       2005-03-27 13:21:26.109659+02   f       5       00:00:20        removed
+34     81.162.241.47   e13-4sw es3024  2005-03-27 13:17:34.658518+02   f       0       00:05:00        removed
+151    81.162.244.164  e53-1sw es3024  2005-03-27 13:21:41.93941+02    t       0       00:05:00        removed
+93     81.162.243.106  e33-3sw es3024  2005-03-27 13:21:42.589349+02   t       0       00:05:00        removed
+51     81.162.242.64   e19-3sw es3024  2005-03-27 13:16:25.080516+02   f       0       00:05:00        removed
+58     81.162.242.71   e21-4sw es3024  2005-03-27 13:17:35.16855+02    f       0       00:05:00        removed
+130    81.162.244.143  e45-4sw es3024  2005-03-27 13:17:55.221024+02   f       0       00:05:00        removed
+172    81.162.245.185  e59-4sw es3024  2005-03-27 13:18:05.249512+02   f       0       00:05:00        removed
+91     81.162.243.104  e33-1sw es3024  2005-03-27 13:18:51.619208+02   f       0       00:05:00        removed
+74     81.162.242.87   e27-2sw es3024  2005-03-27 13:19:01.627392+02   f       0       00:05:00        removed
+12     81.162.241.25   e5-6sw  es3024  2005-03-27 13:19:11.65907+02    f       0       00:05:00        removed
+89     81.162.243.102  e31-5sw es3024  2005-03-27 13:20:31.837713+02   f       0       00:05:00        removed
+225    81.162.240.98   bd      blackdiamond    2005-03-27 13:21:35.038465+02   f       10      00:00:20        removed
+154    81.162.244.167  e53-4sw es3024  2005-03-27 13:16:25.504565+02   f       0       00:05:00        removed
+36     81.162.241.49   e13-6sw es3024  2005-03-27 13:17:35.531534+02   f       0       00:05:00        removed
+50     81.162.242.63   e19-2sw es3024  2005-03-27 13:17:55.547006+02   f       0       00:05:00        removed
+106    81.162.243.119  e37-4sw es3024  2005-03-27 13:18:15.562463+02   f       0       00:05:00        removed
+138    81.162.244.151  e47-6sw es3024  2005-03-27 13:19:21.822733+02   f       0       00:05:00        removed
+59     81.162.242.72   e21-5sw es3024  2005-03-27 13:17:47.590918+02   f       0       00:05:00        removed
+102    81.162.243.115  e35-6sw es3024  2005-03-27 13:18:06.775277+02   f       0       00:05:00        removed
+134    81.162.244.147  e47-2sw es3024  2005-03-27 13:18:16.783539+02   f       0       00:05:00        removed
+26     81.162.241.39   e11-2sw es3024  2005-03-27 13:18:26.79084+02    f       0       00:05:00        removed
+216    127.0.0.1       vision-sponsor  es3024  2005-03-27 13:20:53.695607+02   f       0       00:05:00        removed
+184    81.162.245.197  e63-4sw es3024  2005-03-27 13:18:06.9152+02     f       0       00:05:00        removed
+196    81.162.245.209  e67-4sw es3024  2005-03-27 13:18:16.922538+02   f       0       00:05:00        removed
+95     81.162.243.108  e33-5sw es3024  2005-03-27 13:18:16.988269+02   f       0       00:05:00        removed
+38     81.162.241.51   e15-2sw es3024  2005-03-27 13:18:26.99682+02    f       0       00:05:00        removed
+60     81.162.242.73   e21-6sw es3024  2005-03-27 13:18:57.086812+02   f       0       00:05:00        removed
+73     81.162.242.86   e27-1sw es3024  2005-03-27 13:19:07.114926+02   f       0       00:05:00        removed
+118    81.162.243.131  e41-4sw es3024  2005-03-27 13:18:52.456053+02   f       0       00:05:00        removed
+100    81.162.243.113  e35-4sw es3024  2005-03-27 13:20:22.485517+02   f       0       00:05:00        removed
+132    81.162.244.145  e45-6sw es3024  2005-03-27 13:20:32.492844+02   f       0       00:05:00        removed
+131    81.162.244.144  e45-5sw es3024  2005-03-27 13:21:42.507294+02   t       0       00:05:00        removed
+125    81.162.243.138  e43-5sw es3024  2005-03-27 13:18:52.532065+02   f       0       00:05:00        removed
+173    81.162.245.186  e59-5sw es3024  2005-03-27 13:19:12.547121+02   f       0       00:05:00        removed
+212    127.0.0.1       info-desk       es3024  2005-03-27 13:20:12.561191+02   f       0       00:05:00        removed
+188    81.162.245.201  e65-2sw es3024  2005-03-27 13:20:22.567537+02   f       0       00:05:00        removed
+40     81.162.241.53   e15-4sw es3024  2005-03-27 13:20:32.574729+02   f       0       00:05:00        removed
+199    81.162.245.212  e69-2sw es3024  2005-03-27 13:20:42.582037+02   f       0       00:05:00        removed
+156    81.162.244.169  e53-6sw es3024  2005-03-27 13:20:33.372782+02   f       0       00:05:00        removed
+202    81.162.245.215  e69-5sw es3024  2005-03-27 13:20:47.618076+02   f       0       00:05:00        removed
+20     81.162.241.33   e9-2sw  es3024  2005-03-27 13:18:57.800335+02   f       0       00:05:00        removed
+117    81.162.243.130  e41-3sw es3024  2005-03-27 13:19:02.463533+02   f       0       00:05:00        removed
+164    81.162.244.177  e57-2sw es3024  2005-03-27 13:20:42.500004+02   f       0       00:05:00        removed
+197    81.162.245.210  e67-5sw es3024  2005-03-27 13:19:13.321114+02   f       0       00:05:00        removed
+\.
+
+
+--
+-- Data for Name: switchtypes; Type: TABLE DATA; Schema: public; Owner: postgres
+--
+
+COPY switchtypes (switchtype, ports) FROM stdin;
+blackdiamond   1001-1007,4001-4016,5001-5024,6001-6048
+es3024 1-25
+cisco6509      1-123
+summit400      1-50
+cisco3550      1-50
+summit7i       1-32
+summit48       1-50
+\.
+
+
diff --git a/web/overlay.pl b/web/overlay.pl
new file mode 100755 (executable)
index 0000000..21eff19
--- /dev/null
@@ -0,0 +1,160 @@
+#! /usr/bin/perl
+use GD;
+use LWP::Simple;
+use CGI;
+use DBI;
+
+my $cgi = CGI->new;
+my $dbh = DBI->connect("dbi:Pg:dbname=snmpfetch;host=violet.tg05.gathering.org", "snmpfetch", "removed")
+or die "Couldn't connect to database";
+
+my $cam = $cgi->param('cam');
+if (!defined($cam) || ($cam ne "1" && $cam ne "2")) {
+       $cam = 1;
+}
+
+GD::Image->trueColor(1);
+my $imgfile = LWP::Simple::get(($cam == 1) ? 'http://tgcam.jodal.no/techserver.php' : 'http://tgcam.jodal.no/crewcam.php')
+       or die "LWP: $!";
+my $gd = GD::Image->newFromJpegData($imgfile)
+       or die "GD: $!";
+
+my @coeffs;
+if ($cam == 1) {
+       @coeffs = (
+               2.295433895, -3.779680538, 1041.484066,
+               0.2246879859, 6.923972919, -1575.662172,
+               -0.0004822922595, 0.01151624710, -1.684908753
+       );
+} else {
+       @coeffs = (
+               3.656223906, -6.265111699, 863.9199590,
+               -5.954616242, 51.56856164, -9307.725196,
+               -0.006634136987, 0.04963057393, -7.875733154
+       );
+}
+
+# fetch our data
+my $q = $dbh->prepare('select * from switches natural left join
+               ( select switch,sum(bytes_in)/count(*) as
+                 bytes_in,sum(bytes_out)/count(*) as bytes_out from get_datarate() group
+                 by switch ) t1 where ip<>\'127.0.0.1\' and sysname like \'e%-%sw\'');
+$q->execute();
+
+my %sc = ();
+while (my $ref = $q->fetchrow_hashref()) {
+       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 = 20_000_000.0;   # 10mbit
+               my $min =    100_000.0;   # 100kbit
+               if ($traffic >= $min) {
+                       $intensity = 2.0 * (log($traffic / $min) / log(10)) / (log($max / $min) / log(10));
+                       $intensity = 2.0 if ($intensity > 2.0);
+               }
+
+               $sc{$ref->{'sysname'}} = get_color($intensity);
+       }
+}
+
+for my $y (0..479) {
+       for my $x (0..639) {
+               my $z = 1.0;
+
+               my $nx = $coeffs[0] * $x + $coeffs[1] * $y + $coeffs[2] * $z;
+               my $ny = $coeffs[3] * $x + $coeffs[4] * $y + $coeffs[5] * $z;
+               my $nz = $coeffs[6] * $x + $coeffs[7] * $y + $coeffs[8] * $z;
+
+               my $kx = $nx / $nz + (($cam == 2) ? 700 : 0);
+               my $ky = $ny / $nz + (($cam == 2) ? -15 : 0);
+
+               if ($kx >= 0 && $kx < 640 && $ky >= 0 && $ky < 476) {
+                       my $col = int($kx / 213) + 1;
+                       my $row = int($ky / 32) * 2 + 5;
+
+                       my $gnf = $sc{"e$row-${col}sw"};
+                       if (defined($gnf)) {
+                               my ($ra, $ga, $ba) = $gd->rgb($gd->getPixel($x, $y));
+                               my ($rb, $gb, $bb) = $gd->rgb($gnf);
+
+                               my $f = 0.5;
+
+                               my $r = $ra * (1.0 - $f) + $rb * $f;
+                               my $g = $ga * (1.0 - $f) + $gb * $f;
+                               my $b = $ba * (1.0 - $f) + $bb * $f;
+
+                               $gd->setPixel($x, $y, $gd->colorAllocate($r, $g, $b));
+                       }
+               }
+               if ($kx >= 680 && $kx < 1280 && $ky >= 0 && $ky < 476) {
+                       my $col = int(($kx - 680) / 213) + 4;
+                       my $row = int($ky / 32) * 2 + 5;
+
+                       my $gnf = $sc{"e$row-${col}sw"};
+                       if (defined($gnf)) {
+                               my ($ra, $ga, $ba) = $gd->rgb($gd->getPixel($x, $y));
+                               my ($rb, $gb, $bb) = $gd->rgb($gnf);
+
+                               my $f = 0.5;
+
+                               my $r = $ra * (1.0 - $f) + $rb * $f;
+                               my $g = $ga * (1.0 - $f) + $gb * $f;
+                               my $b = $ba * (1.0 - $f) + $bb * $f;
+
+                               $gd->setPixel($x, $y, $gd->colorAllocate($r, $g, $b));
+                       }
+               }
+               if ($kx >= 0 && $kx < 640 && $ky >= 510 && $ky < 1050) {
+                       my $col = int($kx / 213) + 1;
+                       my $row = int($ky / 32) * 2 + 5;
+
+                       my $gnf = $sc{"e$row-${col}sw"};
+                       if (defined($gnf)) {
+                               my ($ra, $ga, $ba) = $gd->rgb($gd->getPixel($x, $y));
+                               my ($rb, $gb, $bb) = $gd->rgb($gnf);
+
+                               my $f = 0.5;
+
+                               my $r = $ra * (1.0 - $f) + $rb * $f;
+                               my $g = $ga * (1.0 - $f) + $gb * $f;
+                               my $b = $ba * (1.0 - $f) + $bb * $f;
+
+                               $gd->setPixel($x, $y, $gd->colorAllocate($r, $g, $b));
+                       }
+               }
+               if ($kx >= 680 && $kx < 1280 && $ky >= 510 && $ky < 1050) {
+                       my $col = int(($kx - 680) / 213) + 4;
+                       my $row = int($ky / 32) * 2 + 5;
+
+                       my $gnf = $sc{"e$row-${col}sw"};
+                       if (defined($gnf)) {
+                               my ($ra, $ga, $ba) = $gd->rgb($gd->getPixel($x, $y));
+                               my ($rb, $gb, $bb) = $gd->rgb($gnf);
+
+                               my $f = 0.5;
+
+                               my $r = $ra * (1.0 - $f) + $rb * $f;
+                               my $g = $ga * (1.0 - $f) + $gb * $f;
+                               my $b = $ba * (1.0 - $f) + $bb * $f;
+
+                               $gd->setPixel($x, $y, $gd->colorAllocate($r, $g, $b));
+                       }
+               }
+       }
+}
+
+
+print CGI::header(-type=>'image/png', -refresh=>'10; http://nms.tg05.gathering.org/overlay.pl?cam=' . $cam);
+print $gd->png;
+
+sub get_color {
+        my $intensity = shift;
+        my $gamma = 1.0/1.90;
+        if ($intensity > 1.0) {
+                return $gd->colorAllocate(255.0, 255.0 * ((2.0 - $intensity) ** $gamma), 0);
+        } else {
+                return $gd->colorAllocate(255.0 * ($intensity ** $gamma), 255, 0);
+        }
+}
+
diff --git a/web/portkart.pl b/web/portkart.pl
new file mode 100755 (executable)
index 0000000..24a26ec
--- /dev/null
@@ -0,0 +1,71 @@
+#! /usr/bin/perl
+use CGI;
+use GD;
+use DBI;
+my $cgi = CGI->new;
+
+my $dbh = DBI->connect("dbi:Pg:dbname=snmpfetch;host=violet.tg05.gathering.org", "snmpfetch", "removed")
+        or die "Couldn't connect to database";
+
+GD::Image->trueColor(1);
+$img = GD::Image->new('snmp-bg.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(32,$y,53,$y+1,$clr);
+}
+
+my $q = $dbh->prepare('select switch,port,bytes_in,bytes_out,placement,switchtype from switches natural join placements natural join get_current_datarate() where switchtype in (\'es3024\')');
+$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 = 20_000_000.0;   # 100mbit
+               my $min =    100_000.0;   # 100kbit
+               if ($traffic >= $min) {
+                       $intensity = 2.0 * (log($traffic / $min) / log(10)) / (log($max / $min) / log(10));
+                       $intensity = 2.0 if ($intensity > 2.0);
+               }
+               $clr = get_color($intensity);
+       } else {
+               $clr = $img->colorResolve(0, 0, 255);
+       }
+       
+       $ref->{'placement'} =~ /\((\d+),(\d+)\),\((\d+),(\d+)\)/;
+       my $npo = ($ref->{'switchtype'} eq 'es3024') ? 26 : 25;
+       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 > 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/sendsms.pl b/web/sendsms.pl
new file mode 100755 (executable)
index 0000000..86b80ef
--- /dev/null
@@ -0,0 +1,55 @@
+#!/usr/bin/perl
+#
+
+use HTTP::Cookies;
+use LWP::UserAgent;
+use Data::Dumper;
+use strict;
+use warnings;
+
+my $uname = "eirikn";
+my $pass = "removed";
+
+my $ua = new LWP::UserAgent;
+$ua->timeout(15);
+$ua->agent('Mozilla/5.0');
+
+#$ua->credentials( "http://zepo.tg05.gathering.org", "/", $uname, $pass );
+
+my $content;
+my %form;
+$form{'userid'} = $uname;
+$form{'next'} = "Look me up";
+
+#my $content = $ua->get("http://zepo.tg05.gathering.org/");
+
+
+$content = $ua->post("http://zepo.tg05.gathering.org/login", \%form);
+
+if (!defined($content->{'_headers'}{'location'})) {
+       die "Could not find dudes";
+}
+$content->{'_headers'}{'set-cookie'} =~ /SID=(\w+);/;
+my $sessioncookie = $1;
+$content = $ua->get("https://partyticket.net/enter?dude_id=39457&got=it", "cookie" => "SID=".$sessioncookie.";");
+
+$content->{'_headers'}{'set-cookie'} =~ /SID=(\w+);/;
+$sessioncookie = $1;
+
+print Dumper($content);
+
+$form{'password'} = $pass;
+$form{'userid'} = 39457;
+$form{'next'} = "Log in";
+$content = $ua->post("https://zepo.tg05.gathering.org/enter&got=it", "cookie" => "SID=".$sessioncookie, \%form);
+
+print Dumper($content);
+
+
+
+
+sub getpage {
+       my ($page) = @_;
+
+       
+}
diff --git a/web/showswitch.pl b/web/showswitch.pl
new file mode 100755 (executable)
index 0000000..7dd716c
--- /dev/null
@@ -0,0 +1,215 @@
+#! /usr/bin/perl
+use CGI;
+use DBI;
+use Time::HiRes;
+use POSIX ":sys_wait_h";
+use strict;
+use warnings;
+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 = DBI->connect("dbi:Pg:dbname=snmpfetch;host=violet.tg05.gathering.org", "snmpfetch", "removed")
+        or die "Couldn't connect to database";
+
+# 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 polls natural join switches natural left join portnames where time between now() - \'1 day\'::interval and now() and switch=? order by switch,port,time;');
+$q->execute($switch);
+
+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) {
+               # 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);
+       }
+
+       # 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);
+
+my $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/smanagement.pl b/web/smanagement.pl
new file mode 100755 (executable)
index 0000000..ce270c3
--- /dev/null
@@ -0,0 +1,273 @@
+#!/usr/bin/perl
+#
+#
+
+my $username = '';
+my $password = 'removed';
+
+# Seconds to wait for connection
+my $timeout = 15;
+
+
+use warnings;
+use strict;
+use Switch;
+use CGI;
+use Net::Telnet;
+use DBI;
+use Data::Dumper;
+
+# Grab from .htaccess-authentication
+my $user = $ENV{'REMOTE_USER'};
+
+my $dbh = DBI->connect("dbi:Pg:dbname=snmpfetch;host=violet.tg05.gathering.org",
+                       "snmpfetch", "removed")
+       or die "Couldn't connect to database";
+$dbh->{AutoCommit} = 0;
+
+# Ugly casting, found not other way
+my $sinsert = $dbh->prepare(   "INSERT INTO squeue 
+                               (gid, added, priority, addr, sysname, cmd, author)
+                               VALUES(?::text::int, now(), ?::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");
+
+# Send a command to switch and return the data recvied from the switch
+sub switch_exec($$) {
+       my ($cmd, $conn) = @_;
+
+       # Send the command and get data from switch
+       my @data = $conn->cmd($cmd);
+       my @lines = ();
+       foreach my $line (@data) {
+               # Remove escape-7 sequence
+               $line =~ s/\x1b\x37//g;
+               push (@lines, $line);
+       }
+
+       return @lines;
+}
+
+sub switch_connect($) {
+       my ($ip) = @_;
+
+       my $conn = new Net::Telnet(     Timeout => $timeout,
+                                       Errmode => 'return',
+                                       Prompt => '/(es3024|e\d+\-\dsw)>/i');
+       my $ret = $conn->open(  Host => $ip);
+       if (!$ret || $ret != 1) {
+               return (0);
+       }
+       # XXX: Just send the password as text, I did not figure out how to
+       # handle authentication with only password through $conn->login().
+       #$conn->login(  Prompt => '/password[: ]*$/i',
+       #               Name => $password,
+       #               Password => $password);
+       $conn->cmd($password);
+       # Get rid of banner
+       $conn->get;
+       return ($conn);
+}
+
+sub parse_range($) {
+       my $switches = $_;
+       my @range;
+
+       my @rangecomma = split(/\s*,\s*/, $switches);
+       foreach (@rangecomma) {
+               my ($first, $drop1, $last, $drop2) = $_ =~ /(e\d+\-[123456])(sw)?\s*\-\s*(e\d+\-[123456])?(sw)?/;
+               if (!defined($first) && $_ =~ /e\d+\-[123456]/) {
+                       $first = $_;
+               }
+               if (!defined($first)) {
+                       print "<font color=\"red\">Parse error in: $_</font><br>\n";
+                       next;
+               }
+               my ($rowstart, $placestart) = $first =~ /e(\d+)\-([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+)\-([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."sw");
+       if ($sgetip->rows() < 1) {
+               print "Could not get the ip for: ".$sysname."sw";
+               return undef;
+       }
+       my $row = $sgetip->fetchrow_hashref();
+       return $row->{'ip'};
+}
+
+my $cgi = new CGI;
+
+print $cgi->header(-type=>'text/html');
+
+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>Disabled</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>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"></textarea></td>
+       <td>En kommando per linje</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 = ();
+               print "<font color=\"red\">Slått av!</font>\n";
+       }
+       case 'switch' {
+#              print "Sender `".$cgi->param('cmd')."` til switchene `"
+#                    .$cgi->param('range')."`.<br />";
+               $_ = $cgi->param('range');
+               @switches = parse_range($_);
+       }
+       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;
+       }
+       print "$switch got addr $addr <br>\n";
+       my @cmds = split(/[\n\r]+/, $cgi->param('cmd'));
+       print "Queuing commands for $switch:\n";
+       foreach my $cmd (@cmds) {
+               my $result = $sinsert->execute($gid, $pri, $addr, $switch, $cmd, $user);
+       #       my $result = 1;
+               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/snmp-bg.png b/web/snmp-bg.png
new file mode 100644 (file)
index 0000000..a63a19e
Binary files /dev/null and b/web/snmp-bg.png differ
diff --git a/web/ssendfile.pl b/web/ssendfile.pl
new file mode 100755 (executable)
index 0000000..d64de05
--- /dev/null
@@ -0,0 +1,91 @@
+#!/usr/bin/perl
+#
+#
+
+use warnings;
+use strict;
+use Net::Telnet;
+use POSIX;
+
+my $password = 'removed';
+my $timeout = 15;
+my $delaytime = 30;
+my $poll_frequency = 60;
+
+# Send a command to switch and return the data recvied from the switch
+sub switch_exec($$) {
+       my ($cmd, $conn) = @_;
+
+       # Send the command and get data from switch
+       my @data = $conn->cmd($cmd);
+       my @lines = ();
+       foreach my $line (@data) {
+               # Remove escape-7 sequence
+               $line =~ s/\x1b\x37//g;
+               push (@lines, $line);
+       }
+
+       return @lines;
+}
+
+sub switch_connect($) {
+       my ($ip) = @_;
+
+#                                      Dump_Log => '/tmp/dumplog-queue',
+       my $conn = new Net::Telnet(     Timeout => $timeout,
+                                       Errmode => 'return',
+                                       Prompt => '/(es3024|e\d+\-\dsw)>/i');
+       my $ret = $conn->open(  Host => $ip);
+       if (!$ret || $ret != 1) {
+               return (undef);
+       }
+       # XXX: Just send the password as text, I did not figure out how to
+       # handle authentication with only password through $conn->login().
+       #$conn->login(»·Prompt => '/password[: ]*$/i',
+       #               Name => $password,
+       #               Password => $password);
+       $conn->cmd($password);
+       # Get rid of banner
+       $conn->get;
+       return ($conn);
+}
+
+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 = 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 = switch_connect($1);
+#              if (!defined($conn)) {
+#                      die "Could not connect to new ip: $1\n";
+#              }
+#      }
+#      else {
+               my @data = switch_exec($cmd, $conn);
+               foreach my $line (@data) {
+                       $line =~ s/[\r\n]+//g;
+                       print "$line\n";
+               }
+#      }
+}
diff --git a/web/sshow.pl b/web/sshow.pl
new file mode 100755 (executable)
index 0000000..32a8306
--- /dev/null
@@ -0,0 +1,269 @@
+#!/usr/bin/perl
+#
+#
+
+my $username = '';
+my $password = 'removed';
+
+# Seconds to wait for connection
+my $timeout = 15;
+
+use warnings;
+use strict;
+use Switch;
+use CGI;
+use Net::Telnet;
+use DBI;
+
+# Grab from .htaccess-authentication
+my $user = $ENV{'REMOTE_USER'};
+
+my $dbh = DBI->connect("dbi:Pg:dbname=snmpfetch;host=violet.tg05.gathering.org",
+                       "snmpfetch", "removed")
+       or die "Couldn't connect to database";
+$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');
+
+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";
+       }
+       if ($cgi->param('agid') eq 'Disable') {
+               $sdisablegid->execute($gid);
+               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/stemp-bg5.png b/web/stemp-bg5.png
new file mode 100644 (file)
index 0000000..e48227a
Binary files /dev/null and b/web/stemp-bg5.png differ
diff --git a/web/stempmap-ptn.pl b/web/stempmap-ptn.pl
new file mode 100755 (executable)
index 0000000..3522b51
--- /dev/null
@@ -0,0 +1,57 @@
+#!/usr/bin/perl
+#
+#
+
+use CGI;
+use GD;
+use DBI;
+use strict;
+use warnings;
+
+my $img = GD::Image->new('stemp-bg5.png');
+my $cgi = CGI->new;
+
+my $dbh = DBI->connect("dbi:Pg:dbname=snmpfetch;host=violet.tg05.gathering.org", "snmpfetch", "removed")
+       or die "Couldn't connect to database";
+
+my $black = $img->colorAllocate(0,0,0);
+my $white = $img->colorAllocate(255,255,255);
+my $green = $img->colorAllocate(0,255,0);
+my $blue = $img->colorAllocate(0,0,255);
+
+my $avrgtemp = 54;
+my $mintemp = 10.0;
+my $maxtemp = 80.0;
+
+my $color = &getcolor($avrgtemp);
+
+for (my $i = $mintemp; $i <= $maxtemp; $i++) {
+       $img->line(600, 220 + $i - $mintemp, 645, 220 + $i - $mintemp, &getcolor($i));
+}
+
+$img->string(gdMediumBoldFont, 600, 200, "Freezing!$mintemp", $black);
+$img->string(gdMediumBoldFont, 600, 210, "$mintemp C", $black);
+$img->string(gdMediumBoldFont, 600, 220 + $maxtemp, "Too hot! $maxtemp", $black);
+$img->string(gdMediumBoldFont, 600, 210 + $maxtemp, "$maxtemp C", $black);
+
+my $px = 5;
+my $py = 30;
+
+#$img->stringUp(gdGiantFont,$px,$py - 2,"$avrgtemp",$white);
+$img->filledRectangle($px - 0, $py - 17, $px + 12, $py + 5, $white);
+$img->stringUp(gdLargeFont,$px - 4,$py - 1,"$avrgtemp",$blue);
+$img->rectangle($px, $py, $px + 7,$py + 7,$black);
+$img->filledRectangle($px + 1, $py + 1, $px + 6, $py + 6,$color);
+
+print $cgi->header(-type=>'image/png');
+print $img->png;
+
+sub getcolor {
+       my ($temp) = @_;
+
+       my $percent = ($temp - $mintemp) / ($maxtemp - $mintemp);
+       my $colorred = 255 * $percent;
+       my $colorblue = 255 - $colorred;
+
+       return $img->colorAllocate($colorred, $colorblue, 0);
+}
diff --git a/web/stempmap.pl b/web/stempmap.pl
new file mode 100755 (executable)
index 0000000..b2df70b
--- /dev/null
@@ -0,0 +1,96 @@
+#!/usr/bin/perl
+#
+#
+
+use CGI;
+use GD;
+use DBI;
+use strict;
+use warnings;
+
+GD::Image->trueColor(1);
+
+my $img = GD::Image->new('snmp-bg.png');
+#my $img = GD::Image->new(100,100);
+my $cgi = CGI->new;
+
+my $dbh = DBI->connect("dbi:Pg:dbname=snmpfetch;host=violet.tg05.gathering.org", "snmpfetch", "removed")
+       or die "Couldn't connect to database";
+
+my $sgetpoll = $dbh->prepare('select switch,(select temp from temppoll where switches.switch=temppoll.switch AND temp != 0 order by id desc limit 1) AS temp,placement from switches natural join placements');
+
+my $black = $img->colorAllocate(0,0,0);
+my $white = $img->colorAllocate(255,255,255);
+my $green = $img->colorAllocate(0,255,0);
+my $blue = $img->colorAllocate(0,0,255);
+
+my $avrgtemp = 54.5;
+my $mintemp = 30.0;
+my $maxtemp = 55.0;
+my $steps = 100;
+
+my $color = &getcolor($avrgtemp);
+
+open (OUT, "> /tmp/outtemps");
+for (my $i = 0; $i < $steps; $i++) {
+       my $diff = $maxtemp - $mintemp;
+       my $temp = $mintemp + ($maxtemp - $mintemp) * ((($diff / $steps) * $i)/$diff);
+       $img->line(5, $i, 45, $i, &getcolor2($temp));
+}
+close(OUT);
+
+$img->string(gdMediumBoldFont, 50, 0, "Freezing!", $black);
+$img->string(gdMediumBoldFont, 50, $steps - 11, "Too hot!", $black);
+$img->string(gdMediumBoldFont, 50, 12, "$mintemp C", $black);
+$img->string(gdMediumBoldFont, 50, $steps - 22, "$maxtemp C", $black);
+
+#$img->string(gdMediumBoldFont, 600, 200, "Freezing!$mintemp", $black);
+#$img->string(gdMediumBoldFont, 600, 210, "$mintemp C", $black);
+#$img->string(gdMediumBoldFont, 600, 220 + $maxtemp, "Too hot! $maxtemp", $black);
+#$img->string(gdMediumBoldFont, 600, 210 + $maxtemp, "$maxtemp C", $black);
+
+
+$sgetpoll->execute();
+while (my $ref = $sgetpoll->fetchrow_hashref()) {
+       next if (!defined($ref->{'temp'}));
+
+       $ref->{'placement'} =~ /\((\d+),(\d+)\),\((\d+),(\d+)\)/;
+       $avrgtemp = $ref->{'temp'};
+       my $px = $3;
+       my $py = $4 + 16;
+       my $roundtemp = sprintf ("%.0f", $avrgtemp);
+       $color = getcolor($avrgtemp);
+       $img->filledRectangle($px - 0, $py - 17, $px + 12, $py + 5, $white);
+       $img->stringUp(gdGiantFont,$px - 1,$py - 1,"$roundtemp",$blue);
+       $img->rectangle($px, $py, $px + 10,$py + 10,$black);
+       $img->filledRectangle($px + 1, $py + 1, $px + 9, $py + 9,$color);
+}
+
+print $cgi->header(-type=>'image/png');
+print $img->png;
+
+sub getcolor {
+       my ($temp) = @_;
+
+       my $t = ($temp - $mintemp) / ($maxtemp - $mintemp);
+       $t = 0 if ($t < 0);
+       $t = 1 if ($t > 1);
+
+       my $colorred = 255 * $t;
+       my $colorblue = 255 - $colorred;
+
+       return $img->colorResolve($colorred, 0, $colorblue);
+}
+
+sub getcolor2 {
+       my ($temp) = @_;
+
+       my $t = ($temp - $mintemp) / ($maxtemp - $mintemp);
+       $t = 0 if ($t < 0);
+       $t = 1 if ($t > 1);
+
+       my $colorred = 255 * $t;
+       my $colorblue = 255 - $colorred;
+
+       return $img->colorResolve($colorred, 0, $colorblue);
+}
diff --git a/web/streaming.pl b/web/streaming.pl
new file mode 100755 (executable)
index 0000000..4b12add
--- /dev/null
@@ -0,0 +1,25 @@
+#!/usr/bin/perl
+use GD;
+use CGI;
+use strict;
+
+my $cgi = CGI->new;
+
+GD::Image->trueColor(1);
+my $img = new GD::Image(100,100);
+
+my $wht = $img->colorResolve(0,0,0);
+my $blk = $img->colorResolve(255,255,255);
+my $red = $img->colorResolve(255,0,0);
+my $grn = $img->colorResolve(0,255,0);
+my $blu = $img->colorResolve(0,0,255);
+
+$img->transparent($wht);
+$img->interlaced('true');
+
+$img->string(gdMediumBoldFont,0,0,"TG05 - Streaming",$blu);
+
+print $cgi->header(-type=>'image/png',
+                   -refresh=>'10; http://nms.tg05.gathering.org/streaming.pl');
+print $img->png;
+
diff --git a/web/tempfetch.pl b/web/tempfetch.pl
new file mode 100644 (file)
index 0000000..eed5417
--- /dev/null
@@ -0,0 +1,139 @@
+#! /usr/bin/perl
+#use BER;
+use Data::Dumper;
+use DBI;
+use Net::Telnet;
+use POSIX;
+use Time::HiRes;
+use strict;
+use warnings;
+#require 'SNMP_Session.pm';
+
+# Tweak timeouit og sjekk med :support||:net hva passord vil bli
+my $password = 'removed';
+my $timeout = 25;
+my $location = 'skipet';
+
+my $dbh = DBI->connect("dbi:Pg:dbname=snmpfetch;host=violet.tg05.gathering.org", "snmpfetch", "removed")
+       or die "Couldn't connect to database";
+$dbh->{AutoCommit} = 0;
+
+my $qswitch = $dbh->prepare(<<"EOF")
+SELECT 
+  *
+FROM
+  switches
+  NATURAL LEFT JOIN switchtypes
+WHERE
+  (locked='f' OR now() - last_updated > '15 minutes'::interval)
+LIMIT 1
+FOR UPDATE OF switches
+EOF
+       or die "Couldn't prepare qswitch";
+my $qlock = $dbh->prepare("UPDATE switches SET locked='t', last_updated=now() WHERE switch=?")
+       or die "Couldn't prepare qlock";
+my $qunlock = $dbh->prepare("UPDATE switches SET locked='f', last_updated=now() WHERE switch=?")
+       or die "Couldn't prepare qunlock";
+my $qpoll = $dbh->prepare("INSERT INTO temppoll (time, switch, temp) VALUES (timeofday()::timestamp,?::text::int,?::text::float)")
+       or die "Couldn't prepare qpoll";
+
+while (1) {
+       # Find a switch to grab
+       $qswitch->execute()
+               or die "Couldn't get switch";
+       my $switch = $qswitch->fetchrow_hashref();
+
+       if (!defined($switch)) {
+               $dbh->commit;
+               mylog("No available switches in pool, sleeping.");
+               sleep 60;
+               next;
+       }
+
+       $qlock->execute($switch->{'switch'})
+               or die "Couldn't lock switch";
+       $dbh->commit;
+
+       if ($switch->{'locked'}) {
+               mylog("WARNING: Lock timed out on $switch->{'ip'}, breaking lock");
+       }
+
+       my $msg;
+       if (defined($switch->{'overdue'})) {
+               $msg = sprintf "Polling temp on %s (%s), %s overdue.",
+                       $switch->{'ip'}, $switch->{'sysname'}, $switch->{'overdue'};
+       } else {
+               $msg = sprintf "Polling temp on %s (%s), never polled before.",
+                       $switch->{'ip'}, $switch->{'sysname'};
+       }
+       mylog($msg);
+
+       my $ip = $switch->{'ip'};
+       my $start = [Time::HiRes::gettimeofday];
+       eval {
+               my $conn = switch_connect($ip);
+               if (!defined($conn)) {
+                       print "Could not connect to switch ".$switch->{'switch'}."\n";
+               }
+               my @data = switch_exec('sys monitor status', $conn);
+               my @fields = split(/\s+/, $data[2]);
+               # The temp fields are 6, 7, 8
+               my $avgtemp = ($fields[6] + $fields[7] + $fields[8]) / 3;
+               print $avgtemp." avgtemp\n";
+               $qpoll->execute($switch->{'switch'},
+                               $avgtemp) or die "Could not exec qpoll";
+       };
+       my $elapsed = Time::HiRes::tv_interval($start);
+       $msg = sprintf "Polled $switch->{'ip'} in %5.3f seconds.", $elapsed;
+       mylog($msg);
+
+       $qunlock->execute($switch->{'switch'})
+               or die "Couldn't unlock switch";
+       sleep 1;
+       $dbh->commit;
+}
+
+sub switch_exec {
+       my ($cmd, $conn) = @_;
+
+       # Send the command and get data from switch
+       my @data = $conn->cmd($cmd);
+       my @lines = ();
+       foreach my $line (@data) {
+               # Remove escape-7 sequence
+               $line =~ s/\x1b\x37//g;
+               push (@lines, $line);
+               }
+
+       return @lines;
+}
+
+sub switch_connect {
+       my ($ip) = @_;
+
+       my $conn = new Net::Telnet(     Timeout => $timeout,
+                                       Dump_Log => '/tmp/dumplog',
+                                       Errmode => 'return',
+                                       Prompt => '/(es3024|e\d+\-\dsw)>/i');
+       my $ret = $conn->open(  Host => $ip);
+       if (!$ret || $ret != 1) {
+               return (0);
+       }
+       # XXX: Just send the password as text, I did not figure out how to
+       # handle authentication with only password through $conn->login().
+       #$conn->login(  Prompt => '/password[: ]*$/i',
+       #               Name => $password,
+       #               Password => $password);
+       my @data = $conn->cmd($password);
+       # Get rid of banner
+       $conn->get;
+       return ($conn);
+}
+
+
+sub mylog {
+       my $msg = shift;
+       my $time = POSIX::ctime(time);
+       $time =~ s/\n.*$//;
+       printf STDERR "[%s] %s\n", $time, $msg;
+}