facter 1.3.8 → 1.5
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.
- data/CHANGELOG +68 -0
- data/README +1 -1
- data/Rakefile +2 -1
- data/bin/facter +16 -11
- data/lib/facter.rb +55 -1001
- data/lib/facter/Cfkey.rb +42 -0
- data/lib/facter/architecture.rb +14 -0
- data/lib/facter/domain.rb +64 -0
- data/lib/facter/facterversion.rb +3 -0
- data/lib/facter/fqdn.rb +10 -0
- data/lib/facter/hardwareisa.rb +4 -0
- data/lib/facter/hardwaremodel.rb +13 -0
- data/lib/facter/hostname.rb +25 -0
- data/lib/facter/id.rb +4 -0
- data/lib/facter/ipaddress.rb +151 -0
- data/lib/facter/iphostnumber.rb +18 -0
- data/lib/facter/ipmess.rb +64 -74
- data/lib/facter/kernel.rb +3 -0
- data/lib/facter/kernelrelease.rb +8 -0
- data/lib/facter/lsb.rb +37 -0
- data/lib/facter/lsbmajdistrelease.rb +15 -0
- data/lib/facter/macaddress.rb +65 -0
- data/lib/facter/macosx.rb +25 -55
- data/lib/facter/manufacturer.rb +7 -45
- data/lib/facter/memory.rb +26 -49
- data/lib/facter/netmask.rb +17 -0
- data/lib/facter/operatingsystem.rb +37 -0
- data/lib/facter/operatingsystemrelease.rb +63 -0
- data/lib/facter/processor.rb +36 -14
- data/lib/facter/ps.rb +8 -0
- data/lib/facter/puppetversion.rb +10 -0
- data/lib/facter/rubysitedir.rb +8 -0
- data/lib/facter/rubyversion.rb +3 -0
- data/lib/facter/ssh.rb +33 -0
- data/lib/facter/uniqueid.rb +4 -0
- data/lib/facter/util/collection.rb +126 -0
- data/lib/facter/util/confine.rb +41 -0
- data/lib/facter/util/fact.rb +122 -0
- data/lib/facter/util/ip.rb +98 -0
- data/lib/facter/util/loader.rb +96 -0
- data/lib/facter/util/macosx.rb +50 -0
- data/lib/facter/util/manufacturer.rb +39 -0
- data/lib/facter/util/memory.rb +54 -0
- data/lib/facter/util/netmask.rb +36 -0
- data/lib/facter/util/resolution.rb +125 -0
- metadata +76 -34
data/lib/facter/processor.rb
CHANGED
@@ -1,26 +1,13 @@
|
|
1
|
-
#
|
2
1
|
# processor.rb
|
3
2
|
# Additional Facts about the machine's CPUs
|
4
3
|
#
|
5
4
|
# Copyright (C) 2006 Mooter Media Ltd
|
6
5
|
# Author: Matthew Palmer <matt@solutionsfirst.com.au>
|
7
6
|
#
|
8
|
-
#
|
9
|
-
# This program is free software; you can redistribute it and/or
|
10
|
-
# modify it under the terms of the GNU General Public License
|
11
|
-
# as published by the Free Software Foundation (version 2 of the License)
|
12
|
-
# This program is distributed in the hope that it will be useful,
|
13
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
-
# GNU General Public License for more details.
|
16
|
-
# You should have received a copy of the GNU General Public License
|
17
|
-
# along with this program; if not, write to the Free Software
|
18
|
-
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston MA 02110-1301 USA
|
19
|
-
#
|
20
7
|
|
21
8
|
require 'thread'
|
22
9
|
|
23
|
-
if Facter.kernel == "Linux"
|
10
|
+
if Facter.value(:kernel) == "Linux"
|
24
11
|
processor_num = -1
|
25
12
|
processor_list = []
|
26
13
|
Thread::exclusive do
|
@@ -50,3 +37,38 @@ if Facter.kernel == "Linux"
|
|
50
37
|
end
|
51
38
|
end
|
52
39
|
end
|
40
|
+
|
41
|
+
if Facter.value(:kernel) == "AIX"
|
42
|
+
processor_num = -1
|
43
|
+
processor_list = {}
|
44
|
+
Thread::exclusive do
|
45
|
+
procs = Facter::Util::Resolution.exec('lsdev -Cc processor')
|
46
|
+
procs.each do |proc|
|
47
|
+
if proc =~ /^proc(\d+)/
|
48
|
+
processor_num = $1.to_i
|
49
|
+
# Not retrieving the frequency since AIX 4.3.3 doesn't support the
|
50
|
+
# attribute and some people still use the OS.
|
51
|
+
proctype = Facter::Util::Resolution.exec('lsattr -El proc0 -a type')
|
52
|
+
if proctype =~ /^type\s+(\S+)\s+/
|
53
|
+
processor_list["processor#{processor_num}"] = $1
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
Facter.add("ProcessorCount") do
|
60
|
+
confine :kernel => :aix
|
61
|
+
setcode do
|
62
|
+
processor_list.length.to_s
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
processor_list.each do |proc, desc|
|
67
|
+
Facter.add(proc) do
|
68
|
+
confine :kernel => :aix
|
69
|
+
setcode do
|
70
|
+
desc
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
data/lib/facter/ps.rb
ADDED
data/lib/facter/ssh.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
## ssh.rb
|
2
|
+
## Facts related to SSH
|
3
|
+
##
|
4
|
+
## This program is free software; you can redistribute it and/or
|
5
|
+
## modify it under the terms of the GNU General Public License
|
6
|
+
## as published by the Free Software Foundation (version 2 of the License)
|
7
|
+
## This program is distributed in the hope that it will be useful,
|
8
|
+
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
9
|
+
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
10
|
+
## GNU General Public License for more details.
|
11
|
+
## You should have received a copy of the GNU General Public License
|
12
|
+
## along with this program; if not, write to the Free Software
|
13
|
+
## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston MA 02110-1301 USA
|
14
|
+
##
|
15
|
+
|
16
|
+
["/etc/ssh","/usr/local/etc/ssh","/etc","/usr/local/etc"].each do |dir|
|
17
|
+
{"SSHDSAKey" => "ssh_host_dsa_key.pub", "SSHRSAKey" => "ssh_host_rsa_key.pub"}.each do |name,file|
|
18
|
+
Facter.add(name) do
|
19
|
+
setcode do
|
20
|
+
value = nil
|
21
|
+
filepath = File.join(dir,file)
|
22
|
+
if FileTest.file?(filepath)
|
23
|
+
begin
|
24
|
+
File.open(filepath) { |f| value = f.read.chomp.split(/\s+/)[1] }
|
25
|
+
rescue
|
26
|
+
value = nil
|
27
|
+
end
|
28
|
+
end
|
29
|
+
value
|
30
|
+
end # end of proc
|
31
|
+
end # end of add
|
32
|
+
end # end of hash each
|
33
|
+
end # end of dir each
|
@@ -0,0 +1,126 @@
|
|
1
|
+
require 'facter'
|
2
|
+
require 'facter/util/fact'
|
3
|
+
require 'facter/util/loader'
|
4
|
+
|
5
|
+
# Manage which facts exist and how we access them. Largely just a wrapper
|
6
|
+
# around a hash of facts.
|
7
|
+
class Facter::Util::Collection
|
8
|
+
# Return a fact object by name. If you use this, you still have to call
|
9
|
+
# 'value' on it to retrieve the actual value.
|
10
|
+
def [](name)
|
11
|
+
value(name)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Add a resolution mechanism for a named fact. This does not distinguish
|
15
|
+
# between adding a new fact and adding a new way to resolve a fact.
|
16
|
+
def add(name, options = {}, &block)
|
17
|
+
name = canonize(name)
|
18
|
+
|
19
|
+
unless fact = @facts[name]
|
20
|
+
fact = Facter::Util::Fact.new(name)
|
21
|
+
|
22
|
+
@facts[name] = fact
|
23
|
+
end
|
24
|
+
|
25
|
+
# Set any fact-appropriate options.
|
26
|
+
options.each do |opt, value|
|
27
|
+
method = opt.to_s + "="
|
28
|
+
if fact.respond_to?(method)
|
29
|
+
fact.send(method, value)
|
30
|
+
options.delete(opt)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
if block
|
35
|
+
resolve = fact.add(&block)
|
36
|
+
# Set any resolve-appropriate options
|
37
|
+
options.each do |opt, value|
|
38
|
+
method = opt.to_s + "="
|
39
|
+
if resolve.respond_to?(method)
|
40
|
+
resolve.send(method, value)
|
41
|
+
options.delete(opt)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
unless options.empty?
|
47
|
+
raise ArgumentError, "Invalid facter option(s) %s" % options.keys.collect { |k| k.to_s }.join(",")
|
48
|
+
end
|
49
|
+
|
50
|
+
return fact
|
51
|
+
end
|
52
|
+
|
53
|
+
include Enumerable
|
54
|
+
|
55
|
+
# Iterate across all of the facts.
|
56
|
+
def each
|
57
|
+
@facts.each do |name, fact|
|
58
|
+
value = fact.value
|
59
|
+
unless value.nil?
|
60
|
+
yield name.to_s, value
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Return a fact by name.
|
66
|
+
def fact(name)
|
67
|
+
name = canonize(name)
|
68
|
+
|
69
|
+
loader.load(name) unless @facts[name]
|
70
|
+
|
71
|
+
return @facts[name]
|
72
|
+
end
|
73
|
+
|
74
|
+
# Flush all cached values.
|
75
|
+
def flush
|
76
|
+
@facts.each { |name, fact| fact.flush }
|
77
|
+
end
|
78
|
+
|
79
|
+
def initialize
|
80
|
+
@facts = Hash.new
|
81
|
+
end
|
82
|
+
|
83
|
+
# Return a list of all of the facts.
|
84
|
+
def list
|
85
|
+
return @facts.keys
|
86
|
+
end
|
87
|
+
|
88
|
+
# Load all known facts.
|
89
|
+
def load_all
|
90
|
+
loader.load_all
|
91
|
+
end
|
92
|
+
|
93
|
+
# The thing that loads facts if we don't have them.
|
94
|
+
def loader
|
95
|
+
unless defined?(@loader)
|
96
|
+
@loader = Facter::Util::Loader.new
|
97
|
+
end
|
98
|
+
@loader
|
99
|
+
end
|
100
|
+
|
101
|
+
# Return a hash of all of our facts.
|
102
|
+
def to_hash
|
103
|
+
@facts.inject({}) do |h, ary|
|
104
|
+
value = ary[1].value
|
105
|
+
if ! value.nil?
|
106
|
+
# For backwards compatibility, convert the fact name to a string.
|
107
|
+
h[ary[0].to_s] = value
|
108
|
+
end
|
109
|
+
h
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def value(name)
|
114
|
+
if fact = fact(name)
|
115
|
+
fact.value
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
private
|
120
|
+
|
121
|
+
# Provide a consistent means of getting the exact same fact name
|
122
|
+
# every time.
|
123
|
+
def canonize(name)
|
124
|
+
name.to_s.downcase.to_sym
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# A restricting tag for fact resolution mechanisms. The tag must be true
|
2
|
+
# for the resolution mechanism to be suitable.
|
3
|
+
class Facter::Util::Confine
|
4
|
+
attr_accessor :fact, :values
|
5
|
+
|
6
|
+
# Add the restriction. Requires the fact name, an operator, and the value
|
7
|
+
# we're comparing to.
|
8
|
+
def initialize(fact, *values)
|
9
|
+
raise ArgumentError, "The fact name must be provided" unless fact
|
10
|
+
raise ArgumentError, "One or more values must be provided" if values.empty?
|
11
|
+
fact = fact.to_s if fact.is_a? Symbol
|
12
|
+
@fact = fact
|
13
|
+
@values = values.collect do |value|
|
14
|
+
if value.is_a? String
|
15
|
+
value
|
16
|
+
else
|
17
|
+
value.to_s
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_s
|
23
|
+
return "'%s' '%s'" % [@fact, @values.join(",")]
|
24
|
+
end
|
25
|
+
|
26
|
+
# Evaluate the fact, returning true or false.
|
27
|
+
def true?
|
28
|
+
unless fact = Facter[@fact]
|
29
|
+
Facter.debug "No fact for %s" % @fact
|
30
|
+
return false
|
31
|
+
end
|
32
|
+
value = fact.value
|
33
|
+
|
34
|
+
return false if value.nil?
|
35
|
+
|
36
|
+
@values.each { |v|
|
37
|
+
return true if value.downcase == v.downcase
|
38
|
+
}
|
39
|
+
return false
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
require 'facter'
|
2
|
+
require 'facter/util/resolution'
|
3
|
+
|
4
|
+
class Facter::Util::Fact
|
5
|
+
TIMEOUT = 5
|
6
|
+
|
7
|
+
attr_accessor :name, :ldapname
|
8
|
+
|
9
|
+
# Create a new fact, with no resolution mechanisms.
|
10
|
+
def initialize(name, options = {})
|
11
|
+
@name = name.to_s.downcase.intern
|
12
|
+
|
13
|
+
# LAK:NOTE: This is slow for many options, but generally we won't have any and at
|
14
|
+
# worst we'll have one. If we add more, this should be made more efficient.
|
15
|
+
options.each do |name, value|
|
16
|
+
case name
|
17
|
+
when :ldapname: self.ldapname = value
|
18
|
+
else
|
19
|
+
raise ArgumentError, "Invalid fact option '%s'" % name
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
@ldapname ||= @name.to_s
|
24
|
+
|
25
|
+
@resolves = []
|
26
|
+
@searching = false
|
27
|
+
|
28
|
+
@value = nil
|
29
|
+
end
|
30
|
+
|
31
|
+
# Add a new resolution mechanism. This requires a block, which will then
|
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
|
+
|
36
|
+
resolve = Facter::Util::Resolution.new(@name)
|
37
|
+
|
38
|
+
resolve.instance_eval(&block)
|
39
|
+
|
40
|
+
@resolves << resolve
|
41
|
+
|
42
|
+
# Immediately sort the resolutions, so that we always have
|
43
|
+
# a sorted list for looking up values.
|
44
|
+
# We always want to look them up in the order of number of
|
45
|
+
# confines, so the most restricted resolution always wins.
|
46
|
+
@resolves.sort! { |a, b| b.length <=> a.length }
|
47
|
+
|
48
|
+
return resolve
|
49
|
+
end
|
50
|
+
|
51
|
+
# Flush any cached values.
|
52
|
+
def flush
|
53
|
+
@value = nil
|
54
|
+
@suitable = nil
|
55
|
+
end
|
56
|
+
|
57
|
+
# Return the value for a given fact. Searches through all of the mechanisms
|
58
|
+
# and returns either the first value or nil.
|
59
|
+
def value
|
60
|
+
return @value if @value
|
61
|
+
|
62
|
+
if @resolves.length == 0
|
63
|
+
Facter.debug "No resolves for %s" % @name
|
64
|
+
return nil
|
65
|
+
end
|
66
|
+
|
67
|
+
searching do
|
68
|
+
@value = nil
|
69
|
+
|
70
|
+
foundsuits = false
|
71
|
+
@value = @resolves.inject(nil) { |result, resolve|
|
72
|
+
next unless resolve.suitable?
|
73
|
+
foundsuits = true
|
74
|
+
|
75
|
+
tmp = resolve.value
|
76
|
+
|
77
|
+
break tmp unless tmp.nil? or tmp == ""
|
78
|
+
}
|
79
|
+
|
80
|
+
unless foundsuits
|
81
|
+
Facter.debug "Found no suitable resolves of %s for %s" % [@resolves.length, @name]
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
if @value.nil?
|
86
|
+
# nothing
|
87
|
+
Facter.debug("value for %s is still nil" % @name)
|
88
|
+
return nil
|
89
|
+
else
|
90
|
+
return @value
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
# Are we in the midst of a search?
|
97
|
+
def searching?
|
98
|
+
@searching
|
99
|
+
end
|
100
|
+
|
101
|
+
# Lock our searching process, so we never ge stuck in recursion.
|
102
|
+
def searching
|
103
|
+
if searching?
|
104
|
+
Facter.debug "Caught recursion on %s" % @name
|
105
|
+
|
106
|
+
# return a cached value if we've got it
|
107
|
+
if @value
|
108
|
+
return @value
|
109
|
+
else
|
110
|
+
return nil
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# If we've gotten this far, we're not already searching, so go ahead and do so.
|
115
|
+
@searching = true
|
116
|
+
begin
|
117
|
+
yield
|
118
|
+
ensure
|
119
|
+
@searching = false
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
module Facter::IPAddress
|
2
|
+
|
3
|
+
def self.get_interfaces
|
4
|
+
|
5
|
+
int = nil
|
6
|
+
|
7
|
+
case Facter.value(:kernel)
|
8
|
+
when 'Linux', 'OpenBSD', 'NetBSD', 'FreeBSD'
|
9
|
+
output = %x{/sbin/ifconfig -a}
|
10
|
+
when 'SunOS'
|
11
|
+
output = %x{/usr/sbin/ifconfig -a}
|
12
|
+
end
|
13
|
+
|
14
|
+
# We get lots of warnings on platforms that don't get an output
|
15
|
+
# made.
|
16
|
+
if output
|
17
|
+
int = output.scan(/^\w+[.:]?\d+/)
|
18
|
+
else
|
19
|
+
[]
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.get_interface_value_nonbsd(interface, label)
|
25
|
+
|
26
|
+
tmp1 = nil
|
27
|
+
|
28
|
+
case Facter.value(:kernel)
|
29
|
+
when 'Linux'
|
30
|
+
output_int = %x{/sbin/ifconfig #{interface}}
|
31
|
+
addr = /inet addr:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/
|
32
|
+
mac = /(?:ether|HWaddr)\s+(\w{1,2}:\w{1,2}:\w{1,2}:\w{1,2}:\w{1,2}:\w{1,2})/
|
33
|
+
mask = /Mask:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/
|
34
|
+
when 'OpenBSD', 'NetBSD', 'FreeBSD'
|
35
|
+
output_int = %x{/sbin/ifconfig #{interface}}
|
36
|
+
addr = /inet\s+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/
|
37
|
+
mac = /(?:ether|lladdr)\s+(\w\w:\w\w:\w\w:\w\w:\w\w:\w\w)/
|
38
|
+
mask = /netmask\s+(\w{10})/
|
39
|
+
when 'SunOS'
|
40
|
+
output_int = %x{/usr/sbin/ifconfig #{interface}}
|
41
|
+
addr = /inet\s+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/
|
42
|
+
mac = /(?:ether|lladdr)\s+(\w?\w:\w?\w:\w?\w:\w?\w:\w?\w:\w?\w)/
|
43
|
+
mask = /netmask\s+(\w{8})/
|
44
|
+
end
|
45
|
+
|
46
|
+
case label
|
47
|
+
when 'ipaddress'
|
48
|
+
regex = addr
|
49
|
+
when 'macaddress'
|
50
|
+
regex = mac
|
51
|
+
when 'netmask'
|
52
|
+
regex = mask
|
53
|
+
end
|
54
|
+
|
55
|
+
if interface != "lo" && interface != "lo0"
|
56
|
+
output_int.each { |s|
|
57
|
+
tmp1 = $1 if s =~ regex
|
58
|
+
}
|
59
|
+
end
|
60
|
+
|
61
|
+
if tmp1
|
62
|
+
value = tmp1
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.get_interface_value_bsd(interface, label)
|
68
|
+
|
69
|
+
tmp1 = []
|
70
|
+
|
71
|
+
int_hash = {}
|
72
|
+
output_int = %x{/sbin/ifconfig #{interface}}
|
73
|
+
addr = /inet\s+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/
|
74
|
+
mac = /(?:ether|lladdr)\s+(\w\w:\w\w:\w\w:\w\w:\w\w:\w\w)/
|
75
|
+
mask = /netmask\s+(\w{10})/
|
76
|
+
|
77
|
+
case label
|
78
|
+
when 'ipaddress'
|
79
|
+
regex = addr
|
80
|
+
when 'macaddress'
|
81
|
+
regex = mac
|
82
|
+
when 'netmask'
|
83
|
+
regex = mask
|
84
|
+
end
|
85
|
+
|
86
|
+
if interface != "lo" && interface != "lo0"
|
87
|
+
output_int.each { |s|
|
88
|
+
tmp1.push($1) if s =~ regex
|
89
|
+
}
|
90
|
+
end
|
91
|
+
|
92
|
+
if tmp1
|
93
|
+
value = tmp1.shift
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|