Ncm switch ports.pl

From Federal Burro of Information
Jump to navigationJump to search

sample config ( yaml);


gibraltar-kelowna-gm-sw1:
 name: gibraltar-kelowna-gm-sw1
 ip: 10.5.1.10
 community: public
 snmpversion: 2c
 description: snmp(ifName) snmp(ifAlias)
 commentcondition:
  - oid: ifOperStatus
    # up(1)
    value: '1'
  - oid: ifType
    value: '6'
 vars:
  - oid: dot3StatsDuplexStatus
    mib: EtherLike-MIB
    # fullDuplex(3)
    value: '3'
  - oid: ifHighSpeed
    mib: IF-MIB
    value: 1000
  - oid: ifOperStatus
    mib: IF-MIB
    value: up

Script

#!/usr/bin/perl -w

use strict;
use YAML qw(LoadFile Dump);
use Data::Dumper;
use Net::SNMP;;

# example service description:
my $service_template = 'define service{
use                     generic-service
host_name               HOSTNAME
service_description     ifName - VARIABLE - ifAlias
check_command           check_snmp!-P VERSION -C SNMPSTRING -m THEMIB -o VARIABLE.ifIndex -r VALUE
}';

#print "Service Template\n";
#print $service_template;

#Todo
# ifalias not found then put a NULL or name not defined value

my $dosnmp  = 1;
my $timeout = 1;
my $debug   = 0;
my $verbose = 1;

my %tables;
my %name2oid;

# any var we might care about needto be defined here FIXME
$tables{'ifTable'}          = '.1.3.6.1.2.1.2.2';
$name2oid{'ifIndex'}       = '.1.3.6.1.2.1.2.2.1.1';
$name2oid{'ifDescr'}       = '.1.3.6.1.2.1.2.2.1.2'; # GigabitEthernet0/1
$name2oid{'ifType'}        = '.1.3.6.1.2.1.2.2.1.3'; # ethernetCsmacd or propVirtual
$name2oid{'ifAdminStatus'} = '.1.3.6.1.2.1.2.2.1.7'; # not needed
$name2oid{'ifOperStatus'}  = '.1.3.6.1.2.1.2.2.1.8';

$tables{'ifXTable'}        = '.1.3.6.1.2.1.31';
$name2oid{'ifName'}        = '.1.3.6.1.2.1.31.1.1.1.1'; # Gi0/1
$name2oid{'ifAlias'}       = '.1.3.6.1.2.1.31.1.1.1.18'; # extest11-ilom
$name2oid{'ifHighSpeed'}   = '.1.3.6.1.2.1.31.1.1.1.15';

$tables{'dot3StatsTable'}          = '.1.3.6.1.2.1.10.7.2';
$name2oid{'dot3StatsDuplexStatus'} = '.1.3.6.1.2.1.10.7.2.1.19';

# build the backward lookup
my %oid2name;

foreach my $name ( keys %name2oid ) {
    $oid2name{$name2oid{$name}} = $name;
}

if ( ! $ARGV[0] ) {
    die "Need a config file in argv[0]\n";
}

$verbose && print STDERR "Config File is ".$ARGV[0]."\n";

# Has all devices in it
my $deviceconfig = LoadFile($ARGV[0]);
$verbose && print STDERR "Config File is loaded\n";

my %snmp;

if ( $debug ) {
    print STDERR "--------\n";
    print STDERR "Data: Yaml\n";
    print STDERR Dump $deviceconfig;
    print STDERR "-------------\n";
}

