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


perfSONAR_PS-Collectors-LinkStatus documentation  | view source Contained in the perfSONAR_PS-Collectors-LinkStatus distribution.

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

use strict; use warnings;

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

our $VERSION = 0.09;

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 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;
}

getType Returns the status type of this agent: admin or oper. =cut sub getType { my ($self) = @_;

    return $self->{TYPE};
}

setType ($self, $type) Sets the status type of this agent: admin or oper. =cut sub setType { my ($self, $type) = @_;

    $self->{TYPE} = $type;

    return;
}

setHostname ($self, $hostname) Sets the hostname for this agent to poll. =cut sub setHostname { my ($self, $hostname) = @_;

    $self->{HOSTNAME} = $hostname;

    return;
}

getHostname ($self) Returns the hostname that this agent is polling. =cut sub getHostname { my ($self) = @_;

    return $self->{HOSTNAME};
}

setifIndex ($self, $ifIndex) Sets the ifIndex that this agent returns the status of. =cut sub setifIndex { my ($self, $ifIndex) = @_;

    $self->{IFINDEX} = $ifIndex;

    return;
}

getifIndex ($self) Returns the ifIndex that this agent returns the status of. =cut sub getifIndex { my ($self) = @_;

    return $self->{IFINDEX};
}

setCommunity ($self, $community) Sets the community string that will be used by this agent. =cut sub setCommunity { my ($self, $community) = @_;

    $self->{COMMUNITY} = $community;

    return;
}

getCommunity ($self) Returns the community string that will be used by this agent. =cut sub getCommunity { my ($self) = @_;

    return $self->{COMMUNITY};
}

setVersion ($self, $version) Sets the snmp version string for this agent. =cut sub setVersion { my ($self, $version) = @_;

    $self->{VERSION} = $version;

    return;
}

getVersion ($self) Returns the snmp version string for this agent. =cut sub getVersion { my ($self) = @_;

    return $self->{VERSION};
}

setOID ($self, $oid) Sets the OID for this agent. =cut sub setOID { my ($self, $oid) = @_;

    $self->{OID} = $oid;

    return;
}

getOID ($self) Returns the OID for this agent. =cut sub getOID { my ($self) = @_;

    return $self->{OID};
}

setAgent ($self, $agent) Sets the caching snmp object used by this agent =cut sub setAgent { my ($self, $agent) = @_;

    $self->{AGENT} = $agent;

    return;
}

getAgent ($self) Returns the caching snmp object used by this agent =cut sub getAgent { my ($self) = @_;

    return $self->{AGENT};
}

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 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

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  | view source Contained in the perfSONAR_PS-Collectors-LinkStatus distribution.