facter 1.6.18 → 1.7.0.rc1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of facter might be problematic. Click here for more details.

Files changed (126) hide show
  1. data/Gemfile +23 -8
  2. data/bin/facter +4 -1
  3. data/ext/build_defaults.yaml +1 -1
  4. data/ext/debian/changelog.erb +4 -22
  5. data/ext/debian/control +2 -2
  6. data/ext/project_data.yaml +1 -1
  7. data/ext/redhat/facter.spec.erb +10 -9
  8. data/install.rb +27 -53
  9. data/lib/facter.rb +23 -5
  10. data/lib/facter/application.rb +21 -0
  11. data/lib/facter/blockdevices.rb +105 -0
  12. data/lib/facter/domain.rb +19 -7
  13. data/lib/facter/filesystems.rb +38 -0
  14. data/lib/facter/hardwaremodel.rb +3 -2
  15. data/lib/facter/ipaddress6.rb +1 -2
  16. data/lib/facter/kernelrelease.rb +10 -2
  17. data/lib/facter/ldom.rb +47 -0
  18. data/lib/facter/macaddress.rb +1 -1
  19. data/lib/facter/manufacturer.rb +7 -1
  20. data/lib/facter/memory.rb +58 -160
  21. data/lib/facter/operatingsystem.rb +17 -2
  22. data/lib/facter/operatingsystemmajrelease.rb +33 -0
  23. data/lib/facter/operatingsystemrelease.rb +88 -37
  24. data/lib/facter/osfamily.rb +6 -2
  25. data/lib/facter/processor.rb +2 -2
  26. data/lib/facter/ps.rb +5 -0
  27. data/lib/facter/ssh.rb +50 -12
  28. data/lib/facter/util/cfpropertylist.rb +6 -0
  29. data/lib/facter/util/cfpropertylist/LICENSE +19 -0
  30. data/lib/facter/util/cfpropertylist/README +44 -0
  31. data/lib/facter/util/cfpropertylist/Rakefile +44 -0
  32. data/lib/facter/util/cfpropertylist/THANKS +7 -0
  33. data/lib/facter/util/cfpropertylist/lib/cfpropertylist.rb +6 -0
  34. data/lib/facter/util/cfpropertylist/lib/rbBinaryCFPropertyList.rb +562 -0
  35. data/lib/facter/util/cfpropertylist/lib/rbCFPlistError.rb +26 -0
  36. data/lib/facter/util/cfpropertylist/lib/rbCFPropertyList.rb +402 -0
  37. data/lib/facter/util/cfpropertylist/lib/rbCFTypes.rb +244 -0
  38. data/lib/facter/util/cfpropertylist/lib/rbLibXMLParser.rb +135 -0
  39. data/lib/facter/util/cfpropertylist/lib/rbNokogiriParser.rb +140 -0
  40. data/lib/facter/util/cfpropertylist/lib/rbREXMLParser.rb +136 -0
  41. data/lib/facter/util/collection.rb +36 -14
  42. data/lib/facter/util/composite_loader.rb +12 -0
  43. data/lib/facter/util/config.rb +36 -0
  44. data/lib/facter/util/confine.rb +1 -6
  45. data/lib/facter/util/directory_loader.rb +83 -0
  46. data/lib/facter/util/fact.rb +49 -42
  47. data/lib/facter/util/file_read.rb +32 -0
  48. data/lib/facter/util/ip.rb +2 -9
  49. data/lib/facter/util/loader.rb +16 -2
  50. data/lib/facter/util/macosx.rb +15 -2
  51. data/lib/facter/util/memory.rb +154 -27
  52. data/lib/facter/util/nothing_loader.rb +15 -0
  53. data/lib/facter/util/parser.rb +141 -0
  54. data/lib/facter/util/processor.rb +27 -35
  55. data/lib/facter/util/resolution.rb +97 -26
  56. data/lib/facter/util/solaris_zones.rb +153 -0
  57. data/lib/facter/util/virtual.rb +32 -3
  58. data/lib/facter/version.rb +72 -2
  59. data/lib/facter/virtual.rb +56 -3
  60. data/lib/facter/zfs_version.rb +10 -0
  61. data/lib/facter/zonename.rb +6 -0
  62. data/lib/facter/zones.rb +17 -0
  63. data/lib/facter/zpool_version.rb +10 -0
  64. data/spec/fixtures/ifconfig/ifconfig_net_tools_1.60.txt +19 -0
  65. data/spec/fixtures/ifconfig/ifconfig_ubuntu_1204.txt +16 -0
  66. data/spec/fixtures/ldom/ldom_v1 +6 -0
  67. data/spec/fixtures/unit/filesystems/linux +28 -0
  68. data/spec/fixtures/unit/util/manufacturer/intel_linux_dmidecode +549 -0
  69. data/spec/fixtures/unit/virtual/sysfs_dmi_entries_raw.txt +0 -0
  70. data/spec/fixtures/unit/zfs_version/freebsd_8.2 +14 -0
  71. data/spec/fixtures/unit/zfs_version/freebsd_9.0 +13 -0
  72. data/spec/fixtures/unit/zfs_version/linux-fuse_0.6.9 +14 -0
  73. data/spec/fixtures/unit/zfs_version/solaris_10 +10 -0
  74. data/spec/fixtures/unit/zfs_version/solaris_11 +12 -0
  75. data/spec/fixtures/unit/zpool_version/freebsd_8.2 +26 -0
  76. data/spec/fixtures/unit/zpool_version/freebsd_9.0 +38 -0
  77. data/spec/fixtures/unit/zpool_version/linux-fuse_0.6.9 +35 -0
  78. data/spec/fixtures/unit/zpool_version/solaris_10 +31 -0
  79. data/spec/fixtures/unit/zpool_version/solaris_11 +43 -0
  80. data/spec/integration/facter_spec.rb +12 -0
  81. data/spec/spec_helper.rb +9 -0
  82. data/spec/unit/architecture_spec.rb +1 -1
  83. data/spec/unit/blockdevices_spec.rb +109 -0
  84. data/spec/unit/domain_spec.rb +189 -81
  85. data/spec/unit/ec2_spec.rb +15 -8
  86. data/spec/unit/filesystems_spec.rb +50 -0
  87. data/spec/unit/hardwaremodel_spec.rb +8 -1
  88. data/spec/unit/id_spec.rb +6 -5
  89. data/spec/unit/ipaddress6_spec.rb +14 -2
  90. data/spec/unit/ipaddress_spec.rb +1 -1
  91. data/spec/unit/kernel_spec.rb +24 -0
  92. data/spec/unit/kernelmajversion_spec.rb +17 -0
  93. data/spec/unit/kernelrelease_spec.rb +53 -0
  94. data/spec/unit/kernelversion_spec.rb +32 -0
  95. data/spec/unit/ldom_spec.rb +74 -0
  96. data/spec/unit/macaddress_spec.rb +3 -1
  97. data/spec/unit/manufacturer_spec.rb +115 -0
  98. data/spec/unit/memory_spec.rb +442 -75
  99. data/spec/unit/operatingsystem_spec.rb +16 -2
  100. data/spec/unit/operatingsystemmajrelease_spec.rb +16 -0
  101. data/spec/unit/operatingsystemrelease_spec.rb +110 -1
  102. data/spec/unit/processor_spec.rb +22 -7
  103. data/spec/unit/ps_spec.rb +42 -0
  104. data/spec/unit/ssh_spec.rb +76 -0
  105. data/spec/unit/util/collection_spec.rb +94 -118
  106. data/spec/unit/util/config_spec.rb +36 -5
  107. data/spec/unit/util/confine_spec.rb +31 -43
  108. data/spec/unit/util/directory_loader_spec.rb +87 -0
  109. data/spec/unit/util/fact_spec.rb +37 -25
  110. data/spec/unit/util/file_read_spec.rb +29 -0
  111. data/spec/unit/util/ip_spec.rb +4 -2
  112. data/spec/unit/util/loader_spec.rb +102 -45
  113. data/spec/unit/util/macosx_spec.rb +40 -9
  114. data/spec/unit/util/manufacturer_spec.rb +12 -1
  115. data/spec/unit/util/parser_spec.rb +135 -0
  116. data/spec/unit/util/resolution_spec.rb +136 -4
  117. data/spec/unit/util/solaris_zones_spec.rb +127 -0
  118. data/spec/unit/util/virtual_spec.rb +54 -0
  119. data/spec/unit/version_spec.rb +42 -0
  120. data/spec/unit/virtual_spec.rb +102 -27
  121. data/spec/unit/zfs_version_spec.rb +76 -0
  122. data/spec/unit/zonename_spec.rb +14 -0
  123. data/spec/unit/zones_spec.rb +55 -0
  124. data/spec/unit/zpool_version_spec.rb +76 -0
  125. metadata +113 -11
  126. data/lib/facter/arp.rb +0 -28
