smart_proxy_monitoring 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +675 -0
- data/README.md +174 -0
- data/bundler.d/monitoring.rb +2 -0
- data/lib/smart_proxy_monitoring/configuration_loader.rb +8 -0
- data/lib/smart_proxy_monitoring/dependency_injection.rb +8 -0
- data/lib/smart_proxy_monitoring/monitoring_api.rb +77 -0
- data/lib/smart_proxy_monitoring/monitoring_http_config.ru +5 -0
- data/lib/smart_proxy_monitoring/monitoring_plugin.rb +19 -0
- data/lib/smart_proxy_monitoring/version.rb +5 -0
- data/lib/smart_proxy_monitoring.rb +4 -0
- data/lib/smart_proxy_monitoring_common/monitoring_common.rb +6 -0
- data/lib/smart_proxy_monitoring_icinga2/icinga2_api_observer.rb +66 -0
- data/lib/smart_proxy_monitoring_icinga2/icinga2_client.rb +127 -0
- data/lib/smart_proxy_monitoring_icinga2/icinga2_initial_importer.rb +109 -0
- data/lib/smart_proxy_monitoring_icinga2/icinga2_result_uploader.rb +97 -0
- data/lib/smart_proxy_monitoring_icinga2/icinga2_upload_queue.rb +9 -0
- data/lib/smart_proxy_monitoring_icinga2/monitoring_icinga2_common.rb +21 -0
- data/lib/smart_proxy_monitoring_icinga2/monitoring_icinga2_main.rb +68 -0
- data/lib/smart_proxy_monitoring_icinga2/monitoring_icinga2_plugin.rb +16 -0
- data/lib/smart_proxy_monitoring_icinga2/plugin_configuration.rb +28 -0
- data/lib/smart_proxy_monitoring_icinga2.rb +2 -0
- data/settings.d/monitoring.yml.example +11 -0
- data/settings.d/monitoring_icinga2.yml.example +17 -0
- metadata +142 -0
data/README.md
ADDED
@@ -0,0 +1,174 @@
|
|
1
|
+
# Smart Proxy - Monitoring
|
2
|
+
|
3
|
+
This plug-in adds support for Monitoring to Foreman's Smart Proxy.
|
4
|
+
It requires also the Foreman Monitoring plug-in.
|
5
|
+
|
6
|
+
# Installation
|
7
|
+
|
8
|
+
Please see the Foreman manual for appropriate instructions:
|
9
|
+
|
10
|
+
* [Foreman: How to Install a Plugin](http://theforeman.org/manuals/latest/index.html#6.Plugins)
|
11
|
+
|
12
|
+
The gem name is `smart_proxy_monitoring`.
|
13
|
+
|
14
|
+
RPM users can install the `rubygem-smart_proxy_monitoring` packages.
|
15
|
+
|
16
|
+
This plug-in has not been packaged for Debian, yet.
|
17
|
+
|
18
|
+
# Configuration
|
19
|
+
|
20
|
+
The plug-in requires some configuration on the Monitoring server and the Smart Proxy.
|
21
|
+
For now the only supported Monitoring solution is Icinga 2.
|
22
|
+
|
23
|
+
## Icinga 2
|
24
|
+
|
25
|
+
The Smart Proxy connects to the Icinga 2 API using an API User with password or
|
26
|
+
certificate to get Monitoring information. It requires at least Icinga 2 version 2.5.
|
27
|
+
|
28
|
+
The Icinga project provides detailed [documentation on Icinga 2](http://docs.icinga.org/icinga2/).
|
29
|
+
The required steps for connecting the Smart Proxy and Icinga 2 will be found below.
|
30
|
+
|
31
|
+
### Monitoring Server
|
32
|
+
|
33
|
+
On the Monitoring Server you have to enable the API and create API User.
|
34
|
+
|
35
|
+
For testing the fastest way to setup this will be the following commands.
|
36
|
+
|
37
|
+
```
|
38
|
+
# icinga2 api setup
|
39
|
+
# systemctl restart icinga2.service
|
40
|
+
```
|
41
|
+
|
42
|
+
This will create the certficates, enable the API feature and create and API User `root` with
|
43
|
+
a random password. The configuration of the API User will be located in `/etc/icinga2/conf.d/api-users.conf`.
|
44
|
+
|
45
|
+
More detailed instructions:
|
46
|
+
|
47
|
+
To enable the API follow the next steps, if the API is already enabled skip this steps
|
48
|
+
and start by creating an API User. The API will already be enabled if you use the Icingaweb 2
|
49
|
+
Module Director for configuration, Icinga 2 as Agents or in a distributed or high-available
|
50
|
+
setup.
|
51
|
+
|
52
|
+
Before you can enable the API a CA and a host certificate are required, the instructions
|
53
|
+
will help you to setup Icinga 2's own CA. You can also use your Puppet's certificates or
|
54
|
+
any other CA.
|
55
|
+
|
56
|
+
To create Icinga 2's own CA run:
|
57
|
+
|
58
|
+
```
|
59
|
+
# icinga2 pki new-ca
|
60
|
+
```
|
61
|
+
|
62
|
+
Afterwards copy the CA certificate to Icinga 2's pki directory:
|
63
|
+
|
64
|
+
```
|
65
|
+
# cp /var/lib/icinga2/ca/ca.crt /etc/icinga2/pki/
|
66
|
+
```
|
67
|
+
|
68
|
+
To create a certificate request for the node run:
|
69
|
+
|
70
|
+
```
|
71
|
+
# icinga2 pki new-cert --cn $(hostname -f) --key /etc/icinga2/pki/$(hostname -f).key --csr /etc/icinga2/pki/$(hostname -f).csr
|
72
|
+
```
|
73
|
+
|
74
|
+
And then sign the certficate request to get a certificate by executing:
|
75
|
+
|
76
|
+
```
|
77
|
+
# icinga2 pki sign-csr --csr /etc/icinga2/pki/$(hostname -f).csr --cert /etc/icinga2/pki/$(hostname -f).crt
|
78
|
+
```
|
79
|
+
|
80
|
+
With the certificates created and placed in Icinga 2's pki directory you can enable the API feature.
|
81
|
+
|
82
|
+
```
|
83
|
+
# icinga2 feature enable api
|
84
|
+
# systemctl restart icinga2.service
|
85
|
+
```
|
86
|
+
|
87
|
+
To allow API connections you have to create an API User. You should name him according to the use case,
|
88
|
+
so instructions will create an user named `foreman`.
|
89
|
+
|
90
|
+
Password authentication is easier to setup, but certificate-based authentication is more secure.
|
91
|
+
|
92
|
+
Password authentication only requires you to create an API User object in a configuration file
|
93
|
+
read by Icinga 2.
|
94
|
+
|
95
|
+
```
|
96
|
+
# vi /etc/icinga2/conf.d/api-users.conf
|
97
|
+
object ApiUser "foreman" {
|
98
|
+
password = "foreman"
|
99
|
+
permissions = [ "*" ]
|
100
|
+
}
|
101
|
+
# systemctl reload icinga2.service
|
102
|
+
```
|
103
|
+
|
104
|
+
Certificate-based authentication requires the API User object and a signed certificate.
|
105
|
+
|
106
|
+
```
|
107
|
+
# vi /etc/icinga2/conf.d/api-users.conf
|
108
|
+
object ApiUser "foreman" {
|
109
|
+
client_cn = "foreman"
|
110
|
+
permissions = [ "*" ]
|
111
|
+
}
|
112
|
+
# systemctl reload icinga2.service
|
113
|
+
# icinga2 pki new-cert --cn foreman --key /etc/icinga2/pki/foreman.key --csr /etc/icinga2/pki/foreman.csr
|
114
|
+
# icinga2 pki sign-csr --csr /etc/icinga2/pki/foreman.csr --cert /etc/icinga2/pki/foreman.crt
|
115
|
+
```
|
116
|
+
|
117
|
+
### Smart Proxy
|
118
|
+
|
119
|
+
Ensure that the Monitoring module is enabled and uses the provider monitoring_icinga2.
|
120
|
+
It is the default provider so also no setting for use_provider is fine.
|
121
|
+
If you configured hosts in Icinga2 only with hostname instead of FQDN, you can add `:strip_domain` with
|
122
|
+
all the parts to strip, e.g. `.localdomain`.
|
123
|
+
|
124
|
+
```
|
125
|
+
# vi /etc/foreman-proxy/settings.d/monitoring.yaml
|
126
|
+
---
|
127
|
+
:enabled: true
|
128
|
+
:use_provider: monitoring_icinga2
|
129
|
+
```
|
130
|
+
|
131
|
+
Configure the provider with your server details and the API User information.
|
132
|
+
Typically you will have to change the server attribute, copy the CA certificate from the server (located
|
133
|
+
in /etc/icinga2/pki/) and provide the authentication details of the API User. If using the IP address
|
134
|
+
instead of the FQDN of the server, you will have to set verify_ssl to false.
|
135
|
+
|
136
|
+
```
|
137
|
+
# vi /etc/foreman-proxy/settings.d/monitoring_icinga2.yaml
|
138
|
+
---
|
139
|
+
:enabled: true
|
140
|
+
:server: icinga2.localdomain
|
141
|
+
:api_cacert: /usr/share/foreman-proxy/monitoring/ca.crt
|
142
|
+
:api_user: foreman
|
143
|
+
:api_usercert: /usr/share/foreman-proxy/monitoring/foreman.crt
|
144
|
+
:api_userkey: /usr/share/foreman-proxy/monitoring/foreman.key
|
145
|
+
#:api_password: foreman
|
146
|
+
:verify_ssl: true
|
147
|
+
```
|
148
|
+
|
149
|
+
|
150
|
+
# TODO
|
151
|
+
|
152
|
+
Monitoring:
|
153
|
+
* Add host creation and update
|
154
|
+
|
155
|
+
Provider Icinga2:
|
156
|
+
* Add endpoint and zone management for Icinga 2 as agent
|
157
|
+
|
158
|
+
# Copyright
|
159
|
+
|
160
|
+
Copyright (c) 2016 The Foreman developers
|
161
|
+
|
162
|
+
This program is free software: you can redistribute it and/or modify
|
163
|
+
it under the terms of the GNU General Public License as published by
|
164
|
+
the Free Software Foundation, either version 3 of the License, or
|
165
|
+
(at your option) any later version.
|
166
|
+
|
167
|
+
This program is distributed in the hope that it will be useful,
|
168
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
169
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
170
|
+
GNU General Public License for more details.
|
171
|
+
|
172
|
+
You should have received a copy of the GNU General Public License
|
173
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
174
|
+
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'sinatra'
|
2
|
+
require 'smart_proxy_monitoring/monitoring_plugin'
|
3
|
+
|
4
|
+
module Proxy::Monitoring
|
5
|
+
class Api < ::Sinatra::Base
|
6
|
+
extend Proxy::Monitoring::DependencyInjection
|
7
|
+
inject_attr :monitoring_provider, :server
|
8
|
+
|
9
|
+
include ::Proxy::Log
|
10
|
+
helpers ::Proxy::Helpers
|
11
|
+
authorize_with_trusted_hosts
|
12
|
+
authorize_with_ssl_client
|
13
|
+
|
14
|
+
delete '/host/:host' do |host|
|
15
|
+
begin
|
16
|
+
validate_dns_name!(host)
|
17
|
+
host = strip_domain(host)
|
18
|
+
|
19
|
+
server.remove_host(host)
|
20
|
+
rescue Proxy::Monitoring::NotFound => e
|
21
|
+
log_halt 404, e
|
22
|
+
rescue Proxy::Monitoring::ConnectionError => e
|
23
|
+
log_halt 503, e
|
24
|
+
rescue Exception => e
|
25
|
+
log_halt 400, e
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
post '/downtime/host/:host?' do |host|
|
30
|
+
author = params[:author] || 'foreman'
|
31
|
+
comment = params[:comment] || 'triggered by foreman'
|
32
|
+
start_time = params[:start_time] || Time.now.to_i
|
33
|
+
end_time = params[:end_time] || (Time.now.to_i + (24 * 3600))
|
34
|
+
|
35
|
+
begin
|
36
|
+
validate_dns_name!(host)
|
37
|
+
host = strip_domain(host)
|
38
|
+
|
39
|
+
server.set_downtime_host(host, author, comment, start_time, end_time)
|
40
|
+
rescue Proxy::Monitoring::NotFound => e
|
41
|
+
log_halt 404, e
|
42
|
+
rescue Proxy::Monitoring::ConnectionError => e
|
43
|
+
log_halt 503, e
|
44
|
+
rescue Exception => e
|
45
|
+
log_halt 400, e
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
delete '/downtime/host/:host?' do |host|
|
50
|
+
author = params[:author] || 'foreman'
|
51
|
+
comment = params[:comment] || 'triggered by foreman'
|
52
|
+
|
53
|
+
begin
|
54
|
+
validate_dns_name!(host)
|
55
|
+
host = strip_domain(host)
|
56
|
+
|
57
|
+
server.remove_downtime_host(host, author, comment)
|
58
|
+
rescue Proxy::Monitoring::NotFound => e
|
59
|
+
log_halt 404, e
|
60
|
+
rescue Proxy::Monitoring::ConnectionError => e
|
61
|
+
log_halt 503, e
|
62
|
+
rescue Exception => e
|
63
|
+
log_halt 400, e
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def validate_dns_name!(name)
|
68
|
+
raise Proxy::Monitoring::Error.new("Invalid DNS name #{name}") unless name =~ /^([a-zA-Z0-9]([-a-zA-Z0-9]+)?\.?)+$/
|
69
|
+
end
|
70
|
+
|
71
|
+
def strip_domain(name)
|
72
|
+
domain = Proxy::Monitoring::Plugin.settings.strip_domain
|
73
|
+
name.slice!(domain) unless domain.nil?
|
74
|
+
name
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'smart_proxy_monitoring/version'
|
2
|
+
|
3
|
+
module Proxy::Monitoring
|
4
|
+
class NotFound < RuntimeError; end
|
5
|
+
class ConnectionError < RuntimeError; end
|
6
|
+
class Error < RuntimeError; end
|
7
|
+
|
8
|
+
class Plugin < ::Proxy::Plugin
|
9
|
+
plugin 'monitoring', Proxy::Monitoring::VERSION
|
10
|
+
|
11
|
+
uses_provider
|
12
|
+
default_settings use_provider: 'monitoring_icinga2'
|
13
|
+
|
14
|
+
http_rackup_path File.expand_path('monitoring_http_config.ru', File.expand_path('../', __FILE__))
|
15
|
+
https_rackup_path File.expand_path('monitoring_http_config.ru', File.expand_path('../', __FILE__))
|
16
|
+
|
17
|
+
load_classes ::Proxy::Monitoring::ConfigurationLoader
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'thread'
|
2
|
+
require 'socket'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module ::Proxy::Monitoring::Icinga2
|
6
|
+
class Icinga2ApiObserver
|
7
|
+
include ::Proxy::Log
|
8
|
+
include ::Proxy::Monitoring::Icinga2::Common
|
9
|
+
|
10
|
+
attr_reader :semaphore
|
11
|
+
|
12
|
+
def initialize(queue)
|
13
|
+
@queue = queue.queue
|
14
|
+
@semaphore = Mutex.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def monitor
|
18
|
+
loop do
|
19
|
+
logger.debug "Connecting to Icinga event monitoring api: #{Icinga2Client.baseurl}."
|
20
|
+
|
21
|
+
ssl_socket = Icinga2Client.events_socket('/events?queue=foreman&types=StateChange&types=AcknowledgementSet&types=AcknowledgementCleared&types=DowntimeTriggered&types=DowntimeRemoved')
|
22
|
+
|
23
|
+
logger.info 'Icinga event api monitoring started.'
|
24
|
+
|
25
|
+
while line = ssl_socket.gets
|
26
|
+
next unless line.chars.first == '{'
|
27
|
+
|
28
|
+
with_event_counter('Icinga2 Event API Monitor') do
|
29
|
+
begin
|
30
|
+
parsed = JSON.parse(line)
|
31
|
+
if @queue.size > 100_000
|
32
|
+
@queue.clear
|
33
|
+
logger.error 'Queue was full. Flushing. Events were lost.'
|
34
|
+
end
|
35
|
+
@queue.push(parsed)
|
36
|
+
rescue JSON::ParserError => e
|
37
|
+
logger.error "Icinga2 Event API Monitor: Malformed JSON: #{e.message}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
logger.info 'Icinga event api monitoring stopped.'
|
43
|
+
end
|
44
|
+
rescue Errno::ECONNREFUSED => e
|
45
|
+
logger.error "Icinga Event Stream: Connection refused. Retrying in 5 seconds. Reason: #{e.message}"
|
46
|
+
sleep 5
|
47
|
+
retry
|
48
|
+
rescue Exception => e
|
49
|
+
logger.error "Error while monitoring: #{e.message}\n#{e.backtrace.join("\n")}"
|
50
|
+
sleep 1
|
51
|
+
retry
|
52
|
+
ensure
|
53
|
+
ssl_socket.sysclose unless ssl_socket.nil?
|
54
|
+
end
|
55
|
+
|
56
|
+
def start
|
57
|
+
@thread = Thread.new { monitor }
|
58
|
+
@thread.abort_on_exception = true
|
59
|
+
@thread
|
60
|
+
end
|
61
|
+
|
62
|
+
def stop
|
63
|
+
@thread.terminate unless @thread.nil?
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'uri'
|
3
|
+
require 'rest-client'
|
4
|
+
require 'thread'
|
5
|
+
require 'socket'
|
6
|
+
require 'base64'
|
7
|
+
|
8
|
+
module ::Proxy::Monitoring::Icinga2
|
9
|
+
class Icinga2Client
|
10
|
+
class << self
|
11
|
+
def client(request_url)
|
12
|
+
headers = {
|
13
|
+
'Accept' => 'application/json'
|
14
|
+
}
|
15
|
+
|
16
|
+
options = {
|
17
|
+
headers: headers,
|
18
|
+
user: user,
|
19
|
+
ssl_ca_file: cacert,
|
20
|
+
verify_ssl: ssl
|
21
|
+
}
|
22
|
+
|
23
|
+
auth_options = if certificate_request?
|
24
|
+
{
|
25
|
+
ssl_client_cert: cert,
|
26
|
+
ssl_client_key: key
|
27
|
+
}
|
28
|
+
else
|
29
|
+
{
|
30
|
+
password: password
|
31
|
+
}
|
32
|
+
end
|
33
|
+
options.merge!(auth_options)
|
34
|
+
|
35
|
+
RestClient::Resource.new(
|
36
|
+
URI.encode([baseurl, request_url].join('')),
|
37
|
+
options
|
38
|
+
)
|
39
|
+
end
|
40
|
+
|
41
|
+
def events_socket(endpoint)
|
42
|
+
uri = URI.parse([baseurl, endpoint].join(''))
|
43
|
+
socket = TCPSocket.new(uri.host, uri.port)
|
44
|
+
|
45
|
+
ssl_context = OpenSSL::SSL::SSLContext.new
|
46
|
+
ssl_context.ca_file = cacert
|
47
|
+
|
48
|
+
if ssl
|
49
|
+
ssl_context.set_params(verify_mode: OpenSSL::SSL::VERIFY_PEER)
|
50
|
+
else
|
51
|
+
ssl_context.set_params(verify_mode: OpenSSL::SSL::VERIFY_NONE)
|
52
|
+
end
|
53
|
+
|
54
|
+
if certificate_request?
|
55
|
+
ssl_context.cert = cert
|
56
|
+
ssl_context.key = key
|
57
|
+
end
|
58
|
+
|
59
|
+
ssl_socket = OpenSSL::SSL::SSLSocket.new(socket, ssl_context)
|
60
|
+
ssl_socket.sync_close = true
|
61
|
+
ssl_socket.connect
|
62
|
+
|
63
|
+
ssl_socket.write "POST #{uri.request_uri} HTTP/1.1\r\n"
|
64
|
+
ssl_socket.write "Accept: application/json\r\n"
|
65
|
+
unless certificate_request?
|
66
|
+
auth = Base64.encode64("#{user}:#{password}")
|
67
|
+
ssl_socket.write "Authorization: Basic #{auth}"
|
68
|
+
end
|
69
|
+
ssl_socket.write "\r\n"
|
70
|
+
|
71
|
+
ssl_socket
|
72
|
+
end
|
73
|
+
|
74
|
+
def get(url)
|
75
|
+
client(url).get
|
76
|
+
end
|
77
|
+
|
78
|
+
def post(url, data)
|
79
|
+
client(url).post(data)
|
80
|
+
end
|
81
|
+
|
82
|
+
def put(url)
|
83
|
+
client(url).put
|
84
|
+
end
|
85
|
+
|
86
|
+
def delete(url)
|
87
|
+
client(url).delete
|
88
|
+
end
|
89
|
+
|
90
|
+
def cert
|
91
|
+
file = Proxy::Monitoring::Icinga2::Plugin.settings.api_usercert
|
92
|
+
return unless !file.nil? && File.file?(file)
|
93
|
+
OpenSSL::X509::Certificate.new(File.read(file))
|
94
|
+
end
|
95
|
+
|
96
|
+
def key
|
97
|
+
file = Proxy::Monitoring::Icinga2::Plugin.settings.api_userkey
|
98
|
+
return unless !file.nil? && File.file?(file)
|
99
|
+
OpenSSL::PKey::RSA.new(File.read(file))
|
100
|
+
end
|
101
|
+
|
102
|
+
def cacert
|
103
|
+
Proxy::Monitoring::Icinga2::Plugin.settings.api_cacert
|
104
|
+
end
|
105
|
+
|
106
|
+
def user
|
107
|
+
Proxy::Monitoring::Icinga2::Plugin.settings.api_user
|
108
|
+
end
|
109
|
+
|
110
|
+
def password
|
111
|
+
Proxy::Monitoring::Icinga2::Plugin.settings.api_password
|
112
|
+
end
|
113
|
+
|
114
|
+
def ssl
|
115
|
+
Proxy::Monitoring::Icinga2::Plugin.settings.verify_ssl
|
116
|
+
end
|
117
|
+
|
118
|
+
def certificate_request?
|
119
|
+
cert && key
|
120
|
+
end
|
121
|
+
|
122
|
+
def baseurl
|
123
|
+
"https://#{Proxy::Monitoring::Icinga2::Plugin.settings.server}:#{Proxy::Monitoring::Icinga2::Plugin.settings.api_port}/v1"
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'thread'
|
2
|
+
require 'socket'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module ::Proxy::Monitoring::Icinga2
|
6
|
+
class Icinga2InitialImporter
|
7
|
+
include ::Proxy::Log
|
8
|
+
|
9
|
+
def initialize(queue)
|
10
|
+
@queue = queue.queue
|
11
|
+
end
|
12
|
+
|
13
|
+
def monitor
|
14
|
+
logger.debug 'Starting initial icinga import.'
|
15
|
+
|
16
|
+
around_action('Initial Host Import') do
|
17
|
+
import_hosts
|
18
|
+
end
|
19
|
+
|
20
|
+
around_action('Initial Services Import') do
|
21
|
+
import_services
|
22
|
+
end
|
23
|
+
|
24
|
+
around_action('Initial Downtimes Import') do
|
25
|
+
import_downtimes
|
26
|
+
end
|
27
|
+
|
28
|
+
logger.info 'Finished initial icinga import.'
|
29
|
+
rescue Exception => e
|
30
|
+
logger.error "Error during initial import: #{e.message}\n#{e.backtrace}"
|
31
|
+
end
|
32
|
+
|
33
|
+
def import_hosts
|
34
|
+
results = Icinga2Client.get('/objects/hosts?attrs=name&attrs=last_check_result&attrs=acknowledgement')
|
35
|
+
results = JSON.parse(results)
|
36
|
+
results['results'].each do |result|
|
37
|
+
parsed = {
|
38
|
+
host: result['attrs']['name'],
|
39
|
+
result: result['attrs']['last_check_result']['state'],
|
40
|
+
timestamp: result['attrs']['last_check_result']['schedule_end'],
|
41
|
+
acknowledged: (result['attrs']['acknowledgement'] != 0),
|
42
|
+
initial: true,
|
43
|
+
type: '_parsed'
|
44
|
+
}
|
45
|
+
@queue.push(parsed)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def import_services
|
50
|
+
results = Icinga2Client.get('/objects/services?attrs=name&attrs=last_check_result&attrs=acknowledgement&attrs=host_name')
|
51
|
+
results = JSON.parse(results)
|
52
|
+
results['results'].each do |result|
|
53
|
+
parsed = {
|
54
|
+
host: result['attrs']['host_name'],
|
55
|
+
service: result['attrs']['name'],
|
56
|
+
result: result['attrs']['last_check_result']['state'],
|
57
|
+
timestamp: result['attrs']['last_check_result']['schedule_end'],
|
58
|
+
acknowledged: (result['attrs']['acknowledgement'] != 0),
|
59
|
+
initial: true,
|
60
|
+
type: '_parsed'
|
61
|
+
}
|
62
|
+
@queue.push(parsed)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def import_downtimes
|
67
|
+
results = Icinga2Client.get('/objects/downtimes?attrs=host_name&attrs=service_name&attrs=trigger_time')
|
68
|
+
results = JSON.parse(results)
|
69
|
+
results['results'].each do |result|
|
70
|
+
next unless result['attrs']['trigger_time'] != 0
|
71
|
+
parsed = {
|
72
|
+
host: result['attrs']['host_name'],
|
73
|
+
service: result['attrs']['service_name'],
|
74
|
+
downtime: true,
|
75
|
+
initial: true,
|
76
|
+
type: '_parsed'
|
77
|
+
}
|
78
|
+
@queue.push(parsed)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def start
|
83
|
+
@thread = Thread.new { monitor }
|
84
|
+
@thread.abort_on_exception = true
|
85
|
+
@thread
|
86
|
+
end
|
87
|
+
|
88
|
+
def stop
|
89
|
+
@thread.terminate unless @thread.nil?
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def around_action(task)
|
95
|
+
beginning_time = Time.now
|
96
|
+
logger.info "Starting Task: #{task}."
|
97
|
+
yield
|
98
|
+
end_time = Time.now
|
99
|
+
logger.info "Finished Task: #{task} in #{end_time - beginning_time} seconds."
|
100
|
+
rescue Errno::ECONNREFUSED => e
|
101
|
+
logger.error "Icinga Initial Importer: Connection refused in task #{task}. Reason: #{e.message}"
|
102
|
+
logger.error "Icinga Initial Importer: Restarting #{task} in 5 seconds."
|
103
|
+
sleep 5
|
104
|
+
retry
|
105
|
+
rescue JSON::ParserError => e
|
106
|
+
logger.error "Icinga Initial Importer: Failed to parse JSON: #{e.message}"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|