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

Commit

Permalink
(FACT-2609) Add lspci resolver
Browse files Browse the repository at this point in the history
  • Loading branch information
Oana Tanasoiu committed Jun 2, 2020
1 parent 67a5f04 commit 05ee6c0
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 4 deletions.
21 changes: 19 additions & 2 deletions lib/facts/linux/virtual.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +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
fact_value ||= check_open_vz || check_vserver || check_xen || check_other_facts || check_lspci || 'physical'

Facter::ResolvedFact.new(FACT_NAME, fact_value)
end
Expand Down Expand Up @@ -40,6 +44,19 @@ def check_vserver
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
39 changes: 39 additions & 0 deletions lib/resolvers/lspci.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# 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' }.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.split("\n").each do |line|
REGEX_VALUES.each { |key, value| return value if line =~ /#{key}/ }

return 'vmware' if line =~ /VM[wW]are/
return 'parallels' if line =~ /1ab8:|[Pp]arallels/
return 'kvm' if line =~ /virtio/i
end
end
end
end
end
end
33 changes: 32 additions & 1 deletion spec/facter/facts/linux/virtual_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,42 @@
end
end

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

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: 'virtual', value: value)
end
end

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

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

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

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

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
Expand Down
40 changes: 40 additions & 0 deletions spec/facter/resolvers/lspci_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# frozen_string_literal: true

describe Facter::Resolvers::Lspci do
subject(:lspci_resolver) { Facter::Resolvers::Lspci }

let(:log_spy) { instance_spy(Facter::Log) }

before do
lspci_resolver.instance_variable_set(:@log, log_spy)
allow(Facter::Core::Execution).to receive(:execute).with('lspci', logger: log_spy).and_return(output)
end

after do
lspci_resolver.invalidate_cache
end

context 'when lspci fails' do
let(:output) { '' }

it 'returns nil' do
expect(lspci_resolver.resolve(:vm)).to be_nil
end
end

context 'when lspci detects vmware' do
let(:output) { load_fixture('lspci_vmware').read }

it 'returns hypervisor name' do
expect(lspci_resolver.resolve(:vm)).to eq('vmware')
end
end

context 'when lspci detects xen' do
let(:output) { load_fixture('lspci_aws').read }

it 'returns hypervisor name' do
expect(lspci_resolver.resolve(:vm)).to eq('xenhvm')
end
end
end
2 changes: 1 addition & 1 deletion spec/facter/resolvers/vmware_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
describe Facter::Resolvers::Vmware do
subject(:vmware_resolver) { Facter::Resolvers::Vmware }

let(:log_spy) { Facter::Log }
let(:log_spy) { instance_spy(Facter::Log) }

before do
vmware_resolver.instance_variable_set(:@log, log_spy)
Expand Down
3 changes: 3 additions & 0 deletions spec/fixtures/lspci_aws
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
00:00.0 Host bridge: Intel Corporation FX PMC [Natoma] (rev 02)
00:02.0 VGA compatible controller: Cirrus Logic GD 5446
00:03.0 Unassigned class [ff80]: XenSource, Inc. Xen Platform Device (rev 01)
6 changes: 6 additions & 0 deletions spec/fixtures/lspci_vmware
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
00:10.0 SCSI storage controller: LSI Logic / Symbios Logic 53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (rev 01)
00:11.0 PCI bridge: VMware PCI bridge (rev 02)
00:18.5 PCI bridge: VMware PCI Express Root Port (rev 01)
00:18.6 PCI bridge: VMware PCI Express Root Port (rev 01)
00:18.7 PCI bridge: VMware PCI Express Root Port (rev 01)
03:00.0 Ethernet controller: VMware VMXNET3 Ethernet Controller (rev 01)

0 comments on commit 05ee6c0

Please sign in to comment.