snmp4em 0.3 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +45 -17
- data/lib/snmp4em/extensions/snmp/integer.rb +2 -2
- data/lib/snmp4em/extensions/snmp/ip_address.rb +2 -2
- data/lib/snmp4em/extensions/snmp/null.rb +2 -2
- data/lib/snmp4em/extensions/snmp/object_id.rb +2 -2
- data/lib/snmp4em/extensions/snmp/octet_string.rb +2 -2
- data/lib/snmp4em/extensions/snmp/response_error.rb +9 -4
- data/lib/snmp4em/handler.rb +2 -4
- data/lib/snmp4em/manager.rb +21 -11
- data/lib/snmp4em/notification_handler.rb +27 -0
- data/lib/snmp4em/notification_manager.rb +23 -0
- data/lib/snmp4em/requests/snmp_bulkwalk_request.rb +86 -0
- data/lib/snmp4em/requests/snmp_get_request.rb +33 -24
- data/lib/snmp4em/requests/snmp_getbulk_request.rb +50 -50
- data/lib/snmp4em/requests/snmp_getnext_request.rb +43 -26
- data/lib/snmp4em/requests/snmp_set_request.rb +34 -61
- data/lib/snmp4em/requests/snmp_walk_request.rb +49 -59
- data/lib/snmp4em/{common_requests.rb → snmp_common_requests.rb} +16 -13
- data/lib/snmp4em/snmp_request.rb +37 -11
- data/lib/snmp4em/snmp_v2c_requests.rb +21 -6
- data/lib/snmp4em.rb +5 -5
- metadata +40 -16
- data/Gemfile +0 -7
- data/Manifest +0 -29
- data/Rakefile +0 -17
- data/snmp4em.gemspec +0 -23
- data/spec/models/test_message.rb +0 -7
- data/spec/models/test_request.rb +0 -10
- data/spec/models/test_response.rb +0 -7
- data/spec/spec.opts +0 -3
- data/spec/spec_helper.rb +0 -18
- data/spec/unit/handler_spec.rb +0 -34
- data/spec/unit/manager_spec.rb +0 -82
data/README.rdoc
CHANGED
@@ -7,20 +7,29 @@ This gem extends Ruby-SNMP[http://snmplib.rubyforge.org] to use the asynchronous
|
|
7
7
|
|
8
8
|
== Features
|
9
9
|
|
10
|
-
Version 0.
|
10
|
+
Version 1.0.0 supports:
|
11
11
|
|
12
|
-
* SNMP v1 and v2
|
13
|
-
* SNMP Get, GetNext,
|
12
|
+
* SNMP v1 and v2
|
13
|
+
* SNMP Get, GetNext, Set, and Walk requests. For SNMPv2 clients, GetBulk and WalkBulk
|
14
14
|
* Ability to query/set/walk multiple OIDs in parallel.
|
15
15
|
|
16
16
|
Future revisions of this library may support:
|
17
17
|
|
18
18
|
* Ability to act as an SNMP agent, responding to external queries.
|
19
|
-
* Ability to send/receive SNMP traps
|
20
19
|
|
21
20
|
There are no plans to support SNMP v3.
|
22
21
|
|
23
22
|
|
23
|
+
== Backwards compatibility
|
24
|
+
|
25
|
+
Version 1.0.0 tweaks the return values of a few functions. Please test code thoroughly before upgrading to 1.0.0 in production!
|
26
|
+
|
27
|
+
|
28
|
+
== Running tests
|
29
|
+
|
30
|
+
This library now includes a full suite of functional tests. They communicate with an SNMP daemon running on the localhost. The library comes with the necessary configuration, but it's much easier to fire up the provided rake task (`rake server`), running in a separate terminal window, before running `rspec`. This works fine on a Mac OS X machine using homebrew (`brew install net-snmp`).
|
31
|
+
|
32
|
+
|
24
33
|
== Acknowledgements
|
25
34
|
|
26
35
|
* The SNMP packet processing is handled by the Ruby-SNMP[http://snmplib.rubyforge.org] library, by David Halliday
|
@@ -39,7 +48,7 @@ A few definitions:
|
|
39
48
|
A simple SNMP-GET:
|
40
49
|
|
41
50
|
EM.run {
|
42
|
-
snmp = SNMP4EM::Manager.new(:host => "192.168.1.1"
|
51
|
+
snmp = SNMP4EM::Manager.new(:host => "192.168.1.1")
|
43
52
|
|
44
53
|
request = snmp.get([OID_SYSNAME, OID_SYSLOCATION])
|
45
54
|
|
@@ -104,12 +113,8 @@ A simple SNMP-WALK:
|
|
104
113
|
request = snmp.walk(OID_SYSTEM)
|
105
114
|
|
106
115
|
request.callback do |response|
|
107
|
-
|
108
|
-
|
109
|
-
puts "#{vb[0]} = #{vb[1]}"
|
110
|
-
end
|
111
|
-
else
|
112
|
-
puts "Got error: #{response[OID_SYSTEM]}"
|
116
|
+
response[OID_SYSTEM].each do |oid, value|
|
117
|
+
puts "#{oid} = #{value}"
|
113
118
|
end
|
114
119
|
end
|
115
120
|
|
@@ -118,6 +123,24 @@ A simple SNMP-WALK:
|
|
118
123
|
end
|
119
124
|
}
|
120
125
|
|
126
|
+
A simple SNMP-BULKWALK:
|
127
|
+
|
128
|
+
EM.run {
|
129
|
+
snmp = SNMP4EM::Manager.new(:host => "192.168.1.1")
|
130
|
+
|
131
|
+
request = snmp.bulkwalk(OID_SYSTEM)
|
132
|
+
|
133
|
+
request.callback do |response|
|
134
|
+
response[OID_SYSTEM].each do |oid, value|
|
135
|
+
puts "#{oid} = #{value}"
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
request.errback do |error|
|
140
|
+
puts "BULK-WALK got error #{error}"
|
141
|
+
end
|
142
|
+
}
|
143
|
+
|
121
144
|
A simple SNMP-GET-BULK:
|
122
145
|
|
123
146
|
EM.run {
|
@@ -126,12 +149,8 @@ A simple SNMP-GET-BULK:
|
|
126
149
|
request = snmp.getbulk(OID_SYSTEM)
|
127
150
|
|
128
151
|
request.callback do |response|
|
129
|
-
|
130
|
-
|
131
|
-
puts "#{vb[0]} = #{vb[1]}"
|
132
|
-
end
|
133
|
-
else
|
134
|
-
puts "Got error: #{response[OID_SYSTEM]}"
|
152
|
+
response[OID_SYSTEM].each do |oid, value|
|
153
|
+
puts "#{oid} = #{value}"
|
135
154
|
end
|
136
155
|
end
|
137
156
|
|
@@ -140,8 +159,17 @@ A simple SNMP-GET-BULK:
|
|
140
159
|
end
|
141
160
|
}
|
142
161
|
|
162
|
+
|
143
163
|
== Change Log
|
144
164
|
|
165
|
+
Version 1.0.0:
|
166
|
+
|
167
|
+
* Added SNMPv2 BULKWALK support
|
168
|
+
* Added ability to receive SNMP traps / informs
|
169
|
+
* Added functional tests (finally!)
|
170
|
+
* Moved documentation to Yard
|
171
|
+
* Lots of code cleanup
|
172
|
+
|
145
173
|
Version 0.2.1:
|
146
174
|
|
147
175
|
* Code cleanups, speed boosts
|
@@ -1,11 +1,16 @@
|
|
1
|
-
module SNMP
|
1
|
+
module SNMP
|
2
2
|
|
3
3
|
class ResponseError
|
4
4
|
attr_reader :error_status
|
5
|
-
alias :rubify :error_status
|
5
|
+
alias :rubify :error_status
|
6
6
|
|
7
|
-
|
8
|
-
|
7
|
+
# Accepts either a string (from SNMP::PDU.error_status) or one of SNMP::EndOfMibView, SNMP::NoSuchObject, or SNMP::NoSuchInstance
|
8
|
+
def initialize(error)
|
9
|
+
if [SNMP::EndOfMibView, SNMP::NoSuchObject, SNMP::NoSuchInstance].include? error
|
10
|
+
@error_status = error.asn1_type.to_sym
|
11
|
+
else
|
12
|
+
@error_status = error.to_sym
|
13
|
+
end
|
9
14
|
end
|
10
15
|
|
11
16
|
# String representation of this error
|
data/lib/snmp4em/handler.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module SNMP4EM
|
2
|
-
class Handler < EventMachine::Connection
|
2
|
+
class Handler < EventMachine::Connection # @private
|
3
3
|
def receive_data(data)
|
4
4
|
begin
|
5
5
|
message = SNMP::Message.decode(data)
|
@@ -10,7 +10,6 @@ module SNMP4EM
|
|
10
10
|
end
|
11
11
|
|
12
12
|
response = message.pdu
|
13
|
-
request = Manager.pending_requests[response.request_id]
|
14
13
|
|
15
14
|
#
|
16
15
|
# in the event of a timeout retry, the request will have been
|
@@ -18,8 +17,7 @@ module SNMP4EM
|
|
18
17
|
# request, ignore it.
|
19
18
|
#
|
20
19
|
|
21
|
-
if request
|
22
|
-
request.timeout_timer.cancel
|
20
|
+
if request = Manager.pending_requests[response.request_id]
|
23
21
|
request.handle_response(response)
|
24
22
|
end
|
25
23
|
end
|
data/lib/snmp4em/manager.rb
CHANGED
@@ -1,8 +1,14 @@
|
|
1
1
|
# The SNMP4EM library
|
2
2
|
|
3
3
|
module SNMP4EM
|
4
|
+
# Provides access to send and receive SNMP messages via a UDP socket.
|
5
|
+
#
|
6
|
+
# _Note_ - The methods for actually sending requests are documented in {SNMP4EM::SNMPCommonRequests} and, for
|
7
|
+
# those specific to SNMPv2, {SNMP4EM::SNMPv2cRequests}.
|
4
8
|
class Manager
|
5
|
-
include SNMP4EM::
|
9
|
+
include SNMP4EM::SNMPCommonRequests
|
10
|
+
|
11
|
+
MAX_INDEX = 2**31 # @private Largest SNMP Signed INTEGER
|
6
12
|
|
7
13
|
#
|
8
14
|
# @pending_requests maps a request's id to its SnmpRequest
|
@@ -14,21 +20,24 @@ module SNMP4EM
|
|
14
20
|
attr_reader :pending_requests
|
15
21
|
attr_reader :socket
|
16
22
|
|
17
|
-
|
18
|
-
|
23
|
+
# Initializes the outgoing socket. Checks to see if it's in an error state, and if so closes and reopens the socket
|
24
|
+
def init_socket
|
19
25
|
if !@socket.nil? && @socket.error?
|
20
|
-
|
21
|
-
|
26
|
+
@socket.close_connection
|
27
|
+
@socket = nil
|
22
28
|
end
|
23
29
|
|
30
|
+
@next_index ||= rand(MAX_INDEX)
|
24
31
|
@socket ||= EM::open_datagram_socket("0.0.0.0", 0, Handler)
|
25
32
|
end
|
26
33
|
|
34
|
+
# Assigns an SNMP ID to an outgoing request so that it can be matched with its incoming response
|
27
35
|
def track_request(request)
|
28
36
|
@pending_requests.delete(request.snmp_id)
|
29
37
|
|
30
38
|
begin
|
31
|
-
|
39
|
+
@next_index = (@next_index + 1) % MAX_INDEX
|
40
|
+
request.snmp_id = @next_index
|
32
41
|
end while @pending_requests[request.snmp_id]
|
33
42
|
|
34
43
|
@pending_requests[request.snmp_id] = request
|
@@ -37,14 +46,15 @@ module SNMP4EM
|
|
37
46
|
|
38
47
|
attr_reader :host, :port, :timeout, :retries, :version, :community_ro, :community_rw
|
39
48
|
|
40
|
-
# Creates a new object to communicate with
|
49
|
+
# Creates a new object to communicate with SNMP agents. Optionally pass in the following parameters:
|
41
50
|
# * _host_ - IP/hostname of remote agent (default: 127.0.0.1)
|
42
51
|
# * _port_ - UDP port on remote agent (default: 161)
|
43
|
-
# * _community_ - Community string to use (default: public)
|
44
|
-
# * _community_ro_ - Read-only community string to use for
|
45
|
-
# * _community_rw_ - Read-write community string to use for
|
52
|
+
# * _community_ - Community string to use for all operations (default: public)
|
53
|
+
# * _community_ro_ - Read-only community string to use for read-only operations (default: public)
|
54
|
+
# * _community_rw_ - Read-write community string to use for read-write operations (default: public)
|
46
55
|
# * _timeout_ - Number of seconds to wait before a request times out (default: 1)
|
47
56
|
# * _retries_ - Number of retries before failing (default: 3)
|
57
|
+
# * _version_ - SNMP version, either :SNMPv1 or :SNMPv2c (default: :SNMPv2c)
|
48
58
|
|
49
59
|
def initialize(args = {})
|
50
60
|
@host = args[:host] || "127.0.0.1"
|
@@ -61,7 +71,7 @@ module SNMP4EM
|
|
61
71
|
self.class.init_socket
|
62
72
|
end
|
63
73
|
|
64
|
-
def send(message)
|
74
|
+
def send(message) # @private
|
65
75
|
self.class.socket.send_datagram message.encode, @host, @port
|
66
76
|
end
|
67
77
|
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module SNMP4EM
|
2
|
+
class NotificationHandler < EventMachine::Connection # @private
|
3
|
+
attr_accessor :callbacks
|
4
|
+
|
5
|
+
def post_init
|
6
|
+
@callbacks = []
|
7
|
+
end
|
8
|
+
|
9
|
+
def receive_data(data)
|
10
|
+
source_port, source_ip = Socket.unpack_sockaddr_in(get_peername)
|
11
|
+
|
12
|
+
begin
|
13
|
+
message = SNMP::Message.decode(data)
|
14
|
+
rescue Exception => err
|
15
|
+
return
|
16
|
+
end
|
17
|
+
|
18
|
+
trap = message.pdu
|
19
|
+
|
20
|
+
return unless trap.is_a?(SNMP::SNMPv1_Trap) || trap.is_a?(SNMP::SNMPv2_Trap)
|
21
|
+
|
22
|
+
trap.source_ip = source_ip
|
23
|
+
|
24
|
+
@callbacks.each { |callback| callback.yield(message.pdu) }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module SNMP4EM
|
2
|
+
# Provides access to receive SNMP traps (SNMPv1) and notifications (SNMPv2)
|
3
|
+
class NotificationManager
|
4
|
+
attr_reader :host, :port, :timeout, :retries, :version, :community_ro, :community_rw
|
5
|
+
|
6
|
+
# Creates a new object to communicate with SNMP agents. Optionally pass in the following parameters:
|
7
|
+
# * _host_ - IP/hostname of local interface on which to listen (default: 127.0.0.1)
|
8
|
+
# * _port_ - UDP port on which to listen (default: 162)
|
9
|
+
def initialize(args = {})
|
10
|
+
@host = args[:host] || "127.0.0.1"
|
11
|
+
@port = args[:port] || 162
|
12
|
+
|
13
|
+
@socket = EM::open_datagram_socket(@host, @port, NotificationHandler)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Register a callback that is upon reception of a trap/notification. Multiple callbacks can be
|
17
|
+
# registered. Each will be passed the trap/notification object. It is important to determine whether
|
18
|
+
# it is a SNMP::SNMPv1_Trap or SNMP::SNMPv2_Trap, as each behaves slightly differently.
|
19
|
+
def on_trap &block
|
20
|
+
@socket.callbacks << block
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module SNMP4EM
|
2
|
+
|
3
|
+
# The result of calling {SNMPv2cRequests#bulkwalk}.
|
4
|
+
|
5
|
+
class SnmpBulkWalkRequest < SnmpRequest
|
6
|
+
attr_accessor :snmp_id
|
7
|
+
|
8
|
+
# Used to register a callback that is triggered when the query result is ready. The resulting object is passed as a parameter to the block.
|
9
|
+
def callback &block
|
10
|
+
super
|
11
|
+
end
|
12
|
+
|
13
|
+
# Used to register a callback that is triggered when query fails to complete successfully.
|
14
|
+
def errback &block
|
15
|
+
super
|
16
|
+
end
|
17
|
+
|
18
|
+
def on_init args # @private
|
19
|
+
@oids.each{|oid| oid.merge!({:next_oid => oid[:requested_oid], :responses => {}})}
|
20
|
+
end
|
21
|
+
|
22
|
+
def handle_response(response) # @private
|
23
|
+
super
|
24
|
+
|
25
|
+
if response.error_status == :noError
|
26
|
+
vb_list = response.vb_list
|
27
|
+
vb_index = 0
|
28
|
+
curr_pending_oids = pending_oids
|
29
|
+
|
30
|
+
while response_vb = vb_list.shift
|
31
|
+
oid = curr_pending_oids[vb_index % curr_pending_oids.count]
|
32
|
+
response_oid = response_vb.name
|
33
|
+
|
34
|
+
next unless oid[:state] == :pending
|
35
|
+
|
36
|
+
if response_vb.value == SNMP::EndOfMibView
|
37
|
+
oid[:state] = :complete
|
38
|
+
|
39
|
+
elsif ! response_oid.subtree_of?(oid[:requested_oid])
|
40
|
+
oid[:state] = :complete
|
41
|
+
else
|
42
|
+
oid[:responses][response_oid.to_s] = format_value(response_vb)
|
43
|
+
oid[:next_oid] = response_oid
|
44
|
+
end
|
45
|
+
|
46
|
+
vb_index += 1
|
47
|
+
end
|
48
|
+
|
49
|
+
else
|
50
|
+
error_oid = pending_oids[response.error_index - 1]
|
51
|
+
error_oid[:state] = :error
|
52
|
+
error_oid[:error] = SNMP::ResponseError.new(response.error_status)
|
53
|
+
end
|
54
|
+
|
55
|
+
if pending_oids.empty? || (@max_results && @oids.collect{|oid| oid[:responses].count}.max >= @max_results)
|
56
|
+
result = {}
|
57
|
+
|
58
|
+
@oids.each do |oid|
|
59
|
+
requested_oid = oid[:requested_string]
|
60
|
+
result[requested_oid] = oid[:error] || oid[:responses]
|
61
|
+
end
|
62
|
+
|
63
|
+
succeed result
|
64
|
+
return
|
65
|
+
end
|
66
|
+
|
67
|
+
send
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def send
|
73
|
+
Manager.track_request(self)
|
74
|
+
|
75
|
+
vb_list = SNMP::VarBindList.new(pending_oids.collect{|oid| oid[:next_oid]})
|
76
|
+
request = SNMP::GetBulkRequest.new(@snmp_id, vb_list)
|
77
|
+
|
78
|
+
request.max_repetitions = 10
|
79
|
+
request.non_repeaters = 0
|
80
|
+
|
81
|
+
message = SNMP::Message.new(@sender.version, @sender.community_ro, request)
|
82
|
+
|
83
|
+
super(message)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -1,39 +1,48 @@
|
|
1
1
|
module SNMP4EM
|
2
2
|
|
3
|
-
#
|
3
|
+
# The result of calling {SNMPCommonRequests#get}.
|
4
4
|
|
5
5
|
class SnmpGetRequest < SnmpRequest
|
6
6
|
attr_accessor :snmp_id
|
7
7
|
|
8
|
-
#
|
9
|
-
|
10
|
-
|
8
|
+
# Used to register a callback that is triggered when the query result is ready. The resulting object is passed as a parameter to the block.
|
9
|
+
def callback &block
|
10
|
+
super
|
11
|
+
end
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
request_oid = @pending_oids.shift
|
17
|
-
value = @return_raw || !vb.value.respond_to?(:rubify) ? vb.value : vb.value.rubify
|
13
|
+
# Used to register a callback that is triggered when query fails to complete successfully.
|
14
|
+
def errback &block
|
15
|
+
super
|
16
|
+
end
|
18
17
|
|
19
|
-
|
18
|
+
def handle_response(response) # @private
|
19
|
+
super
|
20
|
+
|
21
|
+
if response.error_status == :noError
|
22
|
+
pending_oids.zip(response.varbind_list).each do |oid, response_vb|
|
23
|
+
oid[:response] = format_value(response_vb)
|
24
|
+
oid[:state] = :complete
|
20
25
|
end
|
21
26
|
|
22
27
|
else
|
23
|
-
|
24
|
-
error_oid =
|
25
|
-
|
28
|
+
error_oid = pending_oids[response.error_index - 1]
|
29
|
+
error_oid[:state] = :error
|
30
|
+
error_oid[:error] = SNMP::ResponseError.new(response.error_status)
|
26
31
|
end
|
27
32
|
|
28
|
-
if
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
33
|
+
if pending_oids.empty?
|
34
|
+
result = {}
|
35
|
+
|
36
|
+
@oids.each do |oid|
|
37
|
+
requested_oid = oid[:requested_string]
|
38
|
+
result[requested_oid] = oid[:error] || oid[:response]
|
39
|
+
end
|
40
|
+
|
41
|
+
succeed result
|
42
|
+
return
|
36
43
|
end
|
44
|
+
|
45
|
+
send
|
37
46
|
end
|
38
47
|
|
39
48
|
private
|
@@ -41,9 +50,9 @@ module SNMP4EM
|
|
41
50
|
def send
|
42
51
|
Manager.track_request(self)
|
43
52
|
|
44
|
-
|
53
|
+
query_oids = @oids.select{|oid| oid[:state] == :pending}.collect{|oid| oid[:requested_oid]}
|
45
54
|
|
46
|
-
vb_list = SNMP::VarBindList.new(
|
55
|
+
vb_list = SNMP::VarBindList.new(query_oids)
|
47
56
|
request = SNMP::GetRequest.new(@snmp_id, vb_list)
|
48
57
|
message = SNMP::Message.new(@sender.version, @sender.community_ro, request)
|
49
58
|
|
@@ -1,71 +1,73 @@
|
|
1
1
|
module SNMP4EM
|
2
2
|
|
3
|
-
#
|
3
|
+
# The result of calling {SNMPv2Requests#getbulk}.
|
4
4
|
|
5
5
|
class SnmpGetBulkRequest < SnmpRequest
|
6
6
|
attr_accessor :snmp_id
|
7
7
|
|
8
|
-
#
|
9
|
-
|
10
|
-
|
8
|
+
# Used to register a callback that is triggered when the query result is ready. The resulting object is passed as a parameter to the block.
|
9
|
+
def callback &block
|
10
|
+
super
|
11
|
+
end
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
@maxrepetitions = args[:maxrepetitions] || 10
|
15
|
-
|
13
|
+
# Used to register a callback that is triggered when query fails to complete successfully.
|
14
|
+
def errback &block
|
16
15
|
super
|
17
16
|
end
|
17
|
+
|
18
|
+
def on_init args # @private
|
19
|
+
@oids.each_index do |i|
|
20
|
+
@oids[i][:responses] = {}
|
21
|
+
@oids[i][:method] = (i < (args[:non_repeaters] || 0) ? :non_repeating : :repeating)
|
22
|
+
end
|
23
|
+
|
24
|
+
@max_results ||= 10
|
25
|
+
end
|
18
26
|
|
19
|
-
def handle_response(response)
|
27
|
+
def handle_response(response) # @private
|
28
|
+
super
|
29
|
+
|
30
|
+
pending_repeating_oids = pending_oids.select{|oid| oid[:method] == :repeating}
|
31
|
+
pending_non_repeating_oids = pending_oids.select{|oid| oid[:method] == :non_repeating}
|
32
|
+
|
20
33
|
if response.error_status == :noError
|
21
34
|
# No errors, populate the @responses object so it can be returned
|
22
35
|
|
23
|
-
|
24
|
-
|
25
|
-
response_vb = response.vb_list[i]
|
36
|
+
vb_list = response.vb_list
|
37
|
+
vb_index = 0
|
26
38
|
|
27
|
-
|
39
|
+
pending_non_repeating_oids.each do |oid|
|
40
|
+
response_vb = vb_list.shift
|
41
|
+
oid[:responses][response_vb.name.to_s] = format_value(response_vb)
|
42
|
+
oid[:state] = :complete
|
28
43
|
end
|
29
44
|
|
30
|
-
|
31
|
-
|
32
|
-
response_vb =
|
33
|
-
|
34
|
-
|
35
|
-
@responses[request_oid.to_s] << [response_vb.name, response_vb.value]
|
45
|
+
while response_vb = vb_list.shift
|
46
|
+
oid = pending_repeating_oids[vb_index % pending_repeating_oids.count]
|
47
|
+
oid[:responses][response_vb.name.to_s] = format_value(response_vb) unless response_vb.value == SNMP::EndOfMibView
|
48
|
+
oid[:state] = :complete
|
49
|
+
vb_index += 1
|
36
50
|
end
|
37
51
|
|
38
|
-
@pending_oids.clear
|
39
|
-
|
40
52
|
else
|
41
|
-
|
42
|
-
error_oid =
|
43
|
-
|
53
|
+
error_oid = pending_oids[response.error_index - 1]
|
54
|
+
error_oid[:state] = :error
|
55
|
+
error_oid[:error] = SNMP::ResponseError.new(response.error_status)
|
44
56
|
end
|
45
57
|
|
46
|
-
if
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
if (!@return_raw)
|
53
|
-
@responses.each_pair do |search_oid, values|
|
54
|
-
values.collect! do |oid_value|
|
55
|
-
oid_value[1] = oid_value[1].rubify if oid_value[1].respond_to?(:rubify)
|
56
|
-
oid_value
|
57
|
-
end
|
58
|
-
|
59
|
-
@responses[search_oid] = values
|
60
|
-
end
|
58
|
+
if pending_oids.empty?
|
59
|
+
result = {}
|
60
|
+
|
61
|
+
@oids.each do |oid|
|
62
|
+
requested_oid = oid[:requested_string]
|
63
|
+
result[requested_oid] = oid[:error] || oid[:responses]
|
61
64
|
end
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
else
|
66
|
-
@error_retries -= 1
|
67
|
-
send
|
65
|
+
|
66
|
+
succeed result
|
67
|
+
return
|
68
68
|
end
|
69
|
+
|
70
|
+
send
|
69
71
|
end
|
70
72
|
|
71
73
|
private
|
@@ -73,13 +75,11 @@ module SNMP4EM
|
|
73
75
|
def send
|
74
76
|
Manager.track_request(self)
|
75
77
|
|
76
|
-
|
77
|
-
|
78
|
-
vb_list = SNMP::VarBindList.new(@pending_oids)
|
78
|
+
vb_list = SNMP::VarBindList.new(pending_oids.collect{|oid| oid[:requested_oid]})
|
79
79
|
request = SNMP::GetBulkRequest.new(@snmp_id, vb_list)
|
80
80
|
|
81
|
-
request.max_repetitions = @
|
82
|
-
request.non_repeaters =
|
81
|
+
request.max_repetitions = @max_results
|
82
|
+
request.non_repeaters = pending_oids.select{|oid| oid[:method] == :non_repeating}.count
|
83
83
|
|
84
84
|
message = SNMP::Message.new(@sender.version, @sender.community_ro, request)
|
85
85
|
|