foreman_icinga 0.0.3
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 +7 -0
- data/app/helpers/concerns/foreman_icinga/hosts_helper_ext.rb +31 -0
- data/app/models/concerns/foreman_icinga/host_extensions.rb +67 -0
- data/app/models/host_status/icinga_status.rb +72 -0
- data/app/models/setting/icinga.rb +42 -0
- data/app/services/icinga.rb +84 -0
- data/lib/foreman_icinga.rb +3 -0
- data/lib/foreman_icinga/engine.rb +31 -0
- metadata +51 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f71e804e85b08f2b14fb7865f28325f96bb11efc
|
4
|
+
data.tar.gz: 98ee2bc7eb4d5cdb0af315574b5cb7ca49d438ec
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2e574aa8dd618d34755337bc9d9ac96bca00c3972973c402660044bbfeb25915b3101f22908a970b6fc7a88684f28b2e232b0d7cefe41ad3029b03f7f7513278
|
7
|
+
data.tar.gz: 672a244cdf704e100276b17d9ec1d25776b62cc7e5d4a72452e244579ecdefc7c439c6248139127f57c1ebaac3bab3223ccc5e1ae54ae6d500f03d016155f48d
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module ForemanIcinga
|
2
|
+
module HostsHelperExt
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
alias_method_chain :host_title_actions, :icinga
|
7
|
+
end
|
8
|
+
|
9
|
+
def host_title_actions_with_icinga(host)
|
10
|
+
title_actions(
|
11
|
+
button_group(
|
12
|
+
link_to(_('Icinga'), icinga_show_host_path(host), :target => '_blank')
|
13
|
+
)
|
14
|
+
)
|
15
|
+
host_title_actions_without_icinga(host)
|
16
|
+
end
|
17
|
+
|
18
|
+
def icinga_show_host_path(host)
|
19
|
+
params = {
|
20
|
+
:host => host.name
|
21
|
+
}
|
22
|
+
icinga_url_for('monitoring/host/show', params)
|
23
|
+
end
|
24
|
+
|
25
|
+
def icinga_url_for(route, params = {})
|
26
|
+
base = URI.join(Setting[:icinga_address], route).to_s
|
27
|
+
return base if params.empty?
|
28
|
+
base + '?' + params.to_query
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module ForemanIcinga
|
2
|
+
module HostExtensions
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
included do
|
5
|
+
before_destroy :downtime_host
|
6
|
+
after_build :downtime_host
|
7
|
+
|
8
|
+
has_one :icinga_status_object, :class_name => 'HostStatus::IcingaStatus', :foreign_key => 'host_id'
|
9
|
+
|
10
|
+
scoped_search :in => :icinga_status_object, :on => :status, :rename => :icinga_status,
|
11
|
+
:complete_value => {
|
12
|
+
:ok => HostStatus::IcingaStatus::OK,
|
13
|
+
:warning => HostStatus::IcingaStatus::WARNING,
|
14
|
+
:critical => HostStatus::IcingaStatus::CRITICAL,
|
15
|
+
:unknown => HostStatus::IcingaStatus::UNKNOWN
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
def icinga_status(options = {})
|
20
|
+
@icinga_status ||= get_status(HostStatus::IcingaStatus).to_status(options)
|
21
|
+
end
|
22
|
+
|
23
|
+
def icinga_status_label(options = {})
|
24
|
+
@icinga_status_label ||= get_status(HostStatus::IcingaStatus).to_label(options)
|
25
|
+
end
|
26
|
+
|
27
|
+
def refresh_icinga_status
|
28
|
+
get_status(HostStatus::IcingaStatus).refresh
|
29
|
+
end
|
30
|
+
|
31
|
+
def downtime_host
|
32
|
+
logger.debug _('Setting downtime for host %s in Icinga') % name
|
33
|
+
return false unless icinga_configured?
|
34
|
+
return true unless icinga_enabled?
|
35
|
+
|
36
|
+
begin
|
37
|
+
icinga = Icinga.new
|
38
|
+
params = {
|
39
|
+
'host' => name,
|
40
|
+
'comment' => 'host deleted in foreman',
|
41
|
+
'duration' => '7200'
|
42
|
+
}
|
43
|
+
response = icinga.call('deployment/downtime/schedule', '', params)
|
44
|
+
errors.add(:base, _("Error from Icinga server: '%s'") % response['message']) if response['status'] == 'error'
|
45
|
+
|
46
|
+
rescue => error
|
47
|
+
message = _('Failed to set Icinga downtime for %s.') % name
|
48
|
+
errors.add(:base, message)
|
49
|
+
Foreman::Logging.exception(message, error)
|
50
|
+
end
|
51
|
+
errors.empty?
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def icinga_configured?
|
57
|
+
if icinga_enabled? && (Setting[:icinga_address].blank? || Setting[:icinga_token].blank?)
|
58
|
+
errors.add(:base, _('Icinga plugin is enabled but not configured. Please configure it before trying to delete a host.'))
|
59
|
+
end
|
60
|
+
errors.empty?
|
61
|
+
end
|
62
|
+
|
63
|
+
def icinga_enabled?
|
64
|
+
[true, 'true'].include? Setting[:icinga_enabled]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module HostStatus
|
2
|
+
class IcingaStatus < HostStatus::Status
|
3
|
+
OK = 0
|
4
|
+
WARNING = 1
|
5
|
+
CRITICAL = 2
|
6
|
+
UNKNOWN = 3
|
7
|
+
|
8
|
+
def relevant?
|
9
|
+
host_not_in_build? && host_known_in_icinga?
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_status(_options = {})
|
13
|
+
parse_host_status call_icinga
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_global(_options = {})
|
17
|
+
case self.status
|
18
|
+
when OK
|
19
|
+
HostStatus::Global::OK
|
20
|
+
when WARNING
|
21
|
+
HostStatus::Global::WARN
|
22
|
+
when CRITICAL
|
23
|
+
HostStatus::Global::ERROR
|
24
|
+
else
|
25
|
+
HostStatus::Global::OK
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.status_name
|
30
|
+
N_('Icinga Status')
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_label(_options = {})
|
34
|
+
case self.status
|
35
|
+
when OK
|
36
|
+
N_('OK')
|
37
|
+
when WARNING
|
38
|
+
N_('Warning')
|
39
|
+
when CRITICAL
|
40
|
+
N_('Critical')
|
41
|
+
else
|
42
|
+
N_('Unknown')
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def host_not_in_build?
|
47
|
+
host && !host.build
|
48
|
+
end
|
49
|
+
|
50
|
+
def host_known_in_icinga?
|
51
|
+
true
|
52
|
+
end
|
53
|
+
|
54
|
+
def client
|
55
|
+
@icinga ||= Icinga.new
|
56
|
+
end
|
57
|
+
|
58
|
+
def call_icinga
|
59
|
+
client.call('deployment/health/check', '', {'host' => host.name})
|
60
|
+
end
|
61
|
+
|
62
|
+
def parse_host_status(response)
|
63
|
+
return UNKNOWN if response.key?('status') && response['status'] == 'error'
|
64
|
+
return UNKNOWN unless response.key?('healthy')
|
65
|
+
if response['healthy']
|
66
|
+
OK
|
67
|
+
else
|
68
|
+
WARNING
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
class Setting::Icinga < ::Setting
|
2
|
+
BLANK_ATTRS << 'icinga_address'
|
3
|
+
BLANK_ATTRS << 'icinga_token'
|
4
|
+
|
5
|
+
def self.load_defaults
|
6
|
+
if SETTINGS[:icinga].present?
|
7
|
+
default_enabled = SETTINGS[:icinga][:enabled]
|
8
|
+
default_address = SETTINGS[:icinga][:address]
|
9
|
+
default_token = SETTINGS[:icinga][:token]
|
10
|
+
default_icinga_ssl_ca_file = SETTINGS[:icinga][:icinga_ssl_ca_file]
|
11
|
+
end
|
12
|
+
|
13
|
+
default_enabled = false if default_enabled.nil?
|
14
|
+
default_address ||= 'https://icingahost/icingaweb2/'
|
15
|
+
default_token ||= ''
|
16
|
+
default_icinga_ssl_ca_file ||= "#{SETTINGS[:puppetssldir]}/certs/ca.pem"
|
17
|
+
|
18
|
+
Setting.transaction do
|
19
|
+
[
|
20
|
+
set('icinga_enabled', _("Integration with Icingaweb2, enabled will set a downtime for a host when it's deleted in Foreman"), default_enabled)
|
21
|
+
].compact.each { |s| create s.update(:category => 'Setting::Icinga') }
|
22
|
+
end
|
23
|
+
|
24
|
+
Setting.transaction do
|
25
|
+
[
|
26
|
+
set('icinga_address', _('Foreman will send Icingaweb2 requests to this address'), default_address)
|
27
|
+
].compact.each { |s| create s.update(:category => 'Setting::Icinga') }
|
28
|
+
end
|
29
|
+
|
30
|
+
Setting.transaction do
|
31
|
+
[
|
32
|
+
set('icinga_token', _('Foreman will authenticate to icingaweb2 using this token'), default_token)
|
33
|
+
].compact.each { |s| create s.update(:category => 'Setting::Icinga') }
|
34
|
+
end
|
35
|
+
|
36
|
+
Setting.transaction do
|
37
|
+
[
|
38
|
+
set('icinga_ssl_ca_file', _('SSL CA file that Foreman will use to communicate with icinga'), default_icinga_ssl_ca_file)
|
39
|
+
].compact.each { |s| create s.update(:category => 'Setting::Icinga') }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'rest-client'
|
2
|
+
|
3
|
+
class Icinga
|
4
|
+
attr_reader :client, :token, :address
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@address = Setting[:icinga_address]
|
8
|
+
@token = Setting[:icinga_token]
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(endpoint, payload = '', params = {})
|
12
|
+
uri = icinga_url_for(endpoint, params.merge(default_params))
|
13
|
+
parse client(uri).post(payload)
|
14
|
+
rescue OpenSSL::SSL::SSLError => e
|
15
|
+
message = "SSL Connection to Icinga failed: #{e}"
|
16
|
+
logger.warn message
|
17
|
+
error_response message
|
18
|
+
end
|
19
|
+
|
20
|
+
def logger
|
21
|
+
Rails.logger
|
22
|
+
end
|
23
|
+
|
24
|
+
protected
|
25
|
+
|
26
|
+
attr_reader :connect_params
|
27
|
+
|
28
|
+
def connect_params
|
29
|
+
{
|
30
|
+
:timeout => 3,
|
31
|
+
:open_timeout => 3,
|
32
|
+
:headers => {
|
33
|
+
:accept => :json
|
34
|
+
},
|
35
|
+
:verify_ssl => verify_ssl?,
|
36
|
+
:ssl_ca_file => ssl_ca_file
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
def ssl_ca_file
|
41
|
+
Setting[:icinga_ssl_ca_file]
|
42
|
+
end
|
43
|
+
|
44
|
+
def verify_ssl?
|
45
|
+
OpenSSL::SSL::VERIFY_PEER
|
46
|
+
end
|
47
|
+
|
48
|
+
def default_params
|
49
|
+
{
|
50
|
+
'token' => token,
|
51
|
+
'json' => true
|
52
|
+
}
|
53
|
+
end
|
54
|
+
|
55
|
+
def client(uri)
|
56
|
+
RestClient::Resource.new(uri, connect_params)
|
57
|
+
end
|
58
|
+
|
59
|
+
def parse(response)
|
60
|
+
if response && response.code >= 200 && response.code < 300
|
61
|
+
return response.body.present? ? JSON.parse(response.body) : error_response(_('received empty result'))
|
62
|
+
else
|
63
|
+
error_response "#{response.code} #{response.message}"
|
64
|
+
end
|
65
|
+
rescue JSON::ParserError => e
|
66
|
+
message = "Failed to parse icinga response: #{response} -> #{e}"
|
67
|
+
logger.warn message
|
68
|
+
error_response message
|
69
|
+
end
|
70
|
+
|
71
|
+
def error_response(message)
|
72
|
+
{
|
73
|
+
'status' => 'error',
|
74
|
+
'message' => message,
|
75
|
+
'success' => false
|
76
|
+
}
|
77
|
+
end
|
78
|
+
|
79
|
+
def icinga_url_for(route, params = {})
|
80
|
+
base = URI.join(address, route).to_s
|
81
|
+
return base if params.empty?
|
82
|
+
base + '?' + params.to_query
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module ForemanIcinga
|
2
|
+
class Engine < ::Rails::Engine
|
3
|
+
engine_name 'foreman_icinga'
|
4
|
+
|
5
|
+
config.autoload_paths += Dir["#{config.root}/app/controllers/concerns"]
|
6
|
+
config.autoload_paths += Dir["#{config.root}/app/helpers/concerns"]
|
7
|
+
config.autoload_paths += Dir["#{config.root}/app/models/concerns"]
|
8
|
+
config.autoload_paths += Dir["#{config.root}/app/overrides"]
|
9
|
+
config.autoload_paths += Dir["#{config.root}/app/services"]
|
10
|
+
|
11
|
+
initializer 'foreman_icinga.load_default_settings', :before => :load_config_initializers do |_app|
|
12
|
+
require_dependency File.expand_path('../../../app/models/setting/icinga.rb', __FILE__) if begin
|
13
|
+
Setting.table_exists?
|
14
|
+
rescue
|
15
|
+
(false)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
initializer 'foreman_icinga.register_plugin', :after => :finisher_hook do |_app|
|
20
|
+
Foreman::Plugin.register :foreman_icinga do
|
21
|
+
requires_foreman '>= 1.10'
|
22
|
+
register_custom_status HostStatus::IcingaStatus
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
config.to_prepare do
|
27
|
+
Host::Managed.send :include, ForemanIcinga::HostExtensions
|
28
|
+
HostsHelper.send(:include, ForemanIcinga::HostsHelperExt)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
metadata
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: foreman_icinga
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Timo Goebel
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-12-21 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Set a downtime for hosts after they are deleted in Foreman.
|
14
|
+
email: timo.goebel@dm.de
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- app/helpers/concerns/foreman_icinga/hosts_helper_ext.rb
|
20
|
+
- app/models/concerns/foreman_icinga/host_extensions.rb
|
21
|
+
- app/models/host_status/icinga_status.rb
|
22
|
+
- app/models/setting/icinga.rb
|
23
|
+
- app/services/icinga.rb
|
24
|
+
- lib/foreman_icinga.rb
|
25
|
+
- lib/foreman_icinga/engine.rb
|
26
|
+
homepage: http://www.github.com/FILIADATAGmbH/foreman_icinga
|
27
|
+
licenses:
|
28
|
+
- GPL-3.0
|
29
|
+
metadata: {}
|
30
|
+
post_install_message:
|
31
|
+
rdoc_options: []
|
32
|
+
require_paths:
|
33
|
+
- lib
|
34
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
35
|
+
requirements:
|
36
|
+
- - ">="
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: '0'
|
39
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
requirements: []
|
45
|
+
rubyforge_project:
|
46
|
+
rubygems_version: 2.4.5
|
47
|
+
signing_key:
|
48
|
+
specification_version: 4
|
49
|
+
summary: This is a foreman plugin to interact with icingaweb2 deployment module.
|
50
|
+
test_files: []
|
51
|
+
has_rdoc:
|