[Pkg-puppet-devel] [facter] 33/61: (#21518) Use WMI to collect per-interface facts

Stig Sandbeck Mathisen ssm at debian.org
Mon Nov 4 15:01:56 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 672efc59bb02f1799a7782233d7e6055064f595a
Author: Rob Reynolds <rob at puppetlabs.com>
Date:   Wed Jul 24 17:17:18 2013 -0700

    (#21518) Use WMI to collect per-interface facts
    
    Previously, we used netsh.exe to collect the interfaces fact, and the
    derived per-interface facts on Windows. However, netsh.exe is not
    available on plain 2003 servers, and the facts relied on netsh.exe
    outputting en_US text.
    
    This commit refactors the method to use WMI instead, which does not
    have these issues.
---
 lib/facter/util/ip/windows.rb     |   57 ++++++++++++++++++++++++++++++++++---
 spec/unit/util/ip/windows_spec.rb |   48 +++++++++++++++++++++++++++++++
 2 files changed, 101 insertions(+), 4 deletions(-)

diff --git a/lib/facter/util/ip/windows.rb b/lib/facter/util/ip/windows.rb
index 3030d30..1a5fc83 100644
--- a/lib/facter/util/ip/windows.rb
+++ b/lib/facter/util/ip/windows.rb
@@ -17,6 +17,13 @@ class Facter::Util::IP::Windows
   # @api private
   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'
 
+  WINDOWS_LABEL_WMI_MAP = {
+      :ipaddress => 'IPAddress',
+      :ipaddress6 => 'IPAddress',
+      :macaddress => 'MACAddress',
+      :netmask => 'IPSubnet'
+  }
+
   def self.to_s
     'windows'
   end
@@ -30,16 +37,58 @@ class Facter::Util::IP::Windows
     false
   end
 
-  # Uses netsh.exe to obtain a list of interfaces.
+  # Retrieves a list of unique interfaces names.
   #
   # @return [Array]
   #
   # @api private
   def self.interfaces
-    cmd = "#{NETSH} interface %s show interface"
-    output = exec("#{cmd % 'ip'} && #{cmd % 'ipv6'}").to_s
+    network_interfaces = []
+    self.exec_wmi_ip_query do |nic_config|
+      Facter::Util::WMI.execquery("SELECT * FROM Win32_NetworkAdapter WHERE Index = #{nic_config.Index}").each do |nic|
+        network_interfaces << nic.NetConnectionId
+      end
+    end
+
+    network_interfaces.uniq
+  end
+
+  # Get the value of an interface and label. For example, you may want to find
+  # the MTU for eth0.
+  #
+  # @param interface [String] label [String]
+  #
+  # @return [String] or [NilClass]
+  #
+  # @api private
+  def self.value_for_interface_and_label(interface, label)
+    wmi_value = WINDOWS_LABEL_WMI_MAP[label.downcase.to_sym]
+    label_value = nil
+    Facter::Util::WMI.execquery("SELECT Index FROM Win32_NetworkAdapter WHERE NetConnectionID = '#{interface}'").each do |nic|
+      Facter::Util::WMI.execquery("SELECT #{wmi_value} FROM Win32_NetworkAdapterConfiguration WHERE Index = #{nic.Index}").each do |nic_config|
+        case label.downcase.to_sym
+        when :ipaddress
+          nic_config.IPAddress.any? do |addr|
+            label_value = addr if valid_ipv4_address?(addr)
+            label_value
+          end
+        when :ipaddress6
+          nic_config.IPAddress.any? do |addr|
+            label_value = addr if Facter::Util::IP::Windows.valid_ipv6_address?(addr)
+            label_value
+          end
+        when :netmask
+          nic_config.IPSubnet.any? do |addr|
+            label_value = addr if Facter::Util::IP::Windows.valid_ipv4_address?(addr)
+            label_value
+          end
+        when :macaddress
+          label_value = nic_config.MACAddress
+        end
+      end
+    end
 
-    output.scan(/\s* connected\s*(\S.*)/).flatten.uniq
+    label_value
   end
 
   # Executes a wmi query that returns ip information and returns for each item in the results
diff --git a/spec/unit/util/ip/windows_spec.rb b/spec/unit/util/ip/windows_spec.rb
new file mode 100644
index 0000000..da7cbc5
--- /dev/null
+++ b/spec/unit/util/ip/windows_spec.rb
@@ -0,0 +1,48 @@
+# encoding: UTF-8
+
+require 'spec_helper'
+require 'facter/util/ip/windows'
+
+describe Facter::Util::IP::Windows do
+  before :each do
+    Facter.fact(:kernel).stubs(:value).returns('windows')
+  end
+
+  describe ".to_s" do
+    let(:to_s) { described_class.to_s }
+
+    it { to_s.should eq 'windows' }
+  end
+
+  describe ".convert_netmask_from_hex?" do
+    let :convert_netmask_from_hex? do
+      described_class.convert_netmask_from_hex?
+    end
+
+    it { convert_netmask_from_hex?.should be false }
+  end
+
+  describe ".bonding_master" do
+    let(:bonding_master) { described_class.bonding_master('eth0') }
+
+    pending("porting to Windows") do
+      it { bonding_master.should be_nil }
+    end
+  end
+
+  describe ".interfaces" do
+    let(:name)       { 'Local Area Connection' }
+    let(:index)      { 7 }
+    let(:nic_config) { mock('nic_config', :Index => index) }
+    let(:nic)        { mock('nic', :NetConnectionId => name ) }
+
+    it "should return an array of only connected interfaces" do
+      Facter::Util::WMI.expects(:execquery).with(Facter::Util::IP::Windows::WMI_IP_INFO_QUERY).
+        returns([nic_config])
+      Facter::Util::WMI.expects(:execquery).with("SELECT * FROM Win32_NetworkAdapter WHERE Index = #{index}").
+        returns([nic])
+
+      described_class.interfaces.should == [name]
+    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