Skip to content
This repository has been archived by the owner on Jun 19, 2020. It is now read-only.

Commit

Permalink
(FACT-2608) Add is_virtual fact (#535)
Browse files Browse the repository at this point in the history
  • Loading branch information
oanatmaria authored Jun 2, 2020
1 parent 593da0a commit d4a6842
Show file tree
Hide file tree
Showing 2 changed files with 228 additions and 0 deletions.
67 changes: 67 additions & 0 deletions lib/facts/linux/is_virtual.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# frozen_string_literal: true

module Facts
module Linux
class IsVirtual
FACT_NAME = 'is_virtual'
HYPERVISORS_HASH = { 'VMware' => 'vmware', 'VirtualBox' => 'virtualbox', 'Parallels' => 'parallels',
'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

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'

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

def check_gce
bios_vendor = Facter::Resolvers::Linux::DmiBios.resolve(:bios_vendor)
'gce' if bios_vendor&.include?('Google')
end

def check_docker_lxc
Facter::Resolvers::DockerLxc.resolve(:vm)
end

def check_vmware
Facter::Resolvers::Vmware.resolve(:vm)
end

def retrieve_from_virt_what
Facter::Resolvers::VirtWhat.resolve(:vm)
end

def check_open_vz
Facter::Resolvers::OpenVz.resolve(:vm)
end

def check_vserver
Facter::Resolvers::VirtWhat.resolve(:vserver)
end

def check_xen
Facter::Resolvers::Xen.resolve(:vm)
end

def check_other_facts
product_name = Facter::Resolvers::Linux::DmiBios.resolve(:product_name)
bios_vendor = Facter::Resolvers::Linux::DmiBios.resolve(:bios_vendor)
return 'kvm' if bios_vendor&.include?('Amazon EC2')
return unless product_name

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

def check_lspci
Facter::Resolvers::Lspci.resolve(:vm)
end

def check_if_virtual(found_vm)
PHYSICAL_HYPERVISORS.count(found_vm).zero?
end
end
end
end
161 changes: 161 additions & 0 deletions spec/facter/facts/linux/is_virtual_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
# frozen_string_literal: true

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

let(:vm) { 'docker' }
let(:value) { true }

before do
allow(Facter::Resolvers::DockerLxc).to \
receive(:resolve).with(:vm).and_return(vm)
end

it 'calls Facter::Resolvers::DockerLxc' do
fact.call_the_resolver
expect(Facter::Resolvers::DockerLxc).to have_received(:resolve).with(:vm)
end

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

context 'when is gce' do
let(:vm) { nil }
let(:value) { true }

before do
allow(Facter::Resolvers::Linux::DmiBios).to receive(:resolve).with(:bios_vendor).and_return('Google Engine')
end

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

context 'when is vmware' do
let(:vm) { nil }
let(:vmware_value) { 'vmware_fusion' }
let(:value) { true }

before do
allow(Facter::Resolvers::Vmware).to receive(:resolve).with(:vm).and_return(vmware_value)
end

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

context 'when is xen-hvm' do
let(:vm) { nil }
let(:virtwhat_value) { 'xenhvm' }
let(:value) { true }

before do
allow(Facter::Resolvers::Linux::DmiBios).to receive(:resolve).with(:bios_vendor).and_return(nil)
allow(Facter::Resolvers::VirtWhat).to receive(:resolve).with(:vm).and_return(virtwhat_value)
end

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

context 'when is openVz' do
let(:vm) { nil }
let(:openvz_value) { 'openvzve' }
let(:value) { true }

before do
allow(Facter::Resolvers::OpenVz).to receive(:resolve).with(:vm).and_return(openvz_value)
end

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

context 'when is vserver' do
let(:vm) { nil }
let(:virtwhat_value) { 'vserver_host' }
let(:value) { false }

before do
allow(Facter::Resolvers::VirtWhat).to receive(:resolve).with(:vm).and_return(nil)
allow(Facter::Resolvers::VirtWhat).to receive(:resolve).with(:vserver).and_return(virtwhat_value)
end

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

context 'when is xen priviledged' do
let(:vm) { nil }
let(:xen_value) { 'xen0' }
let(:value) { false }

before do
allow(Facter::Resolvers::Xen).to receive(:resolve).with(:vm).and_return(xen_value)
end

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

context 'when is bochs discovered with dmi product_name' do
let(:vm) { nil }
let(:value) { true }

before do
allow(Facter::Resolvers::Linux::DmiBios).to receive(:resolve).with(:bios_vendor).and_return(nil)
allow(Facter::Resolvers::Linux::DmiBios).to receive(:resolve).with(:product_name).and_return('Bochs Machine')
end

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

context 'when is hyper-v discovered with lspci' do
let(:vm) { nil }
let(:lspci_value) { 'hyperv' }
let(:value) { true }

before do
allow(Facter::Resolvers::Lspci).to receive(:resolve).with(:vm).and_return(lspci_value)
end

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

context 'when resolvers return nil ' do
let(:vm) { false }

before do
allow(Facter::Resolvers::Linux::DmiBios).to receive(:resolve).with(:bios_vendor).and_return(nil)
allow(Facter::Resolvers::Linux::DmiBios).to receive(:resolve).with(:product_name).and_return(nil)
allow(Facter::Resolvers::Lspci).to receive(:resolve).with(:vm).and_return(nil)
end

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

0 comments on commit d4a6842

Please sign in to comment.