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 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.2.1 supports:
10
+ Version 1.0.0 supports:
11
11
 
12
- * SNMP v1 and v2 only
13
- * SNMP Get, GetNext, GetBulk (v2 only), Set, and Walk requests.
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", :version => :SNMPv1)
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
- if (response[OID_SYSTEM].is_a? Array)
108
- response[OID_SYSTEM].each do |vb|
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
- if (response[OID_SYSTEM].is_a? Array)
130
- response[OID_SYSTEM].each do |vb|
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,6 +1,6 @@
1
- module SNMP #:nodoc:
1
+ module SNMP
2
2
 
3
- class Integer #:nodoc:
3
+ class Integer # @private
4
4
  alias :rubify :to_i
5
5
  end
6
6
 
@@ -1,6 +1,6 @@
1
- module SNMP #:nodoc:
1
+ module SNMP
2
2
 
3
- class IpAddress #:nodoc:
3
+ class IpAddress # @private
4
4
  alias :rubify :to_s
5
5
  end
6
6
 
@@ -1,6 +1,6 @@
1
- module SNMP #:nodoc:
1
+ module SNMP
2
2
 
3
- class Null #:nodoc:
3
+ class Null # @private
4
4
  class << self
5
5
  def rubify
6
6
  nil
@@ -1,6 +1,6 @@
1
- module SNMP #:nodoc:
1
+ module SNMP
2
2
 
3
- class ObjectId #:nodoc:
3
+ class ObjectId # @private
4
4
  alias :rubify :to_s
5
5
  end
6
6
 
@@ -1,6 +1,6 @@
1
- module SNMP #:nodoc:
1
+ module SNMP
2
2
 
3
- class OctetString #:nodoc:
3
+ class OctetString # @private
4
4
  alias :rubify :to_s
5
5
  end
6
6
 
@@ -1,11 +1,16 @@
1
- module SNMP #:nodoc:
1
+ module SNMP
2
2
 
3
3
  class ResponseError
4
4
  attr_reader :error_status
5
- alias :rubify :error_status #:nodoc:
5
+ alias :rubify :error_status
6
6
 
7
- def initialize(error_status) #:nodoc:
8
- @error_status = error_status
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
@@ -1,5 +1,5 @@
1
1
  module SNMP4EM
2
- class Handler < EventMachine::Connection #:nodoc:
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
@@ -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::CommonRequests
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
- def init_socket #:nodoc:
18
- # When the socket is in error state, close the socket and re-open a new one.
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
- @socket.close_connection
21
- @socket = nil
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
- request.snmp_id = rand(2**31) # Largest SNMP Signed INTEGER
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 SNMPv1 agents. Optionally pass in the following parameters:
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 get/getnext/walk operations (default: public)
45
- # * _community_rw_ - Read-write community string to use for set operations (default: public)
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) #:nodoc:
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
- # This implements EM::Deferrable, so you can hang a callback() or errback() to retrieve the results.
3
+ # The result of calling {SNMPCommonRequests#get}.
4
4
 
5
5
  class SnmpGetRequest < SnmpRequest
6
6
  attr_accessor :snmp_id
7
7
 
8
- # For an SNMP-GET request, @pending_oids will be a ruby array of SNMP::ObjectNames that need to be fetched. As
9
- # responses come back from the agent, this array will be pruned of any error-producing OIDs. Once no errors
10
- # are returned, the @responses hash will be populated and returned.
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
- def handle_response(response) #:nodoc:
13
- if response.error_status == :noError
14
- # No errors, populate the @responses object so it can be returned
15
- response.each_varbind do |vb|
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
- @responses[request_oid.to_s] = value
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
- # Got an error, remove that oid from @pending_oids so we can try again
24
- error_oid = @pending_oids.delete_at(response.error_index - 1)
25
- @responses[error_oid.to_s] = SNMP::ResponseError.new(response.error_status)
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 @error_retries < 0
29
- fail "exhausted all retries"
30
- elsif @pending_oids.empty?
31
- # Send the @responses back to the requester, we're done!
32
- succeed @responses
33
- else
34
- @error_retries -= 1
35
- send
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
- # Send the contents of @pending_oids
53
+ query_oids = @oids.select{|oid| oid[:state] == :pending}.collect{|oid| oid[:requested_oid]}
45
54
 
46
- vb_list = SNMP::VarBindList.new(@pending_oids)
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
- # This implements EM::Deferrable, so you can hang a callback() or errback() to retrieve the results.
3
+ # The result of calling {SNMPv2Requests#getbulk}.
4
4
 
5
5
  class SnmpGetBulkRequest < SnmpRequest
6
6
  attr_accessor :snmp_id
7
7
 
8
- # For an SNMP-GETBULK request, @pending_oids will be a ruby array of SNMP::ObjectNames that need to be fetched. As
9
- # responses come back from the agent, this array will be pruned of any error-producing OIDs. Once no errors
10
- # are returned, the @responses hash will be populated and returned.
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
- def initialize(sender, oids, args = {}) #:nodoc:
13
- @nonrepeaters = args[:nonrepeaters] || 0
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) #:nodoc:
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
- @nonrepeaters.times do |i|
24
- request_oid = @pending_oids.shift
25
- response_vb = response.vb_list[i]
36
+ vb_list = response.vb_list
37
+ vb_index = 0
26
38
 
27
- @responses[request_oid.to_s] = [[response_vb.name, response_vb.value]]
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
- (@nonrepeaters ... response.vb_list.size).each do |i|
31
- request_oid = @pending_oids[(i - @nonrepeaters) % @pending_oids.size]
32
- response_vb = response.vb_list[i]
33
-
34
- @responses[request_oid.to_s] ||= Array.new
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
- # Got an error, remove that oid from @pending_oids so we can try again
42
- error_oid = @pending_oids.delete_at(response.error_index - 1)
43
- @responses[error_oid.to_s] = SNMP::ResponseError.new(response.error_status)
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 (@pending_oids.empty? || @error_retries.zero?)
47
- until @pending_oids.empty?
48
- error_oid = @pending_oids.shift
49
- @responses[error_oid.to_s] = SNMP::ResponseError.new(:genErr)
50
- end
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
- # Send the @responses back to the requester, we're done!
64
- succeed @responses
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
- # Send the contents of @pending_oids
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 = @maxrepetitions
82
- request.non_repeaters = @nonrepeaters
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