POE::Component::SNMP 0.90

  Hi! I wanted to take a moment to explain how this version of this
module came into being.  I intend to ramble a bit, and you do *not*
need to read this to start using this module immediately.

  In early May of 2004, I jumped on to the #POE channel on IRC, and
merlyn (aka Randal Schwartz) was talking about a new POE script he was
working on, to demonstrate POE combined with Tk.  merlyn and dngnand
(aka Rocco Caputo, author of POE) were tossing variants back and forth
like madmen, and while various versions were flying by in the channel,
I grabbed one to see what the fuss was about.

  The script in question worked as follows: Open a POE::Wheel::Run
session, with this command: 

ssh $hostname "while uptime; do sleep 3; done"

Every 3 seconds, the host in question runs uptime(1), which, in
addition to showing the number of days since the system's last reboot,
also displays the system's load average over the last 1, 5, and 15
minutes.  Send the output of this command to a POE event which parses
the load averages out, and plot graphically using a Tk::Graph widget.

  One of the variants the flew by that day was one called
loadavg_multi.  It was capable of plotting the loads for multiple
hosts simultaneously, in different colors.  Since I administer a
network with roughly 30 or so active machines (with any number of
domains and virtual domains), this was a great utility for me to
monitor how they were doing, especially considering that part of my
workstation's display was already dedicated to multiple xload(1)
windows, showing exactly this data.

  I added the program to my startup sequence, and was quite happy.  I
even customized its output slightly to add an additional status report
having to do with estimated network hits/day.  But after running it
for a week or two, I noticed a problem: when the program's Tk window
was closed, the ssh sessions it had opened had a tendency to *stay*
open.  So the box I was running the graph on had a large number of
stale ssh connections open, each running uptime(1) every 3 seconds,
but none connected to any output.  This of course also included the
resources consumed on the boxes being monitored, again by stale ssh
sessions.

  I looked for a different solution, and remembered that the NET-SNMP
(formerly known as UCD-SNMP) daemon was capable of reporting system
load average via a SNMP variable.  Ah-hah!  All I had to do was
reconfigure the loadavg_multi program to use SNMP for its data instead
of ssh, and I would have the best of both worlds!  And look, somebody
had already written a POE::Component::SNMP... great!

  So I updated the script so that it got its data via SNMP, but then I
noticed something: the POE component (v0.01) had to be told explicitly
to dispatch its SNMP calls.  After a closer look, it turned out that
it didn't use POE's event loop at all, but instead blocked while
dispatching its own events via the internal dispatcher within the
Net::SNMP module.  Basically, the module's author had written a very
thin wrapper over Net::SNMP so that it could was invoked via POE's
events, but had not fully "POE-ized" the module.

  So I looked at the problem field: It seems that Net::SNMP uses a
singleton Dispatcher object to handle all of its scheduling and socket
communication.  That seemed to have some potential, as that would mean
that I might be able to simply replace that object with a POE-ized
subclass of it, and not have to change anything else.  Additionally,
dispatch seemed to be a sequence of listen/unlisten calls on UDP
sockets, and basic time delays within its event queue.  So my job
would be to intercept these calls to utilize POE's scheduling and
select() behavior, and I shouldn't have to touch anything else.
Great!

  Over the course of the next 2 weeks or so, in between tasks at work
and late at night at home, I subclassed Net::SNMP::Dispatcher as
POE::Component::SNMP::Dispatcher.  So far I had managed to add
behavior to POE-ize the POE SNMP component without having to touch the
original at all.  I had only one cosmetic change I wanted to make, but
could live without: when querying more than one host at a time, there
was no internal method for determining which host had responded, when
dispatching an event based on incoming SNMP data.  I had worked around
it by adding the target's hostname to the list of variables I was
querying for, but since I was experimenting privately, I could simply
add the hostname to the list of variables returned to the event.

  During this period, I had asked dngnand about a couple of POE
details, and had suggested he load POE::Component::SNMP and look at a
copy of my Dispatcher module to see what I was working on.  So dngnand
went to load the component from CPAN, only to find that the original
author had retired the module (which was now only available in the
CPAN archives, and not the live network).

  When I had completed the Dispatcher, I of course wanted to use it in
the loadavg_multi script, to plot the load on multiple simultaneous
hosts.  However, I found problem: Net::SNMP caches UDP socket handles
based on the LOCAL address.  What this meant was, the same socket was
being re-used for every query being made (regardless of how many
target hosts), which meant that I couldn't listen for responses to
more than one query (host) at a time.  Finally, I was now forced to
modify the original POE::Component::SNMP module to pass parameters to
Net::SNMP so that each SNMP session would get a different socket to
listen on.  However, with this change the component was finally,
truly, multiplexed and POE-ized.

  (I've included my loadavg_multi_snmp version of merlyn's original
script in the eg/ directory of the distribution.  If you find it
useful, drop me a line!)

  About this time, I contacted the module's original author, saying
I'd like to revive the module and either send in my patches or inherit
the module for myself.  I had to wait a few days (he was on vacation
:-), but then he finally responded with his endorsement and permission
for me to assume ownership of this POE component, for the good of the
greater Perl (and POE) community.


  So, with all that being said, I would like to publicly and profusely
thank Todd Caine for his original work in wrapping and packaging the
Net::SNMP module into the POE framework.  While his solution
technically wasn't "complete", it did lay 95% of the groundwork for
this module to reach the outside world.  I admit it, I'm great with
back ends, and terrible with interfaces.  If I had been the originator
of this module, the API would be clumsy and haphazard, and the
usefulness of it to anybody else would have probably been severely
limited.  As it was, I was able to extend this module without knowing
*ANYTHING* about SNMP, my contributions to this module have been
almost transparent to the user, and I've only added technical
enhancement to what was already a well designed, well written, and
well documented module.  Thank you, Todd!

Rob Bloodgood
June 10th, 2004
