foreman_wreckingball 3.2.0 → 4.0.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 +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>
|