$verbose && print STDERR "Looping over device list\n";
for my $device ( keys %$deviceconfig ) {
    if ( $verbose ) {

        print STDERR "Device name: " .$device."\n";
        print STDERR "Community "    .$deviceconfig->{$device}->{'community'}."\n";
        print STDERR "Ip "           .$deviceconfig->{$device}->{'ip'}."\n";
        print STDERR "Name "         .$deviceconfig->{$device}->{'name'}."\n";
        print STDERR "Desc "         .$deviceconfig->{$device}->{'description'}."\n";
        print STDERR "Snmp Version: ".$deviceconfig->{$device}->{'snmpversion'}."\n";
    }

    $debug &&  print STDERR Dumper $deviceconfig->{$device} ;

    my $service = $service_template;

    # per device substitutions
    $debug && print STDERR "Substituing HOSTNAME VERSION SNMPSTRING\n";
    $service =~ s/HOSTNAME/$deviceconfig->{$device}->{'name'}/g;
    $service =~ s/VERSION/$deviceconfig->{$device}->{'snmpversion'}/g;
    $service =~ s/SNMPSTRING/$deviceconfig->{$device}->{'community'}/g;

    $debug && print STDERR "Service is now:\n";
    $debug && print STDERR $service."\n";

    my $interfaces; # hashref where we store collected data.

    $verbose && print STDERR "Conditions:\n";
    $verbose && print STDERR Dumper($deviceconfig->{$device}->{'commentcondition'});

    $verbose && print STDERR "Starting SNMP work\n";

    if ( $dosnmp ) {
        ($snmp{session}, $snmp{error}) = Net::SNMP -> session(
            -hostname  => $deviceconfig->{$device}->{'ip'} ,
            -community => $deviceconfig->{$device}->{'community'} ,
            -timeout   => $timeout,
        );

        #if ( $debug ) {
        #    print "SNMP session\n";
        #    print "--------\n";
        #    print Dumper($snmp{session});
        #}

        # Pseudo code:
        # for each table
        # for each oid
        # if the oid is one we care about
        # populate data structure $interfaces ( hashref )

        for my $table ( keys %tables ) {
            $verbose && print STDERR "Fetching Table $table (". $tables{$table} .")\n";
            my $result = $snmp{session} -> get_table( -baseoid => $tables{$table} );


            if ( defined($result) ) {
                foreach my $key ( keys %{$result} ) {
                    # print "Found $key\n";
                    # Keys are like this ".1.3.6.1.2.1.31.1.1.1.1.10127"
                    #                     |--- VARIABLE OID ----|.INDEX
                    $key =~ /^(.*)\.(\d+)$/;
                    my $oid = $1;
                    my $index = $2;

                    # if we put this oid in the hash at the top of the script then we care about it and put it into the collected data structure $interfaces
                    if ( $oid2name{$oid} ) {

                        #$debug && print "Found an interesting oid\n";
                        #$debug && print $oid2name{$oid}." ".$result->{$key}."\n";

                        if ( $result->{$key} ) {
                            $interfaces->{$index}->{$oid2name{$oid}} = $result->{$key};
                        } else {
                            $interfaces->{$index}->{$oid2name{$oid}} = $oid2name{$oid}.':null';
                        }
                    }
                }

            }
        }

        # finsihed collecting data, now organize the data formate it and print it.

        for my $index ( sort {$a <=> $b} keys %$interfaces ) { # get interface indexes order numerically
            $verbose && print STDERR "Working on Index: ".$index. "\n";

            # not pretty FIXME
            my $vararrref = $deviceconfig->{$device}->{'vars'};
            my @vararr = @$vararrref;

            for my $var ( @vararr )  {
                $debug && print STDERR "Working on var ".$var->{'oid'}."\n";

                # copy the template here so that we can do substitutions on it for this specific nagios "service"
                my $service_instance = $service;

                # First substitute this interfaces properties like ifName ifAlias ifIndex.
                # if the template has these names in it , they will get the value for this interface.
                # if the template had             "description: ifName ifAlias"
                # this code would change that to: "description: Gi0/1 server1"
                # recall, $index is an interger , $interfaces->{$index} is a reference to a hash , where each key is the name of the interface variable.

                for my $oidname ( sort keys %{$interfaces->{$index}} ) {
                    $service_instance =~ s/$oidname/$interfaces->{$index}->{$oidname}/g;
                }

                # thse are straight substitutions for CAPITALIZED variables in the template which have to do with this varaible.
                # i.e. for ifOperStatus -m should be IF-MIB and -r should be up ( defined in the config file).
                $service_instance =~ s/VARIABLE/$var->{'oid'}/g;
                $service_instance =~ s/THEMIB/$var->{'mib'}/g;
                $service_instance =~ s/VALUE/$var->{'value'}/g;

                my $commentflag = 0;
                # then commented it out if it doens't meet the conditions

                # not pretty FIXME
                my $conditionarrayref = $deviceconfig->{$device}->{'commentcondition'};
                my @conditionarr = @$conditionarrayref; # array of pointers to a hash.
                # each array element is ONE condition
                # the array element points to the properties of that condition
                # for example:
                # 'oid' => 'ifOperStatus'
                # 'value' => 'up'

                for my $condition ( @conditionarr ) {
                    $debug && print STDERR "The condition is that ". $condition->{'oid'} ." must be ". $condition->{'value'} ."\n";
                    $debug && print STDERR $condition->{'oid'} . " is " . $interfaces->{$index}->{$condition->{'oid'}} ."\n";
                    if ( $interfaces->{$index}->{$condition->{'oid'}} ne $condition->{'value'} ) {
                        $commentflag = 1;
                        $debug && print STDERR "found a reason to comment out this device $device index $index Variable ". $var->{'oid'}."\n";
                        $debug && print STDERR "oid: ".$condition->{'oid'}." = ". $condition->{'value'}."\n";
                    }
                }

                # if comment flag is set then comment out else continue (1)
                $commentflag ? $service_instance =~ s/^/#/mg : 1;

                print "\n".$service_instance."\n";

            } # end of variables for this interface

        } # end of collected interface data

    } # end of snmp work
}