foreman_wreckingball 3.2.0 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +2 -1
- data/app/assets/javascripts/foreman_wreckingball/modal.js +26 -17
- data/app/assets/javascripts/foreman_wreckingball/status_hosts_table.js +34 -2
- data/app/assets/javascripts/foreman_wreckingball/status_managed_hosts_dashboard.js +14 -0
- data/app/assets/stylesheets/foreman_wreckingball/status_hosts_table.css.scss +7 -0
- data/app/assets/stylesheets/foreman_wreckingball/status_managed_hosts_dashboard.css.scss +8 -0
- data/app/controllers/foreman_wreckingball/hosts_controller.rb +73 -43
- data/app/helpers/foreman_wreckingball/statuses_helper.rb +21 -0
- data/app/lib/actions/foreman_wreckingball/bulk_remediate.rb +27 -0
- data/app/lib/vsphere_os_identifiers/data.yaml +14 -0
- data/app/models/concerns/foreman_wreckingball/host_extensions.rb +4 -0
- data/app/models/concerns/foreman_wreckingball/host_status_extensions.rb +1 -1
- data/app/models/foreman_wreckingball/spectre_v2_status.rb +1 -1
- data/app/models/foreman_wreckingball/vmware_hypervisor_facet.rb +4 -7
- data/app/models/setting/wreckingball.rb +7 -3
- data/app/services/foreman_wreckingball/vmware_hypervisor_importer.rb +1 -3
- data/app/views/foreman_wreckingball/hosts/_hosts.json.rabl +9 -13
- data/app/views/foreman_wreckingball/hosts/_status_dashboard_content.erb +2 -0
- data/app/views/foreman_wreckingball/hosts/_status_managed_hosts_dashboard_cards.html.erb +16 -0
- data/app/views/foreman_wreckingball/hosts/_status_managed_hosts_dashboard_cards_card.html.erb +11 -0
- data/app/views/foreman_wreckingball/hosts/_status_row.html.erb +8 -12
- data/app/views/foreman_wreckingball/hosts/_status_row_actions.html.erb +22 -0
- data/app/views/foreman_wreckingball/hosts/_status_row_hosts_table.html.erb +8 -1
- data/app/views/foreman_wreckingball/hosts/_status_row_hosts_table_actions.html.erb +9 -0
- data/app/views/foreman_wreckingball/hosts/schedule_remediate.html.erb +44 -26
- data/app/views/foreman_wreckingball/hosts/status_dashboard.html.erb +6 -6
- data/app/views/foreman_wreckingball/hosts/status_managed_hosts_dashboard.html.erb +121 -28
- data/config/routes.rb +2 -4
- data/lib/foreman_wreckingball/engine.rb +41 -24
- data/lib/foreman_wreckingball/version.rb +1 -1
- data/lib/tasks/foreman_vmware_checks_tasks.rake +1 -1
- data/test/actions/foreman_wreckingball/bulk_remediate_test.rb +31 -0
- data/test/actions/foreman_wreckingball/host/refresh_vmware_facet_test.rb +3 -3
- data/test/actions/foreman_wreckingball/host/remediate_hardware_version_test.rb +2 -2
- data/test/actions/foreman_wreckingball/host/remediate_spectre_v2_test.rb +2 -2
- data/test/actions/foreman_wreckingball/host/remediate_vmware_operatingsystem_test.rb +1 -1
- data/test/controllers/foreman_wreckingball/hosts_controller_test.rb +83 -31
- data/test/factories/compute_resource.rb +1 -1
- data/test/factories/foreman_wreckingball_factories.rb +120 -116
- data/test/factories/task.rb +3 -3
- data/test/helpers/foreman_wreckingball/status_helper.rb +10 -0
- data/test/integration/hosts_status_dashboard_test.rb +15 -15
- data/test/integration/hosts_status_managed_hosts_test.rb +30 -18
- data/test/integration_test_plugin_helper.rb +1 -0
- data/test/models/foreman_wreckingball/vmware_facet_test.rb +5 -5
- data/test/models/host_test.rb +2 -2
- data/test/test_plugin_helper.rb +2 -0
- metadata +20 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 69707f89619ebddac7ddefecc16e1a029f917acff12ebcd5b043f212b71ea1cc
|
4
|
+
data.tar.gz: 71db825c47159fb7e7a083b2b0555f32f1ee094239ee93b8d2cf8961d8e3eb5b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dddb50886e2f10627b4d4d0a7058c0daeabb8659f68e9b8c1499d94ad3c764840b536d3bda174f74e179a647507d0172996bf3be4be089721fdafb2e32993b7c
|
7
|
+
data.tar.gz: 508e576b9e2568f4804424712d71065e2a957417d32f703923d789040ac4490361a7855aaf278ab33c9b4b35c008f840361dc594c95ceab34a4aa022b7e600b3
|
data/README.md
CHANGED
@@ -9,29 +9,38 @@ function submit_modal_form() {
|
|
9
9
|
$('#confirmation-modal').modal('hide');
|
10
10
|
}
|
11
11
|
|
12
|
-
function show_modal(element
|
13
|
-
if (
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
}
|
12
|
+
function show_modal(element) {
|
13
|
+
if ($(element).attr('disabled')) { return; }
|
14
|
+
|
15
|
+
const url = $(element).attr('href');
|
16
|
+
const title = $(element).data('title');
|
17
|
+
const hostAssociation = $(element).data('host-association');
|
18
|
+
|
19
|
+
if (title) { $('#confirmation-modal .modal-title').text(title); }
|
20
|
+
|
20
21
|
$('#confirmation-modal .modal-body')
|
21
22
|
.empty()
|
22
23
|
.append('<div class="modal-spinner spinner spinner-lg"></div>');
|
23
24
|
$('#confirmation-modal').modal();
|
24
|
-
$('#confirmation-modal .modal-body').load(url + ' #content',
|
25
|
-
function(response, status, xhr) {
|
26
|
-
$('#confirmation-modal .form-actions').remove();
|
27
25
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
}
|
32
|
-
|
33
|
-
|
26
|
+
let params;
|
27
|
+
if (!!hostAssociation) {
|
28
|
+
params = Object.assign({}, { host_association: hostAssociation },
|
29
|
+
!!$(element).data('owned-only') ? { owned_only: true } : null);
|
30
|
+
} else if($(element).data('status-id')) {
|
31
|
+
params = { status_ids: [$(element).data('status-id')] };
|
32
|
+
} else {
|
33
|
+
const statusIds = $(element).closest('.status-row')
|
34
|
+
.find(':checkbox[name="status-id"]:checked')
|
35
|
+
.map((_, e) => { return e.value; })
|
36
|
+
.toArray();
|
37
|
+
params = { status_ids: statusIds };
|
38
|
+
}
|
34
39
|
|
40
|
+
$('#confirmation-modal .modal-body').load(`${url}?${$.param(params)} #content`,
|
41
|
+
(response, status, xhr) => {
|
42
|
+
$('#confirmation-modal .form-actions').remove();
|
43
|
+
$('#confirmation-modal button[data-action="submit"]').attr('class', 'btn btn-primary');
|
35
44
|
$('#confirmation-modal a[rel="popover"]').popover();
|
36
45
|
|
37
46
|
trigger_form_selector_binds('schedule_remediate_form', url);
|
@@ -10,7 +10,8 @@ $(document).ready(() => {
|
|
10
10
|
processing: true,
|
11
11
|
serverSide: true,
|
12
12
|
columnDefs: [
|
13
|
-
{ className: 'ellipsis', targets: [
|
13
|
+
{ className: 'ellipsis', targets: [1, 2, 3, 4] },
|
14
|
+
{ width: '10px', targets: 0 }
|
14
15
|
],
|
15
16
|
ajax: {
|
16
17
|
url: $(element).data('hosts-url'),
|
@@ -26,13 +27,23 @@ $(document).ready(() => {
|
|
26
27
|
dataSrc: (json) => {
|
27
28
|
return json.data.map((e) => {
|
28
29
|
let row = [
|
30
|
+
`<input name='status-id' type='checkbox' value='${e.status.id}' data-remediate='${!!e.remediate}' >`,
|
29
31
|
`<a href="${e.path}">${e.name}</a>`,
|
30
32
|
`<span class="${e.status.icon_class}"></span><span class="${e.status.status_class}">${e.status.label}</span>`,
|
31
33
|
(e.owner || {}).name || '',
|
32
34
|
(e.environment || {}).name || ''
|
33
35
|
];
|
34
36
|
if(e.remediate) {
|
35
|
-
row.push(
|
37
|
+
row.push(`
|
38
|
+
<span class="btn btn-sm btn-default">
|
39
|
+
<a data-title="${e.remediate.title}"
|
40
|
+
data-id="aid_wreckingball_hosts_${e.name}_schedule_remediate"
|
41
|
+
data-status-id="${e.status.id}"
|
42
|
+
onclick="show_modal(this); return false;"
|
43
|
+
href="${e.remediate.path}">
|
44
|
+
${e.remediate.label}
|
45
|
+
</a>
|
46
|
+
</span>`);
|
36
47
|
} else {
|
37
48
|
row.push(null);
|
38
49
|
}
|
@@ -44,6 +55,27 @@ $(document).ready(() => {
|
|
44
55
|
$(element).on('error.dt', (_, settings) => {
|
45
56
|
$(settings.nTable).closest('.status-hosts-container').addClass('ajax-error');
|
46
57
|
});
|
58
|
+
$(element).on('page.dt', () => {
|
59
|
+
$selectAll.prop('checked', false).change();
|
60
|
+
$remediateSelected.attr('disabled', true);
|
61
|
+
});
|
62
|
+
|
63
|
+
const $selectAll = $(this).find(':checkbox[name="select-all"]');
|
64
|
+
const $remediateSelected = $(this).find('a.remediate-selected');
|
65
|
+
|
66
|
+
$selectAll.prop('checked', false);
|
67
|
+
|
68
|
+
$selectAll.change(() => {
|
69
|
+
const $selectHost = $(this).find(':checkbox[name="status-id"]');
|
70
|
+
$selectHost.prop('checked', $selectAll.is(':checked'));
|
71
|
+
$remediateSelected.attr('disabled', !$selectAll.is(':checked'));
|
72
|
+
});
|
73
|
+
|
74
|
+
$(this).on('change', ':checkbox[name=status-id]', () => {
|
75
|
+
const isAnyHostChecked = $(this).find(':checkbox[name="status-id"]').is(':checked');
|
76
|
+
$selectAll.prop('checked', isAnyHostChecked);
|
77
|
+
$remediateSelected.attr('disabled', !isAnyHostChecked);
|
78
|
+
});
|
47
79
|
});
|
48
80
|
});
|
49
81
|
});
|
@@ -0,0 +1,14 @@
|
|
1
|
+
$(document).ready(() => {
|
2
|
+
$('table#missing_vms').add('table#wrong_hosts').add('table#more_than_one_hosts')
|
3
|
+
.DataTable({
|
4
|
+
bLengthChange: true,
|
5
|
+
lengthMenu: [20, 50, 100],
|
6
|
+
order: [[ 0, 'desc' ]],
|
7
|
+
columnDefs: [
|
8
|
+
{
|
9
|
+
'targets': 'no-sort',
|
10
|
+
'orderable': false,
|
11
|
+
}
|
12
|
+
]
|
13
|
+
});
|
14
|
+
});
|
@@ -4,16 +4,11 @@ module ForemanWreckingball
|
|
4
4
|
class HostsController < ::HostsController
|
5
5
|
include ::ForemanTasks::Concerns::Parameters::Triggering
|
6
6
|
include ::HostsHelper
|
7
|
-
|
8
|
-
include ::ApplicationHelper
|
9
|
-
else
|
10
|
-
include ::AuthorizeHelper
|
11
|
-
end
|
7
|
+
include ::AuthorizeHelper
|
12
8
|
|
13
9
|
AJAX_REQUESTS = [:status_hosts].freeze
|
14
10
|
before_action :ajax_request, :only => AJAX_REQUESTS
|
15
|
-
before_action :
|
16
|
-
before_action :find_status, :only => [:submit_remediate, :schedule_remediate]
|
11
|
+
before_action :find_statuses, :only => [:schedule_remediate, :submit_remediate]
|
17
12
|
|
18
13
|
def status_dashboard
|
19
14
|
@newest_data = Host.authorized(:view_hosts).joins(:vmware_facet).maximum('vmware_facets.updated_at')
|
@@ -43,48 +38,63 @@ module ForemanWreckingball
|
|
43
38
|
end
|
44
39
|
|
45
40
|
def status_managed_hosts_dashboard
|
46
|
-
|
47
|
-
.try { |query| params[:owned_only] ? query.owned_by_current_user_or_group_with_current_user : query }
|
41
|
+
vmware_compute_resources = Foreman::Model::Vmware.unscoped.all
|
48
42
|
|
49
|
-
|
43
|
+
@errors = {}
|
50
44
|
|
51
|
-
# get all vms by compute resource id
|
52
|
-
vms_by_compute_resource_id = {}
|
53
45
|
# NOTE The call to ComputeResource#vms may slow things down
|
54
|
-
|
46
|
+
vms_by_compute_resource_id = vmware_compute_resources.each_with_object({}) do |cr, memo|
|
47
|
+
memo[cr.id] = cr.vms.all
|
48
|
+
rescue StandardError => e
|
49
|
+
@errors[cr.name] = e.message
|
50
|
+
Foreman::Logging.exception("Failed to load VMs from compute resource #{cr.name}", e)
|
51
|
+
end
|
55
52
|
|
56
|
-
|
53
|
+
# Get all VM UUIDs found in any of the compute resources
|
54
|
+
all_vm_uuids = vms_by_compute_resource_id.values.flatten.group_by(&:id).keys
|
57
55
|
|
58
|
-
#
|
59
|
-
@
|
56
|
+
# Map all VM UUIDs to all compute resources that have access to this VM
|
57
|
+
@vm_compute_resource_mapping = all_vm_uuids.each_with_object({}) do |uuid, obj|
|
58
|
+
cr_ids = vms_by_compute_resource_id.select { |_cr_id, vms| vms.find { |vm| vm.id == uuid } }.keys
|
59
|
+
obj[uuid] = vmware_compute_resources.select { |cr| cr_ids.include?(cr.id) }
|
60
|
+
end
|
60
61
|
|
61
62
|
@missing_hosts = []
|
62
|
-
@
|
63
|
+
@wrong_hosts = []
|
64
|
+
@more_than_one_hosts = []
|
63
65
|
|
64
|
-
|
65
|
-
|
66
|
+
Host::Managed.authorized(:view_hosts, Host)
|
67
|
+
.includes(:compute_resource)
|
68
|
+
.where(compute_resource: vmware_compute_resources)
|
69
|
+
.try { |query| params[:owned_only] ? query.owned_by_current_user_or_group_with_current_user : query }
|
70
|
+
.each do |host|
|
66
71
|
|
67
|
-
|
68
|
-
cr_id, _vms = vms_by_compute_resource_id.find { |_cr_id, vms| vms.find { |vm| vm.uuid == host.uuid } }
|
72
|
+
compute_resources = @vm_compute_resource_mapping[host.uuid]
|
69
73
|
|
70
|
-
if
|
71
|
-
#
|
74
|
+
if compute_resources.empty?
|
75
|
+
# VM is not found on any compute resource, vSphere does not have the vm uuid
|
72
76
|
@missing_hosts << host
|
73
|
-
elsif
|
74
|
-
# The
|
75
|
-
@
|
77
|
+
elsif compute_resources.count > 1
|
78
|
+
# The vm uuid is found on more than one compute resource
|
79
|
+
@more_than_one_hosts << host
|
80
|
+
elsif host.compute_resource_id != compute_resources.first.id
|
81
|
+
# The host is associated to a wrong compute resource
|
82
|
+
@wrong_hosts << host
|
76
83
|
end
|
77
84
|
end
|
85
|
+
|
86
|
+
@compute_resource_authorizer = Authorizer.new(User.current, collection: vmware_compute_resources)
|
87
|
+
@host_authorizer = Authorizer.new(User.current)
|
78
88
|
end
|
79
89
|
|
80
90
|
# ajax method
|
81
91
|
def status_hosts
|
82
|
-
@status = HostStatus.find_wreckingball_status_by_host_association(params.fetch(:status)
|
92
|
+
@status = HostStatus.find_wreckingball_status_by_host_association(params.fetch(:status))
|
83
93
|
|
84
94
|
all_hosts = Host.authorized(:view_hosts, Host)
|
85
95
|
.joins(@status.host_association)
|
86
96
|
.try { |query| params[:owned_only] ? query.owned_by_current_user_or_group_with_current_user : query }
|
87
|
-
.includes(@status.host_association, :vmware_facet
|
97
|
+
.includes([*(:environment if Host::Managed.reflect_on_environment?), @status.host_association, :vmware_facet])
|
88
98
|
.where.not('host_status.status': @status.global_ok_list)
|
89
99
|
.preload(:owner)
|
90
100
|
.order(:name)
|
@@ -119,20 +129,21 @@ module ForemanWreckingball
|
|
119
129
|
end
|
120
130
|
|
121
131
|
def submit_remediate
|
122
|
-
|
123
|
-
task = User.as_anonymous_admin do
|
124
|
-
triggering = ::ForemanTasks::Triggering.new_from_params(triggering_params)
|
125
|
-
if triggering.future?
|
126
|
-
triggering.parse_start_at!
|
127
|
-
triggering.parse_start_before!
|
128
|
-
else
|
129
|
-
triggering.start_at ||= Time.zone.now
|
130
|
-
end
|
132
|
+
return not_found unless @statuses.any?
|
131
133
|
|
132
|
-
|
134
|
+
triggering = ::ForemanTasks::Triggering.new_from_params(triggering_params)
|
135
|
+
if triggering.future?
|
136
|
+
triggering.parse_start_at!
|
137
|
+
triggering.parse_start_before!
|
138
|
+
else
|
139
|
+
triggering.start_at ||= Time.zone.now
|
133
140
|
end
|
134
|
-
|
135
|
-
|
141
|
+
|
142
|
+
task = User.as_anonymous_admin do
|
143
|
+
triggering.trigger(::Actions::ForemanWreckingball::BulkRemediate, @statuses)
|
144
|
+
end
|
145
|
+
|
146
|
+
redirect_to foreman_tasks_task_path(task.id)
|
136
147
|
end
|
137
148
|
|
138
149
|
private
|
@@ -143,13 +154,32 @@ module ForemanWreckingball
|
|
143
154
|
end
|
144
155
|
end
|
145
156
|
|
146
|
-
def
|
147
|
-
@
|
157
|
+
def statuses_params
|
158
|
+
@statuses_params ||= params.permit(:host_association, :owned_only, status_ids: [])
|
159
|
+
end
|
160
|
+
|
161
|
+
def find_statuses
|
162
|
+
@statuses = begin
|
163
|
+
host_association = statuses_params[:host_association]
|
164
|
+
status_class = HostStatus.find_wreckingball_status_by_host_association(host_association)
|
165
|
+
if status_class
|
166
|
+
Host.authorized(:remediate_vmware_status_hosts, Host)
|
167
|
+
.joins(status_class.host_association)
|
168
|
+
.includes(status_class.host_association)
|
169
|
+
.try { |query| statuses_params[:owned_only] ? query.owned_by_current_user_or_group_with_current_user : query }
|
170
|
+
.where.not('host_status.status': status_class.global_ok_list)
|
171
|
+
.map { |host| host.send(status_class.host_association) }
|
172
|
+
else
|
173
|
+
HostStatus::Status.includes(:host).where(id: statuses_params[:status_ids]).select do |status|
|
174
|
+
User.current.can?(:remediate_vmware_status_hosts, status.host)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
148
178
|
end
|
149
179
|
|
150
180
|
def action_permission
|
151
181
|
case params[:action]
|
152
|
-
when 'status_dashboard', 'status_hosts'
|
182
|
+
when 'status_dashboard', 'status_hosts', 'status_managed_hosts_dashboard'
|
153
183
|
'view'
|
154
184
|
when 'refresh_status_dashboard'
|
155
185
|
'refresh_vmware_status'
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ForemanWreckingball
|
4
|
+
module StatusesHelper
|
5
|
+
def status_actions(host_association, owned_only, supports_remediate)
|
6
|
+
actions = []
|
7
|
+
actions << display_link_if_authorized(_('Refresh'),
|
8
|
+
hash_for_refresh_status_dashboard_hosts_path,
|
9
|
+
title: _('Refresh Data'),
|
10
|
+
method: :put)
|
11
|
+
if supports_remediate
|
12
|
+
actions << display_link_if_authorized(_('Remediate All'),
|
13
|
+
hash_for_schedule_remediate_hosts_path,
|
14
|
+
'data-host-association': host_association,
|
15
|
+
'data-owned-only': owned_only,
|
16
|
+
onClick: 'show_modal(this); return false;')
|
17
|
+
end
|
18
|
+
actions.reject(&:blank?)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Actions
|
4
|
+
module ForemanWreckingball
|
5
|
+
class BulkRemediate < Actions::Base
|
6
|
+
def plan(statuses)
|
7
|
+
sequence do
|
8
|
+
statuses.group_by(&:class).each do |statuses_klass, statuses_list|
|
9
|
+
plan_action(::Actions::BulkAction, statuses_klass.remediate_action, statuses_list.map(&:host)) if statuses_klass.respond_to?(:remediate_action)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def run
|
15
|
+
# dummy run phase to save input
|
16
|
+
end
|
17
|
+
|
18
|
+
def resource_locks
|
19
|
+
:link
|
20
|
+
end
|
21
|
+
|
22
|
+
def humanized_name
|
23
|
+
_('Bulk remediate')
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -388,6 +388,13 @@ rhel7_64Guest:
|
|
388
388
|
:name: RedHat
|
389
389
|
:major: 7
|
390
390
|
:since: 5.5
|
391
|
+
rhel8_64Guest:
|
392
|
+
:description: Red Hat Enterprise Linux 8 (64-bit)
|
393
|
+
:architecture: x86_64
|
394
|
+
:osfamily: Redhat
|
395
|
+
:name: RedHat
|
396
|
+
:major: 8
|
397
|
+
:since: 6.5
|
391
398
|
sjdsGuest:
|
392
399
|
:description: Sun Java Desktop System
|
393
400
|
sles10Guest:
|
@@ -426,6 +433,13 @@ sles12_64Guest:
|
|
426
433
|
:name: SLES
|
427
434
|
:major: 12
|
428
435
|
:since: 5.5
|
436
|
+
sles15_64Guest:
|
437
|
+
:description: SUSE Linux Enterprise 15 (64-bit)
|
438
|
+
:architecture: x86_64
|
439
|
+
:osfamily: Suse
|
440
|
+
:name: SLES
|
441
|
+
:major: 15
|
442
|
+
:since: 6.0
|
429
443
|
sles64Guest:
|
430
444
|
:description: SUSE Linux Enterprise 8/9 (64-bit)
|
431
445
|
:architecture: x86_64
|
@@ -16,6 +16,10 @@ module ForemanWreckingball
|
|
16
16
|
scope :owned_by_current_user, -> { where(owner_type: 'User', owner_id: User.current.id) }
|
17
17
|
scope :owned_by_group_with_current_user, -> { where(owner_type: 'Usergroup', owner_id: User.current.usergroup_ids_with_parents) }
|
18
18
|
scope :owned_by_current_user_or_group_with_current_user, -> { owned_by_current_user.or(owned_by_group_with_current_user) }
|
19
|
+
|
20
|
+
def self.reflect_on_environment?
|
21
|
+
reflect_on_association(:environment).present?
|
22
|
+
end
|
19
23
|
end
|
20
24
|
|
21
25
|
def action_input_key
|
@@ -7,7 +7,7 @@ module ForemanWreckingball
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def find_wreckingball_status_by_host_association(host_association)
|
10
|
-
wreckingball_statuses.find { |s| s.host_association == host_association }
|
10
|
+
wreckingball_statuses.find { |s| s.host_association.to_s == host_association.to_s }
|
11
11
|
end
|
12
12
|
end
|
13
13
|
end
|
@@ -72,7 +72,7 @@ module ForemanWreckingball
|
|
72
72
|
end
|
73
73
|
|
74
74
|
def required_cpu_features_present?
|
75
|
-
!(host.vmware_facet.cpu_features & ['cpuid.
|
75
|
+
!(host.vmware_facet.cpu_features.map(&:downcase) & ['cpuid.ibrs', 'cpuid.ibpb', 'cpuid.stibp']).empty?
|
76
76
|
end
|
77
77
|
end
|
78
78
|
end
|
@@ -6,14 +6,11 @@ module ForemanWreckingball
|
|
6
6
|
|
7
7
|
validates_lengths_from_database
|
8
8
|
|
9
|
-
validates :host, :
|
9
|
+
validates :host, presence: true, allow_blank: false
|
10
10
|
|
11
|
-
belongs_to :vmware_cluster, :
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
has_many :vmware_facets, :class_name => '::ForemanWreckingball::VmwareFacet', :through => :vmware_clusters,
|
16
|
-
:inverse_of => :vmware_hypervisor_facets
|
11
|
+
belongs_to :vmware_cluster, inverse_of: :vmware_hypervisor_facets, class_name: '::ForemanWreckingball::VmwareCluster'
|
12
|
+
has_one :compute_resource, inverse_of: :vmware_hypervisor_facets, through: :vmware_cluster
|
13
|
+
has_many :vmware_facets, inverse_of: :vmware_hypervisor_facets, through: :vmware_cluster
|
17
14
|
|
18
15
|
serialize :feature_capabilities, JSON
|
19
16
|
|
@@ -2,14 +2,18 @@
|
|
2
2
|
|
3
3
|
class Setting
|
4
4
|
class Wreckingball < ::Setting
|
5
|
+
def self.default_settings
|
6
|
+
[
|
7
|
+
set('min_vsphere_hardware_version', N_('Minimum required Hardware version for vSphere VMs'), 13, N_('Hardware version'))
|
8
|
+
]
|
9
|
+
end
|
10
|
+
|
5
11
|
def self.load_defaults
|
6
12
|
return unless ActiveRecord::Base.connection.table_exists?('settings')
|
7
13
|
return unless super
|
8
14
|
|
9
15
|
Setting.transaction do
|
10
|
-
|
11
|
-
set('min_vsphere_hardware_version', N_('Minimum required Hardware version for vSphere VMs'), 13, N_('Hardware version'))
|
12
|
-
].compact.each { |s| Setting::Wreckingball.create s.update(category: 'Setting::Wreckingball') }
|
16
|
+
default_settings.compact.each { |s| Setting::Wreckingball.create s.update(category: 'Setting::Wreckingball') }
|
13
17
|
end
|
14
18
|
|
15
19
|
true
|
@@ -11,7 +11,7 @@ module ForemanWreckingball
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def import!
|
14
|
-
logger.info "Can not determine organization for compute resource #{compute_resource}."
|
14
|
+
logger.info "Can not determine organization for compute resource #{compute_resource}."
|
15
15
|
compute_resource.refresh_cache
|
16
16
|
compute_resource.vmware_clusters.each do |cluster|
|
17
17
|
import_hypervisors(cluster)
|
@@ -113,12 +113,10 @@ module ForemanWreckingball
|
|
113
113
|
end
|
114
114
|
|
115
115
|
def organization
|
116
|
-
return unless SETTINGS[:organizations_enabled]
|
117
116
|
compute_resource.organizations.first
|
118
117
|
end
|
119
118
|
|
120
119
|
def location
|
121
|
-
return unless SETTINGS[:locations_enabled]
|
122
120
|
compute_resource.locations.first
|
123
121
|
end
|
124
122
|
|
@@ -2,14 +2,16 @@
|
|
2
2
|
|
3
3
|
collection @hosts
|
4
4
|
|
5
|
-
attributes :name
|
5
|
+
attributes :id, :name
|
6
6
|
|
7
7
|
child owner: :owner do
|
8
8
|
attribute :name
|
9
9
|
end
|
10
10
|
|
11
|
-
|
12
|
-
|
11
|
+
if Host::Managed.reflect_on_environment?
|
12
|
+
child :environment do
|
13
|
+
attribute :name
|
14
|
+
end
|
13
15
|
end
|
14
16
|
|
15
17
|
node(:path) { |host| host_path(host) }
|
@@ -17,6 +19,7 @@ node(:path) { |host| host_path(host) }
|
|
17
19
|
node(:status) do |host|
|
18
20
|
status = host.public_send(locals[:host_association])
|
19
21
|
{
|
22
|
+
id: status.id,
|
20
23
|
label: status.to_label,
|
21
24
|
icon_class: host_global_status_icon_class(status.to_global),
|
22
25
|
status_class: host_global_status_class(status.to_global)
|
@@ -24,18 +27,11 @@ node(:status) do |host|
|
|
24
27
|
end
|
25
28
|
|
26
29
|
node(:remediate, if: lambda do |host|
|
27
|
-
locals[:supports_remediate] &&
|
28
|
-
|
29
|
-
status_id: host.public_send(locals[:host_association]).id)
|
30
|
-
.merge(auth_object: host,
|
31
|
-
permission: :remediate_vmware_status_hosts)
|
32
|
-
authorized_for(options)
|
33
|
-
end
|
34
|
-
end) do |host|
|
35
|
-
status_id = host.public_send(locals[:host_association]).id
|
30
|
+
locals[:supports_remediate] && User.current.can?(:remediate_vmware_status_hosts, host)
|
31
|
+
end) do
|
36
32
|
{
|
37
33
|
label: _('Remediate'),
|
38
34
|
title: _('Remediate Host OS'),
|
39
|
-
path:
|
35
|
+
path: schedule_remediate_hosts_path
|
40
36
|
}
|
41
37
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<div class='status-managed-hosts-dashboard-cards container-fluid container-cards-pf'>
|
2
|
+
<div class='row row-cards-pf'>
|
3
|
+
<%= render partial: 'status_managed_hosts_dashboard_cards_card', locals: {
|
4
|
+
title: _('Hosts not found in vSphere'),
|
5
|
+
count: missing_hosts_count
|
6
|
+
} %>
|
7
|
+
<%= render partial: 'status_managed_hosts_dashboard_cards_card', locals: {
|
8
|
+
title: _('Hosts associated to wrong Compute Resource'),
|
9
|
+
count: wrong_hosts_count
|
10
|
+
} %>
|
11
|
+
<%= render partial: 'status_managed_hosts_dashboard_cards_card', locals: {
|
12
|
+
title: _('Hosts found on more than one Compute Resource'),
|
13
|
+
count: more_than_one_hosts_count
|
14
|
+
} %>
|
15
|
+
</div>
|
16
|
+
</div>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<div class='col-xs-12 col-sm-4'>
|
2
|
+
<div class='card-pf card-pf-accented card-pf-aggregate-status'>
|
3
|
+
<%= content_tag :h2, title, class: 'card-pf-title' %>
|
4
|
+
<div class='card-pf-body'>
|
5
|
+
<p class='card-pf-aggregate-status-notifications'>
|
6
|
+
<%= content_tag :span, nil, class: "pficon pficon-#{count > 0 ? 'error-circle-o' : 'ok'}" %>
|
7
|
+
<%= count if count > 0 %>
|
8
|
+
</p>
|
9
|
+
</div>
|
10
|
+
</div>
|
11
|
+
</div>
|
@@ -3,18 +3,14 @@
|
|
3
3
|
<div class="list-view-pf-expand">
|
4
4
|
<span class="fa fa-angle-right"></span>
|
5
5
|
</div>
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
</ul>
|
15
|
-
</div>
|
16
|
-
<% end %>
|
17
|
-
</div>
|
6
|
+
<%=
|
7
|
+
render :partial => 'status_row_actions', locals: {
|
8
|
+
id: id,
|
9
|
+
supports_remediate: supports_remediate,
|
10
|
+
host_association: host_association,
|
11
|
+
owned_only: owned_only
|
12
|
+
}
|
13
|
+
%>
|
18
14
|
<div class="list-view-pf-main-info">
|
19
15
|
<div class="list-view-pf-left">
|
20
16
|
<span class="pficon list-view-pf-icon-md <%= classes_for_vmware_status_row(counter) %>"></span>
|