foreman_wreckingball 3.0.1 → 3.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -1
  3. data/app/assets/javascripts/foreman_wreckingball/modal.js +26 -18
  4. data/app/assets/javascripts/foreman_wreckingball/status_hosts_table.js +81 -0
  5. data/app/assets/javascripts/foreman_wreckingball/status_managed_hosts_dashboard.js +14 -0
  6. data/app/assets/javascripts/foreman_wreckingball/status_row.js +17 -0
  7. data/app/assets/stylesheets/foreman_wreckingball/status_hosts_table.css.scss +13 -0
  8. data/app/assets/stylesheets/foreman_wreckingball/status_managed_hosts_dashboard.css.scss +8 -0
  9. data/app/controllers/foreman_wreckingball/hosts_controller.rb +143 -43
  10. data/app/helpers/concerns/foreman_wreckingball/hosts_helper_extensions.rb +0 -15
  11. data/app/helpers/foreman_wreckingball/statuses_helper.rb +21 -0
  12. data/app/lib/actions/foreman_wreckingball/bulk_remediate.rb +27 -0
  13. data/app/lib/actions/foreman_wreckingball/host/remediate_hardware_version.rb +63 -0
  14. data/app/lib/actions/foreman_wreckingball/host/remediate_spectre_v2.rb +58 -0
  15. data/app/lib/fog_extensions/foreman_wreckingball/vsphere/mock.rb +13 -0
  16. data/app/lib/fog_extensions/foreman_wreckingball/vsphere/real.rb +7 -0
  17. data/app/lib/fog_extensions/foreman_wreckingball/vsphere/server.rb +14 -0
  18. data/app/models/concerns/foreman_wreckingball/host_extensions.rb +10 -20
  19. data/app/models/concerns/foreman_wreckingball/host_status_extensions.rb +13 -0
  20. data/app/models/concerns/foreman_wreckingball/user_extensions.rb +12 -0
  21. data/app/models/concerns/foreman_wreckingball/usergroup_extensions.rb +18 -0
  22. data/app/models/concerns/foreman_wreckingball/vmware_facet_host_extensions.rb +10 -0
  23. data/app/models/foreman_wreckingball/cpu_hot_add_status.rb +8 -0
  24. data/app/models/foreman_wreckingball/hardware_version_status.rb +70 -0
  25. data/app/models/foreman_wreckingball/operatingsystem_status.rb +8 -0
  26. data/app/models/foreman_wreckingball/spectre_v2_status.rb +19 -3
  27. data/app/models/foreman_wreckingball/tools_status.rb +9 -1
  28. data/app/models/foreman_wreckingball/vmware_facet.rb +9 -4
  29. data/app/models/foreman_wreckingball/vmware_hypervisor_facet.rb +4 -7
  30. data/app/models/setting/wreckingball.rb +22 -0
  31. data/app/services/foreman_wreckingball/vmware_cluster_importer.rb +7 -7
  32. data/app/services/foreman_wreckingball/vmware_hypervisor_importer.rb +17 -4
  33. data/app/views/foreman_wreckingball/hosts/_hosts.json.rabl +35 -0
  34. data/app/views/foreman_wreckingball/hosts/_status_dashboard_content.erb +13 -23
  35. data/app/views/foreman_wreckingball/hosts/_status_managed_hosts_dashboard_cards.html.erb +16 -0
  36. data/app/views/foreman_wreckingball/hosts/_status_managed_hosts_dashboard_cards_card.html.erb +11 -0
  37. data/app/views/foreman_wreckingball/hosts/_status_row.html.erb +16 -55
  38. data/app/views/foreman_wreckingball/hosts/_status_row_actions.html.erb +22 -0
  39. data/app/views/foreman_wreckingball/hosts/_status_row_hosts_table.html.erb +24 -0
  40. data/app/views/foreman_wreckingball/hosts/_status_row_hosts_table_actions.html.erb +9 -0
  41. data/app/views/foreman_wreckingball/hosts/schedule_remediate.html.erb +44 -26
  42. data/app/views/foreman_wreckingball/hosts/status_dashboard.html.erb +9 -6
  43. data/app/views/foreman_wreckingball/hosts/status_hosts.json.rabl +13 -0
  44. data/app/views/foreman_wreckingball/hosts/status_managed_hosts_dashboard.html.erb +142 -0
  45. data/config/environments/production.rb +7 -0
  46. data/config/routes.rb +4 -4
  47. data/db/migrate/20181020174609_add_power_state_to_vmware_facets.rb +7 -0
  48. data/db/migrate/20181021111543_add_indexes_to_vmware_hypervisor_facets.rb +8 -0
  49. data/lib/foreman_wreckingball/engine.rb +71 -23
  50. data/lib/foreman_wreckingball/version.rb +1 -1
  51. data/lib/tasks/foreman_vmware_checks_tasks.rake +1 -1
  52. data/test/actions/foreman_wreckingball/bulk_remediate_test.rb +31 -0
  53. data/test/actions/foreman_wreckingball/host/refresh_vmware_facet_test.rb +5 -4
  54. data/test/actions/foreman_wreckingball/host/remediate_hardware_version_test.rb +63 -0
  55. data/test/actions/foreman_wreckingball/host/remediate_spectre_v2_test.rb +62 -0
  56. data/test/actions/foreman_wreckingball/host/remediate_vmware_operatingsystem_test.rb +4 -2
  57. data/test/controllers/foreman_wreckingball/hosts_controller_test.rb +278 -39
  58. data/test/factories/compute_resource.rb +6 -1
  59. data/test/factories/foreman_wreckingball_factories.rb +166 -115
  60. data/test/factories/host.rb +16 -0
  61. data/test/factories/task.rb +17 -0
  62. data/test/helpers/foreman_wreckingball/status_helper.rb +10 -0
  63. data/test/integration/hosts_status_dashboard_test.rb +50 -0
  64. data/test/integration/hosts_status_managed_hosts_test.rb +105 -0
  65. data/test/integration_test_plugin_helper.rb +13 -0
  66. data/test/models/foreman_wreckingball/hardware_version_status_test.rb +88 -0
  67. data/test/models/foreman_wreckingball/tools_status_test.rb +5 -2
  68. data/test/models/foreman_wreckingball/vmware_facet_test.rb +27 -6
  69. data/test/models/host_status_test.rb +22 -0
  70. data/test/models/host_test.rb +64 -4
  71. data/test/models/usergroup_test.rb +25 -0
  72. data/test/test_plugin_helper.rb +19 -0
  73. data/test/unit/foreman_wreckingball/vmware_cluster_importer_test.rb +17 -2
  74. data/test/unit/foreman_wreckingball/vmware_hypervisor_importer_test.rb +11 -0
  75. metadata +55 -8
  76. data/app/services/foreman_wreckingball/debris_collector.rb +0 -249
