[Pkg-puppet-devel] [SCM] Packaging of Facter for debian branch, upstream, updated. 51bcebe38cab6088c901f1006339bbe40a36d161

Rein Henrichs reinh at reinh.com
Wed Aug 18 05:55:55 UTC 2010


The following commit has been merged in the upstream branch:
commit a2bcacdc54fc9e9446bd5b084e70d60aaaeeebd2
Author: Rein Henrichs <reinh at reinh.com>
Date:   Mon Aug 2 17:28:45 2010 -0700

    [#2330] Uptime should not make redundant system calls
    
    Rewrite of uptime facts and supporting utility methods. Works on unix,
    BSD, windows. No longer makes redundant system calls.
    
    Uses Facter::Util::Uptime utility methods:
    
    * Implemented uptime_seconds_unix using /proc/uptime or who -b on unix,
      sysctl on BSD.
    
      Added unit tests for the behaviors of get_uptime_seconds_unix: read
      from proc/uptime, read uptime from "sysctl -b kern.boottime", read
      uptime from "who -b", and return nil if nothing else works.
    
    * Implemented uptime_seconds_win using the Win32 API.
    
    Facts implemented:
    
    * uptime_{seconds,hours,days}
    
        Returns the respective integer value.
    
    * uptime
    
        Returns human readable uptime statistic that preserves original
        behavior.
    
        Examples:
    
          3 days
          1 day
          5:08 hours
          0:35 hours

diff --git a/lib/facter/uptime.rb b/lib/facter/uptime.rb
index 3a3bc86..56a959b 100644
--- a/lib/facter/uptime.rb
+++ b/lib/facter/uptime.rb
@@ -1,20 +1,23 @@
 require 'facter/util/uptime'
 
 Facter.add(:uptime) do
-    confine :operatingsystem => %w{Solaris Linux Fedora RedHat CentOS SuSE SLES Debian Ubuntu Gentoo AIX}
-    setcode do
-        Facter::Util::Uptime.get_uptime_simple
-    end
-end
+  setcode do
+    seconds = Facter.fact(:uptime_seconds).value
 
-if FileTest.exists?("/proc/uptime")
-    uptime = Facter::Util::Uptime.get_uptime
+    unless seconds
+      "unknown"
+    else
+      days    = seconds / (60 * 60 * 24)
+      hours   = seconds / (60 * 60) % 24
+      minutes = seconds / 60 % 60
 
-    %w{days hours seconds}.each do |label|
-        Facter.add("uptime_" + label) do
-            setcode do
-                Facter::Util::Uptime.get_uptime_period(uptime, label)
-            end 
-        end 
-    end 
+      case days
+      when 0 then "#{hours}:#{"%02d" % minutes} hours"
+      when 1 then '1 day'
+      else "#{days} days"
+      end
+    end
+
+  end
 end
+
diff --git a/lib/facter/uptime_days.rb b/lib/facter/uptime_days.rb
new file mode 100644
index 0000000..add305c
--- /dev/null
+++ b/lib/facter/uptime_days.rb
@@ -0,0 +1,7 @@
+Facter.add(:uptime_days) do
+  setcode do
+    hours = Facter.value(:uptime_hours)
+    hours && hours / 24 # hours in day
+  end
+end
+
diff --git a/lib/facter/uptime_hours.rb b/lib/facter/uptime_hours.rb
new file mode 100644
index 0000000..ce691d2
--- /dev/null
+++ b/lib/facter/uptime_hours.rb
@@ -0,0 +1,7 @@
+Facter.add(:uptime_hours) do
+  setcode do
+    seconds = Facter.value(:uptime_seconds)
+    seconds && seconds / (60 * 60) # seconds in hour
+  end
+end
+
diff --git a/lib/facter/uptime_seconds.rb b/lib/facter/uptime_seconds.rb
new file mode 100644
index 0000000..14bb573
--- /dev/null
+++ b/lib/facter/uptime_seconds.rb
@@ -0,0 +1,10 @@
+require 'facter/util/uptime'
+
+Facter.add(:uptime_seconds) do
+  setcode { Facter::Util::Uptime.get_uptime_seconds_unix }
+end
+
+Facter.add(:uptime_seconds) do
+  confine :kernel => :windows
+  setcode { Facter::Util::Uptime.get_uptime_seconds_win }
+end
diff --git a/lib/facter/util/uptime.rb b/lib/facter/util/uptime.rb
index c1e339b..f8a17db 100644
--- a/lib/facter/util/uptime.rb
+++ b/lib/facter/util/uptime.rb
@@ -1,32 +1,52 @@
+require 'time'
+
 # A module to gather uptime facts
 #
 module Facter::Util::Uptime
-    def self.get_uptime_simple
-        time = Facter::Util::Resolution.exec('uptime')
-        if time =~ /up\s*(\d+\s\w+)/
-            $1
-        elsif time =~ /up\s*(\d+:\d+)/
-            $1 + " hours"
-        else
-            "unknown"
+    def self.get_uptime_seconds_unix
+        uptime_proc_uptime or uptime_sysctl or uptime_who_dash_b
+    end
+
+    def self.get_uptime_seconds_win
+        require 'Win32API'
+        getTickCount = Win32API.new("kernel32", "GetTickCount", nil, 'L')
+        compute_uptime(Time.at(getTickCount.call() / 1000.0))
+    end
+
+    private
+
+    def self.uptime_proc_uptime
+        if File.exists? uptime_file
+            r = File.read uptime_file
+            r.split(" ").first.to_i
+        end
+    end
+
+    def self.uptime_sysctl
+        if (output = `#{uptime_sysctl_cmd}`) and $?.success?
+            compute_uptime(Time.at(output.unpack('L').first))
+        end
+    end
+
+    def self.uptime_who_dash_b
+        if (output = `#{uptime_who_cmd}`) and $?.success?
+            compute_uptime(Time.parse(output))
         end
     end
 
-    def self.get_uptime
-        r = IO.popen("/bin/cat /proc/uptime")
-        uptime, idletime = r.readline.split(" ")        
-        r.close
-        uptime_seconds = uptime.to_i
+    def self.compute_uptime(time)
+        (Time.now - time).to_i
+    end
+
+    def self.uptime_file
+        "/proc/uptime"
+    end
+
+    def self.uptime_sysctl_cmd
+        'sysctl -b kern.boottime 2>/dev/null'
     end
 
-    def self.get_uptime_period(seconds, label)
-        case label
-        when 'days'
-            value = seconds / 86400
-        when 'hours'
-            value = seconds / 3600
-        when 'seconds'
-            seconds
-        end     
+    def self.uptime_who_cmd
+        'who -b 2>/dev/null'
     end
-end   
+end
diff --git a/spec/fixtures/uptime/sysctl_kern_boottime b/spec/fixtures/uptime/sysctl_kern_boottime
new file mode 100644
index 0000000..0c54fe4
Binary files /dev/null and b/spec/fixtures/uptime/sysctl_kern_boottime differ
diff --git a/spec/fixtures/uptime/ubuntu_proc_uptime b/spec/fixtures/uptime/ubuntu_proc_uptime
new file mode 100644
index 0000000..7e8ed74
--- /dev/null
+++ b/spec/fixtures/uptime/ubuntu_proc_uptime
@@ -0,0 +1 @@
+5097686.63 40756306.43
diff --git a/spec/fixtures/uptime/who_b_boottime b/spec/fixtures/uptime/who_b_boottime
new file mode 100644
index 0000000..9b29dcd
--- /dev/null
+++ b/spec/fixtures/uptime/who_b_boottime
@@ -0,0 +1 @@
+reboot   ~        Aug  1 14:13 
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 34992d7..c8bd547 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -1,5 +1,7 @@
 dir = File.expand_path(File.dirname(__FILE__))
 
+SPECDIR = dir
+
 $LOAD_PATH.unshift("#{dir}/")
 $LOAD_PATH.unshift("#{dir}/../lib")
 
diff --git a/spec/unit/uptime.rb b/spec/unit/uptime.rb
new file mode 100644
index 0000000..19a55fe
--- /dev/null
+++ b/spec/unit/uptime.rb
@@ -0,0 +1,112 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../spec_helper'
+
+require 'facter'
+require 'facter/util/uptime'
+
+describe "uptime facts:" do
+  before { Facter.clear }
+  after { Facter.clear }
+
+  context "when uptime information is available" do
+    describe "uptime" do
+      test_cases = [
+        [60 * 60 * 24 * 3,      '3 days'],
+        [60 * 60 * 24 * 3 + 25, '3 days'],
+        [60 * 60 * 24 * 1,      '1 day'],
+        [60 * 60 * 24 * 1 + 25, '1 day'],
+        [60 * (60 * 3 + 45),    '3:45 hours'],
+        [60 * (60 * 3 + 4),     '3:04 hours'],
+        [60 * 60,               '1:00 hours'],
+        [60 * 35,               '0:35 hours']
+      ]
+
+      test_cases.each do |seconds, expected|
+        it "should return #{expected.inspect} for #{seconds} seconds" do
+          Facter::Util::Uptime.stubs(:get_uptime_seconds_unix).returns(seconds)
+          Facter::Util::Uptime.stubs(:get_uptime_seconds_win).returns(seconds)
+
+          Facter.fact(:uptime).value.should == expected
+        end
+      end
+    end
+
+  end
+
+  context "when uptime information is available" do
+    before do
+      Facter::Util::Uptime.stubs(:get_uptime_seconds_unix).returns(60 * 60 * 24 + 23)
+      Facter::Util::Uptime.stubs(:get_uptime_seconds_win).returns(60 * 60 * 24 + 23)
+    end
+
+    describe "uptime_seconds" do
+      it "should return the uptime in seconds" do
+        Facter.fact(:uptime_seconds).value.should == 60 * 60 * 24 + 23
+      end
+    end
+
+    describe "uptime_hours" do
+      it "should return the uptime in hours" do
+        Facter.fact(:uptime_hours).value.should == 24
+      end
+    end
+
+    describe "uptime_days" do
+      it "should return the uptime in days" do
+        Facter.fact(:uptime_days).value.should == 1
+      end
+    end
+  end
+
+  context "when uptime information is not available" do
+    before do
+      Facter::Util::Uptime.stubs(:get_uptime_seconds_unix).returns(nil)
+      Facter::Util::Uptime.stubs(:get_uptime_seconds_win).returns(nil)
+      $stderr, @old = StringIO.new, $stderr
+    end
+
+    after do
+      $stderr = @old
+    end
+
+    describe "uptime" do
+      it "should return 'unknown'" do
+        Facter.fact(:uptime).value.should == "unknown"
+      end
+    end
+
+    describe "uptime_seconds" do
+      it "should return nil" do
+        Facter.fact(:uptime_seconds).value.should == nil
+      end
+
+      it "should not print a warn message to stderr" do
+        Facter.fact(:uptime_seconds).value
+        $stderr.string.should == ""
+      end
+    end
+
+    describe "uptime_hours" do
+      it "should return nil" do
+        Facter.fact(:uptime_hours).value.should == nil
+      end
+
+      it "should not print a warn message to stderr" do
+        Facter.fact(:uptime_hours).value
+        $stderr.string.should == ""
+      end
+    end
+
+    describe "uptime_days" do
+      it "should return nil" do
+        Facter.fact(:uptime_days).value.should == nil
+      end
+
+      it "should not print a warn message to stderr" do
+        Facter.fact(:uptime_days).value
+        $stderr.string.should == ""
+      end
+    end
+  end
+end
diff --git a/spec/unit/util/uptime.rb b/spec/unit/util/uptime.rb
new file mode 100644
index 0000000..9ba6665
--- /dev/null
+++ b/spec/unit/util/uptime.rb
@@ -0,0 +1,53 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+require 'facter/util/uptime'
+
+describe Facter::Util::Uptime do
+
+  describe ".get_uptime_seconds_unix" do
+    context "when /proc/uptime is available" do
+      before do
+        uptime_file = File.join(SPECDIR, "fixtures", "uptime", "ubuntu_proc_uptime")
+        Facter::Util::Uptime.stubs(:uptime_file).returns(uptime_file)
+      end
+
+      it "should return the uptime in seconds as an integer" do
+        Facter::Util::Uptime.get_uptime_seconds_unix.should == 5097686
+      end
+
+    end
+
+    it "should use sysctl kern.boottime when /proc/uptime not available" do
+      nonexistent_file = '/non/existent/file'
+      File.exists?(nonexistent_file).should == false
+      Facter::Util::Uptime.stubs(:uptime_file).returns(nonexistent_file)
+      sysctl_output_file = File.join(SPECDIR, 'fixtures', 'uptime', 'sysctl_kern_boottime') # Aug 01 14:13:47 -0700 2010
+      Facter::Util::Uptime.stubs(:uptime_sysctl_cmd).returns("cat #{sysctl_output_file}")
+      Time.stubs(:now).returns Time.parse("Aug 01 15:13:47 -0700 2010") # one hour later
+      Facter::Util::Uptime.get_uptime_seconds_unix.should == 60 * 60
+    end
+
+    it "should use who -b when neither /proc/uptime nor sysctl kern.boottime is available" do
+      nonexistent_file = '/non/existent/file'
+      File.exists?(nonexistent_file).should == false
+      Facter::Util::Uptime.stubs(:uptime_file).returns(nonexistent_file)
+      Facter::Util::Uptime.stubs(:uptime_sysctl_cmd).returns("cat #{nonexistent_file}")
+      who_b_output_file = File.join(SPECDIR, 'fixtures', 'uptime', 'who_b_boottime') # Aug 1 14:13
+      Facter::Util::Uptime.stubs(:uptime_who_cmd).returns("cat #{who_b_output_file}")
+      Time.stubs(:now).returns Time.parse("Aug 01 15:13") # one hour later
+      Facter::Util::Uptime.get_uptime_seconds_unix.should == 60 * 60
+    end
+
+    it "should return nil when none of /proc/uptime, sysctl kern.boottime, or who -b is available" do
+      nonexistent_file = '/non/existent/file'
+      File.exists?(nonexistent_file).should == false
+      Facter::Util::Uptime.stubs(:uptime_file).returns(nonexistent_file)
+      Facter::Util::Uptime.stubs(:uptime_sysctl_cmd).returns("cat #{nonexistent_file}")
+      Facter::Util::Uptime.stubs(:uptime_who_cmd).returns("cat #{nonexistent_file}")
+      Facter::Util::Uptime.get_uptime_seconds_unix.should == nil
+    end
+  end
+
+end

-- 
Packaging of Facter for debian



More information about the Pkg-puppet-devel mailing list