@@ -0,0 +1,12 @@
1
+ # A composite loader that allows for more than one
2
+ # default directory loader
3
+
4
+ class Facter::Util::CompositeLoader
5
+ def initialize(loaders)
6
+ @loaders = loaders
7
+ end
8
+
9
+ def load(collection)
10
+ @loaders.each { |loader| loader.load(collection) }
11
+ end
12
+ end
@@ -3,7 +3,43 @@ require 'rbconfig'
3
3
  # A module to return config related data
4
4
  #
5
5
  module Facter::Util::Config
6
+
7
+ def self.ext_fact_loader
8
+ @ext_fact_loader || Facter::Util::DirectoryLoader.default_loader
9
+ end
10
+
11
+ def self.ext_fact_loader=(loader)
12
+ @ext_fact_loader = loader
13
+ end
14
+
15
+ def self.is_mac?
16
+ RbConfig::CONFIG['host_os'] =~ /darwin/i
17
+ end
18
+
19
+ # Returns true if OS is windows
6
20
  def self.is_windows?
7
21
  RbConfig::CONFIG['host_os'] =~ /mswin|win32|dos|mingw|cygwin/i
8
22
  end
23
+
24
+ def self.windows_data_dir
25
+ if Dir.const_defined? 'COMMON_APPDATA' then
26
+ Dir::COMMON_APPDATA
27
+ else
28
+ nil
29
+ end
30
+ end
31
+
32
+ def self.external_facts_dirs
33
+ windows_dir = windows_data_dir
34
+ if windows_dir.nil? then
35
+ ["/etc/facter/facts.d", "/etc/puppetlabs/facter/facts.d"]
36
+ else
37
+ [File.join(windows_dir, 'PuppetLabs', 'facter', 'facts.d')]
38
+ end
39
+ end
40
+ end
41
+
42
+ if Facter::Util::Config.is_windows?
43
+ require 'rubygems'
44
+ require 'win32/dir'
9
45
  end
