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

Commit

Permalink
Merge branch 'master' of github.com:puppetlabs/facter-ng
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrei Filipovici committed Jun 3, 2020
2 parents fef475f + d4a6842 commit 7b933dd
Show file tree
Hide file tree
Showing 14 changed files with 577 additions and 3 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
32 changes: 31 additions & 1 deletion lib/facts/linux/virtual.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,14 @@ module Facts
module Linux
class Virtual
FACT_NAME = '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

def call_the_resolver
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, fact_value)
end
Expand All @@ -27,6 +32,31 @@ def check_vmware
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
end
end
end
35 changes: 35 additions & 0 deletions lib/resolvers/lspci.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# frozen_string_literal: true

module Facter
module Resolvers
class Lspci < BaseResolver
@semaphore = Mutex.new
@fact_list ||= {}

REGEX_VALUES = { 'VirtualBox' => 'virtualbox', 'XenSource' => 'xenhvm',
'Microsoft Corporation Hyper-V' => 'hyperv', 'Class 8007: Google, Inc' => 'gce',
'VM[wW]are' => 'vmware', '1ab8:' => 'parallels', '[Pp]arallels' => 'parallels',
'(?i)(virtio)' => 'kvm' }.freeze

class << self
private

def post_resolve(fact_name)
@fact_list.fetch(fact_name) { lspci_command(fact_name) }
end

def lspci_command(fact_name)
output = Facter::Core::Execution.execute('lspci', logger: log)
return if output.empty?

@fact_list[:vm] = retrieve_vm(output)
@fact_list[fact_name]
end

def retrieve_vm(output)
output.each_line { |line| REGEX_VALUES.each { |key, value| return value if line =~ /#{key}/ } }
end
end
end
end
end
45 changes: 45 additions & 0 deletions lib/resolvers/open_vz.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# frozen_string_literal: true

module Facter
module Resolvers
class OpenVz < BaseResolver
# build

@semaphore = Mutex.new
@fact_list ||= {}

class << self
private

def post_resolve(fact_name)
@fact_list.fetch(fact_name) { check_proc_vz(fact_name) }
end

def check_proc_vz(fact_name)
if !Dir.exist?('/proc/vz') || !File.executable?('/proc/lve/list') || Dir.entries('/proc/vz').count.equal?(2)
return
end

@fact_list[:vm] = read_proc_status
@fact_list[fact_name]
end

def read_proc_status
proc_status_content = Facter::Util::FileHelper.safe_readlines('/proc/self/status', nil)
return unless proc_status_content

proc_status_content.each do |line|
parts = line.split("\s")
next unless parts.size.equal?(2)

next unless /^envID:/ =~ parts[0]

return 'openvzhn' if parts[1] == '0'

return 'openvzve'
end
end
end
end
end
end
26 changes: 26 additions & 0 deletions lib/resolvers/xen.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# frozen_string_literal: true

module Facter
module Resolvers
class Xen < BaseResolver
@semaphore = Mutex.new
@fact_list ||= {}

class << self
private

def post_resolve(fact_name)
@fact_list.fetch(fact_name) { chech_xen_dirs(fact_name) }
end

def chech_xen_dirs(fact_name)
xen_type = 'xen0' if File.exist?('/dev/xen/evtchn')
xen_type = 'xenu' if !xen_type && (File.exist?('/proc/xen') || File.exist?('/dev/xvda1'))

@fact_list[:vm] = xen_type
@fact_list[fact_name]
end
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
Loading

0 comments on commit 7b933dd

Please sign in to comment.