[Pkg-puppet-devel] [facter] 63/180: (FACT-189) Add LXC detection to virtual and is_virtual fact

Stig Sandbeck Mathisen ssm at debian.org
Mon Jun 30 15:06:31 UTC 2014


This is an automated email from the git hooks/post-receive script.

ssm pushed a commit to branch master
in repository facter.

commit 632041b2aba05ee85b431a802288273b922ca639
Author: Jeff McCune <jeff at puppetlabs.com>
Date:   Sun Feb 9 22:20:24 2014 -0800

    (FACT-189) Add LXC detection to virtual and is_virtual fact
    
    Without this patch the virtual and is_virtual facts are returning
    "physical" and "false" respectively.  This is a problem because Linux
    Containers are a virtual environment and it is useful to configure
    things differently in lxc when compared to other virtual environments.
    
    This patch addresses the problem by detecting if the process is running
    inside of a linux container by looking at the cgroup entries for the
    init process.  This method is described at
    http://stackoverflow.com/questions/20010199/determining-if-a-process-runs-inside-lxc-docker#
    
    Basically, if /proc/1/cgroup looks like this, we're not in a lxc
    container:
    
        9:hugetlb:/
        8:perf_event:/
        7:blkio:/
        6:freezer:/
        5:devices:/
        4:memory:/
        3:cpuacct:/
        2:cpu:/
        1:cpuset:/
    
    But if they look like this then we are in a container:
    
        9:hugetlb:/lxc/e411045bbbc61eca5d3af7eb0764c30833606f51d20c176f406afbdb47bb04be
        8:perf_event:/lxc/e411045bbbc61eca5d3af7eb0764c30833606f51d20c176f406afbdb47bb04be
        7:blkio:/lxc/e411045bbbc61eca5d3af7eb0764c30833606f51d20c176f406afbdb47bb04be
        6:freezer:/lxc/e411045bbbc61eca5d3af7eb0764c30833606f51d20c176f406afbdb47bb04be
        5:devices:/lxc/e411045bbbc61eca5d3af7eb0764c30833606f51d20c176f406afbdb47bb04be
        4:memory:/lxc/e411045bbbc61eca5d3af7eb0764c30833606f51d20c176f406afbdb47bb04be
        3:cpuacct:/lxc/e411045bbbc61eca5d3af7eb0764c30833606f51d20c176f406afbdb47bb04be
        2:cpu:/lxc/e411045bbbc61eca5d3af7eb0764c30833606f51d20c176f406afbdb47bb04be
        1:cpuset:/lxc/e411045bbbc61eca5d3af7eb0764c30833606f51d20c176f406afbdb47bb04be
    
    The identifier is the container id and might be useful for a future fact
    to identify the container Facter is running in.
---
 lib/facter/util/virtual.rb                         | 13 ++++++++++
 lib/facter/virtual.rb                              | 13 ++++++++++
 spec/fixtures/virtual/proc_1_cgroup/in_a_container |  9 +++++++
 .../virtual/proc_1_cgroup/not_in_a_container       |  9 +++++++
 spec/unit/util/virtual_spec.rb                     | 30 ++++++++++++++++++++++
 spec/unit/virtual_spec.rb                          | 18 +++++++++++++
 6 files changed, 92 insertions(+)

diff --git a/lib/facter/util/virtual.rb b/lib/facter/util/virtual.rb
index e655838..8d22595 100644
--- a/lib/facter/util/virtual.rb
+++ b/lib/facter/util/virtual.rb
@@ -1,4 +1,5 @@
 require 'facter/util/file_read'
+require 'pathname'
 
 module Facter::Util::Virtual
   ##
@@ -130,6 +131,18 @@ module Facter::Util::Virtual
     Facter::Core::Execution.exec("/usr/bin/getconf MACHINE_MODEL").chomp =~ /Virtual Machine/
   end
 
+  ##
+  # lxc? returns true if the process is running inside of a linux container.
+  # Implementation derived from
+  # http://stackoverflow.com/questions/20010199/determining-if-a-process-runs-inside-lxc-docker
+  def self.lxc?
+    path = Pathname.new('/proc/1/cgroup')
+    return false unless path.readable?
+    lxc_hierarchies = path.readlines.map {|l| l.split(":")[2].to_s.start_with? '/lxc/' }
+    return true if lxc_hierarchies.include?(true)
+    return false
+  end
+
   def self.zlinux?
     "zlinux"
   end
diff --git a/lib/facter/virtual.rb b/lib/facter/virtual.rb
index 05f5e79..516db2e 100644
--- a/lib/facter/virtual.rb
+++ b/lib/facter/virtual.rb
@@ -251,6 +251,19 @@ Facter.add("virtual") do
     end
   end
 end
+
+##
+# virtual fact specific to linux containers.  This also works for Docker
+# containers running in lxc.
+Facter.add("virtual") do
+  has_weight 700
+  confine :kernel => "Linux"
+
+  setcode do
+    "lxc" if Facter::Util::Virtual.lxc?
+  end
+end
+
 # Fact: is_virtual
 #
 # Purpose: returning true or false for if a machine is virtualised or not.
