From ab2c509f38885420c670786be97d9219bebb524b Mon Sep 17 00:00:00 2001 From: Laurent Date: Wed, 16 May 2012 12:20:33 +0200 Subject: fixes, better support for ip6address, new tests --- lib/ohai/plugins/network.rb | 80 ++++++++++------ spec/ohai/plugins/network_spec.rb | 190 +++++++++++++++++++++++++++----------- 2 files changed, 190 insertions(+), 80 deletions(-) diff --git a/lib/ohai/plugins/network.rb b/lib/ohai/plugins/network.rb index 86c13e3a..ea0cf7a8 100644 --- a/lib/ohai/plugins/network.rb +++ b/lib/ohai/plugins/network.rb @@ -28,9 +28,6 @@ counters[:network] = Mash.new unless counters[:network] require_plugin "hostname" require_plugin "#{os}::network" -# ipaddress and macaddress can be set from the #{os}::network plugin -return unless ipaddress.nil? - def find_ip_and_iface(family = "inet", match = nil) raise "bad family #{family}" unless [ "inet", "inet6" ].include? family @@ -38,13 +35,12 @@ def find_ip_and_iface(family = "inet", match = nil) scope_prio = [ "global", "site", "link", "host", "node", nil ] ipaddresses = [] - # trying to write it as readable as possible (iow it's not a kick-ass optimised one-liner) # ipaddresses going to hold #{family} ipaddresses and their scope Mash[network['interfaces']].each do |iface, iface_v| iface_v['addresses'].each do |addr, addr_v| next if addr_v.nil? or not addr_v.has_key? "family" or addr_v['family'] != family ipaddresses << { - :ipaddress => IPAddress("#{addr}/#{addr_v["netmask"]}"), + :ipaddress => addr_v["prefixlen"] ? IPAddress("#{addr}/#{addr_v["prefixlen"]}") : IPAddress("#{addr}/#{addr_v["netmask"]}"), :scope => addr_v["scope"], :iface => iface } @@ -54,12 +50,13 @@ def find_ip_and_iface(family = "inet", match = nil) # return if there isn't any #{family} address ! return [ nil, nil ] if ipaddresses.empty? - if match.nil? + if match.nil? or match ~ /^0\.0\.0\.0/ or match ~ /^::$/ # sort ip addresses by scope, by prefixlen and then by ip address # then return the first ip address + # 128 - prefixlen: longest prefixes first r = ipaddresses.sort_by do |v| [ ( scope_prio.index(v[:scope].downcase) or 999999 ), - v[:ipaddress].prefix, + 128 - v[:ipaddress].prefix.to_i, ( family == "inet" ? v[:ipaddress].to_u32 : v[:ipaddress].to_u128 ) ] end.first @@ -67,12 +64,13 @@ def find_ip_and_iface(family = "inet", match = nil) # sort by prefixlen # return the first matching ip address r = ipaddresses.sort do |a,b| - a[:ipaddress].prefix <=> b[:ipaddress].prefix + b[:ipaddress].prefix.to_i <=> a[:ipaddress].prefix.to_i end r = r.select do |v| v[:ipaddress].include? IPAddress(match) end.first end + returni [ nil, nil ] if r.nil? [ r[:ipaddress].to_s, r[:iface] ] end @@ -90,23 +88,51 @@ def network_contains_address(address_to_match, network_ip, network_opts) end end -# If we have a default interface that has addresses, populate the short-cut attributes -# 0.0.0.0 is not a valid gateway address in this case -iface=nil -if network[:default_interface] and - network[:default_gateway] and - network[:default_gateway] != "0.0.0.0" and - network["interfaces"][network[:default_interface]] and - network["interfaces"][network[:default_interface]]["addresses"] - Ohai::Log.debug("Using default interface '#{network[:default_interface]}' and default gateway '#{network[:default_gateway]}' to set the default ip") - ( ip, iface ) = find_ip_and_iface("inet", network[:default_gateway]) - raise "error: looking for the default ip on '#{network[:default_interface]}' gives an ip '#{ip}' on '#{iface}'" if network[:default_interface] != iface - ipaddress ip -else - ( ip, iface ) = find_ip_and_iface("inet") - ipaddress ip +# ipaddress, ip6address and macaddress can be set by the #{os}::network plugin +# atm it is expected macaddress is set at the same time than ipaddress +# if ipaddress is set and macaddress is nil, that means the interface +# ipaddress is bound to has the NOARP flag + + +results = {} + +[ + { :name => "inet", + :prefix => "default" }, + { :name => "inet6", + :prefix => "default_inet6" } +].each do |f| + r = {} + # If we have a default interface that has addresses, + # populate the short-cut attributes + # 0.0.0.0 is not a valid gateway address in this case + if network["#{f[:prefix]}_interface"] and + network["#{f[:prefix]}_gateway"] and + network["interfaces"][network["#{f[:prefix]}_interface"]] and + network["interfaces"][network["#{f[:prefix]}_interface"]]["addresses"] + Ohai::Log.debug("Using default #{f[:name]} interface '#{network["#{f[:prefix]}_interface"]}' and default #{f[:name]} gateway '#{network["#{f[:prefix]}_gateway"]}' to set the default #{f[:name]} ip") + ( r["ip"], r["iface"] ) = find_ip_and_iface(f[:name], network["#{f[:prefix]}_gateway"]) + else + ( r["ip"], r["iface"] ) = find_ip_and_iface(f[:name]) + end + Ohai::Log.warn("conflict when looking for the default #{f[:name]} ip: network[:#{f[:prefix]}_interface] is set to '#{network["#{f[:prefix]}_interface"]}' ipaddress '#{r["ip"]}' is set on '#{r["iface"]}'") if network["#{f[:prefix]}_interface"] and network["#{f[:prefix]}_interface"] != r["iface"] + r["mac"] = find_mac_from_iface(r["iface"]) unless r["iface"].nil? + unless r["ip"].nil? + # don't overwrite attributes if they've already been set by the "#{os}::network" plugin + if f[:name] == "inet" and ipaddress.nil? + ipaddress r["ip"] + # macaddress is always set from the ipv4 default_route + macaddress r["mac"] + elsif f[:name] == "inet6" and ip6address.nil? + ip6address r["ip"] + end + #macaddress r["mac"] unless macaddress # macaddress set from ipv4 otherwise from ipv6 + + end + results[f[:name]] = r +end + +if results["inet"]["iface"] and results["inet6"]["iface"] and + results["inet"]["iface"] != results["inet6"]["iface"] + Ohai::Log.info("ipaddress and ip6address are set from different interfaces (#{results["inet"]["iface"]} & #{results["inet6"]["iface"]}), macaddress has been set using the ipaddress interface") end -macaddress find_mac_from_iface(iface) unless iface.nil? -( ip6, iface6 ) = find_ip_and_iface("inet6") -ip6address ip6 -Ohai::Log.warn("ipaddress and ip6address are set from different interfaces (#{iface} & #{iface6}), macaddress has been set using the ipaddress interface") if iface and iface6 and iface != iface6 diff --git a/spec/ohai/plugins/network_spec.rb b/spec/ohai/plugins/network_spec.rb index 9044d96a..2354761b 100644 --- a/spec/ohai/plugins/network_spec.rb +++ b/spec/ohai/plugins/network_spec.rb @@ -20,61 +20,138 @@ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper.rb') describe Ohai::System, "Network Plugin" do - checks = { - "linux" => { - "data" => { - # pp Hash[node['network']] from shef to get the network data - # have just removed the arp entries by hand - "network" => {"default_interface"=>"eth0", - "interfaces"=> - {"lo"=> - {"flags"=>["LOOPBACK", "UP"], - "addresses"=> - {"::1"=>{"scope"=>"Node", "prefixlen"=>"128", "family"=>"inet6"}, - "127.0.0.1"=> - {"scope"=>"Node", - "netmask"=>"255.0.0.0", - "prefixlen"=>"8", - "family"=>"inet"}}, - "mtu"=>"16436", - "encapsulation"=>"Loopback"}, - "eth0"=> - {"flags"=>["BROADCAST", "MULTICAST", "UP"], - "number"=>"0", - "addresses"=> - {"fe80::216:3eff:fe2f:3679"=> - {"scope"=>"Link", "prefixlen"=>"64", "family"=>"inet6"}, - "00:16:3E:2F:36:79"=>{"family"=>"lladdr"}, - "192.168.66.33"=> - {"scope"=>"Global", - "netmask"=>"255.255.255.0", - "broadcast"=>"192.168.66.255", - "prefixlen"=>"24", - "family"=>"inet"}}, - "routes"=>{"192.168.66.0/24"=>{"scope"=>"Link", "src"=>"192.168.66.33"}}, - "mtu"=>"1500", - "type"=>"eth", - "encapsulation"=>"Ethernet"}}, - "default_gateway"=>"192.168.66.15"} - }, - "expected_results" => { - "ipaddress" => "192.168.66.33", - "macaddress" => "00:16:3E:2F:36:79" - } + checks = {} + basic_linux_network_data = { + # pp Hash[node['network']] from shef to get the network data + # have just removed the neighbour and route entries by hand + "default_interface"=>"eth0", + "interfaces"=> + {"lo"=> + {"flags"=>["LOOPBACK", "UP"], + "addresses"=> + {"::1"=>{"scope"=>"Node", "prefixlen"=>"128", "family"=>"inet6"}, + "127.0.0.1"=> + {"scope"=>"Node", + "netmask"=>"255.0.0.0", + "prefixlen"=>"8", + "family"=>"inet"}}, + "mtu"=>"16436", + "encapsulation"=>"Loopback"}, + "eth0"=> + {"flags"=>["BROADCAST", "MULTICAST", "UP"], + "number"=>"0", + "addresses"=> + { + "fe80::216:3eff:fe2f:3679"=> {"scope"=>"Link", "prefixlen"=>"64", "family"=>"inet6"}, + "00:16:3E:2F:36:79"=>{"family"=>"lladdr"}, + "192.168.66.33"=> {"scope"=>"Global", + "netmask"=>"255.255.255.0", + "broadcast"=>"192.168.66.255", + "prefixlen"=>"24", + "family"=>"inet"}, + "3ffe:1111:2222::1"=> { + "prefixlen"=> "48", + "family"=> "inet6", + "scope"=> "Global" + }}, + "mtu"=>"1500", + "type"=>"eth", + "encapsulation"=>"Ethernet"}}, + "default_gateway"=>"192.168.66.15", + "default_inet6_gateway" => "3ffe:1111:2222::" + } + checks["1 linux"] = { + "data" => { + "network" => basic_linux_network_data + }, + "expected_results" => { + "ipaddress" => "192.168.66.33", + "macaddress" => "00:16:3E:2F:36:79", + "ip6address" => "3ffe:1111:2222::1" + } + } + # checks["linux with ipv6"] = { + # } + # checks["linux with default ipv4 and ipv6 gateway on different interfaces"] = { + # } + # checks["linux with conflict between default gateway and default address"] = { + # } + checks["2 linux with {ip,mac}address set from the linux plugin"] = { + "data" => { + "network" => basic_linux_network_data, + "ipaddress" => "10.11.12.13", + "macaddress" => "00:AA:BB:CC:DD:EE", }, - "linux with {ip,mac}address set from the linux plugin" => { - "data" => { - "ipaddress" => "192.168.66.33", - "macaddress" => "00:16:3E:2F:36:79" - }, - "expected_results" => { - "ipaddress" => "192.168.66.33", - "macaddress" => "00:16:3E:2F:36:79" - } + "expected_results" => { + "ipaddress" => "10.11.12.13", + "macaddress" => "00:AA:BB:CC:DD:EE", + "ip6address" => "3ffe:1111:2222::1" + } + } + checks["3 linux with {ip,mac}address set from the linux plugin, ip6address detected"] = { + "data" => { + "network" => basic_linux_network_data, + "ipaddress" => "10.11.12.13", + "macaddress" => "00:AA:BB:CC:DD:EE", + }, + "expected_results" => { + "ipaddress" => "10.11.12.13", + "macaddress" => "00:AA:BB:CC:DD:EE", + "ip6address" => "3ffe:1111:2222::1" + } + } + checks["4 linux with ip6address set from the linux plugin, {ip,mac}address detected"] = { + "data" => { + "network" => basic_linux_network_data, + "ip6address" => "3ffe:8888:9999::1" + }, + "expected_results" => { + "ipaddress" => "192.168.66.33", + "macaddress" => "00:16:3E:2F:36:79", + "ip6address" => "3ffe:8888:9999::1" + } + } + checks["5 linux with {mac,ip6}address set from the linux plugin, {ip,mac}address detected"] = { + "data" => { + "network" => basic_linux_network_data, + "ip6address" => "3ffe:8888:9999::1", + "macaddress" => "00:11:22:33:44:55" + }, + "expected_results" => { + "ipaddress" => "192.168.66.33", + "macaddress" => "00:16:3E:2F:36:79", + "ip6address" => "3ffe:8888:9999::1" + } + } + checks["6 linux with {ip,mac,ip6}address set from the linux plugin"] = { + "data" => { + "network" => basic_linux_network_data, + "ipaddress" => "10.11.12.13", + "macaddress" => "00:AA:BB:CC:DD:EE", + "ip6address" => "3ffe:8888:9999::1" + }, + "expected_results" => { + "network" => basic_linux_network_data, + "ipaddress" => "10.11.12.13", + "macaddress" => "00:AA:BB:CC:DD:EE", + "ip6address" => "3ffe:8888:9999::1" + } + } + checks["7 linux with {ip,ip6}address set from the linux plugin"] = { + "data" => { + "network" => basic_linux_network_data, + "ipaddress" => "10.11.12.13", + "ip6address" => "3ffe:8888:9999::1" + }, + "expected_results" => { + "ipaddress" => "10.11.12.13", + "macaddress" => nil, + "ip6address" => "3ffe:8888:9999::1" } } - checks.each do | check_name, check_data | + checks.keys.sort.each do |check_name| + check_data = checks[check_name] describe "it checks results from #{check_name}" do before do @ohai = Ohai::System.new @@ -84,11 +161,18 @@ describe Ohai::System, "Network Plugin" do end end - check_data["expected_results"].each do |attribute, value| + it "doesn't fail" do + Ohai::Log.should_not_receive(:debug).with(/Plugin network threw exception/) + @ohai._require_plugin("network") + end + + check_data["expected_results"].keys.sort.each do |attribute| + value = check_data["expected_results"][attribute] it "sets #{attribute}" do @ohai._require_plugin("network") + puts "A - #{@ohai["ipaddress"].inspect} - #{@ohai["macaddress"].inspect} - #{@ohai["ip6address"].inspect}" @ohai.should have_key(attribute) - @ohai[attribute].should == value! + @ohai[attribute].should == value end end end -- cgit v1.2.1