@@ -31,11 +31,6 @@ class Facter::Util::Confine
31
31
 
32
32
  return false if value.nil?
33
33
 
34
- @values.each do |v|
35
- v = convert(v)
36
- next unless v.class == value.class
37
- return true if value == v
38
- end
39
- return false
34
+ return @values.any? { |v| convert(v) === value }
40
35
  end
41
36
  end
@@ -0,0 +1,83 @@
1
+ # A Facter plugin that loads external facts.
2
+ #
3
+ # Default Unix Directories:
4
+ # /etc/facter/facts.d, /etc/puppetlbas/facter/facts.d
5
+ #
6
+ # Default Windows Direcotires:
7
+ # C:\ProgramData\Puppetlabs\facter\facts.d (2008)
8
+ # C:\Documents and Settings\All Users\Application Data\Puppetlabs\facter\facts.d (2003)
9
+ #
10
+ # Can also load from command-line specified directory
11
+ #
12
+ # Facts can be in the form of JSON, YAML or Text files
13
+ # and any executable that returns key=value pairs.
14
+
15
+ require 'facter'
16
+ require 'facter/util/config'
17
+ require 'facter/util/composite_loader'
18
+ require 'facter/util/parser'
19
+ require 'yaml'
20
+
21
+ class Facter::Util::DirectoryLoader
22
+
23
+ class NoSuchDirectoryError < Exception
24
+ end
25
+
26
+ # This value makes it highly likely that external facts will take
27
+ # precedence over all other facts
28
+ EXTERNAL_FACT_WEIGHT = 10000
29
+
30
+ # Directory for fact loading
31
+ attr_reader :directory
32
+
33
+ def initialize(dir)
34
+ @directory = dir
35
+ end
36
+
37
+ def self.loader_for(dir)
38
+ if File.directory?(dir)
39
+ Facter::Util::DirectoryLoader.new(dir)
40
+ else
41
+ raise NoSuchDirectoryError
42
+ end
43
+ end
44
+
45
+ def self.default_loader
46
+ loaders = Facter::Util::Config.external_facts_dirs.collect do |dir|
47
+ Facter::Util::DirectoryLoader.new(dir)
48
+ end
49
+ Facter::Util::CompositeLoader.new(loaders)
50
+ end
51
+
52
+ # Load facts from files in fact directory using the relevant parser classes to
53
+ # parse them.
54
+ def load(collection)
55
+ entries.each do |file|
56
+ parser = Facter::Util::Parser.parser_for(file)
57
+ if parser == nil
58
+ next
59
+ end
60
+
61
+ data = parser.results
62
+ if data == false
63
+ Facter.warn "Could not interpret fact file #{file}"
64
+ elsif data == {} or data == nil
65
+ Facter.warn "Fact file #{file} was parsed but returned an empty data set"
66
+ else
67
+ data.each { |p,v| collection.add(p, :value => v) { has_weight(EXTERNAL_FACT_WEIGHT) } }
68
+ end
69
+ end
70
+ end
71
+
72
+ private
73
+
74
+ def entries
75
+ Dir.entries(directory).find_all { |f| should_parse?(f) }.sort.map { |f| File.join(directory, f) }
76
+ rescue Errno::ENOENT => detail
77
+ []
78
+ end
79
+
80
+ def should_parse?(file)
81
+ not file =~ /^\./
82
+ end
83
+ end
@@ -30,20 +30,13 @@ class Facter::Util::Fact
30
30
 
