foreman_monitoring 0.0.3 → 0.1.0
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 +4 -4
- data/README.md +28 -1
- data/app/controllers/api/v2/monitoring_results_controller.rb +8 -0
- data/app/controllers/concerns/foreman_monitoring/hosts_controller_extensions.rb +140 -0
- data/app/helpers/concerns/foreman_monitoring/hosts_helper_ext.rb +35 -11
- data/app/lib/proxy_api/monitoring.rb +35 -0
- data/app/models/concerns/foreman_monitoring/host_extensions.rb +48 -8
- data/app/models/concerns/foreman_monitoring/hostgroup_extensions.rb +15 -0
- data/app/models/concerns/orchestration/monitoring.rb +105 -0
- data/app/models/host_status/monitoring_status.rb +5 -1
- data/app/models/setting/monitoring.rb +23 -6
- data/app/overrides/add_host_multiple_power_set_downtime_checkbox.rb +5 -0
- data/app/overrides/add_host_set_downtime_modal.rb +5 -0
- data/app/services/monitoring.rb +56 -3
- data/app/views/hosts/_downtime_fields.html.erb +3 -0
- data/app/views/hosts/_host_downtime_checkbox.html.erb +8 -0
- data/app/views/hosts/_set_host_downtime.html.erb +20 -0
- data/app/views/hosts/select_multiple_downtime.html.erb +5 -0
- data/app/views/hosts/select_multiple_monitoring_proxy.html.erb +5 -0
- data/app/views/monitoring_results/_host_tab.html.erb +2 -0
- data/app/views/monitoring_results/_host_tab_pane.html.erb +2 -0
- data/config/routes.rb +16 -0
- data/db/migrate/20161220201510_add_monitoring_proxy_id_to_host_and_hostgroup.rb +11 -0
- data/lib/foreman_monitoring/engine.rb +35 -3
- data/lib/foreman_monitoring/version.rb +1 -1
- data/test/factories/host.rb +6 -0
- data/test/functional/hosts_controller_test.rb +190 -0
- data/test/lib/proxy_api/monitoring_test.rb +30 -0
- data/test/test_plugin_helper.rb +4 -0
- data/test/unit/host_status/monitoring_status_test.rb +7 -2
- data/test/unit/host_test.rb +111 -5
- data/test/unit/monitoring_test.rb +9 -3
- metadata +19 -6
@@ -6,7 +6,7 @@ module HostStatus
|
|
6
6
|
UNKNOWN = 3
|
7
7
|
|
8
8
|
def relevant?(_options = {})
|
9
|
-
host_not_in_build? && host_known_in_monitoring?
|
9
|
+
host_not_in_build? && host.monitored? && host_known_in_monitoring?
|
10
10
|
end
|
11
11
|
|
12
12
|
def to_status(_options = {})
|
@@ -59,6 +59,10 @@ module HostStatus
|
|
59
59
|
host.monitoring_results.any?
|
60
60
|
end
|
61
61
|
|
62
|
+
def host_monitored?
|
63
|
+
host.monitored?
|
64
|
+
end
|
65
|
+
|
62
66
|
def should_affect_global_status?
|
63
67
|
Setting[:monitoring_affect_global_status]
|
64
68
|
end
|
@@ -1,16 +1,33 @@
|
|
1
1
|
class Setting
|
2
2
|
class Monitoring < ::Setting
|
3
|
+
|
4
|
+
def self.default_settings
|
5
|
+
[
|
6
|
+
set('monitoring_affect_global_status',
|
7
|
+
_("Monitoring status will affect a host's global status when enabled"),
|
8
|
+
true, N_('Monitoring status should affect global status')),
|
9
|
+
set('monitoring_create_action',
|
10
|
+
_("What action should be taken when a host is created"),
|
11
|
+
'create', N_('Host Create Action'), nil, {:collection => Proc.new {::Monitoring::CREATE_ACTIONS} }),
|
12
|
+
set('monitoring_delete_action',
|
13
|
+
_("What action should be taken when a host is deleted"),
|
14
|
+
'delete', N_('Host Delete Action'), nil, {:collection => Proc.new {::Monitoring::DELETE_ACTIONS} })
|
15
|
+
]
|
16
|
+
end
|
17
|
+
|
3
18
|
def self.load_defaults
|
4
19
|
# Check the table exists
|
5
20
|
return unless super
|
6
21
|
|
7
|
-
|
8
|
-
|
9
|
-
set('monitoring_affect_global_status',
|
10
|
-
_("Monitoring status will affect a host's global status when enabled"),
|
11
|
-
true, N_('Monitoring status should affect global status'))
|
12
|
-
].compact.each { |s| create! s.update(:category => 'Setting::Monitoring') }
|
22
|
+
self.transaction do
|
23
|
+
default_settings.each { |s| self.create! s.update(:category => "Setting::Monitoring")}
|
13
24
|
end
|
25
|
+
|
26
|
+
true
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.humanized_category
|
30
|
+
N_('Monitoring')
|
14
31
|
end
|
15
32
|
end
|
16
33
|
end
|
data/app/services/monitoring.rb
CHANGED
@@ -1,13 +1,66 @@
|
|
1
1
|
class Monitoring
|
2
|
+
CREATE_ACTIONS = {
|
3
|
+
'none' => _('None'),
|
4
|
+
'create' => _('Create Host Object')
|
5
|
+
}.freeze
|
6
|
+
|
7
|
+
DELETE_ACTIONS = {
|
8
|
+
'none' => _('None'),
|
9
|
+
'delete' => _('Delete Host Object'),
|
10
|
+
'downtime' => _('Set Downtime for Host')
|
11
|
+
}.freeze
|
12
|
+
|
2
13
|
delegate :logger, :to => :Rails
|
3
14
|
attr_reader :proxy, :proxy_api
|
4
15
|
|
5
|
-
def
|
6
|
-
|
16
|
+
def self.create_action?(action)
|
17
|
+
Setting[:monitoring_create_action] == action.to_s
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.delete_action?(action)
|
21
|
+
Setting[:monitoring_delete_action] == action.to_s
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize(opts)
|
25
|
+
@proxy = opts.fetch(:monitoring_proxy)
|
7
26
|
@proxy_api = ProxyAPI::Monitoring.new(:url => proxy.url)
|
8
27
|
end
|
9
28
|
|
10
29
|
def set_downtime_host(host, options = {})
|
11
|
-
proxy_api.create_host_downtime(host.fqdn,
|
30
|
+
proxy_api.create_host_downtime(host.fqdn, default_downtime_options.merge(options))
|
31
|
+
end
|
32
|
+
|
33
|
+
def del_downtime_host(host, options = {})
|
34
|
+
proxy_api.remove_host_downtime(host.fqdn, default_downtime_options.merge(options))
|
35
|
+
end
|
36
|
+
|
37
|
+
def create_host(host)
|
38
|
+
proxy_api.create_host(host.fqdn, host.monitoring_attributes)
|
39
|
+
end
|
40
|
+
|
41
|
+
def update_host(host)
|
42
|
+
proxy_api.update_host(host.fqdn, host.monitoring_attributes)
|
43
|
+
end
|
44
|
+
|
45
|
+
def delete_host(host)
|
46
|
+
# We cannot use host.fqdn here as that is delegated to primary interface that does not exist anymore
|
47
|
+
proxy_api.delete_host(host.name)
|
48
|
+
end
|
49
|
+
|
50
|
+
def query_host(host)
|
51
|
+
result = proxy_api.query_host(host.name)
|
52
|
+
return {} unless result
|
53
|
+
{
|
54
|
+
:attrs => result
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def default_downtime_options
|
61
|
+
{
|
62
|
+
:author => 'Foreman',
|
63
|
+
:comment => 'triggered by Foreman'
|
64
|
+
}
|
12
65
|
end
|
13
66
|
end
|
@@ -0,0 +1,3 @@
|
|
1
|
+
<%= text_f f, :comment, :size => "col-md-5", :label => _('Comment'), :help_inline => _('Short description that explains why the downtime was set.'), :required => true %>
|
2
|
+
<%= datetime_f f, :starttime, :size => "col-md-5", :label => _('Starttime'), :help_inline => _('Time when the downtime should start.'), :value => DateTime.now.strftime("%Y-%m-%dT%H:%M"), :required => true %>
|
3
|
+
<%= datetime_f f, :endtime, :size => "col-md-5", :label => _('Endtime'), :help_inline => _('Time when the downtime should end.'), :value => DateTime.now.advance(:hours => 2).strftime("%Y-%m-%dT%H:%M"), :required => true %>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<div id="set_host_downtime" class="modal fade hide">
|
2
|
+
<div class="modal-dialog">
|
3
|
+
<div class="modal-content">
|
4
|
+
<div class="modal-header">
|
5
|
+
<%= alert_close('modal') %>
|
6
|
+
<h4 class="modal-title"><%= _('Set host downtime for %s') % @host %></h4>
|
7
|
+
</div>
|
8
|
+
<div class="modal-body">
|
9
|
+
<%= form_for :downtime,
|
10
|
+
:method => :put,
|
11
|
+
:url => hash_for_downtime_host_path(:id => @host).merge(:auth_object => @host, :permission => 'build_hosts') do |f| %>
|
12
|
+
<%= render :partial => 'downtime_fields', :locals => { :f => f } %>
|
13
|
+
<div class="modal-footer">
|
14
|
+
<%= modal_close %>
|
15
|
+
<%= f.submit(_("Set downtime"), :class => "btn btn-success submit") %>
|
16
|
+
</div>
|
17
|
+
<% end %>
|
18
|
+
</div>
|
19
|
+
</div>
|
20
|
+
</div>
|
@@ -1,3 +1,4 @@
|
|
1
|
+
<%- if authorized_for(:permission => 'view_monitoring_results', :auth_object => @host) && @host.monitored? -%>
|
1
2
|
<div class="tab-pane" id="monitoring">
|
2
3
|
<% if @host.monitoring_results.any? %>
|
3
4
|
<table class="table table-bordered table-striped">
|
@@ -23,3 +24,4 @@
|
|
23
24
|
<div class="alert alert-success"> <%= _('No monitoring results for this host') %> </div>
|
24
25
|
<% end %>
|
25
26
|
</div>
|
27
|
+
<%- end -%>
|
data/config/routes.rb
CHANGED
@@ -7,4 +7,20 @@ Rails.application.routes.draw do
|
|
7
7
|
resources :monitoring_results, :only => [:create]
|
8
8
|
end
|
9
9
|
end
|
10
|
+
|
11
|
+
scope '/monitoring' do
|
12
|
+
constraints(:id => %r{[^\/]+}) do
|
13
|
+
resources :hosts, :only => [] do
|
14
|
+
member do
|
15
|
+
put 'downtime'
|
16
|
+
end
|
17
|
+
collection do
|
18
|
+
post :select_multiple_downtime
|
19
|
+
post :update_multiple_downtime
|
20
|
+
post :select_multiple_monitoring_proxy
|
21
|
+
post :update_multiple_monitoring_proxy
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
10
26
|
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class AddMonitoringProxyIdToHostAndHostgroup < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
add_column :hosts, :monitoring_proxy_id, :integer
|
4
|
+
add_column :hostgroups, :monitoring_proxy_id, :integer
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.down
|
8
|
+
remove_column :hosts, :monitoring_proxy_id
|
9
|
+
remove_column :hostgroups, :monitoring_proxy_id
|
10
|
+
end
|
11
|
+
end
|
@@ -30,15 +30,47 @@ module ForemanMonitoring
|
|
30
30
|
|
31
31
|
initializer 'foreman_monitoring.register_plugin', :before => :finisher_hook do |_app|
|
32
32
|
Foreman::Plugin.register :foreman_monitoring do
|
33
|
-
requires_foreman '>= 1.
|
33
|
+
requires_foreman '>= 1.15'
|
34
|
+
|
35
|
+
apipie_documented_controllers ["#{ForemanMonitoring::Engine.root}/app/controllers/api/v2/*.rb"]
|
36
|
+
|
37
|
+
security_block :foreman_monitoring do
|
38
|
+
permission :view_monitoring_results,
|
39
|
+
{},
|
40
|
+
:resource_type => 'Host'
|
41
|
+
permission :manage_host_downtimes,
|
42
|
+
{ :hosts => [:downtime, :select_multiple_downtime, :update_multiple_downtime] },
|
43
|
+
:resource_type => 'Host'
|
44
|
+
permission :upload_monitoring_results,
|
45
|
+
:'api/v2/monitoring_results' => [:create]
|
46
|
+
end
|
47
|
+
|
48
|
+
role 'Monitoring viewer', [:view_monitoring_results]
|
49
|
+
role 'Monitoring manager', [:view_monitoring_results, :manage_host_downtimes, :upload_monitoring_results]
|
50
|
+
|
34
51
|
register_custom_status HostStatus::MonitoringStatus
|
52
|
+
|
53
|
+
add_controller_action_scope(HostsController, :index) { |base_scope| base_scope.includes(:monitoring_results) }
|
54
|
+
|
55
|
+
monitoring_proxy_options = {
|
56
|
+
:feature => 'Monitoring',
|
57
|
+
:label => N_('Monitoring Proxy'),
|
58
|
+
:description => N_('Monitoring Proxy to use to manage monitoring of this host'),
|
59
|
+
:api_description => N_('ID of Monitoring Proxy to use to manage monitoring of this host')
|
60
|
+
}
|
61
|
+
|
62
|
+
# add monitoring smart proxy to hosts and hostgroups
|
63
|
+
smart_proxy_for Host::Managed, :monitoring_proxy, monitoring_proxy_options
|
64
|
+
smart_proxy_for Hostgroup, :monitoring_proxy, monitoring_proxy_options
|
35
65
|
end
|
36
66
|
end
|
37
67
|
|
38
68
|
config.to_prepare do
|
39
69
|
begin
|
40
|
-
Host::Managed.send :include, ForemanMonitoring::HostExtensions
|
41
|
-
|
70
|
+
::Host::Managed.send :include, ForemanMonitoring::HostExtensions
|
71
|
+
::Hostgroup.send :include, ForemanMonitoring::HostgroupExtensions
|
72
|
+
::HostsHelper.send(:include, ForemanMonitoring::HostsHelperExt)
|
73
|
+
::HostsController.send :include, ForemanMonitoring::HostsControllerExtensions
|
42
74
|
rescue => e
|
43
75
|
Rails.logger.warn "ForemanMonitoring: skipping engine hook (#{e})"
|
44
76
|
end
|
data/test/factories/host.rb
CHANGED
@@ -0,0 +1,190 @@
|
|
1
|
+
require 'test_plugin_helper'
|
2
|
+
|
3
|
+
class HostsControllerExtensionsTest < ActionController::TestCase
|
4
|
+
tests ::HostsController
|
5
|
+
setup do
|
6
|
+
User.current = users(:admin)
|
7
|
+
disable_monitoring_orchestration
|
8
|
+
@host = FactoryGirl.create(:host, :managed)
|
9
|
+
end
|
10
|
+
|
11
|
+
context 'when setting a host downtime' do
|
12
|
+
setup do
|
13
|
+
@request.env['HTTP_REFERER'] = host_path(:id => @host)
|
14
|
+
end
|
15
|
+
|
16
|
+
test 'the flash should inform it' do
|
17
|
+
Host::Managed.any_instance.stubs(:downtime_host).returns(true)
|
18
|
+
put :downtime, {
|
19
|
+
:id => @host.name,
|
20
|
+
:downtime => {
|
21
|
+
:comment => 'Maintenance work.',
|
22
|
+
:starttime => DateTime.now,
|
23
|
+
:endtime => DateTime.now
|
24
|
+
}
|
25
|
+
}, set_session_user
|
26
|
+
assert_response :found
|
27
|
+
assert_redirected_to host_path(:id => @host)
|
28
|
+
assert_nil flash[:error]
|
29
|
+
assert_not_nil flash[:notice]
|
30
|
+
assert_equal "Created downtime for #{@host}", flash[:notice]
|
31
|
+
end
|
32
|
+
|
33
|
+
test 'with missing comment param the flash should inform it' do
|
34
|
+
put :downtime, { :id => @host.name }, set_session_user
|
35
|
+
assert_response :found
|
36
|
+
assert_redirected_to host_path(:id => @host)
|
37
|
+
assert_not_nil flash[:error]
|
38
|
+
assert_equal 'No comment for downtime set!', flash[:error]
|
39
|
+
end
|
40
|
+
|
41
|
+
test 'with missing date params the flash should inform it' do
|
42
|
+
put :downtime, { :id => @host.name, :downtime => { :comment => 'Maintenance work.' } }, set_session_user
|
43
|
+
assert_response :found
|
44
|
+
assert_redirected_to host_path(:id => @host)
|
45
|
+
assert_not_nil flash[:error]
|
46
|
+
assert_equal 'No start/endtime for downtime!', flash[:error]
|
47
|
+
end
|
48
|
+
|
49
|
+
test 'with invalid starttime the flash should inform it' do
|
50
|
+
put :downtime, {
|
51
|
+
:id => @host.name,
|
52
|
+
:downtime => {
|
53
|
+
:comment => 'Maintenance work.',
|
54
|
+
:starttime => 'invalid',
|
55
|
+
:endtime => 'invalid' }
|
56
|
+
}, set_session_user
|
57
|
+
assert_response :found
|
58
|
+
assert_redirected_to host_path(:id => @host)
|
59
|
+
assert_not_nil flash[:error]
|
60
|
+
assert_equal 'Invalid start/endtime for downtime!', flash[:error]
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe 'setting a downtime on multiple hosts' do
|
65
|
+
before do
|
66
|
+
@hosts = FactoryGirl.create_list(:host, 2, :with_monitoring)
|
67
|
+
@request.env['HTTP_REFERER'] = hosts_path
|
68
|
+
end
|
69
|
+
|
70
|
+
test 'show a host selection' do
|
71
|
+
host_ids = @hosts.map(&:id)
|
72
|
+
xhr :post, :select_multiple_downtime, {:host_ids => host_ids}, set_session_user
|
73
|
+
assert_response :success
|
74
|
+
assert response.body =~ /#{@hosts.first.name}.*#{@hosts.last.name}/m
|
75
|
+
end
|
76
|
+
|
77
|
+
test 'should set a downtime' do
|
78
|
+
Host::Managed.any_instance.expects(:downtime_host).twice.returns(true)
|
79
|
+
params = {
|
80
|
+
:host_ids => @hosts.map(&:id),
|
81
|
+
:downtime => {
|
82
|
+
:comment => 'Maintenance work.',
|
83
|
+
:starttime => DateTime.now,
|
84
|
+
:endtime => DateTime.now
|
85
|
+
}
|
86
|
+
}
|
87
|
+
|
88
|
+
post :update_multiple_downtime, params,
|
89
|
+
set_session_user
|
90
|
+
|
91
|
+
assert_response :found
|
92
|
+
assert_redirected_to hosts_path
|
93
|
+
assert_nil flash[:error]
|
94
|
+
assert_not_nil flash[:notice]
|
95
|
+
assert_equal 'A downtime was set for the selected hosts.', flash[:notice]
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
describe 'changing the power state on multiple hosts' do
|
100
|
+
before do
|
101
|
+
@hosts = FactoryGirl.create_list(:host, 2, :with_monitoring)
|
102
|
+
@request.env['HTTP_REFERER'] = hosts_path
|
103
|
+
|
104
|
+
power_mock = mock('power')
|
105
|
+
power_mock.expects(:poweroff).twice
|
106
|
+
Host::Managed.any_instance.stubs(:power).returns(power_mock)
|
107
|
+
Host::Managed.any_instance.stubs(:supports_power?).returns(true)
|
108
|
+
end
|
109
|
+
|
110
|
+
test 'should set a downtime if selected' do
|
111
|
+
Host::Managed.any_instance.expects(:downtime_host).twice.returns(true)
|
112
|
+
params = {
|
113
|
+
:host_ids => @hosts.map(&:id),
|
114
|
+
:power => {
|
115
|
+
:action => 'poweroff',
|
116
|
+
:set_downtime => true
|
117
|
+
}
|
118
|
+
}
|
119
|
+
|
120
|
+
post :update_multiple_power_state, params,
|
121
|
+
set_session_user
|
122
|
+
|
123
|
+
assert_response :found
|
124
|
+
assert_redirected_to hosts_path
|
125
|
+
assert_nil flash[:error]
|
126
|
+
assert_not_nil flash[:notice]
|
127
|
+
assert_equal 'The power state of the selected hosts will be set to poweroff', flash[:notice]
|
128
|
+
end
|
129
|
+
|
130
|
+
test 'should not set a downtime if not selected' do
|
131
|
+
Host::Managed.any_instance.expects(:downtime_host).never
|
132
|
+
params = {
|
133
|
+
:host_ids => @hosts.map(&:id),
|
134
|
+
:power => {
|
135
|
+
:action => 'poweroff',
|
136
|
+
:set_downtime => false
|
137
|
+
}
|
138
|
+
}
|
139
|
+
|
140
|
+
post :update_multiple_power_state, params,
|
141
|
+
set_session_user
|
142
|
+
|
143
|
+
assert_response :found
|
144
|
+
assert_redirected_to hosts_path
|
145
|
+
assert_nil flash[:error]
|
146
|
+
assert_not_nil flash[:notice]
|
147
|
+
assert_equal 'The power state of the selected hosts will be set to poweroff', flash[:notice]
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
describe 'changing the monitoring proxy of multiple hosts' do
|
152
|
+
let(:hosts) { FactoryGirl.create_list(:host, 2, :with_monitoring) }
|
153
|
+
let(:monitoring_proxy) { FactoryGirl.create(:smart_proxy, :monitoring, :organizations => [hosts.first.organization], :locations => [hosts.first.location]) }
|
154
|
+
before do
|
155
|
+
@request.env['HTTP_REFERER'] = hosts_path
|
156
|
+
end
|
157
|
+
|
158
|
+
test 'show a host selection' do
|
159
|
+
host_ids = hosts.map(&:id)
|
160
|
+
xhr :post, :select_multiple_monitoring_proxy, {:host_ids => host_ids}, set_session_user
|
161
|
+
assert_response :success
|
162
|
+
assert response.body =~ /#{hosts.first.name}.*#{hosts.last.name}/m
|
163
|
+
end
|
164
|
+
|
165
|
+
test 'should change the proxy' do
|
166
|
+
hosts.each do |host|
|
167
|
+
refute_equal monitoring_proxy, host.monitoring_proxy
|
168
|
+
end
|
169
|
+
|
170
|
+
params = {
|
171
|
+
:host_ids => hosts.map(&:id),
|
172
|
+
:proxy => { :proxy_id => monitoring_proxy.id }
|
173
|
+
}
|
174
|
+
|
175
|
+
post :update_multiple_monitoring_proxy, params,
|
176
|
+
set_session_user
|
177
|
+
|
178
|
+
assert_response :found
|
179
|
+
assert_redirected_to hosts_path
|
180
|
+
assert_nil flash[:error]
|
181
|
+
assert_equal "The Monitoring proxy of the selected hosts was set to #{monitoring_proxy.name}.", flash[:notice]
|
182
|
+
|
183
|
+
hosts.each do |host|
|
184
|
+
as_admin do
|
185
|
+
assert_equal monitoring_proxy, host.reload.monitoring_proxy
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|