@@ -0,0 +1,22 @@
1
+ <% actions = status_actions(host_association, owned_only, supports_remediate) %>
2
+
3
+ <% if actions.any? %>
4
+ <div class='list-view-pf-actions'>
5
+ <div class='dropdown pull-right dropdown-kebab-pf'>
6
+ <%= content_tag :button, class: 'btn btn-link dropdown-toggle',
7
+ type: 'button',
8
+ id: "dropdownKebabRight#{id}",
9
+ 'data-toggle': 'dropdown',
10
+ 'aria-haspopup': true,
11
+ 'aria-expanded': true do %>
12
+ <span class='fa fa-ellipsis-v' />
13
+ <% end %>
14
+
15
+ <%= content_tag :ul, class: 'dropdown-menu dropdown-menu-right', 'aria-labelledby': "dropdownKebabRight#{id}" do %>
16
+ <% actions.each do |action| %>
17
+ <%= content_tag :li, action %>
18
+ <% end %>
19
+ <% end %>
20
+ </div>
21
+ </div>
22
+ <% end %>
@@ -0,0 +1,24 @@
1
+ <%= render :partial => 'status_row_hosts_table_actions', locals: { supports_remediate: supports_remediate } %>
2
+
3
+ <%= content_tag :table, id: status,
4
+ class: 'table table-striped table-fixed status-hosts',
5
+ 'data-hosts-url': ajax_status_dashboard_hosts_path(status, owned_only: params[:owned_only]) do %>
6
+ <%= content_tag :thead do %>
7
+ <%= content_tag :tr do %>
8
+ <%= content_tag :th do %>
9
+ <%= check_box_tag 'select-all' %>
10
+ <% end %>
11
+ <%= content_tag :th, _('Hostname') %>
12
+ <%= content_tag :th, _('Status') %>
13
+ <%= content_tag :th, _('Owner') %>
14
+ <%= content_tag :th, _('Puppet Environment') %>
15
+ <%= content_tag :th, _('Actions') %>
16
+ <% end %>
17
+ <% end %>
18
+ <%= content_tag(:tbody) {} %>
19
+ <% end %>
20
+
21
+ <%= render :partial => 'status_row_hosts_table_actions', locals: { supports_remediate: supports_remediate } %>
22
+
23
+ <%= alert header: _("Oops, we're sorry but something went wrong"), text: '',
24
+ class: 'alert-danger', close: false %>
@@ -0,0 +1,9 @@
1
+ <%= content_tag :div, class: 'text-right' do %>
2
+ <% if supports_remediate %>
3
+ <%= content_tag :a, _('Remediate selected'),
4
+ href: schedule_remediate_hosts_path,
5
+ class: 'btn btn-default remediate-selected',
6
+ onclick: 'show_modal(this); return false;',
7
+ disabled: true %>
8
+ <% end %>
9
+ <% end %>
@@ -1,35 +1,53 @@
1
- <% title _('Remediate %s') % @host %>
1
+ <% title _('Remediate') %>
2
2
  <% javascript 'foreman_tasks/trigger_form' %>