31
31
  # Add a new resolution mechanism. This requires a block, which will then
32
32
  # be evaluated in the context of the new mechanism.
33
- def add(&block)
34
- raise ArgumentError, "You must pass a block to Fact<instance>.add" unless block_given?
35
-
33
+ def add(value = nil, &block)
36
34
  begin
37
35
  resolve = Facter::Util::Resolution.new(@name)
38
36
 
39
- resolve.instance_eval(&block)
40
-
37
+ resolve.instance_eval(&block) if block
41
38
  @resolves << resolve
42
39
 
43
- # Immediately sort the resolutions, so that we always have
44
- # a sorted list for looking up values.
45
- @resolves.sort! { |a, b| b.weight <=> a.weight }
46
-
47
40
  resolve
48
41
  rescue => e
49
42
  Facter.warn "Unable to add resolve for #{@name}: #{e}"
@@ -51,10 +44,13 @@ class Facter::Util::Fact
51
44
  end
52
45
  end
53
46
 
54
- # Flush any cached values.
47
+ ##
48
+ # Flush any cached values. If the resolver has a callback block defined
49
+ # using the on_flush DSL method, then invoke that block by sending a message
50
+ # to Resolution#flush.
55
51
  def flush
52
+ @resolves.each { |r| r.flush }
56
53
  @value = nil
57
- @suitable = nil
58
54
  end
59
55
 
60
56
  # Return the value for a given fact. Searches through all of the mechanisms
@@ -62,38 +58,24 @@ class Facter::Util::Fact
62
58
  def value
63
59
  return @value if @value
64
60
 
65
- if @resolves.length == 0
61
+ if @resolves.empty?
66
62
  Facter.debug "No resolves for %s" % @name
67
63
  return nil
68
64
  end
69
65
 
70
66
  searching do
71
- @value = nil
72
-
73
- foundsuits = false
74
- @value = @resolves.inject(nil) { |result, resolve|
75
- next unless resolve.suitable?
76
- foundsuits = true
77
67
 
78
- tmp = resolve.value
68
+ suitable_resolutions = sort_by_weight(find_suitable_resolutions(@resolves))
69
+ @value = find_first_real_value(suitable_resolutions)
79
70
 
80
- break tmp unless tmp.nil? or tmp == ""
81
- }
71
+ announce_when_no_suitable_resolution(suitable_resolutions)
72
+ announce_when_no_value_found(@value)
82
73
 
