net-snmp2 0.3.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.
Files changed (59) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +5 -0
  3. data/.rspec +1 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE +20 -0
  6. data/README.md +28 -0
  7. data/Rakefile +24 -0
  8. data/TODO.md +6 -0
  9. data/bin/mib2rb +129 -0
  10. data/bin/net-snmp2 +64 -0
  11. data/examples/agent.rb +104 -0
  12. data/examples/manager.rb +11 -0
  13. data/examples/trap_handler.rb +46 -0
  14. data/examples/v1_trap_session.rb +24 -0
  15. data/examples/v2_trap_session.rb +21 -0
  16. data/lib/net-snmp2.rb +85 -0
  17. data/lib/net/snmp.rb +27 -0
  18. data/lib/net/snmp/agent/agent.rb +48 -0
  19. data/lib/net/snmp/agent/provider.rb +51 -0
  20. data/lib/net/snmp/agent/provider_dsl.rb +124 -0
  21. data/lib/net/snmp/agent/request_dispatcher.rb +38 -0
  22. data/lib/net/snmp/constants.rb +287 -0
  23. data/lib/net/snmp/debug.rb +54 -0
  24. data/lib/net/snmp/dispatcher.rb +108 -0
  25. data/lib/net/snmp/error.rb +29 -0
  26. data/lib/net/snmp/listener.rb +76 -0
  27. data/lib/net/snmp/message.rb +142 -0
  28. data/lib/net/snmp/mib/mib.rb +67 -0
  29. data/lib/net/snmp/mib/module.rb +39 -0
  30. data/lib/net/snmp/mib/node.rb +122 -0
  31. data/lib/net/snmp/mib/templates.rb +48 -0
  32. data/lib/net/snmp/oid.rb +134 -0
  33. data/lib/net/snmp/pdu.rb +235 -0
  34. data/lib/net/snmp/repl/manager_repl.rb +243 -0
  35. data/lib/net/snmp/session.rb +560 -0
  36. data/lib/net/snmp/trap_handler/trap_handler.rb +42 -0
  37. data/lib/net/snmp/trap_handler/v1_trap_dsl.rb +44 -0
  38. data/lib/net/snmp/trap_handler/v2_trap_dsl.rb +38 -0
  39. data/lib/net/snmp/trap_session.rb +92 -0
  40. data/lib/net/snmp/utility.rb +10 -0
  41. data/lib/net/snmp/varbind.rb +57 -0
  42. data/lib/net/snmp/version.rb +5 -0
  43. data/lib/net/snmp/wrapper.rb +450 -0
  44. data/net-snmp2.gemspec +30 -0
  45. data/spec/README.md +105 -0
  46. data/spec/async_spec.rb +123 -0
  47. data/spec/em_spec.rb +23 -0
  48. data/spec/error_spec.rb +34 -0
  49. data/spec/fiber_spec.rb +41 -0
  50. data/spec/mib_spec.rb +68 -0
  51. data/spec/net-snmp_spec.rb +18 -0
  52. data/spec/oid_spec.rb +21 -0
  53. data/spec/spec_helper.rb +10 -0
  54. data/spec/sync_spec.rb +132 -0
  55. data/spec/thread_spec.rb +19 -0
  56. data/spec/trap_spec.rb +45 -0
  57. data/spec/utility_spec.rb +10 -0
  58. data/spec/wrapper_spec.rb +69 -0
  59. metadata +166 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3b281e88b9dc311d024200f3c6a1490a275aeeb2
