zabbix_receiver 0.0.1 → 0.0.2

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 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