snmp4em 0.2.1 → 0.3

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.
@@ -1,60 +1,32 @@
1
1
  module SNMP4EM
2
2
 
3
- # Returned from SNMP4EM::SNMPv1.getnext(). This implements EM::Deferrable, so you can hang a callback()
4
- # or errback() to retrieve the results.
3
+ # This implements EM::Deferrable, so you can hang a callback() or errback() to retrieve the results.
5
4
 
6
5
  class SnmpGetNextRequest < SnmpRequest
7
- attr_reader :snmp_id
6
+ attr_accessor :snmp_id
8
7
 
9
8
  # For an SNMP-GETNEXT request, @pending_oids will be a ruby array of SNMP::ObjectNames that need to be fetched. As
10
9
  # responses come back from the agent, this array will be pruned of any error-producing OIDs. Once no errors
11
10
  # are returned, the @responses hash will be populated and returned. The values of the hash will consist of a
12
11
  # two-element array, in the form of [OID, VALUE], showing the next oid & value.
13
-
14
- def initialize(sender, oids, args = {}) #:nodoc:
15
- @sender = sender
16
-
17
- @timeout_timer = nil
18
- @timeout_retries = @sender.retries
19
- @error_retries = oids.size
20
-
21
- @return_raw = args[:return_raw] || false
22
-
23
- @responses = Hash.new
24
- @pending_oids = SNMP::VarBindList.new(oids).collect{|r| r.name}
25
-
26
- init_callbacks
27
- send
28
- end
29
12
 
30
13
  def handle_response(response) #:nodoc:
31
- if (response.error_status == :noError)
14
+ if response.error_status == :noError
32
15
  # No errors, populate the @responses object so it can be returned
33
16
  response.each_varbind do |vb|
34
17
  request_oid = @pending_oids.shift
35
- @responses[request_oid.to_s] = [vb.name, vb.value]
18
+ value = @return_raw || !vb.value.respond_to?(:rubify) ? vb.value : vb.value.rubify
19
+ @responses[request_oid.to_s] = [vb.name.to_s, value]
36
20
  end
37
-
38
21
  else
39
22
  # Got an error, remove that oid from @pending_oids so we can try again
40
23
  error_oid = @pending_oids.delete_at(response.error_index - 1)
41
24
  @responses[error_oid.to_s] = SNMP::ResponseError.new(response.error_status)
42
25
  end
43
-
44
- if (@pending_oids.empty? || @error_retries.zero?)
45
- until @pending_oids.empty?
46
- error_oid = @pending_oids.shift
47
- @responses[error_oid.to_s] = SNMP::ResponseError.new(:genErr)
48
- end
49
26
 
50
- @responses.each_pair do |oid, value|
51
- if value.is_a? Array
52
- @responses[oid][1] = value[1].rubify if (!@return_raw && value[1].respond_to?(:rubify))
53
- else
54
- @responses[oid] = value.rubify if (!@return_raw && value.respond_to?(:rubify))
55
- end
56
- end
57
-
27
+ if @error_retries < 0
28
+ fail "exhausted all retries"
29
+ elsif @pending_oids.empty?
58
30
  # Send the @responses back to the requester, we're done!
59
31
  succeed @responses
60
32
  else
@@ -66,13 +38,13 @@ module SNMP4EM
66
38
  private
67
39
 
68
40
  def send #:nodoc:
69
- # Send the contents of @pending_oids
41
+ Manager.track_request(self)
70
42
 
71
- @snmp_id = generate_snmp_id
43
+ # Send the contents of @pending_oids
72
44
 
73
45
  vb_list = SNMP::VarBindList.new(@pending_oids)
74
46
  request = SNMP::GetNextRequest.new(@snmp_id, vb_list)
75
- message = SNMP::Message.new(:SNMPv1, @sender.community_ro, request)
47
+ message = SNMP::Message.new(@sender.version, @sender.community_ro, request)
76
48
 
77
49
  super(message)