diff --git a/spec/fixtures/virtual/proc_1_cgroup/in_a_container b/spec/fixtures/virtual/proc_1_cgroup/in_a_container
new file mode 100644
index 0000000..bed734f
--- /dev/null
+++ b/spec/fixtures/virtual/proc_1_cgroup/in_a_container
@@ -0,0 +1,9 @@
+9:hugetlb:/lxc/e411045bbbc61eca5d3af7eb0764c30833606f51d20c176f406afbdb47bb04be
+8:perf_event:/lxc/e411045bbbc61eca5d3af7eb0764c30833606f51d20c176f406afbdb47bb04be
+7:blkio:/lxc/e411045bbbc61eca5d3af7eb0764c30833606f51d20c176f406afbdb47bb04be
+6:freezer:/lxc/e411045bbbc61eca5d3af7eb0764c30833606f51d20c176f406afbdb47bb04be
+5:devices:/lxc/e411045bbbc61eca5d3af7eb0764c30833606f51d20c176f406afbdb47bb04be
+4:memory:/lxc/e411045bbbc61eca5d3af7eb0764c30833606f51d20c176f406afbdb47bb04be
+3:cpuacct:/lxc/e411045bbbc61eca5d3af7eb0764c30833606f51d20c176f406afbdb47bb04be
+2:cpu:/lxc/e411045bbbc61eca5d3af7eb0764c30833606f51d20c176f406afbdb47bb04be
+1:cpuset:/lxc/e411045bbbc61eca5d3af7eb0764c30833606f51d20c176f406afbdb47bb04be
diff --git a/spec/fixtures/virtual/proc_1_cgroup/not_in_a_container b/spec/fixtures/virtual/proc_1_cgroup/not_in_a_container
new file mode 100644
index 0000000..07c5957
--- /dev/null
+++ b/spec/fixtures/virtual/proc_1_cgroup/not_in_a_container
@@ -0,0 +1,9 @@
+9:hugetlb:/
+8:perf_event:/
+7:blkio:/
+6:freezer:/
+5:devices:/
+4:memory:/
+3:cpuacct:/
+2:cpu:/
+1:cpuset:/
diff --git a/spec/unit/util/virtual_spec.rb b/spec/unit/util/virtual_spec.rb
index 9414f8e..e9ef651 100755
--- a/spec/unit/util/virtual_spec.rb
+++ b/spec/unit/util/virtual_spec.rb
@@ -291,4 +291,34 @@ describe Facter::Util::Virtual do
   context "on windows" do
     it_should_behave_like "virt-what", "windows", 'c:\windows\system32\virt-what', "NUL"
   end
+
+  describe '.lxc?' do
+    subject do
+      Facter::Util::Virtual.lxc?
+    end
+
+    fixture_path = fixtures('virtual', 'proc_1_cgroup')
+
+    context '/proc/1/cgroup has at least one hierarchy rooted in /lxc/' do
+      before :each do
+        fakepath = Pathname.new(File.join(fixture_path, 'in_a_container'))
+        Pathname.stubs(:new).with('/proc/1/cgroup').returns(fakepath)
+      end
+
+      it 'is true' do
+        subject.should be_true
+      end
+    end
+
+    context '/proc/1/cgroup has no hierarchies rooted in /lxc/' do
+      before :each do
+        fakepath = Pathname.new(File.join(fixture_path, 'not_in_a_container'))
+        Pathname.stubs(:new).with('/proc/1/cgroup').returns(fakepath)
+      end
+
+      it 'is false' do
+        subject.should be_false
+      end
+    end
+  end
 end
diff --git a/spec/unit/virtual_spec.rb b/spec/unit/virtual_spec.rb
index 21afa14..fe0aa0d 100755
--- a/spec/unit/virtual_spec.rb
+++ b/spec/unit/virtual_spec.rb
@@ -6,6 +6,7 @@ require 'facter/util/macosx'
 
 describe "Virtual fact" do
   before(:each) do
+    Facter::Util::Virtual.stubs(:lxc?).returns(false)
     Facter::Util::Virtual.stubs(:zone?).returns(false)
     Facter::Util::Virtual.stubs(:openvz?).returns(false)
     Facter::Util::Virtual.stubs(:vserver?).returns(false)
@@ -170,6 +171,17 @@ describe "Virtual fact" do
       Facter.fact(:virtual).value.should == "hyperv"
     end
 
+    context "In a Linux Container (LXC)" do
+      before :each do
+        Facter.fact(:kernel).stubs(:value).returns("Linux")
+      end
+
+      it 'is "lxc" when Facter::Util::Virtual.lxc? is true' do
+        Facter::Util::Virtual.stubs(:lxc?).returns(true)
+        Facter.fact(:virtual).value.should == 'lxc'
+      end
+    end
+
     context "In Google Compute Engine" do
       before :each do
         Facter.fact(:kernel).stubs(:value).returns("Linux")
@@ -462,4 +474,10 @@ describe "is_virtual fact" do
     Facter.fact(:virtual).stubs(:value).returns("ovirt")
     Facter.fact(:is_virtual).value.should == "true"
   end
+
+  it "should be true when running in LXC" do
+    Facter.fact(:kernel).stubs(:value).returns("Linux")
+    Facter.fact(:virtual).stubs(:value).returns("lxc")
+    Facter.fact(:is_virtual).value.should == "true"
+  end
 end

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-puppet/facter.git



More information about the Pkg-puppet-devel mailing list