[Pkg-puppet-devel] [facter] 32/61: (#16668) Use WMI to collect IPv6 address
Stig Sandbeck Mathisen
ssm at debian.org
Mon Nov 4 15:01:55 UTC 2013
This is an automated email from the git hooks/post-receive script.
ssm pushed a commit to branch master
in repository facter.
commit 66d8c80575e167946e72f8b0004ce79e0d1baf6b
Author: Rob Reynolds <rob at puppetlabs.com>
Date: Wed Jul 24 17:12:03 2013 -0700
(#16668) Use WMI to collect IPv6 address
Previously, we were using netsh.exe to collect the ipaddress6 fact, but it
relied on en_US output that wasn't internationalizable.
This commit uses WMI, like the ipaddress fact, and handles issues like
multiple NICs, both IPv4 and IPv6 IP addresses on a single NIC,
per-interface metrics, and the binding order of interfaces.
---
lib/facter/ipaddress6.rb | 15 ++++-
lib/facter/util/ip/windows.rb | 18 +++++
spec/unit/ipaddress6_spec.rb | 145 ++++++++++++++++++++++++++++++++++++++---
3 files changed, 167 insertions(+), 11 deletions(-)
diff --git a/lib/facter/ipaddress6.rb b/lib/facter/ipaddress6.rb
index 4e44d13..559088b 100644
--- a/lib/facter/ipaddress6.rb
+++ b/lib/facter/ipaddress6.rb
@@ -26,7 +26,7 @@ require 'facter/util/ip'
def get_address_after_token(output, token, return_first=false)
ip = nil
- String(output).scan(/#{token} ((?>[0-9,a-f,A-F]*\:{1,2})+[0-9,a-f,A-F]{0,4})/).each do |match|
+ String(output).scan(/#{token}\s?((?>[0-9,a-f,A-F]*\:{1,2})+[0-9,a-f,A-F]{0,4})/).each do |match|
match = match.first
unless match =~ /fe80.*/ or match == "::1"
ip = match
@@ -66,8 +66,17 @@ end
Facter.add(:ipaddress6) do
confine :kernel => :windows
setcode do
- output = Facter::Util::Resolution.exec("#{ENV['SYSTEMROOT']}/system32/netsh.exe interface ipv6 show address level=verbose")
+ require 'facter/util/ip/windows'
+ ipaddr = nil
- get_address_after_token(output, 'Address', true)
+ adapters = Facter::Util::IP::Windows.get_preferred_network_adapters
+ adapters.find do |nic|
+ nic.IPAddress.any? do |addr|
+ ipaddr = addr if Facter::Util::IP::Windows.valid_ipv6_address?(addr)
+ ipaddr
+ end
+ end
+
+ ipaddr
end
end
diff --git a/lib/facter/util/ip/windows.rb b/lib/facter/util/ip/windows.rb
index 11ce6ec..3030d30 100644
--- a/lib/facter/util/ip/windows.rb
+++ b/lib/facter/util/ip/windows.rb
@@ -104,4 +104,22 @@ class Facter::Util::IP::Windows
nil
end
+
+ # Determines if the value passed in is a valid ipv6 address.
+ #
+ # @param ip_address [String]
+ #
+ # @return [String] or [NilClass]
+ #
+ # @api private
+ def self.valid_ipv6_address?(ip_address)
+ String(ip_address).scan(/(?>[0-9,a-f,A-F]*\:{1,2})+[0-9,a-f,A-F]{0,4}/).each do |match|
+ unless match =~ /fe80.*/ or match == "::1"
+ return match
+ end
+ end
+
+ nil
+ end
+
end
diff --git a/spec/unit/ipaddress6_spec.rb b/spec/unit/ipaddress6_spec.rb
index 54e553d..e46ef86 100755
--- a/spec/unit/ipaddress6_spec.rb
+++ b/spec/unit/ipaddress6_spec.rb
@@ -12,7 +12,7 @@ def netsh_fixture(filename)
end
-describe "IPv6 address fact" do
+describe "The IPv6 address fact" do
include FacterSpec::ConfigHelper
before do
@@ -55,14 +55,143 @@ describe "IPv6 address fact" do
Facter.value(:ipaddress6).should == "2610:10:20:209:203:baff:fe27:a7c"
end
- it "should return ipaddress6 information for Windows" do
- ENV.stubs(:[]).with('SYSTEMROOT').returns('d:/windows')
- given_a_configuration_of(:is_windows => true)
+ context "on Windows" do
+ require 'facter/util/wmi'
+ require 'facter/util/registry'
+ require 'facter/util/ip/windows'
- fixture = netsh_fixture('windows_netsh_addresses_with_multiple_interfaces')
- Facter::Util::Resolution.stubs(:exec).with('d:/windows/system32/netsh.exe interface ipv6 show address level=verbose').
- returns(fixture)
+ let(:settingId0) { '{4AE6B55C-6DD6-427D-A5BB-13535D4BE926}' }
+ let(:settingId1) { '{38762816-7957-42AC-8DAA-3B08D0C857C7}' }
+ let(:nic_bindings) { ["\\Device\\#{settingId0}", "\\Device\\#{settingId1}" ] }
- Facter.value(:ipaddress6).should == "2001:0:4137:9e76:2087:77a:53ef:7527"
+ before :each do
+ Facter.fact(:kernel).stubs(:value).returns(:windows)
+ Facter::Util::Registry.stubs(:hklm_read).returns(nic_bindings)
+ given_a_configuration_of(:is_windows => true)
+ end
+
+ it "should do what when VPN is turned on?"
+
+ context "when you have no active network adapter" do
+ it "should return nil if there are no active (or any) network adapters" do
+ Facter::Util::WMI.expects(:execquery).with(Facter::Util::IP::Windows::WMI_IP_INFO_QUERY).returns([])
+
+ Facter.value(:ipaddress6).should == nil
+ end
+ end
+
+ context "when you have one network adapter" do
+ it "should return empty if ipv6 is not on" do
+ network1 = mock('network1', :IPAddress => ["12.123.12.12"])
+ Facter::Util::WMI.expects(:execquery).returns([network1])
+
+ Facter.value(:ipaddress6).should == nil
+ end
+
+ it "should return the ipv6 address properly" do
+ network1 = mock('network1', :IPAddress => ["12.123.12.12", "2011:0:4137:9e76:2087:77a:53ef:7527"])
+ Facter::Util::WMI.expects(:execquery).returns([network1])
+
+ Facter.value(:ipaddress6).should == "2011:0:4137:9e76:2087:77a:53ef:7527"
+ end
+
+ it "should return the first ipv6 address if there is more than one (multi-homing)" do
+ network1 = mock('network1', :IPAddress => ["12.123.12.12", "2013:0:4137:9e76:2087:77a:53ef:7527", "2011:0:4137:9e76:2087:77a:53ef:7527"])
+ Facter::Util::WMI.expects(:execquery).returns([network1])
+
+ Facter.value(:ipaddress6).should == "2013:0:4137:9e76:2087:77a:53ef:7527"
+ end
+
+ it "should return return nil if the ipv6 address is link local" do
+ network1 = mock('network1', :IPAddress => ["12.123.12.12", "fe80::2db2:5b42:4e30:b508"])
+ Facter::Util::WMI.expects(:execquery).returns([network1])
+
+ Facter.value(:ipaddress6).should == nil
+ end
+ end
+
+ context "when you have more than one network adapter" do
+ it "should return empty if ipv6 is not on" do
+ network1 = mock('network1')
+ network1.expects(:SettingID).returns(settingId0)
+ network1.expects(:IPConnectionMetric).returns(10)
+ network1.expects(:IPAddress).returns(["12.123.12.12"])
+ network2 = mock('network2')
+ network2.expects(:SettingID).returns(settingId1)
+ network2.expects(:IPConnectionMetric).returns(10)
+ network2.expects(:IPAddress).returns(["12.123.12.13"])
+ Facter::Util::WMI.expects(:execquery).returns([network1, network2])
+
+ Facter.value(:ipaddress6).should == nil
+ end
+
+ it "should return the ipv6 of the adapter with the lowest IP connection metric (best connection)" do
+ network1 = mock('network1')
+ network1.expects(:IPConnectionMetric).returns(10)
+ network2 = mock('network2')
+ network2.expects(:IPConnectionMetric).returns(5)
+ network2.expects(:IPAddress).returns(["12.123.12.13", "2013:0:4137:9e76:2087:77a:53ef:7527"])
+ Facter::Util::WMI.expects(:execquery).returns([network1, network2])
+
+ Facter.value(:ipaddress6).should == "2013:0:4137:9e76:2087:77a:53ef:7527"
+ end
+
+ it "should return the ipv6 of the adapter with the lowest IP connection metric (best connection) that has ipv6 enabled" do
+ network1 = mock('network1')
+ network1.expects(:IPConnectionMetric).returns(10)
+ network1.expects(:IPAddress).returns(["12.123.12.12", "2011:0:4137:9e76:2087:77a:53ef:7527"])
+ network2 = mock('network2')
+ network2.expects(:IPConnectionMetric).returns(5)
+ network2.expects(:IPAddress).returns(["12.123.12.13"])
+
+ Facter::Util::WMI.expects(:execquery).returns([network2, network1])
+
+ Facter.value(:ipaddress6).should == "2011:0:4137:9e76:2087:77a:53ef:7527"
+ end
+
+ context "when the IP connection metric is the same" do
+ it "should return the ipv6 of the adapter with the lowest binding order" do
+ network1 = mock('network1')
+ network1.expects(:SettingID).returns(settingId0)
+ network1.expects(:IPConnectionMetric).returns(5)
+ network1.expects(:IPAddress).returns(["12.123.12.12", "2011:0:4137:9e76:2087:77a:53ef:7527"])
+ network2 = mock('network2')
+ network2.expects(:SettingID).returns(settingId1)
+ network2.expects(:IPConnectionMetric).returns(5)
+ #network2.expects(:IPAddress).returns(["12.123.12.13", "2013:0:4137:9e76:2087:77a:53ef:7527"])
+ Facter::Util::WMI.expects(:execquery).returns([network1, network2])
+
+ Facter.value(:ipaddress6).should == "2011:0:4137:9e76:2087:77a:53ef:7527"
+ end
+
+ it "should return the ipv6 of the adapter with the lowest binding order even if the adapter is not first" do
+<<<<<<< HEAD
+ network1 = mock('network1')
+ network1.expects(:SettingID).returns(settingId1)
+ network1.expects(:IPConnectionMetric).returns(5)
+ network2 = mock('network2')
+ network2.expects(:SettingID).returns(settingId0)
+ network2.expects(:IPConnectionMetric).returns(5)
+ network2.expects(:IPAddress).returns(["12.123.12.13", "2013:0:4137:9e76:2087:77a:53ef:7527"])
+ Facter::Util::WMI.expects(:execquery).returns([network1, network2])
+
+ Facter.value(:ipaddress6).should == "2013:0:4137:9e76:2087:77a:53ef:7527"
+||||||| parent of 6541f09... maint: remove whitespace from netmask.rb, windows_network.rb, and ipaddress6_spec.rb
+ nics = given_two_valid_windows_nics_with_ipv4_and_ipv6
+ Facter::Util::Registry.stubs(:hklm_read).returns(["\\Device\\#{settingId1}", "\\Device\\#{settingId0}" ])
+
+ Facter::Util::WMI.expects(:execquery).returns(nics.values)
+
+ Facter.value(:ipaddress6).should == ipv6Address1
+=======
+ nics = given_two_valid_windows_nics_with_ipv4_and_ipv6
+ Facter::Util::Registry.stubs(:hklm_read).returns(["\\Device\\#{settingId1}", "\\Device\\#{settingId0}" ])
+ Facter::Util::WMI.expects(:execquery).returns(nics.values)
+
+ Facter.value(:ipaddress6).should == ipv6Address1
+>>>>>>> 6541f09... maint: remove whitespace from netmask.rb, windows_network.rb, and ipaddress6_spec.rb
+ end
+ end
+ end
end
end
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-puppet/facter.git
More information about the Pkg-puppet-devel
mailing list