perfSONAR_PS::Collectors::LinkStatus::Agent::SNMP - This module provides an


perfSONAR_PS-Collectors-LinkStatus documentation Contained in the perfSONAR_PS-Collectors-LinkStatus distribution.

Index


Code Index:

NAME

Top

perfSONAR_PS::Collectors::LinkStatus::Agent::SNMP - This module provides an agent for the Link Status Collector that gets status information for a link by asking an SNMP server.

DESCRIPTION

Top

This agent will query the SNMP service and return the estimated time on the SNMP server, along with the status of the given interface. The actual structure of the agent is split into two pieces (stored in one file for clarity). There's an element whose sole purpose is to grab all the SNMP stats from a given host and cache them. This is described at the bottom of the file. Then, there is a higher-level agent, whose sole purpose is to get a single data point for a single ifIndex. The caching object is meant to be shared among all the agents so that it does not clutter the SNMP server with numerous calls each time status information is grabbed. While users can get the caching element for a given agent, they should not interact with it directly.

API =cut

Top

new ($package, $status_type, $hostname, $ifIndex, $version, $community, $oid, $agent) This function instantiates a new SNMP Agent for grabbing the ifIndex/oid off the specified host. The $agent element is an optional one that can be used to pass in an existing caching object. If unspecified, a new caching object will be created. =cut

getType Returns the status type of this agent: admin or oper. =cut

setType ($self, $type) Sets the status type of this agent: admin or oper. =cut

setHostname ($self, $hostname) Sets the hostname for this agent to poll. =cut

getHostname ($self) Returns the hostname that this agent is polling. =cut

setifIndex ($self, $ifIndex) Sets the ifIndex that this agent returns the status of. =cut

getifIndex ($self) Returns the ifIndex that this agent returns the status of. =cut

setCommunity ($self, $community) Sets the community string that will be used by this agent. =cut

getCommunity ($self) Returns the community string that will be used by this agent. =cut

setVersion ($self, $version) Sets the snmp version string for this agent. =cut

getVersion ($self) Returns the snmp version string for this agent. =cut

setOID ($self, $oid) Sets the OID for this agent. =cut

getOID ($self) Returns the OID for this agent. =cut

setAgent ($self, $agent) Sets the caching snmp object used by this agent =cut

getAgent ($self) Returns the caching snmp object used by this agent =cut

run ($self) Queries the local caching object for the OID/ifIndex of interest and grabs the most recent time for the SNMP server. It then converts the result of the OID/ifIndex into a known status type and returns the time/status. =cut

VERSION

Top

$Id:$

AUTHOR

Top

Aaron Brown, aaron@internet2.edu

LICENSE

Top

You should have received a copy of the Internet2 Intellectual Property Framework along with this software. If not, see <http://www.internet2.edu/membership/ip.html>

COPYRIGHT

Top


perfSONAR_PS-Collectors-LinkStatus documentation Contained in the perfSONAR_PS-Collectors-LinkStatus distribution.
package perfSONAR_PS::Collectors::LinkStatus::Agent::SNMP;

use strict;
use warnings;

use fields 'TYPE', 'HOSTNAME', 'IFINDEX', 'COMMUNITY', 'VERSION', 'OID', 'AGENT';


our $VERSION = 0.09;

sub new {
    my ($class, $type, $hostname, $ifIndex, $version, $community, $oid, $agent) = @_;

    my $self = fields::new($class);

    if ($agent ne "") {
        $self->{"AGENT"} = $agent;
    } else {
        $self->{"AGENT"} = new perfSONAR_PS::Collectors::LinkStatus::SNMPAgent( $hostname, "" , $version, $community, "");
    }

    $self->{"TYPE"} = $type;
    $self->{"HOSTNAME"} = $hostname;
    $self->{"IFINDEX"} = $ifIndex;
    $self->{"COMMUNITY"} = $community;
    $self->{"VERSION"} = $version;
    $self->{"OID"} = $oid;

    return $self;
}

sub getType {
    my ($self) = @_;

    return $self->{TYPE};
}

sub setType {
    my ($self, $type) = @_;

    $self->{TYPE} = $type;

    return;
}