83
- unless foundsuits
84
- Facter.debug "Found no suitable resolves of %s for %s" % [@resolves.length, @name]
85
- end
86
- end
87
-
88
- if @value.nil?
89
- # nothing
90
- Facter.debug("value for %s is still nil" % @name)
91
- return nil
92
- else
93
- return @value
74
+ @value
94
75
  end
95
76
  end
96
77
 
78
+
97
79
  private
98
80
 
99
81
  # Are we in the midst of a search?
@@ -103,16 +85,7 @@ class Facter::Util::Fact
103
85
 
104
86
  # Lock our searching process, so we never ge stuck in recursion.
105
87
  def searching
106
- if searching?
107
- Facter.debug "Caught recursion on %s" % @name
108
-
109
- # return a cached value if we've got it
110
- if @value
111
- return @value
112
- else
113
- return nil
114
- end
115
- end
88
+ raise RuntimeError, "Caught recursion on #{@name}" if searching?
116
89
 
117
90
  # If we've gotten this far, we're not already searching, so go ahead and do so.
118
91
  @searching = true
@@ -122,4 +95,38 @@ class Facter::Util::Fact
122
95
  @searching = false
123
96
  end
124
97
  end
98
+
99
+ def find_suitable_resolutions(resolutions)
100
+ resolutions.find_all{ |resolve| resolve.suitable? }
101
+ end
102
+
103
+ def sort_by_weight(resolutions)
104
+ resolutions.sort { |a, b| b.weight <=> a.weight }
105
+ end
106
+
107
+ def find_first_real_value(resolutions)
108
+ resolutions.each do |resolve|
109
+ value = normalize_value(resolve.value)
110
+ if not value.nil?
111
+ return value
112
+ end
113
+ end
114
+ nil
115
+ end
116
+
117
+ def announce_when_no_suitable_resolution(resolutions)
118
+ if resolutions.empty?
119
+ Facter.debug "Found no suitable resolves of %s for %s" % [@resolves.length, @name]
120
+ end
121
+ end
122
+
123
+ def announce_when_no_value_found(value)
124
+ if value.nil?
125
+ Facter.debug("value for %s is still nil" % @name)
126
+ end
127
+ end
128
+
129
+ def normalize_value(value)
130
+ value == "" ? nil : value
131
+ end
125
132
  end
@@ -0,0 +1,32 @@
1
+ module Facter
2
+ module Util
3
+ ##
4
+ # {Facter::Util::FileRead} is a utility module intended to provide easily
5
+ # mockable methods that delegate to simple file read methods. The intent is to
6
+ # avoid the need to execute the `cat` system command or `File.read` directly in
7
+ # Ruby, as mocking these behaviors can have wide-ranging effects.
8
+ #
9
+ # All Facter facts are encouraged to use this method instead of File.read or
10
+ # Facter::Util::Resolution.exec('cat ...')
11
+ #
12
+ # @api public
13
+ module FileRead
14
+ ##
15
+ # read returns the raw content of a file as a string. If the file does not
16
+ # exist, or the process does not have permission to read the file then nil is
17
+ # returned.
18
+ #
19
+ # @api public
20
+ #
21
+ # @return [String] the raw contents of the file at {path} or {nil} if the
22
+ # file cannot be read because it does not exist or the process does not have
23
+ # permission to read the file.
24
+ def self.read(path)
25
+ File.read(path)
26
+ rescue Errno::ENOENT, Errno::EACCES => detail
27
+ Facter.debug "Could not read #{path}: #{detail.message}"
28
+ nil
29
+ end
30
+ end
31
+ end
32
+ end
@@ -5,8 +5,8 @@ module Facter::Util::IP
5
5
  # a given platform or set of platforms.
