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-2695) implementation for virtualbox hypervisor fact #1956

Merged
merged 2 commits into from
Jul 9, 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
35 changes: 35 additions & 0 deletions lib/facts/linux/hypervisors/virtualbox.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# frozen_string_literal: true

module Facts
module Linux
module Hypervisors
class VirtualBox
FACT_NAME = 'hypervisors.virtualbox'

def call_the_resolver
fact_value = check_virtualbox
Facter::ResolvedFact.new(FACT_NAME, fact_value)
end

def check_virtualbox
virtualbox_details = nil

if Facter::Resolvers::Linux::DmiBios.resolve(:product_name) == 'VirtualBox' ||
Facter::Resolvers::VirtWhat.resolve(:vm) =~ /virtualbox/ ||
Facter::Resolvers::Lspci.resolve(:vm) == 'virtualbox'

virtualbox_details = {}

version = Facter::Resolvers::DmiDecode.resolve(:virtualbox_version)
revision = Facter::Resolvers::DmiDecode.resolve(:virtualbox_revision)

virtualbox_details[:version] = version if version
virtualbox_details[:revision] = revision if revision
end

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

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

class << self
private

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

def run_dmidecode(fact_name)
output = Facter::Core::Execution.execute('dmidecode', logger: log)

@fact_list[:virtualbox_version] = output.match(/vboxVer_(\S+)/)&.captures&.first
@fact_list[:virtualbox_revision] = output.match(/vboxRev_(\S+)/)&.captures&.first
@fact_list[fact_name]
end
end
end
end
end
66 changes: 66 additions & 0 deletions spec/facter/facts/linux/hypervisors/virtual_box_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# frozen_string_literal: true

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

let(:version) { '6.4.1' }
let(:revision) { '136177' }
let(:value) { { 'version' => version, 'revision' => revision } }

before do
allow(Facter::Resolvers::DmiDecode).to receive(:resolve).with(:virtualbox_version).and_return(version)
allow(Facter::Resolvers::DmiDecode).to receive(:resolve).with(:virtualbox_revision).and_return(revision)
allow(Facter::Resolvers::Linux::DmiBios).to receive(:resolve).with(:product_name).and_return('VirtualBox')
end

it 'calls Facter::Resolvers::Linux::DmiBios' do
fact.call_the_resolver
expect(Facter::Resolvers::Linux::DmiBios).to have_received(:resolve).with(:product_name)
end

it 'calls Facter::Resolvers::DmiDecode with version' do
fact.call_the_resolver
expect(Facter::Resolvers::DmiDecode).to have_received(:resolve).with(:virtualbox_version)
end

it 'calls Facter::Resolvers::DmiDecode with revision' do
fact.call_the_resolver
expect(Facter::Resolvers::DmiDecode).to have_received(:resolve).with(:virtualbox_revision)
end

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

context 'when virtualbox is not detected' do
let(:value) { nil }

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

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

context 'when virtualbox details are not present' do
let(:value) { {} }

before do
allow(Facter::Resolvers::DmiDecode).to receive(:resolve).with(:virtualbox_version).and_return(nil)
allow(Facter::Resolvers::DmiDecode).to receive(:resolve).with(:virtualbox_revision).and_return(nil)
end

it 'returns virtualbox fact as empty hash' do
expect(fact.call_the_resolver).to be_an_instance_of(Facter::ResolvedFact).and \
have_attributes(name: 'hypervisors.virtualbox', value: value)
end
end
end
end
36 changes: 36 additions & 0 deletions spec/facter/resolvers/dmi_decode_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# frozen_string_literal: true

describe Facter::Resolvers::DmiDecode do
describe '#resolve' do
subject(:dmidecode) { Facter::Resolvers::DmiDecode }

let(:command_output) { load_fixture('dmi_decode').read }

before do
allow(Facter::Core::Execution).to receive(:execute)
.with('dmidecode', logger: instance_of(Facter::Log)).and_return(command_output)
end

after { dmidecode.invalidate_cache }

it 'detects virtualbox version' do
expect(dmidecode.resolve(:virtualbox_version)).to eql('6.1.4')
end

it 'detects virtualbox revision' do
expect(dmidecode.resolve(:virtualbox_revision)).to eql('136177')
end

context 'when dmidecode command failed' do
let(:command_output) { 'command not found: dmidecode' }

it 'detects virtualbox version as nil' do
expect(dmidecode.resolve(:virtualbox_version)).to be(nil)
end

it 'detects virtualbox revision as nil' do
expect(dmidecode.resolve(:virtualbox_revision)).to be(nil)
end
end
end
end
82 changes: 82 additions & 0 deletions spec/fixtures/dmi_decode
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# dmidecode 3.1
Getting SMBIOS data from sysfs.
SMBIOS 2.5 present.
10 structures occupying 449 bytes.
Table at 0x000E1000.

Handle 0x0000, DMI type 0, 20 bytes
BIOS Information
Vendor: innotek GmbH
Version: VirtualBox
Release Date: 12/01/2006
Address: 0xE0000
Runtime Size: 128 kB
ROM Size: 128 kB
Characteristics:
ISA is supported
PCI is supported
Boot from CD is supported
Selectable boot is supported
8042 keyboard services are supported (int 9h)
CGA/mono video services are supported (int 10h)
ACPI is supported

Handle 0x0001, DMI type 1, 27 bytes
System Information
Manufacturer: innotek GmbH
Product Name: VirtualBox
Version: 1.2
Serial Number: 0
UUID: 784198EC-5827-476E-9E24-B0E98E8958F5
Wake-up Type: Power Switch
SKU Number: Not Specified
Family: Virtual Machine

Handle 0x0008, DMI type 2, 15 bytes
Base Board Information
Manufacturer: Oracle Corporation
Product Name: VirtualBox
Version: 1.2
Serial Number: 0
Asset Tag: Not Specified
Features:
Board is a hosting board
Location In Chassis: Not Specified
Chassis Handle: 0x0003
Type: Motherboard
Contained Object Handles: 0

Handle 0x0003, DMI type 3, 13 bytes
Chassis Information
Manufacturer: Oracle Corporation
Type: Other
Lock: Not Present
Version: Not Specified
Serial Number: Not Specified
Asset Tag: Not Specified
Boot-up State: Safe
Power Supply State: Safe
Thermal State: Safe
Security Status: None

Handle 0x0007, DMI type 126, 42 bytes
Inactive

Handle 0x0005, DMI type 126, 15 bytes
Inactive

Handle 0x0006, DMI type 126, 28 bytes
Inactive

Handle 0x0002, DMI type 11, 7 bytes
OEM Strings
String 1: vboxVer_6.1.4
String 2: vboxRev_136177

Handle 0x0008, DMI type 128, 8 bytes
OEM-specific Type
Header and Data:
80 08 08 00 3D A0 2A 00

Handle 0xFEFF, DMI type 127, 4 bytes
End Of Table