sub setHostname {
    my ($self, $hostname) = @_;

    $self->{HOSTNAME} = $hostname;

    return;
}

sub getHostname {
    my ($self) = @_;

    return $self->{HOSTNAME};
}

sub setifIndex {
    my ($self, $ifIndex) = @_;

    $self->{IFINDEX} = $ifIndex;

    return;
}

sub getifIndex {
    my ($self) = @_;

    return $self->{IFINDEX};
}

sub setCommunity {
    my ($self, $community) = @_;

    $self->{COMMUNITY} = $community;

    return;
}

sub getCommunity {
    my ($self) = @_;

    return $self->{COMMUNITY};
}

sub setVersion {
    my ($self, $version) = @_;

    $self->{VERSION} = $version;

    return;
}

sub getVersion {
    my ($self) = @_;

    return $self->{VERSION};
}

sub setOID {
    my ($self, $oid) = @_;

    $self->{OID} = $oid;

    return;
}

sub getOID {
    my ($self) = @_;

    return $self->{OID};
}

sub setAgent {
    my ($self, $agent) = @_;

    $self->{AGENT} = $agent;

    return;
}

sub getAgent {
    my ($self) = @_;

    return $self->{AGENT};
}

sub run {
    my ($self) = @_;

    $self->{AGENT}->setSession;
    my $measurement_value = $self->{AGENT}->getVar($self->{OID}.".".$self->{IFINDEX});
    my $measurement_time = $self->{AGENT}->getHostTime;
    $self->{AGENT}->closeSession;

    if (defined $measurement_value) {
        if ($self->{OID} eq "1.3.6.1.2.1.2.2.1.8") {
            if ($measurement_value eq "2") {
                $measurement_value = "down";
            } elsif ($measurement_value eq "1") {
                $measurement_value = "up";
            } else {
                $measurement_value = "unknown";
            }
        } elsif ($self->{OID} eq "1.3.6.1.2.1.2.2.1.7") {
            if ($measurement_value eq "2") {
                $measurement_value = "down";
            } elsif ($measurement_value eq "1") {
                $measurement_value = "normaloperation";
            } elsif ($measurement_value eq "3") {
                $measurement_value = "troubleshooting";
            } else {
                $measurement_value = "unknown";
            }
        }
    } else {
        return (-1, "No value for measurement");
    }

    return (0, $measurement_time, $measurement_value);
}

1;

# ================ Internal Package perfSONAR_PS::Collectors::LinkStatus::SNMPAgent ================

package perfSONAR_PS::Collectors::LinkStatus::Agent::SNMP::Host;

use Net::SNMP;
use Log::Log4perl qw(get_logger);

use perfSONAR_PS::Common;

use fields 'HOST', 'PORT','VERSION', 'COMMUNITY', 'VARIABLES', 'CACHED_TIME', 'CACHE_LENGTH', 'HOSTTICKS', 'SESSION', 'ERROR', 'REFTIME', 'CACHED';

sub new {
    my ($class, $host, $port, $ver, $comm, $vars, $cache_length) = @_;

    my $self = fields::new($class);

    if(defined $host and $host ne "") {
        $self->{"HOST"} = $host;
    }
    if(defined $port and $port ne "") {
        $self->{"PORT"} = $port;
    } else {
        $self->{"PORT"} = 161;
    }
    if(defined $ver and $ver ne "") {
        $self->{"VERSION"} = $ver;
    }
    if(defined $comm and $comm ne "") {
        $self->{"COMMUNITY"} = $comm;
    }
    if(defined $vars and $vars ne "") {
        $self->{"VARIABLES"} = \%{$vars};
    } else {
        $self->{"VARIABLES"} = ();
    }
    if (defined $cache_length and $cache_length ne "") {
        $self->{"CACHE_LENGTH"} = $cache_length;
    } else {
        $self->{"CACHE_LENGTH"} = 1;
    }

    $self->{"VARIABLES"}->{"1.3.6.1.2.1.1.3.0"} = ""; # add the host ticks so we can track it
        $self->{"HOSTTICKS"} = 0;

    return $self;
}

