Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
169 changes: 157 additions & 12 deletions Force10.pm
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
package Force10;
package CFG2JSON::Force10;
use strict;
use Data::Dumper;
use NetAddr::IP;

sub new{
my ($class,$args)=@_;
my $class = shift;
my $args = { @_ };
my $config=$args->{config};
my $gbics=buildGbicHash($config);
my $dev=getinfo($config);
my $interfaces=getinterfaces($config);
$dev->{interfaces}=$interfaces;
my ($ints,$vlans)=getinterfaces($config,$gbics);
$dev->{interfaces}=$ints;
$dev->{vlans}=$vlans;
my $self = bless {device=>$dev}, $class;
}

Expand All @@ -16,46 +20,187 @@ sub getinfo{
my $obj={};
my @inventory=[];
for(@config){
$obj->{version}=$1 if $_=~/!Inventory: Software Version\s+:\s(.*)/i;
push(@{$obj->{syslog}},$2) if $_=~/logging( vrf MGMT)? ([\d\.]+)/i;
push(@{$obj->{snmp}},$1) if $_=~/snmp-server host ([\d\.]+) /i;
push(@{$obj->{tacacs}},$1) if $_=~/tacacs-server host ([\d\.]+)/i;
if($_=~/!Inventory: Software Version\s+:\s([\d\.]+)(\((.*)\))?/i){
$obj->{version}=$1;
$obj->{subversion}=$3;
}
$obj->{model}=$2 if $_=~/!Inventory: (System|Chassis) Type\s+:\s(.*?)\s+/i;
$obj->{nics_num}=$obj->{nics_num}+$1 if $_=~/!Chassis: Num Ports\s+:\s+([\d]+)/i;
$obj->{macaddress}=$1 if $_=~/!Chassis: Burned In MAC\s+:\s+([\w:]+)/i;
$obj->{memory}=$obj->{memory}+($1/1000) if $_=~/!Memory.*\s([\d]+)M/;
$obj->{taaccounting}=$1 if $_=~/aaa accounting commands (.*)/i;
push(@inventory,$_) if $_=~m/!(Inventory|Chassis).*/i;
}
for(@inventory){
if($obj->{model} eq 'E300'){
$obj->{serial}=$1 if $_=~/!Chassis: Serial Number : (.*?)\s+/i;
$obj->{serial}=$1 if $_=~/!Chassis: Serial Number : ([\w]+)/i;
}else{
if($_=~/!Inventory: \*\s(.*)/i){
my @ia=split(/\s+/,$1);
$obj->{serial}=$ia[7]
$obj->{serial}=$ia[7];
$obj->{serial}=$ia[2] if $obj->{serial} eq 'N/A' || !$obj->{serial};
}
}
}
return $obj;
}

