net-snmp 0.1.4 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|