Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(FACT-2729) Add Solaris is_virtual fact #2056

Merged
merged 1 commit into from
Sep 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions lib/facter/facts/linux/is_virtual.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ module Linux
class IsVirtual
FACT_NAME = 'is_virtual'

PHYSICAL_HYPERVISORS = %w[physical xen0 vmware_server vmware_workstation openvzhn vserver_host].freeze

def call_the_resolver # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
fact_value = check_docker_lxc || check_gce || retrieve_from_virt_what || check_vmware
fact_value ||= check_open_vz || check_vserver || check_xen || check_other_facts || check_lspci || 'physical'
Expand Down Expand Up @@ -59,7 +57,7 @@ def check_lspci
end

def check_if_virtual(found_vm)
PHYSICAL_HYPERVISORS.count(found_vm).zero?
Facter::FactsUtils::PHYSICAL_HYPERVISORS.count(found_vm).zero?
end
end
end
Expand Down
64 changes: 64 additions & 0 deletions lib/facter/facts/solaris/is_virtual.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# frozen_string_literal: true

module Facts
module Solaris
class IsVirtual
FACT_NAME = 'is_virtual'

def initialize
@log = Facter::Log.new(self)
end

def call_the_resolver
@log.debug('Solaris Virtual Resolver')

fact_value = check_ldom || check_zone || check_xen || check_other_facts || 'physical'

@log.debug("Fact value is: #{fact_value}")

Facter::ResolvedFact.new(FACT_NAME, check_if_virtual(fact_value))
end

def check_ldom
@log.debug('Checking LDoms')
return unless Facter::Resolvers::Solaris::Ldom.resolve(:role_control) == 'false'

Facter::Resolvers::Solaris::Ldom.resolve(:role_impl)
end

def check_zone
@log.debug('Checking LDoms')
zone_name = Facter::Resolvers::Solaris::ZoneName.resolve(:current_zone_name)

return if zone_name == 'global'

'zone'
end

def check_xen
@log.debug('Checking XEN')
Facter::Resolvers::Xen.resolve(:vm)
end

def check_other_facts
isa = Facter::Resolvers::Uname.resolve(:processor)
klass = isa == 'sparc' ? 'DmiSparc' : 'Dmi'

product_name = Facter::Resolvers::Solaris.const_get(klass).resolve(:product_name)
bios_vendor = Facter::Resolvers::Solaris.const_get(klass).resolve(:bios_vendor)

return 'kvm' if bios_vendor&.include?('Amazon EC2')

return unless product_name

Facter::FactsUtils::HYPERVISORS_HASH.each { |key, value| return value if product_name.include?(key) }

nil
end

def check_if_virtual(found_vm)
Facter::FactsUtils::PHYSICAL_HYPERVISORS.count(found_vm).zero?
end
end
end
end
2 changes: 2 additions & 0 deletions lib/facter/facts_utils/facts_utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,7 @@ module FactsUtils
'KVM' => 'kvm', 'Virtual Machine' => 'hyperv', 'RHEV Hypervisor' => 'rhev',
'oVirt Node' => 'ovirt', 'HVM domU' => 'xenhvm', 'Bochs' => 'bochs', 'OpenBSD' => 'vmm',
'BHYVE' => 'bhyve' }.freeze

PHYSICAL_HYPERVISORS = %w[physical xen0 vmware_server vmware_workstation openvzhn vserver_host].freeze
end
end
155 changes: 155 additions & 0 deletions spec/facter/facts/solaris/is_virtual_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
# frozen_string_literal: true

describe Facts::Solaris::IsVirtual do
describe '#call_the_resolver' do
subject(:fact) { Facts::Solaris::IsVirtual.new }

let(:processor) { 'i386' }

before do
allow(Facter::Resolvers::Uname).to receive(:resolve).with(:processor).and_return(processor)
end

context 'when no hypervisor is found' do
let(:vm) { false }
let(:current_zone_name) { 'global' }
let(:role_control) { 'false' }

before do
allow(Facter::Resolvers::Solaris::ZoneName)
.to receive(:resolve)
.with(:current_zone_name)
.and_return(current_zone_name)
allow(Facter::Resolvers::Solaris::Ldom).to receive(:resolve).with(:role_impl).and_return(nil)
allow(Facter::Resolvers::Solaris::Ldom).to receive(:resolve).with(:role_control).and_return(nil)
allow(Facter::Resolvers::Solaris::Dmi).to receive(:resolve).with(:product_name).and_return('unkown')
allow(Facter::Resolvers::Solaris::Dmi).to receive(:resolve).with(:bios_vendor).and_return('unkown')
allow(Facter::Resolvers::VirtWhat).to receive(:resolve).with(:vm).and_return(nil)
end