sub getinterfaces{
my ($c,$gbics)=@_;
my ($ints,$vlans);
my $c = shift;
my $ints;
$c=~s/\n/<nl>/g;
my @ints_arr=split(/<nl>i/,$c);
shift @ints_arr;
for(@ints_arr){
my $int=$_;
if($int=~/nterface (.*?)<nl>(.*?(shutdown|!<nl>router)).*/i){
my $i=$1;
my $vl=$i;
my $rc=$2;
$ints->{$i}{rawconfig}=$rc;
if($i=~m/Vlan ([\d]+)/i){
push(@{$ints->{$i}{vlans}},$1);
$ints->{$i}{formfactor}='virtual';
$ints->{$i}{mode}='sub';
}elsif($i=~m/port.*/i){
$ints->{$i}{formfactor}='LAG';
}else{
my $sp=lc($i);
$sp=~s/(tengigabitethernet|fortygige) //i;
if($gbics->{$sp}){
if(uc($gbics->{$sp}{formfactor})=~/MEDIANOT/){
$ints->{$i}{formfactor}='none';
}elsif(uc($gbics->{$sp}{formfactor})=~/UNKNOWNUNKNOWN/){
$ints->{$i}{formfactor}='unknown';
}else{
$ints->{$i}{formfactor}=$gbics->{$sp}{formfactor};
$ints->{$i}{serial}=$gbics->{$sp}{serial};
$ints->{$i}{qualified}=$gbics->{$sp}{qualified};
}
}else{
$ints->{$i}{formfactor}='physical';
}
}
$rc=~s/!<nl>router$//i;
$vl=~s/Vlan //;
for(split/<nl>/,$rc){
my $l=$_;
$ints->{$i}{description}=$1 if $l=~/description (.*)/i;
$ints->{$i}{ipaddress}=$1 if $l=~/ip address (.*)/i;
push(@{$ints->{$i}{ipaddress}},{ip=>$1,bits=>$2,type=>'interface',version=>'4'}) if $l=~/ip address ([\d]+\..*)\/([\d]+)/;
push(@{$ints->{$i}{ipaddress}},{ip=>$1,type=>'vrrp',version=>'4'}) if $l=~/virtual-address\s([\d]+\.[\d\.]+)/;
push(@{$ints->{$i}{ipaddress}},{ip=>$1,bits=>$2,type=>'interface',version=>'6'}) if $l=~/ipv6 address\s([\w]+:.*)\/([\d]+)/;
push(@{$ints->{$i}{ipaddress}},{ip=>$1,type=>'vrrp',version=>'6'}) if $l=~/virtual-address\s([\w]+:[\w:]+)/;
$ints->{$i}{vrf}=$1 if $l=~/ip vrf forwarding (.*)/i;
$ints->{$i}{mtu}=$1 if $l=~m/mtu\s([\d]+)/i;
addGroup($i,$1,$2,$3) if $l=~/(untagged|tagged) ([\w+-]+) ([\d\/]+.*)/i;
if($i=~/Vlan ([\d]+)/){
my $vl=$1;
push(@{$vlans},{'vlan'=>$vl,'name'=>$1}) if $l=~/name\s(.*)/i;
}
if($l=~m/\s+(port-channel\s[\d]+) mode active/){
my $pci=$1;
$pci=~s/port/Port/;
$ints->{$i}{parent}=$pci;
push(@{$ints->{$pci}{children}},$i);
}
}
#update vrrp network bitmask
$ints->{$i}{ipaddress}=updateBits($ints->{$i}{ipaddress});
}
}
processInts();
return ($ints,$vlans);
#subs
sub processInts{
for(keys %{$ints}){
my $i=$_;
if($i=~/Vlan.*/){
if(@{$ints->{$i}{ipaddress}}<1){
delete $ints->{$i};
}
}
}
$ints->{console}{formfactor}='NONE';
}
sub addGroup{
my ($int,$im,$ib,$info)=@_;
$im=~s/untagged/access/i;
my $i1s;
my $vl=$int;
$vl=~s/Vlan //;
for(split(/,/,$info)){
my $pn=$_;
if($pn=~/([\d\/]+\/)?([\d]+)-([\d\/]+\/)?([\d]+)$/){
$i1s=$1 if $1;
my $i1p=$2;
my $i2s=$3;
my $i2p=$4;
for($i1p...$i2p){
my $p=$i1s.$_;
my $i=$ib.' '.$p;
#print "vl:$vl rx: $i\n";
push(@{$ints->{$i}{vlans}},$vl);
$ints->{$i}{mode}=$im;
}
}else{
my $i;
if($pn=~/([\d\/]+\/)?([\d]+)/i){
$i1s=$1 if !$i1s;
$pn=$i1s.$pn if !$1;
$i=$ib.' '.$pn;
}
#print "ib:$ib i1s:$i1s pn:$pn vl:$vl base $i\n";
push(@{$ints->{$i}{vlans}},$vl);
$ints->{$i}{mode}=$im;
}
}
}
}


sub updateBits{
my $ips = shift;
my $nets;
for(@{$ips}){
if($_->{bits}){
my $n=new NetAddr::IP $_->{ip}.'/'.$_->{bits};
push(@{$nets},$n);
}
}
my $c=0;
for(@{$ips}){
my $nip=new NetAddr::IP $_->{ip};
if(!$_->{bits}){
for(@{$nets}){
if($_->contains($nip)){
$ips->[$c]{bits}=$_->masklen();
last;
}
}
$ips->[$c]{bits}='32' if !$ips->[$c]{bits};
}
$c++;
}
return $ips;
}

sub buildGbicHash{
my $c=shift;
$c =~ s/\n/<nl>/g;
my $gb;
for(split(/<nl>/,$c)){
#if($_=~/!NAME: \"(.*)\"(\s+)?DESCR:\s\"(.*)\"(\s)?PID:\s(.*)VID:\s(.*)SN:\s(.*)/){
if($_=~/!InventoryMedia:\s+([\d]+.*)/){
my ($slot,$port,$type,$media,$serial,$qualified)=split(/\s+/,$1);
my $sp=$slot.'/'.$port;
$gb->{$sp}{formfactor}=$type.$media;
$gb->{$sp}{serial}=$serial;
$gb->{$sp}{qualified}=$qualified;
}
}
return $ints
return $gb;
}

1
109 changes: 93 additions & 16 deletions Scrape.pm
Original file line number Diff line number Diff line change
@@ -1,33 +1,46 @@
package Scrape;
package CFG2JSON::Scrape;
use strict;
use FindBin;
use lib $FindBin::Bin;
use JSON;
use Force10;
use Arista;
use Cisco;
use Juniper;
use CFG2JSON::Force10;
use CFG2JSON::Arista;
use CFG2JSON::Arbor;
use CFG2JSON::Opengear;
use CFG2JSON::Cisco;
use CFG2JSON::Juniper;
use File::Slurp;

