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.
- data/Gemfile +7 -0
- data/Manifest +19 -6
- data/{README → README.rdoc} +40 -37
- data/Rakefile +17 -0
- data/lib/snmp4em/{snmp_v1.rb → common_requests.rb} +6 -32
- data/lib/snmp4em/extensions/snmp/integer.rb +7 -0
- data/lib/snmp4em/extensions/snmp/ip_address.rb +7 -0
- data/lib/snmp4em/extensions/snmp/null.rb +11 -0
- data/lib/snmp4em/extensions/snmp/object_id.rb +7 -0
- data/lib/snmp4em/extensions/snmp/octet_string.rb +7 -0
- data/lib/snmp4em/extensions/snmp/response_error.rb +17 -0
- data/lib/snmp4em/extensions.rb +6 -0
- data/lib/snmp4em/handler.rb +14 -5
- data/lib/snmp4em/manager.rb +69 -0
- data/lib/snmp4em/requests/snmp_get_request.rb +13 -36
- data/lib/snmp4em/requests/snmp_getbulk_request.rb +7 -21
- data/lib/snmp4em/requests/snmp_getnext_request.rb +11 -39
- data/lib/snmp4em/requests/snmp_set_request.rb +10 -6
- data/lib/snmp4em/requests/snmp_walk_request.rb +51 -67
- data/lib/snmp4em/snmp_request.rb +24 -13
- data/lib/snmp4em/snmp_v2c_requests.rb +25 -0
- data/lib/snmp4em.rb +10 -6
- data/snmp4em.gemspec +15 -22
- data/spec/models/test_message.rb +7 -0
- data/spec/models/test_request.rb +10 -0
- data/spec/models/test_response.rb +7 -0
- data/spec/spec.opts +3 -0
- data/spec/spec_helper.rb +18 -0
- data/spec/unit/handler_spec.rb +34 -0
- data/spec/unit/manager_spec.rb +82 -0
- metadata +77 -51
- data/lib/snmp4em/common.rb +0 -39
- data/lib/snmp4em/snmp_connection.rb +0 -43
- data/lib/snmp4em/snmp_v2.rb +0 -104
@@ -1,60 +1,32 @@
|
|
1
1
|
module SNMP4EM
|
2
2
|
|
3
|
-
#
|
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
|
-
|
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
|
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
|
-
@
|
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
|
-
|
51
|
-
|
52
|
-
|
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
|
-
|
41
|
+
Manager.track_request(self)
|
70
42
|
|
71
|
-
|
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(
|
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
|
-
|
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 =
|
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
|
-
|
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(
|
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
|
-
#
|
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
|
-
|
6
|
+
attr_accessor :snmp_id
|
8
7
|
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
|
16
|
-
|
17
|
-
|
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
|
-
|
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
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
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
|
-
|
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
|
-
|
59
|
-
|
60
|
-
|
61
|
-
@
|
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
|
-
|
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
|
-
|
55
|
+
Manager.track_request(self)
|
83
56
|
|
84
|
-
#
|
85
|
-
|
86
|
-
|
87
|
-
@
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
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(
|
81
|
+
vb_list = SNMP::VarBindList.new(query_oids)
|
98
82
|
request = SNMP::GetNextRequest.new(@snmp_id, vb_list)
|
99
|
-
message = SNMP::Message.new(
|
83
|
+
message = SNMP::Message.new(@sender.version, @sender.community_ro, request)
|
100
84
|
|
101
85
|
super(message)
|
102
86
|
end
|
data/lib/snmp4em/snmp_request.rb
CHANGED
@@ -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
|
-
|
11
|
-
|
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
|
-
|
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
|
42
|
+
if @timeout_retries > 0
|
32
43
|
send
|
33
44
|
@timeout_retries -= 1
|
34
45
|
else
|
35
|
-
fail
|
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.
|
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
|
-
|
8
|
+
|
9
|
+
require 'snmp4em/extensions'
|
6
10
|
require 'snmp4em/handler'
|
7
|
-
require 'snmp4em/
|
8
|
-
require 'snmp4em/
|
9
|
-
require 'snmp4em/
|
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 =
|
5
|
-
s.version = "0.
|
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 =
|
10
|
-
s.description =
|
11
|
-
s.email =
|
12
|
-
s.extra_rdoc_files = ["README"]
|
13
|
-
s.files = ["lib/snmp4em.rb", "lib/snmp4em/
|
14
|
-
s.homepage =
|
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 =
|
18
|
-
s.rubygems_version =
|
19
|
-
s.summary =
|
20
|
-
|
21
|
-
|
22
|
-
|
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
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
@@ -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
|