3
3
  <% stylesheet 'foreman_tasks/trigger_form' %>
4
4
 
5
+ <% if @statuses.any? %>
6
+ <% if @statuses.group_by(&:class).map { |i| i.first}.select { |i| i.try(:dangerous_remediate?) }.any? %>
7
+ <%= alert(:text => _('This will cause a service interruption.'), :class => 'alert-warning', :close => false) %>
8
+ <% end %>
5
9
 
6
- <% if @status.class.respond_to?(:dangerous_remediate?) && @status.class.dangerous_remediate? -%>
7
- <%= alert(:text => _('This will cause a service interruption.'), :class => 'alert-warning', :close => false) %>
8
- <% end -%>
10
+ <%= n_('One host selected for remediation.', '%s hosts selected for remediation.', @statuses.count) % @statuses.count %>
9
11
 
10
- <%= form_for @triggering, :url => submit_remediate_host_path(:id => @host.id, :status_id => @status), :html => { :class => 'form-horizontal', :id => 'schedule_remediate_form' } do |f| %>
11
- <%= javascript_tag do %>
12
- $(function() { trigger_form_selector_binds('<%= f.options[:html][:id] %>','<%= f.object_name %>') });
13
- <% end %>
14
- <div class="form-group">
15
- <label class="col-md-2 control-label"><%= _('Schedule') %></label>
16
- <div class="col-md-8">
17
- <%= fields_for :triggering, @triggering do |trigger_fields| %>
18
- <%= radio_button_f trigger_fields, :mode, :class => 'trigger_mode_selector', :value => 'immediate', :text => _("Execute now") %>
19
- <%= radio_button_f trigger_fields, :mode, :class => 'trigger_mode_selector', :value => 'future', :text => _("Schedule future execution") %>
12
+ <ul class='hosts-list' style='max-height: 100px; overflow-y: scroll;'>
13
+ <% @statuses.each do |status| %>
14
+ <li>
15
+ <%= status.host.name %>
16
+ <%= content_tag(:span, nil, class: 'glyphicon glyphicon-warning-sign text-warning', title: _('This will cause a service interruption.')) if status.class.try(:dangerous_remediate?) %>
17
+ </li>
18
+ <% end %>
19
+ </ul>
20
+
21
+ <%= form_for @triggering, html: { class: 'form-horizontal', id: 'schedule_remediate_form' },
22
+ url: submit_remediate_hosts_path(host_association: @statuses_params[:host_association],
23
+ owned_only: @statuses_params[:owned_only],
24
+ status_ids: @statuses_params[:status_ids]) do |f| %>
25
+ <%= javascript_tag do %>
26
+ $(function() { trigger_form_selector_binds('<%= f.options[:html][:id] %>','<%= f.object_name %>') });
27
+ <% end %>
28
+ <div class="form-group">
29
+ <label class="col-md-2 control-label"><%= _('Schedule') %></label>
30
+ <div class="col-md-8">
31
+ <%= fields_for :triggering, @triggering do |trigger_fields| %>
32
+ <%= radio_button_f trigger_fields, :mode, :class => 'trigger_mode_selector', :value => 'immediate', :text => _('Execute now') %>
33
+ <%= radio_button_f trigger_fields, :mode, :class => 'trigger_mode_selector', :value => 'future', :text => _('Schedule future execution') %>
34
+ </div>
20
35
  </div>
21
- </div>
22
36
 
