#! /usr/bin/perl # # # use GDBM_File; use POSIX; use GD; init(); read_genesis(); init_output_files(); measure(); plot_nodes(); plot_links(); output_html_dot(); close_files(); fork_mrtgs(); finish(); sub finish { sleep(30); system("/usr/bin/mrtg /home/wleiden/stats/mrtg/users.cfg"); system("/usr/bin/mrtg /home/wleiden/stats/mrtg/total.cfg"); } sub init { $wdir="/home/wleiden/stats/mrtg/output/"; $indexfn="$wdir/index.html"; $statusfn="$wdir/status.html"; $mapfn="/home/wleiden/public_html/nodemap/index.html"; $dotfn="/home/wleiden/stats/mrtg/map.dot"; $psfn="/home/wleiden/stats/mrtg/map.ps"; $xyfile='/home/wleiden/stats/mrtg/xy.gdbm'; $nodemapfn="/home/wleiden/stats/mrtg/nodemap.pl"; $datadir="/home/wleiden/stats/mrtg/data/"; $neato='/usr/bin/neato'; $convert='/usr/bin/convert'; $statusfn2="/home/wleiden/stats/mrtg/status.now"; $svn='/usr/bin/svn'; $genesis_dir='/home/wleiden/svn/genesis'; $maxloadavg=50; $maxage=1300; $fontsize{gdSmallFont}=4; $fontsize{gdGiantFont}=10; $now=localtime(time()); $SIG{CHLD}="IGNORE"; parse_ARGV(); $revision=`$svn info $genesis_dir|grep 'Last Changed Rev:'`; $revision=~s/Last Changed Rev:\s+(\d+)\D*/$1/s; } sub getport { local($node,$essid,$headtail)=@_; local($pdir)=$XY{"DIR_${node}_${essid}"}; if ($pdir ne '') { #print "PDIR{$node}=$pdir ->"; $pdir=int((8*($pdir%360)/360)+.5); #print "$pdir ->"; if ($pdir eq 0) {$pdir='n';} elsif ($pdir eq 1) {$pdir='ne';} elsif ($pdir eq 2) {$pdir='e';} elsif ($pdir eq 3) {$pdir='se';} elsif ($pdir eq 4) {$pdir='s';} elsif ($pdir eq 5) {$pdir='sw';} elsif ($pdir eq 6) {$pdir='w';} elsif ($pdir eq 7) {$pdir='nw';} if ($pdir=~/^(n|e|s|w|ne|nw|se|sw)$/) {$pdir=",${headtail}port=\":$pdir\"";} #print "$pdir -> $port\n"; } return($pdir); } sub ping { local($host)=@_; local($alive)=`/usr/local/sbin/fping $host`; if ($alive=~/alive/) {return(1);} if ($DEBUG) {print "Host down: [$alive]\n";} return(0); } sub create_line { local($master,$slave,$mx,$my,$sx,$sy,$dx,$dy,$dashed,$color,$style,$width,$load)=@_; local($im,$x1,$y1,$x2,$y2); local($result)=0; # $txt.="($mx,$my;$sx,$sy) = $color"; if ($color eq 'red') {$R=255;$G=$B=0;} elsif ($color eq 'green') {$R=0;$G=255;$B=0;} elsif ($color eq 'orange') {$R=255;$G=165;$B=0;} elsif ($color eq 'grey') {$R=150;$G=150;$B=150;} elsif ($color eq 'blue') {$R=0;$G=0;$B=255;} elsif ($color eq 'yellow') {$R=255;$G=200;$B=0;} if ($load ne '') { if ($load <= 0) {$R=0;$G=180;$B=0;} elsif ($load < 1) {$l=($load)*180;$R=0;$G=180;$B=$l;} elsif ($load < 2) {$l=($load-int($load))*180;$R=0;$G=180-$l;$B=180;} else {$l=($load-int($load))*30;$R=$l;$G=0;$B=180;} } $len=int(sqrt(($dx*$dx)+($dy*$dy))); #if ($HIRES) {print "Length $master-$slave = $len\n";} if ($len>19) { #print "$master($mx,$my) --> $slave($sx,$sy) ==> ($dx,$dy)=> $len\n"; $im = new GD::Image($dx+1,$dy+1); $COLOR{$white} = $im->colorAllocate(255,255,255); $COLOR{$black} = $im->colorAllocate(0,0,0); $COLOR{$red} = $im->colorAllocate(255,0,0); $COLOR{$green} = $im->colorAllocate(0,255,0); $COLOR{$orange} = $im->colorAllocate(255,200,0); $COLOR{$gray} = $im->colorAllocate(150,150,150); $COLOR{$blue} = $im->colorAllocate(0,0,255); $COLOR{$ltblue} = $im->colorAllocate(0x87,0xce,255); $COLOR{$margenta} = $im->colorAllocate(255,0,255); $COLOR{$cyan} = $im->colorAllocate(0,150,255); $COLOR{$yellow} = $im->colorAllocate(255,200,0); $im->transparent($w); # $im->rectangle(0,0,$dx,$dy,$COLOR{$black}); $COLOR{"gdStyled"}=gdStyled; if ($style eq 1) {mysetStyle("(\$COLOR{$color}) x 10 , (gdTransparent) x 5");$color="gdStyled";$width=0;} if ($style eq 2) {mysetStyle("(\$COLOR{$color}) x 8 , (gdTransparent) x 8");$color="gdStyled";$width=0;} if ($style eq 3) {mysetStyle("(\$COLOR{$color}) x 5 , (gdTransparent) x 10");$color="gdStyled";$width=0} if ((($sx > $mx) && ($sy > $my)) || (($sx < $mx) && ($sy < $my))) {$x1=0;$y1=0;$x2=$dx;$y2=$dy;$result=1;} else {$x1=0;$y1=$dy;$x2=$dx;$y2=0;$result=2;} if ($load ne '') {$color=RGB($R,$G,$B);} if ($HISTORY) { if ($color eq $red) {$color=$blue;$dashed=0;$width=2;} elsif ($color ne $gray) {$color=$blue;$width=2;} elsif ($HIRES) {$color=$gray;$dashed=0;$width=2;} if ($RIJNLAND) {$width=1;} } if ($dashed) {mydashedLine($x1,$y1,$x2,$y2,$color);} else { myline($x1,$y1,$x2,$y2,$color); if ($width>0) { if ($dx>$dy) {myline($x1,$y1-1,$x2,$y2-1,$color); myline($x1,$y1+1,$x2,$y2+1,$color);} else {myline($x1-1,$y1,$x2-1,$y2,$color); myline($x1+1,$y1,$x2+1,$y2,$color);} } if ($width>1) { if ($dx>$dy) {myline($x1,$y1-2,$x2,$y2-2,$color); myline($x1,$y1+2,$x2,$y2+2,$color);} else {myline($x1-2,$y1,$x2-2,$y2,$color); myline($x1+2,$y1,$x2+2,$y2,$color);} } } if (($HISTORY eq 0) && ($HIRES eq 0)) { $fn="/home/wleiden/public_html/nodemap/links/$link.png"; open (PNG,">$fn") || die "$! $fn\n"; print PNG $im->png; close(PNG); } return($result); } else { print IMAGE "### link $master-$slave to short: $len\n"; } return(0); } sub mysetStyle { local($e)=@_; $im->setStyle(eval($e)); print IMAGE " \$nm->setStyle($e);\n"; } sub myline { local($x1,$y1,$x2,$y2,$color)=@_; $im->line($x1,$y1,$x2,$y2,$COLOR{$color}); print IMAGE " \$nm->line($x+$x1,$y+$y1,$x+$x2,$y+$y2,\$COLOR{$color}); # $lname\n"; } sub mydashedLine { local($x1,$y1,$x2,$y2,$color)=@_; $im->dashedLine($x1,$y1,$x2,$y2,$COLOR{$color}); local($dx)=abs($x1-$x2); local($dy)=abs($y1-$y2); if (($dx>50) && ($dy>50)) # Work around bug in GD, small slope line becomes block. { print IMAGE " \$nm->dashedLine($x+$x1,$y+$y1,$x+$x2,$y+$y2,\$COLOR{$color}); # $lname\n"; } else { print IMAGE " \$nm->line($x+$x1,$y+$y1,$x+$x2,$y+$y2,\$COLOR{$color}); # $lname\n"; } } sub MIN { local($a,$b)=@_; if ($a < $b) {return($a);} return($b); } sub MAX { local($a,$b)=@_; if ($a > $b) {return($a);} return($b); } sub RGB { local($R,$G,$B)=@_;$R=floor($R+.5);$G=floor($G+.5);$B=floor($B+.5); $COLOR{"mycolor"} = $im->colorAllocate($R,$G,$B); #print "$load=> R=$R G=$G B=$B\n"; print IMAGE "\n \$COLOR{mycolor}=\$nm->colorAllocate($R,$G,$B);\n"; return("mycolor"); } sub read_genesis { chdir("/home/wleiden/svn/genesis/nodes/") || die "$! /home/wleiden/svn/genesis/nodes/\n"; foreach $node (<*/wleiden.conf>) { #$node=~s/\.pl$//; $node=~s/\/wleiden\.conf//gi; if ($node=~/(demo|test|vuilnis)/) {next;} push(@NODES,$node); } $nodes=join(" ",sort @NODES); } sub parse_ARGV { #LIMITS $xm=90100; $xM=97970; $ym=461050; $yM=466800; $RIJNLAND=0; if ($ARGV[0] eq 'DEBUG') {shift(@ARGV); $DEBUG=1;print "DEBUG\n";} else {$DEBUG=0;} if ($ARGV[0] eq 'HISTORY') {shift(@ARGV);$DEBUG=1;$HISTORY=1;print "HISTORY\n";$nodemapfn="/home/wleiden/stats/mrtg/history.pl";} else {$HISTORY=0;} if ($ARGV[0] eq 'HIRES') {shift(@ARGV);$DEBUG=1;$HIRES=1;print "HIRES\n";$nodemapfn="/home/wleiden/stats/mrtg/hires.pl";$FONT='gdGiantFont'; if ($ARGV[0] eq 'RIJNLAND') #Usage: mrtg.pl HIRES RIJNLAND { shift(@ARGV); print "RIJNLAND\n"; $RIJNLAND=1; #LIMITS $xm=85000; $xM=111250; $ym=450000; $yM=480000; $nodedia=5; $nodemapfn="/home/wleiden/stats/mrtg/rijnland.pl"; print "NMFN=$nodemapfn\n"; } else { #LIMITS $xm=90100; $xM=98450; $ym=459550; $yM=469700; $nodedia=15; } } else {$RIJNLAND=$HIRES=0;$FONT='gdSmallFont';} } sub init_output_files { print "Opening $nodemapfn.$$\n"; open (IMAGE,">${nodemapfn}.$$") || die "Could not create ${nodemapfn}.$$\n"; $black="black";$red="red";$white="white";$gray="gray";$green="green"; $orange="orange";$blue="blue";$margenta="margenta";$cyan="cyan";$yellow="yellow"; $ltblue='ltblue'; $DCOLOR{$white} = sprintf("#%02x%02x%02x",255,255,255); $DCOLOR{$black} = sprintf("#%02x%02x%02x",0,0,0); $DCOLOR{$red} = sprintf("#%02x%02x%02x",255,0,0); $DCOLOR{$green} = sprintf("#%02x%02x%02x",0,255,0); $DCOLOR{$orange} = sprintf("#%02x%02x%02x",255,165,0); $DCOLOR{$gray} = sprintf("#%02x%02x%02x",150,150,150); $DCOLOR{$blue} = sprintf("#%02x%02x%02x",0,0,255); $DCOLOR{$margenta} = sprintf("#%02x%02x%02x",255,0,255); $DCOLOR{$cyan} = sprintf("#%02x%02x%02x",0,150,255); $DCOLOR{$yellow} = sprintf("#%02x%02x%02x",255,200,0); if ($HIRES) { if ($RIJNLAND) {$leiden='hires_kaart_rijnland_50.png';$dia=20;} else {$leiden='hires_kaart_leiden_51.png';$dia=50;} } else {$leiden='leiden4.png';$dia=20;} print IMAGE <colorAllocate(255,255,255); \$w->fill(10,10,\$wc); \$nm = new GD::Image(\$fn) || die "Could not open file: \$fn\\n"; (\$width,\$heigth)=\$nm->getBounds(); for (\$x=0;\$x<\$width;\$x++) { \$nm->copy(\$w,\$x,0,0,0,$dia,$dia); \$nm->copy(\$w,\$x,\$heigth-$dia,0,0,$dia,$dia); } for (\$y=0;\$y<\$heigth;\$y++) { \$nm->copy(\$w,0,\$y,0,0,$dia,$dia); \$nm->copy(\$w,\$width-$dia,\$y,0,0,$dia,$dia); } \$COLOR{$white} = \$nm->colorAllocate(255,255,255); \$COLOR{$black} = \$nm->colorAllocate(0,0,0); \$COLOR{$red} = \$nm->colorAllocate(255,0,0); \$COLOR{$green} = \$nm->colorAllocate(0,255,0); \$COLOR{$orange} = \$nm->colorAllocate(255,165,0); \$COLOR{$gray} = \$nm->colorAllocate(150,150,150); \$COLOR{$blue} = \$nm->colorAllocate(0,0,255); \$COLOR{$margenta} = \$nm->colorAllocate(255,0,255); \$COLOR{$cyan} = \$nm->colorAllocate(0,150,255); \$COLOR{$yellow} = \$nm->colorAllocate(255,200,0); \$COLOR{$ltblue} = \$nm->colorAllocate(180,180,255); \$COLOR{"gdStyled"}=gdStyled; \$bludot=GD::Image->new("images/bludot10.png"); \$reddot=GD::Image->new("images/reddot10.png"); \$gredot=GD::Image->new("images/gredot10.png"); \$grydot=GD::Image->new("images/grydot10.png"); \$orgdot=GD::Image->new("images/orgdot10.png"); \$yeldot=GD::Image->new("images/yeldot10.png"); EOI open(INDEX,">${indexfn}.$$") || die "Could not create file: ${indexfn}.$$\n"; open(STATUS,">${statusfn}.$$") || die "Could not create file: ${statusfn}.$$\n"; open(MAP,">${mapfn}.$$") || die "Could not create file: ${mapfn}.$$\n"; open(DOT,">${dotfn}.$$") || die "Could not create file: ${dotfn}.$$\n"; print INDEX <
  • total traffic
  • users
  • nodemap

    EOH print DOT <&1 |") || die "$! /usr/local/sbin/fping\n"; while () { $node=''; if (/^(\S+) is alive/) { $node=$1;$status='';$online++; $file="/home/wleiden/stats/mrtg/data/${node}.gdbm.debug"; if ( -e $file) { ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, $atime,$mtime,$ctime,$blksize,$blocks) = stat($file); $age=time()-$mtime; } else {$age=-1;open (TOUCH,">$file");close (TOUCH);} print "Age = $age\n"; $ps=`ps auwx|grep $node`; if ($ps=~/^(\S+)\s+(\d+).*\/usr\/local\/bin\/mrtg \/home\/wleiden\/stats\/mrtg\/cfg\/$node.cfg/m) { $PID=$2; #print "PID=$2 [$file]\n"; if ($age > 300) {kill(11,$PID);} } if ($age < 0) { $S{$node}="pingable"; } if ($age > $maxage) {$S{$node}="pingable";} else {$S{$node}="online";} if ($DEBUG) {print "$S{$node}: $node (age=$age)\n";} } elsif (/^(\S+) is unreachable/) { $node=$1;$file="/home/wleiden/stats/mrtg/data/${node}.gdbm.debug"; if (-e $file) {$offline++;$S{$node}="offline";if ($DEBUG) {print "Offline: $node [$file]\n";}} else {$constr++;$S{$node}="constr";if ($DEBUG) {print "Constr: $node\n";}} } elsif (/^(\S+) address not found/) { $node=$1; $constr++;$S{$node}="constr";if ($DEBUG) {print "Constr: $node\n";} } print STATUS "$node=$status\n"; #print "$node = $status\n"; } close(FPING); } } # DEBUG sub plot_nodes { tie %XY,'GDBM_File',"$xyfile", &GDBM_READER, 0640 || die "Could not tie $xyfile\n"; $divs=$positions='';$counter=$ncounter=0; $min_ox=$max_ox=$min_oy=$max_oy=0; foreach $node (sort @NODES) { $txt='';$name=$node;$name=~s/^.node//i; $S=$S{$node}; if ($S eq 'online') {$color='gre';$ncolor=sprintf("#%02x%02x%02x",0,255,0);} elsif ($S eq 'pingable') {$color='blu';$ncolor=sprintf("#%02x%02x%02x",0,0,255);} elsif ($S eq 'offline') {$color='red';$ncolor=sprintf("#%02x%02x%02x",255,0,0);} elsif ($S eq 'constr') {$color='gry';$ncolor=sprintf("#%02x%02x%02x",150,150,150);} else {$color='org';$ncolor=sprintf("#%02x%02x%02x",255,165,0);} $NCOLOR{$node}=$ncolor; #print "STATUS: $node:$S:$color\n"; $X=$Y=0; ($X,$Y)=split(/:/,$XY{"$node-XY"}); ($RealX,$RealY)=split(/:/,$XY{"$node-RXY"}); if ($RealX) {$X=$RealX;$Y=$RealY;} $OrigX=$X;$OrigY=$Y; $labelpos=$XY{"$node-labelpos"}; if (($X < $xm) || ($X > $xM) || ($Y < $ym) || ($Y > $yM)) { if (($X > 0) && ($Y>0)) { $counter=0; print "MAPLIMIT: $node ($X,$Y) ->"; if ($X > $xM) {$X=$xM-(($counter %10)*400);} elsif ($X < $xm) {$X=$xm+-(($counter %10)*400);} if ($Y > $yM) {$Y=$yM-int($counter/10)*400;} elsif ($Y < $ym) {$Y=$ym+int($counter/10)*400;} print "($X,$Y)\n"; } else { $txt.="$name"; $x=$xM-(($counter %10)*400); $y=$ym+int($counter/10)*400; } $counter++; } { if ($HIRES) { if ($RIJNLAND) { # uit concat.pl: #$x=99250; #$y=463750; #$width=10; #$heigth=12; #$scale=4; #$step=2500; $OX=( 87500-(floor(10/2)*500)); # ++ = <- 87000 $OY=(474500+(floor(12/2)*500)); # ++ = down 474500 $x=floor(.5+($X-$OX)/25); $y=floor(.5+($OY-$Y)/25)+100; } else { # uit concat.pl: #$x=94000; #$y=464500; #$width=17; #$heigth=21; #step=500 $OX=(94000-(floor(17/2)*500)); $OY=(464500+(floor(21/2)*500)); $x=floor(.5+($X-$OX)/5); $y=floor(.5+($OY-$Y)/5)+100; } } else { $x=floor(.5+($X-90000)/10); $y=floor(.5+(467000-$Y)/10); } } $x{$node}=$x;$y{$node}=$y; $ox{$node}=$OrigX;$oy{$node}=$OrigY; if (($min_ox == 0) || ($ox{$node} < $min_ox)) {$min_ox=$ox{$node};} if (($max_ox == 0) || ($ox{$node} > $max_ox)) {$max_ox=$ox{$node};} if (($min_oy == 0) || ($oy{$node} < $min_oy)) {$min_oy=$oy{$node};} if (($max_oy == 0) || ($oy{$node} > $max_oy)) {$max_oy=$oy{$node};} $diameter=10/2; $x-=$diameter;$y-=$diameter; $positions.=sprintf < $node
    $txt
    EOP $hist_color=$color; if (($HISTORY)) # || ($HIRES)) { if ($hist_color=~/(gre|blu|red)/) {$hist_color='gre';$hicolor="green";} else {$hicolor="gray";} } else { if ($color eq 'red') {$hicolor='red';} elsif ($color eq 'gre') {$hicolor='green';} elsif ($color eq 'blu') {$hicolor='ltblue';} else {$color='gray';} } if ($HIRES) { if ($node=~/proxy/) {next;} $DOTS.=sprintf " \$nm->arc($x{$node},$y{$node},$nodedia+1,$nodedia+1,0,360,\$COLOR{black}); # $node\n"; $DOTS.=sprintf " \$nm->arc($x{$node},$y{$node},$nodedia+2,$nodedia+2,0,360,\$COLOR{black}); # $node\n"; $DOTS.=sprintf " \$nm->arc($x{$node},$y{$node},$nodedia+3,$nodedia+3,0,360,\$COLOR{black}); # $node\n"; # $DOTS.=sprintf " \$nm->fill($x{$node},$y{$node},\$COLOR{$hicolor}); # $node\n"; for ($i=0;$i<$nodedia;$i++) { $DOTS.=sprintf " \$nm->arc($x{$node},$y{$node},$i,$i,0,360,\$COLOR{$hicolor}); # $node\n"; } } else { $DOTS.=sprintf " \$nm->copy(\$${hist_color}dot,$x,$y,0,0,10,10); # $node\n"; } if ($labelpos eq 'left') {$x-=2+(length($name)*$fontsize{$FONT});$y-=$fontsize{$FONT}/3;} else {$x+=2+2*$fontsize{$FONT};$y-=$fontsize{$FONT}/3;} if ($RIJNLAND) { if (($X>90100) && ($X<97970) && ($Y>461050) && ($Y<466800)) {next;} } $DOTS.=" \$nm->string($FONT,$x,$y,$name,\$COLOR{black});\n"; } } sub plot_links { $txt=''; foreach $slave (sort @NODES) { local($sslave)=$slave;$sslave=~s/^.node//i;$sslave=~s/\d+$//; $sslave=~s/unigorn/unigor/i; foreach $key (split(/:/,$XY{"${slave}-S"})) { #print "Slave ($slave) = $key\n"; if ($key eq '') {next;} ($essid,$ptp,$if)=split(/=/,$key); $master=$XY{"$essid-E"}; # $txt.="${slave} ($if)==>$essid = $master ($ptp)"; if ($master) { local($smaster)=$master;$smaster=~s/^.node//i;$smaster=~s/\d+$//; $smaster=~s/unigorn/unigor/i; $lname="$master-$slave"; $LINKS{$master}.=":$lname:"; $LINKS{$slave}.=":$lname:"; $mx=$x{$master};$my=$y{$master};$sx=$x{$slave};$sy=$y{$slave}; $dx=abs($mx-$sx);$dy=abs($my-$sy);$link="${master}-${slave}"; $dashed=$style=$width=$usage=0;$load=''; if (($S{$master} eq 'constr') || ($S{$slave} eq 'constr')) {$color=$gray;$dashed=1;} elsif (($S{$master} eq 'offline') || ($S{$slave} eq 'offline')) {$color=$red;$dashed=1;} elsif (($S{$master} eq 'online') && ($S{$slave} eq 'pingable')) {$color=$yellow;$dashed=0;} elsif (($S{$master} eq 'online') || ($S{$master} eq 'pingable') || ($S{$slave} eq 'online')) {$color=$green;$style=0; $wlanstats="/home/wleiden/stats/mrtg/data/${slave}.gdbm"; tie %WLS,'GDBM_File',"$wlanstats", &GDBM_READER, 0640 || die "Could not tie $wlanstats\n"; $pktloss=$WLS{"pktloss-$ptp"}; $speed=$WLS{"act-TX-speed-$if"}; #print "tied: $wlanstats\[$ptp:$if\]:$pktloss:$speed\n"; untie(%WLS); if ($pktloss ne '') { if ($pktloss <= 1) {$style=0;} elsif ($pktloss <= 5) {$style=1;} elsif ($pktloss <= 10) {$style=2;} elsif ($pktloss > 10) {$style=2;$color=$red;} else {$style=3;} $PKTLOSS{$lname}=$pktloss; $PKTSTYLE{$lname}=$style; #print "pktloss=$pktloss $master-$slave\n"; } if (($speed > 0) && (! ($pktloss >90))) { if ($speed> 5) {$width=2;} elsif ($speed> 2) {$width=1;} $WIDTH{$lname}=$width; $bps=0; if (open(MRTG,"/home/wleiden/stats/mrtg/output/$slave/${if}_bytes.log")) { ;$line=; if ($line ne '') {($date,$in,$out,$junk,$junk)=split(/\s+/,);$bps=$in+$out;} close(MRTG); } $load=(100*2 * $bps)/($speed*1024*1024/8); $LOAD{$lname}=$load; if ($load > 0) {$load=log($load);} else {$load=0;} #printf "$master-$slave = $bps/$speed => %.2f\n",$load; } } else {$color=$orange;$style=1;} $DASHED{$lname}=$dashed; $x=MIN($mx,$sx);$y=MIN($my,$sy);$dx+1;$dy+1; $line=create_line($master,$slave,$mx,$my,$sx,$sy,$dx,$dy,$dashed,$color,$style,$width,$load); if ($line > 0) { $positions.="#$link {position:absolute; width:${dx}px; height:${dy}px; z-index:30;left:${x}px; top:${y}px; overflow:visible; visibility:visible;}\n"; $divs.=sprintf <$link EOP2 } local($lcolor)=$LCOLOR{$lname}=$DCOLOR{$color}; # #sprintf("#%02x%02x%02x",$R,$G,$B); $style='bold';# "dashed", "dotted", "solid", "invis" and "bold" $len=5; $port=''; if ($essid=~/(il|ap)-([^.]+)\./) { $pdir=$2; if ($pdir!~/omni/) { $pdir=~s/^z/s/i; $pdir=~s/^([ns])o$/$1e/i; if ($pdir=~/^(n|e|s|w|ne|nw|se|sw)$/) {$port=",headport=\":$pdir\"";} } } if ($headport eq '') {$port=getport($master,$essid,'head');} $port.=getport($slave,$essid,'tail'); $port=''; $DOT2.=sprintf " \"%s\" -> \"%s\" [style=%s,len=%d,color=\"$lcolor\"${port}]\n", lc($sslave),lc($smaster),$style,$len,$lcolor; $MASTERDONE{$smaster}=1; } # $txt.="
    \n"; } } } sub output_html_dot { $ncounter=0; local(%xy_used); foreach $node (@NODES) { local($snode)=$node;$snode=~s/^.node//i;$snode=~s/\d+$//; $snode=~s/(unigor)n/$1/i; if ((! exists($DOTDONE{$snode})) && ($LINKS{$node})) { local($x)=$ox{$node}+rand()*10; #niet dezelfde coordinaten local($y)=$oy{$node}+rand()*10; while ($xy_used{"$x:$y"}) { $x+=10; #niet dezelfde coordinaten anders raakt neato in de war.. $y+=10; } $xy_used{"$x:$y"}++; printf DOT "\n\"%s\"[fontsize=36,label=\"%s\",color=\"%s\",pos=\"%f,%f\"]\n", lc($snode),$snode,$NCOLOR{$node},$x,$y; $DOTDONE{$snode}=1; } $ncounter++; $S=$S{$node}; if ($S eq 'online') {$status="online";} elsif ($S eq 'pingable') {$status="pingable";} elsif ($S eq 'offline') {$status="offline";} elsif ($S eq 'constr') {$status="planned";} else {$status="demo/test";} if (($ncounter %5) eq 1) {$lc=" BGCOLOR=lightcyan";} else {$lc='';} print STATUS "$node:$S:
    \n"; print INDEX "
    $ncounter${node}$status \n"; foreach $lname (split(/:/,$LINKS{$node})) { if ($lname eq '') {next;} $link3=$lname; $link3=~s/-?$node-?//gi;$link2=$link3; $link2=~s/^.node//gi; $pktloss=$PKTLOSS{$lname}; $pktstyle=$PKTSTYLE{$lname}; $lcolor=$LCOLOR{$lname}; $load=$LOAD{$lname}; $width=$WIDTH{$lname}; $dashed=$DASHED{$lname}; if ($width eq 2) {$width="";} else {$width="";} if ($pktloss > 10) {$pktloss="";} else {$pktloss='';} if ($lcolor ne '') {$lcolor="";} if ($load > 100) {$load=sprintf "(%.0f\%)",100;} elsif ($load > 1) {$load=sprintf "(%.0f\%)",$load;} elsif ($load > .1) {$load=sprintf "(%.1f\%)",$load;} else {$load='';} if ((($dashed) && ($lcolor=~/000000/)) || ($S eq 'constr') || ($S{$link3} eq 'constr')) {$lcolor="";} print INDEX "${lcolor}${width}${pktloss}${link2} $load\n"; } } print DOT "\n$DOT2\n}\n"; print INDEX<

    $online nodes online.
    $offline nodes offline.
    $constr nodes planned (under construction).

    Generated at $now (rev: $revision) EOF print MAP < Wireless Leiden NodeMap

    $divs
    Generated at $now (rev: $revision)

    $txt

    EOM if ($HIRES) {$tx=1100;$ty=2080;} else {$tx=450;$ty=580;} print IMAGE <string($FONT,$tx,$ty,"Generated at: $now (rev: $revision)",\$COLOR{black}); EOIF $tx=$ty=0; if ($RIJNLAND) { print IMAGE <string($FONT,$tx,$ty,"Generated at: $now (rev: $revision)",\$COLOR{black}); open (F,">images/rijnland.png") || die "$! images/rijnland.png\n"; print F \$nm->png(); close F; EOFH1 }elsif ($HIRES) { print IMAGE <string($FONT,$tx,$ty,"Generated at: $now (rev: $revision)",\$COLOR{black}); open (F,">images/hires.png") || die "$! images/hires.png\n"; print F \$nm->png(); close F; EOFH1 } elsif ($HISTORY) { print IMAGE <string($FONT,$tx,$ty,"Generated at: $now (rev: $revision)",\$COLOR{black}); open (F,">images/history.jpg") || die "$! images/history.jpg\n"; print F \$nm->jpeg(85); close F; EOFH2 } else { print IMAGE <images/nodemap.jpg") || die "$! images/nodemap.jpg\n"; print F \$nm->jpeg(85); close F; EOFH3 } open(STATUS,">$statusfn2") || die "$! $statusfn2\n"; } sub close_files { close(STATUS); close(INDEX); close(MAP); close(IMAGE); close(DOT); unlink($nodemapfn); chdir("/home/wleiden/stats/mrtg/") || die "$! /home/wleiden/stats/mrtg\n"; rename("${dotfn}.$$",$dotfn); rename("${nodemapfn}.$$",$nodemapfn); chmod( 0755,$nodemapfn); system($nodemapfn) || die "ERROR: $! $nodemapfn\n"; $nmfn=$nodemapfn; $nmfn=~s/\.[^.]+$//; $nmfn=~s/^.*?([^\/]+)$/$1/; print "NMFN: $nmfn\n"; if (($HIRES eq 0) && ($HISTORY eq 0)) { unlink($indexfn); unlink($statusfn); unlink($mapfn); rename("${indexfn}.$$",$indexfn); rename("${statusfn}.$$",$statusfn); rename("${mapfn}.$$",$mapfn); if ($DEBUG) {print "Doing neato.\n";} system ("/bin/sh -c 'ulimit -t 30; $neato -Tjpg -o images/map.jpg $dotfn'"); system ("/bin/sh -c 'ulimit -t 30; $neato -Tsvgz -o images/map.svgz $dotfn'"); #do($nodemapfn) || die "$! $nodemapfn\n"; $doit="/usr/bin/scp -q images/map.jpg images/${nmfn}.* wcl\@rumba:/home/wcl/public_html/nodemap/"; print "DOING: $doit\n"; if (($pid=fork()) eq 0) { if (! $DEBUG) { if (ping("rumba.morgana.net")) { # exec($doit); } else {print "no SCP; rumba offline.\n";} } } } elsif (($pid=fork()) eq 0) { if (ping("rumba.morgana.net")) { exec('/usr/bin/scp -q images/${nmfn}.* \ wcl@rumba:/home/wcl/public_html/nodemap/'); } else {print "no SCP; rumba offline.\n";} } close(STATUS); } sub fork_mrtgs { if ($DEBUG && ($ARGV[1] ne 'FORCE')) {exit;} print "Starting MRTGs.\n"; foreach $node (keys %S) { if ($DEBUG) {print "MRTG.Doing: $node\n";} # open (LOADAVG,"/proc/loadavg"); # $loadavg=;close(LOADAVG); $loadavg=`uptime`; if ($loadavg=~/averages?:\s+([0-9.]+)/) { $loadavg=100*$1; print "LOAD: $loadavg. While at node: $node\n"; if ($loadavg > $maxloadavg) {print "CPULOAD $loadavg > $maxloadavg. Skipped: $node\n";sleep (10);next;} } if ($S{$node}=~/(online|pingable)/i) { if (! $DEBUG) {sleep(10);} $ps=`ps auwx|grep $node`; if ($ps=~/^\S+\s+(\d+).*\/usr\/local\/bin\/mrtg \/home\/wleiden\/stats\/mrtg\/cfg\/$node.cfg/) { $pid=$1; ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, $atime,$mtime,$ctime,$blksize,$blocks) = stat("$datadir/${node}.pid"); if ($mtime > 0) { $age=time()-$mtime; if ($age > 600) {kill(15,$pid);sleep(1);} } else { print "Already running: $node PID: $pid\n"; next; } } $P="MRTG_$node"; if (($pid=fork()) eq 0) { if ($DEBUG) {print "Child for node $node\n";exit;} else { $0=$PROGRAM_NAME=$P; exec "exec /usr/bin/nohup /usr/bin/mrtg /home/wleiden/stats/mrtg/cfg/$node.cfg 2> /home/wleiden/stats/mrtg/data/${node}.log"; } } else { open (PID,">$datadir/${node}.pid");print PID "$pid\n"; close(PID); } } elsif ($DEBUG) {print "MRTG.Node offline: $node\n";} } }