gri 10.0.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.
- checksums.yaml +7 -0
- data/.gitignore +7 -0
- data/MIT-LICENSE.txt +20 -0
- data/README.md +132 -0
- data/Rakefile +5 -0
- data/bin/grapher +17 -0
- data/bin/gri +5 -0
- data/bin/gricast +17 -0
- data/bin/grispark +5 -0
- data/bin/griwalk +9 -0
- data/bin/trad +19 -0
- data/bin/trad-http +17 -0
- data/gri.gemspec +21 -0
- data/lib/fluent/plugin/out_gri.rb +56 -0
- data/lib/gri/api.rb +28 -0
- data/lib/gri/app_collector.rb +154 -0
- data/lib/gri/app_walker.rb +23 -0
- data/lib/gri/blank.rb +49 -0
- data/lib/gri/builtindefs.rb +211 -0
- data/lib/gri/cast.rb +84 -0
- data/lib/gri/cgraph.rb +37 -0
- data/lib/gri/clist.rb +163 -0
- data/lib/gri/collector.rb +284 -0
- data/lib/gri/config.rb +134 -0
- data/lib/gri/ds_list.rb +166 -0
- data/lib/gri/format_helper.rb +112 -0
- data/lib/gri/gparams.rb +43 -0
- data/lib/gri/graph.rb +239 -0
- data/lib/gri/grapher.rb +70 -0
- data/lib/gri/ldb.rb +160 -0
- data/lib/gri/list.rb +242 -0
- data/lib/gri/log.rb +140 -0
- data/lib/gri/loop.rb +109 -0
- data/lib/gri/ltsv.rb +58 -0
- data/lib/gri/main.rb +107 -0
- data/lib/gri/mlog.rb +22 -0
- data/lib/gri/mmsgpack.rb +57 -0
- data/lib/gri/msnmp.rb +601 -0
- data/lib/gri/page.rb +235 -0
- data/lib/gri/pcollector.rb +209 -0
- data/lib/gri/plugin.rb +75 -0
- data/lib/gri/plugin/bootstrap.rb +65 -0
- data/lib/gri/plugin/cisco.rb +98 -0
- data/lib/gri/plugin/exec_collector.rb +89 -0
- data/lib/gri/plugin/juniper.rb +5 -0
- data/lib/gri/plugin/netsnmp.rb +8 -0
- data/lib/gri/plugin/ucdavis.rb +176 -0
- data/lib/gri/plugin/writer_fluentd.rb +26 -0
- data/lib/gri/polling_unit.rb +88 -0
- data/lib/gri/q.rb +5 -0
- data/lib/gri/request.rb +29 -0
- data/lib/gri/rrd.rb +438 -0
- data/lib/gri/scheduler.rb +68 -0
- data/lib/gri/sgraph.rb +147 -0
- data/lib/gri/spark.rb +94 -0
- data/lib/gri/tra_collector.rb +80 -0
- data/lib/gri/trad.rb +170 -0
- data/lib/gri/updater.rb +201 -0
- data/lib/gri/util_daemon.rb +19 -0
- data/lib/gri/util_marshal.rb +13 -0
- data/lib/gri/utils.rb +63 -0
- data/lib/gri/vendor.rb +76 -0
- data/lib/gri/version.rb +3 -0
- data/lib/gri/wmain.rb +67 -0
- data/lib/gri/writer.rb +184 -0
- data/mcollector +47 -0
- data/test/mock.rb +60 -0
- data/test/root/gra/.sysdb/sysdb.txt +3 -0
- data/test/root/gra/testhost/.records.txt +2 -0
- data/test/root/if.def +2 -0
- data/test/root/test.conf +4 -0
- data/test/root/testtab +9 -0
- data/test/root/testtab2 +2 -0
- data/test/root/tra/testhost/_/20130614 +20 -0
- data/test/test_app.rb +58 -0
- data/test/test_builtindefs.rb +24 -0
- data/test/test_collector.rb +58 -0
- data/test/test_config.rb +62 -0
- data/test/test_ds_list.rb +48 -0
- data/test/test_exec_collector.rb +33 -0
- data/test/test_format_helper.rb +68 -0
- data/test/test_graph.rb +69 -0
- data/test/test_ldb.rb +29 -0
- data/test/test_list.rb +65 -0
- data/test/test_log.rb +16 -0
- data/test/test_loop.rb +35 -0
- data/test/test_ltsv.rb +38 -0
- data/test/test_main.rb +19 -0
- data/test/test_mmsgpack.rb +27 -0
- data/test/test_msnmp.rb +147 -0
- data/test/test_page.rb +51 -0
- data/test/test_pcollector.rb +71 -0
- data/test/test_plugin.rb +62 -0
- data/test/test_plugin_cisco.rb +23 -0
- data/test/test_polling_unit.rb +58 -0
- data/test/test_request.rb +26 -0
- data/test/test_rrd.rb +53 -0
- data/test/test_rrd_updater.rb +139 -0
- data/test/test_scheduler.rb +31 -0
- data/test/test_tra_collector.rb +40 -0
- data/test/test_trad.rb +33 -0
- data/test/test_util_marshal.rb +17 -0
- data/test/test_utils.rb +15 -0
- data/test/test_vendor.rb +40 -0
- data/test/test_writer.rb +33 -0
- data/test/unittest_helper.rb +27 -0
- metadata +208 -0
data/lib/gri/loop.rb
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
module GRI
|
2
|
+
class Loop
|
3
|
+
attr_reader :collectors
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@collectors = {}
|
7
|
+
|
8
|
+
@rs = []
|
9
|
+
@ws = []
|
10
|
+
@handlers = {}
|
11
|
+
@times = {}
|
12
|
+
@tos = {}
|
13
|
+
@pt = Time.now
|
14
|
+
@procs = []
|
15
|
+
end
|
16
|
+
|
17
|
+
def attach collector
|
18
|
+
@collectors[collector] = true
|
19
|
+
collector.attach self
|
20
|
+
end
|
21
|
+
|
22
|
+
def detach collector
|
23
|
+
collector.on_detach
|
24
|
+
@collectors.delete collector
|
25
|
+
del_ios = @handlers.select {|k, v| v == collector}
|
26
|
+
del_ios.each {|io, handler|
|
27
|
+
@handlers.delete io
|
28
|
+
@times.delete io
|
29
|
+
@tos.delete io
|
30
|
+
@rs.delete io
|
31
|
+
@ws.delete io
|
32
|
+
}
|
33
|
+
@on_detach.call
|
34
|
+
end
|
35
|
+
|
36
|
+
def on_detach &on_detach
|
37
|
+
@on_detach = on_detach
|
38
|
+
end
|
39
|
+
|
40
|
+
def next_tick &cb
|
41
|
+
@procs.push cb
|
42
|
+
end
|
43
|
+
|
44
|
+
def watch io, flag, to, handler
|
45
|
+
now = Time.now
|
46
|
+
@handlers[io] = handler
|
47
|
+
@times[io] = now
|
48
|
+
@tos[io] = to
|
49
|
+
case flag
|
50
|
+
when :r
|
51
|
+
@rs.push io
|
52
|
+
when :w
|
53
|
+
@ws.push io
|
54
|
+
when :rw
|
55
|
+
@rs.push io
|
56
|
+
@ws.push io
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def has_active_watchers?
|
61
|
+
!(@rs.empty? and @ws.empty? and @collectors.empty? and @procs.empty?)
|
62
|
+
end
|
63
|
+
|
64
|
+
def run
|
65
|
+
while has_active_watchers?
|
66
|
+
run_once
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def run_once
|
71
|
+
while (cb = @procs.shift)
|
72
|
+
cb.call
|
73
|
+
end
|
74
|
+
if (a = IO.select(@rs, @ws, nil, 1))
|
75
|
+
rs, ws = a
|
76
|
+
for io in rs
|
77
|
+
@rs.delete io
|
78
|
+
if (h = @handlers[io])
|
79
|
+
h.on_readable io
|
80
|
+
end
|
81
|
+
end
|
82
|
+
for io in ws
|
83
|
+
@ws.delete io
|
84
|
+
if (h = @handlers[io])
|
85
|
+
h.on_writable io
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
if @pt.sec != (now = Time.now).sec
|
90
|
+
for io in @rs + @ws
|
91
|
+
if (t = @times[io]) and (to = @tos[io]) > 0 and (now - t >= to)
|
92
|
+
@rs.delete io
|
93
|
+
@ws.delete io
|
94
|
+
if (h = @handlers[io])
|
95
|
+
h.retry
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
for c in @collectors.keys
|
100
|
+
if c.attached_at and c.attached_at + c.timeout < now
|
101
|
+
c.on_timeout
|
102
|
+
detach c
|
103
|
+
end
|
104
|
+
end
|
105
|
+
@pt = now
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
data/lib/gri/ltsv.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# conding: us-ascii
|
2
|
+
|
3
|
+
module LTSV
|
4
|
+
def escape18 s
|
5
|
+
s.to_s.gsub(/\n/, "\\n").gsub(/\r/, "\\r").gsub(/\t/, "\\t")
|
6
|
+
end
|
7
|
+
|
8
|
+
def escape19 s
|
9
|
+
s.to_s.force_encoding(Encoding::ASCII_8BIT).
|
10
|
+
gsub(/\n/, "\\n").gsub(/\r/, "\\r").gsub(/\t/, "\\t")
|
11
|
+
end
|
12
|
+
|
13
|
+
alias_method :escape,
|
14
|
+
(''.respond_to? :force_encoding) ? :escape19 : :escape18
|
15
|
+
extend LTSV
|
16
|
+
|
17
|
+
def serialize value
|
18
|
+
h = value.to_hash
|
19
|
+
h.map {|k, v| "#{k}:#{escape v}"}.join("\t")
|
20
|
+
end
|
21
|
+
|
22
|
+
def dump_to_io values, io
|
23
|
+
(Hash === values) and values = values.values
|
24
|
+
for value in values
|
25
|
+
io.puts serialize(value)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def dump_to_file values, path
|
30
|
+
tmp_path = path + ".tmp#{$$}"
|
31
|
+
open(tmp_path, 'w') {|f|
|
32
|
+
dump_to_io values, f
|
33
|
+
}
|
34
|
+
File.rename tmp_path, path
|
35
|
+
end
|
36
|
+
|
37
|
+
def parse_string line
|
38
|
+
h = {}
|
39
|
+
for item in line.split("\t")
|
40
|
+
k, v = item.split(':', 2)
|
41
|
+
next unless k
|
42
|
+
h[k] = case v
|
43
|
+
when nil; nil
|
44
|
+
when ''; nil
|
45
|
+
else v
|
46
|
+
end
|
47
|
+
end
|
48
|
+
h
|
49
|
+
end
|
50
|
+
|
51
|
+
def load_from_file path
|
52
|
+
File.open(path, 'rb') {|f| parse_io f}
|
53
|
+
end
|
54
|
+
|
55
|
+
def parse_io io
|
56
|
+
io.map {|line| parse_string line.chomp}
|
57
|
+
end
|
58
|
+
end
|
data/lib/gri/main.rb
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'socket'
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
|
6
|
+
require 'gri/config'
|
7
|
+
require 'gri/builtindefs'
|
8
|
+
require 'gri/plugin'
|
9
|
+
require 'gri/app_collector'
|
10
|
+
require 'gri/pcollector'
|
11
|
+
require 'gri/tra_collector'
|
12
|
+
require 'gri/updater'
|
13
|
+
require 'gri/writer'
|
14
|
+
require 'gri/log'
|
15
|
+
|
16
|
+
module GRI
|
17
|
+
class Main
|
18
|
+
attr_reader :config, :options
|
19
|
+
|
20
|
+
def initialize
|
21
|
+
@options = {}
|
22
|
+
optparser = optparse @options
|
23
|
+
optparser.parse!
|
24
|
+
config_path = options[:config_path] || GRI::Config::DEFAULT_PATH
|
25
|
+
@config = GRI::Config.init config_path
|
26
|
+
@options.each {|k, v| @config.setvar k.to_s, v}
|
27
|
+
root_dir = @config['root-dir'] ||= Config::ROOT_PATH
|
28
|
+
|
29
|
+
plugin_dirs = @config.getvar('plugin-dir') || [root_dir + '/plugin']
|
30
|
+
GRI::Plugin.load_plugins plugin_dirs, @config
|
31
|
+
|
32
|
+
log_dir = @config['log-dir'] || root_dir + '/log'
|
33
|
+
Dir.mkdir log_dir unless File.exist? log_dir
|
34
|
+
Log.init "#{log_dir}/#{optparser.program_name}.log",
|
35
|
+
:log_level=>@config['log-level']
|
36
|
+
|
37
|
+
@config['tra-dir'] ||= root_dir + '/tra'
|
38
|
+
@config['gra-dir'] ||= root_dir + '/gra'
|
39
|
+
end
|
40
|
+
|
41
|
+
def run
|
42
|
+
@config['para'] = true unless config.has_key? 'para'
|
43
|
+
if @config['walker']
|
44
|
+
app = AppWalker.new @config
|
45
|
+
writer = Writer.create 'stdout', @config.to_h
|
46
|
+
app.writers.push writer
|
47
|
+
elsif @config['collector']
|
48
|
+
# collector
|
49
|
+
app = AppCollector.new @config
|
50
|
+
writer = Writer.create 'ldb', @config.to_h
|
51
|
+
app.writers.push writer
|
52
|
+
else
|
53
|
+
# minigri
|
54
|
+
app = AppCollector.new @config
|
55
|
+
wopts = @config.to_h.update :merge_p=>true
|
56
|
+
writer = Writer.create 'rrd', wopts
|
57
|
+
app.writers.push writer
|
58
|
+
end
|
59
|
+
if @options['writers']
|
60
|
+
for w in @options['writers']
|
61
|
+
writer = Writer.create w, @config.to_h
|
62
|
+
app.writers.push writer if writer
|
63
|
+
end
|
64
|
+
end
|
65
|
+
app.run
|
66
|
+
if app.metrics[:nometrics].zero? and !$debug
|
67
|
+
hostname = Socket.gethostname rescue 'unknown'
|
68
|
+
hostname = hostname.split(/\./).first
|
69
|
+
t = Time.now.to_i
|
70
|
+
interval = @config['interval'] || 300
|
71
|
+
records = app.metrics.map {|k, v|
|
72
|
+
{'_interval'=>interval, '_host'=>"GRIMETRICS-#{hostname}",
|
73
|
+
'_time'=>t, '_key'=>"num_#{k}", 'num'=>v}}
|
74
|
+
writer = Writer.create 'ldb', @config.to_h
|
75
|
+
writer.write records
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def optparse opts
|
80
|
+
op = OptionParser.new
|
81
|
+
op.on('--debug') {$debug = true; STDOUT.sync = true;
|
82
|
+
opts['log-level'] = 'debug'}
|
83
|
+
op.on('--Doption=STR') {|arg| (opts['Doption'] ||= []).push arg}
|
84
|
+
|
85
|
+
op.on('--add-writer=WRITER') {|arg| (opts['writers'] ||= []).push arg}
|
86
|
+
op.on('-O OPT_STR') {|arg| (opts['O'] ||= []).push arg}
|
87
|
+
op.on('--collector') {opts['collector'] = true}
|
88
|
+
op.on('--config-path=PATH') {|arg| opts[:config_path] = arg}
|
89
|
+
op.on('--duration=SEC', Integer) {|arg| opts['duration'] = arg}
|
90
|
+
op.on('--gritab-path=PATH') {|arg| opts['gritab-path'] = arg}
|
91
|
+
op.on('--host-pat=PAT', '-h') {|arg| (opts['host-pat'] ||= []).push arg}
|
92
|
+
op.on('--interval=SEC', Integer) {|arg| opts['interval'] = arg}
|
93
|
+
op.on('--log-level=LEVEL') {|arg| opts['log-level'] = arg}
|
94
|
+
op.on('--nop') {opts['nop'] = true}
|
95
|
+
op.on('--para') {opts['para'] = true}
|
96
|
+
op.on('-p', '--plugin-dir=DIR') {|arg|
|
97
|
+
(opts['plugin-dir'] ||= []).push arg}
|
98
|
+
op.on('--rrdupdater', '--updater') {opts['updater'] = true}
|
99
|
+
op.on('--single') {opts['para'] = false}
|
100
|
+
op.on('--tra=URL') {|arg| opts['tra'] = arg}
|
101
|
+
|
102
|
+
op.on('-c COMMUNITY') {|arg| opts['community'] = arg}
|
103
|
+
op.on('-v VER') {|arg| opts['version'] = arg}
|
104
|
+
op
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
data/lib/gri/mlog.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
module Log
|
2
|
+
extend Log
|
3
|
+
|
4
|
+
def init(*args)
|
5
|
+
end
|
6
|
+
def write grp, str, severity=nil
|
7
|
+
end
|
8
|
+
def puts(*args)
|
9
|
+
end
|
10
|
+
def pp(*args)
|
11
|
+
end
|
12
|
+
def debug(*args, &block)
|
13
|
+
end
|
14
|
+
def info(*args, &block)
|
15
|
+
end
|
16
|
+
def warn(*args, &block)
|
17
|
+
end
|
18
|
+
def error(*args, &block)
|
19
|
+
end
|
20
|
+
def fatal(*args, &block)
|
21
|
+
end
|
22
|
+
end
|
data/lib/gri/mmsgpack.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
# coding: us-ascii
|
2
|
+
|
3
|
+
class Fixnum
|
4
|
+
def to_msgpack
|
5
|
+
if (self >= -32 and self <= 127)
|
6
|
+
[self].pack('c')
|
7
|
+
elsif self < 4294967296
|
8
|
+
"\xd2"+[self].pack('N')
|
9
|
+
else
|
10
|
+
"\xcf"+[(self>>32), (self&0xffffffff)].pack('N2')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class Bignum
|
16
|
+
def to_msgpack
|
17
|
+
"\xcf"+[(self>>32), (self&0xffffffff)].pack('N2')
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class Float
|
22
|
+
def to_msgpack
|
23
|
+
if self < 4294967296
|
24
|
+
"\xce"+[(self/65536).to_i, self%65536].pack('n2')
|
25
|
+
else
|
26
|
+
"\xcf"+[(self/281474976710656).to_i,
|
27
|
+
(self/4294967296%65536).to_i,
|
28
|
+
(self%4294967296/65536).to_i, self%65536].pack('n4')
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class Nil
|
34
|
+
def to_msgpack
|
35
|
+
"\xc0"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class String
|
40
|
+
def to_msgpack
|
41
|
+
"\xdb"+[self.size].pack('N')+self
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class Array
|
46
|
+
def to_msgpack
|
47
|
+
"\xdc" + [self.size].pack('n') +
|
48
|
+
self.map {|e| e.to_msgpack}.join('')
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class Hash
|
53
|
+
def to_msgpack
|
54
|
+
"\xde" + [self.size].pack('n') +
|
55
|
+
self.map {|k, v| k.to_msgpack + v.to_msgpack}.join('')
|
56
|
+
end
|
57
|
+
end
|
data/lib/gri/msnmp.rb
ADDED
@@ -0,0 +1,601 @@
|
|
1
|
+
# coding: us-ascii
|
2
|
+
|
3
|
+
class String
|
4
|
+
unless ''.respond_to? :getbyte
|
5
|
+
def getbyte idx
|
6
|
+
self[idx]
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
unless ''.respond_to? :slice!
|
11
|
+
def slice!(arg1, arg2 = 1)
|
12
|
+
return nil if arg2 < 0
|
13
|
+
if arg1.class == Fixnum
|
14
|
+
rval = self[arg1, arg2]
|
15
|
+
len = self.length
|
16
|
+
rpos = arg1 + arg2
|
17
|
+
rpos += len if arg1 < 0
|
18
|
+
rlen = len - rpos
|
19
|
+
region_l = self[0...arg1]
|
20
|
+
region_r = self[rpos, rlen]
|
21
|
+
region_r = '' if region_r == nil
|
22
|
+
self.replace(region_l + region_r)
|
23
|
+
elsif arg1.class == String
|
24
|
+
rval = arg1
|
25
|
+
self.gsub!(arg1, "")
|
26
|
+
else
|
27
|
+
return nil
|
28
|
+
end
|
29
|
+
rval
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
module BER
|
35
|
+
class C64
|
36
|
+
def initialize s
|
37
|
+
@s = s
|
38
|
+
@a = [0, 0, 0, 0, 0, 0, 0, 0]
|
39
|
+
j = 7
|
40
|
+
(s.size-1).downto(0) {|i| @a[j] = s.getbyte(i); j -= 1}
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_s
|
44
|
+
'0x' + @a.map {|b| sprintf "%02x", b}.join('')
|
45
|
+
end
|
46
|
+
|
47
|
+
def to_binary
|
48
|
+
@a.pack('C*')
|
49
|
+
end
|
50
|
+
|
51
|
+
def to_msgpack
|
52
|
+
"\xcf" + @a.pack('C*')
|
53
|
+
end
|
54
|
+
|
55
|
+
def to_i
|
56
|
+
n = 0
|
57
|
+
0.upto(7) {|i| n = n * 256 + @a[i]}
|
58
|
+
n
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def enc tag, val
|
63
|
+
case tag
|
64
|
+
when 0x02
|
65
|
+
return enc_int(val)
|
66
|
+
when 0x04
|
67
|
+
return enc_str(val)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def enc_len n
|
72
|
+
if n < 128 then
|
73
|
+
return n.chr
|
74
|
+
end
|
75
|
+
e_len = ''
|
76
|
+
while n > 0
|
77
|
+
e_len = (n & 0xff).chr + e_len
|
78
|
+
n = n >> 8
|
79
|
+
end
|
80
|
+
return (e_len.size | 0x80).chr + e_len
|
81
|
+
end
|
82
|
+
|
83
|
+
def enc_int n
|
84
|
+
ebuf = ''
|
85
|
+
if n < 0 then
|
86
|
+
begin
|
87
|
+
ebuf = (n & 0xff).chr + ebuf
|
88
|
+
n = n >> 8
|
89
|
+
end until (n == -1) and (ebuf.getbyte(0) & 0x80 == 0x80)
|
90
|
+
else
|
91
|
+
begin
|
92
|
+
ebuf = (n & 0xff).chr + ebuf
|
93
|
+
n = n >> 8
|
94
|
+
end while n > 0
|
95
|
+
end
|
96
|
+
return "\x02" + enc_len(ebuf.size) + ebuf
|
97
|
+
end
|
98
|
+
|
99
|
+
def enc_str s
|
100
|
+
return "\x04" + enc_len(s.size) + s
|
101
|
+
end
|
102
|
+
|
103
|
+
def enc_a_oid a
|
104
|
+
a.shift; a.shift
|
105
|
+
e = '+' # 1.3
|
106
|
+
until a.empty?
|
107
|
+
subid = a.shift.to_i
|
108
|
+
s = ''
|
109
|
+
if subid == 0 then
|
110
|
+
e += "\x00"
|
111
|
+
else
|
112
|
+
while subid > 0
|
113
|
+
if s.empty?
|
114
|
+
s = (subid & 0x7f).chr + s
|
115
|
+
else
|
116
|
+
s = (subid & 0x7f | 0x80).chr + s
|
117
|
+
end
|
118
|
+
subid = subid >> 7
|
119
|
+
end
|
120
|
+
e += s
|
121
|
+
end
|
122
|
+
end
|
123
|
+
e
|
124
|
+
end
|
125
|
+
|
126
|
+
def enc_v_oid oid
|
127
|
+
a = oid.split('.')
|
128
|
+
enc_a_oid a
|
129
|
+
end
|
130
|
+
|
131
|
+
def enc_oid oid
|
132
|
+
e = enc_v_oid oid
|
133
|
+
return "\x06" + enc_len(e.size) + e
|
134
|
+
end
|
135
|
+
|
136
|
+
def enc_oid_list oid_list
|
137
|
+
s = ''
|
138
|
+
for e in oid_list
|
139
|
+
vb = enc_oid(e) + "\x05\x00" # BER.enc_null
|
140
|
+
s = s + "\x30" + enc_len(vb.size) + vb
|
141
|
+
end
|
142
|
+
varbind = "\x30" + enc_len(s.size) + s
|
143
|
+
end
|
144
|
+
|
145
|
+
def enc_varbind enoid
|
146
|
+
s = "\x06" + enc_len(enoid.size) + enoid + "\x05\x00"
|
147
|
+
s = "\x30" + enc_len(s.size) + s
|
148
|
+
return "\x30" + enc_len(s.size) + s
|
149
|
+
end
|
150
|
+
|
151
|
+
def cat_enoid enoids
|
152
|
+
s = ''
|
153
|
+
for enoid in enoids
|
154
|
+
vb = "\x06" + enc_len(enoid.size) + enoid + "\x05\x00"
|
155
|
+
s = s + "\x30" + enc_len(vb.size) + vb
|
156
|
+
end
|
157
|
+
varbind = "\x30" + enc_len(s.size) + s
|
158
|
+
end
|
159
|
+
|
160
|
+
def dec_oid msg
|
161
|
+
msg = msg.clone
|
162
|
+
if msg.getbyte(0) == 0x2b
|
163
|
+
oid = [1, 3]
|
164
|
+
msg.slice! 0
|
165
|
+
else
|
166
|
+
oid = []
|
167
|
+
end
|
168
|
+
until msg.empty?
|
169
|
+
c = msg.getbyte 0
|
170
|
+
msg.slice! 0
|
171
|
+
if c > 127
|
172
|
+
id = 0
|
173
|
+
while c > 127
|
174
|
+
id = (id << 7) + (c & 0x7f)
|
175
|
+
c = msg.getbyte 0
|
176
|
+
msg.slice! 0
|
177
|
+
end
|
178
|
+
id = (id << 7) + c
|
179
|
+
oid.push id
|
180
|
+
else
|
181
|
+
oid.push c
|
182
|
+
end
|
183
|
+
end
|
184
|
+
return oid
|
185
|
+
end
|
186
|
+
|
187
|
+
def dec_int s
|
188
|
+
if (s.getbyte(0) & 0x80) == 0x80
|
189
|
+
n = -1
|
190
|
+
else
|
191
|
+
n = 0
|
192
|
+
end
|
193
|
+
while s.size > 0
|
194
|
+
n = n << 8 | s.getbyte(0)
|
195
|
+
s = s[1..-1]
|
196
|
+
end
|
197
|
+
return n
|
198
|
+
end
|
199
|
+
|
200
|
+
def dec_cnt s
|
201
|
+
n = 0
|
202
|
+
while s.size > 0
|
203
|
+
n = n << 8 | s.getbyte(0)
|
204
|
+
s = s[1..-1]
|
205
|
+
end
|
206
|
+
return n
|
207
|
+
end
|
208
|
+
|
209
|
+
def dec_cnt64 s
|
210
|
+
C64.new(s)
|
211
|
+
end
|
212
|
+
|
213
|
+
Object.const_defined?(:RUBY_VERSION) and
|
214
|
+
alias_method(:dec_cnt64, :dec_cnt)
|
215
|
+
|
216
|
+
def tlv data
|
217
|
+
tag = data.getbyte 0
|
218
|
+
if (len = data.getbyte(1)) < 128
|
219
|
+
val = data[2, len]
|
220
|
+
remain = data[(len + 2)..-1]
|
221
|
+
elsif len == 0x81
|
222
|
+
len = data.getbyte 2
|
223
|
+
val = data[3, len]
|
224
|
+
remain = data[(len + 3)..-1]
|
225
|
+
else
|
226
|
+
n = len & 0x7f
|
227
|
+
len = 0
|
228
|
+
for i in 1..n
|
229
|
+
len = len * 256 + data.getbyte(i + 1)
|
230
|
+
end
|
231
|
+
val = data[n + 2, len]
|
232
|
+
remain = data[(len + n + 2).. -1]
|
233
|
+
end
|
234
|
+
return tag, val, remain
|
235
|
+
end
|
236
|
+
|
237
|
+
def dec_msg msg
|
238
|
+
if msg[1, 1] < "\x80"
|
239
|
+
idx = msg.getbyte(6) + 7
|
240
|
+
pdutype, pdu, msg = tlv msg[idx..-1]
|
241
|
+
elsif msg[1, 1] == "\x81"
|
242
|
+
idx = msg.getbyte(7) + 8
|
243
|
+
pdutype, pdu, msg = tlv msg[idx..-1]
|
244
|
+
else
|
245
|
+
tag, val, msg = tlv msg
|
246
|
+
tag, ver, msg = tlv val
|
247
|
+
tag, comm, msg = tlv msg
|
248
|
+
pdutype, pdu, msg = tlv msg
|
249
|
+
end
|
250
|
+
idlen = pdu.getbyte 1
|
251
|
+
enc_reqid = pdu[0, idlen + 2]
|
252
|
+
error_status = pdu.getbyte(idlen + 4)
|
253
|
+
error_index = pdu.getbyte(idlen + 7)
|
254
|
+
tag, varbind, msg = tlv pdu[idlen+8..-1]
|
255
|
+
return enc_reqid, error_status, error_index, varbind
|
256
|
+
end
|
257
|
+
|
258
|
+
def dec_varbind_block msg
|
259
|
+
while msg.size > 0
|
260
|
+
tag,val,msg=tlv(msg)
|
261
|
+
tag,val1,msg0=tlv(val)
|
262
|
+
tag,val2,msg1=tlv(msg0)
|
263
|
+
case tag
|
264
|
+
when 0x02
|
265
|
+
val2=dec_int(val2)
|
266
|
+
when 0x05 #Null
|
267
|
+
val2=nil
|
268
|
+
when 0x06 #OID
|
269
|
+
#val2=dec_oid(val2)
|
270
|
+
when 0x40 # IP Address
|
271
|
+
val2 = val2.unpack('CCCC').join('.')
|
272
|
+
when 0x41, 0x42, 0x43 #Counter or Gauge or Tick
|
273
|
+
val2 = dec_cnt val2
|
274
|
+
when 0x46 #Counter64
|
275
|
+
val2 = dec_cnt64 val2
|
276
|
+
when 0x80
|
277
|
+
next # skip
|
278
|
+
end
|
279
|
+
yield val1, tag, val2
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
def dec_varbind msg
|
284
|
+
list=[]
|
285
|
+
val1 = tag = val2 = nil #XXX
|
286
|
+
dec_varbind_block(msg) {|val1, tag, val2|
|
287
|
+
list.push([val1,tag,val2])
|
288
|
+
}
|
289
|
+
return list
|
290
|
+
end
|
291
|
+
|
292
|
+
extend BER
|
293
|
+
end
|
294
|
+
|
295
|
+
class SNMP
|
296
|
+
OIDS = {
|
297
|
+
'iso'=>'1',
|
298
|
+
'org'=>'1.3',
|
299
|
+
'dod'=>'1.3.6',
|
300
|
+
'internet'=>'1.3.6.1',
|
301
|
+
'directory'=>'1.3.6.1.1',
|
302
|
+
'mgmt'=>'1.3.6.1.2',
|
303
|
+
'mib-2'=>'1.3.6.1.2.1',
|
304
|
+
'system'=>'1.3.6.1.2.1.1',
|
305
|
+
'sysDescr'=>'1.3.6.1.2.1.1.1',
|
306
|
+
'sysObjectID'=>'1.3.6.1.2.1.1.2',
|
307
|
+
'sysUpTime'=>'1.3.6.1.2.1.1.3',
|
308
|
+
'sysContact'=>'1.3.6.1.2.1.1.4',
|
309
|
+
'sysName'=>'1.3.6.1.2.1.1.5',
|
310
|
+
'sysLocation'=>'1.3.6.1.2.1.1.6',
|
311
|
+
'sysServices'=>'1.3.6.1.2.1.1.7',
|
312
|
+
|
313
|
+
'interfaces'=>'1.3.6.1.2.1.2',
|
314
|
+
'ifNumber'=>'1.3.6.1.2.1.2.1',
|
315
|
+
'ifTable'=>'1.3.6.1.2.1.2.2',
|
316
|
+
'ifEntry'=>'1.3.6.1.2.1.2.2.1',
|
317
|
+
'ifIndex'=>'1.3.6.1.2.1.2.2.1.1',
|
318
|
+
'ifInOctets'=>'1.3.6.1.2.1.2.2.1.10',
|
319
|
+
'ifInUcastPkts'=>'1.3.6.1.2.1.2.2.1.11',
|
320
|
+
'ifInNUcastPkts'=>'1.3.6.1.2.1.2.2.1.12',
|
321
|
+
'ifInDiscards'=>'1.3.6.1.2.1.2.2.1.13',
|
322
|
+
'ifInErrors'=>'1.3.6.1.2.1.2.2.1.14',
|
323
|
+
'ifInUnknownProtos'=>'1.3.6.1.2.1.2.2.1.15',
|
324
|
+
'ifOutOctets'=>'1.3.6.1.2.1.2.2.1.16',
|
325
|
+
'ifOutUcastPkts'=>'1.3.6.1.2.1.2.2.1.17',
|
326
|
+
'ifOutNUcastPkts'=>'1.3.6.1.2.1.2.2.1.18',
|
327
|
+
'ifOutDiscards'=>'1.3.6.1.2.1.2.2.1.19',
|
328
|
+
'ifDescr'=>'1.3.6.1.2.1.2.2.1.2',
|
329
|
+
'ifOutErrors'=>'1.3.6.1.2.1.2.2.1.20',
|
330
|
+
'ifOutQLen'=>'1.3.6.1.2.1.2.2.1.21',
|
331
|
+
'ifSpecific'=>'1.3.6.1.2.1.2.2.1.22',
|
332
|
+
'ifType'=>'1.3.6.1.2.1.2.2.1.3',
|
333
|
+
'ifMtu'=>'1.3.6.1.2.1.2.2.1.4',
|
334
|
+
'ifSpeed'=>'1.3.6.1.2.1.2.2.1.5',
|
335
|
+
'ifPhysAddress'=>'1.3.6.1.2.1.2.2.1.6',
|
336
|
+
'ifAdminStatus'=>'1.3.6.1.2.1.2.2.1.7',
|
337
|
+
'ifOperStatus'=>'1.3.6.1.2.1.2.2.1.8',
|
338
|
+
'ifLastChange'=>'1.3.6.1.2.1.2.2.1.9',
|
339
|
+
|
340
|
+
'ipAddrTable'=>'1.3.6.1.2.1.4.20',
|
341
|
+
'ipAddrEntry'=>'1.3.6.1.2.1.4.20.1',
|
342
|
+
'ipAdEntIfIndex'=>'1.3.6.1.2.1.4.20.1.2',
|
343
|
+
'ipAdEntNetMask'=>'1.3.6.1.2.1.4.20.1.3',
|
344
|
+
'ipNetToMediaIfIndex'=>'1.3.6.1.2.1.4.22.1.1',
|
345
|
+
'ipNetToMediaPhysAddress'=>'1.3.6.1.2.1.4.22.1.2',
|
346
|
+
'ipNetToMediaNetAddress'=>'1.3.6.1.2.1.4.22.1.3',
|
347
|
+
'ipNetToMediaType'=>'1.3.6.1.2.1.4.22.1.4',
|
348
|
+
|
349
|
+
'tcp'=>'1.3.6.1.2.1.6',
|
350
|
+
'tcpCurrEstab'=>'1.3.6.1.2.1.6.9.0',
|
351
|
+
'tcpActiveOpens'=>'1.3.6.1.2.1.6.5.0',
|
352
|
+
'tcpPassiveOpens'=>'1.3.6.1.2.1.6.6.0',
|
353
|
+
'tcpAttemptFails'=>'1.3.6.1.2.1.6.7.0',
|
354
|
+
'tcpEstabResets'=>'1.3.6.1.2.1.6.8.0',
|
355
|
+
'tcpInSegs'=>'1.3.6.1.2.1.6.10.0',
|
356
|
+
'tcpOutSegs'=>'1.3.6.1.2.1.6.11.0',
|
357
|
+
'tcpRetransSegs'=>'1.3.6.1.2.1.6.12.0',
|
358
|
+
'tcpInErrs'=>'1.3.6.1.2.1.6.14.0',
|
359
|
+
'tcpOutRsts'=>'1.3.6.1.2.1.6.15.0',
|
360
|
+
|
361
|
+
'udp'=>'1.3.6.1.2.1.7',
|
362
|
+
'udpInDatagrams' => '1.3.6.1.2.1.7.1.0',
|
363
|
+
'udpNoPorts' => '1.3.6.1.2.1.7.2.0',
|
364
|
+
'udpInErrors' => '1.3.6.1.2.1.7.3.0',
|
365
|
+
'udpOutDatagrams' => '1.3.6.1.2.1.7.4.0',
|
366
|
+
|
367
|
+
'host'=>'1.3.6.1.2.1.25',
|
368
|
+
'hrSystem'=>'1.3.6.1.2.1.25.1',
|
369
|
+
'hrSystemNumUsers'=>'1.3.6.1.2.1.25.1.5.0',
|
370
|
+
'hrSystemProcesses'=>'1.3.6.1.2.1.25.1.6.0',
|
371
|
+
'hrSystemMaxProcesses'=>'1.3.6.1.2.1.25.1.7.0',
|
372
|
+
'hrSystem'=>'1.3.6.1.2.1.25.1',
|
373
|
+
'hrStorage'=>'1.3.6.1.2.1.25.2',
|
374
|
+
'hrStorageTypes'=>'1.3.6.1.2.1.25.2.1',
|
375
|
+
'hrStorageFixedDisk'=>'1.3.6.1.2.1.25.2.1.4',
|
376
|
+
'hrMemorySize'=>'1.3.6.1.2.1.25.2.2.0',
|
377
|
+
'hrStorageTable'=>'1.3.6.1.2.1.25.2.3',
|
378
|
+
'hrStorageEntry'=>'1.3.6.1.2.1.25.2.3.1',
|
379
|
+
'hrStorageIndex'=>'1.3.6.1.2.1.25.2.3.1.1',
|
380
|
+
'hrStorageType'=>'1.3.6.1.2.1.25.2.3.1.2',
|
381
|
+
'hrStorageDescr'=>'1.3.6.1.2.1.25.2.3.1.3',
|
382
|
+
'hrStorageAllocationUnits'=>'1.3.6.1.2.1.25.2.3.1.4',
|
383
|
+
'hrStorageSize'=>'1.3.6.1.2.1.25.2.3.1.5',
|
384
|
+
'hrStorageUsed'=>'1.3.6.1.2.1.25.2.3.1.6',
|
385
|
+
|
386
|
+
'hrSWRunName'=>'1.3.6.1.2.1.25.4.2.1.2',
|
387
|
+
'hrSWRunPath'=>'1.3.6.1.2.1.25.4.2.1.4',
|
388
|
+
'hrSWRunParameters'=>'1.3.6.1.2.1.25.4.2.1.5',
|
389
|
+
'hrSWRunPerfCPU'=>'1.3.6.1.2.1.25.5.1.1.1',
|
390
|
+
'hrSWRunPerfMem'=>'1.3.6.1.2.1.25.5.1.1.2',
|
391
|
+
|
392
|
+
'ifMIB'=>'1.3.6.1.2.1.31',
|
393
|
+
'ifXEntry'=>'1.3.6.1.2.1.31.1.1.1',
|
394
|
+
'ifName'=>'1.3.6.1.2.1.31.1.1.1.1',
|
395
|
+
'ifInMulticastPkts'=>'1.3.6.1.2.1.31.1.1.1.2',
|
396
|
+
'ifInBroadcastPkts'=>'1.3.6.1.2.1.31.1.1.1.3',
|
397
|
+
'ifOutMulticastPkts'=>'1.3.6.1.2.1.31.1.1.1.4',
|
398
|
+
'ifOutBroadcastPkts'=>'1.3.6.1.2.1.31.1.1.1.5',
|
399
|
+
'ifHCInOctets'=>'1.3.6.1.2.1.31.1.1.1.6',
|
400
|
+
'ifHCInUcastPkts'=>'1.3.6.1.2.1.31.1.1.1.7',
|
401
|
+
'ifHCInMulticastPkts'=>'1.3.6.1.2.1.31.1.1.1.8',
|
402
|
+
'ifHCInBroadcastPkts'=>'1.3.6.1.2.1.31.1.1.1.9',
|
403
|
+
'ifHCOutOctets'=>'1.3.6.1.2.1.31.1.1.1.10',
|
404
|
+
'ifHCOutUcastPkts'=>'1.3.6.1.2.1.31.1.1.1.11',
|
405
|
+
'ifHCOutMulticastPkts'=>'1.3.6.1.2.1.31.1.1.1.12',
|
406
|
+
'ifHCOutBroadcastPkts'=>'1.3.6.1.2.1.31.1.1.1.13',
|
407
|
+
'ifLinkUpDownTrapEnable'=>'1.3.6.1.2.1.31.1.1.1.14',
|
408
|
+
'ifHighSpeed'=>'1.3.6.1.2.1.31.1.1.1.15',
|
409
|
+
'ifPromiscuousMode'=>'1.3.6.1.2.1.31.1.1.1.16',
|
410
|
+
'ifConnectorPresent'=>'1.3.6.1.2.1.31.1.1.1.17',
|
411
|
+
'ifAlias'=>'1.3.6.1.2.1.31.1.1.1.18',
|
412
|
+
|
413
|
+
'entityMIB'=>'1.3.6.1.2.1.47',
|
414
|
+
'entPhysicalEntry'=>'1.3.6.1.2.1.47.1.1.1.1',
|
415
|
+
'entPhysicalDescr'=>'1.3.6.1.2.1.47.1.1.1.1.2',
|
416
|
+
'entPhysicalName'=>'1.3.6.1.2.1.47.1.1.1.1.7',
|
417
|
+
|
418
|
+
'experimental'=>'1.3.6.1.3',
|
419
|
+
'private'=>'1.3.6.1.4',
|
420
|
+
'enterprises'=>'1.3.6.1.4.1',
|
421
|
+
}
|
422
|
+
ROIDS = {}
|
423
|
+
RECV_SIZE = 2000
|
424
|
+
|
425
|
+
attr_reader :sock
|
426
|
+
attr_accessor :state, :numeric
|
427
|
+
|
428
|
+
def self.add_oid sym, oid
|
429
|
+
OIDS[sym] = oid
|
430
|
+
end
|
431
|
+
|
432
|
+
def self.update h
|
433
|
+
OIDS.merge! h
|
434
|
+
end
|
435
|
+
|
436
|
+
def initialize host, port=nil
|
437
|
+
port ||= 161
|
438
|
+
if ROIDS.empty?
|
439
|
+
for sym, oid in OIDS
|
440
|
+
ROIDS[BER.enc_v_oid(oid)] = sym
|
441
|
+
end
|
442
|
+
end
|
443
|
+
@host = host
|
444
|
+
@port = port
|
445
|
+
@request_id = 1000
|
446
|
+
@retries = 3
|
447
|
+
@timeout = 4
|
448
|
+
@ver = "\x02\x01\x00" # INT: 0 (ver 1)
|
449
|
+
@community = "\x04\x06public"
|
450
|
+
@numeric = false
|
451
|
+
@state = :IDLE
|
452
|
+
@sock = nil
|
453
|
+
end
|
454
|
+
|
455
|
+
def connect
|
456
|
+
@sock = UDPSocket.new
|
457
|
+
@sock.connect @host, @port
|
458
|
+
end
|
459
|
+
|
460
|
+
def close
|
461
|
+
@sock.close
|
462
|
+
end
|
463
|
+
|
464
|
+
def version=(ver)
|
465
|
+
ver = {'1'=>0, '2c'=>1}[ver] || 0
|
466
|
+
@ver = BER.enc_int ver
|
467
|
+
end
|
468
|
+
|
469
|
+
def community=(community)
|
470
|
+
@community = BER.enc_str community
|
471
|
+
end
|
472
|
+
|
473
|
+
def enoid2name enoid
|
474
|
+
a = BER.dec_oid enoid
|
475
|
+
n = a.size
|
476
|
+
n0 = n
|
477
|
+
|
478
|
+
while n > 1
|
479
|
+
if (s = ROIDS[BER.enc_a_oid(a[0, n])])
|
480
|
+
return ([s] + a[n, n0-n]).join('.')
|
481
|
+
end
|
482
|
+
n -= 1
|
483
|
+
end
|
484
|
+
s || a.join('.')
|
485
|
+
end
|
486
|
+
|
487
|
+
def make_msg cmd, err_index, varbind
|
488
|
+
@request_id += 1
|
489
|
+
@enc_request_id = BER.enc_int @request_id
|
490
|
+
s = @enc_request_id + "\x02\x01\x00" + err_index + varbind
|
491
|
+
s = @ver + @community + cmd + BER.enc_len(s.size) + s
|
492
|
+
s = "\x30" + BER.enc_len(s.size) + s
|
493
|
+
end
|
494
|
+
|
495
|
+
def make_req st, arg
|
496
|
+
case st
|
497
|
+
when :GETBULK_REQ
|
498
|
+
vb = "\x06" + BER.enc_len(arg.size) + arg + "\x05\x00"
|
499
|
+
vb = "\x30" + BER.enc_len(vb.size) + vb
|
500
|
+
varbind = "\x30" + BER.enc_len(vb.size) + vb
|
501
|
+
s = make_msg "\xa5", "\x02\x01\x0c", varbind
|
502
|
+
when :GETNEXT_REQ
|
503
|
+
vb = "\x06" + BER.enc_len(arg.size) + arg + "\x05\x00"
|
504
|
+
vb = "\x30" + BER.enc_len(vb.size) + vb
|
505
|
+
varbind = "\x30" + BER.enc_len(vb.size) + vb
|
506
|
+
s = make_msg "\xa1", "\x02\x01\x00", varbind
|
507
|
+
when :GET_REQ
|
508
|
+
s = make_msg "\xa0", "\x02\x01\x00", arg
|
509
|
+
end
|
510
|
+
s
|
511
|
+
end
|
512
|
+
|
513
|
+
def walk_start enoid, &cb
|
514
|
+
@req_enoid = enoid
|
515
|
+
@cb = cb
|
516
|
+
@state = (@ver == "\002\001\001") ? :GETBULK_REQ : :GETNEXT_REQ
|
517
|
+
end
|
518
|
+
|
519
|
+
def _walk enoid, &cb
|
520
|
+
walk_start enoid, &cb
|
521
|
+
req_loop enoid
|
522
|
+
end
|
523
|
+
|
524
|
+
def walk oid, &cb
|
525
|
+
noid = OIDS[oid] || oid
|
526
|
+
enoid = BER.enc_v_oid noid
|
527
|
+
_walk(enoid) {|enoid, tag, val|
|
528
|
+
oid = @numeric ? (BER.dec_oid(enoid).join('.')) : (enoid2name enoid)
|
529
|
+
cb.call oid, tag, val
|
530
|
+
}
|
531
|
+
end
|
532
|
+
|
533
|
+
def get_start varbind, &cb
|
534
|
+
@req_enoid = ''
|
535
|
+
@cb = cb
|
536
|
+
@state = :GET_REQ
|
537
|
+
end
|
538
|
+
|
539
|
+
def get_varbind varbind, &cb
|
540
|
+
get_start varbind, &cb
|
541
|
+
req_loop varbind
|
542
|
+
end
|
543
|
+
|
544
|
+
def get oid_list, &cb
|
545
|
+
oids = oid_list.map {|s| BER.enc_v_oid(OIDS[s]||s)}
|
546
|
+
varbind = BER.cat_enoid oids
|
547
|
+
get_varbind(varbind) {|enoid, tag, val|
|
548
|
+
oid = @numeric ? (BER.dec_oid(enoid).join('.')) : (enoid2name enoid)
|
549
|
+
cb.call oid, tag, val
|
550
|
+
}
|
551
|
+
end
|
552
|
+
|
553
|
+
def req_loop arg
|
554
|
+
connect unless @sock
|
555
|
+
until @state == :SUCCESS or @state == :IDLE
|
556
|
+
s = make_req @state, arg
|
557
|
+
@retry_count = 0
|
558
|
+
while true
|
559
|
+
@sock.send s, 0
|
560
|
+
if (a = IO.select([@sock], nil, nil, @timeout))
|
561
|
+
msg = @sock.recv RECV_SIZE, 0
|
562
|
+
arg = recv_msg msg
|
563
|
+
if arg
|
564
|
+
@state = :SUCCESS if @state == :GET_REQ
|
565
|
+
break
|
566
|
+
end
|
567
|
+
else
|
568
|
+
if (@retry_count += 1) >= @retries
|
569
|
+
@state = :IDLE
|
570
|
+
return
|
571
|
+
end
|
572
|
+
end
|
573
|
+
end
|
574
|
+
end
|
575
|
+
end
|
576
|
+
|
577
|
+
def recv_msg msg
|
578
|
+
enc_request_id, @error_status, @error_index, varbind = BER.dec_msg msg
|
579
|
+
return unless enc_request_id == @enc_request_id
|
580
|
+
unless @error_status == 0
|
581
|
+
@state = :IDLE
|
582
|
+
return
|
583
|
+
end
|
584
|
+
|
585
|
+
vars = BER.dec_varbind varbind
|
586
|
+
if vars.empty?
|
587
|
+
@state = :SUCCESS
|
588
|
+
return
|
589
|
+
end
|
590
|
+
for var in vars
|
591
|
+
if (var[1] != 130) and var[0].index(@req_enoid) #130=endOfMibView
|
592
|
+
@cb.call(*var)
|
593
|
+
else
|
594
|
+
@state = :SUCCESS
|
595
|
+
end
|
596
|
+
end
|
597
|
+
enoid = vars[-1][0]
|
598
|
+
rescue StandardError
|
599
|
+
raise SystemCallError, 'broken packet'
|
600
|
+
end
|
601
|
+
end
|