SNMP Library for EventMachine
Summary
This gem extends Ruby-SNMP to use the asynchronous EventMachine library for added performance and scalability. This allows code to scale monitoring applications to access a very high number of devices without the need for complex asynchronous I/O handling.
Features
The library currently supports:
-
SNMP v1 and v2
-
SNMP Get, GetNext, Set, and Walk requests. For SNMPv2 clients, GetBulk and WalkBulk
-
Ability to query/set/walk multiple OIDs in parallel.
-
For Ruby 1.9 and above, fiber support to streamline asychronous code
Future revisions of this library may support:
-
Ability to act as an SNMP agent, responding to external queries.
There are no plans to support SNMP v3 or the parsing of MIB files.
Options
You may set the following options:
SNMP4EM::Manager.new(
:version => :SNMPv2c,
:host => "127.0.0.1",
:port => 161,
:community => "public", # Shorthand for setting both :community_ro and :community_rw
:community_ro => "public",
:community_rw => "public",
:fiber => false,
:timeout => 1,
:retries => 3 # Can also be specified as an array of individual timeouts
# For instance, [0.5, 1, 2.5] would send three requests with increasing timeout values
)
These options may also be passed to an individual query method, for instance:
snmp = SNMP4EM::Manager.new(...)
snmp.get(OID, :retries => 2, :timeout => 1)
And when receiving traps:
SNMP4EM::NotificationManager.new(
:host => "127.0.0.1", # Local interface on which to listen for traps. By default, localhost only!
:port => 161 # Port on which to listen for traps.
)
Backwards compatibility
Version 1.0.0 tweaks the return values of a few functions. Please test code thoroughly before upgrading to 1.0.0 in production!
Running tests
This library now includes a full suite of functional tests. They communicate with an SNMP daemon running on the localhost. The library comes with the necessary configuration, but it’s much easier to fire up the provided rake task (‘rake server`), running in a separate terminal window, before running `rspec`. This works fine on a Mac OS X machine using homebrew (`brew install net-snmp`).
Acknowledgements
-
The SNMP packet processing is handled by the Ruby-SNMP library, by David Halliday
-
EventMachine, by Francis Cianfrocca and Aman Gupta
-
All the helpful folks on the Freenode #eventmachine channel
Examples
A few definitions:
OID_SYSTEM = "1.3.6.1.2.1.1"
OID_SYSNAME = "1.3.6.1.2.1.1.5.0"
OID_SYSLOCATION = "1.3.6.1.2.1.1.6.0"
A simple SNMP-GET:
EM.run {
snmp = SNMP4EM::Manager.new(:host => "192.168.1.1")
request = snmp.get([OID_SYSNAME, OID_SYSLOCATION])
request.callback do |response|
puts "System name = #{response[OID_SYSNAME]}"
puts "System location = #{response[OID_SYSLOCATION]}"
end
request.errback do |error|
puts "GET got error #{error}"
end
}
A simple SNMP-GETNEXT:
EM.run {
snmp = SNMP4EM::Manager.new(:host => "192.168.1.1")
request = snmp.getnext(OID_SYSNAME)
request.callback do |response|
r = response[OID_SYSNAME]
puts "The next OID is #{r[0]}, the next value is #{r[1]}"
end
request.errback do |error|
puts "GETNEXT got error #{error}"
end
}
A simple SNMP-SET:
EM.run {
snmp = SNMP4EM::Manager.new(:host => "192.168.1.1")
request = snmp.set({OID_SYSNAME => "My System Name", OID_SYSLOCATION => "My System Location"})
request.callback do |response|
if (response[OID_SYSNAME] == true)
puts "System name set successful"
else
puts "System name set unsuccessful: #{response[OID_SYSNAME]}"
end
if (response[OID_SYSLOCATION] == true)
puts "System location set successful"
else
puts "System location set unsuccessful: #{response[OID_SYSLOCATION]}"
end
end
request.errback do |error|
puts "SET got error #{error}"
end
}
A simple SNMP-WALK:
EM.run {
snmp = SNMP4EM::Manager.new(:host => "192.168.1.1")
request = snmp.walk(OID_SYSTEM)
request.callback do |response|
response[OID_SYSTEM].each do |oid, value|
puts "#{oid} = #{value}"
end
end
request.errback do |error|
puts "WALK got error #{error}"
end
}
A simple SNMP-BULKWALK:
EM.run {
snmp = SNMP4EM::Manager.new(:host => "192.168.1.1")
request = snmp.bulkwalk(OID_SYSTEM)
request.callback do |response|
response[OID_SYSTEM].each do |oid, value|
puts "#{oid} = #{value}"
end
end
request.errback do |error|
puts "BULK-WALK got error #{error}"
end
}
A simple SNMP-GET-BULK:
EM.run {
snmp = SNMP4EM::Manager.new(:host => "192.168.1.1")
request = snmp.getbulk(OID_SYSTEM)
request.callback do |response|
response[OID_SYSTEM].each do |oid, value|
puts "#{oid} = #{value}"
end
end
request.errback do |error|
puts "GET-BULK got error #{error}"
end
}
Handling traps:
EM.run {
manager = SNMP4EM::NotificationManager.new
manager.on_trap do |trap|
if trap.is_a? SNMP::SNMPv1_Trap
puts "Got a SNMPv1_Trap"
elsif trap.is_a? SNMP::SNMPv2_Trap
puts "Got a SNMPv2_Trap"
end
end
}
Fiber Support
If your Ruby supports it, you can pass enable fibers, either per-manager or per-request. This unwinds much of the complexity in writing event-driven code. Instead of receiving an object on which to hang callbacks, the current fiber will be suspended until the response is available. If an error occurs, it will be returned as a SNMP::RequestTimeout. Unfortunately, there is no way to raise this error, you are responsible for manually checking whether the returned object is an error or not.
For example:
EM.run {
snmp = SNMP4EM::Manager.new(:host => "192.168.1.1")
f = Fiber.new do
response = snmp.get([OID_SYSNAME, OID_SYSLOCATION])
if response.is_a? SNMP::RequestTimeout
puts "Uh oh!"
else
puts "System name = #{response[OID_SYSNAME]}"
puts "System location = #{response[OID_SYSLOCATION]}"
end
end
}
Change Log
Version 1.1.5:
-
Fix memory leak (#10), many thanks to @paddor
Version 1.1.5:
-
Fix an error when constructing a GetBulkRequest when using version >= 1.3.1 of the SNMP gem
Version 1.1.2:
-
Changed timeout error handling. We now raise a SNMP::RequestTimeout instead of a StandardError.
Version 1.1.0:
-
Fiber support
Version 1.0.2:
-
Ability to specify timeouts as an array of timeout values. Inspired by github.com/calmh/node-snmp-native.
Version 1.0.1:
-
Requests resulting in an error now return nil unless return_raw is enabled
Version 1.0.0:
-
Added SNMPv2 BULKWALK support
-
Added ability to receive SNMP traps / informs
-
Added functional tests (finally!)
-
Moved documentation to Yard
-
Lots of code cleanup
Version 0.2.1:
-
Code cleanups, speed boosts
Version 0.2.0:
-
Added support for SNMPv2, including GET-BULK operations
Version 0.1.0:
-
Initial deployment, ability to run get/getnext/set/walk requests in parallel
Credits
Author: Norman Elton [email protected]