zabbix_receiver 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1db84526dbaff0fd80bb4cef61161ceb0074ba7a
4
- data.tar.gz: c303aa0a685791c419d8a77610f8408974075701
3
+ metadata.gz: b9b18abfc85a6f0c988942665b7764545131a0e5
4
+ data.tar.gz: e4ff56edf7bbfd4ba960881f25db18ab9156cbda
5
5
  SHA512:
6
- metadata.gz: d15a574d116ca65dee81029ab96f8d92f747654bf2625e77935f5b384ce1e29ae7e87472a7afb78365f98859c450f47f8944fe50c04421e0585d4eced63ba096
7
- data.tar.gz: de862f50067ed77859ddb88751c00526cfca9c368b31e7a878d749137a92d8a9f2619fd26a8fa4feb9ac3bfea640bba194d876fb918e733cf00171fb327fc48e
6
+ metadata.gz: 39fcb740b7dc74ea719ac4dc330e52f28aa9202db534669527eb1b4b7f80aee4d3319f49dbdf6808518fe9a0d091c369d092c5cdbf113275e562e745beba5356
7
+ data.tar.gz: 4d755551630c848207a7174b93804c9ef63244197666da6d7109a597e21d41bc7df077a8e372e641d616d4d00950641dc7a2d3df2986b4a5d158810db22023ea
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require 'zabbix_receiver'
3
+ ZabbixReceiver::CLI.start(ARGV)
@@ -0,0 +1,70 @@
1
+ require 'zabbix_receiver'
2
+ require 'serverengine'
3
+ require 'optparse'
4
+
5
+ module ZabbixReceiver
6
+ class CLI
7
+ REQUIRED_OPTIONS = %i(daemonize workers proxy_to_host proxy_to_port bind port)
8
+
9
+ def self.start(argv)
10
+ self.new(argv).start
11
+ end
12
+
13
+ def initialize(argv)
14
+ load_options(argv)
15
+ end
16
+
17
+ def start
18
+ options = {
19
+ worker_type: 'process',
20
+ }.merge(@options)
21
+
22
+ se = ServerEngine.create(Server, Worker, options)
23
+ se.run
24
+ end
25
+
26
+ private
27
+
28
+ def load_options(argv)
29
+ argv_for_main, argv_for_output = argv.slice_before('--').to_a
30
+ argv_for_output.shift
31
+
32
+ @options = {
33
+ daemonize: false,
34
+ workers: 1,
35
+ bind: '0.0.0.0',
36
+ port: 10051,
37
+ proxy_to_port: 10051,
38
+ to: 'stdout',
39
+ }
40
+
41
+ parser = OptionParser.new
42
+ parser.on('--daemonize') {|v| @options[:daemonize] = true }
43
+ parser.on('--log=VAL', 'default: STDERR') {|v| @options[:log] = v }
44
+ parser.on('--pid-path=VAL') {|v| @options[:pid_path] = v }
45
+ parser.on('--workers=VAL') {|v| @options[:worker] = v }
46
+ parser.on('--bind=VAL') {|v| @options[:bind] = v }
47
+ parser.on('--port=VAL') {|v| @options[:port] = v }
48
+ parser.on('--proxy-to-host=VAL') {|v| @options[:proxy_to_host] = v }
49
+ parser.on('--proxy-to-port=VAL') {|v| @options[:proxy_to_port] = v }
50
+ parser.on('--to=VAL') {|v| @options[:to] = v }
51
+ parser.on('--log-level=VAL') {|v| @options[:log_level] = v }
52
+ parser.parse!(argv_for_main)
53
+
54
+ REQUIRED_OPTIONS.each do |key|
55
+ unless @options.has_key?(key)
56
+ raise "--#{key.to_s.split('_').join('-')} option is required."
57
+ end
58
+ end
59
+
60
+ @options[:output_class] = output_class
61
+ @options[:output_options] = @options[:output_class].parse_options(argv_for_output)
62
+ end
63
+
64
+ def output_class
65
+ require "zabbix_receiver/output/#{@options[:to]}"
66
+ class_name = @options[:to].split('_').map {|v| v.capitalize }.join
67
+ ZabbixReceiver::Output.const_get(class_name)
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,16 @@
1
+ module ZabbixReceiver
2
+ module Output
3
+ class Stdout
4
+ def self.parse_options(argv)
5
+ {}
6
+ end
7
+
8
+ def initialize(logger, options)
9
+ end
10
+
11
+ def receive_sender_data(data)
12
+ puts data
13
+ end
14
+ end
15
+ end
16
+ end
@@ -1,110 +1,14 @@
1
- require 'json'
2
- require 'logger'
3
-
4
1
  module ZabbixReceiver
5
- class Server
6
- ZABBIX_HEADER = "ZBXD\x01"
7
-
8
- def initialize(options = {})
9
- @options = {
10
- proxy_to: {
11
- port: 10051,
12
- },
13
- }.merge(options)
14
-
15
- validate_options
16
-
17
- @logger = options[:logger] || Logger.new(StringIO.new)
18
-
19
- @blocks_on_receive_sender_data = []
20
- end
21
-
22
- def on_receive_sender_data(&block)
23
- @blocks_on_receive_sender_data << block
24
- end
25
-
26
- def start(address, port)
27
- server = TCPServer.open(address, port)
28
-
29
- while true
30
- Thread.start(server.accept) do |f|
31
- accept(f)
32
- end
33
- end
34
- end
35
-
36
- def accept(f)
37
- request = parse(f)
38
-
39
- @logger.debug "Request: #{request}"
40
-
41
- request_type = request['request']
2
+ module Server
3
+ attr_reader :sock
42
4
 
43
- case request_type
44
- when 'active checks'
45
- proxy_request(f)
46
- when 'sender data'
47
- @blocks_on_receive_sender_data.each do |block|
48
- block.call(request)
49
- end
5
+ def before_run
6
+ bind = config[:bind]
7
+ port = config[:port]
50
8
 
51
- count = request['data'].size
52
-
53
- respond_with(f, {
54
- "response" => "success",
55
- "info" => "Processed #{count} Failed 0 Total #{count} Seconds spent 0.000000"
56
- })
57
- else
58
- @logger.error "Unknown request type (#{request_type})"
59
- end
60
- ensure
61
- f && f.close
62
- end
63
-
64
- def proxy_request(f)
65
- f.seek(0)
66
-
67
- socket = TCPSocket.open(
68
- @options[:proxy_to][:host],
69
- @options[:proxy_to][:port],
70
- )
71
- socket.write(f.read)
72
- f.write(socket.read)
73
- ensure
74
- socket && socket.close
75
- end
76
-
77
- private
78
-
79
- def parse(f)
80
- f.seek(0)
81
-
82
- unless f.read(5) == ZABBIX_HEADER
83
- @logger.error "Invalid Zabbix request"
84
- return
85
- end
86
-
87
- length = f.read(8).unpack('q').first
88
- body = f.read
89
- unless body.size == length
90
- @logger.error "Length mismatch"
91
- return
92
- end
93
-
94
- JSON.parse(body)
95
- end
96
-
97
- def respond_with(f, payload)
98
- payload = payload.to_json
99
- f.write(ZABBIX_HEADER + [payload.bytesize].pack('q') + payload)
100
- end
9
+ logger.info "Listening on #{bind}:#{port}..."
101
10
 
102
- def validate_options
103
- [:host, :port].each do |k|
104
- unless @options[:proxy_to][k]
105
- raise "options[:proxy_to][:#{k}] is required."
106
- end
107
- end
11
+ @sock = TCPServer.open(bind, port)
108
12
  end
109
13
  end
110
14
  end