78
50
  end
@@ -4,7 +4,7 @@ module SNMP4EM
4
4
  # or errback() to retrieve the results.
5
5
 
6
6
  class SnmpSetRequest < SnmpRequest
7
- attr_reader :snmp_id
7
+ attr_accessor :snmp_id
8
8
 
9
9
  # For an SNMP-SET request, @pending_varbinds will by an SNMP::VarBindList, initially populated from the
10
10
  # provided oids hash. Variables can be passed as specific types from the SNMP library (i.e. SNMP::IpAddress)
@@ -13,22 +13,26 @@ module SNMP4EM
13
13
  # are produced, the @responses object is populated and returned.
14
14
 
15
15
  def initialize(sender, oids, args = {}) #:nodoc:
16
+ _oids = [*oids]
17
+
16
18
  @sender = sender
17
19
 
18
20
  @timeout_timer = nil
19
21
  @timeout_retries = @sender.retries
20
- @error_retries = oids.size
22
+ @error_retries = _oids.size
21
23
 
22
24
  @return_raw = args[:return_raw] || false
23
25
 
24
26
  @responses = Hash.new
25
27
  @pending_varbinds = SNMP::VarBindList.new()
26
28
 
27
- oids.each_pair do |oid,value|
29
+ _oids.each do |oid,value|
28
30
  if value.is_a? Integer
29
31
  snmp_value = SNMP::Integer.new(value)
30
32
  elsif value.is_a? String
31
33
  snmp_value = SNMP::OctetString.new(value)
34
+ else
35
+ snmp_value = value
32
36
  end
33
37
 
34
38
  @pending_varbinds << SNMP::VarBind.new(oid,snmp_value)
@@ -76,13 +80,13 @@ module SNMP4EM
76
80
  private
77
81
 
78
82
  def send
83
+ Manager.track_request(self)
84
+
79
85
  # Send the contents of @pending_varbinds
80
-
81
- @snmp_id = generate_snmp_id
82
86
 
83
87
  vb_list = SNMP::VarBindList.new(@pending_varbinds)
84
88
  request = SNMP::SetRequest.new(@snmp_id, vb_list)
85
- message = SNMP::Message.new(:SNMPv1, @sender.community_rw, request)
89
+ message = SNMP::Message.new(@sender.version, @sender.community_ro, request)
86
90
 
87
91
  super(message)
88
92
  end
@@ -1,74 +1,47 @@
1
1
  module SNMP4EM
2
2
 
3
- # Returned from SNMP4EM::SNMPv1.walk(). This implements EM::Deferrable, so you can hang a callback()
4
- # or errback() to retrieve the results.
3
+ # This implements EM::Deferrable, so you can hang a callback() or errback() to retrieve the results.
5
4
 
6
5
  class SnmpWalkRequest < SnmpRequest
7
- attr_reader :snmp_id
6
+ attr_accessor :snmp_id
8
7
 
9
- # For an SNMP-WALK request, @pending_oids will be a ruby array of SNMP::ObjectNames that need to be walked.
10
- # Note that this library supports walking multiple OIDs in parallel. Once any error-producing OIDs are removed,
11
- # a series of SNMP-GETNEXT requests are sent. Each response OID is checked to see if it begins with the walk OID.
12
- # If so, the incoming OID/value pair is appended to the @response hash, and will be used in subsequent GETNEXT
13
- # requests. Once an OID is returned that does not begin with the walk OID, that walk OID is removed from the
14
- # @pending_oids array.
15
-
16
- def initialize(sender, oids, args = {}) #:nodoc:
17
- @sender = sender
18
-
19
- @timeout_timer = nil
20
- @timeout_retries = @sender.retries
21
- @error_retries = oids.size
22
-
23
- @return_raw = args[:return_raw] || false
24
- @max_results = args[:max_results] || nil
25
-
26
- @responses = Hash.new
27
- @pending_oids = SNMP::VarBindList.new(oids).collect{|r| r.name}
28
-
29
- init_callbacks
30
- send
31
- end
32
-
8
+ # SNMP-WALK is faked using GETNEXT queries until the returned OID isn't a subtree of the walk OID.
9
+ #
10
+ # @next_oids is a hash that maps the base walk OID to the next OID to be queried.
11
+ #
12
+ # @query_indexes simply tracks the order in which the next_oids were packaged up, in order to
13
+ # determine which query left the subtree
14
+ #
15
+ # Note that this library supports walking multiple base OIDs in parallel, and that the walk fails
16
+ # atomically with a list of OIDS that failed to gather.
17
+ #
33
18
  def handle_response(response) #:nodoc:
34
- oids_to_delete = []
19
+ if response.error_status == :noError
35
20
 
36
- if (response.error_status == :noError)
37
21
  response.varbind_list.each_index do |i|
38
- walk_oid = @pending_oids[i]
39
22
  response_vb = response.varbind_list[i]
40
-
41
- # Initialize the responses array if necessary
42
- @responses[walk_oid.to_s] ||= Array.new
43
-
44
- # If the incoming response-oid begins with the walk-oid, then append the pairing
45
- # to the @response array. Otherwise, add it to the list of oids ready to delete
46
- if (response_vb.name[0,walk_oid.length] == walk_oid)
47
- @responses[walk_oid.to_s] << [response_vb.name, response_vb.value]
23
+ response_oid = response_vb.name
24
+ response_walk_oid = response_oid.dup; response_walk_oid.pop
25
+
26
+ if response_walk_oid.subtree_of?(@query_indexes[i])
27
+ value = @return_raw || !response_vb.value.respond_to?(:rubify) ? response_vb.value : response_vb.value.rubify
28
+ @responses[response_walk_oid.to_s][response_oid.dup.pop] = value
29
+ @next_oids[response_walk_oid] = response_oid
48
30
  else
49
- # If we were to delete thid oid from @pending_oids now, it would mess up the
50
- # @pending_oids[i] call above.
51
- oids_to_delete << walk_oid
31
+ @next_oids.delete(@query_indexes[i])
52
32
  end
53
33
  end
54
34
 
55
35
  @max_results -= 1 unless @max_results.nil?
56
-
57
36
  else
58
- error_oid = @pending_oids[response.error_index - 1]
59
- oids_to_delete << error_oid
60
-
61
- @responses[error_oid.to_s] = SNMP::ResponseError.new(response.error_status)
37
+ @errors ||= []
38
+ error_oid = response.varbind_list[response.error_index].name
39
+ @errors << SNMP::ResponseError.new("Couldn't gather: #{error_oid} -> #{response.error_status}")
40
+ fail @errors if @error_retries < 1
62
41
  @error_retries -= 1
63
42
  end
64
-
65
- oids_to_delete.each{|oid| @pending_oids.delete oid}
66
-
67
- if (@pending_oids.empty? || (@error_retries < 0) || (@max_results.to_i < 0))
68
- @responses.each_pair do |oid, value|
69
- @responses[oid] = value.rubify if (!@return_raw && value.respond_to?(:rubify))
70
- end
71
-
43
+
44
+ if @next_oids.empty? || @max_results.to_i < 0
72
45
  # Send the @responses back to the requester, we're done!
73
46
  succeed @responses
74
47
  else
@@ -79,24 +52,35 @@ module SNMP4EM
79
52
  private
80
53
 
81
54
  def send
82
- @snmp_id = generate_snmp_id
55
+ Manager.track_request(self)
83
56
 
84
- # This oids array will consist of all the oids that need to be getnext'd
85
- oids = Array.new
86
-
87
- @pending_oids.each do |oid|
88
- # If there's already a response for this walk-oid, then use the last returned oid, otherwise
89
- # start with the walk-oid.
90
- if @responses.has_key?(oid.to_s)
91
- oids << @responses[oid.to_s].last.first
92
- else
93
- oids << oid
57
+ #
58
+ # @next_oids maps the walk oid to its next getnext oid
59
+ #
60
+ unless @next_oids
61
+ @responses = {}
62
+ @next_oids = {}
63
+ @pending_oids.each do |walk_oid|
64
+ @next_oids[walk_oid] = walk_oid
65
+ @responses[walk_oid.to_s] = {}
94
66
  end