23
- <div class="trigger_fields">
24
- <%= content_tag(:fieldset, nil, :id => 'trigger_mode_future', :class => "trigger_mode_form #{'hidden' unless @triggering.future?}") do
25
- safe_join([
26
- text_f(f, :start_at_raw, :label => _('Start at'), :placeholder => 'YYYY-mm-dd HH:MM'),
27
- text_f(f, :start_before_raw, :label => _('Start before'), :placeholder => 'YYYY-mm-dd HH:MM',
28
- :label_help => _('Indicates that the action should be cancelled if it cannot be started before this time.'))
29
- ])
30
- end %>
31
- </div>
32
- <% end %>
37
+ <div class="trigger_fields">
38
+ <%= content_tag(:fieldset, nil, id: 'trigger_mode_future', class: "trigger_mode_form #{'hidden' unless @triggering.future?}") do
39
+ safe_join([
40
+ text_f(f, :start_at_raw, label: _('Start at'), placeholder: 'YYYY-mm-dd HH:MM'),
41
+ text_f(f, :start_before_raw, label: _('Start before'), placeholder: 'YYYY-mm-dd HH:MM',
42
+ label_help: _('Indicates that the action should be cancelled if it cannot be started before this time.'))
43
+ ])
44
+ end %>
45
+ </div>
46
+ <% end %>
33
47
 
34
- <%= submit_or_cancel f, false, :cancel_path => { :controller => :'foreman_wreckingball/hosts', :action => :status_dashboard } %>
48
+ <%= submit_or_cancel f, false, :cancel_path => { controller: :'foreman_wreckingball/hosts', action: :status_dashboard } %>
49
+ <% end %>
50
+ <% else %>
51
+ <%= content_tag :h3, _('No hosts selected') %>
52
+ <%= content_tag :p, _('Please select some hosts and try again') %>
35
53
  <% end %>
@@ -1,5 +1,8 @@
1
1
  <% title _('VMware Status Overview') %>
2
2
  <% javascript 'foreman_wreckingball/modal' %>
3
+ <% javascript 'foreman_wreckingball/status_hosts_table' %>
4
+ <% stylesheet 'foreman_wreckingball/status_hosts_table' %>
5
+ <% javascript 'foreman_wreckingball/status_row' %>
3
6
  <% javascript 'foreman_tasks/trigger_form' %>
4
7
  <% stylesheet 'foreman_tasks/trigger_form' %>
5
8
 
@@ -10,11 +13,11 @@
10
13
  render 'status_dashboard_empty'
11
14
  end
12
15
  %>