it 'returns is_virtual fact as physical' do
expect(fact.call_the_resolver).to be_an_instance_of(Facter::ResolvedFact).and \
have_attributes(name: 'is_virtual', value: vm)
end
end

context 'when ldom hypervisor is found' do
let(:vm) { true }
let(:current_zone_name) { 'global' }

before do
allow(Facter::Resolvers::Solaris::ZoneName)
.to receive(:resolve)
.with(:current_zone_name)
.and_return(current_zone_name)
allow(Facter::Resolvers::Solaris::Ldom).to receive(:resolve).with(:role_impl).and_return(vm)
allow(Facter::Resolvers::Solaris::Ldom).to receive(:resolve).with(:role_control).and_return(role_control)
end

context 'when role_control is false' do
let(:role_control) { 'false' }

it 'returns virtual fact as physical' do
expect(fact.call_the_resolver).to be_an_instance_of(Facter::ResolvedFact).and \
have_attributes(name: 'is_virtual', value: vm)
end
end

context 'when role_control is true' do
let(:role_control) { 'true' }
let(:vm) { false }

it 'returns is_virtual fact as physical' do
expect(fact.call_the_resolver).to be_an_instance_of(Facter::ResolvedFact).and \
have_attributes(name: 'is_virtual', value: vm)
end
end
end

context 'when zone hypervisor is found' do
let(:vm) { true }

before do
allow(Facter::Resolvers::Solaris::ZoneName).to receive(:resolve).with(:current_zone_name).and_return(vm)
allow(Facter::Resolvers::Solaris::Ldom).to receive(:resolve).with(:role_impl).and_return(nil)
allow(Facter::Resolvers::Solaris::Ldom).to receive(:resolve).with(:role_control).and_return(nil)
end

it 'returns is_virtual fact as physical' do
expect(fact.call_the_resolver).to be_an_instance_of(Facter::ResolvedFact).and \
have_attributes(name: 'is_virtual', value: vm)
end
end

context 'when xen hypervisor is found' do
let(:current_zone_name) { 'global' }
let(:role_control) { 'false' }
let(:xen_vm) { true }

before do
allow(Facter::Resolvers::Solaris::ZoneName)
.to receive(:resolve)
.with(:current_zone_name)
.and_return(current_zone_name)
allow(Facter::Resolvers::Solaris::Ldom).to receive(:resolve).with(:role_impl).and_return(nil)
allow(Facter::Resolvers::Solaris::Ldom).to receive(:resolve).with(:role_control).and_return(nil)
allow(Facter::Resolvers::Solaris::Dmi).to receive(:resolve).with(:product_name).and_return('unkown')
allow(Facter::Resolvers::Solaris::Dmi).to receive(:resolve).with(:bios_vendor).and_return('unkown')
allow(Facter::Resolvers::Xen).to receive(:resolve).with(:vm).and_return(xen_vm)
end

it 'returns is_virtual fact' do
expect(fact.call_the_resolver).to be_an_instance_of(Facter::ResolvedFact).and \
have_attributes(name: 'is_virtual', value: xen_vm)
end
end

context 'when other hypervisors' do
let(:vm) { 'global' }

before do
allow(Facter::Resolvers::Solaris::ZoneName).to receive(:resolve).with(:current_zone_name).and_return(vm)
allow(Facter::Resolvers::Solaris::Ldom).to receive(:resolve).with(:role_impl).and_return(nil)
allow(Facter::Resolvers::Solaris::Ldom).to receive(:resolve).with(:role_control).and_return(nil)
end

context 'when processor is i386' do
let(:processor) { 'i386' }
let(:dmi) { class_double(Facter::Resolvers::Solaris::Dmi).as_stubbed_const }

before do
allow(dmi).to receive(:resolve)
end

it 'calls Dmi resolver for product_name' do
fact.call_the_resolver
expect(dmi).to have_received(:resolve).with(:product_name)
end

it 'calls Dmi resolver for bios_vendor' do
fact.call_the_resolver
expect(dmi).to have_received(:resolve).with(:bios_vendor)
end
end

context 'when processor is sparc' do
let(:processor) { 'sparc' }
let(:dmi) { class_spy(Facter::Resolvers::Solaris::DmiSparc).as_stubbed_const }

before do
allow(dmi).to receive(:resolve)
end

it 'calls DmiSparc resolver for product_name' do
fact.call_the_resolver
expect(dmi).to have_received(:resolve).with(:product_name)
end

it 'calls DmiSparc resolver for bios_vendor' do
fact.call_the_resolver
expect(dmi).to have_received(:resolve).with(:bios_vendor)
end
end
end
end
end