jablonka.czprosek.czf

hotsanic

Subversion Repositories:
[/] [trunk/] [lib/] [HotSaNICsnmp.pm] - Rev 24 Go to most recent revision

Compare with Previous - Blame - Download


#
# $Id: HotSaNICsnmp.pm,v 1.24 2004/02/08 17:04:51 bernisys Exp $
#

package HotSaNICsnmp;

use Fcntl;
use HotSaNICparser;

($VERSION = '$Revision: 1.24 $') =~ s/.*(\d+\.\d+).*/$1/;

# Get modulename
my $MODNAME = HotSaNICparser::get_module_name();

# Get HotSaNIC global configuration
my %conf = HotSaNICparser::get_config("../..",$MODNAME);

# Hash to hold the probed/read versions of diffrerent agents.
my %agent_v; 

#
# get_session($host, $community, $ver)
#
# returns a new Net::SNMP session and sets version
#

sub get_session {
        my ($host, $comm, $ver) = @_;

        undef my $result;

        $result = Net::SNMP->session(
                Hostname  => $host, 
                Community => $comm,
                Port      => 161 
                );

        if(defined($result)) {
                $result->version($ver);
                $result->timeout(2);
                $result->retries(1);
        }

        return $result;
}

#
# probe_version($host, $community)
#
# Checks the given hosts ability to answer bulk requests and returns
# either '1' if no bulk request was possible and '2c' if it was. 
#

sub probe_version {
        my $sys = 0; # use Net::SNMP by default

        eval { require Net::SNMP; };
        $sys = 1 if($@); # use system commands

        my ($host, $comm) = @_;
        my $result = 1; # default return value is '1'

        # Now send a probe request to check which version to use
        if($sys == 1) {
                print time." $MODNAME: probe_version() fallback\n" if $conf{DEBUGLEVEL} >= 2;
                return $result if !defined($conf{SNMPBULKWALK});
                open RESULT,"$conf{SNMPBULKWALK} -c $comm -v 2c -r 1 -t 2 $host .1.3.6.1.2.1.1.1|";
                $result = '2c' if $? == 0;
                close RESULT;
        } else {
                print time." $MODNAME: probe_version() module\n" if $conf{DEBUGLEVEL} >= 2;
                my $session = get_session($host, $comm, '2c');
        
                return $result if !defined($session);

                my @test = '.1.3.6.1.2.1.1.1';

                $result = '2c' if defined($session->get_bulk_request(-varbindlist => \@test));
                $session->close();
        }

        return $result;
}

#
# set_version($host, $comm)
#
# trys to determit the version to use with specified host. If not in the 
# info file the probe function will be called to set a version. 
#

sub set_version {
        my ($host, $comm) = @_;

        $lockfile=$conf{VARDIR}."modules/$host.lock";
        $infofile=$conf{VARDIR}."modules/$host.info";

        sleep 1 while !sysopen(LOCK, $lockfile, O_WRONLY|O_EXCL|O_CREAT, 0644); # grab lock or wait

        # Read info either from filesystem or probe it. 
        if( -e $infofile ) {
                open (INFO, "<$infofile");
                $agent_v{$host} = <INFO>;
                close INFO;
        } else {
                open (INFO, ">$infofile");
                $agent_v{$host} = probe_version($host, $comm);
                print INFO $agent_v{$host};
                close INFO;
        }

        close LOCK; # close lockfile
        unlink $lockfile; # release lock

        print time." $MODNAME: set_version() [$agent_v{$host}]\n" if $conf{DEBUGLEVEL} >= 1;
}

#
# snmp_walk($host, $comm, @oid) 
#
# This function is used by the modules to retrieve one or more  subtables from 
# the SNMP tree on $host. The root OIDs are given in the third argument. 
# The returned value is a reference to a hash which holds the result, 
# where the OIDs are used as keys and guess the values are values from 
# the snmptree.
#
# Note: The module has not to care about anything like using CPAN module
# or system commands, since this is handled transparent in this lib
#

sub snmp_walk {
        my ($host, $comm, @oid) = @_;
        undef my %result;

        print time." $MODNAME: enter snmp_walk()\n" if $conf{DEBUGLEVEL} >= 3;

        set_version($host, $comm) if !defined($agent_v{$host});

        for (@oid) {
                my $res = snmp_mod_walk($host, $comm, $_);
                next if !defined ($res);
                foreach ( keys(%$res) ) {
                        $result{$_} = $$res{$_};
                }
        }

        print time." $MODNAME: leave snmp_walk()\n" if $conf{DEBUGLEVEL} >= 3; 

        return \%result;
}

