I realized that some of that could still be achieved with
snmp_dispatcher, so I wrote another example to be put into the POD
documentation. This would probably fulfill the bug, rather than talking
about snmp_dispatch_once.
Here's the POD code. You will likely need to look at it from the
text/plain download from RT to get the right space formatting.
-----------------------
=head2 5. Non-blocking SNMPv1 get-request on multiple hosts and multiple
OIDs
(with poll buffering)
This example polls many different hosts using multiple OIDs. Unlike the
previous example, this one only polls a set number of hosts at a time. The
results are cached until the host has given all of the information. Then the
results are printed, the host's cache is removed, and another host is
loaded. This will keep exactly $MAX_HOST hosts (currently set to 5) polling
at all times.
This set up is good for a large amount of hosts polling the same data. With
the right machine, retry/timeout settings, and max number of hosts, this set
up could poll hundreds of hosts a minute. Forking to multiple processes on
a multi-core system would produce even faster polling.
#! /usr/local/bin/perl
use strict;
use warnings;
use Net::SNMP;
# Some constants/globals
my $MAX_HOSTS = 5;
my %LOADED;
my %CACHE;
# Hash of OIDs
my %OID = (
'sysUpTime' => '1.3.6.1.2.1.1.3.0',
'sysContact' => '1.3.6.1.2.1.1.4.0',
'sysLocation' => '1.3.6.1.2.1.1.6.0',
);
# Hash of hosts and location data.
my %host_data = (
'10.1.1.1' => 'Building 1, First Floor',
'10.1.1.2' => 'Building 1, Second Floor',
'10.2.1.1' => 'Building 2, First Floor',
'10.2.1.2' => 'Building 2, Second Floor',
'10.3.1.1' => 'Building 3, First Floor',
'10.3.1.2' => 'Building 3, Second Floor',
'10.4.1.1' => 'Building 4, First Floor',
'10.4.1.2' => 'Building 4, Second Floor',
'10.5.1.1' => 'Building 5, First Floor',
'10.5.1.2' => 'Building 5, Second Floor',
'localhost' => 'Right here!',
);
my @HOST_LIST = sort keys %host_data;
# Load the hosts up to MAX_HOSTS
for my $i (1 .. $MAX_HOSTS) {
my $host = shift @HOST_LIST;
&load_host($host);
}
# Now initiate the SNMP message exchange.
snmp_dispatcher();
exit 0;
# Opens the session and send the get_requests for the specific host
sub load_host
{
my ($host) = @_;
my ($session, $error) = Net::SNMP->session(
-hostname => $host,
-community => 'private',
-nonblocking => 1,
);
if (!defined $session) {
printf "ERROR: Failed to create session for host '%s': %s.\n",
$host, $error;
next;
}
for my $oid_name (sort keys %OID) {
my $result = $session->get_request(
-varbindlist => [$OID{$oid_name}],
-callback => [ \&get_callback, $host, $oid_name ],
);
if (!defined $result) {
printf "ERROR: Failed to queue get request for host '%s':
%s.\n",
$session->hostname(), $session->error();
}
$LOADED{$host}->{$oid_name} = 1;
}
return;
}
# Process each OID, cache them, and then run the print_host function when
# all of the OIDs are collected for that host
sub get_callback
{
my ($session, $host, $oid_name) = @_;
delete $LOADED{$host}->{$oid_name};
my $result = $session->var_bind_list;
if (!defined $result) {
printf "ERROR: Get request failed for host '%s': %s.\n",
$session->hostname(), $session->error();
return;
}
my @values = values %{$result};
$CACHE{$host}->{$oid_name} = $values[0];
# If we are finished with all of the OIDs, print the details, remove
# the cache, and load another host
unless (keys %{$LOADED{$host}}) {
&print_host($host);
delete $CACHE{$host};
if (@HOST_LIST) {
my $new_host = shift @HOST_LIST;
&load_host($new_host);
}
}
return;
}
sub print_host
{
my ($host) = @_;
print $host_data{$host}.":\n";
for my $oid_name (sort keys %OID) {
print "\t$oid_name: ".$CACHE{$host}->{$oid_name}."\n";
}
return;
}