sub setHost {
    my ($self, $host) = @_;
    my $logger = get_logger("perfSONAR_PS::Collectors::LinkStatus::SNMPAgent");

    if(defined $host and $host ne "") {
        $self->{HOST} = $host;
        $self->{HOSTTICKS} = 0;
    } else {
        $logger->error("Missing argument.");
    }
    return;
}


sub setPort {
    my ($self, $port) = @_;
    my $logger = get_logger("perfSONAR_PS::Collectors::LinkStatus::SNMPAgent");

    if(defined $port and $port ne "") {
        $self->{PORT} = $port;
    } else {
        $logger->error("Missing argument.");
    }
    return;
}


sub setVersion {
    my ($self, $ver) = @_;
    my $logger = get_logger("perfSONAR_PS::Collectors::LinkStatus::SNMPAgent");

    if(defined $ver and $ver ne "") {
        $self->{VERSION} = $ver;
    } else {
        $logger->error("Missing argument.");
    }
    return;
}


sub setCommunity {
    my ($self, $comm) = @_;
    my $logger = get_logger("perfSONAR_PS::Collectors::LinkStatus::SNMPAgent");

    if(defined $comm and $comm ne "") {
        $self->{COMMUNITY} = $comm;
    } else {
        $logger->error("Missing argument.");
    }
    return;
}


sub setVariables {
    my ($self, $vars) = @_;
    my $logger = get_logger("perfSONAR_PS::Collectors::LinkStatus::SNMPAgent");

    if(defined $vars and $vars ne "") {
        $self->{"VARIABLES"} = \%{$vars};
    } else {
        $logger->error("Missing argument.");
    }
    return;
}

sub setCacheLength {
    my ($self, $cache_length) = @_;

    if (defined $cache_length and $cache_length ne "") {
        $self->{"CACHE_LENGTH"} = $cache_length;
    }
    return;
}

sub addVariable {
    my ($self, $var) = @_;
    my $logger = get_logger("perfSONAR_PS::Collectors::LinkStatus::SNMPAgent");

    if(not defined $var or $var eq "") {
        $logger->error("Missing argument.");
    } else {
        $self->{VARIABLES}->{$var} = "";
    }
    return;
}

sub getVar {
    my ($self, $var) = @_;
    my $logger = get_logger("perfSONAR_PS::Collectors::LinkStatus::SNMPAgent");

    if(not defined $var or $var eq "") {
        $logger->error("Missing argument.");
        return;
    } 

    if (not defined $self->{VARIABLES}->{$var} or not defined $self->{CACHED_TIME} or time() - $self->{CACHED_TIME} > $self->{CACHE_LENGTH}) {
        $self->{VARIABLES}->{$var} = "";

        my ($status, $res) = $self->collectVariables();
        if ($status != 0) {
            return;
        }

        my %results = %{ $res };

        $self->{CACHED} = \%results;
        $self->{CACHED_TIME} = time();
    }

    return $self->{CACHED}->{$var};
}

sub getHostTime {
    my ($self) = @_;
    return $self->{REFTIME};
}

sub refreshVariables {
    my ($self) = @_;
    my ($status, $res) = $self->collectVariables();

    if ($status != 0) {
        return;
    }

    my %results = %{ $res };

    $self->{CACHED} = \%results;
    $self->{CACHED_TIME} = time();

    return;
}

sub getVariableCount {
    my ($self) = @_;

    my $num = 0;
    foreach my $oid (keys %{$self->{VARIABLES}}) {
        $num++;
    }
    return $num;
}

sub removeVariables {
    my ($self) = @_;
    my $logger = get_logger("perfSONAR_PS::Collectors::LinkStatus::SNMPAgent");

    undef $self->{VARIABLES};
    if(defined $self->{VARIABLES}) {
        $logger->error("Remove failure.");
    }
    return;
}

sub removeVariable {
    my ($self, $var) = @_;
    my $logger = get_logger("perfSONAR_PS::Collectors::LinkStatus::SNMPAgent");

    if(defined $var and $var ne "") {
        delete $self->{VARIABLES}->{$var};
    } else {
        $logger->error("Missing argument.");
    }
    return;
}

