net-snmp 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +14 -29
- data/lib/net/snmp/dispatcher.rb +103 -0
- data/lib/net/snmp/oid.rb +3 -0
- data/lib/net/snmp/pdu.rb +46 -13
- data/lib/net/snmp/session.rb +92 -33
- data/lib/net/snmp/version.rb +1 -1
- data/lib/net/snmp/wrapper.rb +1 -0
- data/lib/net/snmp.rb +12 -31
- data/lib/net-snmp.rb +1 -1
- data/net-snmp.gemspec +1 -1
- data/spec/async_spec.rb +106 -0
- data/spec/em_spec.rb +26 -0
- data/spec/fiber_spec.rb +43 -0
- data/spec/net-snmp_spec.rb +14 -185
- data/spec/sync_spec.rb +95 -0
- metadata +12 -3
data/README.rdoc
CHANGED
@@ -25,11 +25,12 @@ You can use the library in two styles: synchronously or asynchronously. If you
|
|
25
25
|
calls will block until a result is returned or the request times out. If you use the asynchronous style, you
|
26
26
|
must provide a block to the client methods, which will be called when the data is ready.
|
27
27
|
|
28
|
-
In order for your callbacks to fire, you must call Net::SNMP.
|
28
|
+
In order for your callbacks to fire, you must call Net::SNMP::Dispatcher.poll You may pass a timeout argument to
|
29
29
|
the dispatcher. If you pass false, the call will block forever until data is ready. If you pass an integer, it will block for
|
30
30
|
<timeout> seconds. If you pass nil (the default), it will do a poll and return immediately. In that case, you
|
31
31
|
will have to arrange for the dispatcher to run periodically. This can be done in your main event loop or in a
|
32
|
-
seperate thread.
|
32
|
+
seperate thread. There are convenience class methods in Net::SNMP::Dispatcher called run_loop, fiber_loop, em_loop, thread_loop
|
33
|
+
and so on for setting up various polling loops. Or, you can roll your own loop.
|
33
34
|
|
34
35
|
If you like eventmachine, it's very easy to set up the dispatcher to run periodically in the adaptor. If you're
|
35
36
|
using eventmachine with ruby 1.9, the library uses fibers behind the scenes to turn your synchronous calls into asynchronous
|
@@ -57,36 +58,16 @@ A simple synchronous SNMP-GET
|
|
57
58
|
result.free # you have to manually free the memory in sync calls for now.
|
58
59
|
|
59
60
|
An asynchronous SNMP-GET
|
60
|
-
|
61
61
|
Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :community => 'demopublic') do |session|
|
62
62
|
session.get(["sysDescr.0", "sysContact.0"]) do |result|
|
63
63
|
puts result.varbinds[0].value
|
64
64
|
end
|
65
65
|
end
|
66
|
-
Net::SNMP.
|
67
|
-
|
68
|
-
|
69
|
-
Running the dispatcher in a seperate thread
|
70
|
-
|
71
|
-
dispatcher_thread = Thread.new do
|
72
|
-
while Net::SNMP.dispatcher == 0
|
73
|
-
sleep 1
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :community => 'demopublic') do |s|
|
78
|
-
s.get(["sysDescr.0", "sysContact.0"]) do |result|
|
79
|
-
puts result.varbinds[0].value
|
80
|
-
end
|
81
|
-
end
|
82
|
-
dispatcher_thread.join
|
66
|
+
Net::SNMP::Dispatcher.poll(false) #Setting timeout to false causes dispatcher to block until data is ready
|
83
67
|
|
84
68
|
Running the dispatcher from eventmachine
|
85
69
|
EM.run do
|
86
|
-
|
87
|
-
Net::SNMP.dispatcher
|
88
|
-
end
|
89
|
-
|
70
|
+
Net::SNMP::Dispatcher.em_loop
|
90
71
|
Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :community => 'demopublic') do |session|
|
91
72
|
session.get("sysDescr.0") do |result|
|
92
73
|
puts result.varbinds[0].value
|
@@ -96,16 +77,13 @@ Running the dispatcher from eventmachine
|
|
96
77
|
|
97
78
|
Using synchronous style with eventmachine in ruby 1.9
|
98
79
|
EM.run do
|
80
|
+
Net::SNMP::Dispatcher.fiber_loop
|
99
81
|
Fiber.new {
|
100
|
-
EM.tick_loop do
|
101
|
-
Net::SNMP.dispatcher
|
102
|
-
end
|
103
82
|
session = Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :community => 'demopublic')
|
104
83
|
result = session.get("sysDescr.0")
|
105
84
|
puts result.varbinds[0].value
|
106
|
-
|
85
|
+
EM.stop
|
107
86
|
}.resume
|
108
|
-
EM.stop
|
109
87
|
end
|
110
88
|
|
111
89
|
|
@@ -128,12 +106,19 @@ Having the appropriate MIBs loaded will allow you to pass names instead of numer
|
|
128
106
|
you can call Net::SNMP.get_oid("sysDescr.0"). For more complex MIB parsing needs, see smi-ffi[http://github.com/mixtli/smi-ffi]
|
129
107
|
|
130
108
|
|
109
|
+
== BUGS
|
110
|
+
Right now, snmpv3 is only working using synchronous API. Asynchronous calls seem to miss packets.
|
111
|
+
I have no idea why it would be different for v3 vs v1/v2. If anyone knows, tell me ;)
|
112
|
+
|
113
|
+
|
131
114
|
== CAVEATS/DISCLAIMER
|
132
115
|
|
133
116
|
THIS GEM COULD CRASH YOUR SYSTEM AND EAT YOUR CHILDREN!
|
134
117
|
|
135
118
|
You have been warned.
|
136
119
|
|
120
|
+
The API is subject to change.
|
121
|
+
|
137
122
|
This is very much alpha software. For more information on usage, take a look at the specs. Currently it's
|
138
123
|
only tested against net-snmp 5.5. The net-snmp api seems pretty stable, but if anything changes, it could
|
139
124
|
break this gem. Please let me know if you find bugs or missing features. Or better yet, send a pull request.
|
@@ -0,0 +1,103 @@
|
|
1
|
+
class Net::SNMP::Dispatcher
|
2
|
+
class << self
|
3
|
+
|
4
|
+
# timeout = nil no block(poll), timeout = false block forever, timeout = int, block int seconds
|
5
|
+
def poll(timeout = nil)
|
6
|
+
fdset = Net::SNMP::Wrapper.get_fd_set
|
7
|
+
num_fds = FFI::MemoryPointer.new(:int)
|
8
|
+
tv_sec = timeout ? timeout.round : 0
|
9
|
+
tv_usec = timeout ? (timeout - timeout.round) * 1000000 : 0
|
10
|
+
tval = Net::SNMP::Wrapper::TimeVal.new(:tv_sec => tv_sec, :tv_usec => tv_usec)
|
11
|
+
block = FFI::MemoryPointer.new(:int)
|
12
|
+
|
13
|
+
if timeout.nil?
|
14
|
+
block.write_int(0)
|
15
|
+
else
|
16
|
+
block.write_int(1)
|
17
|
+
end
|
18
|
+
#puts "calling snmp_select_info"
|
19
|
+
Net::SNMP::Wrapper.snmp_select_info(num_fds, fdset, tval.pointer, block )
|
20
|
+
#puts "done snmp_select_info."
|
21
|
+
num_ready = 0
|
22
|
+
#puts "block = #{block.read_int}"
|
23
|
+
|
24
|
+
#puts "numready = #{num_fds.read_int}"
|
25
|
+
#puts "tv = #{tval[:tv_sec]} #{tval[:tv_usec]}"
|
26
|
+
#puts "timeout = #{timeout}"
|
27
|
+
tv = (timeout == false ? nil : tval)
|
28
|
+
#puts "calling select"
|
29
|
+
#puts "tv = #{tv.inspect}"
|
30
|
+
#puts "calling select with #{num_fds.read_int}"
|
31
|
+
num_ready = Net::SNMP::Wrapper.select(num_fds.read_int, fdset, nil, nil, tv)
|
32
|
+
#puts "done select. num_ready = #{num_ready}"
|
33
|
+
if num_ready > 0
|
34
|
+
Net::SNMP::Wrapper.snmp_read(fdset)
|
35
|
+
elsif num_ready == 0
|
36
|
+
# timeout. do something here? or just return 0?
|
37
|
+
elsif num_ready == -1
|
38
|
+
# error. check snmp_error?
|
39
|
+
else
|
40
|
+
# uhhh
|
41
|
+
end
|
42
|
+
#puts "done snmp_read"
|
43
|
+
num_ready
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
def run_loop(options = {})
|
48
|
+
if defined?(EM) && EM.reactor_running?
|
49
|
+
fiber_loop(options)
|
50
|
+
else
|
51
|
+
thread_loop(options)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# You should not pass nil to this as it will peg your cpu
|
56
|
+
def thread_loop(options = {})
|
57
|
+
|
58
|
+
timeout = options[:timeout] || false
|
59
|
+
sleep_time = options[:sleep]
|
60
|
+
Thread.new do
|
61
|
+
loop do
|
62
|
+
poll(timeout)
|
63
|
+
sleep(sleep_time) if sleep_time
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
def em_loop(options = {})
|
70
|
+
timeout = options[:timeout]
|
71
|
+
sleep_time = options[:sleep_time] || 0.1
|
72
|
+
myproc = Proc.new do
|
73
|
+
EM.next_tick do
|
74
|
+
while(true) do
|
75
|
+
num_ready = poll(timeout)
|
76
|
+
break if num_ready == 0
|
77
|
+
end
|
78
|
+
EM.add_timer(sleep_time) do
|
79
|
+
myproc.call
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
myproc.call
|
84
|
+
end
|
85
|
+
|
86
|
+
def fiber_loop(options = {})
|
87
|
+
timeout = options[:timeout]
|
88
|
+
sleep_time = options[:sleep] || 0.01
|
89
|
+
Fiber.new {
|
90
|
+
loop do
|
91
|
+
num_handled = poll(timeout)
|
92
|
+
if num_handled == 0
|
93
|
+
f = Fiber.current
|
94
|
+
EM.add_timer(sleep_time) do
|
95
|
+
f.resume
|
96
|
+
end
|
97
|
+
Fiber.yield
|
98
|
+
end
|
99
|
+
end
|
100
|
+
}.resume(nil)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
data/lib/net/snmp/oid.rb
CHANGED
data/lib/net/snmp/pdu.rb
CHANGED
@@ -3,7 +3,7 @@ module Net
|
|
3
3
|
class PDU
|
4
4
|
extend Forwardable
|
5
5
|
attr_accessor :struct, :varbinds, :callback
|
6
|
-
def_delegators :struct, :
|
6
|
+
def_delegators :struct, :pointer
|
7
7
|
|
8
8
|
def initialize(arg)
|
9
9
|
@varbinds = []
|
@@ -38,30 +38,63 @@ module Net
|
|
38
38
|
def max_repetitions
|
39
39
|
@struct.errindex
|
40
40
|
end
|
41
|
+
def enterprise=(e_oid)
|
42
|
+
@enterprise = e_iod
|
43
|
+
@struct.enterprise = e_oid.pointer
|
44
|
+
@struct.enterprise_length = e_oid.size
|
45
|
+
end
|
46
|
+
def enterprise
|
47
|
+
@enterprise
|
48
|
+
end
|
49
|
+
|
50
|
+
def agent_addr=(addr)
|
51
|
+
@struct.agent_addr = addr.split('.').pack("CCCC")
|
52
|
+
@agent_addr = addr
|
53
|
+
end
|
41
54
|
|
55
|
+
def agent_addr
|
56
|
+
@agent_addr
|
57
|
+
end
|
42
58
|
|
43
|
-
def add_varbind(options)
|
44
59
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
when nil
|
49
|
-
Constants::ASN_NULL
|
60
|
+
def method_missing(m, *args)
|
61
|
+
if @struct.respond_to?(m)
|
62
|
+
@struct.send(m, *args)
|
50
63
|
else
|
51
|
-
|
64
|
+
super
|
52
65
|
end
|
66
|
+
end
|
53
67
|
|
68
|
+
def add_varbind(options)
|
69
|
+
options[:type] ||= case options[:value]
|
70
|
+
when String
|
71
|
+
Constants::ASN_OCTET_STR
|
72
|
+
when Fixnum
|
73
|
+
Constants::ASN_INTEGER
|
74
|
+
when nil
|
75
|
+
Constants::ASN_NULL
|
76
|
+
else
|
77
|
+
raise "Unknown value type"
|
78
|
+
end
|
79
|
+
|
80
|
+
value = options[:value]
|
54
81
|
value_len = case options[:value]
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
82
|
+
when String
|
83
|
+
options[:value].length
|
84
|
+
when nil
|
85
|
+
0
|
86
|
+
else
|
87
|
+
options[:value].size
|
59
88
|
end
|
60
89
|
|
61
90
|
|
91
|
+
if value.respond_to?(:pointer)
|
92
|
+
value = value.pointer
|
93
|
+
end
|
94
|
+
|
62
95
|
oid = Net::SNMP::OID.new(options[:oid])
|
63
96
|
|
64
|
-
var_ptr = Wrapper.snmp_pdu_add_variable(@struct.pointer, oid.pointer, oid.length_pointer.read_int, options[:type],
|
97
|
+
var_ptr = Wrapper.snmp_pdu_add_variable(@struct.pointer, oid.pointer, oid.length_pointer.read_int, options[:type], value, value_len)
|
65
98
|
varbind = Varbind.new(var_ptr)
|
66
99
|
#Wrapper.print_varbind(varbind.struct)
|
67
100
|
varbinds << varbind
|
data/lib/net/snmp/session.rb
CHANGED
@@ -5,6 +5,7 @@ module Net
|
|
5
5
|
class Session
|
6
6
|
extend Forwardable
|
7
7
|
attr_accessor :struct, :callback
|
8
|
+
attr_reader :version
|
8
9
|
def_delegator :@struct, :pointer
|
9
10
|
#@sessions = []
|
10
11
|
@requests = {}
|
@@ -25,6 +26,7 @@ module Net
|
|
25
26
|
options[:community_len] = options[:community].length
|
26
27
|
options[:version] ||= Constants::SNMP_VERSION_1
|
27
28
|
@callback = options[:callback]
|
29
|
+
@version = options[:version] || 1
|
28
30
|
#self.class.sessions << self
|
29
31
|
@sess = Wrapper::SnmpSession.new(nil)
|
30
32
|
Wrapper.snmp_sess_init(@sess.pointer)
|
@@ -43,7 +45,6 @@ module Net
|
|
43
45
|
Constants::SNMP_VERSION_1
|
44
46
|
end
|
45
47
|
|
46
|
-
|
47
48
|
if options[:timeout]
|
48
49
|
@sess.timeout = options[:timeout] * 1000000
|
49
50
|
end
|
@@ -51,7 +52,6 @@ module Net
|
|
51
52
|
@sess.retries = options[:retries]
|
52
53
|
end
|
53
54
|
|
54
|
-
|
55
55
|
if @sess.version == Constants::SNMP_VERSION_3
|
56
56
|
@sess.securityLevel = options[:security_level] || Constants::SNMP_SEC_LEVEL_NOAUTH
|
57
57
|
|
@@ -70,7 +70,6 @@ module Net
|
|
70
70
|
if options[:context]
|
71
71
|
@sess.contextName = FFI::MemoryPointer.from_string(options[:context])
|
72
72
|
@sess.contextNameLen = options[:context].length
|
73
|
-
|
74
73
|
end
|
75
74
|
|
76
75
|
if options[:username]
|
@@ -84,13 +83,19 @@ module Net
|
|
84
83
|
unless key_result == Constants::SNMPERR_SUCCESS
|
85
84
|
Wrapper.snmp_perror("netsnmp")
|
86
85
|
end
|
87
|
-
|
88
86
|
end
|
89
87
|
|
90
88
|
# General callback just takes the pdu, calls the session callback if any, then the request specific callback.
|
91
89
|
@sess.callback = lambda do |operation, session, reqid, pdu_ptr, magic|
|
92
|
-
pdu
|
93
|
-
|
90
|
+
callback.call(operation, reqid, pdu, magic) if callback
|
91
|
+
|
92
|
+
puts "in main callback"
|
93
|
+
if self.class.requests[reqid]
|
94
|
+
puts "got request"
|
95
|
+
pdu = Net::SNMP::PDU.new(pdu_ptr)
|
96
|
+
self.class.requests[reqid].call(pdu)
|
97
|
+
self.class.requests.delete(reqid)
|
98
|
+
end
|
94
99
|
0
|
95
100
|
end
|
96
101
|
|
@@ -99,15 +104,6 @@ module Net
|
|
99
104
|
#@struct = Wrapper.snmp_sess_session(@handle)
|
100
105
|
end
|
101
106
|
|
102
|
-
|
103
|
-
|
104
|
-
def run_callbacks(operation, reqid, pdu, magic)
|
105
|
-
callback.call(operation, reqid, pdu, magic) if callback
|
106
|
-
if self.class.requests[reqid]
|
107
|
-
self.class.requests[reqid].call(pdu)
|
108
|
-
self.class.requests.delete(reqid)
|
109
|
-
end
|
110
|
-
end
|
111
107
|
|
112
108
|
|
113
109
|
def get(oidlist, options = {}, &block)
|
@@ -132,6 +128,7 @@ module Net
|
|
132
128
|
pdu = Net::SNMP::PDU.new(Constants::SNMP_MSG_GETBULK)
|
133
129
|
oidlist = [oidlist] unless oidlist.kind_of?(Array)
|
134
130
|
oidlist.each do |oid|
|
131
|
+
puts "adding #{oid.inspect}"
|
135
132
|
pdu.add_varbind(:oid => oid)
|
136
133
|
end
|
137
134
|
pdu.non_repeaters = options[:non_repeaters] || 0
|
@@ -193,6 +190,27 @@ module Net
|
|
193
190
|
results
|
194
191
|
end
|
195
192
|
|
193
|
+
|
194
|
+
def default_max_repeaters
|
195
|
+
# We could do something based on transport here. 25 seems safe
|
196
|
+
25
|
197
|
+
end
|
198
|
+
|
199
|
+
def get_columns(columns, options = {})
|
200
|
+
column_oids = columns.map {|c| Net::SNMP::OID.new(c)}
|
201
|
+
options[:max_repetitions] ||= default_max_repeaters / columns.size
|
202
|
+
results = {}
|
203
|
+
if version == 1
|
204
|
+
else
|
205
|
+
while(result = get_bulk(columns, options))
|
206
|
+
result.varbinds.each do |vb|
|
207
|
+
match = column_oids.select {|c| vb.oid.oid =~ /^#{c.oid}/ }
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
196
214
|
def error(msg)
|
197
215
|
Wrapper.snmp_perror("snmp_error")
|
198
216
|
Wrapper.snmp_sess_perror( "snmp_error", @sess.pointer)
|
@@ -200,24 +218,6 @@ module Net
|
|
200
218
|
raise Net::SNMP::Error.new({:session => self}), msg
|
201
219
|
end
|
202
220
|
|
203
|
-
# def dispatcher
|
204
|
-
# fdset = Net::SNMP::Wrapper.get_fd_set
|
205
|
-
# num_fds = FFI::MemoryPointer.new(:int)
|
206
|
-
# tval = Net::SNMP::Wrapper::TimeVal.new
|
207
|
-
# block = FFI::MemoryPointer.new(:int)
|
208
|
-
# block.write_int(0)
|
209
|
-
#
|
210
|
-
# # Note.. for some reason, snmp_sess_select_info changes block to be 1.
|
211
|
-
# Net::SNMP::Wrapper.snmp_sess_select_info(@handle, num_fds, fdset, tval.pointer, block )
|
212
|
-
# if num_fds.read_int > 0
|
213
|
-
# zero = Wrapper::TimeVal.new(:tv_sec => 0, :tv_usec => 0)
|
214
|
-
# #Wrapper.print_timeval(zero)
|
215
|
-
#
|
216
|
-
# num_ready = Net::SNMP::Wrapper.select(num_fds.read_int, fdset, nil, nil, zero.pointer)
|
217
|
-
# Net::SNMP::Wrapper.snmp_sess_read(@handle, fdset)
|
218
|
-
# end
|
219
|
-
# end
|
220
|
-
|
221
221
|
|
222
222
|
private
|
223
223
|
def send_pdu(pdu, &block)
|
@@ -252,8 +252,67 @@ module Net
|
|
252
252
|
end
|
253
253
|
end
|
254
254
|
end
|
255
|
+
end
|
256
|
+
|
257
|
+
# def get_entries_cb(pdu, columns, options)
|
258
|
+
# cache = {}
|
259
|
+
# row_index = nil
|
260
|
+
# varbinds = pdu.varbinds.dup
|
261
|
+
# while(varbinds.size > 0)
|
262
|
+
# row = {}
|
263
|
+
# columns.each do |column|
|
264
|
+
# vb = varbinds.shift
|
265
|
+
# if vb.oid.to_s =~ /#{column.to_s}\.(\d+(:?\.\d+)*)/
|
266
|
+
# index = $1
|
267
|
+
# else
|
268
|
+
# last_entry = true
|
269
|
+
# next
|
270
|
+
# end
|
271
|
+
# row_index = index unless row_index
|
272
|
+
# index_cmp = Net::SNMP.oid_lex_cmp(index, row_index)
|
273
|
+
# if(index_cmp == 0)
|
274
|
+
# end
|
275
|
+
# end
|
276
|
+
# end
|
277
|
+
# end
|
278
|
+
|
279
|
+
|
280
|
+
|
281
|
+
|
282
|
+
def trap(options = {})
|
283
|
+
pdu = PDU.new(Constants::SNMP_MSG_TRAP)
|
284
|
+
options[:enterprise] ||= '1.3.6.1.4.1.3.1.1' # uh, just send netsnmp enterprise i guess
|
285
|
+
pdu.enterprise = OID.new(options[:enterprise])
|
286
|
+
pdu.trap_type = options[:trap_type] || 1 # need to check all these defaults
|
287
|
+
pdu.specific_type = options[:specific_type] || 0
|
288
|
+
pdu.time = 1 # put what here?
|
289
|
+
send_pdu(pdu)
|
290
|
+
end
|
255
291
|
|
292
|
+
|
293
|
+
def trap_v2(options = {})
|
294
|
+
pdu = PDU.new(Constants::SNMP_MSG_TRAP2)
|
295
|
+
build_trap_pdu(options)
|
296
|
+
send_pdu(pdu)
|
297
|
+
end
|
298
|
+
|
299
|
+
def inform(options = {}, &block)
|
300
|
+
pdu = PDU.new(Constants::SNMP_MSG_INFORM)
|
301
|
+
build_trap_pdu(options)
|
302
|
+
send_pdu(pdu, &block)
|
303
|
+
end
|
304
|
+
|
305
|
+
def build_trap_pdu(pdu, options = {})
|
306
|
+
pdu.add_varbind(:oid => OID.new('sysUpTime'), :type => Constants::ASN_TIMETICKS, :value => 0)
|
307
|
+
pdu.add_varbind(:oid => OID.new('snmpTrapOID'), :type => Constants::ASN_OBJECT_ID, :value => options[:oid])
|
308
|
+
if options[:varbinds]
|
309
|
+
options[:varbinds].each do |vb|
|
310
|
+
pdu.add_varbind(vb)
|
311
|
+
end
|
312
|
+
end
|
256
313
|
end
|
314
|
+
|
315
|
+
|
257
316
|
end
|
258
317
|
end
|
259
318
|
end
|
data/lib/net/snmp/version.rb
CHANGED
data/lib/net/snmp/wrapper.rb
CHANGED
@@ -251,6 +251,7 @@ module Wrapper
|
|
251
251
|
# attach_function :netsnmp_oid_tree_equals, [ :pointer, :uint, :pointer, :uint ], :int
|
252
252
|
attach_function :netsnmp_oid_is_subtree, [ :pointer, :uint, :pointer, :uint ], :int
|
253
253
|
attach_function :netsnmp_oid_find_prefix, [ :pointer, :uint, :pointer, :uint ], :int
|
254
|
+
attach_function :netsnmp_transport_open_client, [:string, :pointer], :pointer
|
254
255
|
attach_function :init_snmp, [ :string ], :void
|
255
256
|
attach_function :snmp_pdu_build, [ :pointer, :pointer, :pointer ], :pointer
|
256
257
|
attach_function :snmpv3_parse, [ :pointer, :pointer, :pointer, :pointer, :pointer ], :int
|
data/lib/net/snmp.rb
CHANGED
@@ -8,39 +8,11 @@ module Net
|
|
8
8
|
Wrapper.init_snmp(tag)
|
9
9
|
end
|
10
10
|
|
11
|
-
# timeout = nil no block(poll), timeout = false block forever, timeout = int, block int seconds
|
12
|
-
def self.dispatcher(timeout = nil)
|
13
|
-
fdset = Net::SNMP::Wrapper.get_fd_set
|
14
|
-
num_fds = FFI::MemoryPointer.new(:int)
|
15
|
-
tv_sec = timeout || 0
|
16
|
-
tval = Net::SNMP::Wrapper::TimeVal.new(:tv_sec => tv_sec, :tv_usec => 0)
|
17
|
-
block = FFI::MemoryPointer.new(:int)
|
18
|
-
|
19
|
-
if timeout.nil?
|
20
|
-
block.write_int(0)
|
21
|
-
else
|
22
|
-
block.write_int(1)
|
23
|
-
end
|
24
|
-
#puts "calling snmp_select_info"
|
25
|
-
Net::SNMP::Wrapper.snmp_select_info(num_fds, fdset, tval.pointer, block )
|
26
|
-
#puts "done snmp_select_info."
|
27
|
-
num_ready = 0
|
28
|
-
#puts "block = #{block.read_int}"
|
29
|
-
|
30
|
-
#puts "numready = #{num_fds.read_int}"
|
31
|
-
#puts "tv = #{tval[:tv_sec]} #{tval[:tv_usec]}"
|
32
|
-
if num_fds.read_int > 0
|
33
|
-
tv = timeout == false ? nil : tval
|
34
|
-
#puts "calling select"
|
35
|
-
num_ready = Net::SNMP::Wrapper.select(num_fds.read_int, fdset, nil, nil, tv)
|
36
|
-
#puts "done select. num_ready = #{num_ready}"
|
37
|
-
Net::SNMP::Wrapper.snmp_read(fdset)
|
38
|
-
else
|
39
|
-
end
|
40
|
-
num_ready
|
41
|
-
end
|
42
11
|
|
43
12
|
|
13
|
+
|
14
|
+
# Some utility methods
|
15
|
+
|
44
16
|
def self._get_oid(name)
|
45
17
|
oid_ptr = FFI::MemoryPointer.new(:ulong, Constants::MAX_OID_LEN)
|
46
18
|
oid_len_ptr = FFI::MemoryPointer.new(:size_t)
|
@@ -57,6 +29,15 @@ module Net
|
|
57
29
|
oid_ptr.read_array_of_long(oid_len_ptr.read_int).join(".")
|
58
30
|
end
|
59
31
|
|
32
|
+
def self.oid_lex_cmp(a,b)
|
33
|
+
[a,b].each do |i|
|
34
|
+
i.sub!(/^\./,'')
|
35
|
+
i.gsub!(/ /, '.0')
|
36
|
+
i.replace(i.split('.').map(&:to_i).pack('N*'))
|
37
|
+
end
|
38
|
+
a <=> b
|
39
|
+
end
|
40
|
+
|
60
41
|
|
61
42
|
end
|
62
43
|
end
|
data/lib/net-snmp.rb
CHANGED
@@ -2,7 +2,7 @@ require 'forwardable'
|
|
2
2
|
require 'nice-ffi'
|
3
3
|
require 'fiber'
|
4
4
|
|
5
|
-
%w(snmp snmp/version snmp/constants snmp/oid snmp/error snmp/pdu snmp/wrapper snmp/session snmp/varbind snmp/mib snmp/mib/node).each do |f|
|
5
|
+
%w(snmp snmp/version snmp/constants snmp/oid snmp/error snmp/pdu snmp/wrapper snmp/session snmp/varbind snmp/mib snmp/mib/node snmp/dispatcher).each do |f|
|
6
6
|
require "#{File.dirname(__FILE__)}/net/#{f}"
|
7
7
|
end
|
8
8
|
Net::SNMP::MIB.init
|
data/net-snmp.gemspec
CHANGED
data/spec/async_spec.rb
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe "async" do
|
4
|
+
context "version 1" do
|
5
|
+
it "get should work" do
|
6
|
+
did_callback = false
|
7
|
+
Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :community => 'demopublic') do |s|
|
8
|
+
s.get(["sysDescr.0", "sysContact.0"]) do |result|
|
9
|
+
did_callback = true
|
10
|
+
result.varbinds[0].value.should eql("test.net-snmp.org")
|
11
|
+
result.varbinds[1].value.should match(/Coders/)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
Net::SNMP::Dispatcher.poll(false)
|
15
|
+
did_callback.should be(true)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "getnext should work" do
|
19
|
+
did_callback = false
|
20
|
+
Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :community => 'demopublic') do |s|
|
21
|
+
s.get_next(["sysDescr", "sysContact"]) do |result|
|
22
|
+
did_callback = true
|
23
|
+
result.varbinds[0].value.should eql("test.net-snmp.org")
|
24
|
+
result.varbinds[1].value.should match(/Coders/)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
Net::SNMP::Dispatcher.poll(false)
|
28
|
+
did_callback.should be(true)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
context "version 2" do
|
34
|
+
it "get should work" do
|
35
|
+
did_callback = false
|
36
|
+
Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :community => 'demopublic', :version => '2c') do |s|
|
37
|
+
s.get(["sysDescr.0", "sysContact.0"]) do |result|
|
38
|
+
did_callback = true
|
39
|
+
result.varbinds[0].value.should eql("test.net-snmp.org")
|
40
|
+
result.varbinds[1].value.should match(/Coders/)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
Net::SNMP::Dispatcher.poll(false)
|
44
|
+
did_callback.should be(true)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "getnext should work" do
|
48
|
+
did_callback = false
|
49
|
+
Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :community => 'demopublic', :version => '2c') do |s|
|
50
|
+
s.get_next(["sysDescr", "sysContact"]) do |result|
|
51
|
+
did_callback = true
|
52
|
+
result.varbinds[0].value.should eql("test.net-snmp.org")
|
53
|
+
result.varbinds[1].value.should match(/Coders/)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
Net::SNMP::Dispatcher.poll(false)
|
57
|
+
did_callback.should be(true)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context "version 3" do
|
62
|
+
#failing intermittently
|
63
|
+
it "should get async using snmpv3" do
|
64
|
+
did_callback = false
|
65
|
+
Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :version => 3, :username => 'MD5User',:security_level => Net::SNMP::Constants::SNMP_SEC_LEVEL_AUTHNOPRIV, :auth_protocol => :md5, :password => 'The Net-SNMP Demo Password') do |sess|
|
66
|
+
sess.get(["sysDescr.0"]) do |result|
|
67
|
+
did_callback = true
|
68
|
+
result.varbinds[0].value.should eql('test.net-snmp.org')
|
69
|
+
end
|
70
|
+
sleep(0.5)
|
71
|
+
Net::SNMP::Dispatcher.poll(false)
|
72
|
+
#Net::SNMP::Dispatcher.poll(false)
|
73
|
+
puts "done poll"
|
74
|
+
did_callback.should be(true)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
it "get should work" do
|
80
|
+
did_callback = false
|
81
|
+
Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :version => 3, :username => 'MD5User',:security_level => Net::SNMP::Constants::SNMP_SEC_LEVEL_AUTHNOPRIV, :auth_protocol => :md5, :password => 'The Net-SNMP Demo Password') do |sess|
|
82
|
+
sess.get(["sysDescr.0", "sysContact.0"]) do |result|
|
83
|
+
did_callback = true
|
84
|
+
result.varbinds[0].value.should eql("test.net-snmp.org")
|
85
|
+
result.varbinds[1].value.should match(/Coders/)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
Net::SNMP::Dispatcher.poll(false)
|
89
|
+
did_callback.should be(true)
|
90
|
+
end
|
91
|
+
|
92
|
+
it "getnext should work" do
|
93
|
+
did_callback = false
|
94
|
+
|
95
|
+
Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :version => 3, :username => 'MD5User',:security_level => Net::SNMP::Constants::SNMP_SEC_LEVEL_AUTHNOPRIV, :auth_protocol => :md5, :password => 'The Net-SNMP Demo Password') do |sess|
|
96
|
+
sess.get_next(["sysDescr", "sysContact"]) do |result|
|
97
|
+
did_callback = true
|
98
|
+
result.varbinds[0].value.should eql("test.net-snmp.org")
|
99
|
+
result.varbinds[1].value.should match(/Coders/)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
Net::SNMP::Dispatcher.poll(false)
|
103
|
+
did_callback.should be(true)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
data/spec/em_spec.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe "em" do
|
4
|
+
|
5
|
+
it "should work in event_machine" do
|
6
|
+
require 'eventmachine'
|
7
|
+
did_callback = false
|
8
|
+
EM.run do
|
9
|
+
Net::SNMP::Dispatcher.em_loop
|
10
|
+
|
11
|
+
session = Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :community => 'demopublic') do |s|
|
12
|
+
s.get("sysDescr.0") do |result|
|
13
|
+
did_callback = true
|
14
|
+
result.varbinds[0].value.should eql("test.net-snmp.org")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
EM.add_timer(3) do
|
19
|
+
did_callback.should be_true
|
20
|
+
EM.stop
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
end
|
data/spec/fiber_spec.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
require 'eventmachine'
|
3
|
+
require 'fiber'
|
4
|
+
|
5
|
+
describe "in fiber" do
|
6
|
+
|
7
|
+
def wrap_fiber
|
8
|
+
EM.run do
|
9
|
+
Net::SNMP::Dispatcher.fiber_loop
|
10
|
+
Fiber.new { yield; EM.stop }.resume(nil)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
it "get should work in a fiber with synchronous calling style" do
|
16
|
+
wrap_fiber do
|
17
|
+
session = Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :community => 'demopublic')
|
18
|
+
result = session.get("sysDescr.0")
|
19
|
+
puts "got result = #{result}"
|
20
|
+
result.varbinds[0].value.should eql("test.net-snmp.org")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
it "getnext" do
|
25
|
+
wrap_fiber do
|
26
|
+
Net::SNMP::Session.open(:peername => "test.net-snmp.org", :community => "demopublic" ) do |sess|
|
27
|
+
result = sess.get_next(["sysUpTimeInstance.0"])
|
28
|
+
result.varbinds.first.oid.oid.should eql("1.3.6.1.2.1.1.4.0")
|
29
|
+
result.varbinds.first.value.should match(/Net-SNMP Coders/)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should get using snmpv3" do
|
35
|
+
wrap_fiber do
|
36
|
+
Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :version => 3, :username => 'MD5User', :security_level => Net::SNMP::Constants::SNMP_SEC_LEVEL_AUTHNOPRIV, :auth_protocol => :md5, :password => 'The Net-SNMP Demo Password') do |sess|
|
37
|
+
result = sess.get(["sysDescr.0"])
|
38
|
+
result.varbinds.first.value.should eql('test.net-snmp.org')
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
data/spec/net-snmp_spec.rb
CHANGED
@@ -1,35 +1,6 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
2
|
|
3
3
|
describe "NetSnmp" do
|
4
|
-
it "should get single oid" do
|
5
|
-
Net::SNMP::Session.open(:peername => "test.net-snmp.org", :community => "demopublic" ) do |sess|
|
6
|
-
result = sess.get("sysDescr.0")
|
7
|
-
result.varbinds.first.value.should eql("test.net-snmp.org")
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
it "should get multiple oids" do
|
12
|
-
Net::SNMP::Session.open(:peername => "test.net-snmp.org", :community => 'demopublic' ) do |sess|
|
13
|
-
result = sess.get(["sysDescr.0", "sysName.0"])
|
14
|
-
result.varbinds[0].value.should eql("test.net-snmp.org")
|
15
|
-
result.varbinds[1].value.should eql("test.net-snmp.org")
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
it "should get multiple requests asynchronously" do
|
20
|
-
did_callback = false
|
21
|
-
session = Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :community => 'demopublic') do |s|
|
22
|
-
s.get(["sysDescr.0", "sysContact.0"]) do |result|
|
23
|
-
did_callback = true
|
24
|
-
result.varbinds[0].value.should eql("test.net-snmp.org")
|
25
|
-
result.varbinds[1].value.should match(/Coders/)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
Net::SNMP.dispatcher(false)
|
29
|
-
did_callback.should be(true)
|
30
|
-
end
|
31
|
-
|
32
|
-
|
33
4
|
it "should get an oid asynchronously in a thread" do
|
34
5
|
did_callback = false
|
35
6
|
session = Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :community => 'demopublic') do |s|
|
@@ -40,7 +11,7 @@ describe "NetSnmp" do
|
|
40
11
|
end
|
41
12
|
end
|
42
13
|
Thread.new do
|
43
|
-
while Net::SNMP.
|
14
|
+
while Net::SNMP::Dispatcher.poll == 0
|
44
15
|
sleep 1
|
45
16
|
end
|
46
17
|
end.join
|
@@ -48,101 +19,24 @@ describe "NetSnmp" do
|
|
48
19
|
end
|
49
20
|
|
50
21
|
|
51
|
-
it "
|
52
|
-
Net::SNMP::Session.open(:peername =>
|
53
|
-
result = sess.
|
54
|
-
result.should
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :version => 3, :username => 'MD5User', :security_level => Net::SNMP::Constants::SNMP_SEC_LEVEL_AUTHNOPRIV, :auth_protocol => :md5, :password => 'The Net-SNMP Demo Password') do |sess|
|
60
|
-
result = sess.get("sysDescr.0")
|
61
|
-
result.varbinds.first.value.should eql('test.net-snmp.org')
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
it "should get async using snmpv3" do
|
66
|
-
did_callback = false
|
67
|
-
Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :version => 3, :username => 'MD5User',:security_level => Net::SNMP::Constants::SNMP_SEC_LEVEL_AUTHNOPRIV, :auth_protocol => :md5, :password => 'The Net-SNMP Demo Password') do |sess|
|
68
|
-
sess.get(["sysDescr.0", "sysName.0"]) do |result|
|
69
|
-
did_callback = true
|
70
|
-
result.varbinds[0].value.should eql('test.net-snmp.org')
|
71
|
-
result.varbinds[1].value.should eql('test.net-snmp.org')
|
72
|
-
0
|
73
|
-
end
|
74
|
-
sleep(1)
|
75
|
-
Net::SNMP.dispatcher()
|
76
|
-
did_callback.should be(true)
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
|
81
|
-
# To test sets, you have to have a local snmpd running with write permissions
|
82
|
-
it "should set a value" do
|
83
|
-
Net::SNMP::Session.open(:peername => '127.0.0.1', :version => 1) do |sess|
|
84
|
-
result = sess.set([['sysContact.0', Net::SNMP::Constants::ASN_OCTET_STR, 'yomama']])
|
85
|
-
result.varbinds.first.value.should match(/yomama/)
|
86
|
-
result.should_not be_error
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
#it "should set using snmpv3" do
|
91
|
-
# pending
|
92
|
-
# Net::SNMP::Session.open(:peername => '127.0.0.1', :version => 3, :username => 'myuser', :authprotocol => :sha1, :authkey => '0x1234', :privprotocol => :des, :privkey => '0x25252') do |sess|
|
93
|
-
# result = sess.set([["sysDescr.0", Net::SNMP::Constants::ASN_OCTET_STR, 'yomama']])
|
94
|
-
# result.varbinds.first.value.should match(/Darwin/)
|
95
|
-
# end
|
96
|
-
#end
|
97
|
-
|
98
|
-
it "should get next an array of oids" do
|
99
|
-
Net::SNMP::Session.open(:peername => "test.net-snmp.org", :community => "demopublic" ) do |sess|
|
100
|
-
result = sess.get_next(["sysUpTimeInstance.0"])
|
101
|
-
result.varbinds.first.oid.oid.should eql("1.3.6.1.2.1.1.4.0")
|
102
|
-
result.varbinds.first.value.should match(/Net-SNMP Coders/)
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
22
|
+
# it "should get columns" do
|
23
|
+
# Net::SNMP::Session.open(:peername => 'localhost', :version => '2c', :community => 'public') do |sess|
|
24
|
+
# result = sess.get_columns(['ifIndex', 'ifInOctets', 'ifOutOctets'])
|
25
|
+
# result.size.should eql(7)
|
26
|
+
# result['1']['ifIndex'].should eql('1')
|
27
|
+
# result['2']['ifInOctets'].should be > 10
|
28
|
+
# end
|
29
|
+
# end
|
106
30
|
|
107
|
-
it "should get_bulk_request" do
|
108
|
-
Net::SNMP::Session.open(:peername => "test.net-snmp.org" , :version => '2c', :community => 'demopublic') do |sess|
|
109
|
-
result = sess.get_bulk(["sysContact.0"], :max_repetitions => 10)
|
110
|
-
result.varbinds.first.oid.name.should eql("1.3.6.1.2.1.1.5.0")
|
111
|
-
result.varbinds.first.value.should eql("test.net-snmp.org")
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
it "should get a table of values with explicit columns" do
|
116
|
-
session = Net::SNMP::Session.open(:peername => "localhost", :version => '2c')
|
117
|
-
table = session.get_table("ifTable", :columns => ["ifIndex", "ifDescr", "ifName"])
|
118
|
-
table[0]['ifName'].should eql("lo0")
|
119
|
-
table[1]['ifName'].should eql("gif0")
|
120
|
-
end
|
121
31
|
|
122
|
-
it "should
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
32
|
+
it "should compare oids" do
|
33
|
+
Net::SNMP.oid_lex_cmp('1.3.5', '1.3.7').should eql(-1)
|
34
|
+
Net::SNMP.oid_lex_cmp('1.3.7', '1.3.5').should eql(1)
|
35
|
+
Net::SNMP.oid_lex_cmp('1.3.7', '1.3.7.1').should eql(-1)
|
36
|
+
Net::SNMP.oid_lex_cmp('1.3.5', '1.3.5').should eql(0)
|
127
37
|
end
|
128
38
|
|
129
|
-
it "should get a table of values ipAddrEntry" do
|
130
|
-
puts Net::SNMP::Constants::ASN_IPADDRESS
|
131
|
-
session = Net::SNMP::Session.open(:peername => "localhost", :version => '2c')
|
132
|
-
table = session.get_table("ipAddrEntry")
|
133
|
-
puts table.inspect
|
134
|
-
table[0]['ipAdEntAddr'].should eql('127.0.0.1')
|
135
|
-
table[1]['ipAdEntNetMask'].should eql('255.255.255.0')
|
136
|
-
end
|
137
39
|
|
138
|
-
it "should get a table of values ifXEntry" do
|
139
|
-
puts Net::SNMP::Constants::ASN_IPADDRESS
|
140
|
-
session = Net::SNMP::Session.open(:peername => "localhost", :version => '2c')
|
141
|
-
table = session.get_table("ifXEntry")
|
142
|
-
puts table.inspect
|
143
|
-
table[0]['ifName'].should eql('lo0')
|
144
|
-
table[3]['ifHighSpeed'].should eql(1000)
|
145
|
-
end
|
146
40
|
|
147
41
|
it "should translate an oid" do
|
148
42
|
|
@@ -154,74 +48,9 @@ describe "NetSnmp" do
|
|
154
48
|
|
155
49
|
|
156
50
|
|
157
|
-
it "should work in event_machine" do
|
158
|
-
require 'eventmachine'
|
159
|
-
did_callback = false
|
160
|
-
EM.run do
|
161
|
-
tickloop = EM.tick_loop do
|
162
|
-
Net::SNMP.dispatcher
|
163
|
-
end
|
164
51
|
|
165
|
-
session = Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :community => 'demopublic') do |s|
|
166
|
-
s.get("sysDescr.0") do |result|
|
167
|
-
did_callback = true
|
168
|
-
result.varbinds[0].value.should eql("test.net-snmp.org")
|
169
|
-
end
|
170
|
-
|
171
|
-
end
|
172
52
|
|
173
|
-
EM.add_timer(3) do
|
174
|
-
did_callback.should be_true
|
175
|
-
EM.stop
|
176
|
-
end
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
it "should work in a fiber" do
|
181
|
-
require 'eventmachine'
|
182
|
-
did_callback = false
|
183
|
-
EM.run do
|
184
|
-
tickloop = EM.tick_loop do
|
185
|
-
Net::SNMP.dispatcher
|
186
|
-
end
|
187
53
|
|
188
|
-
Fiber.new {
|
189
|
-
session = Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :community => 'demopublic') do |s|
|
190
|
-
s.get("sysDescr.0") do |result|
|
191
|
-
did_callback = true
|
192
|
-
result.varbinds[0].value.should eql("test.net-snmp.org")
|
193
|
-
end
|
194
|
-
|
195
|
-
end
|
196
|
-
|
197
|
-
EM.add_timer(3) do
|
198
|
-
did_callback.should eql(true)
|
199
|
-
EM.stop
|
200
|
-
end
|
201
|
-
}.resume
|
202
|
-
end
|
203
|
-
end
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
it "get should work in a fiber with synchronous calling style" do
|
208
|
-
require 'eventmachine'
|
209
|
-
did_callback = false
|
210
|
-
EM.run do
|
211
|
-
Fiber.new {
|
212
|
-
|
213
|
-
EM.tick_loop do
|
214
|
-
|
215
|
-
Net::SNMP.dispatcher
|
216
|
-
end
|
217
|
-
sleep 1
|
218
|
-
session = Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :community => 'demopublic')
|
219
|
-
result = session.get("sysDescr.0")
|
220
|
-
result.varbinds[0].value.should eql("test.net-snmp.org")
|
221
|
-
}.resume
|
222
|
-
EM.stop
|
223
|
-
end
|
224
|
-
end
|
225
54
|
|
226
55
|
|
227
56
|
end
|
data/spec/sync_spec.rb
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe "synchronous calls" do
|
4
|
+
# To test sets, you have to have a local snmpd running with write permissions
|
5
|
+
context "version 1" do
|
6
|
+
it "get should succeed" do
|
7
|
+
Net::SNMP::Session.open(:peername => "test.net-snmp.org", :community => "demopublic" ) do |sess|
|
8
|
+
result = sess.get("sysDescr.0")
|
9
|
+
result.varbinds.first.value.should eql("test.net-snmp.org")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
it "get should succeed with multiple oids" do
|
14
|
+
Net::SNMP::Session.open(:peername => "test.net-snmp.org", :community => 'demopublic' ) do |sess|
|
15
|
+
result = sess.get(["sysDescr.0", "sysName.0"])
|
16
|
+
result.varbinds[0].value.should eql("test.net-snmp.org")
|
17
|
+
result.varbinds[1].value.should eql("test.net-snmp.org")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
it "set should succeed" do
|
22
|
+
Net::SNMP::Session.open(:peername => '127.0.0.1', :version => 1) do |sess|
|
23
|
+
result = sess.set([['sysContact.0', Net::SNMP::Constants::ASN_OCTET_STR, 'yomama']])
|
24
|
+
result.varbinds.first.value.should match(/yomama/)
|
25
|
+
result.should_not be_error
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
it "getnext should succeed" do
|
30
|
+
Net::SNMP::Session.open(:peername => "test.net-snmp.org", :community => "demopublic" ) do |sess|
|
31
|
+
result = sess.get_next(["sysUpTimeInstance.0"])
|
32
|
+
result.varbinds.first.oid.oid.should eql("1.3.6.1.2.1.1.4.0")
|
33
|
+
result.varbinds.first.value.should match(/Net-SNMP Coders/)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
it "getbulk should succeed" do
|
39
|
+
Net::SNMP::Session.open(:peername => "test.net-snmp.org" , :version => '2c', :community => 'demopublic') do |sess|
|
40
|
+
result = sess.get_bulk(["sysContact.0"], :max_repetitions => 10)
|
41
|
+
result.varbinds.first.oid.name.should eql("1.3.6.1.2.1.1.5.0")
|
42
|
+
result.varbinds.first.value.should eql("test.net-snmp.org")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
it "getbulk should succeed with multiple oids" do
|
47
|
+
Net::SNMP::Session.open(:peername => "localhost" , :version => '2c', :community => 'public') do |sess|
|
48
|
+
result = sess.get_bulk(["ifInOctets", 'ifOutOctets', 'ifInErrors', 'ifOutErrors'], :max_repeaters =>10)
|
49
|
+
result.varbinds.size.should eql(40)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
it "get should return error with invalid oid" do
|
54
|
+
Net::SNMP::Session.open(:peername => "test.net-snmp.org", :community => "demopublic" ) do |sess|
|
55
|
+
result = sess.get(["XXXsysDescr.0"]) #misspelled
|
56
|
+
result.should be_error
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
it "get_table should work with multiple columns" do
|
61
|
+
session = Net::SNMP::Session.open(:peername => "localhost", :version => '1')
|
62
|
+
table = session.get_table("ifTable", :columns => ["ifIndex", "ifDescr", "ifName"])
|
63
|
+
table[0]['ifName'].should eql("lo0")
|
64
|
+
table[1]['ifName'].should eql("gif0")
|
65
|
+
end
|
66
|
+
|
67
|
+
it "get_table should work" do
|
68
|
+
session = Net::SNMP::Session.open(:peername => "localhost", :version => '1')
|
69
|
+
table = session.get_table("ifEntry")
|
70
|
+
table[0]['ifIndex'].should eql(1)
|
71
|
+
table[1]['ifIndex'].should eql(2)
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
context "version 2" do
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
context "version 3" do
|
81
|
+
it "should get using snmpv3" do
|
82
|
+
Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :version => 3, :username => 'MD5User', :security_level => Net::SNMP::Constants::SNMP_SEC_LEVEL_AUTHNOPRIV, :auth_protocol => :md5, :password => 'The Net-SNMP Demo Password') do |sess|
|
83
|
+
result = sess.get("sysDescr.0")
|
84
|
+
result.varbinds.first.value.should eql('test.net-snmp.org')
|
85
|
+
end
|
86
|
+
end
|
87
|
+
#it "should set using snmpv3" do
|
88
|
+
# pending
|
89
|
+
# Net::SNMP::Session.open(:peername => '127.0.0.1', :version => 3, :username => 'myuser', :authprotocol => :sha1, :authkey => '0x1234', :privprotocol => :des, :privkey => '0x25252') do |sess|
|
90
|
+
# result = sess.set([["sysDescr.0", Net::SNMP::Constants::ASN_OCTET_STR, 'yomama']])
|
91
|
+
# result.varbinds.first.value.should match(/Darwin/)
|
92
|
+
# end
|
93
|
+
#end
|
94
|
+
end
|
95
|
+
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
version: 0.1.
|
8
|
+
- 5
|
9
|
+
version: 0.1.5
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Ron McClain
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2011-04-
|
17
|
+
date: 2011-04-24 00:00:00 -05:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -69,6 +69,7 @@ files:
|
|
69
69
|
- lib/net-snmp.rb
|
70
70
|
- lib/net/snmp.rb
|
71
71
|
- lib/net/snmp/constants.rb
|
72
|
+
- lib/net/snmp/dispatcher.rb
|
72
73
|
- lib/net/snmp/error.rb
|
73
74
|
- lib/net/snmp/inline.rb
|
74
75
|
- lib/net/snmp/mib.rb
|
@@ -80,9 +81,13 @@ files:
|
|
80
81
|
- lib/net/snmp/version.rb
|
81
82
|
- lib/net/snmp/wrapper.rb
|
82
83
|
- net-snmp.gemspec
|
84
|
+
- spec/async_spec.rb
|
85
|
+
- spec/em_spec.rb
|
86
|
+
- spec/fiber_spec.rb
|
83
87
|
- spec/mib_spec.rb
|
84
88
|
- spec/net-snmp_spec.rb
|
85
89
|
- spec/spec_helper.rb
|
90
|
+
- spec/sync_spec.rb
|
86
91
|
- spec/wrapper_spec.rb
|
87
92
|
has_rdoc: true
|
88
93
|
homepage: ""
|
@@ -117,7 +122,11 @@ signing_key:
|
|
117
122
|
specification_version: 3
|
118
123
|
summary: Object oriented wrapper around C net-snmp libraries
|
119
124
|
test_files:
|
125
|
+
- spec/async_spec.rb
|
126
|
+
- spec/em_spec.rb
|
127
|
+
- spec/fiber_spec.rb
|
120
128
|
- spec/mib_spec.rb
|
121
129
|
- spec/net-snmp_spec.rb
|
122
130
|
- spec/spec_helper.rb
|
131
|
+
- spec/sync_spec.rb
|
123
132
|
- spec/wrapper_spec.rb
|