4
+ data.tar.gz: 7d0fd5cf86fd4bd509458de1bc0ce77fbcc03dcf
5
+ SHA512:
6
+ metadata.gz: 2de1bdd8d99a79ed0849d4546c8af674fed288657c08dfff5631b41c23237ac87ac454f81d5059f4f579c4819da75659a3c324f304246b023ae9375df44cd3a1
7
+ data.tar.gz: 86dfd53cd984247500282b01108d96addac69ef79229edc8ea26c1eca4d05861e733c97a81b637ef4ccfe57c95904d6bcc64751bfd0b196cf86696a69ba8c371
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/
5
+ *DS_Store
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in net-snmp2.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 mixtli
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,28 @@
1
+ net-snmp2
2
+ =========
3
+
4
+ (Checkout the [wiki](https://github.com/jbreeden/net-snmp2/wiki))
5
+
6
+ An object oriented Ruby wrapper around the C [netsnmp](http://www.net-snmp.org) libraries.
7
+ It provides classes for manager sessions, agents, pdus, varbinds, MIB inspection, and more.
8
+
9
+ The gem also includes some useful executables including:
10
+ - **net-snmp2**
11
+ + An interactive REPL for inspecting the MIB, and acting as an SNMP manager.
12
+ + Supports managing multiple agents at once.
13
+ + Implemented on top of [Pry](http://pryrepl.org/), so it inherits all of Pry's goodness.
14
+ - **mib2rb**
15
+ + A [mib2c](http://www.net-snmp.org/wiki/index.php/Mib2c) like tool that uses ERB files to format and display the system MIB.
16
+ + mib2rb has a default template that prints the MIB details in a human-readable format, providing functionality similar to [snmptranslate](http://www.net-snmp.org/wiki/index.php/TUT:snmptranslate).
17
+
18
+ Features
19
+ --------
20
+
21
+ * Supports SNMP versions 1, 2c, and 3
22
+ * Supports both synchronous and asynchronous calls
23
+ * Supports sending of snmpv1 traps and snmpv2 traps/informs using TrapSession
24
+ * Integrates well with eventmachine, or can be used standalone.
25
+ * In Ruby 1.9, uses fibers behind the scenes to emulate synchronous calls asynchronously
26
+ * MIB support
27
+ * Convenience methods such as session.walk, session.get_columns, and session.table
28
+ * SNMP Agent support
@@ -0,0 +1,24 @@
1
+ require 'bundler'
2
+ require 'pry'
3
+ Bundler::GemHelper.install_tasks
4
+
5
+ task :console do
6
+ require 'pry'
7
+ require 'logger'
8
+ $: << 'lib'
9
+ require 'net-snmp2'
10
+ Net::SNMP::Debug.logger = Logger.new(STDOUT)
11
+ Net::SNMP::Debug.logger.level = Logger::INFO
12
+ include Net::SNMP
13
+ ARGV.clear
14
+
15
+ current_prompt = nil
16
+ Pry.config.prompt = [
17
+ proc { |obj, level|
18
+ current_prompt = "[net-snmp2 (#{obj}) (#{level})] "
19
+ }, proc {
20
+ "[#{'.' * (current_prompt.length - 3)}] "
21
+ }
22
+ ]
23
+ Net::SNMP.pry
24
+ end
data/TODO.md ADDED
@@ -0,0 +1,6 @@
1
+ TODO
2
+ ====
3
+
4
+ - Need to write tests to perform many requests of each type and check for memory leaks.
5
+ + So far v1 & v2 traps for TrapSession seem fine, as does the TrapHandler class.
6
+ - [DONE] Finish implementing Agent's get_bulk feature (this is the last thing outstanding)
@@ -0,0 +1,129 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ $: << "#{File.dirname(__FILE__)}/../lib"
4
+ require 'logger'
5
+ require 'optparse'
6
+ require 'erb'
7
+ require 'net-snmp2'
8
+
9
+ Net::SNMP.init
10
+ Templates = Net::SNMP::MIB::Templates
11
+
12
+ usage = <<USAGE
13
+
14
+ Usage: mib2rb [OPTION]... ROOT_NODE [ERB_FILE]
15
+
16
+ Description
17
+ Prints a mib subtree according to the ERB_FILE.
18
+ Within the ERB file, the `root` variable contains the
19
+ Net::SNMP::Node object corresponding to ROOT_NODE, and
20
+ `nodes` is a collection of the root & all descendants.
21
+
22
+ Options
23
+ -h, Prints this usage information.
24
+
25
+ Aliases: --help
26
+
27
+ -l LEVEL Set the log level.
28
+ Logs are piped to STDERR, so you can redirect
29
+ STDOUT to a file without worrying about logs
30
+ getting into the output.
31
+
32
+ Values: debug, info, warn, error, fatal, none
33
+ Default: none
34
+ Aliases: --log-level
35
+
36
+ -f FORMAT Select the output format.
37
+ If this option is supplied with an ERB file,
38
+ the option is ignored and the file is used instead.
39
+
40
+ Values: [d]efault, [j]son
41
+ Default: default
42
+ Aliases: --format
43
+
44
+ Arguments
45
+ ROOT_NODE [Required] The root node of the mib tree to translate.
46
+ May be specified as numeric oid or mib name.
47
+
48
+ ERB_FILE [Optional] The template file to use for output.
49
+
50
+ Default: Builtin template specifying human readable output.
51
+ (See below)
52
+
53
+ Default ERB_FILE Template
54
+ -------------------------
55
+
56
+ #{Templates::DESCRIBE}
57
+ USAGE
58
+
59
+ root_node = nil
60
+ erb_template = nil
61
+
62
+ OptionParser.new do|opts|
63
+ opts.on( '-h', '--help') do
64
+ puts usage
65
+ exit
66
+ end
67
+
68
+ opts.on('-l', '--log-level LEVEL') do |level|
69
+ break if level =~ /none/i
70
+
71
+ Net::SNMP::Debug.logger = Logger.new(STDERR)
72
+ Net::SNMP::Debug.logger.level = case level
73
+ when /debug/i
74
+ Logger::DEBUG
75
+ when /info/i
76
+ Logger::INFO
77
+ when /warn/i
78
+ Logger::WARN
79
+ when /error/i
80
+ Logger::ERROR
81
+ when /fatal/i
82
+ Logger::FATAL
83
+ else
84
+ puts "Invalid log level: #{level}"
85
+ puts
86
+ puts usage
87
+ exit(1)
88
+ end
89
+ end
90
+
91
+ opts.on('-f', '--format FORMAT') do |format|
92
+ case format
93
+ when /^d(efault)?$/i
94
+ erb_template = Templates::DESCRIBE
95
+ when /^j(son)?$/i
96
+ erb_template = Templates::JSON
97
+ else
98
+ puts "Invalid format: #{format}"
99
+ puts
100
+ puts usage
101
+ exit(1)
102
+ end
103
+ end
104
+
105
+ end.parse!
106
+
107
+ case ARGV.length
108
+ when 1
109
+ root_node = Net::SNMP::MIB.get_node(ARGV[0])
110
+ # If format wasn't set by -f option, default it here
111
+ erb_template ||= Templates::DESCRIBE
112
+ when 2
113
+ root_node = Net::SNMP::MIB.get_node(ARGV[0])
114
+ erb_template = File.read(ARGV[1])
115
+ else
116
+ puts "Invalid arguments..."
117
+ puts
118
+ puts usage
119
+ exit(1)
120
+ end
121
+
122
+ def render(node, erb_template)
123
+ root = node
124
+ nodes = [root] + root.descendants.to_a
125
+ erb = ERB.new(erb_template, nil, '-')
126
+ puts erb.result binding
127
+ end
128
+
129
+ render(root_node, erb_template)
@@ -0,0 +1,64 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ $: << "#{File.dirname(__FILE__)}/../lib"
4
+ require 'logger'
5
+ require 'optparse'
6
+ require 'erb'
7
+ require 'pry'
8
+ require 'net-snmp2'
9
+ require 'net/snmp/repl/manager_repl'
10
+
11
+ usage = '
12
+ Usage: net-snmp2 [-v VERSION] [-c COMMUNITY] [HOST[:PORT]]
13
+ '.sub("\n", "")
14
+
15
+ # Default option values
16
+ options = {
17
+ :version => '2c',
18
+ :community => 'public',
19
+ :peername => 'localhost',
20
+ :port => '161'
21
+ }
22
+
23
+ OptionParser.new do |opt|
24
+ opt.on("-v VERSION") do |version|
25
+ case version
26
+ when /^1$/
27
+ options[:version] = '1'
28
+ when /^2c?$/i
29
+ options[:version] = '2c'
30
+ when /^3$/
31
+ options[:version] = '3'
32
+ else
33
+ puts "Invalid version: #{version}"
34
+ puts
35
+ puts usage
36
+ end
37
+ end
38
+
39
+ opt.on("-c COMMUNITY") do |community|
40
+ options[:community] = community
41
+ end
42
+
43
+ opt.on('-h') do
44
+ puts usage
45
+ exit
46
+ end
47
+
48
+ end.parse!
49
+
50
+ session = nil
51
+ if ARGV.length > 0
52
+ peername = ARGV[0]
53
+ m = peername.match /^([^:]*)(:([0-9]*))?$/
54
+ options[:peername] = m[1]
55
+ options[:port] = m[3] unless m[3].nil? || m[3].empty?
56
+ session = Net::SNMP::Session.open(options)
57
+ end
58
+
59
+ Net::SNMP::Debug.logger = Logger.new(STDOUT)
60
+ Net::SNMP::Debug.logger.level = Logger::INFO
61
+ ARGV.clear
62
+
63
+ Net::SNMP.init
64
+ Net::SNMP::ManagerRepl.start(session)
@@ -0,0 +1,104 @@
1
+ $: << '../lib'
2
+ require 'net-snmp2'
3
+
4
+ # Initialize SNMP and give it a logger
5
+ Net::SNMP.init
6
+ Net::SNMP::Debug.logger = Logger.new(STDOUT)
7
+ Net::SNMP::Debug.logger.level = Logger::INFO
8
+
9
+ agent = Net::SNMP::Agent.new
10
+
11
+ # If the program gets the interrupt signal, tell the agent
12
+ # to stop so the program can exit.
13
+ trap(:INT) {
14
+ agent.stop
15
+ }
16
+
17
+ # Using an in-memory Hash to represent our MIB storage
18
+ mib = {
19
+ '1.3.1.1' => 1,
20
+ '1.3.1.2' => "I'm a string"
21
+ }
22
+
23
+ # The `provide` function creates a provider the Agent can
24
+ # delegate to when a request has a varbind that lives under
25
+ # the given OID. (Or, for all requests if given `:all`,
26
+ # which is the default)
27
+ #
28
+ # Notes: All get/set handlers are called
29
+ # once for each varbind, not once per message. This means
30
+ # the agent may call multiple providers to satisfy a single
31
+ # message. It also means that the code for iterating over
32
+ # a request's varbinds, setting errindex values, etc, is
33
+ # encapsulated in the Agent code, and you do not have to
34
+ # implement it yourself.
35
+ agent.provide '1.3' do
36
+
37
+ get do
38
+ # `oid` is provided by the DSL as the OID object for the current varbind
39
+ #
40
+ # Note: The ProviderDsl (in which all agent handlers are run)
41
+ # includes Net::SNMP::Debug, so you can use the info, warn, debug,
42
+ # error, and fatal logging methods.
43
+ info "Got a get request for #{oid}"
44
+
45
+ if mib.has_key? oid_str
46
+ # `reply` is provided by the DSL to set the response for the current varbind.
47
+ # For a GetBulk request, you can use it's alias `add`, which is more natural
48
+ # in that context, when you may be setting multiple response varbinds for a
49
+ # single requested OID.
50
+ #
51
+ # `oid_str` is alo provided, and is the same as `oid.to_s`
52
+ reply(mib[oid_str])
53
+ else
54
+ # `no_such_object` can be used to indicate that the variable requested
55
+ # does not exist in the MIB on this machine. See also: `no_such_instance`
56
+ no_such_object
57
+ end
58
+ end
59
+
60
+ set do
61
+ info "Get a set request for #{oid} = #{value}"
62
+
63
+ # Randomly fail 20% of the time
64
+ if rand > 0.8
65
+ info "Decided to fail... Sending WRONGTYPE errstat"
66
+ # `error` sets the error status of the reply to the given integer.
67
+ # The Agent code handles setting the error index behind the scenes,
68
+ # so you don't have to set it here.
69
+ error Net::SNMP::Constants::SNMP_ERR_WRONGTYPE
70
+ next
71
+ end
72
+
73
+ if mib.has_key? oid_str
74
+ # Saving the set value in our MIB storage
75
+ mib[oid_str] = value
76
+ # `ok` copies the current varbind to the response,
77
+ # indicating success to the manager. (Aliased as `echo`)
78
+ ok
79
+ else
80
+ no_such_object
81
+ end
82
+ end
83
+
84
+ # Note that the `get_next` handler is also used for varbinds
85
+ # 1..non_repeaters from the request pdu of a get_bulk
86
+ get_next do
87
+ puts "get_next called for #{oid_str}"
88
+ reply(oid: oid_str + '.0', value: 'get_next value')
89
+ end
90
+
91
+ # `get_bulk` handler serves all varbinds in a get_bulk request
92
+ # after the non_repeaters have been served by `get_next`
93
+ get_bulk do
94
+ puts "get_bulk called for #{oid_str}"
95
+ (0..max_repetitions).each do |i|
96
+ add(oid: "#{oid_str}.#{i}", value: "Bulk value ##{i}")
97
+ end
98
+ end
99
+
100
+ end
101
+
102
+ # Start the agent's run loop, listening to port 161
103
+ # Aliases: `run`, `start`
104
+ agent.listen(161)
@@ -0,0 +1,11 @@
1
+ $: << '../lib'
2
+
3
+ require 'net-snmp2'
4
+ t_start = Time.now
5
+ pdu = nil
6
+ #Net::SNMP.init # Uncomment this to go real slow
7
+ Net::SNMP::Session.open(:peername => "localhost", :community => "public" ) do |session|
8
+ pdu = session.get(["1.3.6.1.4.1.290.6.7.3.1.3.6.0", '1.3.6.1.4.1.290.6.7.3.1.3.7.0'])
9
+ end
10
+ t_end = Time.now
11
+ puts "Got #{pdu.varbinds[0].value} & #{pdu.varbinds[1].value} in #{(t_end - t_start) * 1000} ms"
@@ -0,0 +1,46 @@
1
+ $: << '../lib'
2
+ require 'net-snmp2'
3
+
4
+ # Initialize SNMP and give it a logger
5
+ Net::SNMP.init
6
+ Net::SNMP::Debug.logger = Logger.new(STDOUT)
7
+ Net::SNMP::Debug.logger.level = Logger::INFO
8
+
9
+ handler = Net::SNMP::TrapHandler.new do
10
+ v1 do
11
+ info <<-EOF
12
+
13
+
14
+ Got V1 Trap
15
+ -----------
16
+
17
+ Enterprise OID: #{enterprise}
18
+ Trap Type: #{general_trap_type}
19
+ Specific Type: #{specific_trap_type}
20
+ Agent Address: #{agent_address}
21
+ Uptime: #{uptime}
22
+ Varbinds: #{varbinds.map {|vb| "#{vb.oid.label}(#{vb.oid}) = #{vb.value}"}.join(', ')}
23
+ EOF
24
+ end
25
+
26
+ v2 do
27
+ info <<-EOF
28
+
29
+
30
+ Got V2 Trap
31
+ -----------
32
+
33
+ Trap OID: #{trap_oid}
34
+ Uptime: #{uptime}
35
+ Varbinds: #{varbinds.map {|vb| "#{vb.oid.label}(#{vb.oid}) = #{vb.value}"}.join(', ')}
36
+ EOF
37
+ end
38
+ end
39
+
40
+ # If the program gets the interrupt signal, tell the trap handler
41
+ # to stop so the program can exit.
42
+ trap(:INT) {
43
+ handler.stop
44
+ }
45
+
46
+ handler.listen(162)