95
67
  end
68
+
69
+ #
70
+ # @query_indexes maps the index of the requested oid to the walk oid
71
+ #
72
+ i = 0
73
+ @query_indexes = {}
74
+ query_oids = \
75
+ @next_oids.collect do |walk_oid, next_oid|
76
+ @query_indexes[i] = walk_oid
77
+ i += 1
78
+ next_oid
79
+ end
96
80
 
97
- vb_list = SNMP::VarBindList.new(oids)
81
+ vb_list = SNMP::VarBindList.new(query_oids)
98
82
  request = SNMP::GetNextRequest.new(@snmp_id, vb_list)
99
- message = SNMP::Message.new(:SNMPv1, @sender.community_ro, request)
83
+ message = SNMP::Message.new(@sender.version, @sender.community_ro, request)
100
84
 
101
85
  super(message)
102
86
  end
@@ -1,24 +1,35 @@
1
1
  module SNMP4EM
2
2
  class SnmpRequest #:nodoc:
3
3
  include EM::Deferrable
4
-
5
- def generate_snmp_id
6
- begin
7
- snmp_id = rand(1073741823) # Largest Fixnum
8
- end until (SnmpConnection.pending_requests.select{|r| r.snmp_id == snmp_id}.empty?)
9
4
 
10
- return snmp_id
11
- end
5
+ attr_accessor :timeout_timer
6
+
7
+ def initialize(sender, oids, args = {}) #:nodoc:
8
+ _oids = [*oids]
9
+
10
+ @sender = sender
11
+
12
+ @timeout_timer = nil
13
+ @timeout_retries = @sender.retries
14
+ @error_retries = _oids.size
15
+
16
+ @return_raw = args[:return_raw] || false
17
+
18
+ @responses = {}
19
+ @pending_oids = _oids.collect { |oid_str| SNMP::ObjectId.new(oid_str) }
12
20
 
21
+ init_callbacks
22
+ send
23
+ end
24
+
13
25
  def init_callbacks
14
26
  self.callback do
15
- SnmpConnection.pending_requests.delete_if {|r| r.snmp_id == @snmp_id}
16
- @timeout_timer.cancel
27
+ Manager.pending_requests.delete(@snmp_id)
17
28
  end
18
29
 
19
30
  self.errback do
20
- SnmpConnection.pending_requests.delete_if {|r| r.snmp_id == @snmp_id}
21
31
  @timeout_timer.cancel
32
+ Manager.pending_requests.delete(@snmp_id)
22
33
  end
23
34
  end
24
35
 
@@ -28,13 +39,13 @@ module SNMP4EM
28
39
  @timeout_timer.cancel if @timeout_timer.is_a?(EM::Timer)
29
40
 
30
41
  @timeout_timer = EM::Timer.new(@sender.timeout) do
31
- if (@timeout_retries > 0)
42
+ if @timeout_retries > 0
32
43
  send
33
44
  @timeout_retries -= 1
34
45
  else
35
- fail("timeout")
46
+ fail "exhausted all timeout retries"
36
47
  end
37
48
  end
38
49
  end
39
50
  end
