I have made the following changes and tested to confirm it fixes the bug 
and tested on AIX 5.3 & 6.1, HP-UX 11.23, and Solaris 2.6 & 7.  I have also 
created a fairly exhaustive set of RSpec tests I think.  

I am still wondering if people will object to the fact I've removed the 
kstat method for Solaris - I think the uptime method is better and 
generally more reliable (I've seen kstat broken before a number of times in 
Solaris).  That said, it's easy to leave the kstat in if people prefer.

Changes to RSpec tests / new tests -

# diff -u ./spec/unit/util/uptime_spec.rb.orig 
./spec/unit/util/uptime_spec.rb
--- ./spec/unit/util/uptime_spec.rb.orig        Wed Sep 19 22:26:16 2012
+++ ./spec/unit/util/uptime_spec.rb     Thu Sep 20 17:18:31 2012
@@ -41,36 +41,50 @@

       describe "nor is 'sysctl kern.boottime'" do
         before :each do
-          Facter::Util::Uptime.stubs(:uptime_sysctl_cmd).returns("cat 
\"#{@nonexistent_file}\"")
+          Facter::Util::Uptime.stubs(:uptime_proc_uptime).returns(false)
+          Facter::Util::Uptime.stubs(:uptime_sysctl).returns(false)
+          Facter.fact(:kernel).stubs(:value).returns('SunOS')
         end