13
- <%= render :partial => 'common/modal', :locals => {
14
- :id => 'confirmation-modal',
15
- :title => _('Please Confirm'),
16
- :buttons => [
17
- button_tag(_('Cancel'), :class => 'btn btn-default', :data => { :dismiss => 'modal' }, :type => 'button'),
18
- button_tag(_('Submit'), :class => 'btn btn-primary', :data => { :action => 'submit' }, :onclick => 'submit_modal_form()')
16
+ <%= render partial: 'common/modal', locals: {
17
+ id: 'confirmation-modal',
18
+ title: _('Please Confirm'),
19
+ buttons: [
20
+ button_tag(_('Cancel'), class: 'btn btn-default', data: { dismiss: 'modal' }, type: 'button'),
21
+ button_tag(_('Submit'), class: 'btn btn-primary', data: { action: 'submit' }, onclick: 'submit_modal_form()')
19
22
  ]
20
23
  } %>
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ object false
4
+
5
+ node(:recordsTotal) { @count }
6
+ node(:recordsFiltered) { @count }
7
+ node(:data) do
8
+ partial 'foreman_wreckingball/hosts/_hosts', object: @hosts,
9
+ locals: {
10
+ host_association: @status.host_association,
11
+ supports_remediate: @status.supports_remediate?
12
+ }
13
+ end
@@ -0,0 +1,142 @@
1
+ <% title _('VMware Managed Hosts Overview') %>
2
+ <% javascript 'foreman_wreckingball/status_managed_hosts_dashboard' %>
3
+ <% stylesheet 'foreman_wreckingball/status_managed_hosts_dashboard' %>
4
+
5
+ <%= title_actions(
6
+ button_group(
7
+ if params[:owned_only]
8
+ link_to _('Show all hosts'), status_managed_hosts_dashboard_hosts_path, class: 'btn btn-default'
9
+ else
10
+ link_to _('Show only owned hosts'), status_managed_hosts_dashboard_hosts_path(owned_only: true), class: 'btn btn-default'
11
+ end
12
+ )
13
+ ) %>
14
+
15
+ <%= render partial: 'status_managed_hosts_dashboard_cards', locals: {
16
+ missing_hosts_count: @missing_hosts.count,
17
+ wrong_hosts_count: @wrong_hosts.count,
18
+ more_than_one_hosts_count: @more_than_one_hosts.count
19
+ } %>
20
+
21
+ <% if @errors.any? %>
22
+ <div class="alert alert-warning alert-block base alert-dismissable">
23
+ <%= alert_close %>
24
+ <h3>
25
+ <%= icon_text('warning-triangle-o', '', kind: 'pficon') %>
26
+ <%= _('Failed to load VM data.') %>
27
+ </h3>
28
+ <ul>
29
+ <% @errors.each do |cr, message| %>
30
+ <li><strong><%= cr %>:</strong> <%= message %></li>
31
+ <% end %>
32
+ </ul>
33
+ </div>
34
+ <% end %>
35
+
36
+ <ul class='nav nav-tabs' data-tabs='tabs'>
37
+ <li class='active'>
38
+ <%= content_tag :a, _('List of Hosts not found in vSphere'), href: '#missing_vms_tab', 'data-toggle': 'tab' %>
39
+ </li>
40
+ <li>
41
+ <%= content_tag :a, _('List of Hosts associated to wrong Compute Resource'), href: '#wrong_hosts_tab', 'data-toggle': 'tab' %>
42
+ </li>
43
+ <li>
44
+ <%= content_tag :a, _('List of Hosts found on more than one Compute Resource'), href: '#more_than_one_hosts_tab', 'data-toggle': 'tab' %>
45
+ </li>
46
+ </ul>
47
+
48
+ <div class='tab-content'>
49
+ <div class='tab-pane active' id='missing_vms_tab'>
50
+ <% if @missing_hosts.empty? %>
51
+ <%= content_tag :p, _('No Hosts to show'), class: 'ca' %>
52
+ <% else %>
53
+ <%= content_tag :table, id: 'missing_vms', class: table_css_classes do %>
54
+ <thead>
55
+ <tr>
56
+ <%= content_tag :th, _('Name') %>
57
+ <%= content_tag :th, nil, class: 'no-sort' %>
58
+ </tr>
59
+ </thead>
60
+ <tbody>
61
+ <% @missing_hosts.each do |host| %>
62
+ <tr>
63
+ <%= content_tag :td, link_to_if_authorized(host.name, hash_for_host_path(id: host).merge(permission: 'view_hosts', auth_object: host, authorizer: @host_authorizer)) %>
64
+ <td>
65
+ <%= action_buttons(display_delete_if_authorized(hash_for_host_path(id: host).merge(permission: 'destroy_hosts', auth_object: host, authorizer: @host_authorizer),
66
+ :data => { :confirm => _('Are you sure you want to delete host %s? This action is irreversible.') % host.name })) %>
67
+ </td>
68
+ </tr>
69
+ <% end %>
70
+ </tbody>
71
+ <% end %>
72
+ <% end %>
73
+ </div>
74
+ <div class='tab-pane' id='wrong_hosts_tab'>
75
+ <% if @wrong_hosts.empty? %>
76
+ <%= content_tag :p, _('No Hosts to show'), class: 'ca' %>
77
+ <% else %>
78
+ <%= content_tag :table, id: 'wrong_hosts', class: table_css_classes do %>
79
+ <thead>
80
+ <tr>
81
+ <%= content_tag :th, _('Name') %>
82
+ <%= content_tag :th, _('Associated to') %>
83
+ <%= content_tag :th, _('Found on') %>
84
+ <%= content_tag :th, nil, class: 'no-sort' %>
85
+ </tr>
86
+ </thead>
87
+ <tbody>
88
+ <% @wrong_hosts.each do |host| %>
89
+ <tr>
90
+ <%= content_tag :td, link_to_if_authorized(host.name, hash_for_host_path(id: host).merge(permission: 'view_hosts', auth_object: host, authorizer: @host_authorizer)) %>
91
+ <%= content_tag :td, link_to_if_authorized(host.compute_resource.name, hash_for_compute_resource_path(id: host.compute_resource).merge(permission: 'view_compute_resources', auth_object: host.compute_resource, authorizer: @compute_resource_authorizer)) %>
92
+ <%= content_tag :td, link_to_if_authorized(@vm_compute_resource_mapping[host.uuid].first.name, hash_for_compute_resource_path(id: @vm_compute_resource_mapping[host.uuid].first).merge(permission: 'view_compute_resources', auth_object: @vm_compute_resource_mapping[host.uuid].first, authorizer: @compute_resource_authorizer)) %>
93
+ <td>
94
+ <%= action_buttons(
95
+ display_link_if_authorized(
96
+ _('Fix Association'),
97
+ hash_for_associate_compute_resource_vm_path(
98
+ compute_resource_id: @vm_compute_resource_mapping[host.uuid].first,
99
+ id: host.uuid
100
+ ).merge(
101
+ auth_object: @vm_compute_resource_mapping[host.uuid].first,
102
+ authorizer: @compute_resource_authorizer,
103
+ permission: 'edit_compute_resources'
104
+ ),
105
+ title: _('Associate Host to correct Compute Resouce'),
106
+ method: :put
107
+ )
108
+ ) %>
109
+ </td>
110
+ </tr>
111
+ <% end %>
112
+ </tbody>
113
+ <% end %>
114
+ <% end %>
115
+ </div>
116
+ <div class='tab-pane' id='more_than_one_hosts_tab'>
117
+ <% if @more_than_one_hosts.empty? %>
118
+ <%= content_tag :p, _('No Hosts to show'), class: 'ca' %>
119
+ <% else %>
120
+ <%= content_tag :table, id: 'more_than_one_hosts', class: table_css_classes do %>
121
+ <thead>
122
+ <tr>
123
+ <%= content_tag :th, _('Name') %>
124
+ <%= content_tag :th, _('Associated to') %>
125
+ <%= content_tag :th, _('Found on') %>
126
+ </tr>
127
+ </thead>
128
+ <tbody>
129
+ <% @more_than_one_hosts.each do |host| %>
130
+ <tr>
131
+ <%= content_tag :td, link_to_if_authorized(host.name, hash_for_host_path(id: host).merge(permission: 'view_hosts', auth_object: host, authorizer: authorizer)) %>
132
+ <%= content_tag :td, (link_to_if_authorized(host.compute_resource.name, hash_for_compute_resource_path(id: host.compute_resource).merge(permission: 'view_compute_resources', auth_object: host.compute_resource, authorizer: @compute_resource_authorizer)) if host.compute_resource) %>
133
+ <td>
134
+ <%= safe_join(@vm_compute_resource_mapping[host.uuid].map { |compute_resource| link_to_if_authorized(compute_resource.name, hash_for_compute_resource_path(id: compute_resource).merge(permission: 'view_compute_resources', auth_object: compute_resource, authorizer: @compute_resource_authorizer))}, ', ') %>
135
+ </td>
136
+ </tr>
137
+ <% end %>
138
+ </tbody>
139
+ <% end %>
140
+ <% end %>
141
+ </div>
142
+ </div>
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require Rails.root.join('config', 'environments', 'production.rb')
4
+
5
+ Foreman::Application.configure do
6
+ config.assets.js_compressor = Uglifier.new(harmony: true) if defined?(Uglifier)
7
+ end
@@ -4,13 +4,13 @@ Rails.application.routes.draw do
4
4
  scope '/wreckingball' do
5
5
  constraints(:id => /[^\/]+/) do
6
6
  resources :hosts, controller: 'foreman_wreckingball/hosts', only: [] do
7
- member do
8
- get :schedule_remediate
9
- post :submit_remediate
10
- end
11
7
  collection do
12
8
  get :status_dashboard
9
+ get :status_managed_hosts_dashboard
10
+ get 'status_dashboard/hosts(/:status)', as: :ajax_status_dashboard, action: :status_hosts, defaults: { format: :json }
13
11
  put :refresh_status_dashboard
12
+ get :schedule_remediate
13
+ post :submit_remediate
14
14
  end
15
15
  end
16
16
  end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AddPowerStateToVmwareFacets < ActiveRecord::Migration[5.1]
4
+ def change
5
+ add_column :vmware_facets, :power_state, :integer, default: 1, index: true
6
+ end
7
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AddIndexesToVmwareHypervisorFacets < ActiveRecord::Migration[5.1]
4
+ def change
5
+ add_index :vmware_hypervisor_facets, :uuid
6
+ add_index :vmware_hypervisor_facets, [:vmware_cluster_id, :uuid]
7
+ end
8
+ end
@@ -7,6 +7,14 @@ module ForemanWreckingball
7
7
  class Engine < ::Rails::Engine
8
8
  engine_name 'foreman_wreckingball'
9
9
 
10
+ WRECKINGBALL_STATUSES = [
11
+ 'ForemanWreckingball::ToolsStatus',
12
+ 'ForemanWreckingball::OperatingsystemStatus',
13
+ 'ForemanWreckingball::CpuHotAddStatus',
14
+ 'ForemanWreckingball::SpectreV2Status',
15
+ 'ForemanWreckingball::HardwareVersionStatus'
16
+ ].freeze
17
+
10
18
  config.autoload_paths += Dir["#{config.root}/app/lib"]
11
19
  config.autoload_paths += Dir["#{config.root}/app/services"]
12
20
  config.autoload_paths += Dir["#{config.root}/app/models/concerns"]
@@ -23,9 +31,30 @@ module ForemanWreckingball
23
31
  end
24
32
  end
25
33
 
34
+ initializer 'foreman_wreckingball.load_default_settings', before: :load_config_initializers do
35
+ table_exists = begin
36
+ Setting.table_exists?
37
+ rescue StandardError
38
+ false
39
+ end
40
+ require_dependency File.expand_path('../../app/models/setting/wreckingball.rb', __dir__) if table_exists
41
+ end
42
+
26
43
  initializer 'foreman_wreckingball.register_plugin', :before => :finisher_hook do |_app|
27
44
  Foreman::Plugin.register :foreman_wreckingball do
28
- requires_foreman '>= 1.18'
45
+ requires_foreman '>= 1.21'
46
+
47
+ automatic_assets(false)
48
+ precompile_assets(
49
+ [
50
+ 'foreman_wreckingball/modal.js',
51
+ 'foreman_wreckingball/status_hosts_table.js',
52
+ 'foreman_wreckingball/status_managed_hosts_dashboard.js',
53
+ 'foreman_wreckingball/status_row.js',
54
+ 'foreman_wreckingball/status_hosts_table.css',
55
+ 'foreman_wreckingball/status_managed_hosts_dashboard.css'
56
+ ]
57
+ )
29
58
 
30
59
  security_block :foreman_wreckingball do
31
60
  permission :refresh_vmware_status_hosts, {
@@ -38,7 +67,9 @@ module ForemanWreckingball
38
67
 
39
68
  # Extend built in permissions
40
69
  Foreman::AccessControl.permission(:view_hosts).actions.concat [
41
- 'foreman_wreckingball/hosts/status_dashboard'
70
+ 'foreman_wreckingball/hosts/status_dashboard',
71
+ 'foreman_wreckingball/hosts/status_managed_hosts_dashboard',
72
+ 'foreman_wreckingball/hosts/status_hosts'
42
73
  ]
43
74
 
44
75
  menu :top_menu, :wreckingball_status_dashboard, :url_hash => { :controller => :'foreman_wreckingball/hosts', :action => :status_dashboard },
@@ -46,15 +77,18 @@ module ForemanWreckingball
46
77
  :parent => :hosts_menu,
47
78
  :after => :hosts
48
79
 
49
- register_custom_status(ForemanWreckingball::ToolsStatus)
50
- register_custom_status(ForemanWreckingball::OperatingsystemStatus)
51
- register_custom_status(ForemanWreckingball::CpuHotAddStatus)
80
+ WRECKINGBALL_STATUSES.each { |status| register_custom_status(status.constantize) }
81
+
82
+ menu :top_menu, :wreckingball_status_managed_hosts_dashboard, url_hash: { :controller => :'foreman_wreckingball/hosts', :action => :status_managed_hosts_dashboard },
83
+ caption: N_('VMware Managed Status'),
84
+ parent: :monitor_menu,
85
+ after: :audits
52
86
 
53
87
  register_facet(ForemanWreckingball::VmwareFacet, :vmware_facet)
54
88
 
55
89
  register_facet(ForemanWreckingball::VmwareHypervisorFacet, :vmware_hypervisor_facet)
56
90
 
57
- add_controller_action_scope(HostsController, :index) { |base_scope| base_scope.includes(:vmware_facet) }
91
+ add_controller_action_scope('HostsController', :index) { |base_scope| base_scope.includes(:vmware_facet) }
58
92
 
59
93
  # extend host show page
60
94
  extend_page('compute_resources/show') do |context|
@@ -63,6 +97,9 @@ module ForemanWreckingball
63
97
  :partial => 'compute_resources/hypervisors_tab',
64
98
  :onlyif => proc { |cr| cr.provider_friendly_name == 'VMware' && cr.vmware_hypervisor_facets.any? }
65
99
  end
100
+
101
+ # add custom logger
102
+ logger :import, enabled: true
66
103
  end
67
104
  end
68
105
 
@@ -72,23 +109,25 @@ module ForemanWreckingball
72
109
 
73
110
  # Include concerns in this config.to_prepare block
74
111
  config.to_prepare do
75
- begin
76
- ::ComputeResource.send(:include, ForemanWreckingball::ComputeResourceExtensions)
77
- ::Foreman::Model::Vmware.send(:include, ForemanWreckingball::VmwareExtensions)
78
- ::Host::Managed.send(:include, ForemanWreckingball::HostExtensions)
79
- ::Host::Managed.send(:include, ForemanWreckingball::VmwareFacetHostExtensions)
80
- ::Host::Managed.send(:include, ForemanWreckingball::VmwareHypervisorFacetHostExtensions)
81
- ::HostsHelper.send(:include, ForemanWreckingball::HostsHelperExtensions)
82
-
83
- if ForemanWreckingball.fog_patches_required?
84
- Fog::Compute::Vsphere::Host.send(:include, FogExtensions::ForemanWreckingball::Vsphere::Host)
85
- Fog::Compute::Vsphere::Real.send(:include, FogExtensions::ForemanWreckingball::Vsphere::Real)
86
- end
87
- rescue StandardError => e
88
- Rails.logger.warn "ForemanWreckingball: skipping engine hook (#{e})\n#{e.backtrace.join("\n")}"
112
+ ::HostStatus.extend(ForemanWreckingball::HostStatusExtensions)
113
+
114
+ ::ComputeResource.send(:include, ForemanWreckingball::ComputeResourceExtensions)
115
+ ::Foreman::Model::Vmware.send(:include, ForemanWreckingball::VmwareExtensions)
116
+ ::Host::Managed.send(:include, ForemanWreckingball::HostExtensions)
117
+ ::Host::Managed.send(:include, ForemanWreckingball::VmwareFacetHostExtensions)
118
+ ::Host::Managed.send(:include, ForemanWreckingball::VmwareHypervisorFacetHostExtensions)
119
+ ::HostsHelper.send(:include, ForemanWreckingball::HostsHelperExtensions)
120
+ ::User.send(:include, ForemanWreckingball::UserExtensions)
121
+ ::Usergroup.send(:include, ForemanWreckingball::UsergroupExtensions)
122
+
123
+ if ForemanWreckingball.fog_patches_required?
124
+ ForemanWreckingball.fog_vsphere_namespace::Host.send(:include, FogExtensions::ForemanWreckingball::Vsphere::Host)
125
+ ForemanWreckingball.fog_vsphere_namespace::Server.send(:include, FogExtensions::ForemanWreckingball::Vsphere::Server)
126
+ ForemanWreckingball.fog_vsphere_namespace::Real.send(:include, FogExtensions::ForemanWreckingball::Vsphere::Real)
127
+ ForemanWreckingball.fog_vsphere_namespace::Mock.send(:include, FogExtensions::ForemanWreckingball::Vsphere::Mock)
89
128
  end
90
-
91
- # load 'foreman_wreckingball/scheduled_jobs.rb'
129
+ rescue StandardError => e
130
+ Rails.logger.warn "ForemanWreckingball: skipping engine hook (#{e})\n#{e.backtrace.join("\n")}"
92
131
  end
93
132
 
94
133
  initializer 'foreman_wreckingball.register_gettext', after: :load_config_initializers do |_app|
@@ -103,8 +142,17 @@ module ForemanWreckingball
103
142
  require 'fog/vsphere'
104
143
  require 'fog/vsphere/compute'
105
144
  require 'fog/vsphere/models/compute/host'
106
- !::Fog::Compute::Vsphere::Host.instance_methods.include?(:feature_capabilities)
145
+ true
107
146
  rescue LoadError
108
147
  false
109
148
  end
149
+
150
+ def self.fog_vsphere_namespace
151
+ require 'fog/vsphere/version'
152
+ @fog_vsphere_namespace ||= if Gem::Version.new(Fog::Vsphere::VERSION) >= Gem::Version.new('3.0.0')
153
+ Fog::Vsphere::Compute
154
+ else
155
+ Fog::Compute::Vsphere
156
+ end
157
+ end
110
158
  end