sub new{
my ($class,$args)=@_;
my $class = shift;
my $args = { @_ };
my $filepath=$args->{filepath};
my $hostname=$args->{hostname};
my $sitename=$args->{sitename};
my $config=read_file($filepath.'/'.$sitename.'/configs/'.$hostname);
my $vendor=_getVendor($config);
my $mgmtip=nslookup($hostname);
my $dev;
if($vendor eq 'force10'){
$dev=Force10->new({config=>$config});
$dev=CFG2JSON::Force10->new(config=>$config);
}elsif($vendor eq 'arista'){
$dev=Arista->new({config=>$config});
$dev=CFG2JSON::Arista->new(config=>$config);
}elsif($vendor eq 'cisco'){
$dev=Cisco->new({config=>$config})
}elsif($vendor =~ /joy-juniper/){
$dev=Juniper->new({config=>$config})
$dev=CFG2JSON::Cisco->new(config=>$config);
}elsif($vendor eq 'opengear'){
$dev=CFG2JSON::Opengear->new(config=>$config);
}elsif($vendor =~ /juniper/){
$dev=CFG2JSON::Juniper->new(config=>$config);
}elsif($vendor eq 'arbor'){
$dev=CFG2JSON::Arbor->new(config=>$config);
}else{
$dev->{error}="No matching vendor found for $hostname!";
}
$dev->{device}{mgmtip}=$mgmtip;
$dev->{device}{sitename}=$sitename;
$dev->{device}{hostname}=$hostname;
$dev->{device}{vendor}=$vendor;
$dev->{device}{devicerole}=getDeviceRole($hostname);
my $self = bless {
config => $config,
device => $dev->{device}
Expand All @@ -37,17 +50,81 @@ sub new{
sub _getVendor{
my @cl=split("\n",$_[0]);
my $vl=shift @cl;
$vl=~s/!RANCID-CONTENT-TYPE: //i;
$vl=~s/[!#]RANCID-CONTENT-TYPE: //i;
$vl=~s/joy-//i;
$vl=~s/-srx//i;
return $vl
}

sub json{
my ($self,$key)=@_;
return encode_json $self->{$key};
my $self=shift;
return encode_json $self->{device};
}
sub gethash{
my $self = shift;
return $self->{$key}
my $self=shift;
return $self->{device}
}

sub nslookup{
my $hn=$_[0];
#print "nslookup $hn\n";
my $nsl=`nslookup $_[0]`;
$nsl=~s/\n//g;
$nsl=~s/\'//g;
$nsl=~s/.*usAddress: (.*)$/$1/i;
$nsl=~s/.*server cant find.*/notfound/i;
return $nsl;
}

sub getDeviceRole{
my $l = shift;
my $req;
if($l=~/agg/){
$req='Aggregate';
}elsif($l=~/-lef([\d]+)?-/){
$req='Leaf'
}elsif($l=~/-spn([\d]+)?-/){
$req='Spine'
}elsif($l=~/.*(drc|-dc)$/i){
$req='DirectConnect';
}elsif($l=~/.*-(dc|mx480|service|ss|edg|svc|bro)/i){
$req='Edge';
}elsif($l=~/pdu/i){
$req='PDU';
}elsif($l=~/HSM/i){
$req='HSM';
}elsif($l=~/SDX/i){
$req='SDX';
}elsif($l=~/WAF/i){
$req='WAF';
}elsif($l=~/(srx|afw|sfw)/i){
$req='Firewall';
}elsif($l=~/ids/i){
$req='IDS';
}elsif($l=~/.*(bigswitch|bs4048|bsmf|bmf|\-BS).*/i){
$req='BigSwitch';
}elsif($l=~/.*(admin|mgt|mgg).*/i){
$req='NW Admin';
}elsif($l=~/.*(dist|dst).*/i){
$req='Distribution';
}elsif($l=~/.*(core).*/i){
$req='Core';
}elsif($l=~/.*(arbor|tms).*/i){
$req='Arbor';
}elsif($l=~/.*(logr|lr[12])/){
$req='LogRythm';
}elsif($l=~/.*-(con|oob)/i){
$req='NW Console';
}elsif($l=~/.*(kvm|dns|tac|opennms|cacti|netopsinfo|noctool|nftracker|ns[12]\.).*/i){
$req='Server';
}elsif($l=~/.*mx204.*/){
$req='Core';
}elsif($l=~/.*-e300-[12]/){
$req='Core';
}elsif($l=~/.*-tor/i || $l=~/.*[\d]+\-[12]/){
$req='TOR';
}
return $req;
}

1;