-        it "should use 'kstat -p unix:::boot_time'" do
-          kstat_output_file = my_fixture('kstat_boot_time') # 
unix:0:system_misc:boot_time    1236919980
-          Facter::Util::Uptime.stubs(:uptime_kstat_cmd).returns("cat 
\"#{kstat_output_file}\"")
-          Time.stubs(:now).returns Time.at(1236923580) #one hour later
-          Facter::Util::Uptime.get_uptime_seconds_unix.should == 60 * 60
-        end
+        describe "should use '/usr/bin/uptime'" do
+          # Note about uptime variations.
+          # Solaris (5.6, 5.7, 5.8, 5.9, 5.10 & 5.11) and HP-UX (11.00, 
11.11, 11.23, 11.31) have time right justified at
+          #   at 8 characters, and two spaces before 'up'.
+          # Solaris differs from all other Unices (and Linux) in that the 
plural/singular case of minutes/hours/days are
+          #   written min(s)/hr(s)/day(s) instead of min/mins/hr/hrs etc., 
e.g. 1 min(s), 2 min(s) as opposed to
+          #   1 min, 2 mins, etc.
+          # AIX (4.3.3, 5.2, 5.3, 6.1) differs from other SysV Unices in 
that times are padded with a leading 0 in the
+          #   hour column where necessary, and have AM/PM in uppercase, 
and there are three spaces before 'up'.
+          # Tru64 (4.0, 5.1) differs from other SysV Unices in that times 
are in 24 hour format, and there are no
+          #   leading spaces.
+          # Linux (RHEL 5) differs from the Unices in that seconds are 
given in the time, time is right justified at
+          #   9 characters, one space before up.
+          test_cases = [
+            ['  4:42pm  up 1 min(s),  0 users,  load average: 0.95, 0.25, 
0.09',                                         1*60],
+            [' 10:14pm  up 3 hr(s),  0 users,  load average: 0.00, 0.00, 
0.00',                               3*60*60        ],
+            ['  9:01pm  up  1:47,  0 users,  load average: 0.00, 0.00, 
0.00',                                 1*60*60 + 47*60],
+            ['  1:56pm  up 25 day(s),  2 users,  load average: 0.59, 0.56, 
0.50',              25*24*60*60                   ],
+            ['  2:23pm  up 25 day(s), 27 min(s),  2 users,  load average: 
0.49, 0.45, 0.46',   25*24*60*60            + 27*60],
+            ['  1:07pm  up 174 day(s), 16 hr(s),  0 users,  load average: 
0.05, 0.04, 0.03',  174*24*60*60 + 16*60*60        ],
+            ['  8:59pm  up 94 day(s),  3:17,  46 users,  load average: 
0.66, 0.67, 0.70',      94*24*60*60 +  3*60*60 + 17*60],
+            ['  02:42PM   up 1 day, 39 mins,  0 users,  load average: 
1.49, 1.74, 1.80',        1*24*60*60            + 39*60],
+            ['  02:34PM   up 621 days, 18 hrs,  0 users,  load average: 
2.67, 2.52, 2.56',    621*24*60*60 + 18*60*60        ],
+            ['  02:42PM   up 41 days,   2:38,  0 users,  load average: 
0.38, 0.70, 0.55',      41*24*60*60 +  2*60*60 + 38*60],
+            ['  1:29pm  up 485 days,  0 users,  load average: 0.00, 0.01, 
0.01',              485*24*60*60                   ],
+            ['  3:30am  up 108 days, 1 hr,  31 users,  load average: 0.39, 
0.40, 0.41',       108*24*60*60 +  1*60*60        ],
+            ['13:16  up 58 mins,  2 users,  load average: 0.00, 0.02, 
0.05',                                            58*60],
+            ['13:18  up 1 hr,  1 user,  load average: 0.58, 0.23, 
0.14',                                      1*60*60        ],
+            ['13:19  up  1:01,  1 user,  load average: 0.10, 0.26, 
0.21',                                     1*60*60 +  1*60],
+            ['15:56  up 152 days, 17 hrs,  0 users,  load average: 0.01, 
0.06, 0.07',         152*24*60*60 + 17*60*60        ],
+            [' 13:36:05 up 118 days,  1:15,  1 user,  load average: 0.00, 
0.00, 0.00',        118*24*60*60 +  1*60*60 + 15*60]
+          ]

-        describe "nor is 'kstat -p unix:::boot_time'" do
-          before :each do
-            Facter::Util::Uptime.stubs(:uptime_kstat_cmd).returns("cat 
\"#{@nonexistent_file}\"")
-          end
-
-          it "should use 'who -b'" do
-            who_b_output_file = my_fixture('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
-
-          describe "nor is 'who -b'" do
-            before :each do
-              Facter::Util::Uptime.stubs(:uptime_who_cmd).returns("cat 
\"#{@nonexistent_file}\"")
+          test_cases.each do |uptime_output, expected|
+            it "should return #{expected} for #{uptime_output}" do
+              Facter::Util::Resolution.stubs(:exec).with('/usr/bin/uptime 
2>/dev/null').returns(uptime_output)
+              Facter.fact(:uptime_seconds).value.should == expected
             end
-
-            it "should return nil" do
-              Facter::Util::Uptime.get_uptime_seconds_unix.should == nil
-            end
           end
         end
       end

# diff -u ./lib/facter/util/uptime.rb.orig ./lib/facter/util/uptime.rb
--- ./lib/facter/util/uptime.rb.orig    Wed Sep 19 22:26:11 2012
+++ ./lib/facter/util/uptime.rb Thu Sep 20 18:28:01 2012
@@ -4,7 +4,7 @@
 #
 module Facter::Util::Uptime
   def self.get_uptime_seconds_unix
-    uptime_proc_uptime or uptime_sysctl or uptime_kstat or 
uptime_who_dash_b
+    uptime_proc_uptime or uptime_sysctl or uptime_uptime
   end

   def self.get_uptime_seconds_win
@@ -31,18 +31,33 @@
     end
   end

-  def self.uptime_kstat
-    if output = Facter::Util::Resolution.exec("#{uptime_kstat_cmd} 
2>/dev/null")
-      compute_uptime(Time.at(output.chomp.split(/\s/).last.to_i))
+  def self.uptime_uptime
+    if output = Facter::Util::Resolution.exec("#{uptime_uptime_cmd} 
2>/dev/null")
+      up=0
+      if output =~ /(\d+) day(?:s|\(s\))?,\s+(\d+):(\d+)/
+        # Regexp handles Solaris, AIX, HP-UX, and Tru64.
+        # 'day(?:s|\(s\))?' says maybe 'day', 'days',
+        #   or 'day(s)', and don't set $2.
+        up=86400*$1.to_i + 3600*$2.to_i + 60*$3.to_i
+      elsif output =~ /(\d+) day(?:s|\(s\))?,\s+(\d+) hr(?:s|\(s\))?,/
+        up=86400*$1.to_i + 3600*$2.to_i
+      elsif output =~ /(\d+) day(?:s|\(s\))?,\s+(\d+) min(?:s|\(s\))?,/
+        up=86400*$1.to_i + 60*$2.to_i
+      elsif output =~ /(\d+) day(?:s|\(s\))?,/
+        up=86400*$1.to_i
+      elsif output =~ /up\s+(\d+):(\d+),/
+        # must anchor to 'up' to avoid matching time of day
+        # at beginning of line.
+        up=3600*$1.to_i + 60*$2.to_i
+      elsif output =~ /(\d+) hr(?:s|\(s\))?,/
+        up=3600*$1.to_i
+      elsif output =~ /(\d+) min(?:s|\(s\))?,/
+        up=60*$1.to_i
+      end
+      up
     end
   end

-  def self.uptime_who_dash_b
-    if output = Facter::Util::Resolution.exec("#{uptime_who_cmd} 
2>/dev/null")
-      compute_uptime(Time.parse(output))
-    end
-  end
-
   def self.compute_uptime(time)
     (Time.now - time).to_i
   end
@@ -55,11 +70,7 @@
     'sysctl -n kern.boottime'
   end

-  def self.uptime_kstat_cmd
-    'kstat -p unix:::boot_time'
+  def self.uptime_uptime_cmd
+    "/usr/bin/uptime"
   end
-
-  def self.uptime_who_cmd
-    'who -b'
-  end
 end

If there are no objections I guess I should submit the change.

-- 
You received this message because you are subscribed to the Google Groups 
"Puppet Developers" group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/puppet-dev/-/Y8OHNXCw6HoJ.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/puppet-dev?hl=en.

Reply via email to