facter 1.7.2 → 1.7.3.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 (45) hide show
  1. data/README.md +8 -0
  2. data/Rakefile +10 -4
  3. data/ext/build_defaults.yaml +4 -3
  4. data/ext/debian/changelog.erb +7 -1
  5. data/ext/debian/control +2 -2
  6. data/ext/redhat/facter.spec.erb +1 -1
  7. data/install.rb +1 -1
  8. data/lib/facter/domain.rb +11 -3
  9. data/lib/facter/hardwaremodel.rb +7 -2
  10. data/lib/facter/ipaddress.rb +16 -4
  11. data/lib/facter/ipaddress6.rb +12 -3
  12. data/lib/facter/macaddress.rb +1 -1
  13. data/lib/facter/netmask.rb +19 -0
  14. data/lib/facter/util/directory_loader.rb +1 -1
  15. data/lib/facter/util/ip.rb +14 -18
  16. data/lib/facter/util/ip/windows.rb +215 -0
  17. data/lib/facter/util/macaddress.rb +3 -9
  18. data/lib/facter/util/netmask.rb +1 -1
  19. data/lib/facter/util/parser.rb +30 -19
  20. data/lib/facter/version.rb +1 -1
  21. data/lib/facter/virtual.rb +5 -5
  22. data/spec/fixtures/unit/ipaddress/ifconfig_non_english_locale.txt +18 -0
  23. data/spec/lib/facter_spec/windows_network.rb +64 -0
  24. data/spec/spec_helper.rb +25 -7
  25. data/spec/unit/architecture_spec.rb +1 -0
  26. data/spec/unit/domain_spec.rb +37 -6
  27. data/spec/unit/ec2_spec.rb +1 -1
  28. data/spec/unit/facter_spec.rb +2 -2
  29. data/spec/unit/hardwaremodel_spec.rb +16 -1
  30. data/spec/unit/ipaddress6_spec.rb +106 -13
  31. data/spec/unit/ipaddress_spec.rb +100 -22
  32. data/spec/unit/macaddress_spec.rb +0 -4
  33. data/spec/unit/memory_spec.rb +8 -7
  34. data/spec/unit/netmask_spec.rb +62 -5
  35. data/spec/unit/util/ip/windows_spec.rb +48 -0
  36. data/spec/unit/util/ip_spec.rb +9 -21
  37. data/spec/unit/util/macaddress_spec.rb +52 -10
  38. data/spec/unit/util/parser_spec.rb +32 -3
  39. data/spec/unit/util/virtual_spec.rb +9 -4
  40. data/spec/unit/zfs_version_spec.rb +4 -5
  41. data/spec/unit/zpool_version_spec.rb +4 -5
  42. metadata +480 -477
  43. data/ext/osx/PackageInfo.plist +0 -36
  44. data/ext/osx/createpackage.sh +0 -179
  45. data/spec/fixtures/netsh/windows_netsh_addresses_with_multiple_interfaces +0 -35
