foreman_wreckingball 3.0.0 → 3.0.1
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/app/controllers/foreman_wreckingball/hosts_controller.rb +2 -1
- data/app/helpers/foreman_wreckingball/hypervisors_helper.rb +15 -0
- data/app/lib/fog_extensions/foreman_wreckingball/vsphere/host.rb +1 -26
- data/app/lib/fog_extensions/foreman_wreckingball/vsphere/real.rb +7 -67
- data/app/models/concerns/foreman_wreckingball/compute_resource_extensions.rb +5 -0
- data/app/models/concerns/foreman_wreckingball/host_extensions.rb +5 -0
- data/app/models/foreman_wreckingball/spectre_v2_status.rb +62 -0
- data/app/models/foreman_wreckingball/vmware_facet.rb +24 -9
- data/app/models/foreman_wreckingball/vmware_hypervisor_facet.rb +8 -0
- data/app/services/foreman_wreckingball/debris_collector.rb +249 -0
- data/app/services/foreman_wreckingball/vmware_hypervisor_importer.rb +2 -1
- data/app/views/compute_resources/_hypervisors_tab.html.erb +22 -0
- data/db/migrate/20180504135345_add_cpu_features_to_vmware_facets.rb +7 -0
- data/db/migrate/20180504135515_add_hardware_version_to_vmware_facets.rb +7 -0
- data/db/migrate/20180614105545_add_feature_capabilities_to_vmware_hypervisor_facets.rb +7 -0
- data/lib/foreman_wreckingball/engine.rb +9 -1
- data/lib/foreman_wreckingball/version.rb +1 -1
- data/test/actions/foreman_wreckingball/host/refresh_vmware_facet_test.rb +7 -2
- data/test/actions/foreman_wreckingball/host/remediate_vmware_operatingsystem_test.rb +1 -0
- data/test/controllers/compute_resources_controller_test.rb +19 -0
- data/test/factories/foreman_wreckingball_factories.rb +105 -0
- data/test/models/compute_resource_test.rb +2 -0
- data/test/models/foreman_wreckingball/spectre_v2_status_test.rb +113 -0
- data/test/models/foreman_wreckingball/vmware_facet_test.rb +56 -0
- data/test/models/foreman_wreckingball/vmware_hypervisor_facet_test.rb +27 -0
- data/test/models/host_test.rb +1 -0
- metadata +15 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d61b28b92f7f4ed29367841c4bec7b80ea38cc4610daf6e4ec78f1181ac8b5c9
|
4
|
+
data.tar.gz: 89f264e68c658e9135a07f761584f23e51b543ba8264bb4a0ead2aef132449b5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0e24c4e6c7ad4cd4eb6bb6f6e66a18712bc090fb41f60d0b639448b9763aad0655aa49a4f80206b036b25fc70d9acae8319a5d027becb8f43d6a26263152232a
|
7
|
+
data.tar.gz: 76271354a6bd79fd6263bca07ffdc8cba779b1be3ad9744f0675bc5b80c4498c214c473d2b7825af3af5f73d0f20def793bceeffcecfd784f8e0d78f2e6c8a20
|
@@ -10,7 +10,8 @@ module ForemanWreckingball
|
|
10
10
|
statuses = [
|
11
11
|
ToolsStatus,
|
12
12
|
OperatingsystemStatus,
|
13
|
-
CpuHotAddStatus
|
13
|
+
CpuHotAddStatus,
|
14
|
+
SpectreV2Status
|
14
15
|
]
|
15
16
|
|
16
17
|
@newest_data = Host.authorized(:view_hosts, Host).joins(:vmware_facet).maximum('vmware_facets.updated_at')
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ForemanWreckingball
|
4
|
+
module HypervisorsHelper
|
5
|
+
def wreckingball_spectre_v2_status(vmware_hypervisor_facet)
|
6
|
+
if vmware_hypervisor_facet.feature_capabilities.blank?
|
7
|
+
icon_text('unknown', '', kind: 'pficon', title: _('N/A'))
|
8
|
+
elsif vmware_hypervisor_facet.provides_spectre_features?
|
9
|
+
icon_text('ok', '', kind: 'pficon', title: _('CPU-Features are present on this host.'))
|
10
|
+
else
|
11
|
+
icon_text('error-circle-o', '', kind: 'pficon', title: _('Required CPU features are missing. This host is most likely vulnerable.'))
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -4,33 +4,8 @@ module FogExtensions
|
|
4
4
|
module Host
|
5
5
|
extend ActiveSupport::Concern
|
6
6
|
|
7
|
-
module Overrides
|
8
|
-
def vm_ids
|
9
|
-
attributes[:vm_ids] = attributes[:vm_ids].call if attributes[:vm_ids].is_a?(Proc)
|
10
|
-
attributes[:vm_ids]
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
7
|
included do
|
15
|
-
|
16
|
-
|
17
|
-
attribute :cpu_cores
|
18
|
-
attribute :cpu_sockets
|
19
|
-
attribute :cpu_threads
|
20
|
-
attribute :memory
|
21
|
-
attribute :uuid
|
22
|
-
attribute :model
|
23
|
-
attribute :vendor
|
24
|
-
attribute :ipaddress
|
25
|
-
attribute :ipaddress6
|
26
|
-
attribute :product_name
|
27
|
-
attribute :product_version
|
28
|
-
attribute :hostname
|
29
|
-
attribute :domainname
|
30
|
-
end
|
31
|
-
|
32
|
-
def memory_mb
|
33
|
-
memory / 1024 / 1024
|
8
|
+
attribute :feature_capabilities
|
34
9
|
end
|
35
10
|
end
|
36
11
|
end
|
@@ -5,80 +5,20 @@ module FogExtensions
|
|
5
5
|
extend ActiveSupport::Concern
|
6
6
|
|
7
7
|
module Overrides
|
8
|
-
def
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
def host_system_attribute_mapping
|
9
|
+
super.merge(
|
10
|
+
feature_capabilities: 'config.featureCapability'
|
11
|
+
)
|
12
|
+
end
|
12
13
|
|
13
|
-
|
14
|
-
|
15
|
-
hsh.merge(
|
16
|
-
datacenter: filters[:datacenter],
|
17
|
-
cluster: filters[:cluster],
|
18
|
-
ipaddress: (host['config.network.vnic'].first.spec.ip.ipAddress rescue nil),
|
19
|
-
ipaddress6: (host['config.network.vnic'].first.spec.ip.ipV6Config.ipV6Address.first.ipAddress rescue nil),
|
20
|
-
vm_ids: Proc.new { host['vm'].map {|vm| vm.config.instanceUuid rescue nil} }
|
21
|
-
)
|
22
|
-
end
|
14
|
+
def list_hosts(filters = {})
|
15
|
+
super.map { |h| h[:feature_capabilities] = h[:feature_capabilities].map(&:key); h }
|
23
16
|
end
|
24
17
|
end
|
25
18
|
|
26
19
|
included do
|
27
20
|
prepend Overrides
|
28
21
|
end
|
29
|
-
|
30
|
-
protected
|
31
|
-
|
32
|
-
def map_attrs_to_hash(obj, attribute_mapping)
|
33
|
-
attribute_mapping.each_with_object({}) do |(k, v), hsh|
|
34
|
-
hsh[k] = obj[v]
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def property_collector_results(filter_spec)
|
39
|
-
property_collector = connection.serviceContent.propertyCollector
|
40
|
-
property_collector.RetrieveProperties(:specSet => [filter_spec])
|
41
|
-
end
|
42
|
-
|
43
|
-
def compute_resource_host_traversal_spec
|
44
|
-
RbVmomi::VIM.TraversalSpec(
|
45
|
-
:name => 'computeResourceHostTraversalSpec',
|
46
|
-
:type => 'ComputeResource',
|
47
|
-
:path => 'host',
|
48
|
-
:skip => false
|
49
|
-
)
|
50
|
-
end
|
51
|
-
|
52
|
-
def host_system_filter_spec(obj)
|
53
|
-
RbVmomi::VIM.PropertyFilterSpec(
|
54
|
-
:objectSet => [
|
55
|
-
:obj => obj,
|
56
|
-
:selectSet => [
|
57
|
-
compute_resource_host_traversal_spec
|
58
|
-
]
|
59
|
-
],
|
60
|
-
:propSet => [
|
61
|
-
{ :type => 'HostSystem', :pathSet => host_system_attribute_mapping.values + ['config.network.vnic', 'vm'] }
|
62
|
-
]
|
63
|
-
)
|
64
|
-
end
|
65
|
-
|
66
|
-
def host_system_attribute_mapping
|
67
|
-
{
|
68
|
-
name: 'name',
|
69
|
-
cpu_cores: 'hardware.cpuInfo.numCpuCores',
|
70
|
-
cpu_sockets: 'hardware.cpuInfo.numCpuPackages',
|
71
|
-
cpu_threads: 'hardware.cpuInfo.numCpuThreads',
|
72
|
-
memory: 'hardware.memorySize',
|
73
|
-
uuid: 'hardware.systemInfo.uuid',
|
74
|
-
model: 'hardware.systemInfo.model',
|
75
|
-
vendor: 'hardware.systemInfo.vendor',
|
76
|
-
product_name: 'summary.config.product.name',
|
77
|
-
product_version: 'summary.config.product.version',
|
78
|
-
hostname: 'config.network.dnsConfig.hostName',
|
79
|
-
domainname: 'config.network.dnsConfig.domainName'
|
80
|
-
}
|
81
|
-
end
|
82
22
|
end
|
83
23
|
end
|
84
24
|
end
|
@@ -8,6 +8,11 @@ module ForemanWreckingball
|
|
8
8
|
included do
|
9
9
|
has_many :vmware_clusters, :class_name => 'ForemanWreckingball::VmwareCluster',
|
10
10
|
:inverse_of => :compute_resource, :dependent => :destroy
|
11
|
+
|
12
|
+
has_many :vmware_hypervisor_facets, :class_name => '::ForemanWreckingball::VmwareHypervisorFacet', :through => :vmware_clusters,
|
13
|
+
:inverse_of => :compute_resource
|
14
|
+
|
15
|
+
has_many :hypervisor_hosts, :class_name => 'Host::Managed', :through => :vmware_hypervisor_facets, :source => :host, :inverse_of => :compute_resource
|
11
16
|
end
|
12
17
|
|
13
18
|
def action_input_key
|
@@ -21,6 +21,11 @@ module ForemanWreckingball
|
|
21
21
|
:foreign_key => 'host_id',
|
22
22
|
:inverse_of => :host,
|
23
23
|
:dependent => :destroy
|
24
|
+
has_one :vmware_spectre_v2_status_object,
|
25
|
+
:class_name => 'ForemanWreckingball::SpectreV2Status',
|
26
|
+
:foreign_key => 'host_id',
|
27
|
+
:inverse_of => :host,
|
28
|
+
:dependent => :destroy
|
24
29
|
end
|
25
30
|
|
26
31
|
def action_input_key
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ForemanWreckingball
|
4
|
+
class SpectreV2Status < ::HostStatus::Status
|
5
|
+
ENABLED = 0
|
6
|
+
MISSING = 1
|
7
|
+
|
8
|
+
def self.status_name
|
9
|
+
N_('Spectre v2 Guest Mitigation Enabled')
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.host_association
|
13
|
+
:vmware_spectre_v2_status_object
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.description
|
17
|
+
N_('In order to use hardware based branch target injection mitigation within virtual machines, Hypervisor-Assisted Guest Mitigation must be enabled.')
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.supports_remediate?
|
21
|
+
false
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_status(_options = {})
|
25
|
+
guest_mitigation_enabled? ? ENABLED : MISSING
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_global(_options = {})
|
29
|
+
case status
|
30
|
+
when MISSING
|
31
|
+
HostStatus::Global::ERROR
|
32
|
+
else
|
33
|
+
HostStatus::Global::OK
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def to_label(_options = {})
|
38
|
+
case status
|
39
|
+
when MISSING
|
40
|
+
N_('Guest Mitigation Missing')
|
41
|
+
else
|
42
|
+
N_('Guest Mitigation Enabled')
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def relevant?(_options = {})
|
47
|
+
host && host&.vmware_facet && host.vmware_facet.cpu_features.any?
|
48
|
+
end
|
49
|
+
|
50
|
+
def guest_mitigation_enabled?
|
51
|
+
recent_hw_version? && required_cpu_features_present?
|
52
|
+
end
|
53
|
+
|
54
|
+
def recent_hw_version?
|
55
|
+
host.vmware_facet.hardware_version.gsub(/^vmx-/, '').to_i >= 9
|
56
|
+
end
|
57
|
+
|
58
|
+
def required_cpu_features_present?
|
59
|
+
!(host.vmware_facet.cpu_features & ['cpuid.IBRS', 'cpuid.IBPB', 'cpuid.STIBP']).empty?
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -19,6 +19,8 @@ module ForemanWreckingball
|
|
19
19
|
|
20
20
|
validates :host, :presence => true, :allow_blank => false
|
21
21
|
|
22
|
+
serialize :cpu_features, JSON
|
23
|
+
|
22
24
|
def tools_state_label
|
23
25
|
case tools_state.to_sym
|
24
26
|
when :toolsNotInstalled
|
@@ -35,22 +37,35 @@ module ForemanWreckingball
|
|
35
37
|
def refresh!
|
36
38
|
vm = host.compute_object
|
37
39
|
return unless vm
|
38
|
-
|
39
|
-
:
|
40
|
-
:
|
41
|
-
:
|
42
|
-
:
|
43
|
-
:
|
44
|
-
:
|
45
|
-
:
|
46
|
-
|
40
|
+
data_for_update = {
|
41
|
+
vmware_cluster: ::ForemanWreckingball::VmwareCluster.find_by(name: vm.cluster, compute_resource: host.compute_resource),
|
42
|
+
cpus: vm.cpus,
|
43
|
+
corespersocket: vm.corespersocket,
|
44
|
+
memory_mb: vm.memory_mb,
|
45
|
+
tools_state: vm.tools_state,
|
46
|
+
guest_id: vm.guest_id,
|
47
|
+
cpu_hot_add: vm.cpuHotAddEnabled,
|
48
|
+
hardware_version: vm.hardware_version,
|
49
|
+
cpu_features: []
|
50
|
+
}
|
51
|
+
data_for_update[:cpu_features] = raw_vm_object.runtime.featureRequirement.map(&:key) if vm.ready?
|
52
|
+
update(data_for_update)
|
47
53
|
end
|
48
54
|
|
49
55
|
def refresh_statuses
|
50
56
|
host.get_status(::ForemanWreckingball::ToolsStatus).refresh!
|
51
57
|
host.get_status(::ForemanWreckingball::CpuHotAddStatus).refresh!
|
52
58
|
host.get_status(::ForemanWreckingball::OperatingsystemStatus).refresh!
|
59
|
+
host.get_status(::ForemanWreckingball::SpectreV2Status).refresh!
|
53
60
|
host.refresh_global_status!
|
54
61
|
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def raw_vm_object
|
66
|
+
instance_uuid = host.compute_object.try(:instance_uuid)
|
67
|
+
return unless instance_uuid
|
68
|
+
host.compute_resource.send(:client).send(:get_vm_ref, instance_uuid)
|
69
|
+
end
|
55
70
|
end
|
56
71
|
end
|
@@ -10,11 +10,19 @@ module ForemanWreckingball
|
|
10
10
|
|
11
11
|
belongs_to :vmware_cluster, :inverse_of => :vmware_hypervisor_facets, :class_name => 'ForemanWreckingball::VmwareCluster'
|
12
12
|
|
13
|
+
has_one :compute_resource, :inverse_of => :vmware_hypervisor_facets, :through => :vmware_cluster
|
14
|
+
|
13
15
|
has_many :vmware_facets, :class_name => '::ForemanWreckingball::VmwareFacet', :through => :vmware_clusters,
|
14
16
|
:inverse_of => :vmware_hypervisor_facets
|
15
17
|
|
18
|
+
serialize :feature_capabilities, JSON
|
19
|
+
|
16
20
|
def self.sanitize_name(name)
|
17
21
|
name.tr('_', '-').chomp('.').downcase
|
18
22
|
end
|
23
|
+
|
24
|
+
def provides_spectre_features?
|
25
|
+
!((feature_capabilities || []) & ['cpuid.IBRS', 'cpuid.IBPB', 'cpuid.STIBP']).empty?
|
26
|
+
end
|
19
27
|
end
|
20
28
|
end
|
@@ -0,0 +1,249 @@
|
|
1
|
+
require 'rbvmomi'
|
2
|
+
|
3
|
+
module ForemanWreckingball
|
4
|
+
class DebrisCollector
|
5
|
+
|
6
|
+
PROPERTY_MAPPING = {
|
7
|
+
:VirtualMachine => {
|
8
|
+
mapped: {
|
9
|
+
cpus: 'config.hardware.numCPU',
|
10
|
+
corespersocket: 'config.hardware.numCoresPerSocket',
|
11
|
+
memory_mb: 'config.hardware.memoryMB',
|
12
|
+
tools_state: 'guest.toolsStatus',
|
13
|
+
guest_id: 'config.guestId',
|
14
|
+
cpu_hot_add: 'config.cpuHotAddEnabled',
|
15
|
+
hardware_version: 'config.version',
|
16
|
+
#cpu_features: ''
|
17
|
+
},
|
18
|
+
additional: [
|
19
|
+
'name',
|
20
|
+
'config.instanceUuid'
|
21
|
+
]
|
22
|
+
},
|
23
|
+
:Folder => {
|
24
|
+
mapped: {
|
25
|
+
name: 'name'
|
26
|
+
},
|
27
|
+
additional: [
|
28
|
+
'childEntity'
|
29
|
+
]
|
30
|
+
},
|
31
|
+
}.freeze
|
32
|
+
|
33
|
+
attr_reader :compute_resource
|
34
|
+
attr_accessor :version, :stop_requested
|
35
|
+
|
36
|
+
delegate :logger, to: ::Rails
|
37
|
+
|
38
|
+
def initialize(compute_resource:)
|
39
|
+
logger.debug "Wreckingball Debris Collector: Initializing."
|
40
|
+
@compute_resource = compute_resource
|
41
|
+
self.version = ''
|
42
|
+
self.stop_requested = false
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
def run
|
47
|
+
logger.debug "Wreckingball Debris Collector: Started."
|
48
|
+
|
49
|
+
property_filter
|
50
|
+
|
51
|
+
logger.debug "Wreckingball Debris Collector: Starting initial import."
|
52
|
+
initial_refresh
|
53
|
+
logger.debug "Wreckingball Debris Collector: Finished initial import."
|
54
|
+
|
55
|
+
logger.debug "Wreckingball Debris Collector: Finished."
|
56
|
+
ensure
|
57
|
+
destroy_property_filter
|
58
|
+
end
|
59
|
+
|
60
|
+
def stop
|
61
|
+
logger.debug "Wreckingball Debris Collector: Stop requested."
|
62
|
+
self.stop_requested = true
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def initial_refresh
|
68
|
+
monitor_updates
|
69
|
+
end
|
70
|
+
|
71
|
+
def monitor_updates
|
72
|
+
begin
|
73
|
+
update_set = wait_for_updates
|
74
|
+
return version if update_set.nil?
|
75
|
+
|
76
|
+
self.version = update_set.version
|
77
|
+
process_update_set(update_set)
|
78
|
+
end while update_set.truncated
|
79
|
+
end
|
80
|
+
|
81
|
+
def process_update_set(update_set)
|
82
|
+
property_filter_update = update_set.filterSet.to_a.detect do |update|
|
83
|
+
update.filter == property_filter
|
84
|
+
end
|
85
|
+
return if property_filter_update.nil?
|
86
|
+
|
87
|
+
object_update_set = property_filter_update.objectSet
|
88
|
+
return if object_update_set.blank?
|
89
|
+
|
90
|
+
logger.debug "Wreckingball Debris Collector: Processing #{object_update_set.count} updates..."
|
91
|
+
|
92
|
+
process_object_update_set(object_update_set)
|
93
|
+
|
94
|
+
logger.debug "Wreckingball Debris Collector: Processing #{object_update_set.count} updates... completed."
|
95
|
+
end
|
96
|
+
|
97
|
+
def process_object_update_set(object_update_set)
|
98
|
+
object_update_set.each do |object_update|
|
99
|
+
process_object_update(object_update)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def process_object_update(object_update)
|
104
|
+
managed_object = object_update.obj
|
105
|
+
|
106
|
+
logger.debug "#{object_update.kind} #{object_update.obj.class.wsdl_name}:#{object_update.obj._ref}"
|
107
|
+
|
108
|
+
case object_update.obj.class.wsdl_name
|
109
|
+
when 'VirtualMachine'
|
110
|
+
process_virtual_machine_update(object_update)
|
111
|
+
else
|
112
|
+
# Ignore this for now
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def process_virtual_machine_update(object_update)
|
117
|
+
managed_object = object_update.obj
|
118
|
+
# TODO: Cache this
|
119
|
+
uuid = managed_object.config.instanceUuid
|
120
|
+
|
121
|
+
logger.error "Processing for uuid #{uuid}"
|
122
|
+
|
123
|
+
host = Host::Managed.find_by(compute_resource: compute_resource, uuid: uuid)
|
124
|
+
|
125
|
+
return unless host
|
126
|
+
|
127
|
+
facet = host.vmware_facet || host.build_vmware_facet
|
128
|
+
|
129
|
+
# TODO: Cluster
|
130
|
+
facet.update(
|
131
|
+
map_update_to_properties(:VirtualMachine, object_update.changeSet)
|
132
|
+
)
|
133
|
+
end
|
134
|
+
|
135
|
+
def map_update_to_properties(type, change_set)
|
136
|
+
mapping = PROPERTY_MAPPING[type][:mapped]
|
137
|
+
|
138
|
+
change_set.each_with_object({}) do |property_change, hsh|
|
139
|
+
hsh[mapping.key(property_change.name)] = property_change.val if mapping.key(property_change.name)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def wait_for_updates
|
144
|
+
connection.propertyCollector.WaitForUpdatesEx(
|
145
|
+
:version => version,
|
146
|
+
:options => wait_for_updates_options
|
147
|
+
)
|
148
|
+
end
|
149
|
+
|
150
|
+
def wait_for_updates_options
|
151
|
+
RbVmomi::VIM.WaitOptions(
|
152
|
+
:maxWaitSeconds => 10
|
153
|
+
)
|
154
|
+
end
|
155
|
+
|
156
|
+
def property_filter
|
157
|
+
@property_filter ||= create_property_filter
|
158
|
+
end
|
159
|
+
|
160
|
+
def property_set
|
161
|
+
PROPERTY_MAPPING.map do |type, properties|
|
162
|
+
RbVmomi::VIM::PropertySpec(
|
163
|
+
type: type,
|
164
|
+
pathSet: properties[:mapped].values + (properties[:additional] || [])
|
165
|
+
)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
def traversal_spec_folder_to_child_entity
|
170
|
+
RbVmomi::VIM.TraversalSpec(
|
171
|
+
:name => 'FolderTraversalSpec',
|
172
|
+
:type => 'Folder',
|
173
|
+
:path => 'childEntity',
|
174
|
+
:skip => false,
|
175
|
+
:selectSet => [
|
176
|
+
RbVmomi::VIM.SelectionSpec(:name => 'FolderTraversalSpec'),
|
177
|
+
#RbVmomi::VIM.SelectionSpec(:name => 'tsDcToDsFolder'),
|
178
|
+
#RbVmomi::VIM.SelectionSpec(:name => 'tsDcToHostFolder'),
|
179
|
+
#RbVmomi::VIM.SelectionSpec(:name => 'tsDcToNetworkFolder'),
|
180
|
+
RbVmomi::VIM.SelectionSpec(:name => 'DatacenterToVmFolderTraversalSpec'),
|
181
|
+
#RbVmomi::VIM.SelectionSpec(:name => 'tsCrToHost'),
|
182
|
+
#RbVmomi::VIM.SelectionSpec(:name => 'tsCrToRp'),
|
183
|
+
#RbVmomi::VIM.SelectionSpec(:name => 'tsRpToRp'),
|
184
|
+
#RbVmomi::VIM.SelectionSpec(:name => 'tsRpToVm')
|
185
|
+
]
|
186
|
+
)
|
187
|
+
end
|
188
|
+
|
189
|
+
def traversal_spec_datacenter_to_vm_folder
|
190
|
+
RbVmomi::VIM.TraversalSpec(
|
191
|
+
:name => 'DatacenterToVmFolderTraversalSpec',
|
192
|
+
:type => 'Datacenter',
|
193
|
+
:path => 'vmFolder',
|
194
|
+
:skip => false,
|
195
|
+
:selectSet => [
|
196
|
+
RbVmomi::VIM.SelectionSpec(:name => 'FolderTraversalSpec')
|
197
|
+
]
|
198
|
+
)
|
199
|
+
end
|
200
|
+
|
201
|
+
def object_set(root)
|
202
|
+
traversal_spec = [
|
203
|
+
traversal_spec_folder_to_child_entity,
|
204
|
+
#datacenter_to_datastore_folder,
|
205
|
+
#datacenter_to_host_folder,
|
206
|
+
#datacenter_to_network_folder,
|
207
|
+
traversal_spec_datacenter_to_vm_folder
|
208
|
+
#compute_resource_to_host,
|
209
|
+
#compute_resource_to_resource_pool,
|
210
|
+
#resource_pool_to_resource_pool,
|
211
|
+
#resource_pool_to_vm,
|
212
|
+
]
|
213
|
+
|
214
|
+
RbVmomi::VIM.ObjectSpec(
|
215
|
+
:obj => root,
|
216
|
+
:selectSet => traversal_spec
|
217
|
+
)
|
218
|
+
end
|
219
|
+
|
220
|
+
def create_property_filter
|
221
|
+
property_filter_spec = RbVmomi::VIM.PropertyFilterSpec(
|
222
|
+
:objectSet => [
|
223
|
+
object_set(
|
224
|
+
root_folder
|
225
|
+
)
|
226
|
+
],
|
227
|
+
:propSet => property_set
|
228
|
+
)
|
229
|
+
|
230
|
+
connection.propertyCollector.CreateFilter(
|
231
|
+
:spec => property_filter_spec,
|
232
|
+
:partialUpdates => true
|
233
|
+
)
|
234
|
+
end
|
235
|
+
|
236
|
+
def destroy_property_filter
|
237
|
+
return unless @property_filter
|
238
|
+
@property_filter.DestroyPropertyFilter
|
239
|
+
end
|
240
|
+
|
241
|
+
def root_folder
|
242
|
+
connection.serviceContent.rootFolder
|
243
|
+
end
|
244
|
+
|
245
|
+
def connection
|
246
|
+
compute_resource.send(:client).send(:connection)
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
@@ -63,7 +63,8 @@ module ForemanWreckingball
|
|
63
63
|
:cpu_sockets => hypervisor.cpu_sockets,
|
64
64
|
:cpu_threads => hypervisor.cpu_threads,
|
65
65
|
:memory => hypervisor.memory,
|
66
|
-
:uuid => hypervisor.uuid
|
66
|
+
:uuid => hypervisor.uuid,
|
67
|
+
:feature_capabilities => hypervisor.feature_capabilities
|
67
68
|
}
|
68
69
|
)
|
69
70
|
if result
|
@@ -0,0 +1,22 @@
|
|
1
|
+
<table class="<%= table_css_classes 'table-fixed' %>">
|
2
|
+
<thead>
|
3
|
+
<tr>
|
4
|
+
<th><%= _('Name') %></th>
|
5
|
+
<th class="col-md-3"><%= _('Cluster') %></th>
|
6
|
+
<th class="col-md-1"><%= _('Cores') %></th>
|
7
|
+
<th class="col-md-1"><%= _('Sockets') %></th>
|
8
|
+
<th class="col-md-1"><%= _('Spectre v2') %></th>
|
9
|
+
</tr>
|
10
|
+
</thead>
|
11
|
+
<tbody>
|
12
|
+
<% @compute_resource.hypervisor_hosts.includes(:vmware_hypervisor_facet, :vmware_cluster).each do |host| %>
|
13
|
+
<tr>
|
14
|
+
<td class="ellipsis"><%= link_to_if_authorized(host.name, hash_for_host_path(:id => host)) %></td>
|
15
|
+
<td><%= host.vmware_cluster.name %></td>
|
16
|
+
<td><%= host.vmware_hypervisor_facet.cpu_cores %></td>
|
17
|
+
<td><%= host.vmware_hypervisor_facet.cpu_sockets %></td>
|
18
|
+
<td><%= wreckingball_spectre_v2_status(host.vmware_hypervisor_facet) %></td>
|
19
|
+
</tr>
|
20
|
+
<% end %>
|
21
|
+
</tbody>
|
22
|
+
</table>
|
@@ -55,6 +55,14 @@ module ForemanWreckingball
|
|
55
55
|
register_facet(ForemanWreckingball::VmwareHypervisorFacet, :vmware_hypervisor_facet)
|
56
56
|
|
57
57
|
add_controller_action_scope(HostsController, :index) { |base_scope| base_scope.includes(:vmware_facet) }
|
58
|
+
|
59
|
+
# extend host show page
|
60
|
+
extend_page('compute_resources/show') do |context|
|
61
|
+
context.add_pagelet :main_tabs,
|
62
|
+
:name => N_('Hypervisors'),
|
63
|
+
:partial => 'compute_resources/hypervisors_tab',
|
64
|
+
:onlyif => proc { |cr| cr.provider_friendly_name == 'VMware' && cr.vmware_hypervisor_facets.any? }
|
65
|
+
end
|
58
66
|
end
|
59
67
|
end
|
60
68
|
|
@@ -95,7 +103,7 @@ module ForemanWreckingball
|
|
95
103
|
require 'fog/vsphere'
|
96
104
|
require 'fog/vsphere/compute'
|
97
105
|
require 'fog/vsphere/models/compute/host'
|
98
|
-
!::Fog::Compute::Vsphere::Host.instance_methods.include?(:
|
106
|
+
!::Fog::Compute::Vsphere::Host.instance_methods.include?(:feature_capabilities)
|
99
107
|
rescue LoadError
|
100
108
|
false
|
101
109
|
end
|
@@ -7,8 +7,15 @@ module Actions
|
|
7
7
|
module Vmware
|
8
8
|
class RefreshVmwareFacetTest < ActiveSupport::TestCase
|
9
9
|
include ::Dynflow::Testing
|
10
|
+
|
11
|
+
let(:uuid) { '5032c8a5-9c5e-ba7a-3804-832a03e16381' }
|
12
|
+
let(:vm) { compute_resource.find_vm_by_uuid(uuid) }
|
13
|
+
|
10
14
|
setup do
|
11
15
|
::Fog.mock!
|
16
|
+
::Fog::Compute::Vsphere::Mock.any_instance.stubs(:get_vm_ref).returns(vm)
|
17
|
+
::Fog::Compute::Vsphere::Server.any_instance.stubs(:ready?).returns(false)
|
18
|
+
::ForemanWreckingball::SpectreV2Status.any_instance.stubs(:recent_hw_version?).returns(true)
|
12
19
|
# this is not stubbed correctly in fog-vsphere
|
13
20
|
Fog::Compute::Vsphere::Server.any_instance.stubs(:cpuHotAddEnabled).returns(false)
|
14
21
|
end
|
@@ -18,8 +25,6 @@ module Actions
|
|
18
25
|
cr = FactoryBot.create(:compute_resource, :vmware, :uuid => 'Solutions')
|
19
26
|
ComputeResource.find(cr.id)
|
20
27
|
end
|
21
|
-
let(:uuid) { '5032c8a5-9c5e-ba7a-3804-832a03e16381' }
|
22
|
-
let(:vm) { compute_resource.find_vm_by_uuid(uuid) }
|
23
28
|
|
24
29
|
let(:host) do
|
25
30
|
FactoryBot.create(
|
@@ -11,6 +11,7 @@ module Actions
|
|
11
11
|
::Fog.mock!
|
12
12
|
# this is not stubbed correctly in fog-vsphere
|
13
13
|
Fog::Compute::Vsphere::Server.any_instance.stubs(:cpuHotAddEnabled).returns(false)
|
14
|
+
::ForemanWreckingball::SpectreV2Status.any_instance.stubs(:recent_hw_version?).returns(true)
|
14
15
|
end
|
15
16
|
teardown { ::Fog.unmock! }
|
16
17
|
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'test_plugin_helper'
|
4
|
+
|
5
|
+
class ComputeResourcesControllerTest < ActionController::TestCase
|
6
|
+
describe '#show' do
|
7
|
+
let(:compute_resource) { FactoryBot.create(:compute_resource, :vmware) }
|
8
|
+
let(:vmware_cluster) { FactoryBot.create(:vmware_cluster, compute_resource: compute_resource) }
|
9
|
+
|
10
|
+
test 'shows a compute resource with hypervisors' do
|
11
|
+
skip if Gem::Version.new(Foreman::Version.new.to_s) < Gem::Version.new('1.19.0')
|
12
|
+
FactoryBot.create_list(:vmware_hypervisor_facet, 5, vmware_cluster: vmware_cluster)
|
13
|
+
|
14
|
+
get :show, params: { :id => compute_resource.to_param }, session: set_session_user
|
15
|
+
assert_response :success
|
16
|
+
assert @response.body.match(/Hypervisors/)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -9,6 +9,29 @@ FactoryBot.define do
|
|
9
9
|
memory_mb 8192
|
10
10
|
guest_id 'rhel6_64Guest'
|
11
11
|
cpu_hot_add false
|
12
|
+
hardware_version 'vmx-10'
|
13
|
+
cpu_features [
|
14
|
+
'cpuid.SSE3',
|
15
|
+
'cpuid.PCLMULQDQ',
|
16
|
+
'cpuid.SSSE3',
|
17
|
+
'cpuid.CMPXCHG16B',
|
18
|
+
'cpuid.PCID',
|
19
|
+
'cpuid.SSE41',
|
20
|
+
'cpuid.SSE42',
|
21
|
+
'cpuid.POPCNT',
|
22
|
+
'cpuid.AES',
|
23
|
+
'cpuid.XSAVE',
|
24
|
+
'cpuid.AVX',
|
25
|
+
'cpuid.DS',
|
26
|
+
'cpuid.SS',
|
27
|
+
'cpuid.XCR0_MASTER_SSE',
|
28
|
+
'cpuid.XCR0_MASTER_YMM_H',
|
29
|
+
'cpuid.LAHF64',
|
30
|
+
'cpuid.NX',
|
31
|
+
'cpuid.RDTSCP',
|
32
|
+
'cpuid.LM',
|
33
|
+
'cpuid.Intel'
|
34
|
+
]
|
12
35
|
host
|
13
36
|
end
|
14
37
|
|
@@ -20,6 +43,88 @@ FactoryBot.define do
|
|
20
43
|
cpu_threads 36
|
21
44
|
memory 412_046_372_864
|
22
45
|
uuid { SecureRandom.uuid }
|
46
|
+
feature_capabilities [
|
47
|
+
'cpuid.3DNOW',
|
48
|
+
'cpuid.3DNOWPLUS',
|
49
|
+
'cpuid.3DNPREFETCH',
|
50
|
+
'cpuid.ABM',
|
51
|
+
'cpuid.ADX',
|
52
|
+
'cpuid.AES',
|
53
|
+
'cpuid.AMD',
|
54
|
+
'cpuid.AVX',
|
55
|
+
'cpuid.AVX2',
|
56
|
+
'cpuid.BMI1',
|
57
|
+
'cpuid.BMI2',
|
58
|
+
'cpuid.CMPXCHG16B',
|
59
|
+
'cpuid.CR8AVAIL',
|
60
|
+
'cpuid.Cyrix',
|
61
|
+
'cpuid.DS',
|
62
|
+
'cpuid.ENFSTRG',
|
63
|
+
'cpuid.EXTAPICSPC',
|
64
|
+
'cpuid.F16C',
|
65
|
+
'cpuid.FFXSR',
|
66
|
+
'cpuid.FMA',
|
67
|
+
'cpuid.FMA4',
|
68
|
+
'cpuid.FSGSBASE',
|
69
|
+
'cpuid.HLE',
|
70
|
+
'cpuid.IBPB',
|
71
|
+
'cpuid.IBRS',
|
72
|
+
'cpuid.INVPCID',
|
73
|
+
'cpuid.Intel',
|
74
|
+
'cpuid.LAHF64',
|
75
|
+
'cpuid.LM',
|
76
|
+
'cpuid.MISALIGNED_SSE',
|
77
|
+
'cpuid.MMXEXT',
|
78
|
+
'cpuid.MOVBE',
|
79
|
+
'cpuid.MWAIT',
|
80
|
+
'cpuid.NX',
|
81
|
+
'cpuid.PCID',
|
82
|
+
'cpuid.PCLMULQDQ',
|
83
|
+
'cpuid.PDPE1GB',
|
84
|
+
'cpuid.POPCNT',
|
85
|
+
'cpuid.PSN',
|
86
|
+
'cpuid.RDRAND',
|
87
|
+
'cpuid.RDSEED',
|
88
|
+
'cpuid.RDTSCP',
|
89
|
+
'cpuid.RTM',
|
90
|
+
'cpuid.SMAP',
|
91
|
+
'cpuid.SMEP',
|
92
|
+
'cpuid.SS',
|
93
|
+
'cpuid.SSE3',
|
94
|
+
'cpuid.SSE41',
|
95
|
+
'cpuid.SSE42',
|
96
|
+
'cpuid.SSE4A',
|
97
|
+
'cpuid.SSSE3',
|
98
|
+
'cpuid.STIBP',
|
99
|
+
'cpuid.SVM',
|
100
|
+
'cpuid.SVM_DECODE_ASSISTS',
|
101
|
+
'cpuid.SVM_FLUSH_BY_ASID',
|
102
|
+
'cpuid.SVM_NPT',
|
103
|
+
'cpuid.SVM_NRIP',
|
104
|
+
'cpuid.SVM_VMCB_CLEAN',
|
105
|
+
'cpuid.TBM',
|
106
|
+
'cpuid.VIA',
|
107
|
+
'cpuid.VMX',
|
108
|
+
'cpuid.XCR0_MASTER_SSE',
|
109
|
+
'cpuid.XCR0_MASTER_YMM_H',
|
110
|
+
'cpuid.XOP',
|
111
|
+
'cpuid.XSAVE',
|
112
|
+
'cpuid.XSAVEOPT',
|
113
|
+
'hv.capable',
|
114
|
+
'misc.cpuidFaulting',
|
115
|
+
'vpmc.fixctr.0',
|
116
|
+
'vpmc.fixedWidth',
|
117
|
+
'vpmc.genWidth',
|
118
|
+
'vpmc.genctr.0',
|
119
|
+
'vpmc.genctr.1',
|
120
|
+
'vpmc.genctr.2',
|
121
|
+
'vpmc.genctr.3',
|
122
|
+
'vpmc.microarchitecture.ivybridge',
|
123
|
+
'vpmc.numFixedCtrs',
|
124
|
+
'vpmc.numGenCtrs',
|
125
|
+
'vpmc.version',
|
126
|
+
'vt.realmode'
|
127
|
+
]
|
23
128
|
end
|
24
129
|
|
25
130
|
factory :vmware_cluster, class: 'ForemanWreckingball::VmwareCluster' do
|
@@ -0,0 +1,113 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'test_plugin_helper'
|
4
|
+
|
5
|
+
module ForemanWreckingball
|
6
|
+
class SpectreV2StatusTest < ActiveSupport::TestCase
|
7
|
+
setup do
|
8
|
+
User.current = users(:admin)
|
9
|
+
end
|
10
|
+
|
11
|
+
should belong_to(:host)
|
12
|
+
|
13
|
+
let(:host) do
|
14
|
+
FactoryBot.create(
|
15
|
+
:host,
|
16
|
+
:managed,
|
17
|
+
:with_vmware_facet
|
18
|
+
)
|
19
|
+
end
|
20
|
+
let(:status) { ForemanWreckingball::SpectreV2Status.new(host: host) }
|
21
|
+
|
22
|
+
test 'has a host association' do
|
23
|
+
status.save!
|
24
|
+
assert_equal status, host.public_send(status.class.host_association)
|
25
|
+
end
|
26
|
+
|
27
|
+
test '#relevant is only for hosts with a vmware facet' do
|
28
|
+
h = FactoryBot.build(:host, :managed)
|
29
|
+
refute ForemanWreckingball::ToolsStatus.new(host: h).relevant?
|
30
|
+
assert status.relevant?
|
31
|
+
end
|
32
|
+
|
33
|
+
test '#relevant is for hosts with cpu features' do
|
34
|
+
assert status.relevant?
|
35
|
+
host.vmware_facet.cpu_features = []
|
36
|
+
refute status.relevant?
|
37
|
+
end
|
38
|
+
|
39
|
+
describe 'status calculation' do
|
40
|
+
test 'is missing when mitigations are missing' do
|
41
|
+
status.stubs(:guest_mitigation_enabled?).returns(false)
|
42
|
+
assert_equal SpectreV2Status::MISSING, status.to_status
|
43
|
+
end
|
44
|
+
|
45
|
+
test 'is enabled when mitigations are present' do
|
46
|
+
status.stubs(:guest_mitigation_enabled?).returns(true)
|
47
|
+
assert_equal SpectreV2Status::ENABLED, status.to_status
|
48
|
+
end
|
49
|
+
|
50
|
+
test 'is missing when hardware version is ancient' do
|
51
|
+
status.stubs(:recent_hw_version?).returns(false)
|
52
|
+
assert_equal SpectreV2Status::MISSING, status.to_status
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe 'status labels' do
|
57
|
+
test 'when mitigations are missing' do
|
58
|
+
status.status = SpectreV2Status::MISSING
|
59
|
+
assert_equal 'Guest Mitigation Missing', status.to_label
|
60
|
+
end
|
61
|
+
|
62
|
+
test 'when mitigations are present' do
|
63
|
+
status.status = SpectreV2Status::ENABLED
|
64
|
+
assert_equal 'Guest Mitigation Enabled', status.to_label
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe 'global status' do
|
69
|
+
test 'is error when mitigations are missing' do
|
70
|
+
status.status = SpectreV2Status::MISSING
|
71
|
+
assert_equal HostStatus::Global::ERROR, status.to_global
|
72
|
+
end
|
73
|
+
|
74
|
+
test 'is ok when mitigations are present' do
|
75
|
+
status.status = SpectreV2Status::ENABLED
|
76
|
+
assert_equal HostStatus::Global::OK, status.to_global
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe '#recent_hw_version?' do
|
81
|
+
test 'is true when hw version is quite new' do
|
82
|
+
assert status.recent_hw_version?
|
83
|
+
end
|
84
|
+
|
85
|
+
test 'is false when hw version is ancient' do
|
86
|
+
host.vmware_facet.hardware_version = 'vmx-3'
|
87
|
+
refute status.recent_hw_version?
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe '#required_cpu_features_present?' do
|
92
|
+
test 'is false when neither cpuid.IBRS, cpuid.IBPB nor cpuid.STIBP is present' do
|
93
|
+
host.vmware_facet.cpu_features = ['cpuid.SSE42']
|
94
|
+
refute status.required_cpu_features_present?
|
95
|
+
end
|
96
|
+
|
97
|
+
test 'is true when cpuid.IBRS is present' do
|
98
|
+
host.vmware_facet.cpu_features = ['cpuid.IBRS']
|
99
|
+
assert status.required_cpu_features_present?
|
100
|
+
end
|
101
|
+
|
102
|
+
test 'is true when cpuid.IBPB is present' do
|
103
|
+
host.vmware_facet.cpu_features = ['cpuid.IBPB']
|
104
|
+
assert status.required_cpu_features_present?
|
105
|
+
end
|
106
|
+
|
107
|
+
test 'is true when cpuid.STIBP is present' do
|
108
|
+
host.vmware_facet.cpu_features = ['cpuid.STIBP']
|
109
|
+
assert status.required_cpu_features_present?
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -7,5 +7,61 @@ module ForemanWreckingball
|
|
7
7
|
should validate_presence_of(:host)
|
8
8
|
should belong_to(:vmware_cluster)
|
9
9
|
should have_many(:vmware_hypervisor_facets)
|
10
|
+
|
11
|
+
describe '#refresh!' do
|
12
|
+
let(:uuid) { '5032c8a5-9c5e-ba7a-3804-832a03e16381' }
|
13
|
+
let(:vm) do
|
14
|
+
OpenStruct.new(
|
15
|
+
runtime: OpenStruct.new(
|
16
|
+
featureRequirement: [
|
17
|
+
'cpuid.SSE3',
|
18
|
+
'cpuid.AES',
|
19
|
+
'cpuid.Intel'
|
20
|
+
].map do |cpu_feature|
|
21
|
+
OpenStruct.new(key: cpu_feature)
|
22
|
+
end
|
23
|
+
)
|
24
|
+
)
|
25
|
+
end
|
26
|
+
|
27
|
+
let(:compute_resource) do
|
28
|
+
cr = FactoryBot.create(:compute_resource, :vmware, :uuid => 'Solutions')
|
29
|
+
ComputeResource.find(cr.id)
|
30
|
+
end
|
31
|
+
|
32
|
+
let(:host) do
|
33
|
+
FactoryBot.create(
|
34
|
+
:host,
|
35
|
+
:managed,
|
36
|
+
:with_vmware_facet,
|
37
|
+
compute_resource: compute_resource,
|
38
|
+
uuid: uuid
|
39
|
+
)
|
40
|
+
end
|
41
|
+
let(:vmware_facet) { host.vmware_facet }
|
42
|
+
|
43
|
+
setup do
|
44
|
+
::Fog.mock!
|
45
|
+
::Fog::Compute::Vsphere::Mock.any_instance.stubs(:get_vm_ref).returns(vm)
|
46
|
+
# this is not stubbed correctly in fog-vsphere
|
47
|
+
::Fog::Compute::Vsphere::Server.any_instance.stubs(:cpuHotAddEnabled).returns(false)
|
48
|
+
::Fog::Compute::Vsphere::Server.any_instance.stubs(:hardware_version).returns('vmx-9')
|
49
|
+
::Fog::Compute::Vsphere::Server.any_instance.stubs(:corespersocket).returns(1)
|
50
|
+
::Fog::Compute::Vsphere::Server.any_instance.stubs(:ready?).returns(true)
|
51
|
+
end
|
52
|
+
teardown { ::Fog.unmock! }
|
53
|
+
|
54
|
+
test 'refreshes facet data from vm data' do
|
55
|
+
vmware_facet.refresh!
|
56
|
+
assert_equal 1, vmware_facet.cpus
|
57
|
+
assert_equal 1, vmware_facet.corespersocket
|
58
|
+
assert_equal 2196, vmware_facet.memory_mb
|
59
|
+
assert_equal 'rhel6_64Guest', vmware_facet.guest_id
|
60
|
+
assert_equal 'toolsOk', vmware_facet.tools_state
|
61
|
+
assert_equal false, vmware_facet.cpu_hot_add
|
62
|
+
assert_equal ['cpuid.SSE3', 'cpuid.AES', 'cpuid.Intel'], vmware_facet.cpu_features
|
63
|
+
assert_equal 'vmx-9', vmware_facet.hardware_version
|
64
|
+
end
|
65
|
+
end
|
10
66
|
end
|
11
67
|
end
|
@@ -7,9 +7,36 @@ module ForemanWreckingball
|
|
7
7
|
should validate_presence_of(:host)
|
8
8
|
should belong_to(:vmware_cluster)
|
9
9
|
should have_many(:vmware_facets)
|
10
|
+
should have_one(:compute_resource)
|
10
11
|
|
11
12
|
test 'should sanitize name' do
|
12
13
|
assert_equal 'abc-server.example.com', ForemanWreckingball::VmwareHypervisorFacet.sanitize_name('abc_server.example.com.')
|
13
14
|
end
|
15
|
+
|
16
|
+
describe '#provides_spectre_features?' do
|
17
|
+
let(:facet) do
|
18
|
+
FactoryBot.build(:vmware_hypervisor_facet)
|
19
|
+
end
|
20
|
+
|
21
|
+
test 'should be true when IBRS is available' do
|
22
|
+
facet.feature_capabilities = ['cpuid.IBRS']
|
23
|
+
assert_equal true, facet.provides_spectre_features?
|
24
|
+
end
|
25
|
+
|
26
|
+
test 'should be true when IBPB is available' do
|
27
|
+
facet.feature_capabilities = ['cpuid.IBPB']
|
28
|
+
assert_equal true, facet.provides_spectre_features?
|
29
|
+
end
|
30
|
+
|
31
|
+
test 'should be true when STIBP is available' do
|
32
|
+
facet.feature_capabilities = ['cpuid.STIBP']
|
33
|
+
assert_equal true, facet.provides_spectre_features?
|
34
|
+
end
|
35
|
+
|
36
|
+
test 'should be false when neither IBRS, IBPB nor STIBP is available' do
|
37
|
+
facet.feature_capabilities = ['cpuid.WHATEVER']
|
38
|
+
assert_equal false, facet.provides_spectre_features?
|
39
|
+
end
|
40
|
+
end
|
14
41
|
end
|
15
42
|
end
|
data/test/models/host_test.rb
CHANGED
metadata
CHANGED
@@ -1,27 +1,27 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: foreman_wreckingball
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0.
|
4
|
+
version: 3.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Timo Goebel
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-08-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: foreman-tasks
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: 0.13.1
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 0.13.1
|
27
27
|
- !ruby/object:Gem::Dependency
|
@@ -65,6 +65,7 @@ files:
|
|
65
65
|
- app/assets/javascripts/foreman_wreckingball/modal.js
|
66
66
|
- app/controllers/foreman_wreckingball/hosts_controller.rb
|
67
67
|
- app/helpers/concerns/foreman_wreckingball/hosts_helper_extensions.rb
|
68
|
+
- app/helpers/foreman_wreckingball/hypervisors_helper.rb
|
68
69
|
- app/jobs/update_hosts_vmware_facets.rb
|
69
70
|
- app/lib/actions/foreman_wreckingball/host/refresh_vmware_facet.rb
|
70
71
|
- app/lib/actions/foreman_wreckingball/host/remediate_vmware_operatingsystem.rb
|
@@ -82,12 +83,15 @@ files:
|
|
82
83
|
- app/models/concerns/foreman_wreckingball/vmware_hypervisor_facet_host_extensions.rb
|
83
84
|
- app/models/foreman_wreckingball/cpu_hot_add_status.rb
|
84
85
|
- app/models/foreman_wreckingball/operatingsystem_status.rb
|
86
|
+
- app/models/foreman_wreckingball/spectre_v2_status.rb
|
85
87
|
- app/models/foreman_wreckingball/tools_status.rb
|
86
88
|
- app/models/foreman_wreckingball/vmware_cluster.rb
|
87
89
|
- app/models/foreman_wreckingball/vmware_facet.rb
|
88
90
|
- app/models/foreman_wreckingball/vmware_hypervisor_facet.rb
|
91
|
+
- app/services/foreman_wreckingball/debris_collector.rb
|
89
92
|
- app/services/foreman_wreckingball/vmware_cluster_importer.rb
|
90
93
|
- app/services/foreman_wreckingball/vmware_hypervisor_importer.rb
|
94
|
+
- app/views/compute_resources/_hypervisors_tab.html.erb
|
91
95
|
- app/views/foreman_wreckingball/hosts/_status_dashboard_content.erb
|
92
96
|
- app/views/foreman_wreckingball/hosts/_status_dashboard_empty.erb
|
93
97
|
- app/views/foreman_wreckingball/hosts/_status_row.html.erb
|
@@ -95,6 +99,9 @@ files:
|
|
95
99
|
- app/views/foreman_wreckingball/hosts/status_dashboard.html.erb
|
96
100
|
- config/routes.rb
|
97
101
|
- db/migrate/20171106155000_create_vmware_facets.rb
|
102
|
+
- db/migrate/20180504135345_add_cpu_features_to_vmware_facets.rb
|
103
|
+
- db/migrate/20180504135515_add_hardware_version_to_vmware_facets.rb
|
104
|
+
- db/migrate/20180614105545_add_feature_capabilities_to_vmware_hypervisor_facets.rb
|
98
105
|
- lib/foreman_wreckingball.rb
|
99
106
|
- lib/foreman_wreckingball/engine.rb
|
100
107
|
- lib/foreman_wreckingball/scheduled_jobs.rb
|
@@ -108,6 +115,7 @@ files:
|
|
108
115
|
- test/actions/foreman_wreckingball/host/remediate_vmware_operatingsystem_test.rb
|
109
116
|
- test/actions/foreman_wreckingball/vmware/schedule_vmware_sync_test.rb
|
110
117
|
- test/actions/foreman_wreckingball/vmware/sync_compute_resource_test.rb
|
118
|
+
- test/controllers/compute_resources_controller_test.rb
|
111
119
|
- test/controllers/foreman_wreckingball/hosts_controller_test.rb
|
112
120
|
- test/factories/compute_resource.rb
|
113
121
|
- test/factories/foreman_wreckingball_factories.rb
|
@@ -116,6 +124,7 @@ files:
|
|
116
124
|
- test/models/compute_resources/vmware_test.rb
|
117
125
|
- test/models/foreman_wreckingball/cpu_hot_add_status_test.rb
|
118
126
|
- test/models/foreman_wreckingball/operatingsystem_status_test.rb
|
127
|
+
- test/models/foreman_wreckingball/spectre_v2_status_test.rb
|
119
128
|
- test/models/foreman_wreckingball/tools_status_test.rb
|
120
129
|
- test/models/foreman_wreckingball/vmware_cluster_test.rb
|
121
130
|
- test/models/foreman_wreckingball/vmware_facet_test.rb
|
@@ -154,6 +163,7 @@ test_files:
|
|
154
163
|
- test/models/compute_resource_test.rb
|
155
164
|
- test/models/host_test.rb
|
156
165
|
- test/models/foreman_wreckingball/operatingsystem_status_test.rb
|
166
|
+
- test/models/foreman_wreckingball/spectre_v2_status_test.rb
|
157
167
|
- test/models/foreman_wreckingball/vmware_hypervisor_facet_test.rb
|
158
168
|
- test/models/foreman_wreckingball/cpu_hot_add_status_test.rb
|
159
169
|
- test/models/foreman_wreckingball/vmware_cluster_test.rb
|
@@ -168,4 +178,5 @@ test_files:
|
|
168
178
|
- test/actions/foreman_wreckingball/vmware/sync_compute_resource_test.rb
|
169
179
|
- test/actions/foreman_wreckingball/vmware/schedule_vmware_sync_test.rb
|
170
180
|
- test/test_plugin_helper.rb
|
181
|
+
- test/controllers/compute_resources_controller_test.rb
|
171
182
|
- test/controllers/foreman_wreckingball/hosts_controller_test.rb
|