Difference between revisions of "Visualisation with GraphViz"
(→dottr.pl: comment about those funny-looking numbers) |
(and the login data) |
||
Line 134: | Line 134: | ||
print "\n};\n\n"; | print "\n};\n\n"; | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | == DatabaseLoginData.pm == | ||
+ | <pre> | ||
+ | # database login data | ||
+ | package DatabaseLoginData; | ||
+ | |||
+ | our $db_user = "racktables_user"; | ||
+ | our $db_pw = "supersecretpassword"; | ||
+ | our $db_host = "racktables.example.com"; | ||
+ | |||
+ | 1; | ||
</pre> | </pre> | ||
Latest revision as of 12:18, 10 November 2012
GraphViz is an ingenious package created by IBM to visualise lots of possible object topologies. The package makes it very easy to create all kinds of directed and undirected graphs from raw data.
Hereby I share with you some simple code to create a very basic network topology graph from RackTables database. All updates (expecially fine-tuning the .dot file) are much welcome, since there are hundreds of possible tweaks in dot (the submodule I'm using here) itself.
I use dot (which is the most general topology module) because my tests showed that default layouts of other modules resulted inferior outputs. Still, the .dot file is the same, and you're all free to tweak other settings and show us all. :-)
Code requires perl (DBI / DBD::mysql for database access) and graphviz. If you use accented characters for strings you have to recode the output to UTF-8 somehow, I'm using konwert for that, but recode or other tools would do just fine, too.
dottr.pl
#!/usr/bin/perl ##$Id: dottr.pl,v 5aa2d11fa948 2012/11/10 10:57:04 grin $ # # (c) Peter 'grin' Gervai, 2012 # Released under CreativeCommons-Attribution-ShareAlike-3.0-Unported # # create .dot from racktables links # use DBI; use Encode; use DatabaseLoginData; # $db_user; $db_pw; $db_host my ($db_name, $db_port) = ("racktables_db", 3306); my $dbh = DBI->connect( "dbi:mysql:database=$db_name;host=$DatabaseLoginData::db_host;port=$db_port", $DatabaseLoginData::db_user, $DatabaseLoginData::db_pw, { RaiseError =>1, AutoCommit => 1 } ); ######################################################################### my $sth_links = $dbh->prepare(" SELECT ro1.name AS obj1, p1.name AS port1, Link.cable, p2.name AS port2, ro2.name AS obj2, d.dict_value AS obj1type FROM RackObject AS ro1 JOIN Port AS p1 ON(ro1.id=p1.object_id) JOIN Link ON(p1.id=Link.porta) JOIN Port AS p2 ON(Link.portb=p2.id) JOIN RackObject AS ro2 ON(p2.object_id=ro2.id) LEFT JOIN Dictionary AS d ON(ro1.objtype_id=d.dict_key) ORDER BY obj1, port1"); # I append random number to reservation comments to prevent same comments to # be merged into one node. my $sth_reservations = $dbh->prepare(" SELECT ro.name AS obj1, p.name AS port1, 'RESERVE' AS cable, '' AS port2, CONCAT(reservation_comment,' #',ROUND(RAND()*1000)) AS obj2, d.dict_value AS obj1type FROM RackObject AS ro JOIN Port AS p ON(ro.id=p.object_id) LEFT JOIN Dictionary AS d ON(ro.objtype_id=d.dict_key) WHERE p.reservation_comment IS NOT NULL ORDER BY obj1, port1"); my $res = $sth_links->execute; my $a = $sth_links->fetchall_arrayref; my @data = @$a; $res = $sth_reservations->execute; $a = $sth_reservations->fetchall_arrayref; @data = (@data, @$a); # header print ' graph rackspace_topo { label = "Tarr Racktables topo"; rankdir = LR; edge [ color="#0000a0", decorate=true, fontsize=9, headclip=false ]; node [ shape=box, headport=n, tailport=n ]; '; # generate edges foreach $a (@data) { # node+interface 1 $node{$a->[0]} = $a->[1]; $nodetype{$a->[0]} = $a->[5]; # node+interface 2 $node{$a->[4]} = $a->[3]; # push @link, $a; } # output the nods first foreach my $n (keys %node) { # nodes with empty or "space" names next if $n =~ /^\s*$/; $ntyp = $nodetype{$n}; # color/style depends on node type my $color=""; if( $ntyp eq "Server" ) { $color='color="black"'; } elsif( $ntyp eq "Network switch" ) { $color='color="red" style="bold"'; } elsif( $ntyp eq "Server chassis" ) { $color='color="blue" style="dotted"'; } elsif( $ntyp eq "Network chassis" ) { $color='color="lightblue"'; } elsif( $ntyp eq "MediaConverter" ) { $color='color="gold"'; } elsif( $ntyp eq "Router" ) { $color='color="darkgreen"'; } else { #$color='color="pink"'; # Barbie syndrome FTW } print '"' . $n . "\" [ $color ];\n"; } # and print the edges foreach my $l (@link) { # skip empty... next if $l->[0] =~ /^\s*$/; if( defined( $link{ $l->[0] }{ $l->[4] } ) && $link{ $l->[0] }{ $l->[4] } == $l->[2] ) { # skip duplicate # if you need warnings... here you can. } else { print '"', $l->[0], '" -- "', $l->[4], '" [ label="', $l->[2], "\" color=\"grey\"];\n"; $link{ $l->[0] }{ $l->[4] } = $l->[2]; } } print "\n};\n\n";
DatabaseLoginData.pm
# database login data package DatabaseLoginData; our $db_user = "racktables_user"; our $db_pw = "supersecretpassword"; our $db_host = "racktables.example.com"; 1;
create_svg.sh
#!/bin/bash #$Id: create_svg.sh,v 5aa2d11fa948 2012/11/10 10:57:04 grin $ # # (c) Peter 'grin' Gervai, 2012 # Released under CreativeCommons-Attribution-ShareAlike-3.0-Unported # # create .svg from racktables links # recode the file # first create the .dot file, and recode it using konwert # skip recoding if you're happy without accents, screws up svg otherwise echo "Creating .dot file from the database..." ./dottr.pl | konwert isolatin2-utf8 > map.dot # dot output is fine, others (like neato or circo) not that useful echo "Rendering map.svg and map.png..." dot -Tsvg -o map.svg map.dot dot -Tpng -o map.png map.dot echo "That's all, folks!"