ruby-snmp
ruby-snmp copied to clipboard
walk returns nothing if the oid is a leaf node
manager.get(["1.3.6.1.4.1.674.10892.5.4.600.60.1.7.1.1"]) works
manager.walk(["1.3.6.1.4.1.674.10892.5.4.600.60.1.7.1.1"]) has no results (same oid)
manager.walk(["1.3.6.1.4.1.674.10892.5.4.600.60.1.7.1"]) works too, giving one result. (oid less last .1)
I noticed this a while ago, and changed to using get for the leaf node oids. Then forgot all about it and spent hours yesterday trying to work out why my code wouldn't work, then remembered coming across this a long time ago.
That's the expected behavior. The walk() method uses get_next() not get() to retrieve data. I think this behavior is consistent with other tools.
I had been expecting the same behaviour as the command line snmpwalk, which does return a single leaf oid.
% snmpwalk -v 1 -c public 10.30.20.99 1.3.6.1.4.1.674.10892.5.4.600.60.1.7.1.1 SNMPv2-SMI::enterprises.674.10892.5.4.600.60.1.7.1.1 = INTEGER: 4675038
I'll wrap the walk with my own code, as some devices I am querying have an extra arc at the end of some of their oids, and others don't. Hence I used walk, rather than get for these case, and have gotten into the habit of using walk everywhere.
There isn't much consistency in the use of oids across different manufacturers.
Looked into the net-snmp snmpwalk c code, There is a final GET request done, if no oids are returned. This can be turned off with -CI
% snmpwalk -v 1 -c public -CI 10.30.20.99 1.3.6.1.4.1.674.10892.5.4.600.60.1.7.1.1 %
-CI In fact, the given OID will be retrieved automatically if the main subtree walk returns no useable values. This allows a walk of a single instance to behave as generally expected, and return the specified instance value. This option turns off this final GET request, so a walk of a single instance will return nothing.
There is also a -Ci to do a get of the oid, before doing get next requests. This is turned off by default in the cli snmpwalk.
So your library is correct, it is just that the command line version has these extra options, which I wasn't aware of.
My hack to get the behaviour of the cli snmpwalk.
module SNMP #Manager class from snmp gem class Manager
alias real_walk walk
#Overrides walk in the SNMP gem manager.rb.
#Walks a list of ObjectId or VarBind objects using get_next until the response to the first OID in the list reaches the end of its MIB subtree.
# @param object_list [Array] List of oids we are looking up
# @param index_column The index_column identifies the column that will provide the index for each row.
# @param options [Hash] :walk_include_requested same as cli snmpwalk -Ci (Default is false. When true: does get(oid) before calling walk(oid) )
# :walk_dont_get_requested same as cli snmpwalk -CI (Default is false. When false: do get(oid) if walk returns no results)
#
def walk(object_list, index_column=0, options: {})
@includeRequested = options[:walk_include_requested] != nil ? options[:walk_include_requested] : false
@excludeRequested = options[:walk_dont_get_requested] != nil ? options[:walk_dont_get_requested] : false
object_list.each do |ol|
if @includeRequested
get([ol]).each_varbind { |vb| yield vb }
end
result = false
real_walk([ol], index_column) do |row|
result = true
yield row
end
if !@includeRequested && !@excludeRequested && !result
get([ol]).each_varbind { |vb| yield vb }
end
end
end
end
end
Thanks. I'll think about adding an option to the walk method. I can see how the inconsistency with the snmpwalk command would be confusing.