smart_proxy_monitoring 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,97 @@
1
+ require 'thread'
2
+
3
+ module ::Proxy::Monitoring::Icinga2
4
+ class MonitoringResult < Proxy::HttpRequest::ForemanRequest
5
+ def push_result(result)
6
+ send_request(request_factory.create_post('api/monitoring_results', result))
7
+ end
8
+ end
9
+
10
+ class Icinga2ResultUploader
11
+ include ::Proxy::Log
12
+ include ::Proxy::Monitoring::Icinga2::Common
13
+
14
+ attr_reader :semaphore
15
+
16
+ def initialize(queue)
17
+ @queue = queue.queue
18
+ @semaphore = Mutex.new
19
+ end
20
+
21
+ def upload
22
+ while change = @queue.pop
23
+ with_event_counter('Icinga2 Result Uploader') do
24
+ symbolize_keys_deep!(change)
25
+
26
+ change[:timestamp] = change[:check_result][:schedule_end] if change.key?(:check_result)
27
+ if change.key?(:downtime) && change[:downtime].is_a?(Hash)
28
+ change[:host] = change[:downtime][:host_name] if change[:host].nil? || change[:host].empty?
29
+ change[:service] = change[:downtime][:service_name] if change[:service].nil? || change[:service].empty?
30
+ end
31
+
32
+ if change[:service].nil? || change[:service].empty?
33
+ change[:service] = 'Host Check'
34
+ end
35
+
36
+ case change[:type]
37
+ when 'StateChange'
38
+ transformed = { result: change[:check_result][:state] }
39
+ when 'AcknowledgementSet'
40
+ transformed = { acknowledged: true }
41
+ when 'AchnowledgementCleared'
42
+ transformed = { acknowledged: false }
43
+ when 'DowntimeTriggered'
44
+ transformed = { downtime: true }
45
+ when 'DowntimeRemoved'
46
+ transformed = { downtime: false }
47
+ when '_parsed'
48
+ transformed = change.dup.reject! { |k, _v| k == :type }
49
+ else
50
+ next
51
+ end
52
+ transformed.merge!(
53
+ host: change[:host],
54
+ service: change[:service],
55
+ timestamp: change[:timestamp]
56
+ )
57
+ begin
58
+ MonitoringResult.new.push_result(transformed.to_json)
59
+ rescue Errno::ECONNREFUSED => e
60
+ logger.error "Foreman refused connection when tried to upload monitoring result: #{e.message}"
61
+ sleep 10
62
+ rescue => e
63
+ logger.error "Error while uploading monitoring results to Foreman: #{e.message}"
64
+ sleep 1
65
+ retry
66
+ end
67
+ end
68
+ end
69
+ end
70
+
71
+ def start
72
+ @thread = Thread.new { upload }
73
+ @thread.abort_on_exception = true
74
+ @thread
75
+ end
76
+
77
+ def stop
78
+ @thread.terminate unless @thread.nil?
79
+ end
80
+
81
+ private
82
+
83
+ def symbolize_keys_deep!(h)
84
+ h.keys.each do |k|
85
+ ks = k.to_sym
86
+ h[ks] = h.delete k
87
+ symbolize_keys_deep! h[ks] if h[ks].is_a? Hash
88
+ end
89
+ end
90
+
91
+ def add_domain(host)
92
+ domain = Proxy::Monitoring::Plugin.settings.strip_domain
93
+ host = "#{host}#{domain}" unless domain.nil?
94
+ host
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,9 @@
1
+ require 'thread'
2
+
3
+ module ::Proxy::Monitoring::Icinga2
4
+ class Icinga2UploadQueue
5
+ def queue
6
+ @queue ||= Queue.new
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,21 @@
1
+ module ::Proxy::Monitoring::Icinga2
2
+ module Common
3
+ private
4
+
5
+ def with_event_counter(log_prefix, interval_count = 100, interval_seconds = 60)
6
+ semaphore.synchronize do
7
+ @counter ||= 0
8
+ @timer ||= Time.now
9
+ if @counter >= interval_count || (Time.now - @timer) > interval_seconds
10
+ status = "#{log_prefix}: Observed #{@counter} events in the last #{(Time.now - @timer).round(2)} seconds."
11
+ status += " #{@queue.length} items queued. #{@queue.num_waiting} threads waiting." unless @queue.nil?
12
+ logger.info status
13
+ @timer = Time.now
14
+ @counter = 0
15
+ end
16
+ @counter += 1
17
+ end
18
+ yield
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,68 @@
1
+ module Proxy::Monitoring::Icinga2
2
+ class Provider < ::Proxy::Monitoring::Provider
3
+ include Proxy::Log
4
+ include Proxy::Util
5
+
6
+ def remove_host(host)
7
+ request_url = "/objects/hosts/#{host}?cascade=1"
8
+
9
+ result = with_errorhandling("Remove #{host}") do
10
+ Icinga2Client.delete(request_url)
11
+ end
12
+ result.to_json
13
+ end
14
+
15
+ def remove_downtime_host(host, author, comment)
16
+ request_url = "/actions/remove-downtime?type=Host&filter=host.name==\"#{host}\"\&\&author==\"#{author}\"\&\&comment=\"#{comment}\""
17
+ data = {}
18
+
19
+ result = with_errorhandling("Remove downtime from #{host}") do
20
+ Icinga2Client.post(request_url, data.to_json)
21
+ end
22
+ result.to_json
23
+ end
24
+
25
+ def set_downtime_host(host, author, comment, start_time, end_time)
26
+ request_url = "/actions/schedule-downtime?type=Host&filter=host.name==\"#{host}\""
27
+ data = {
28
+ 'author' => author,
29
+ 'comment' => comment,
30
+ 'start_time' => start_time,
31
+ 'end_time' => end_time,
32
+ 'duration' => 1000
33
+ }
34
+
35
+ result = with_errorhandling("Set downtime on #{host}") do
36
+ Icinga2Client.post(request_url, data.to_json)
37
+ end
38
+ result.to_json
39
+ end
40
+
41
+ private
42
+
43
+ def with_errorhandling(action)
44
+ response = yield
45
+ logger.debug "Monitoring - Action successful: #{action}"
46
+ result = JSON.parse(response.body)
47
+ unless result.key?('results')
48
+ logger.error "Invalid Icinga result or result with errors: #{result.inspect}"
49
+ raise Proxy::Monitoring::Error.new("Icinga server at #{::Proxy::Monitoring::Icinga2::Plugin.settings.server} returned an invalid result.")
50
+ end
51
+ unless result['results'].first
52
+ raise Proxy::Monitoring::NotFound.new("Icinga server at #{::Proxy::Monitoring::Icinga2::Plugin.settings.server} returned an empty result.")
53
+ end
54
+ if result['results'][0]['code'] != 200
55
+ raise Proxy::Monitoring::Error.new("Icinga server at #{::Proxy::Monitoring::Icinga2::Plugin.settings.server} returned an error: #{result['results'][0]['code']} #{result['results'][0]['status']}")
56
+ end
57
+ result
58
+ rescue JSON::ParserError => e
59
+ raise Proxy::Monitoring::Error.new("Icinga server at #{::Proxy::Monitoring::Icinga2::Plugin.settings.server} returned invalid JSON: '#{e.message}'")
60
+ rescue RestClient::Exception => e
61
+ raise Proxy::Monitoring::Error.new("Icinga server at #{::Proxy::Monitoring::Icinga2::Plugin.settings.server} returned an error: '#{e.response}'")
62
+ rescue Errno::ECONNREFUSED => e
63
+ raise Proxy::Monitoring::ConnectionError.new("Icinga server at #{::Proxy::Monitoring::Icinga2::Plugin.settings.server} is not responding")
64
+ rescue SocketError => e
65
+ raise Proxy::Monitoring::ConnectionError.new("Icinga server '#{::Proxy::Monitoring::Icinga2::Plugin.settings.server}' is unknown")
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,16 @@
1
+ module ::Proxy::Monitoring::Icinga2
2
+ class Plugin < ::Proxy::Provider
3
+ plugin :monitoring_icinga2, ::Proxy::Monitoring::VERSION
4
+
5
+ default_settings server: 'localhost'
6
+ default_settings api_port: '5665'
7
+ default_settings verify_ssl: true
8
+
9
+ requires :monitoring, ::Proxy::Monitoring::VERSION
10
+
11
+ start_services :icinga2_initial_importer, :icinga2_api_observer, :icinga2_result_uploader
12
+
13
+ load_classes ::Proxy::Monitoring::Icinga2::PluginConfiguration
14
+ load_dependency_injection_wirings ::Proxy::Monitoring::Icinga2::PluginConfiguration
15
+ end
16
+ end
@@ -0,0 +1,28 @@
1
+ module ::Proxy::Monitoring::Icinga2
2
+ class PluginConfiguration
3
+ def load_classes
4
+ require 'smart_proxy_monitoring_common/monitoring_common'
5
+ require 'smart_proxy_monitoring_icinga2/monitoring_icinga2_main'
6
+ require 'smart_proxy_monitoring_icinga2/monitoring_icinga2_common'
7
+ require 'smart_proxy_monitoring_icinga2/icinga2_upload_queue'
8
+ require 'smart_proxy_monitoring_icinga2/icinga2_client'
9
+ require 'smart_proxy_monitoring_icinga2/icinga2_initial_importer'
10
+ require 'smart_proxy_monitoring_icinga2/icinga2_api_observer'
11
+ require 'smart_proxy_monitoring_icinga2/icinga2_result_uploader'
12
+ end
13
+
14
+ def load_dependency_injection_wirings(container_instance, settings)
15
+ container_instance.dependency :monitoring_provider, lambda { ::Proxy::Monitoring::Icinga2::Provider.new }
16
+ container_instance.singleton_dependency :icinga2_upload_queue, lambda { ::Proxy::Monitoring::Icinga2::Icinga2UploadQueue.new }
17
+ container_instance.singleton_dependency :icinga2_api_observer, (lambda do
18
+ ::Proxy::Monitoring::Icinga2::Icinga2ApiObserver.new(container_instance.get_dependency(:icinga2_upload_queue))
19
+ end)
20
+ container_instance.singleton_dependency :icinga2_result_uploader, (lambda do
21
+ ::Proxy::Monitoring::Icinga2::Icinga2ResultUploader.new(container_instance.get_dependency(:icinga2_upload_queue))
22
+ end)
23
+ container_instance.singleton_dependency :icinga2_initial_importer, (lambda do
24
+ ::Proxy::Monitoring::Icinga2::Icinga2InitialImporter.new(container_instance.get_dependency(:icinga2_upload_queue))
25
+ end)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,2 @@
1
+ require 'smart_proxy_monitoring_icinga2/plugin_configuration'
2
+ require 'smart_proxy_monitoring_icinga2/monitoring_icinga2_plugin'
@@ -0,0 +1,11 @@
1
+ ---
2
+ # Collect Monitoring information
3
+ :enabled: true
4
+
5
+ # Valid providers:
6
+ # monitoring_icinga2 (Icinga 2 API, default)
7
+ #:use_provider: monitoring_icinga2
8
+
9
+ # Strip this part of the domain when communicating with the Monitoring server
10
+ # and add it when communicating with Foreman
11
+ # :strip_domain: .localdomain
@@ -0,0 +1,17 @@
1
+ ---
2
+ # Collect Monitoring information via Icinga 2 API
3
+ :enabled: true
4
+
5
+ # The FQDN or IP address of the Icinga 2 server (if using IP address also set verify_ssl to false)
6
+ :server: icinga2.localdomain
7
+ # The CA certificate used by Icinga 2 (typically located on the server at /etc/icinga2/pki/ca.crt)
8
+ :api_cacert: /usr/share/foreman-proxy/monitoring/ca.crt
9
+ # The name of API User
10
+ :api_user: foreman
11
+ # The certificate issued on the client_cn attribute of the API User and the corresponding key
12
+ :api_usercert: /usr/share/foreman-proxy/monitoring/foreman.crt
13
+ :api_userkey: /usr/share/foreman-proxy/monitoring/foreman.key
14
+ # The password from the password attribute of the API User (if not using certificates)
15
+ #:api_password: foreman
16
+ # SSL Verfification mode (boolean value)
17
+ :verify_ssl: true
metadata ADDED
@@ -0,0 +1,142 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: smart_proxy_monitoring
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Timo Goebel
8
+ - Dirk Goetz
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2016-08-19 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rest-client
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: '0'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: '0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: json
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: rake
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: mocha
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: test-unit
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ description: Monitoring plug-in for Foreman's smart proxy
85
+ email:
86
+ - timo.goebel@dm.de
87
+ - dirk.goetz@netways.de
88
+ executables: []
89
+ extensions: []
90
+ extra_rdoc_files:
91
+ - README.md
92
+ - LICENSE
93
+ files:
94
+ - LICENSE
95
+ - README.md
96
+ - bundler.d/monitoring.rb
97
+ - lib/smart_proxy_monitoring.rb
98
+ - lib/smart_proxy_monitoring/configuration_loader.rb
99
+ - lib/smart_proxy_monitoring/dependency_injection.rb
100
+ - lib/smart_proxy_monitoring/monitoring_api.rb
101
+ - lib/smart_proxy_monitoring/monitoring_http_config.ru
102
+ - lib/smart_proxy_monitoring/monitoring_plugin.rb
103
+ - lib/smart_proxy_monitoring/version.rb
104
+ - lib/smart_proxy_monitoring_common/monitoring_common.rb
105
+ - lib/smart_proxy_monitoring_icinga2.rb
106
+ - lib/smart_proxy_monitoring_icinga2/icinga2_api_observer.rb
107
+ - lib/smart_proxy_monitoring_icinga2/icinga2_client.rb
108
+ - lib/smart_proxy_monitoring_icinga2/icinga2_initial_importer.rb
109
+ - lib/smart_proxy_monitoring_icinga2/icinga2_result_uploader.rb
110
+ - lib/smart_proxy_monitoring_icinga2/icinga2_upload_queue.rb
111
+ - lib/smart_proxy_monitoring_icinga2/monitoring_icinga2_common.rb
112
+ - lib/smart_proxy_monitoring_icinga2/monitoring_icinga2_main.rb
113
+ - lib/smart_proxy_monitoring_icinga2/monitoring_icinga2_plugin.rb
114
+ - lib/smart_proxy_monitoring_icinga2/plugin_configuration.rb
115
+ - settings.d/monitoring.yml.example
116
+ - settings.d/monitoring_icinga2.yml.example
117
+ homepage: http://github.com/theforeman/smart_proxy_monitoring
118
+ licenses:
119
+ - GPLv3
120
+ metadata: {}
121
+ post_install_message:
122
+ rdoc_options: []
123
+ require_paths:
124
+ - lib
125
+ required_ruby_version: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - ">="
128
+ - !ruby/object:Gem::Version
129
+ version: '0'
130
+ required_rubygems_version: !ruby/object:Gem::Requirement
131
+ requirements:
132
+ - - ">="
133
+ - !ruby/object:Gem::Version
134
+ version: '0'
135
+ requirements: []
136
+ rubyforge_project:
137
+ rubygems_version: 2.4.5
138
+ signing_key:
139
+ specification_version: 4
140
+ summary: Monitoring plug-in for Foreman's smart proxy
141
+ test_files: []
142
+ has_rdoc: