Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

Monitor memory on a cisco router

by vlad3848 (Acolyte)
on Mar 19, 2014 at 06:21 UTC ( [id://1078898]=perlquestion: print w/replies, xml ) Need Help??

vlad3848 has asked for the wisdom of the Perl Monks concerning the following question:

Greetings Monks! I am trying to write a script which will monitor available memory on a cisco router. The scrip works without issues when ran on a single node. However, when i try to add additional switches or routers the script fails frequently. If a script fails to log into any of the routers or switches it fails all together. I am using eval to check my ssh connection before running any commands and it helped a little. However, if i add more than 3-4 switches, the script fails pretty consistently. It could have something do do with Net::SSH2 module as this is my first time using it, but i am not 100% sure. Any help would be greatly appreciate it!

#! /usr/bin/perl use Net::SSH2; use warnings; use strict; use Data::Dumper; use Net::Syslog; my $user = "user"; my $password = 'password'; my $secret = 'secret'; ### enable password my @hosts=qw/switch1 switch2 switch3 switch4 switch5 switch6/; my (%deviceHash, $total, $total_unicast,$total_ipv4nonvrf,$total_ipv4v +rf, $total_multicast, $total_mpls, $host, $connect, $s, $ssh); my $array_count= scalar @hosts; foreach (@hosts){ &connect; } my $hash_count = keys %deviceHash; my $i=0; print "The number of keys in the hash $hash_count\n"; if(($array_count != $hash_count) && ($i<=2)){ print "went into conditional statement\n"; print "the kyes $_\n" for keys %deviceHash; foreach my $connection(@hosts){ if (exists $deviceHash{$connection}){ print "the $connection host exists\n"; } else{ print "the $connection doesn't exist"; &connect($connection); } } $i++ } sub connect { $host=$_; $ssh = Net::SSH2->new(); my $retry_count = 0; my $max_retry_count =5; while($retry_count <= $max_retry_count){ my $rc = eval { $ssh->connect($host); }; last if defined $rc; $retry_count++; sleep 2; } if ($@) { &mail2 ($host); print "output on $host $@\n"; next; } if(!$ssh->auth_password($user,$password)){ print("Authentication Failed"); exit(1); } my $channel = $ssh->channel(); $channel->blocking(0); $channel->shell(); $channel->write("enable\n"); $channel->write("$secret\n"); ### enable password from input strin +g3 $channel->write("term len 0\n"); print $channel "sh mls cef sum\n"; while (<$channel>) { unless($_ =~ /routes/){ next; } if ($_ =~ /Total routes/){ $total = (split(/:/, $_))[1]; $total =~ s/^\s+//; $total =~ s/\s+$//; $deviceHash{$host}{"Total"} = $total; } elsif($_ =~ /IPv4 unicast routes/){ $total_unicast = (split(/:/, $_))[1]; $total_unicast =~ s/^\s+//; $total_unicast =~ s/\s+$//; $deviceHash{$host}{"Total_Unicast"} = $total_unicast; } elsif($_ =~ /IPv4 non-vrf routes/){ $total_ipv4nonvrf = (split(/:/, $_))[1]; $total_ipv4nonvrf =~ s/^\s+//; $total_ipv4nonvrf =~ s/\s+$//; $deviceHash{$host}{"Total_IPV4_NONVRF"} = $total_ipv4nonvrf; } elsif($_ =~ /IPv4 vrf routes/){ $total_ipv4vrf = (split(/:/, $_))[1]; $total_ipv4vrf =~ s/^\s+//; $total_ipv4vrf =~ s/\s+$//; $deviceHash{$host}{"Total_IPV4_VRF"} = $total_ipv4vrf; } elsif($_ =~ /IPv4 Multicast routes/){ $total_multicast = (split(/:/, $_))[1]; $total_multicast =~ s/^\s+//; $total_multicast =~ s/\s+$//; $deviceHash{$host}{"Total_IPV4_MULTICAST"} = $total_multicast; } elsif($_ =~ /MPLS routes/){ $total_mpls = (split(/:/, $_))[1]; $total_mpls =~ s/^\s+//; $total_mpls =~ s/\s+$//; $deviceHash{$host}{"Total_IPV4_MULTICAST"} = $total_mpls; } } # exit the routine $channel->write('exit'); # Close the connection $ssh->disconnect(); #sleep (1); } foreach my $key (keys %deviceHash){ if ($deviceHash{$key}{"Total"} >= 100000){ $s = new Net::Syslog(); my $memory = $deviceHash{$key}{"Total"}; $s->send("TCAM memory is being exhausted on $key, the current memory i +s $memory",Name=>'tcam-test',Facility=>'local7',Priority=>'info',Sysl +ogHost=>'192.168.0.1'); #print "the TCAM memory is being exhausted on $key, the current memory + is $memory \n"; } } sub mail2 { my $node=shift; my @to=qw/host.email.com/; open(MAIL, "|/usr/sbin/sendmail -t"); ## Mail Header print MAIL "To: @to\n"; print MAIL "From: root\n"; print MAIL "Subject: The tcam monitoring script was not able to lo +g into $node\n"; ##Mail Body print MAIL "The tcam monitoring script was not able to log into $ +node\n"; print MAIL "If the problem repeats itself please investigate as so +on as possible\n"; close(MAIL); }

The output of the command that is being assigned to the hash goes something like this: Total routes: 94000 IPv4 unicast routes: 94000 IPv4 non-vrf routes: 130 IPv4 vrf routes: 95000 IPv4 Multicast routes: 65 MPLS routes: 560 IPv6 unicast routes: 3 IPv6 non-vrf routes: 2 IPv6 vrf routes: 0 IPv6 multicast routes: 5 EoM routes: 1

Replies are listed 'Best First'.
Re: Monitor memory on a cisco router
by salva (Canon) on Mar 19, 2014 at 09:51 UTC
    The easiest way to retrieve statistics or configuration information from network devices is to use SNMP.

    In any case, using Net::SSH2 correctly is quite hard and often involves looking at the module source code or even at libssh2 one. If you are on a Unix/Linux box, Net::OpenSSH is far easier to use.

    You can even perform the querying in parallel using Net::OpenSSH::Parallel:

    use Net::OpenSSH::Parallel; my $pssh = Net::OpenSSH::Parallel; $pssh->add_host($_, user => $user, password => $password) for @hosts; $pssh->all(parsub => \&query_device); $pssh->run; sub query_device { my ($host, $ssh) = @_; my $output = $ssh->capture({ stdin_data => <<EOD, stderr_to_stdout + => 1 }); enable $secret term len 0; sh mls cef sum EOD $output =~ s/\s+/ /g; print "data from $host: $output\n"; }
      Thank you salva! I'll give it a try. As I've mentioned in my comment below, these metrics are not available in the SNMP MIBs (or/and I can't access some of the devices via SNMP). I can collect just about anything i want via SNMP but not TCAM statistics.
Re: Monitor memory on a cisco router
by VinsWorldcom (Prior) on Mar 19, 2014 at 13:52 UTC

    To echo salva's comments above re: SNMP, have a look at Cisco::Management which uses Net::SNMP and provides a nice interface for memory utilization:

    use Cisco::Management; my $cm = Cisco::Management->new([OPTIONS]); my $meminfo = $cm->memory_info(); ... $meminfo->[0]->{'Name', 'Used', 'Free', ...} $meminfo->[1]->{'Name', 'Used', 'Free', ...} ... $meminfo->[n]->{'Name', 'Used', 'Free', ...} ...

    The scripts provided in the distribution's bin/ directory provide working examples.

      Thank you for your response! Unfortunately, the TCAM (ternary content-addressable memory) metrics i am trying to collect is not available via SNMP. I have to create some form of an ssh collector to gather it. Moreover, due to some security policies some of the devices i am trying to collect these stats for, are not reachable via SNMP from my management network, not even for read only

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1078898]
Approved by rnewsham
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others learning in the Monastery: (7)
As of 2024-04-18 14:46 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found