#
# snmp_get($host, $comm, @oid)
#
# Retrieves one value from the given $host. Works similar to snmp_walk 
# and return also a hash reference. This way you can query more values 
# with get @ once. 
#

sub snmp_get {
        my ($host, $comm, @oid) = @_;
        undef my %result;

        print time." $MODNAME: enter snmp_get()\n" if $conf{DEBUGLEVEL} >= 3;
        
        set_version($host, $comm) if !defined($agent_v{$host});

        $result{$_} = snmp_mod_get($host, $comm, $_) for (@oid);

        print time." $MODNAME: leave snmp_get()\n" if $conf{DEBUGLEVEL} >= 3;

        return \%result;
}

#
# snmp_mod_get($host, $community, $oid)
#
# This is the Net::SNMP based implementation of snmp_get, which will
# hand out control to the system command fallback, if module is not 
# availible. 
#

sub snmp_mod_get {
  eval { require Net::SNMP; };
  return snmp_sys_get(@_) if($@); 

  my ($hostname, $community, $oid) = @_;
  undef my $response;

  my $session = get_session($hostname, $community, $agent_v{$hostname});

  return undef if !defined($session);

  if(!defined($response = $session->get_request($oid))) {
        $session->close;
        return undef;
  }

  $session->close;
  print time." $MODNAME: snmp_mod_get() [$$response{$oid}]\n" if $conf{DEBUGLEVEL} >= 3;
  return $$response{$oid};
}

#
# snmp_mod_walk($host, $community, $oid)
#
# The Net::SNMP based implementation of snmp_walk, which will hand 
# out control to system command based fallback, if module is 
# not availible. 
#

sub snmp_mod_walk {
  eval { require Net::SNMP; };
  return snmp_sys_walk(@_) if($@);

  my ($hostname, $community, $oid) = @_;
  undef my $response;
    
  my $session = get_session($hostname, $community, $agent_v{$hostname});
    
  return undef if(!defined($session));
    
  if(!defined($response = $session->get_table($oid))) {
    $session->close;
    return undef;
    }
    
  $session->close;
  print time." $MODNAME: snmp_mod_walk() [$response]\n" if $conf{DEBUGLEVEL} >= 3;
  return $response;
  }

#
# snmp_sys_walk($host, $community, $oid)
#
# THis is the system command based fallback to snmp_walk, which 
# will be used if no CPAN module is availible on the system using 
# snmp_walk.
#

sub snmp_sys_walk {
  my ($host,$com,$oid)=@_;
  undef my %result;

  defined($conf{SNMPWALK}) || return undef;

  my $command;
 
  if($agent_v{$host} eq '2c') {
    $command = "$conf{SNMPBULKWALK} -c $com -v 2c -r 1 -t 2 -On -Oq $host $oid";
  } else {
    $command = "$conf{SNMPWALK} -c $com -v 1 -r 1 -t 2 -On -Oq $host $oid";
  }

  open OUTPUT,"$command|" || return undef;
  while (<OUTPUT>) {
    chomp;
    my ($key, $value) = split;
    $result{$key} = $value;
    }
  close OUTPUT;

  print time." $MODNAME: snmp_sys_walk() [".\%result."]\n" if $conf{DEBUGLEVEL} >= 3;
  return \%result;
  }

#
# snmp_sys_get($host, $community, $oid)
#
# Analog to all the others here is the fallback to system commands 
# for the get function. Used if, how could it be, no CPAN module 
# availible. 
#

sub snmp_sys_get {
  my ($host,$com,$oid)=@_;
  defined($conf{SNMPGET}) || return undef;

  open RESULT,"$conf{SNMPGET} -c $com -v $agent_v{$host} -r 1 -t 2 -Oq $host $oid|" || return undef;
  my $result=<RESULT>;
  close RESULT;

  chomp $result;
  (undef, $result) = split / /,$result;

  print time." $MODNAME: snmp_sys_get() [$result]\n" if $conf{DEBUGLEVEL} >= 3;
  return $result;
  }

1;


Powered by WebSVN 2.2.1