summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurent <laurent+chef@u-picardie.fr>2012-04-05 03:00:46 +0200
committerBryan McLellan <btm@opscode.com>2012-06-08 08:42:51 -0700
commit7fbb125ee624aa839bb76979c4c49aac6e884346 (patch)
tree83c7ab41f77cda06a5f103a1f14c465e3b1c0419
parent256ba7db6227d70dc3eb97f0feb09e2133320789 (diff)
downloadohai-7fbb125ee624aa839bb76979c4c49aac6e884346.tar.gz
OHAI-355 WIP, new algorithm to set ipaddress (v4 & v6}
TODO: - more tests - handling of point to point interfaces
-rw-r--r--lib/ohai/plugins/network.rb81
-rw-r--r--spec/ohai/plugins/network_spec.rb96
2 files changed, 147 insertions, 30 deletions
diff --git a/lib/ohai/plugins/network.rb b/lib/ohai/plugins/network.rb
index 3087f293..33559d0e 100644
--- a/lib/ohai/plugins/network.rb
+++ b/lib/ohai/plugins/network.rb
@@ -25,31 +25,55 @@ network[:interfaces] = Mash.new unless network[:interfaces]
counters Mash.new unless counters
counters[:network] = Mash.new unless counters[:network]
-ipaddress nil
-ip6address
-macaddress nil
-
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_mac(addresses, match = nil)
- ip = nil; mac = nil; ip6 = nil
- addresses.keys.each do |addr|
- if match.nil?
- ip = addr if addresses[addr]["family"].eql?("inet")
- else
- ip = addr if addresses[addr]["family"].eql?("inet") && network_contains_address(match, addr, addresses[addr])
+def find_ip_and_iface(family = "inet", match = nil)
+ raise "bad family #{family}" unless [ "inet", "inet6" ].include? family
+
+ # going to use that later to sort by scope
+ 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["prefixlen"]}"),
+ :scope => addr_v["scope"],
+ :iface => iface
+ }
end
- ip6 = addr if addresses[addr]["family"].eql?("inet6") && addresses[addr]["scope"].eql?("Global")
- mac = addr if addresses[addr]["family"].eql?("lladdr")
- break if (ip and mac)
end
- Ohai::Log.debug("Found IPv4 address #{ip} with MAC #{mac} #{match.nil? ? '' : 'matching address ' + match}")
- Ohai::Log.debug("Found IPv6 address #{ip6}") if ip6
- [ip, mac, ip6]
+
+ if match.nil?
+ # sort ip addresses by scope, by prefixlen and then by ip address
+ # then return the first ip address
+ r = ipaddresses.sort_by! do |v|
+ [ ( scope_prio.index(v[:scope].downcase) or 999999 ),
+ v[:ipaddress].prefix,
+ ( family == "inet" ? v[:ipaddress].to_u32 : v[:ipaddress].to_u128 )
+ ]
+ end.first
+ else
+ # sort by prefixlen
+ # return the first matching ip address
+ r = ipaddresses.sort do |a,b|
+ a[:ipaddress].prefix <=> b[:ipaddress].prefix
+ end.select do |v|
+ v[:ipaddress].include? IPAddress(match)
+ end.first
+ end
+ [ r[:ipaddress].to_s, r[:iface] ]
+end
+
+def find_mac_from_iface(iface)
+ network["interfaces"][iface]["addresses"].select{|k,v| v["family"]=="lladdr"}.first.first
end
def network_contains_address(address_to_match, network_ip, network_opts)
@@ -64,24 +88,21 @@ 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 for default ip and mac address")
- im = find_ip_and_mac(network["interfaces"][network[:default_interface]]["addresses"], network[:default_gateway])
- ipaddress im.shift
- macaddress im.shift
- ip6address im.shift
+ ( ip, iface ) = find_ip_and_iface("inet", network[:default_gateway])
+ raise "something wrong happened #{network[:default_interface]} != #{iface}" if network[:default_interface] != iface
+ ipaddress ip
else
- network["interfaces"].keys.sort.each do |iface|
- if network["interfaces"][iface]["encapsulation"].eql?("Ethernet")
- Ohai::Log.debug("Picking ip and mac address from first Ethernet interface")
- im = find_ip_and_mac(network["interfaces"][iface]["addresses"])
- ipaddress im.shift
- macaddress im.shift
- return if (ipaddress and macaddress)
- end
- end
+ ( ip, iface ) = find_ip_and_iface("inet")
+ ipaddress ip
end
+macaddress find_mac_from_iface(iface)
+( 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 != iface6
diff --git a/spec/ohai/plugins/network_spec.rb b/spec/ohai/plugins/network_spec.rb
new file mode 100644
index 00000000..9044d96a
--- /dev/null
+++ b/spec/ohai/plugins/network_spec.rb
@@ -0,0 +1,96 @@
+#
+# Author:: Laurent Desarmes <laurent.desarmes@u-picardie.fr>
+# Copyright:: Copyright (c) 2012 Laurent Desarmes
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+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"
+ }
+ },
+ "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"
+ }
+ }
+ }
+
+ checks.each do | check_name, check_data |
+ describe "it checks results from #{check_name}" do
+ before do
+ @ohai = Ohai::System.new
+ @ohai.stub!(:require_plugin).and_return(true)
+ check_data["data"].keys.each do |k|
+ @ohai[k] = check_data["data"][k]
+ end
+ end
+
+ check_data["expected_results"].each do |attribute, value|
+ it "sets #{attribute}" do
+ @ohai._require_plugin("network")
+ @ohai.should have_key(attribute)
+ @ohai[attribute].should == value!
+ end
+ end
+ end
+ end
+end