sub setSession {
    my ($self) = @_;
    my $logger = get_logger("perfSONAR_PS::Collectors::LinkStatus::SNMPAgent");

    if((defined $self->{COMMUNITY} and $self->{COMMUNITY} ne "") and
            (defined $self->{VERSION} and $self->{VERSION} ne "") and
            (defined $self->{HOST} and $self->{HOST} ne "") and
            (defined $self->{PORT} and $self->{PORT} ne "")) {

        ($self->{SESSION}, $self->{ERROR}) = Net::SNMP->session(
                -community     => $self->{COMMUNITY},
                -version       => $self->{VERSION},
                -hostname      => $self->{HOST},
                -port          => $self->{PORT},
                -translate     => [
                -timeticks => 0x0
                ]) or $logger->error("Couldn't open SNMP session to \"".$self->{HOST}."\".");

        if(not defined($self->{SESSION})) {
            $logger->error("SNMP error: ".$self->{ERROR});
        }
    }
    else {
        $logger->error("Session requires arguments 'host', 'version', and 'community'.");
    }
    return;
}

sub closeSession {
    my ($self) = @_;
    my $logger = get_logger("perfSONAR_PS::Collectors::LinkStatus::SNMPAgent");

    if(defined $self->{SESSION}) {
        $self->{SESSION}->close;
    } else {
        $logger->error("Cannont close undefined session.");
    }
    return;
}

sub collectVariables {
    my ($self) = @_;
    my $logger = get_logger("perfSONAR_PS::Collectors::LinkStatus::SNMPAgent");

    if(defined $self->{SESSION}) {
        my @oids = ();

        foreach my $oid (keys %{$self->{VARIABLES}}) {
            push @oids, $oid;
        }

        my $res = $self->{SESSION}->get_request(-varbindlist => \@oids) or $logger->error("SNMP error.");

        if(not defined($res)) {
            my $msg = "SNMP error: ".$self->{SESSION}->error;
            $logger->error($msg);
            return (-1, $msg);
        } else {
            my %results;

            %results = %{ $res };

            if (not defined $results{"1.3.6.1.2.1.1.3.0"}) {
                $logger->warn("No time values, getTime may be screwy");
            } else {
                my $new_ticks = $results{"1.3.6.1.2.1.1.3.0"} / 100;

                if ($self->{HOSTTICKS} == 0) {
                    my($sec, $frac) = Time::HiRes::gettimeofday;
                    $self->{REFTIME} = $sec.".".$frac;
                } else {
                    $self->{REFTIME} += $new_ticks - $self->{HOSTTICKS};
                }

                $self->{HOSTTICKS} = $new_ticks;
            }

            return (0, $res);
        }
    } else {
        my $msg = "Session to \"".$self->{HOST}."\" not found.";
        $logger->error($msg);
        return (-1, $msg);
    }
}

sub collect {
    my ($self, $var) = @_;
    my $logger = get_logger("perfSONAR_PS::Collectors::LinkStatus::SNMPAgent");

    if(defined $var and $var ne "") {
        if(defined $self->{SESSION}) {
            my $results = $self->{SESSION}->get_request(-varbindlist => [$var]) or $logger->error("SNMP error: \"".$self->{ERROR}."\".");
            if(not defined($results)) {
                $logger->error("SNMP error: \"".$self->{ERROR}."\".");
                return -1;
            } else {
                return $results->{"$var"};
            }
        } else {
            $logger->error("Session to \"".$self->{HOST}."\" not found.");
            return -1;
        }
    } else {
        $logger->error("Missing argument.");
    }
    return;
}

1;

__END__

To join the 'perfSONAR-PS' mailing list, please visit:

https://mail.internet2.edu/wws/info/i2-perfsonar

The perfSONAR-PS subversion repository is located at:

https://svn.internet2.edu/svn/perfSONAR-PS

Questions and comments can be directed to the author, or the mailing list.  Bugs,
feature requests, and improvements can be directed here:

https://bugs.internet2.edu/jira/browse/PSPS

# vim: expandtab shiftwidth=4 tabstop=4