Skip to content

Commit

Permalink
(#8210) Add a heavy virtual fact using virt-what
Browse files Browse the repository at this point in the history
Without this patch facter does not return kvm when running inside of an
enterprise linux guest VM hosted on an enterprise linux kvm host.

This is a problem because facter improperly reports the virtual machine
is actually running on physical hardware, which is not true.  This
causes downstream problems for anyone relying on the virtual fact being
accurate.

This patch fixes the problem by adding a new resolver for the virtual
fact that has a very high weight.  The new resolver calls `virt-what`,
available on Enterprise Linux machines by installing the `virt-what`
package.  The last line of output is used to determine the virtual
machine hypervisor type.

If virt-what is not available or returns no output, then existing lower
weight resolvers are used instead.
  • Loading branch information
Jeff McCune committed Oct 19, 2012
1 parent 2ed2575 commit cf43fc0
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 3 deletions.
15 changes: 15 additions & 0 deletions lib/facter/util/virtual.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,19 @@
module Facter::Util::Virtual
##
# virt_what is a delegating helper method intended to make it easier to stub
# the system call without affecting other calls to
# Facter::Util::Resolution.exec
def self.virt_what(command = "virt-what")
Facter::Util::Resolution.exec command
end

##
# lspci is a delegating helper method intended to make it easier to stub the
# system call without affecting other calls to Facter::Util::Resolution.exec
def self.lspci(command = "lspci 2>/dev/null")
Facter::Util::Resolution.exec command
end

def self.openvz?
FileTest.directory?("/proc/vz") and not self.openvz_cloudlinux?
end
Expand Down
35 changes: 34 additions & 1 deletion lib/facter/virtual.rb
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@
end

if result == "physical"
output = Facter::Util::Resolution.exec('lspci 2>/dev/null')
output = Facter::Util::Virtual.lspci
if not output.nil?
output.each_line do |p|
# --- look for the vmware video card to determine if it is virtual => vmware.
Expand Down Expand Up @@ -153,6 +153,39 @@
end
end

##
# virtual fact based on virt-what command.
#
# The output is mapped onto existing known values for the virtual fact in an
# effort to preserve consistency. This fact has a high weight becuase the
# virt-what tool is expected to be maintained upstream.
#
# If the virt-what command is not available, this fact will not resolve to a
# value and lower-weight virtual facts will be attempted.
#
# Only the last line of the virt-what command is returned
Facter.add("virtual") do
has_weight 500

setcode do
output = Facter::Util::Virtual.virt_what
case output
when 'linux_vserver'
Facter::Util::Virtual.vserver_type
when /xen-hvm/i
'xenhvm'
when /xen-dom0/i
'xen0'
when /xen-domU/i
'xenu'
when /ibm_systemz/i
'zlinux'
else
output.to_s.split("\n").last
end
end
end

# Fact: is_virtual
#
# Purpose: returning true or false for if a machine is virtualised or not.
Expand Down
38 changes: 36 additions & 2 deletions spec/unit/virtual_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
Facter::Util::Virtual.stubs(:kvm?).returns(false)
Facter::Util::Virtual.stubs(:hpvm?).returns(false)
Facter::Util::Virtual.stubs(:zlinux?).returns(false)
Facter::Util::Virtual.stubs(:virt_what).returns(nil)
end

it "should be zone on Solaris when a zone" do
Expand Down Expand Up @@ -82,13 +83,13 @@

it "should be parallels with Parallels vendor id from lspci 2>/dev/null" do
Facter.fact(:kernel).stubs(:value).returns("Linux")
Facter::Util::Resolution.stubs(:exec).with('lspci 2>/dev/null').returns("01:00.0 VGA compatible controller: Unknown device 1ab8:4005")
Facter::Util::Virtual.stubs(:lspci).returns("01:00.0 VGA compatible controller: Unknown device 1ab8:4005")
Facter.fact(:virtual).value.should == "parallels"
end

it "should be parallels with Parallels vendor name from lspci 2>/dev/null" do
Facter.fact(:kernel).stubs(:value).returns("Linux")
Facter::Util::Resolution.stubs(:exec).with('lspci 2>/dev/null').returns("01:00.0 VGA compatible controller: Parallels Display Adapter")
Facter::Util::Virtual.stubs(:lspci).returns("01:00.0 VGA compatible controller: Parallels Display Adapter")
Facter.fact(:virtual).value.should == "parallels"
end

Expand Down Expand Up @@ -233,6 +234,39 @@
Facter.fact(:virtual).value.should == "xenhvm"
end
end

describe "with the virt-what command available (#8210)" do
describe "when the output of virt-what disagrees with lower weight facts" do
virt_what_map = {
'xen-hvm' => 'xenhvm',
'xen-dom0' => 'xen0',
'xen-domU' => 'xenu',
'ibm_systemz' => 'zlinux',
}

virt_what_map.each do |input,output|
it "maps #{input} to #{output}" do
Facter::Util::Virtual.expects(:virt_what).returns(input)
Facter.value(:virtual).should == output
end
end
end

describe "arbitrary outputs of virt-what" do
it "returns the last line output from virt-what" do
Facter::Util::Virtual.expects(:virt_what).returns("one\ntwo\nthree space\n")
Facter.value(:virtual).should == "three space"
end
end

describe "when virt-what returns linux_vserver" do
it "delegates to Facter::Util::Virtual.vserver_type" do
Facter::Util::Virtual.expects(:virt_what).returns("linux_vserver")
Facter::Util::Virtual.expects(:vserver_type).returns("fake_vserver_type")
Facter.value(:virtual).should == "fake_vserver_type"
end
end
end
end

describe "is_virtual fact" do
Expand Down

0 comments on commit cf43fc0

Please sign in to comment.