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.
Files changed (107) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +7 -0
  3. data/MIT-LICENSE.txt +20 -0
  4. data/README.md +132 -0
  5. data/Rakefile +5 -0
  6. data/bin/grapher +17 -0
  7. data/bin/gri +5 -0
  8. data/bin/gricast +17 -0
  9. data/bin/grispark +5 -0
  10. data/bin/griwalk +9 -0
  11. data/bin/trad +19 -0
  12. data/bin/trad-http +17 -0
  13. data/gri.gemspec +21 -0
  14. data/lib/fluent/plugin/out_gri.rb +56 -0
  15. data/lib/gri/api.rb +28 -0
  16. data/lib/gri/app_collector.rb +154 -0
  17. data/lib/gri/app_walker.rb +23 -0
  18. data/lib/gri/blank.rb +49 -0
  19. data/lib/gri/builtindefs.rb +211 -0
  20. data/lib/gri/cast.rb +84 -0
  21. data/lib/gri/cgraph.rb +37 -0
  22. data/lib/gri/clist.rb +163 -0
  23. data/lib/gri/collector.rb +284 -0
  24. data/lib/gri/config.rb +134 -0
  25. data/lib/gri/ds_list.rb +166 -0
  26. data/lib/gri/format_helper.rb +112 -0
  27. data/lib/gri/gparams.rb +43 -0
  28. data/lib/gri/graph.rb +239 -0
  29. data/lib/gri/grapher.rb +70 -0
  30. data/lib/gri/ldb.rb +160 -0
  31. data/lib/gri/list.rb +242 -0
  32. data/lib/gri/log.rb +140 -0
  33. data/lib/gri/loop.rb +109 -0
  34. data/lib/gri/ltsv.rb +58 -0
  35. data/lib/gri/main.rb +107 -0
  36. data/lib/gri/mlog.rb +22 -0
  37. data/lib/gri/mmsgpack.rb +57 -0
  38. data/lib/gri/msnmp.rb +601 -0
  39. data/lib/gri/page.rb +235 -0
  40. data/lib/gri/pcollector.rb +209 -0
  41. data/lib/gri/plugin.rb +75 -0
  42. data/lib/gri/plugin/bootstrap.rb +65 -0
  43. data/lib/gri/plugin/cisco.rb +98 -0
  44. data/lib/gri/plugin/exec_collector.rb +89 -0
  45. data/lib/gri/plugin/juniper.rb +5 -0
  46. data/lib/gri/plugin/netsnmp.rb +8 -0
  47. data/lib/gri/plugin/ucdavis.rb +176 -0
  48. data/lib/gri/plugin/writer_fluentd.rb +26 -0
  49. data/lib/gri/polling_unit.rb +88 -0
  50. data/lib/gri/q.rb +5 -0
  51. data/lib/gri/request.rb +29 -0
  52. data/lib/gri/rrd.rb +438 -0
  53. data/lib/gri/scheduler.rb +68 -0
  54. data/lib/gri/sgraph.rb +147 -0
  55. data/lib/gri/spark.rb +94 -0
  56. data/lib/gri/tra_collector.rb +80 -0
  57. data/lib/gri/trad.rb +170 -0
  58. data/lib/gri/updater.rb +201 -0
  59. data/lib/gri/util_daemon.rb +19 -0
  60. data/lib/gri/util_marshal.rb +13 -0
  61. data/lib/gri/utils.rb +63 -0
  62. data/lib/gri/vendor.rb +76 -0
  63. data/lib/gri/version.rb +3 -0
  64. data/lib/gri/wmain.rb +67 -0
  65. data/lib/gri/writer.rb +184 -0
  66. data/mcollector +47 -0
  67. data/test/mock.rb +60 -0
  68. data/test/root/gra/.sysdb/sysdb.txt +3 -0
  69. data/test/root/gra/testhost/.records.txt +2 -0
  70. data/test/root/if.def +2 -0
  71. data/test/root/test.conf +4 -0
  72. data/test/root/testtab +9 -0
  73. data/test/root/testtab2 +2 -0
  74. data/test/root/tra/testhost/_/20130614 +20 -0
  75. data/test/test_app.rb +58 -0
  76. data/test/test_builtindefs.rb +24 -0
  77. data/test/test_collector.rb +58 -0
  78. data/test/test_config.rb +62 -0
  79. data/test/test_ds_list.rb +48 -0
  80. data/test/test_exec_collector.rb +33 -0
  81. data/test/test_format_helper.rb +68 -0
  82. data/test/test_graph.rb +69 -0
  83. data/test/test_ldb.rb +29 -0
  84. data/test/test_list.rb +65 -0
  85. data/test/test_log.rb +16 -0
  86. data/test/test_loop.rb +35 -0
  87. data/test/test_ltsv.rb +38 -0
  88. data/test/test_main.rb +19 -0
  89. data/test/test_mmsgpack.rb +27 -0
  90. data/test/test_msnmp.rb +147 -0
  91. data/test/test_page.rb +51 -0
  92. data/test/test_pcollector.rb +71 -0
  93. data/test/test_plugin.rb +62 -0
  94. data/test/test_plugin_cisco.rb +23 -0
  95. data/test/test_polling_unit.rb +58 -0
  96. data/test/test_request.rb +26 -0
  97. data/test/test_rrd.rb +53 -0
  98. data/test/test_rrd_updater.rb +139 -0
  99. data/test/test_scheduler.rb +31 -0
  100. data/test/test_tra_collector.rb +40 -0
  101. data/test/test_trad.rb +33 -0
  102. data/test/test_util_marshal.rb +17 -0
  103. data/test/test_utils.rb +15 -0
  104. data/test/test_vendor.rb +40 -0
  105. data/test/test_writer.rb +33 -0
  106. data/test/unittest_helper.rb +27 -0
  107. metadata +208 -0
