snmp 0.5.1 → 0.6.0
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 +32 -18
- data/Rakefile +3 -2
- data/lib/snmp/manager.rb +161 -34
- data/lib/snmp/pdu.rb +20 -4
- data/lib/snmp/varbind.rb +56 -9
- data/test/if_table1.yaml +81 -0
- data/test/if_table6.yaml +441 -0
- data/test/test_manager.rb +49 -4
- data/test/test_retry.rb +81 -0
- data/test/test_varbind.rb +41 -0
- data/test/test_walk.rb +133 -46
- metadata +184 -181
data/test/test_manager.rb
CHANGED
@@ -2,13 +2,13 @@ require 'test/unit'
|
|
2
2
|
require 'snmp/manager'
|
3
3
|
|
4
4
|
class EchoTransport
|
5
|
-
def initialize
|
5
|
+
def initialize
|
6
6
|
end
|
7
7
|
|
8
8
|
def close
|
9
9
|
end
|
10
10
|
|
11
|
-
def send(data)
|
11
|
+
def send(data, host, port)
|
12
12
|
@data = data
|
13
13
|
end
|
14
14
|
|
@@ -111,9 +111,8 @@ class TestManager < Test::Unit::TestCase
|
|
111
111
|
end
|
112
112
|
|
113
113
|
def test_request_id
|
114
|
-
srand(100)
|
115
114
|
id = RequestId.new
|
116
|
-
|
115
|
+
fail if id.next < 0 or id.next >= 2**31
|
117
116
|
|
118
117
|
id.force_next(1)
|
119
118
|
assert_equal(1, id.next)
|
@@ -124,6 +123,52 @@ class TestManager < Test::Unit::TestCase
|
|
124
123
|
assert_raise(RuntimeError) { id.force_next(RequestId::MAX_REQUEST_ID) }
|
125
124
|
assert_raise(RuntimeError) { id.force_next(0) }
|
126
125
|
end
|
126
|
+
|
127
|
+
def test_trap_v1
|
128
|
+
manager = Manager.new(:Transport => EchoTransport, :Version => :SNMPv1)
|
129
|
+
sent_data = manager.trap_v1(
|
130
|
+
"enterprises.9",
|
131
|
+
"10.1.2.3",
|
132
|
+
:enterpriseSpecific,
|
133
|
+
42,
|
134
|
+
12345,
|
135
|
+
[VarBind.new("1.3.6.1.2.3.4", Integer.new(1))]
|
136
|
+
)
|
137
|
+
pdu = Message.decode(sent_data).pdu
|
138
|
+
assert_equal(ObjectId.new("1.3.6.1.4.1.9"), pdu.enterprise)
|
139
|
+
assert_equal(IpAddress.new("10.1.2.3"), pdu.agent_addr)
|
140
|
+
assert_equal(:enterpriseSpecific, pdu.generic_trap)
|
141
|
+
assert_equal(42, pdu.specific_trap)
|
142
|
+
assert_equal(TimeTicks.new(12345), pdu.timestamp)
|
143
|
+
assert_equal(1, pdu.vb_list.length)
|
144
|
+
end
|
145
|
+
|
146
|
+
def test_trap_v2
|
147
|
+
sent_data = @manager.trap_v2(1234, "1.3.6.1.2.3.4")
|
148
|
+
pdu = Message.decode(sent_data).pdu
|
149
|
+
assert_equal(1234, pdu.sys_up_time)
|
150
|
+
assert_equal("1.3.6.1.2.3.4", pdu.trap_oid.to_s)
|
151
|
+
assert_equal(2, pdu.vb_list.length)
|
152
|
+
|
153
|
+
sent_data = @manager.trap_v2(1234, "1.3.6.1.2.3.4", ["1.2.3", "1.4.5.6"])
|
154
|
+
pdu = Message.decode(sent_data).pdu
|
155
|
+
assert_equal(1234, pdu.sys_up_time)
|
156
|
+
assert_equal("1.3.6.1.2.3.4", pdu.trap_oid.to_s)
|
157
|
+
assert_equal(4, pdu.vb_list.length)
|
158
|
+
assert_equal("1.4.5.6", pdu.vb_list.last.name.to_s)
|
159
|
+
end
|
160
|
+
|
161
|
+
def test_inform
|
162
|
+
response = @manager.inform(1234, "1.3.6.1.2.3.4")
|
163
|
+
assert_equal(1234, response.vb_list[0].value)
|
164
|
+
assert_equal("1.3.6.1.2.3.4", response.vb_list[1].value.to_s)
|
165
|
+
assert(2, response.vb_list.length)
|
166
|
+
|
167
|
+
response = @manager.inform(1234, "1.3.6.1.2.3.4", ["1.2.3", "1.4.5.6"])
|
168
|
+
assert_equal(1234, response.vb_list[0].value)
|
169
|
+
assert_equal("1.3.6.1.2.3.4", response.vb_list[1].value.to_s)
|
170
|
+
assert(4, response.vb_list.length)
|
171
|
+
end
|
127
172
|
end
|
128
173
|
|
129
174
|
class TrapTestTransport
|
data/test/test_retry.rb
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'snmp/manager'
|
2
|
+
|
3
|
+
class TimeoutManager < SNMP::Manager
|
4
|
+
attr_accessor :response_count
|
5
|
+
|
6
|
+
def initialize(config)
|
7
|
+
super(config)
|
8
|
+
@response_count = 0
|
9
|
+
@raise_on_send = false
|
10
|
+
@raise_on_get = false
|
11
|
+
end
|
12
|
+
|
13
|
+
def raise_send_error
|
14
|
+
@raise_on_send = true
|
15
|
+
end
|
16
|
+
|
17
|
+
def raise_get_error
|
18
|
+
@raise_on_get = true
|
19
|
+
end
|
20
|
+
|
21
|
+
def send_request(request, community, host, port)
|
22
|
+
raise RuntimeError if @raise_on_send
|
23
|
+
end
|
24
|
+
|
25
|
+
def get_response(request)
|
26
|
+
@response_count += 1
|
27
|
+
raise RuntimeError if @raise_on_get
|
28
|
+
raise Timeout::Error, "testing retry count"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class MismatchIdTransport
|
33
|
+
def initialize
|
34
|
+
@data = []
|
35
|
+
end
|
36
|
+
|
37
|
+
def close
|
38
|
+
end
|
39
|
+
|
40
|
+
def send(data, host, port)
|
41
|
+
bad_id_data = data.dup
|
42
|
+
bad_msg = Message.decode(data)
|
43
|
+
bad_msg.pdu.request_id -= 3 # corrupt request_id
|
44
|
+
@data << bad_msg.encode # insert corrupted PDU before real data
|
45
|
+
@data << data
|
46
|
+
end
|
47
|
+
|
48
|
+
def recv(max_bytes)
|
49
|
+
raise "receive queue is empty" unless @data.first
|
50
|
+
SNMP::Message.decode(@data.shift).response.encode[0,max_bytes]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
class TestRetry < Test::Unit::TestCase
|
56
|
+
def test_retry_count
|
57
|
+
assert_response_count(0, 1, SNMP::RequestTimeout)
|
58
|
+
assert_response_count(1, 2, SNMP::RequestTimeout)
|
59
|
+
assert_response_count(5, 6, SNMP::RequestTimeout)
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_retry_on_error
|
63
|
+
assert_response_count(5, 0, RuntimeError) { |m| m.raise_send_error }
|
64
|
+
old_verbose = $VERBOSE
|
65
|
+
$VERBOSE = nil
|
66
|
+
assert_response_count(5, 6, SNMP::RequestTimeout) { |m| m.raise_get_error }
|
67
|
+
$VERBOSE = old_verbose
|
68
|
+
end
|
69
|
+
|
70
|
+
def assert_response_count(retry_count, response_count, exception)
|
71
|
+
m = TimeoutManager.new( :Retries => retry_count )
|
72
|
+
yield m if block_given?
|
73
|
+
assert_raise(exception) { m.get("1.2.3.4") }
|
74
|
+
assert_equal(response_count, m.response_count)
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_drop_mismatched_id
|
78
|
+
m = SNMP::Manager.new(:Transport => MismatchIdTransport)
|
79
|
+
m.get("1.2.3.4")
|
80
|
+
end
|
81
|
+
end
|
data/test/test_varbind.rb
CHANGED
@@ -22,6 +22,12 @@ class TestVarBind < Test::Unit::TestCase
|
|
22
22
|
assert_equal("0\f\006\010+\006\001\002\001\001\002\000\005\000", remainder)
|
23
23
|
end
|
24
24
|
|
25
|
+
def test_varbind_name_alias_oid
|
26
|
+
vb = VarBind.new("1.2.3.4", OctetString.new("blah"))
|
27
|
+
assert(ObjectId.new("1.2.3.4"), vb.name)
|
28
|
+
assert(ObjectId.new("1.2.3.4"), vb.oid)
|
29
|
+
end
|
30
|
+
|
25
31
|
def test_varbind_list_create
|
26
32
|
list = VarBindList.new
|
27
33
|
assert_equal(0, list.length)
|
@@ -99,6 +105,11 @@ class TestVarBind < Test::Unit::TestCase
|
|
99
105
|
assert_equal(s1, s3)
|
100
106
|
end
|
101
107
|
|
108
|
+
def test_octet_string_to_oid
|
109
|
+
s = OctetString.new("test")
|
110
|
+
assert_equal(ObjectId.new([116, 101, 115, 116]), s.to_oid)
|
111
|
+
end
|
112
|
+
|
102
113
|
def test_object_id
|
103
114
|
id = ObjectId.new([1,3,6,1])
|
104
115
|
assert_equal("1.3.6.1", id.to_s)
|
@@ -154,6 +165,17 @@ class TestVarBind < Test::Unit::TestCase
|
|
154
165
|
assert(id1.subtree_of?("1.3.3.4"))
|
155
166
|
assert(!id4.subtree_of?("1.3.3.4"))
|
156
167
|
end
|
168
|
+
|
169
|
+
def test_object_id_index
|
170
|
+
id1 = ObjectId.new("1.3.3.4")
|
171
|
+
id2 = ObjectId.new("1.3.3.4.1")
|
172
|
+
id3 = ObjectId.new("1.3.3.4.1.2")
|
173
|
+
assert(ObjectId.new("1"), id2.index(id1))
|
174
|
+
assert(ObjectId.new("1.2"), id3.index(id1))
|
175
|
+
assert(ObjectId.new("1.2"), id3.index("1.3.3.4"))
|
176
|
+
assert_raise(ArgumentError) { id1.index(id3) }
|
177
|
+
assert_raise(ArgumentError) { id1.index(id1) }
|
178
|
+
end
|
157
179
|
|
158
180
|
def test_object_name_from_string
|
159
181
|
id = ObjectName.new("1.3.4.5.6")
|
@@ -196,6 +218,14 @@ class TestVarBind < Test::Unit::TestCase
|
|
196
218
|
assert(i2 > 54000)
|
197
219
|
end
|
198
220
|
|
221
|
+
def test_integer_to_oid
|
222
|
+
assert(ObjectId.new("123"), Integer.new(123).to_oid)
|
223
|
+
assert(ObjectId.new("0"), Integer.new(0).to_oid)
|
224
|
+
|
225
|
+
i = Integer.new(-1)
|
226
|
+
assert_raise(RangeError) { i.to_oid }
|
227
|
+
end
|
228
|
+
|
199
229
|
def test_ip_address_from_string
|
200
230
|
ip = IpAddress.new("10.0.255.1")
|
201
231
|
assert_equal("10.0.255.1", ip.to_s)
|
@@ -203,6 +233,12 @@ class TestVarBind < Test::Unit::TestCase
|
|
203
233
|
assert_raise(InvalidIpAddress) { IpAddress.new("1.2.3.-1") }
|
204
234
|
assert_raise(InvalidIpAddress) { IpAddress.new("1.2.3") }
|
205
235
|
end
|
236
|
+
|
237
|
+
def test_ip_address_from_self
|
238
|
+
ip1 = IpAddress.new("1.2.3.4")
|
239
|
+
ip2 = IpAddress.new(ip1)
|
240
|
+
assert_equal(ip1, ip2)
|
241
|
+
end
|
206
242
|
|
207
243
|
def test_ip_address_create
|
208
244
|
ip = IpAddress.new("\001\002\003\004")
|
@@ -230,6 +266,11 @@ class TestVarBind < Test::Unit::TestCase
|
|
230
266
|
assert(!ip1.eql?(12))
|
231
267
|
end
|
232
268
|
|
269
|
+
def test_ip_address_to_oid
|
270
|
+
ip = IpAddress.new("1.2.3.4")
|
271
|
+
assert_equal(ObjectId.new("1.2.3.4"), ip.to_oid)
|
272
|
+
end
|
273
|
+
|
233
274
|
def test_counter32_create
|
234
275
|
i = Counter32.new(12345)
|
235
276
|
assert_equal("12345", i.to_s)
|
data/test/test_walk.rb
CHANGED
@@ -1,104 +1,191 @@
|
|
1
1
|
require 'snmp'
|
2
2
|
require 'test/unit'
|
3
|
+
require 'yaml'
|
3
4
|
|
4
5
|
include SNMP
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
##
|
8
|
+
# Accept get and get-next requests, returning the data from the
|
9
|
+
# provided YAML data file. The file contains a list of OID, value, and
|
10
|
+
# value type.
|
11
|
+
#
|
12
|
+
class YamlDataTransport
|
13
|
+
def self.load_data(yaml_file)
|
14
|
+
values = YAML.load(File.new(yaml_file))
|
15
|
+
@@get_map = {}
|
16
|
+
@@get_next_map = {}
|
17
|
+
values.each_index do |i|
|
18
|
+
name, value, klass = values[i]
|
19
|
+
if i < values.length - 1
|
20
|
+
next_name, next_value, next_klass = values[i + 1]
|
21
|
+
else
|
22
|
+
next_value = SNMP::EndOfMibView
|
23
|
+
next_klass = SNMP::EndOfMibView
|
24
|
+
end
|
25
|
+
@@get_map[name] = [name, value, klass]
|
26
|
+
@@get_next_map[name] = [next_name, next_value, next_klass]
|
27
|
+
end
|
11
28
|
end
|
12
|
-
|
13
|
-
def
|
29
|
+
|
30
|
+
def initialize
|
31
|
+
@responses = []
|
14
32
|
end
|
15
33
|
|
16
|
-
def
|
17
|
-
@data = data
|
34
|
+
def close
|
18
35
|
end
|
19
36
|
|
20
|
-
def
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
37
|
+
def send(data, host, port)
|
38
|
+
msg = Message.decode(data)
|
39
|
+
req_class = msg.pdu.class
|
40
|
+
if req_class == SNMP::GetRequest
|
41
|
+
oid_map = @@get_map
|
42
|
+
elsif req_class == SNMP::GetNextRequest
|
43
|
+
oid_map = @@get_next_map
|
27
44
|
else
|
28
|
-
|
29
|
-
|
45
|
+
raise "request not supported: " + req_class
|
46
|
+
end
|
47
|
+
|
48
|
+
resp = msg.response
|
49
|
+
resp.pdu.vb_list.each do |vb|
|
50
|
+
name, value, klass = oid_map[vb.name.to_s]
|
51
|
+
vb.name = ObjectId.new(name)
|
52
|
+
if klass == "SNMP::NoSuchObject" or klass == "SNMP::NoSuchInstance"
|
53
|
+
vb.value = eval(klass)
|
54
|
+
elsif value
|
55
|
+
vb.value = eval("#{klass}.new(value)")
|
56
|
+
else
|
57
|
+
vb.value = SNMP::NoSuchInstance
|
30
58
|
end
|
31
|
-
end
|
32
|
-
|
59
|
+
end
|
60
|
+
@responses << resp.encode
|
61
|
+
end
|
62
|
+
|
63
|
+
def recv(max_bytes)
|
64
|
+
@responses.shift
|
33
65
|
end
|
34
66
|
end
|
35
67
|
|
68
|
+
class TestTransport < Test::Unit::TestCase
|
69
|
+
|
70
|
+
def test_get
|
71
|
+
YamlDataTransport.load_data(File.dirname(__FILE__) + "/if_table6.yaml")
|
72
|
+
SNMP::Manager.open(:Transport => YamlDataTransport) do |snmp|
|
73
|
+
value = snmp.get_value("ifDescr.1")
|
74
|
+
assert_equal("lo0", value)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_get_next
|
79
|
+
YamlDataTransport.load_data(File.dirname(__FILE__) + "/if_table6.yaml")
|
80
|
+
SNMP::Manager.open(:Transport => YamlDataTransport) do |snmp|
|
81
|
+
vb = snmp.get_next("ifDescr.1")
|
82
|
+
assert_equal("gif0", vb.vb_list.first.value)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
36
87
|
|
37
88
|
class TestWalk < Test::Unit::TestCase
|
38
89
|
|
90
|
+
##
|
91
|
+
# A single string or single ObjectId can be passed to walk()
|
92
|
+
#
|
39
93
|
def test_single_object
|
40
|
-
$transport_pdu_count = 3
|
41
94
|
list = []
|
42
|
-
|
95
|
+
ifTable6_manager.walk("ifDescr") do |vb|
|
43
96
|
assert(vb.kind_of?(VarBind), "Expected a VarBind")
|
44
97
|
list << vb
|
45
98
|
end
|
46
|
-
assert_equal(
|
99
|
+
assert_equal(6, list.length)
|
47
100
|
|
48
|
-
$transport_pdu_count = 3
|
49
101
|
list = []
|
50
|
-
|
102
|
+
ifTable6_manager.walk(ObjectId.new("1.3.6.1.2.1.2.2.1.2")) do |vb|
|
51
103
|
assert(vb.kind_of?(VarBind), "Expected a VarBind")
|
52
104
|
list << vb
|
53
105
|
end
|
54
|
-
assert_equal(
|
106
|
+
assert_equal(6, list.length)
|
55
107
|
end
|
56
|
-
|
108
|
+
|
109
|
+
|
110
|
+
##
|
111
|
+
# If a list of one element is passed to walk() then a list of
|
112
|
+
# one element is passed as the block parameter.
|
113
|
+
#
|
57
114
|
def test_single_object_list
|
58
|
-
$transport_pdu_count = 1
|
59
115
|
executed_block = false
|
60
|
-
|
116
|
+
ifTable6_manager.walk(["1.3.6.1.2.1.2.2.1.2"]) do |vb_list|
|
61
117
|
executed_block = true
|
62
118
|
assert_equal(1, vb_list.length)
|
63
|
-
assert_equal("1.3.6.1.1", vb_list.first.name.to_s)
|
119
|
+
assert_equal("1.3.6.1.2.1.2.2.1.2.1", vb_list.first.name.to_s)
|
120
|
+
break
|
64
121
|
end
|
65
122
|
assert(executed_block, "Did not execute block")
|
66
123
|
end
|
67
|
-
|
124
|
+
|
125
|
+
##
|
126
|
+
# If a list of multiple items are passed to walk() then
|
127
|
+
# multiple items are passed to the block.
|
128
|
+
#
|
68
129
|
def test_object_list
|
69
|
-
$transport_pdu_count = 3
|
70
130
|
list1 = []
|
71
131
|
list2 = []
|
72
|
-
|
132
|
+
ifTable6_manager.walk(["ifIndex", "ifDescr"]) do |vb1, vb2|
|
73
133
|
list1 << vb1
|
74
134
|
list2 << vb2
|
75
135
|
end
|
76
|
-
assert_equal(
|
77
|
-
assert_equal(
|
136
|
+
assert_equal(6, list1.length)
|
137
|
+
assert_equal(6, list2.length)
|
138
|
+
|
139
|
+
list1 = []
|
140
|
+
list2 = []
|
141
|
+
ifTable6_manager.walk(["ifIndex", "ifDescr"], 1) do |vb1, vb2|
|
142
|
+
list1 << vb1
|
143
|
+
list2 << vb2
|
144
|
+
end
|
145
|
+
assert_equal(6, list1.length)
|
146
|
+
assert_equal(6, list2.length)
|
78
147
|
end
|
79
|
-
|
148
|
+
|
80
149
|
def test_empty
|
81
|
-
|
82
|
-
manager.walk("1.2.3.4") do |vb|
|
150
|
+
ifTable6_manager.walk("1.3.6.1.2.1.2.2.1.2.1") do |vb|
|
83
151
|
fail("Expected block to not be executed")
|
84
152
|
end
|
85
153
|
end
|
86
|
-
|
154
|
+
|
87
155
|
def test_one
|
88
|
-
$transport_pdu_count = 1
|
89
156
|
list = []
|
90
|
-
|
91
|
-
assert_equal("1.3.6.1.1", vb[0].name.to_s)
|
92
|
-
assert_equal("1.3.6.2.1", vb[1].name.to_s)
|
157
|
+
ifTable1_manager.walk(["1.3.6.1.2.1.2.2.1.1", "1.3.6.1.2.1.2.2.1.2"]) do |vb|
|
158
|
+
assert_equal("1.3.6.1.2.1.2.2.1.1.1", vb[0].name.to_s)
|
159
|
+
assert_equal("1.3.6.1.2.1.2.2.1.2.1", vb[1].name.to_s)
|
160
|
+
list << vb
|
161
|
+
end
|
162
|
+
assert_equal(1, list.length)
|
163
|
+
end
|
164
|
+
|
165
|
+
def test_hole_in_one
|
166
|
+
list = []
|
167
|
+
ifTable1_manager.walk(["ifIndex", "ifDescr", "ifType"]) do |vb|
|
168
|
+
assert_equal("1.3.6.1.2.1.2.2.1.1.1", vb[0].name.to_s)
|
169
|
+
assert_equal(1, vb[0].value)
|
170
|
+
assert_equal("1.3.6.1.2.1.2.2.1.2.1", vb[1].name.to_s)
|
171
|
+
assert_equal("lo0", vb[1].value)
|
172
|
+
assert_equal("1.3.6.1.2.1.2.2.1.3.1", vb[2].name.to_s)
|
173
|
+
assert_equal(NoSuchInstance, vb[2].value)
|
93
174
|
list << vb
|
175
|
+
break
|
94
176
|
end
|
95
177
|
assert_equal(1, list.length)
|
96
178
|
end
|
97
179
|
|
98
180
|
private
|
99
181
|
|
100
|
-
def
|
101
|
-
|
182
|
+
def ifTable1_manager
|
183
|
+
YamlDataTransport.load_data(File.dirname(__FILE__) + "/if_table1.yaml")
|
184
|
+
Manager.new(:Transport => YamlDataTransport)
|
185
|
+
end
|
186
|
+
|
187
|
+
def ifTable6_manager
|
188
|
+
YamlDataTransport.load_data(File.dirname(__FILE__) + "/if_table6.yaml")
|
189
|
+
Manager.new(:Transport => YamlDataTransport)
|
102
190
|
end
|
103
|
-
|
104
191
|
end
|