6
6
  REGEX_MAP = {
7
7
  :linux => {
8
- :ipaddress => /inet addr:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/,
9
- :ipaddress6 => /inet6 addr: ((?![fe80|::1])(?>[0-9,a-f,A-F]*\:{1,2})+[0-9,a-f,A-F]{0,4})/,
8
+ :ipaddress => /inet (?:addr:)?([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/,
9
+ :ipaddress6 => /inet6 (?:addr: )?((?![fe80|::1])(?>[0-9,a-f,A-F]*\:{1,2})+[0-9,a-f,A-F]{0,4})/,
10
10
  :macaddress => /(?:ether|HWaddr)\s+((\w{1,2}:){5,}\w{1,2})/,
11
11
  :netmask => /Mask:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/,
12
12
  :mtu => /MTU:(\d+)/
@@ -286,11 +286,4 @@ module Facter::Util::IP
286
286
  network = ip.mask(subnet.to_s).to_s
287
287
  end
288
288
  end
289
-
290
- def self.get_arp_value(interface)
291
- arp = Facter::Util::Resolution.exec("arp -en -i #{interface} | sed -e 1d")
292
- if arp =~ /^\S+\s+\w+\s+(\S+)\s+\w\s+\S+$/
293
- return $1
294
- end
295
- end
296
289
  end
@@ -1,10 +1,13 @@
1
1
  require 'facter'
2
+ require 'pathname'
3
+ require 'facter/util/directory_loader'
2
4
 
3
5
  # Load facts on demand.
4
6
  class Facter::Util::Loader
5
7
 
6
8
  def initialize
7
9
  @loaded = []
10
+ @valid_path = {}
8
11
  end
9
12
 
10
13
  # Load all resolutions for a single fact.
@@ -53,14 +56,25 @@ class Facter::Util::Loader
53
56
  result = []
54
57
  result += $LOAD_PATH.collect { |d| File.join(d, "facter") }
55
58
  if ENV.include?("FACTERLIB")
56
- result += ENV["FACTERLIB"].split(":")
59
+ result += ENV["FACTERLIB"].split(File::PATH_SEPARATOR)
57
60
  end
58
61
 
59
62
  # This allows others to register additional paths we should search.
60
63
  result += Facter.search_path
61
64
 
62
- result
65
+ result.select do |dir|
66
+ good = valid_search_path? dir
67
+ Facter.debugonce("Relative directory #{dir} removed from search path.") unless good
68
+ good
69
+ end
70
+ end
71
+
72
+ def valid_search_path?(path)
73
+ return @valid_path[path] unless @valid_path[path].nil?
74
+
75
+ return @valid_path[path] = Pathname.new(path).absolute?
63
76
  end
77
+ private :valid_search_path?
64
78
 
65
79
  private
66
80
 
@@ -7,9 +7,11 @@
7
7
 
8
8
  module Facter::Util::Macosx
9
9
  require 'thread'
10
- require 'facter/util/plist'
10
+ require 'facter/util/cfpropertylist'
11
11
  require 'facter/util/resolution'
12
12
 
13
+ Plist_Xml_Doctype = '<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">'
14
+
13
15
  # JJM I'd really like to dynamically generate these methods
14
16
  # by looking at the _name key of the _items dict for each _dataType
15
17
 
@@ -19,7 +21,18 @@ module Facter::Util::Macosx
19
21
 
20
22
  def self.intern_xml(xml)
21
23
  return nil unless xml
22
- Plist::parse_xml(xml)
24
+ bad_xml_doctype = /^.*<!DOCTYPE plist PUBLIC -\/\/Apple Computer.*$/
25
+ if xml =~ bad_xml_doctype
26
+ xml.gsub!( bad_xml_doctype, Plist_Xml_Doctype )
27
+ Facter.debug("Had to fix plist with incorrect DOCTYPE declaration")
28
+ end
29
+ plist = Facter::Util::CFPropertyList::List.new
30
+ begin
31
+ plist.load_str(xml)
32
+ rescue => e
33
+ fail("A plist file could not be properly read by Facter::Util::CFPropertyList: #{e.inspect}")
34
+ end
35
+ Facter::Util::CFPropertyList.native_types(plist.value)
23
36
  end
24
37
 
25
38
  # Return an xml result, modified as we need it.
@@ -3,25 +3,17 @@
3
3
  ##
4
4
 
5
5
  module Facter::Memory
6
- require 'thread'
7
-
8
6
  def self.meminfo_number(tag)
9
7
  memsize = ""
10
- Thread::exclusive do
11
- size, scale = [0, ""]
12
- File.readlines("/proc/meminfo").each do |l|
13
- size, scale = [$1.to_f, $2] if l =~ /^#{tag}:\s+(\d+)\s+(\S+)/
14
- # MemoryFree == memfree + cached + buffers
15
- # (assume scales are all the same as memfree)
16
- if tag == "MemFree" &&
17
- l =~ /^(?:Buffers|Cached):\s+(\d+)\s+(?:\S+)/
18
- size += $1.to_f
19
- end
8
+ size = [0]
9
+ File.readlines("/proc/meminfo").each do |l|
10
+ size = $1.to_f if l =~ /^#{tag}:\s+(\d+)\s+\S+/
11
+ if tag == "MemFree" &&
12
+ l =~ /^(?:Buffers|Cached):\s+(\d+)\s+\S+/
13
+ size += $1.to_f
20
14
  end
21
- memsize = scale_number(size, scale)
22
15
  end
23
-
24
- memsize
16
+ size / 1024.0
25
17
  end
26
18
 
27
19
  def self.scale_number(size, multiplier)
@@ -37,18 +29,15 @@ module Facter::Memory
37
29
  s = suffixes.shift
38
30
  end
39
31
 
40
- return "%.2f %s" % [size, s]
32
+ "%.2f %s" % [size, s]
41
33
  end
42
34
 
43
- def self.vmstat_find_free_memory()
44
- row = Facter::Util::Resolution.exec('vmstat').split("\n")[-1]
35
+ def self.vmstat_find_free_memory(args = [])
36
+ cmd = 'vmstat'
37
+ cmd += (' ' + args.join(' ')) unless args.empty?
38
+ row = Facter::Util::Resolution.exec(cmd).split("\n")[-1]
45
39
  if row =~ /^\s*\d+\s*\d+\s*\d+\s*\d+\s*(\d+)/
46
- Facter.add("MemoryFree") do
47
- memfree = $1
48
- setcode do
49
- Facter::Memory.scale_number(memfree.to_f, "kB")
50
- end
51
- end
40
+ memfree = $1
52
41
  end
53
42
  end
54
43
 
@@ -76,10 +65,148 @@ module Facter::Memory
76
65
  end
77
66
 
78
67
  freemem = ( memfree + memspecfree ) * pagesize
79
- Facter.add("MemoryFree") do
80
- setcode do
81
- Facter::Memory.scale_number(freemem.to_f, "")
68
+ end
69
+
70
+ def self.mem_free(kernel = Facter.value(:kernel))
71
+ output = mem_free_info(kernel)
72
+ scale_mem_free_value output, kernel
73
+ end
74
+
75
+ def self.mem_free_info(kernel = Facter.value(:kernel))
76
+ case kernel
77
+ when /OpenBSD/i, /SunOS/i, /Dragonfly/i
78
+ vmstat_find_free_memory()
79
+ when /FreeBSD/i
80
+ vmstat_find_free_memory(["-H"])
81
+ when /Darwin/i
82
+ vmstat_darwin_find_free_memory()
83
+ end
84
+ end
85
+
86
+ def self.scale_mem_free_value (value, kernel)
87
+ case kernel
88
+ when /OpenBSD/i, /FreeBSD/i, /SunOS/i, /Dragonfly/i
89
+ value.to_f / 1024.0
90
+ when /Darwin/i
91
+ value.to_f / 1024.0 / 1024.0
92
+ else
93
+ value.to_f
94
+ end
95
+ end
96
+
97
+ def self.mem_size(kernel = Facter.value(:kernel))
98
+ output = mem_size_info(kernel)
99
+ scale_mem_size_value output, kernel
100
+ end
101
+
102
+ def self.mem_size_info(kernel = Facter.value(:kernel))
103
+ case kernel
104
+ when /OpenBSD/i
105
+ Facter::Util::Resolution.exec("sysctl hw.physmem | cut -d'=' -f2")
106
+ when /FreeBSD/i
107
+ Facter::Util::Resolution.exec("sysctl -n hw.physmem")
108
+ when /Darwin/i
109
+ Facter::Util::Resolution.exec("sysctl -n hw.memsize")
110
+ when /Dragonfly/i
111
+ Facter::Util::Resolution.exec("sysctl -n hw.physmem")
112
+ end
113
+ end
114
+
115
+ def self.scale_mem_size_value(value, kernel)
116
+ case kernel
117
+ when /OpenBSD/i, /FreeBSD/i, /Darwin/i, /Dragonfly/i
118
+ value.to_f / 1024.0 / 1024.0
119
+ else
120
+ value.to_f
121
+ end
122
+ end
123
+
124
+ def self.swap_size(kernel = Facter.value(:kernel))
125
+ output = swap_info(kernel)
126
+ parse_swap output, kernel, :size if output
127
+ end
128
+
129
+ def self.swap_free(kernel = Facter.value(:kernel))
130
+ output = swap_info(kernel)
131
+ parse_swap output, kernel, :free if output
132
+ end
133
+
134
+ def self.swap_info(kernel = Facter.value(:kernel))
135
+ case kernel
136
+ when /AIX/i
137
+ (Facter.value(:id) == "root") ? Facter::Util::Resolution.exec('swap -l') : nil
138
+ when /OpenBSD/i
139
+ Facter::Util::Resolution.exec('swapctl -s')
140
+ when /FreeBSD/i
141
+ Facter::Util::Resolution.exec('swapinfo -k')
142
+ when /Darwin/i
143
+ Facter::Util::Resolution.exec('sysctl vm.swapusage')
144
+ when /SunOS/i
145
+ Facter::Util::Resolution.exec('/usr/sbin/swap -l')
146
+ end
147
+ end
148
+
149
+ def self.parse_swap (output, kernel = Facter.value(:kernel), size_or_free = :size)
150
+ value_in_mb = 0.0
151
+ value = 0
152
+ is_size = size_or_free == :size
153
+ unless output.nil?
154
+ output.each_line do |line|
155
+ value += parse_swap_line(line, kernel, is_size)
156
+ end
157
+ end
158
+ value_in_mb = scale_swap_value(value, kernel)
159
+ end
160
+
161
+ # There is a lot of duplication here because of concern over being able to add
162
+ # new platforms in a reasonable manner. For all of these platforms the first
163
+ # regex corresponds to the swap size value and the second corresponds to the swap
164
+ # free value, but this may not always be the case. In Ruby 1.9.3 it is possible
165
+ # to give these names, but sadly 1.8.7 does not support this.
166
+
167
+ def self.parse_swap_line(line, kernel, is_size)
168
+ case kernel
169
+ when /AIX/i
170
+ if line =~ /^\/\S+\s.*\s+(\S+)MB\s+(\S+)MB/
171
+ (is_size) ? $1.to_i : $2.to_i
172
+ else
173
+ 0
174
+ end
175
+ when /OpenBSD/i
176
+ if line =~ /^total: (\d+)k bytes allocated = \d+k used, (\d+)k available$/
177
+ (is_size) ? $1.to_i : $2.to_i
178
+ else
179
+ 0
180
+ end
181
+ when /FreeBSD/i
182
+ if line =~ /\S+\s+(\d+)\s+\d+\s+(\d+)\s+\d+%$/
183
+ (is_size) ? $1.to_i : $2.to_i
184
+ else
185
+ 0
186
+ end
187
+ when /Darwin/i
188
+ if line =~ /total\s=\s(\S+)M\s+used\s=\s\S+M\s+free\s=\s(\S+)M\s/
189
+ (is_size) ? $1.to_i : $2.to_i
190
+ else
191
+ 0
82
192
  end
193
+ when /SunOS/i
194
+ if line =~ /^\/\S+\s.*\s+(\d+)\s+(\d+)$/
195
+ (is_size) ? $1.to_i : $2.to_i
196
+ else
197
+ 0
198
+ end
199
+ end
200
+ end
201
+
202
+ def self.scale_swap_value(value, kernel)
203
+ case kernel
204
+ when /OpenBSD/i, /FreeBSD/i
205
+ value.to_f / 1024.0
206
+ when /SunOS/i
207
+ value.to_f / 2 / 1024.0
208
+ else
209
+ value.to_f
83
210
  end
84
211
  end
85
212
  end