40
- end
51
+ end
@@ -0,0 +1,25 @@
1
+ # The SNMP4EM library
2
+
3
+ module SNMP4EM
4
+ module SNMPv2cRequests
5
+ # Sends an SNMPv2 GET-BULK request to fetch multiple OID-value pairings simultaneously. This produces similar results to an SNMP-WALK using a single
6
+ # request/response transaction (SNMP-WALK is actually an inefficient series of GET-NEXTs). Multiple OIDs can be passed into the _oids_ array. Two
7
+ # additional parameters control how this list is processed. Setting the parameter _nonrepeaters_ to value _N_ indicates that the first _N_ OIDs will
8
+ # fetch a single value. This is identical to running a single GET-NEXT for the OID. Any remaining OIDs will fetch multiple values. The number of values
9
+ # fetched is controlled by the parameter _maxrepetitions_. The function returns a SnmpGetBulkRequest object, which implements EM::Deferrable. From there,
10
+ # implement a callback/errback to fetch the result. On success, the result will be a hash, mapping requested OID prefixes to the returned value.
11
+ # Successful fetches will be mapped to an array of two-element arrays, each of which consists of [_oid_ , _value_]. Unsuccessful fetches will be mapped to a
12
+ # symbol representing the error.
13
+
14
+ # For more information, see http://tools.ietf.org/html/rfc1905#section-4.2.3
15
+
16
+ # Optional arguments can be passed into _args_, including:
17
+ # * _return_raw_ - Return objects and errors as their raw SNMP types, such as SNMP::Integer instead of native Ruby integers, SNMP::OctetString instead of native Ruby strings, etc. (default: false)
18
+ # * _nonrepeaters_ - Number of OIDs passed to which exactly one result will be returned (default is 0)
19
+ # * _maxrepetitions_ - Number of OID-value pairs to be returned for each OID (default is 10)
20
+
21
+ def getbulk(oids, args = {})
22
+ SnmpGetBulkRequest.new(self, oids, args.merge(:version => @version))
23
+ end
24
+ end
25
+ end
data/lib/snmp4em.rb CHANGED
@@ -1,15 +1,19 @@
1
- $:.unshift File.expand_path(File.dirname(File.expand_path(__FILE__)))
1
+ $:.unshift File.dirname(File.expand_path(__FILE__))
2
+
3
+ gem "eventmachine", ">= 0.12.10"
4
+ gem "snmp", ">= 1.0.2"
2
5
 
3
6
  require 'eventmachine'
4
7
  require 'snmp'
5
- require 'snmp4em/common'
8
+
9
+ require 'snmp4em/extensions'
6
10
  require 'snmp4em/handler'
7
- require 'snmp4em/snmp_connection'
8
- require 'snmp4em/snmp_v1'
9
- require 'snmp4em/snmp_v2'
11
+ require 'snmp4em/common_requests'
12
+ require 'snmp4em/manager'
13
+ require 'snmp4em/snmp_v2c_requests'
10
14
  require 'snmp4em/snmp_request'
11
15
  require 'snmp4em/requests/snmp_get_request'
12
16
  require 'snmp4em/requests/snmp_getbulk_request'
13
17
  require 'snmp4em/requests/snmp_getnext_request'
14
18
  require 'snmp4em/requests/snmp_set_request'
15
- require 'snmp4em/requests/snmp_walk_request'
19
+ require 'snmp4em/requests/snmp_walk_request'
data/snmp4em.gemspec CHANGED
@@ -1,30 +1,23 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
 
3
3
  Gem::Specification.new do |s|
