= net-snmp
== DESCRIPTION
net-snmp is a Ruby object oriented wrapper around the C netsnmp[http://www.net-snmp.org] libraries.
It provides classes for sessions, pdus, varbinds, and more.
== FEATURES
- Supports SNMP versions 1, 2c, and 3
- Supports both synchronous and asynchronous calls
- Supports sending of snmpv1 traps and snmpv2 traps/informs using TrapSession
- Integrates well with eventmachine, or can be used standalone.
- In Ruby 1.9, uses fibers behind the scenes to emulate synchronous calls asynchronously
- MIB support
- Convenience methods such as session.walk, session.get_columns, and session.table
== USAGE
You must have the net-snmp libraries installed and available on the system. Check to make sure
they are available in your library path. If necessary, add them to your shell like so:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/local/lib/net-snmp
You can use the library in two styles: synchronously or asynchronously. If you use the synchronous style,
calls will block until a result is returned or the request times out. If you use the asynchronous style, you
must provide a block to the client methods, which will be called when the data is ready.
In order for your callbacks to fire, you must call Net::SNMP::Dispatcher.poll You may pass a timeout argument to
the dispatcher. If you pass false, the call will block forever until data is ready. If you pass an integer, it will block for
seconds. If you pass nil (the default), it will do a poll and return immediately. In that case, you
will have to arrange for the dispatcher to run periodically. This can be done in your main event loop or in a
seperate thread. There are convenience class methods in Net::SNMP::Dispatcher called run_loop, fiber_loop, em_loop, thread_loop
and so on for setting up various polling loops. Or, you can roll your own loop.
If you like eventmachine, it's very easy to set up the dispatcher to run periodically in the adaptor. If you're
using eventmachine with ruby 1.9, the library uses fibers behind the scenes to turn your synchronous calls into asynchronous
calls, while allowing you to use a synchronous calling style. Examples of all these scenarios are below.
== FFI
This library uses ruby-ffi to access the net-snmp libraries. If you want to use the C library directly, the wrapper
functions are defined in Net::SNMP::Wrapper. You can call them like so:
Net::SNMP::Wrapper.snmp_perror("some_error")
== NOTES
You must call Session.close when you're done with a session to avoid leaking memory
== ERROR HANDLING
In the synchronous versions, all session methods raise Net::SNMP:Error on any error. Timeouts raise Net::SNMP::TimeoutError.
In the asynchronous versions, the first argument to your callback will be the return status. Possible values include :success, :timeout, and :send_error.
If you need the underlying net-snmp session errors, you can call session.errno, session.snmp_err, and session.error_message.
PDU errors can be retreived with pdu.errstat, pdu.errindex giving the index of the offending varbind. See constants.rb for possible errors.
== EXAMPLES
A simple synchronous SNMP-GET
session = Net::SNMP::Session.open(:peername => "test.net-snmp.org", :community => "demopublic" )
begin
pdu = session.get("sysDescr.0")
puts pdu.varbinds.first.value
rescue Net::SNMP::Error => e
puts e.message
end
session.close
An asynchronous SNMP-GET
session = Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :community => 'demopublic') do |session|
session.get(["sysDescr.0", "sysContact.0"]) do |status, pdu|
if status == :success
puts pdu.varbinds[0].value
else
puts "something went wrong. status is #{status}"
end
end
end
Net::SNMP::Dispatcher.select(false) #Setting timeout to false causes dispatcher to block until data is ready
session.close
An SNMPv3 synchronous AuthPriv (encrypted) SNMP-GET
Net::SNMP::Session.open(:peername => "test.net-snmp.org",
:community => "demopublic",
:version => "3",
:security_level => Net::SNMP::Constants::SNMP_SEC_LEVEL_AUTHPRIV,
:auth_protocol => :sha1,
:priv_protocol => :des,
:username => "myuser",
:auth_password => "mypassword",
:priv_password => "myprivpasswd"
) {|session|
begin
pdu = session.get("sysDescr.0")
puts pdu.varbinds.first.value
rescue Net::SNMP::Error => e
puts e.message
end
end
Running the dispatcher from eventmachine
EM.run do
Net::SNMP::Dispatcher.em_loop
session = Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :community => 'demopublic') do |session|
session.get("sysDescr.0") do |status, pdu|
if status == :success
puts pdu.varbinds[0].value
else
puts "something went wrong. status is #{status}"
end
end
end
EM.add_timer(2) do
session.close
EM.stop
end
end
Using synchronous style with eventmachine in ruby 1.9
EM.run do
Net::SNMP::Dispatcher.fiber_loop
Fiber.new {
session = Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :community => 'demopublic')
begin
pdu = session.get("sysDescr.0")
puts pdu.varbinds[0].value
rescue Net::SNMP::Error => e
puts e.message
end
session.close
EM.stop
}.resume
end
In the last example, note that you must wrap your code in Fiber.new {}.resume. You could instead use the
em-synchrony[https://github.com/igrigorik/em-synchrony] gem, and wrap your loop with EM.synchrony{}.
Note that even though it appears you are making a blocking call, waiting for a return value, actually in the
background, control is passed back to the reactor fiber to process other requests. get() will return once the
data is available. This is all seemless to you, the developer. Behold the power of fibers!
== MIBs
By default, net-snmp loads all of your system MIBS. You can add additional mibs by adding them to your MIBS environment variable.
You can also explicitly add MIBs using the MIB api. For example:
Net::SNMP::MIB.add_mibdir("/usr/local/share/mibs")
Net::SNMP::MIB.read_mib("RFC1213-MIB.txt")
Having the appropriate MIBs loaded will allow you to pass names instead of numeric oids to net-snmp methods. You can also pass
Net::SNMP::OID objects. For example
oid = Net::SNMP::OID.new('sysDescr.0') # or Net::SNMP::OID.new("1.3.6.1.2.1.1.1.0")
puts oid.to_s --> '1.3.6.1.2.1.1.1.0'
puts oid.label --> 'sysDescr.0'
pdu = session.get([oid])
For more complex MIB parsing needs, see smi-ffi[http://github.com/mixtli/smi-ffi]
== EXPERIMENTAL THREAD SUPPORT
If you intent to use threads, you should set:
Net::SNMP.thread_safe = true
Thread support is experimental and may be dropped. Let me know if you're using this feature.
== CAVEATS/DISCLAIMER
THIS GEM COULD CRASH YOUR SYSTEM AND EAT YOUR CHILDREN!
You have been warned.
The API is subject to change.
This is very much alpha software. For more information on usage, take a look at the specs. Currently it's
only tested against net-snmp 5.5. The net-snmp api seems pretty stable, but if anything changes, it could
break this gem. Please let me know if you find bugs or missing features. Or better yet, send a pull request.
== TODO
* Implement walk and get_table convenience methods.
* SNMPv3 support needs testing for various security models
* Better documentation
* More tests
== Note on Patches/Pull Requests
* Fork the project.
* Make your feature addition or bug fix.
* Add tests for it. This is important so I don't break it in a
future version unintentionally.
* Commit, do not mess with rakefile, version, or history.
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
* Send me a pull request. Bonus points for topic branches.
* Bug reports including a failing rspec get priority treatment
== Copyright
Copyright (c) 2010 mixtli. See LICENSE for details.