@@ -1,3 +1,3 @@
1
1
  module ZabbixReceiver
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -0,0 +1,80 @@
1
+ require 'json'
2
+
3
+ module ZabbixReceiver
4
+ module Worker
5
+ ZABBIX_HEADER = "ZBXD\x01"
6
+
7
+ def run
8
+ @output = config[:output_class].new(logger, config[:output_options])
9
+
10
+ until @stop
11
+ process(server.sock.accept)
12
+ end
13
+ end
14
+
15
+ def stop
16
+ @stop = true
17
+ end
18
+
19
+ def process(c)
20
+ request_body = c.read
21
+ request = parse(request_body)
22
+ logger.debug "Request: #{request}"
23
+ request_type = request['request']
24
+
25
+ case request_type
26
+ when 'active checks'
27
+ c.write(proxy_request(request_body))
28
+ when 'sender data'
29
+ @output.receive_sender_data(request)
30
+
31
+ count = request['data'].size
32
+
33
+ respond_with(c, {
34
+ "response" => "success",
35
+ "info" => "Processed #{count} Failed 0 Total #{count} Seconds spent 0.000000"
36
+ })
37
+ else
38
+ logger.error "Unknown request type (#{request_type})"
39
+ end
40
+ ensure
41
+ c.close
42
+ end
43
+
44
+ def proxy_request(request_body)
45
+ socket = TCPSocket.open(
46
+ config[:proxy_to_host],
47
+ config[:proxy_to_port],
48
+ )
49
+ socket.write(request_body)
50
+ socket.read
51
+ ensure
52
+ socket && socket.close
53
+ end
54
+
55
+ private
56
+
57
+ def parse(request_body)
58
+ request = StringIO.new(request_body)
59
+
60
+ unless request.read(5) == ZABBIX_HEADER
61
+ logger.error "Invalid Zabbix request"
62
+ return
63
+ end
64
+
65
+ length = request.read(8).unpack('q').first
66
+ body = request.read
67
+ unless body.size == length
68
+ logger.error "Length mismatch"
69
+ return
70
+ end
71
+
72
+ JSON.parse(body)
73
+ end
74
+
75
+ def respond_with(f, payload)
76
+ payload = payload.to_json
77
+ f.write(ZABBIX_HEADER + [payload.bytesize].pack('q') + payload)
78
+ end
79
+ end
80
+ end
@@ -1,4 +1,6 @@
1
1
  require "zabbix_receiver/server"
2
+ require "zabbix_receiver/worker"
3
+ require "zabbix_receiver/cli"
2
4
  require "zabbix_receiver/version"
3
5
 
4
6
  module ZabbixReceiver
@@ -17,6 +17,8 @@ Gem::Specification.new do |spec|
17
17
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
18
  spec.require_paths = ["lib"]
19
19
 
20
+ spec.add_development_dependency "serverengine"
21
+
20
22
  spec.add_development_dependency "bundler", "~> 1.7"
21
23
  spec.add_development_dependency "rake", "~> 10.0"
22
24
  spec.add_development_dependency "rspec"
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zabbix_receiver
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryota Arai
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-22 00:00:00.000000000 Z
11
+ date: 2015-01-23 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: serverengine
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: bundler
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -55,7 +69,8 @@ dependencies:
55
69
  description:
56
70
  email:
57
71
  - ryota-arai@cookpad.com
58
- executables: []
72
+ executables:
73
+ - zabbix_receiver
59
74
  extensions: []
60
75
  extra_rdoc_files: []
61
76
  files:
@@ -65,9 +80,13 @@ files:
65
80
  - LICENSE.txt
66
81
  - README.md
67
82
  - Rakefile
83
+ - bin/zabbix_receiver
68
84
  - lib/zabbix_receiver.rb
85
+ - lib/zabbix_receiver/cli.rb
86
+ - lib/zabbix_receiver/output/stdout.rb
69
87
  - lib/zabbix_receiver/server.rb
70
88
  - lib/zabbix_receiver/version.rb
89
+ - lib/zabbix_receiver/worker.rb
71
90
  - spec/spec_helper.rb
72
91
  - spec/zabbix_receiver/server_spec.rb
73
92
  - zabbix_receiver.gemspec