@@ -0,0 +1,201 @@
1
+ require 'fileutils'
2
+
3
+ require 'gri/builtindefs'
4
+ require 'gri/rrd'
5
+ require 'gri/utils'
6
+ require 'gri/config'
7
+
8
+ module GRI
9
+ class Updater
10
+ include Utils
11
+ attr_reader :options
12
+
13
+ def self.get_tag_ary description
14
+ unless @tag_pats
15
+ @tag_pats = (pats = GRI::Config.getvar 'tag-rule') ?
16
+ pats.map {|patline| pat, *remain =
17
+ patline.scan(/^\/([^\/]+)\/\s+(\S+)\s+(\S+)\s+(\S+)/)[0] #/
18
+ [Regexp.new(pat), *remain]} : []
19
+ end
20
+ @tag_pats.map {|re, group, subdir, descr_v|
21
+ if re === description
22
+ m = $~.to_a
23
+ if group =~ /^\$(\d+)(\.\w+)?/
24
+ group = m[$1.to_i].dup
25
+ group.downcase! if $2 == '.downcase'
26
+ end
27
+ if subdir =~ /^\$(\d+)(\.\w+)?/
28
+ subdir = m[$1.to_i].dup
29
+ subdir.downcase! if $2 == '.downcase'
30
+ end
31
+ if descr_v =~ /^\$(\d+)/
32
+ descr_v = m[$1.to_i]
33
+ end
34
+ [group, subdir, descr_v]
35
+ else
36
+ nil
37
+ end
38
+ }.compact
39
+ end
40
+
41
+ def initialize options={}
42
+ @options = options
43
+ @interval = options[:step] || options[:interval] || 300
44
+ @config = GRI::Config
45
+ end
46
+
47
+ def update time, record
48
+ end
49
+ end
50
+
51
+ class RRDUpdater < Updater
52
+ attr_reader :rrd, :key
53
+ attr_accessor :rrd_class
54
+
55
+ def initialize options={}
56
+ super
57
+ @tagrrds = {}
58
+ end
59
+
60
+ def create_rrd path, time, interval, ds_specs, rra_specs
61
+ ds_args, @record_keys = mk_ds_args ds_specs, interval
62
+ rra_args = rra_specs || mk_rra_args
63
+ @rrd_args = ds_args + rra_args
64
+ rrd = (@rrd_class || RRD).new @options[:rrdcached_address],
65
+ @options[:base_dir]
66
+ rrd.set_create_args path, (time - interval), interval, *@rrd_args
67
+ rrd
68
+ end
69
+
70
+ def mk_ds_args ds_specs, interval
71
+ ds_args = []
72
+ record_keys = []
73
+ n = 0
74
+ for spec_line in ds_specs
75
+ key, dsname, dst = spec_line.split /,/
76
+ heartbeat = interval * ((dst == 'DERIVE' or dst == 'COUNTER') ? 2.5 : 2)
77
+ key = key[1..-1].intern if key[0] == ?:
78
+ record_keys.push key
79
+ ds_args.push "DS:#{dsname}:#{dst}:#{heartbeat.to_i}:U:U"
80
+ n += 1
81
+ end
82
+ return ds_args, record_keys
83
+ end
84
+
85
+ def mk_rra_args
86
+ rra_args = []
87
+ for cf in ['average', 'max', 'min']
88
+ optrraname = "rra-#{@options[:data_name]}-#{cf}"
89
+ if (optrra = @config.getvar optrraname)
90
+ for line in optrra
91
+ steps, rows = line.split
92
+ rra_args.push "RRA:#{cf.upcase}:0.5:#{steps}:#{rows}"
93
+ end
94
+ else
95
+ optrraname = 'rra-' + cf
96
+ optrra = @config.getvar optrraname
97
+ if optrra
98
+ for line in optrra
99
+ steps, rows = line.split
100
+ rra_args.push "RRA:#{cf.upcase}:0.5:#{steps}:#{rows}"
101
+ end
102
+ end
103
+ end
104
+ end
105
+ rra_args.size.zero? ? default_rra_args : rra_args
106
+ end
107
+
108
+ def default_rra_args
109
+ ['RRA:AVERAGE:0.5:12:9000', 'RRA:MAX:0.5:1:20000',
110
+ 'RRA:MAX:0.5:12:9000', 'RRA:MAX:0.5:144:2000']
111
+ end
112
+
113
+ def mk_key options
114
+ unless (key = options[:key])
115
+ data_name = options[:data_name]
116
+ key = (Numeric === (index = options[:index])) ?
117
+ "#{data_name}#{index}" : "#{data_name}_#{index}"
118
+ end
119
+ key
120
+ end
121
+
122
+ def mk_path options
123
+ host = options[:host]
124
+ dir = options[:dir] || options[:gra_dir] + '/' + host
125
+ dkey = mk_key options
126
+ "#{dir}/#{host}_#{dkey}.rrd"
127
+ end
128
+
129
+ def update time, record
130
+ unless @rrd
131
+ data_name = options[:data_name]
132
+ @specs = DEFS.get_specs data_name
133
+ return unless @specs # unknown data_name
134
+ return unless @specs[:ds]
135
+ #if (index_key = (@specs[:index_key] || @specs[:named_index]) and
136
+ # index = record[index_key])
137
+ # options[:index] = key_encode index
138
+ # options.delete :key
139
+ #end
140
+ @key = mk_key options
141
+ return if (ex_proc = @specs[:exclude?]) and ex_proc.call(record)
142
+ path = mk_path options
143
+ ds_specs = @specs[:ds]
144
+ return if !ds_specs or ds_specs.empty?
145
+ @rrd = create_rrd path, time, (@interval || 300),
146
+ ds_specs, @specs[:rra]
147
+ end
148
+ data = @record_keys.map {|key| record[key]}
149
+ s = "#{time.to_i}:#{mk_update_str data}"
150
+ puts " update #{@key} #{s}" if record['_d']
151
+ @rrd.buffered_update s
152
+
153
+ if (prop = @specs[:prop]) and (descr_k = prop[:description]) and
154
+ (description = record[descr_k]) and !description.empty?
155
+ for group, subdir, descr_v in Updater.get_tag_ary(description)
156
+ unless (tagrrd = @tagrrds[group + '/' + subdir])
157
+ tagrrd = create_tagrrd group, subdir, descr_v, record
158
+ @tagrrds[group + '/' + subdir] = tagrrd
159
+ end
160
+ tagrrd.buffered_update s
161
+ end
162
+ end
163
+ end
164
+
165
+ def mk_update_str data
166
+ data.map {|item|
167
+ if item =~ /\A0x[\da-f]+\z/i
168
+ Integer(item)
169
+ elsif item == '' or item == nil or
170
+ (item.kind_of?(Float) and not(item.finite?)) or
171
+ (item.kind_of?(String) and item !~ /\A[-+e\.\d]+$/i)
172
+ 'U'
173
+ else
174
+ item
175
+ end
176
+ }.join(':')
177
+ end
178
+
179
+ def create_tagrrd group, subdir, descr_v, record
180
+ grp_dir = "#{options[:gra_dir]}/#{group}"
181
+ Dir.mkdir grp_dir unless File.exist? grp_dir
182
+ tag_dir = "#{grp_dir}/#{subdir}"
183
+ Dir.mkdir tag_dir unless File.exist? tag_dir
184
+ open(tag_dir + '/.description', 'w') {|f| f.puts descr_v}
185
+
186
+ time = record['_time']
187
+ path = "#{tag_dir}/#{@options[:host]}_#{@key}.rrd"
188
+ tagrrd = (@rrd_class ||RRD).new @options[:rrdcached_address],
189
+ @options[:base_dir]
190
+ tagrrd.set_create_args path, (time - @interval), @interval, *@rrd_args
191
+ tagrrd
192
+ end
193
+
194
+ def close
195
+ if @rrd
196
+ @rrd.flush_buffer
197
+ end
198
+ @tagrrds.each_value {|tagrrd| tagrrd.flush_buffer}
199
+ end
200
+ end
201
+ end
@@ -0,0 +1,19 @@
1
+ module Process
2
+ class << self
3
+ unless method_defined?(:daemon)
4
+ def daemon(nochdir = nil, noclose = nil)
5
+ exit!(0) if Process.fork
6
+ Process.setsid
7
+ exit!(0) if Process.fork
8
+ Dir.chdir("/") unless nochdir
9
+ unless noclose
10
+ #File.umask(0)
11
+ STDIN.reopen("/dev/null", "r")
12
+ STDOUT.reopen("/dev/null", "w")
13
+ STDERR.reopen("/dev/null", "w")
14
+ end
15
+ 0
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,13 @@
1
+ def Marshal.dump_to_file obj, path
2
+ tmppath = path + ".tmp#{$$}"
3
+ open(tmppath, 'w') {|f| Marshal.dump obj, f}
4
+ File.rename tmppath, path
5
+ end
6
+
7
+ def Marshal.load_from_file path
8
+ obj = nil
9
+ if File.size? path
10
+ open(path) {|f| obj = Marshal.load(f) rescue nil}
11
+ end
12
+ obj
13
+ end
data/lib/gri/utils.rb ADDED
@@ -0,0 +1,63 @@
1
+ require 'gri/ltsv'
2
+
3
+ module GRI
4
+ module Utils
5
+ module_function
6
+
7
+ def load_records dir
8
+ values = LTSV.load_from_file dir + '/.records.txt'
9
+ values.inject({}) {|h, v| h[v['_key']] = v; h}
10
+ end
11
+
12
+ def search_records dirs, host
13
+ for dir in dirs
14
+ path = "#{dir}/#{host}/.records.txt"
15
+ if File.exist? path
16
+ values = LTSV.load_from_file path
17
+ rh = values.inject({}) {|h, v| (k = v['_key']) and h[k] = v; h}
18
+ return [dir, rh]
19
+ end
20
+ end
21
+ nil
22
+ end
23
+
24
+ def get_prop record
25
+ h = {}
26
+ data_name, index = parse_key record['_key']
27
+ record['_index'] = index
28
+ if data_name and (specs = DEFS.get_specs data_name) and specs[:prop]
29
+ specs[:prop].each {|k1, k2| h[k1] = record[k2] if record[k2]}
30
+ h[:name] ||= specs[:prop][:name]
31
+ end
32
+ h
33
+ end
34
+
35
+ def update_ltsv_file path, key, other
36
+ if File.exist? path
37
+ values = LTSV.load_from_file path
38
+ nvalues = values.inject({}) {|h, v| h[v[key]] = v; h}
39
+ nvalues.merge! other
40
+ else
41
+ nvalues = other
42
+ end
43
+ LTSV.dump_to_file nvalues, path
44
+ end
45
+
46
+ def parse_key s
47
+ s.to_s.scan(/\A([^_\d]*)(?:_?(.*))/).first
48
+ end
49
+
50
+ def parse_host_key s
51
+ s.to_s.scan(/\A([-\.A-Za-z0-9]+)_([^_\d]*)(?:_?(.*))/).first
52
+ end
53
+
54
+ def url_encode(s)
55
+ s.to_s.gsub(/[^a-zA-Z0-9_\-.]/n){ sprintf("%%%02X", $&.unpack("C")[0]) }
56
+ end
57
+
58
+ def key_encode s
59
+ s.to_s.tr(':/ =', '\-\-__').gsub(/[^-a-zA-Z0-9_.]/n) { #/
60
+ "%02X"%$&.unpack('C').first}
61
+ end
62
+ end
63
+ end
data/lib/gri/vendor.rb ADDED
@@ -0,0 +1,76 @@
1
+ module GRI
2
+ class Vendor
3
+ DEFS = {}
4
+ class <<DEFS
5
+ alias :update :merge!
6
+ end
7
+
8
+ attr_reader :name, :options
9
+
10
+ def self.check sysinfo, options={}
11
+ vdefs = nil
12
+ if !(sysobjectid = sysinfo['sysObjectID']) or sysobjectid.size < 5
13
+ else
14
+ sysoid = BER.dec_oid(sysobjectid[5..-1])
15
+ sysoid.size.downto(1) {|n|
16
+ sysoidkey = sysoid[0, n].map {|noid| noid.to_s}.join('.')
17
+ if (vdefs = self::DEFS[sysoidkey])
18
+ if Array === vdefs
19
+ vname, voptions, f_re, v_re = vdefs
20
+ vdefs = {:name=>vname, :options=>voptions,
21
+ :firm_re=>f_re, :version_re=>v_re}
22
+ end
23
+ break
24
+ end
25
+ }
26
+ end
27
+ vdefs ||= {:name=>'unknown'}
28
+ Vendor.new vdefs, sysinfo, options
29
+ end
30
+
31
+ def initialize vdefs, sysinfo, options
32
+ @name = vdefs[:name]
33
+ @sysinfo = sysinfo
34
+ @options = {'ver'=>'1', 'interfaces'=>true, 'ipaddr'=>true}
35
+ @options.merge! vdefs[:options] if vdefs[:options]
36
+ @options.merge! options if options
37
+ class <<@options
38
+ def set_unless_defined k, v=true
39
+ self[k] = v unless self.has_key? k
40
+ end
41
+ end
42
+ sysinfo['_firm'] = get_firm vdefs[:firm_re], sysinfo
43
+ sysinfo['_ver'] = get_ver vdefs[:version_re], sysinfo
44
+ sysinfo['_sysdescr'] = sysinfo['sysDescr']
45
+ if (cb = vdefs[:after_initialize])
46
+ cb.call @sysinfo, @options
47
+ end
48
+ end
49
+
50
+ def get_firm f_re, sysinfo
51
+ sysdescr = sysinfo['sysDescr'] || '?'
52
+ if f_re
53
+ match = f_re.match sysdescr
54
+ match ? match[1] : '?'
55
+ else
56
+ (f = sysdescr.scan(/\A([-\w]+)/).first) ? f[0] : '?'
57
+ end
58
+ end
59
+
60
+ def get_ver v_re, sysinfo
61
+ sysdescr = sysinfo['sysDescr'] || '?'
62
+ if v_re
63
+ match = v_re.match sysdescr
64
+ match ? match[1] : '?'
65
+ else
66
+ tmp, = sysdescr.scan(/(\d+\.[\.\d]+)/).first
67
+ tmp || '?'
68
+ end
69
+ end
70
+
71
+ def get_punits
72
+ units = PollingUnit.all_units
73
+ options.keys.map {|k| options[k] ? units[k] : nil}.compact
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,3 @@
1
+ module GRI
2
+ VERSION = "10.0.0"
3
+ end
data/lib/gri/wmain.rb ADDED
@@ -0,0 +1,67 @@
1
+ require 'optparse'
2
+
3
+ require 'gri/msnmp'
4
+ require 'gri/builtindefs'
5
+ require 'gri/vendor'
6
+ require 'gri/plugin'
7
+
8
+ module GRI
9
+ class WMain
10
+ attr_writer :app
11
+
12
+ def initialize app=nil
13
+ @app = app
14
+ config_path = ENV['GRI_CONFIG_PATH'] || Config::DEFAULT_PATH
15
+ Config.init config_path
16
+ end
17
+
18
+ def run opts=nil
19
+ opts ||= {:server=>'webrick', :Port=>5125}
20
+ optparser = optparse opts
21
+ optparser.parse!
22
+ root_dir = Config['root-dir'] ||= Config::ROOT_PATH
23
+ plugin_dirs = Config.getvar('plugin-dir') || [root_dir + '/plugin']
24
+ Plugin.load_plugins plugin_dirs, Config
25
+
26
+ app = @app
27
+ builder = Rack::Builder.new {
28
+ use Rack::Static, :urls=>['/css', '/js'], :root=>app.public_dir
29
+ run app
30
+ }
31
+ if ENV['GATEWAY_INTERFACE']
32
+ Rack::Handler::CGI.run builder
33
+ else
34
+ if Rack.const_defined? :Server
35
+ opts[:app] = builder
36
+ Rack::Server.new(opts).start
37
+ else
38
+ Rack::Handler::WEBrick.run builder, opts
39
+ end
40
+ end
41
+ end
42
+
43
+ def optparse opts
44
+ op = OptionParser.new
45
+ op.on('--debug') {$debug = true; STDOUT.sync = true}
46
+ op.on('-d', '--daemonize') {opts[:daemonize] = true}
47
+ op.on('-h', '--host HOST') {|arg| opts[:Host] = arg}
48
+ op.on('-p', '--port PORT', Integer) {|arg| opts[:Port] = arg}
49
+ op.on('-s', '--server SERVER') {|arg| opts[:server] = arg}
50
+ class <<op
51
+ attr_accessor :options
52
+ end
53
+ op.options = opts
54
+ op
55
+ end
56
+ end
57
+ end
58
+
59
+ module Rack
60
+ class Static
61
+ alias :call0 :call
62
+ def call env
63
+ env['PATH_INFO'] ||= '/'
64
+ call0 env
65
+ end
66
+ end
67
+ end