class Sloth::Snmp
Constants
- VERSION
Public Class Methods
new( mibs: nil, bind: nil, rocommunity: "public", rwcommunity: "private" )
click to toggle source
# File lib/sloth/snmp/impl.rb, line 21 def initialize( mibs: nil, bind: nil, rocommunity: "public", rwcommunity: "private" ) case bind when Integer, NilClass @host = "0.0.0.0" @port = bind || 162 when String host, port = bind.split(':') rescue nil if host.nil? || host.empty? @host = "0.0.0.0" else @host = host end if port.nil? || port.empty? @port = 162 else @port = port.to_i end else raise Sloth::Snmp::Error, "invalid class. : %s" % bind.class end @rocommunity = rocommunity @rwcommunity = rwcommunity @mibs = SNMP::MIB.new @mibs.load_module( "RFC1155-SMI" ) @mibs.load_module( "RFC1158-MIB" ) case mibs when NilClass mibs = [] when Array # noop when String mibs = [mibs] else raise Sloth::Snmp::Error, "invalid class. : %s" % mibs.class end mibpath = mibs.shift while mibpath mibbase = File.basename( mibpath ) mibdir = File.dirname( mibpath ) if ( mibdir == "." && mibbase == mibpath ) @mibs.load_module( mibbase.gsub( /\..*\Z/, "" ) ) else @mibs.load_module( mibbase.gsub( /\..*\Z/, "" ), mibdir ) end mibpath = mibs.shift end @topics = {} @mutex = ::Mutex.new end
Public Instance Methods
build_varbind( topic, type, value )
click to toggle source
# File lib/sloth/snmp/impl.rb, line 282 def build_varbind( topic, type, value ) oid = SNMP::ObjectId.new( topic ) rescue @mibs.oid( topic ) case type when SNMP::OctetString SNMP::VarBind.new( oid, SNMP::OctetString.new( value )) when SNMP::Integer SNMP::VarBind.new( oid, SNMP::Integer.new( value )) when SNMP::Counter32 SNMP::VarBind.new( oid, SNMP::Counter32.new( value )) when SNMP::IpAddress SNMP::VarBind.new( oid, SNMP::IpAddress.new( value )) when SNMP::ObjectId SNMP::VarBind.new( oid, SNMP::ObjectId.new( value )) else SNMP::VarBind.new( oid, SNMP::OctetString.new( value.to_s )) end end
get( peer, topics, **options )
click to toggle source
# File lib/sloth/snmp/impl.rb, line 135 def get( peer, topics, **options ) host, port = peer.split(':') rescue nil host = "127.0.0.1" if host.nil? || host.empty? port = (port || 161).to_i community = options[:rocommunity] || @rocommunity case topics when String oids = [ ( SNMP::ObjectId.new( topics ) rescue @mibs.oid( topics ) ) ] when Array oids = topics.map do |topic| SNMP::ObjectId.new( topic ) rescue @mibs.oid( topic ) end else raise Sloth::Snmp::Error, "topics missing." end if options[:bindto] && options[:device] transport = UDPTransportExt.new( Socket::AF_INET, bindto: options[:bindto], device: options[:device] ) end manager = SNMP::Manager.new( host: host, port: port, community: community, transport: transport ) items = {} begin response = Thread.handle_interrupt( ::Timeout::Error => :on_blocking ) do manager.get( oids ) end response.each_varbind do |varbind| oid, item = * parse_varbind( varbind ) items[oid] = item end rescue SNMP::RequestTimeout => e raise Sloth::Snmp::Error, e.message rescue => e raise Sloth::Snmp::Error, e.message end items end
parse_varbind( varbind, keys: nil )
click to toggle source
# File lib/sloth/snmp/impl.rb, line 244 def parse_varbind( varbind, keys: nil ) keys = [:name, :value] if keys.nil? || keys.empty? oid = varbind.name.to_str name = @mibs.name( oid ) case varbind.value when SNMP::OctetString type = SNMP::OctetString valu = varbind.value.to_s if /[^[:print:]]/.match( valu ) valu = "0x" + valu.unpack("H*").shift end when SNMP::Integer type = SNMP::Integer valu = varbind.value.to_i when SNMP::Counter32 type = SNMP::Counter32 valu = varbind.value.to_i when SNMP::IpAddress type = SNMP::IpAddress valu = varbind.value.to_s when SNMP::ObjectId type = SNMP::ObjectId valu = varbind.value when SNMP::NoSuchInstance, SNMP::NoSuchObject type = varbind.value valu = nil else type = varbind.value valu = nil end tuple = {} tuple[:name] = name if keys.include?( :name ) tuple[:type] = type if keys.include?( :type ) tuple[:value] = valu if keys.include?( :value ) [oid, tuple] end
set( peer, tuple, **options )
click to toggle source
# File lib/sloth/snmp/impl.rb, line 213 def set( peer, tuple, **options ) host, port = peer.split(':') rescue nil host = "127.0.0.1" if host.nil? || host.empty? port = (port || 161).to_i community = options[:rwcommunity] || @rwcommunity if options[:bindto] && options[:device] transport = UDPTransportExt.new( Socket::AF_INET, bindto: options[:bindto], device: options[:device] ) end varbind = build_varbind( tuple[:topic], tuple[:type], tuple[:value] ) manager = SNMP::Manager.new( host: host, port: port, community: community, transport: transport ) begin response = Thread.handle_interrupt( ::Timeout::Error => :on_blocking ) do manager.set( varbind ) end response rescue SNMP::RequestTimeout => e raise Sloth::Snmp::Error, e.message rescue => e raise Sloth::Snmp::Error, e.message ensure manager.close end end
start_listener()
click to toggle source
# File lib/sloth/snmp/impl.rb, line 75 def start_listener @thread ||= Thread.start do listener = SNMP::TrapListener.new( host: @host, port: @port, community: @rocommunity ) do |manager| manager.on_trap_v2c do |mesg| begin next if mesg.error_status != :noError source_ip = mesg.source_ip trap_oid = mesg.trap_oid.join(".") trapname = @mibs.name( trap_oid ) items = {} mesg.each_varbind do |varbind| oid, item = * parse_varbind( varbind ) items[oid] = item end Thread.start do @mutex.synchronize do @topics[ trap_oid ]&.call( trapname, source_ip, items ) end end rescue => e raise Sloth::Snmp::Error, e.message end end end Thread.current[:listener] = listener listener.join end end
stop_listener()
click to toggle source
# File lib/sloth/snmp/impl.rb, line 107 def stop_listener @mutex.synchronize do @topics.clear @thread[:listener].exit @thread = nil end end
trap( *topics, &block )
click to toggle source
# File lib/sloth/snmp/impl.rb, line 115 def trap( *topics, &block ) @mutex.synchronize do topics.each do |topic| trap_oid = SNMP::ObjectId.new( topic ) rescue @mibs.oid( topic ) @topics[trap_oid.to_str] = block end end start_listener end
untrap( *topics )
click to toggle source
# File lib/sloth/snmp/impl.rb, line 125 def untrap( *topics ) @mutex.synchronize do topics.each do |topic| trap_oid = SNMP::ObjectId.new( topic ) rescue @mibs.oid( topic ) @topics.delete( trap_oid.to_str ) end end stop_listener if @topics.empty? end
walk( peer, topic, **options )
click to toggle source
# File lib/sloth/snmp/impl.rb, line 179 def walk( peer, topic, **options ) host, port = peer.split(':') rescue nil host = "127.0.0.1" if host.nil? || host.empty? port = (port || 161).to_i community = options[:rocommunity] || @rocommunity if options[:bindto] && options[:device] transport = UDPTransportExt.new( Socket::AF_INET, bindto: options[:bindto], device: options[:device] ) end manager = SNMP::Manager.new( host: host, port: port, community: community, transport: transport ) topic ||= "internet" base_oid = SNMP::ObjectId.new( topic ) rescue @mibs.oid( topic ) items = {} begin Thread.handle_interrupt( ::Timeout::Error => :on_blocking ) do manager.walk( base_oid ) do |varbind| oid, item = * parse_varbind( varbind ) items[oid] = item end end rescue SNMP::RequestTimeout => e raise Sloth::Snmp::Error, e.message rescue => e raise Sloth::Snmp::Error, e.message end items end