data/README.md CHANGED
@@ -20,6 +20,14 @@ Adding your own facts
20
20
  See the [Adding Facts](http://docs.puppetlabs.com/guides/custom_facts.html)
21
21
  page for details of how to add your own custom facts to Facter.
22
22
 
23
+ Running Specs
24
+ -------------
25
+
26
+ * bundle install --path .bundle/gems
27
+ * bundle exec rake spec
28
+
29
+ Note: external facts in the system facts.d directory can cause spec failures.
30
+
23
31
  Further Information
24
32
  -------------------
25
33
 
data/Rakefile CHANGED
@@ -10,13 +10,19 @@ require 'rake'
10
10
 
11
11
  begin
12
12
  load File.join(File.dirname(__FILE__), 'ext', 'packaging', 'packaging.rake')
13
- require 'rubygems'
14
- require 'rspec'
15
- require 'rspec/core/rake_task'
16
- require 'rcov'
17
13
  rescue LoadError
18
14
  end
19
15
 
16
+ ['rubygems',
17
+ 'rspec',
18
+ 'rspec/core/rake_task',
19
+ 'rcov',].each do |lib|
20
+ begin
21
+ require lib
22
+ rescue LoadError
23
+ end
24
+ end
25
+
20
26
  Dir['tasks/**/*.rake'].each { |t| load t }
21
27
 
22
28
  build_defs_file = 'ext/build_defaults.yaml'
@@ -9,15 +9,16 @@ gpg_name: 'info@puppetlabs.com'
9
9
  gpg_key: '4BD6EC30'
10
10
  sign_tar: FALSE
11
11
  # a space separated list of mock configs
12
- final_mocks: 'pl-el-5-i386 pl-el-5-x86_64 pl-el-6-i386 pl-el-6-x86_64 pl-fedora-17-i386 pl-fedora-17-x86_64 pl-fedora-18-i386 pl-fedora-18-x86_64'
13
- yum_host: 'burji.puppetlabs.com'
12
+ final_mocks: 'pl-el-5-i386 pl-el-5-x86_64 pl-el-6-i386 pl-el-6-x86_64 pl-fedora-17-i386 pl-fedora-17-x86_64 pl-fedora-18-i386 pl-fedora-18-x86_64 pl-fedora-19-i386 pl-fedora-19-x86_64'
13
+ yum_host: 'yum.puppetlabs.com'
14
14
  yum_repo_path: '/opt/repository/yum/'
15
15
  build_gem: TRUE
16
16
  build_dmg: TRUE
17
17
  build_ips: TRUE
18
- apt_host: 'burji.puppetlabs.com'
18
+ apt_host: 'apt.puppetlabs.com'
19
19
  apt_repo_url: 'http://apt.puppetlabs.com'
20
20
  apt_repo_path: '/opt/repository/incoming'
21
21
  ips_repo: '/var/pkgrepo'
22
22
  ips_store: '/opt/repository'
23
23
  ips_host: 'solaris-11-ips-repo.acctest.dc1.puppetlabs.net'
24
+ tar_host: 'downloads.puppetlabs.com'
@@ -1,9 +1,15 @@
1
- facter (<%= @debversion %>) hardy lucid oneiric unstable sid wheezy lucid squeeze precise quantal; urgency=low
1
+ facter (<%= @debversion %>) lucid unstable sid wheezy lucid squeeze precise quantal raring; urgency=low
2
2
 
3
3
  * Update to version <% @debversion %>
4
4
 
5
5
  -- Puppet Labs Release <info@puppetlabs.com> <%= Time.now.strftime("%a, %d %b %Y %H:%M:%S %z")%>
6
6
 
7
+ facter (1.7.2-1puppetlabs2) lucid unstable sid wheezy lucid squeeze precise; urgency=low
8
+
9
+ * Remove dependenices on libssl-ruby from facter as they are not used
10
+
11
+ -- Matthaus Owens <matthaus@puppetlabs.com> Thu, 11 Jul 2013 13:11:30 +0000
12
+
7
13
  facter (1.7.0-0.1rc1puppetlabs1) hardy lucid oneiric unstable sid wheezy lucid squeeze precise; urgency=low
8
14
 
9
15
  * Add dependency on virt-what to facter for better virutalization detection
@@ -2,13 +2,13 @@ Source: facter
2
2
  Section: ruby
3
3
  Priority: optional
4
4
  Maintainer: Puppet Labs <info@puppetlabs.com>
5
- Build-Depends: cdbs, debhelper (>> 7), ruby | ruby-interpreter, libopenssl-ruby | libopenssl-ruby1.8 | libopenssl-ruby1.9.1, rdoc
5
+ Build-Depends: cdbs, debhelper (>> 7), ruby | ruby-interpreter
6
6
  Standards-Version: 3.9.1
7
7
  Homepage: http://www.puppetlabs.com
8
8
 
9
9
  Package: facter
10
10
  Architecture: any
11
- Depends: ${shlibs:Depends}, ${misc:Depends}, ruby | ruby-interpreter, libopenssl-ruby | libopenssl-ruby1.8 | libopenssl-ruby1.9.1, dmidecode [i386 amd64 ia64], virt-what, pciutils
11
+ Depends: ${shlibs:Depends}, ${misc:Depends}, ruby | ruby-interpreter, dmidecode [i386 amd64 ia64], virt-what, pciutils
12
12
  Description: Ruby module for collecting simple facts about a host operating system
13
13
  Some of the facts are preconfigured, such as the hostname and the operating
14
14
  system. Additional facts can be added through simple Ruby scripts.
@@ -32,7 +32,7 @@ Requires: dmidecode
32
32
  Requires: pciutils
33
33
  %endif
34
34
  Requires: virt-what
35
- Requires: ruby(abi) >= 1.8
35
+ Requires: ruby >= 1.8.5
36
36
  BuildRequires: ruby >= 1.8.5
37
37
 
38
38
  # In Fedora 17 ruby-rdoc is called rubygem-rdoc
data/install.rb CHANGED
@@ -60,7 +60,7 @@ $LOAD_PATH.unshift(File.expand_path(File.join(File.dirname(__FILE__), 'lib')))
60
60
  require 'facter'
61
61
  @operatingsystem = Facter[:operatingsystem].value
62
62
 
63
- PREREQS = %w{openssl xmlrpc/client xmlrpc/server cgi}
63
+ PREREQS = %w{cgi}
64
64
 
65
65
  InstallOptions = OpenStruct.new
66
66
 
@@ -29,11 +29,14 @@ Facter.add(:domain) do
29
29
  # Due to dangerous behavior of 'hostname -f' on old OS, we will explicitly opt-in
30
30
  # 'hostname -f' --hkenney May 9, 2012
31
31
  basic_hostname = 'hostname 2> /dev/null'
32
+ windows_hostname = 'hostname > NUL'
32
33
  full_hostname = 'hostname -f 2> /dev/null'
33
34
  can_do_hostname_f = Regexp.union /Linux/i, /FreeBSD/i, /Darwin/i
34
35
 
35
36
  hostname_command = if Facter.value(:kernel) =~ can_do_hostname_f
36
37
  full_hostname
38
+ elsif Facter.value(:kernel) == "windows"
39
+ windows_hostname
37
40
  else
38
41
  basic_hostname
39
42
  end
@@ -42,7 +45,7 @@ Facter.add(:domain) do
42
45
  and name =~ /.*?\.(.+$)/
43
46
 
44
47
  return_value = $1
45
- elsif domain = Facter::Util::Resolution.exec('dnsdomainname 2> /dev/null') \
48
+ elsif Facter.value(:kernel) != "windows" and domain = Facter::Util::Resolution.exec('dnsdomainname 2> /dev/null') \
46
49
  and domain =~ /.+/
47
50
 
48
51
  return_value = domain
@@ -76,10 +79,15 @@ Facter.add(:domain) do
76
79
  if domain == ""
77
80
  require 'facter/util/wmi'
78
81
  Facter::Util::WMI.execquery("select DNSDomain from Win32_NetworkAdapterConfiguration where IPEnabled = True").each { |nic|
79
- domain = nic.DNSDomain
80
- break
82
+ if nic.DNSDomain && nic.DNSDomain.length > 0
83
+ domain = nic.DNSDomain
84
+ break
85
+ end
81
86
  }
82
87
  end
88
+
89
+ domain ||= ''
90
+
83
91
  domain.gsub(/\.$/, '')
84
92
  end
85
93
  end
@@ -32,17 +32,22 @@ Facter.add(:hardwaremodel) do
32
32
  # http://source.winehq.org/source/include/winnt.h#L568
33
33
  # http://msdn.microsoft.com/en-us/library/windows/desktop/aa394373(v=vs.85).aspx
34
34
  # http://msdn.microsoft.com/en-us/library/windows/desktop/windows.system.processorarchitecture.aspx
35
+ # http://linux.derkeiler.com/Mailing-Lists/Kernel/2008-05/msg12924.html (anything over 6 is still i686)
35
36
  # Also, arm and neutral are included because they are valid for the upcoming
36
37
  # windows 8 release. --jeffweiss 23 May 2012
37
38
  require 'facter/util/wmi'
38
39
  model = ""
40
+ architecture_level = nil
41
+
39
42
  Facter::Util::WMI.execquery("select Architecture, Level, AddressWidth from Win32_Processor").each do |cpu|
43
+ architecture_level = (cpu.Level > 5) ? 6 : cpu.Level;
44
+
40
45
  model =
41
46
  case cpu.Architecture
42
47
  when 11 then 'neutral' # PROCESSOR_ARCHITECTURE_NEUTRAL
43
48
  when 10 then 'i686' # PROCESSOR_ARCHITECTURE_IA32_ON_WIN64
44
49
  when 9 then # PROCESSOR_ARCHITECTURE_AMD64
45
- cpu.AddressWidth == 32 ? "i#{cpu.Level}86" : 'x64' # 32 bit OS on 64 bit CPU
50
+ cpu.AddressWidth == 32 ? "i#{architecture_level}86" : 'x64' # 32 bit OS on 64 bit CPU
46
51
  when 8 then 'msil' # PROCESSOR_ARCHITECTURE_MSIL
47
52
  when 7 then 'alpha64' # PROCESSOR_ARCHITECTURE_ALPHA64
48
53
  when 6 then 'ia64' # PROCESSOR_ARCHITECTURE_IA64
@@ -51,7 +56,7 @@ Facter.add(:hardwaremodel) do
51
56
  when 3 then 'powerpc' # PROCESSOR_ARCHITECTURE_PPC
52
57
  when 2 then 'alpha' # PROCESSOR_ARCHITECTURE_ALPHA
53
58
  when 1 then 'mips' # PROCESSOR_ARCHITECTURE_MIPS
54
- when 0 then "i#{cpu.Level}86" # PROCESSOR_ARCHITECTURE_INTEL
59
+ when 0 then "i#{architecture_level}86" # PROCESSOR_ARCHITECTURE_INTEL
55
60
  else 'unknown' # PROCESSOR_ARCHITECTURE_UNKNOWN
56
61
  end
57
62
  break
@@ -33,11 +33,13 @@ Facter.add(:ipaddress) do
33
33
  regexp = /inet (?:addr:)?([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/
34
34
  output.split("\n").each do |line|
35
35
  match = regexp.match(line)
36
- if match
37
- break match[1] unless /^127/.match(match[1])
36
+ if match and not /^127\./.match(match[1])
37
+ ip = match[1]
38
+ break
38
39
  end
39
40
  end
40
41
  end
42
+ ip
41
43
  end
42
44
  end
43
45
 
@@ -104,8 +106,18 @@ end
104
106
  Facter.add(:ipaddress) do
105
107
  confine :kernel => %w{windows}
106
108
  setcode do
107
- require 'socket'
108
- IPSocket.getaddress(Socket.gethostname)
109
+ require 'facter/util/ip/windows'
110
+ ipaddr = nil
111
+
112
+ adapters = Facter::Util::IP::Windows.get_preferred_ipv4_adapters
113
+ adapters.find do |nic|
114
+ nic.IPAddress.any? do |addr|
115
+ ipaddr = addr if Facter::Util::IP::Windows.valid_ipv4_address?(addr)
116
+ ipaddr
117
+ end
118
+ end
119
+
120
+ ipaddr
109
121
  end
110
122
  end
111
123
 
@@ -26,7 +26,7 @@ require 'facter/util/ip'
26
26
  def get_address_after_token(output, token, return_first=false)
27
27
  ip = nil
28
28
 
29
- output.scan(/#{token} ((?>[0-9,a-f,A-F]*\:{1,2})+[0-9,a-f,A-F]{0,4})/).each do |match|
29
+ String(output).scan(/#{token}\s?((?>[0-9,a-f,A-F]*\:{1,2})+[0-9,a-f,A-F]{0,4})/).each do |match|
30
30
  match = match.first
31
31
  unless match =~ /fe80.*/ or match == "::1"
32
32
  ip = match
@@ -66,8 +66,17 @@ end
66
66
  Facter.add(:ipaddress6) do
67
67
  confine :kernel => :windows
68
68
  setcode do
69
- output = Facter::Util::Resolution.exec("#{ENV['SYSTEMROOT']}/system32/netsh.exe interface ipv6 show address level=verbose")
69
+ require 'facter/util/ip/windows'
70
+ ipaddr = nil
70
71
 
71
- get_address_after_token(output, 'Address', true)
72
+ adapters = Facter::Util::IP::Windows.get_preferred_ipv6_adapters
73
+ adapters.find do |nic|
74
+ nic.IPAddress.any? do |addr|
75
+ ipaddr = addr if Facter::Util::IP::Windows.valid_ipv6_address?(addr)
76
+ ipaddr
77
+ end
78
+ end
79
+
80
+ ipaddr
72
81
  end
73
82
  end
@@ -29,7 +29,7 @@ Facter.add(:macaddress) do
29
29
  ether = []
30
30
  output = Facter::Util::IP.exec_ifconfig(["-a","2>/dev/null"])
31
31
 
32
- output.each_line do |s|
32
+ String(output).each_line do |s|
33
33
  ether.push($1) if s =~ /(?:ether|HWaddr) ((\w{1,2}:){5,}\w{1,2})/
34
34
  end
35
35
  Facter::Util::Macaddress.standardize(ether[0])
@@ -21,3 +21,22 @@ Facter.add("netmask") do
21
21
  Facter::NetMask.get_netmask
22
22
  end
23
23
  end
24
+
25
+ Facter.add(:netmask) do
26
+ confine :kernel => :windows
27
+ setcode do
28
+ require 'facter/util/ip/windows'
29
+
30
+ mask = nil
31
+
32
+ adapters = Facter::Util::IP::Windows.get_preferred_ipv4_adapters
33
+ adapters.find do |nic|
34
+ nic.IPSubnet.any? do |subnet|
35
+ mask = subnet if Facter::Util::IP::Windows.valid_ipv4_address?(subnet)
36
+ mask
37
+ end
38
+ end
39
+
40
+ mask
41
+ end
42
+ end
@@ -1,7 +1,7 @@
1
1
  # A Facter plugin that loads external facts.
2
2
  #
3
3
  # Default Unix Directories:
4
- # /etc/facter/facts.d, /etc/puppetlbas/facter/facts.d
4
+ # /etc/facter/facts.d", "/etc/puppetlabs/facter/facts.d"
5
5
  #
6
6
  # Default Windows Direcotires:
7
7
  # C:\ProgramData\Puppetlabs\facter\facts.d (2008)
@@ -31,11 +31,7 @@ module Facter::Util::IP
31
31
  :macaddress => /(\w{1,2}:\w{1,2}:\w{1,2}:\w{1,2}:\w{1,2}:\w{1,2})/,
32
32
  :netmask => /.*\s+netmask (\S+)\s.*/
33
33
  },
34
- :windows => {
35
- :ipaddress => /\s+IP Address:\s+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/,
36
- :ipaddress6 => /Address ((?![fe80|::1])(?>[0-9,a-f,A-F]*\:{1,2})+[0-9,a-f,A-F]{0,4})/,
37
- :netmask => /\s+Subnet Prefix:\s+\S+\s+\(mask ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\)/
38
- }
34
+ :windows => {}
39
35
  }
40
36
 
41
37
  # Convert an interface name into purely alphanumeric characters.
@@ -61,11 +57,12 @@ module Facter::Util::IP
61
57
  end
62
58
 
63
59
  def self.get_interfaces
64
- return [] unless output = Facter::Util::IP.get_all_interface_output()
60
+ if Facter.value(:kernel) == 'windows'
61
+ require 'facter/util/ip/windows'
62
+ return Facter::Util::IP::Windows.interfaces
63
+ end
65
64
 
66
- # windows interface names contain spaces and are quoted and can appear multiple
67
- # times as ipv4 and ipv6
68
- return output.scan(/\s* connected\s*(\S.*)/).flatten.uniq if Facter.value(:kernel) == 'windows'
65
+ return [] unless output = Facter::Util::IP.get_all_interface_output()
69
66
 
70
67
  # Our regex appears to be stupid, in that it leaves colons sitting
71
68
  # at the end of interfaces. So, we have to trim those trailing
@@ -89,9 +86,6 @@ module Facter::Util::IP
89
86
  output.sub!(/^[^\n]*\n/, "") # delete the header line.
90
87
  output
91
88
  end
92
- when 'windows'
93
- output = %x|#{ENV['SYSTEMROOT']}/system32/netsh.exe interface ip show interface|
94
- output += %x|#{ENV['SYSTEMROOT']}/system32/netsh.exe interface ipv6 show interface|
95
89
  end
96
90
  output
97
91
  end
@@ -172,12 +166,9 @@ module Facter::Util::IP
172
166
  def self.get_output_for_interface_and_label(interface, label)
173
167
  return get_single_interface_output(interface) unless Facter.value(:kernel) == 'windows'
174
168
 
175
- if label == 'ipaddress6'
176
- output = %x|#{ENV['SYSTEMROOT']}/system32/netsh.exe interface ipv6 show address \"#{interface}\"|
177
- else
178
- output = %x|#{ENV['SYSTEMROOT']}/system32/netsh.exe interface ip show address \"#{interface}\"|
179
- end
180
- output
169
+ require 'facter/util/ip/windows'
170
+ output = Facter::Util::IP::Windows.value_for_interface_and_label(interface, label)
171
+ output ? output : ""
181
172
  end
182
173
 
183
174
  def self.get_bonding_master(interface)
@@ -220,6 +211,11 @@ module Facter::Util::IP
220
211
  # @return [String] representing the requested value. An empty array is
221
212
  # returned if the kernel is not supported by the REGEX_MAP constant.
222
213
  def self.get_interface_value(interface, label)
214
+ if Facter.value(:kernel) == 'windows'
215
+ require 'facter/util/ip/windows'
216
+ return Facter::Util::IP::Windows.value_for_interface_and_label(interface, label)
217
+ end
218
+
223
219
  tmp1 = []
224
220
 
225
221
  kernel = Facter.value(:kernel).downcase.to_sym
@@ -0,0 +1,215 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'facter/util/wmi'
4
+ require 'facter/util/ip'
5
+
6
+ class Facter::Util::IP::Windows
7
+ # The WMI query used to return ip information
8
+ #
9
+ # @return [String]
10
+ #
11
+ # @api private
12
+ WMI_IP_INFO_QUERY = 'SELECT Description, ServiceName, IPAddress, IPConnectionMetric, InterfaceIndex, Index, IPSubnet, MACAddress, MTU, SettingID FROM Win32_NetworkAdapterConfiguration WHERE IPConnectionMetric IS NOT NULL AND IPEnabled = TRUE'
13
+
14
+ # Mapping fact names to WMI properties of the Win32_NetworkAdapterConfiguration
15
+ #
16
+ # @api private
17
+ WINDOWS_LABEL_WMI_MAP = {
18
+ :ipaddress => 'IPAddress',
19
+ :ipaddress6 => 'IPAddress',
20
+ :macaddress => 'MACAddress',
21
+ :netmask => 'IPSubnet'
22
+ }
23
+
24
+ def self.to_s
25
+ 'windows'
26
+ end
27
+
28
+ # Windows doesn't display netmask in hex.
29
+ #
30
+ # @return [Boolean] false by default
31
+ #
32
+ # @api private
33
+ def self.convert_netmask_from_hex?
34
+ false
35
+ end
36
+
37
+ # Retrieves a list of unique interfaces names.
38
+ #
39
+ # @return [Array<String>]
40
+ #
41
+ # @api private
42
+ def self.interfaces
43
+ interface_names = []
44
+
45
+ network_adapter_configurations.map do |nic|
46
+ Facter::Util::WMI.execquery("SELECT * FROM Win32_NetworkAdapter WHERE Index = #{nic.Index}").each do |nic|
47
+ interface_names << nic.NetConnectionId
48
+ end
49
+ end
50
+
51
+ interface_names.uniq
52
+ end
53
+
54
+ # Get the value of an interface and label. For example, you may want to find
55
+ # the MTU for eth0.
56
+ #
57
+ # @param [String] interface the name of the interface returned by the {#interfaces} method.
58
+ # @param [String] label the type of value to return, e.g. ipaddress
59
+ # @return [String] the value, or nil if not defined
60
+ #
61
+ # @api private
62
+ def self.value_for_interface_and_label(interface, label)
63
+ wmi_value = WINDOWS_LABEL_WMI_MAP[label.downcase.to_sym]
64
+ label_value = nil
65
+ Facter::Util::WMI.execquery("SELECT Index FROM Win32_NetworkAdapter WHERE NetConnectionID = '#{interface}'").each do |nic|
66
+ Facter::Util::WMI.execquery("SELECT #{wmi_value} FROM Win32_NetworkAdapterConfiguration WHERE Index = #{nic.Index}").each do |nic_config|
67
+ case label.downcase.to_sym
68
+ when :ipaddress
69
+ nic_config.IPAddress.any? do |addr|
70
+ label_value = addr if valid_ipv4_address?(addr)
71
+ label_value
72
+ end
73
+ when :ipaddress6
74
+ nic_config.IPAddress.any? do |addr|
75
+ label_value = addr if Facter::Util::IP::Windows.valid_ipv6_address?(addr)
76
+ label_value
77
+ end
78
+ when :netmask
79
+ nic_config.IPSubnet.any? do |addr|
80
+ label_value = addr if Facter::Util::IP::Windows.valid_ipv4_address?(addr)
81
+ label_value
82
+ end
83
+ when :macaddress
84
+ label_value = nic_config.MACAddress
85
+ end
86
+ end
87
+ end
88
+
89
+ label_value
90
+ end
91
+
92
+ # Returns an array of partial Win32_NetworkAdapterConfiguration objects.
93
+ #
94
+ # @return [Array<WIN32OLE>] objects
95
+ #
96
+ # @api private
97
+ def self.network_adapter_configurations
98
+ nics = []
99
+ # WIN32OLE doesn't implement Enumerable
100
+ Facter::Util::WMI.execquery(WMI_IP_INFO_QUERY).each do |nic|
101
+ nics << nic
102
+ end
103
+ nics
104
+ end
105
+
106
+ # Gets a list of active IPv4 network adapter configurations sorted by the
107
+ # lowest IP connection metric. If two configurations have the same metric,
108
+ # then the IPv4 specific binding order as specified in the registry will
109
+ # be used.
110
+ #
111
+ # @return [Array<WIN32OLE>]
112
+ #
113
+ # @api private
114
+ def self.get_preferred_ipv4_adapters
115
+ get_preferred_network_adapters(Bindings4.new)
116
+ end
117
+
118
+ # Gets a list of active IPv6 network adapter configurations sorted by the
119
+ # lowest IP connection metric. If two configurations have the same metric,
120
+ # then the IPv6 specific binding order as specified in the registry will
121
+ # be used.
122
+ #
123
+ # @return [Array<WIN32OLE>]
124
+ #
125
+ # @api private
126
+ def self.get_preferred_ipv6_adapters
127
+ get_preferred_network_adapters(Bindings6.new)
128
+ end
129
+
130
+ # Gets a list of active network adapter configurations sorted by the lowest
131
+ # IP connection metric. If two configurations have the same metric, then
132
+ # the adapter binding order as specified in the registry will be used.
133
+ # Note the order may different for IPv4 vs IPv6 addresses.
134
+ #
135
+ # @see http://support.microsoft.com/kb/894564
136
+ # @return [Array<WIN32OLE>]
137
+ #
138
+ # @api private
139
+ def self.get_preferred_network_adapters(bindings)
140
+ network_adapter_configurations.select do |nic|
141
+ bindings.bindings.include?(nic.SettingID)
142
+ end.sort do |nic_left,nic_right|
143
+ cmp = nic_left.IPConnectionMetric <=> nic_right.IPConnectionMetric
144
+ if cmp == 0
145
+ bindings.bindings[nic_left.SettingID] <=> bindings.bindings[nic_right.SettingID]
146
+ else
147
+ cmp
148
+ end
149
+ end
150
+ end
151
+
152
+ class Bindings4
153
+ def initialize
154
+ @key = 'SYSTEM\CurrentControlSet\Services\Tcpip\Linkage'
155
+ end
156
+
157
+ def bindings
158
+ require 'facter/util/registry'
159
+ bindings = {}
160
+
161
+ Facter::Util::Registry.hklm_read(@key, 'Bind').each_with_index do |entry, index|
162
+ match_data = entry.match(/\\Device\\(\{.*\})/)
163
+ unless match_data.nil?
164
+ bindings[match_data[1]] = index
165
+ end
166
+ end
167
+
168
+ bindings
169
+ rescue
170
+ {}
171
+ end
172
+ end
173
+
174
+ class Bindings6 < Bindings4
175
+ def initialize
176
+ @key = 'SYSTEM\CurrentControlSet\Services\Tcpip6\Linkage'
177
+ end
178
+ end
179
+
180
+ # Determines if the value passed in is a valid ipv4 address.
181
+ #
182
+ # @param [String] ip_address the IPv4 address to validate
183
+ # @return [Boolean]
184
+ #
185
+ # @api private
186
+ def self.valid_ipv4_address?(ip_address)
187
+ String(ip_address).scan(/(?:[0-9]{1,3}\.){3}[0-9]{1,3}/).each do |match|
188
+ # excluding 169.254.x.x in Windows - this is the DHCP APIPA
189
+ # meaning that if the node cannot get an ip address from the dhcp server,
190
+ # it auto-assigns a private ip address
191
+ unless match == "127.0.0.1" or match =~ /^169.254.*/
192
+ return !!match
193
+ end
194
+ end
195
+
196
+ false
197
+ end
198
+
199
+ # Determines if the value passed in is a valid ipv6 address.
200
+ #
201
+ # @param [String] ip_address the IPv6 address to validate
202
+ # @return [Boolean]
203
+ #
204
+ # @api private
205
+ def self.valid_ipv6_address?(ip_address)
206
+ String(ip_address).scan(/(?>[0-9,a-f,A-F]*\:{1,2})+[0-9,a-f,A-F]{0,4}/).each do |match|
207
+ unless match =~ /fe80.*/ or match == "::1"
208
+ return !!match
209
+ end
210
+ end
211
+
212
+ false
213
+ end
214
+
215
+ end