4
- s.name = %q{snmp4em}
5
- s.version = "0.2.1"
4
+ s.name = "snmp4em"
5
+ s.version = "0.3"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Norman Elton"]
9
- s.date = %q{2010-05-17}
10
- s.description = %q{A high-performance SNMP engine built on EventMachine and Ruby-SNMP, supporting SNMPv1 and SNMPv2 operations}
11
- s.email = %q{normelton@gmail.com}
12
- s.extra_rdoc_files = ["README"]
13
- s.files = ["lib/snmp4em.rb", "lib/snmp4em/common.rb", "lib/snmp4em/handler.rb", "lib/snmp4em/requests/snmp_get_request.rb", "lib/snmp4em/requests/snmp_getbulk_request.rb", "lib/snmp4em/requests/snmp_getnext_request.rb", "lib/snmp4em/requests/snmp_set_request.rb", "lib/snmp4em/requests/snmp_walk_request.rb", "lib/snmp4em/snmp_request.rb", "lib/snmp4em/snmp_connection.rb", "lib/snmp4em/snmp_v1.rb", "lib/snmp4em/snmp_v2.rb", "snmp4em.gemspec", "Manifest"]
14
- s.homepage = %q{http://github.com/normelton/snmp4em}
15
- s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Snmp4em", "--main", "README"]
9
+ s.date = "2012-02-23"
10
+ s.description = "A high-performance SNMP engine built on EventMachine and Ruby-SNMP"
11
+ s.email = "normelton@gmail.com"
12
+ s.extra_rdoc_files = ["README.rdoc"]
13
+ s.files = ["Gemfile", "README.rdoc", "Rakefile", "lib/snmp4em.rb", "lib/snmp4em/common_requests.rb", "lib/snmp4em/extensions.rb", "lib/snmp4em/extensions/snmp/integer.rb", "lib/snmp4em/extensions/snmp/ip_address.rb", "lib/snmp4em/extensions/snmp/null.rb", "lib/snmp4em/extensions/snmp/object_id.rb", "lib/snmp4em/extensions/snmp/octet_string.rb", "lib/snmp4em/extensions/snmp/response_error.rb", "lib/snmp4em/handler.rb", "lib/snmp4em/manager.rb", "lib/snmp4em/requests/snmp_get_request.rb", "lib/snmp4em/requests/snmp_getbulk_request.rb", "lib/snmp4em/requests/snmp_getnext_request.rb", "lib/snmp4em/requests/snmp_set_request.rb", "lib/snmp4em/requests/snmp_walk_request.rb", "lib/snmp4em/snmp_request.rb", "lib/snmp4em/snmp_v2c_requests.rb", "snmp4em.gemspec", "spec/models/test_message.rb", "spec/models/test_request.rb", "spec/models/test_response.rb", "spec/spec.opts", "spec/spec_helper.rb", "spec/unit/handler_spec.rb", "spec/unit/manager_spec.rb", "Manifest"]
14
+ s.homepage = "http://github.com/normelton/snmp4em"
15
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Snmp4em", "--main", "README.rdoc"]
16
16
  s.require_paths = ["lib"]
17
- s.rubyforge_project = %q{snmp4em}
18
- s.rubygems_version = %q{1.3.6}
19
- s.summary = %q{A high-performance SNMP engine built on EventMachine and Ruby-SNMP}
20
-
21
- if s.respond_to? :specification_version then
22
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
23
- s.specification_version = 3
24
-
25
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
26
- else
27
- end
28
- else
29
- end
17
+ s.rubyforge_project = "snmp4em"
18
+ s.rubygems_version = "1.8.16"
19
+ s.summary = "A high-performance SNMP engine built on EventMachine and Ruby-SNMP"
20
+ s.add_runtime_dependency 'snmp', '>= 1.0.2'
21
+ s.add_runtime_dependency 'eventmachine', '>= 1.0.0'
22
+
30
23
  end
@@ -0,0 +1,7 @@
1
+ module SNMP4EM
2
+ class TestMessage
3
+
4
+ attr_accessor :pdu
5
+
6
+ end
7
+ end
@@ -0,0 +1,10 @@
1
+ module SNMP4EM
2
+ class TestRequest
3
+
4
+ attr_accessor :snmp_id
5
+
6
+ def handle_response(response)
7
+ end
8
+
9
+ end
10
+ end
@@ -0,0 +1,7 @@
1
+ module SNMP4EM
2
+ class TestResponse
3
+
4
+ attr_accessor :request_id
5
+
6
+ end
7
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1,3 @@
1
+ --colour
2
+ --format nested
3
+ --drb
@@ -0,0 +1,18 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
3
+
4
+ MODELS = File.join(File.dirname(__FILE__), "models")
5
+ $LOAD_PATH.unshift(MODELS)
6
+ Dir[ File.join(MODELS, "*.rb") ].sort.each { |file| require File.basename(file) }
7
+
8
+ require 'rubygems'
9
+ require "spec"
10
+ require "snmp4em"
11
+
12
+ def em
13
+ EM.run {
14
+ yield
15
+ EM.stop
16
+ }
17
+ end
18
+
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe SNMP4EM::Handler do
4
+
5
+ before do
6
+ SNMP4EM::Manager.class_eval do
7
+ @pending_requests = {}
8
+ end
9
+ end
10
+
11
+ describe "#receive_data" do
12
+
13
+ it "should match responses to requests" do
14
+ em do
15
+ response = SNMP4EM::TestResponse.new
16
+ response.request_id = 1
17
+
18
+ message = SNMP4EM::TestMessage.new
19
+ message.pdu = response
20
+ SNMP::Message.should_receive(:decode).and_return(message)
21
+
22
+ request = SNMP4EM::TestRequest.new
23
+ SNMP4EM::Manager.should_receive(:rand).and_return(1)
24
+ SNMP4EM::Manager.track_request(request)
25
+
26
+ request.should_receive(:handle_response).with(response)
27
+ SNMP4EM::Handler.new(nil).receive_data(nil)
28
+ end
29
+
30
+ end
31
+
32
+ end
33
+
34
+ end
@@ -0,0 +1,82 @@
1
+ require 'spec_helper'
2
+
3
+ describe SNMP4EM::Manager do
4
+
5
+ before do
6
+ SNMP4EM::Manager.class_eval do
7
+ @pending_requests = {}
8
+ end
9
+ end
10
+
11
+ describe "#track_request" do
12
+
13
+ it "should assign a random and unique id to each request" do
14
+ em do
15
+ request = SNMP4EM::TestRequest.new
16
+ other_request = SNMP4EM::TestRequest.new
17
+
18
+ SNMP4EM::Manager.should_receive(:rand).and_return(1, 1, 2)
19
+ SNMP4EM::Manager.track_request(request)
20
+ SNMP4EM::Manager.track_request(other_request)
21
+
22
+ request.snmp_id.should == 1
23
+ other_request.snmp_id.should == 2
24
+ end
25
+ end
26
+
27
+ it "should prune requests when their request id changes" do
28
+ em do
29
+ request = SNMP4EM::TestRequest.new
30
+
31
+ SNMP4EM::Manager.should_receive(:rand).and_return(1, 2)
32
+ SNMP4EM::Manager.track_request(request)
33
+ request.snmp_id.should == 1
34
+ SNMP4EM::Manager.pending_requests.size.should == 1
35
+
36
+ SNMP4EM::Manager.track_request(request)
37
+ request.snmp_id.should == 2
38
+ SNMP4EM::Manager.pending_requests.size.should == 1
39
+ end
40
+ end
41
+
42
+ end
43
+
44
+ describe "#initialize" do
45
+
46
+ it "should default to v2c" do
47
+ em do
48
+ SNMP4EM::Manager.new.version.should == :SNMPv2c
49
+ end
50
+ end
51
+
52
+ it "should create the class' UDP socket" do
53
+ em do
54
+ SNMP4EM::Manager.new
55
+ SNMP4EM::Manager.socket.should be_a EventMachine::Connection
56
+ end
57
+ end
58
+
59
+
60
+ context "when using v2c" do
61
+
62
+ it "should acquire the #getbulk method" do
63
+ em do
64
+ SNMP4EM::Manager.new.methods.should include :getbulk
65
+ end
66
+ end
67
+
68
+ end
69
+
70
+ context "when using v1" do
71
+
72
+ it "should not acquire the #getbulk method" do
73
+ em do
74
+ SNMP4EM::Manager.new(:version => :SNMPv1).methods.should_not include :getbulk
75
+ end
76
+ end
77
+
78
+ end
79
+
80
+ end
81
+
82
+ end