summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Smith <tsmith@chef.io>2016-01-08 11:42:47 -0800
committerTim Smith <tsmith@chef.io>2016-01-08 11:42:47 -0800
commitb9ee1e1850e3b79d8a81dbe74cdfe409f4728e9e (patch)
tree8d14704db3acca457cb1ce8a1693dbc70cbe7214
parentd5ff00ea476aedfc4de92bc14ae00152e7c927de (diff)
parent920054afc670cf8f7cb09cf368c043136ca1fe98 (diff)
downloadohai-b9ee1e1850e3b79d8a81dbe74cdfe409f4728e9e.tar.gz
Merge pull request #695 from btm/btm/ipv6_mac
Fix detection of mac address on IPv6 only systems
-rw-r--r--lib/ohai/mixin/network_constants.rb4
-rw-r--r--lib/ohai/plugins/linux/network.rb154
-rw-r--r--lib/ohai/plugins/network.rb91
-rw-r--r--spec/unit/plugins/linux/network_spec.rb39
-rw-r--r--spec/unit/plugins/network_spec.rb147
5 files changed, 291 insertions, 144 deletions
diff --git a/lib/ohai/mixin/network_constants.rb b/lib/ohai/mixin/network_constants.rb
index 2b47a565..738ee546 100644
--- a/lib/ohai/mixin/network_constants.rb
+++ b/lib/ohai/mixin/network_constants.rb
@@ -1,6 +1,6 @@
#
-# Author:: Serdar Sutay (<serdar@opscode.com>)
-# Copyright:: Copyright (c) 2014 Opscode, Inc.
+# Author:: Serdar Sutay (<serdar@chef.io>)
+# Copyright:: Copyright (c) 2014-2015 Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/lib/ohai/plugins/linux/network.rb b/lib/ohai/plugins/linux/network.rb
index 689001dc..0bc90ad1 100644
--- a/lib/ohai/plugins/linux/network.rb
+++ b/lib/ohai/plugins/linux/network.rb
@@ -138,6 +138,7 @@ Ohai.plugin(:Network) do
end.compact.flatten
end
+ # determine layer 1 details for the interface using ethtool
def ethernet_layer_one(iface)
return iface unless ethtool_binary = find_ethtool_binary
keys = %w[ Speed Duplex Port Transceiver Auto-negotiation MDI-X ]
@@ -161,6 +162,7 @@ Ohai.plugin(:Network) do
iface
end
+ # determine link stats, vlans, queue length, and state for an interface using ip
def link_statistics(iface, net_counters)
so = shell_out("ip -d -s link")
tmp_int = nil
@@ -251,7 +253,6 @@ Ohai.plugin(:Network) do
end
end
-
def parse_ip_addr_link_line(cint, iface, line)
if line =~ /link\/(\w+) ([\da-f\:]+) /
iface[cint][:encapsulation] = linux_encaps_lookup($1)
@@ -293,7 +294,7 @@ Ohai.plugin(:Network) do
iface[cint][:addresses][tmp_addr][:scope] = ($1.eql?("host") ? "Node" : $1.capitalize)
end
- # If we found we were an an alias interface, restore cint to its original value
+ # If we found we were an alias interface, restore cint to its original value
cint = original_int unless original_int.nil?
end
cint
@@ -307,6 +308,71 @@ Ohai.plugin(:Network) do
end
end
+ # returns the macaddress for interface from a hash of interfaces (iface elsewhere in this file)
+ def get_mac_for_interface(interfaces, interface)
+ interfaces[interface][:addresses].select{|k,v| v["family"]=="lladdr"}.first.first unless interfaces[interface][:flags].include? "NOARP"
+ end
+
+ # returns the default route with the lowest metric (unspecified metric is 0)
+ def choose_default_route(routes)
+ default_route = routes.select do |r|
+ r[:destination] == "default"
+ end.sort do |x,y|
+ (x[:metric].nil? ? 0 : x[:metric].to_i) <=> (y[:metric].nil? ? 0 : y[:metric].to_i)
+ end.first
+ end
+
+ # ipv4/ipv6 routes are different enough that having a single algorithm to select the favored route for both creates unnecessary complexity
+ # this method attempts to deduce the route that is most important to the user, which is later used to deduce the favored values for {ip,mac,ip6}address
+ # we only consider routes that are default routes, or those routes that get us to the gateway for a default route
+ def favored_default_route(routes, iface, default_route, family)
+ routes.select do |r|
+ if family[:name] == "inet"
+ # selecting routes for ipv4
+ # using the source field when it's specified :
+ # 1) in the default route
+ # 2) in the route entry used to reach the default gateway
+ r[:src] and # it has a src field
+ iface[r[:dev]] and # the iface exists
+ iface[r[:dev]][:addresses].has_key? r[:src] and # the src ip is set on the node
+ iface[r[:dev]][:addresses][r[:src]][:scope].downcase != "link" and # this isn't a link level addresse
+ ( r[:destination] == "default" or
+ ( default_route[:via] and # the default route has a gateway
+ IPAddress(r[:destination]).include? IPAddress(default_route[:via]) # the route matches the gateway
+ )
+ )
+ elsif family[:name] == "inet6"
+ # selecting routes for ipv6
+ iface[r[:dev]] and # the iface exists
+ iface[r[:dev]][:state] == "up" and # the iface is up
+ ( r[:destination] == "default" or
+ ( default_route[:via] and # the default route has a gateway
+ IPAddress(r[:destination]).include? IPAddress(default_route[:via]) # the route matches the gateway
+ )
+ )
+ end
+ end.sort_by do |r|
+ # sorting the selected routes:
+ # - getting default routes first
+ # - then sort by metric
+ # - then by prefixlen
+ [
+ r[:destination] == "default" ? 0 : 1,
+ r[:metric].nil? ? 0 : r[:metric].to_i,
+ # for some reason IPAddress doesn't accept "::/0", it doesn't like prefix==0
+ # just a quick workaround: use 0 if IPAddress fails
+ begin
+ IPAddress( r[:destination] == "default" ? family[:default_route] : r[:destination] ).prefix
+ rescue
+ 0
+ end
+ ]
+ end.first
+ end
+
+ # Both the network plugin and this plugin (linux/network) are run on linux. This plugin runs first.
+ # If the 'ip' binary is available, this plugin may set {ip,mac,ip6}address. The network plugin should not overwrite these.
+ # The older code section below that relies on the deprecated net-tools, e.g. netstat and ifconfig, provides less functionality.
collect_data(:linux) do
require 'ipaddr'
@@ -353,18 +419,15 @@ Ohai.plugin(:Network) do
routes = parse_routes(family, iface)
- # using a temporary var to hold the default route
- # in case there are more than 1 default route, sort it by its metric
- # and return the first one
- # (metric value when unspecified is 0)
- default_route = routes.select do |r|
- r[:destination] == "default"
- end.sort do |x,y|
- (x[:metric].nil? ? 0 : x[:metric].to_i) <=> (y[:metric].nil? ? 0 : y[:metric].to_i)
- end.first
+ default_route = choose_default_route(routes)
if default_route.nil? or default_route.empty?
- Ohai::Log.debug("Unable to determine default #{family[:name]} interface")
+ attribute_name == if family[:name] == "inet"
+ "default_interface"
+ else
+ "default_#{family[:name]}_interface"
+ end
+ Ohai::Log.debug("Unable to determine '#{attribute_name}' as no default routes were found for that interface family")
else
network["#{default_prefix}_interface"] = default_route[:dev]
Ohai::Log.debug("#{default_prefix}_interface set to #{default_route[:dev]}")
@@ -373,52 +436,35 @@ Ohai.plugin(:Network) do
network["#{default_prefix}_gateway"] = default_route[:via] ? default_route[:via] : family[:default_route].chomp("/0")
Ohai::Log.debug("#{default_prefix}_gateway set to #{network["#{default_prefix}_gateway"]}")
+ # deduce the default route the user most likely cares about to pick {ip,mac,ip6}address below
+ favored_route = favored_default_route(routes, iface, default_route, family)
+
+ # FIXME: This entire block should go away, and the network plugin should be the sole source of {ip,ip6,mac}address
+
# since we're at it, let's populate {ip,mac,ip6}address with the best values
- # using the source field when it's specified :
- # 1) in the default route
- # 2) in the route entry used to reach the default gateway
- route = routes.select do |r|
- # selecting routes
- r[:src] and # it has a src field
- iface[r[:dev]] and # the iface exists
- iface[r[:dev]][:addresses].has_key? r[:src] and # the src ip is set on the node
- iface[r[:dev]][:addresses][r[:src]][:scope].downcase != "link" and # this isn't a link level addresse
- ( r[:destination] == "default" or
- ( default_route[:via] and # the default route has a gateway
- IPAddress(r[:destination]).include? IPAddress(default_route[:via]) # the route matches the gateway
- )
- )
- end.sort_by do |r|
- # sorting the selected routes:
- # - getting default routes first
- # - then sort by metric
- # - then by prefixlen
- [
- r[:destination] == "default" ? 0 : 1,
- r[:metric].nil? ? 0 : r[:metric].to_i,
- # for some reason IPAddress doesn't accept "::/0", it doesn't like prefix==0
- # just a quick workaround: use 0 if IPAddress fails
- begin
- IPAddress( r[:destination] == "default" ? family[:default_route] : r[:destination] ).prefix
- rescue
- 0
- end
- ]
- end.first
-
- unless route.nil? or route.empty?
+ # if we don't set these, the network plugin may set them afterwards
+ if favored_route && !favored_route.empty?
if family[:name] == "inet"
- ipaddress route[:src]
- macaddress iface[route[:dev]][:addresses].select{|k,v| v["family"]=="lladdr"}.first.first unless iface[route[:dev]][:flags].include? "NOARP"
- else
- ip6address route[:src]
+ ipaddress favored_route[:src]
+ m = get_mac_for_interface(iface, favored_route[:dev])
+ Ohai::Log.debug("Overwriting macaddress #{macaddress} with #{m} from interface #{favored_route[:dev]}") if macaddress
+ macaddress m
+ elsif family[:name] == "inet6"
+ # this rarely does anything since we rarely have src for ipv6, so this usually falls back on the network plugin
+ ip6address favored_route[:src]
+ if macaddress
+ Ohai::Log.debug("Not setting macaddress from ipv6 interface #{favored_route[:dev]} because macaddress is already set")
+ else
+ macaddress get_mac_for_interface(iface, favored_route[:dev])
+ end
end
+ else
+ Ohai::Log.debug("the linux/network plugin was unable to deduce the favored default route for family '#{family[:name]}' despite finding a default route, and is not setting ipaddress/ip6address/macaddress. the network plugin may provide fallbacks.")
+ Ohai::Log.debug("this potential default route was excluded: #{default_route}")
end
end
- end
-
- else
-
+ end # end families.each
+ else # ip binary not available, falling back to net-tools, e.g. route, ifconfig
begin
so = shell_out("route -n")
route_result = so.stdout.split($/).grep( /^0.0.0.0/ )[0].split( /[ \t]+/ )
@@ -502,7 +548,7 @@ Ohai.plugin(:Network) do
iface[$4][:arp][$1] = $2.downcase
end
end
- end
+ end # end "ip else net-tools" block
iface = ethernet_layer_one(iface)
counters[:network][:interfaces] = net_counters
diff --git a/lib/ohai/plugins/network.rb b/lib/ohai/plugins/network.rb
index bc95a650..ac55f1b0 100644
--- a/lib/ohai/plugins/network.rb
+++ b/lib/ohai/plugins/network.rb
@@ -1,14 +1,14 @@
#
-# Author:: Adam Jacob (<adam@opscode.com>)
-# Copyright:: Copyright (c) 2008 Opscode, Inc.
+# Author:: Adam Jacob (<adam@chef.io>)
+# Copyright:: Copyright (c) 2008-2015 Chef Software, Inc.
# 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.
@@ -26,19 +26,21 @@ Ohai.plugin(:NetworkAddresses) do
depends "network/interfaces"
+ # from interface data create array of hashes with ipaddress, scope, and iface
+ # sorted by scope, prefixlen and then ipaddress where longest prefixes first
def sorted_ips(family = "inet")
- raise "bad family #{family}" unless [ "inet", "inet6" ].include? family
+ fail "bad family #{family}" unless %w(inet inet6).include? family
- # going to use that later to sort by scope
+ # priority of ipv6 link scopes to sort by later
scope_prio = [ "global", "site", "link", "host", "node", nil ]
+ # grab ipaddress, scope, and iface for sorting later
ipaddresses = []
- # ipaddresses going to hold #{family} ipaddresses and their scope
Mash[network['interfaces']].each do |iface, iface_v|
- next if iface_v.nil? or not iface_v.has_key? 'addresses'
+ next if iface_v.nil? || !iface_v.has_key?('addresses')
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 << {
+ ipaddresses << {
:ipaddress => addr_v["prefixlen"] ? IPAddress("#{addr}/#{addr_v["prefixlen"]}") : IPAddress("#{addr}/#{addr_v["netmask"]}"),
:scope => addr_v["scope"].nil? ? nil : addr_v["scope"].downcase,
:iface => iface
@@ -49,35 +51,35 @@ Ohai.plugin(:NetworkAddresses) do
# sort ip addresses by scope, by prefixlen and then by ip address
# 128 - prefixlen: longest prefixes first
ipaddresses.sort_by do |v|
- [ ( scope_prio.index(v[:scope]) or 999999 ),
+ [ ( scope_prio.index(v[:scope]) || 999999 ),
128 - v[:ipaddress].prefix.to_i,
( family == "inet" ? v[:ipaddress].to_u32 : v[:ipaddress].to_u128 )
]
end
end
+ # finds ip address / interface for interface with default route based on
+ # passed in family. returns [ipaddress, interface] uses 1st ip if no default
+ # route is found
def find_ip(family = "inet")
- ips=sorted_ips(family)
+ ips = sorted_ips(family)
- # return if there isn't any #{family} address !
+ # return if there aren't any #{family} addresses!
return [ nil, nil ] if ips.empty?
# shortcuts to access default #{family} interface and gateway
int_attr = Ohai::Mixin::NetworkConstants::FAMILIES[family] +"_interface"
gw_attr = Ohai::Mixin::NetworkConstants::FAMILIES[family] + "_gateway"
- # If we have a default interface that has addresses,
- # populate the short-cut attributes ipaddress, ip6address and macaddress
if network[int_attr]
-
# working with the address(es) of the default network interface
gw_if_ips = ips.select do |v|
v[:iface] == network[int_attr]
end
if gw_if_ips.empty?
Ohai::Log.warn("[#{family}] no ip address on #{network[int_attr]}")
- elsif network[gw_attr] and
- network["interfaces"][network[int_attr]] and
+ elsif network[gw_attr] &&
+ network["interfaces"][network[int_attr]] &&
network["interfaces"][network[int_attr]]["addresses"]
if [ "0.0.0.0", "::", /^fe80:/ ].any? { |pat| pat === network[gw_attr] }
# link level default route
@@ -109,15 +111,16 @@ Ohai.plugin(:NetworkAddresses) do
[ r[:ipaddress].to_s, r[:iface] ]
end
+ # select mac address of first interface with family of lladdr
def find_mac_from_iface(iface)
- r = network["interfaces"][iface]["addresses"].select{|k,v| v["family"]=="lladdr"}
- r.nil? or r.first.nil? ? nil : r.first.first
+ r = network["interfaces"][iface]["addresses"].select{|k,v| v["family"] == "lladdr"}
+ r.nil? || r.first.nil? ? nil : r.first.first
end
+ # address_to_match: String
+ # ipaddress: IPAddress
+ # iface: String
def network_contains_address(address_to_match, ipaddress, iface)
- # address_to_match: String
- # ipaddress: IPAddress
- # iface: String
if peer = network["interfaces"][iface]["addresses"][ipaddress.to_s][:peer]
IPAddress(peer) == IPAddress(address_to_match)
else
@@ -125,11 +128,10 @@ Ohai.plugin(:NetworkAddresses) do
end
end
- # 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
-
+ # ipaddress, ip6address and macaddress are set for each interface by the
+ # #{os}::network plugin. atm it is expected macaddress is set at the same
+ # time as ipaddress. if ipaddress is set and macaddress is nil, that means
+ # the interface ipaddress is bound to has the NOARP flag
collect_data do
results = {}
@@ -138,39 +140,44 @@ Ohai.plugin(:NetworkAddresses) do
counters Mash.new unless counters
counters[:network] = Mash.new unless counters[:network]
- # inet family is treated before inet6
+ # inet family is processed before inet6 to give ipv4 precedence
Ohai::Mixin::NetworkConstants::FAMILIES.keys.sort.each do |family|
r = {}
- ( r["ip"], r["iface"] ) = find_ip(family)
+ # find the ip/interface with the default route for this family
+ (r["ip"], r["iface"]) = find_ip(family)
r["mac"] = find_mac_from_iface(r["iface"]) unless r["iface"].nil?
# don't overwrite attributes if they've already been set by the "#{os}::network" plugin
- if family == "inet" and ipaddress.nil?
+ if (family == "inet") && ipaddress.nil?
if r["ip"].nil?
Ohai::Log.warn("unable to detect ipaddress")
- # i don't issue this warning if r["ip"] exists and r["mac"].nil?
- # as it could be a valid setup with a NOARP default_interface
- Ohai::Log.warn("unable to detect macaddress")
else
ipaddress r["ip"]
- macaddress r["mac"]
end
- elsif family == "inet6" and ip6address.nil?
+ elsif (family == "inet6") && ip6address.nil?
if r["ip"].nil?
Ohai::Log.debug("unable to detect ip6address")
else
ip6address r["ip"]
- if r["mac"] and macaddress.nil? and ipaddress.nil?
- Ohai::Log.debug("macaddress set to #{r["mac"]} from the ipv6 setup")
- macaddress r["mac"]
- end
end
end
+
+ # set the macaddress [only if we haven't already]. this allows the #{os}::network plugin to set macaddress
+ # otherwise we set macaddress on a first-found basis (and we started with ipv4)
+ if macaddress.nil?
+ if r["mac"]
+ Ohai::Log.debug("setting macaddress to '#{r["mac"]}' from interface '#{r["iface"]}' for family '#{family}'")
+ macaddress r["mac"]
+ else
+ Ohai::Log.debug("unable to detect macaddress for family '#{family}'")
+ end
+ end
+
results[family] = r
end
- if results["inet"]["iface"] and results["inet6"]["iface"] and
- results["inet"]["iface"] != results["inet6"]["iface"]
- Ohai::Log.debug("ipaddress and ip6address are set from different interfaces (#{results["inet"]["iface"]} & #{results["inet6"]["iface"]}), macaddress has been set using the ipaddress interface")
+ if results["inet"]["iface"] && results["inet6"]["iface"] &&
+ (results["inet"]["iface"] != results["inet6"]["iface"])
+ Ohai::Log.debug("ipaddress and ip6address are set from different interfaces (#{results["inet"]["iface"]} & #{results["inet6"]["iface"]})")
end
end
end
diff --git a/spec/unit/plugins/linux/network_spec.rb b/spec/unit/plugins/linux/network_spec.rb
index de5a89ce..ab9387ef 100644
--- a/spec/unit/plugins/linux/network_spec.rb
+++ b/spec/unit/plugins/linux/network_spec.rb
@@ -1,7 +1,7 @@
#
# Author:: Caleb Tennis <caleb.tennis@gmail.com>
# Author:: Chris Read <chris.read@gmail.com>
-# Copyright:: Copyright (c) 2011 Opscode, Inc.
+# Copyright:: Copyright (c) 2011-2015 Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -663,7 +663,14 @@ Destination Gateway Genmask Flags Metric Ref Use Iface
expect(plugin['network']['interfaces']['eth0.11']['routes']).to include Mash.new( :destination => "default", :via => "1111:2222:3333:4444::1", :metric => "1024", :family => "inet6")
end
- describe "when there isn't a source field in route entries " do
+ describe "when there isn't a source field in route entries and no ipv6 default routes" do
+ let(:linux_ip_route_inet6) {
+'fe80::/64 dev eth0 proto kernel metric 256
+fe80::/64 dev eth0.11 proto kernel metric 256
+1111:2222:3333:4444::/64 dev eth0.11 metric 1024 expires 86023sec
+'
+ }
+
before(:each) do
plugin.run
end
@@ -798,7 +805,7 @@ default via 1111:2222:3333:4444::ffff dev eth0.11 metric 1023 src 1111:2222:333
end
end
- describe "when there's a source field in a local route entry " do
+ describe "when there's a source field in a local route entry but it isnt in the default route" do
let(:linux_ip_route) {
'10.116.201.0/24 dev eth0 proto kernel src 10.116.201.76
192.168.5.0/24 dev eth0 proto kernel src 192.168.5.1
@@ -828,18 +835,34 @@ default via 1111:2222:3333:4444::1 dev eth0.11 metric 1024
expect(plugin['ipaddress']).to eq("10.116.201.76")
end
+ # without a source address on the default route we cannot pick the an ipv6 address from the interface
+ # In the future an RFC6724 compliant process should choose ip6address in the network plugin
+ it "does not set ip6address" do
+ plugin.run
+ expect(plugin['ip6address']).to eq(nil)
+ end
+
+ context "with only ipv6 routes" do
+ let(:linux_ip_route) { '' }
+
+ it "sets macaddress to the mac address of the ip6 default interface" do
+ expect(plugin['macaddress']).to eq("00:AA:BB:CC:DD:EE")
+ end
+ end
+
describe "when about to set macaddress" do
it "sets macaddress" do
plugin.run
expect(plugin['macaddress']).to eq("12:31:3D:02:BE:A2")
end
- describe "when then interface has the NOARP flag" do
+ context "when then ipv4 interface has the NOARP flag and no ipv6 routes exist" do
let(:linux_ip_route) {
'10.118.19.1 dev tun0 proto kernel src 10.118.19.39
default via 172.16.19.1 dev tun0
'
}
+ let(:linux_ip_route_inet6) { '' }
it "completes the run" do
expect(Ohai::Log).not_to receive(:debug).with(/Plugin linux::network threw exception/)
@@ -853,11 +876,6 @@ default via 172.16.19.1 dev tun0
end
end
end
-
- it "sets ip6address" do
- plugin.run
- expect(plugin['ip6address']).to eq("1111:2222:3333:4444::3")
- end
end
describe "with a link level default route" do
@@ -950,6 +968,9 @@ fe80::/64 dev eth0.11 proto kernel metric 256
inet6 2001:44b8:4160:8f00:a00:27ff:fe13:eacd/64 scope global dynamic
valid_lft 6128sec preferred_lft 2526sec
'}
+ # We don't have the corresponding ipv6 data for these tests
+ let(:linux_ip_route_inet6) { '' }
+ let(:linux_ip_inet6_neighbor_show) { '' }
before(:each) do
allow(plugin).to receive(:is_openvz?).and_return true
diff --git a/spec/unit/plugins/network_spec.rb b/spec/unit/plugins/network_spec.rb
index 03ea6b81..5b426334 100644
--- a/spec/unit/plugins/network_spec.rb
+++ b/spec/unit/plugins/network_spec.rb
@@ -26,8 +26,8 @@ def it_doesnt_fail
end
end
+# basic sanity check that is called in all describes below
def it_populates_ipaddress_attributes
-
source = caller[0]
it "populates ipaddress, macaddress and ip6address" do
@@ -43,11 +43,11 @@ def it_populates_ipaddress_attributes
raise
end
end
-
end
describe Ohai::System, "Network Plugin" do
+ # output of network plugins on particular platforms to mock plugin runs
basic_data = {
"freebsd" => {
"network" => {
@@ -57,7 +57,9 @@ describe Ohai::System, "Network Plugin" do
"number" => "0",
"flags" => ["UP", "BROADCAST", "RUNNING", "SIMPLEX", "MULTICAST"],
"addresses" => {
- "00:00:24:c9:5e:b8" => {"family" => "lladdr"},
+ "00:00:24:c9:5e:b8" => {
+ "family" => "lladdr"
+ },
"fe80::200:24ff:fec9:5eb8" => {
"family" => "inet6",
"zoneid" => "vr0",
@@ -80,7 +82,9 @@ describe Ohai::System, "Network Plugin" do
"number" => "1",
"flags" => ["UP", "BROADCAST", "RUNNING", "PROMISC", "SIMPLEX", "MULTICAST"],
"addresses" => {
- "00:00:24:c9:5e:b9" => {"family" => "lladdr"},
+ "00:00:24:c9:5e:b9" => {
+ "family" => "lladdr"
+ },
"fe80::200:24ff:fec9:5eb9" => {
"family" => "inet6",
"zoneid" => "vr1",
@@ -94,7 +98,9 @@ describe Ohai::System, "Network Plugin" do
"number" => "2",
"flags" => ["UP", "BROADCAST", "RUNNING", "PROMISC", "SIMPLEX", "MULTICAST"],
"addresses" => {
- "00:00:24:c9:5e:ba" => {"family" => "lladdr"},
+ "00:00:24:c9:5e:ba" => {
+ "family" => "lladdr"
+ },
"fe80::200:24ff:fec9:5eba" => {
"family" => "inet6",
"zoneid" => "vr2",
@@ -108,7 +114,9 @@ describe Ohai::System, "Network Plugin" do
"number" => "3",
"flags" => ["UP", "BROADCAST", "RUNNING", "PROMISC", "SIMPLEX", "MULTICAST"],
"addresses" => {
- "00:00:24:c9:5e:bb" => {"family" => "lladdr"},
+ "00:00:24:c9:5e:bb" => {
+ "family" => "lladdr"
+ },
"fe80::200:24ff:fec9:5ebb" => {
"family" => "inet6",
"zoneid" => "vr3",
@@ -128,8 +136,14 @@ describe Ohai::System, "Network Plugin" do
"number" => "0",
"flags" => ["UP", "LOOPBACK", "RUNNING", "MULTICAST"],
"addresses" => {
- "127.0.0.1" => {"family" => "inet", "netmask" => "255.0.0.0"},
- "::1" => {"family" => "inet6", "prefixlen" => "128"},
+ "127.0.0.1" => {
+ "family" => "inet",
+ "netmask" => "255.0.0.0"
+ },
+ "::1" => {
+ "family" => "inet6",
+ "prefixlen" => "128"
+ },
"fe80::1" => {
"family" => "inet6",
"zoneid" => "lo0",
@@ -143,13 +157,18 @@ describe Ohai::System, "Network Plugin" do
"number" => "0",
"flags" => ["LEARNING", "DISCOVER", "AUTOEDGE", "AUTOPTP"],
"addresses" => {
- "02:20:6f:d2:c4:00" => {"family"=>"lladdr"},
+ "02:20:6f:d2:c4:00" => {
+ "family"=>"lladdr"
+ },
"192.168.2.1" => {
"family" => "inet",
"netmask" => "255.255.255.0",
"broadcast" => "192.168.2.255"
},
- "2001:470:d:cb4::1" => {"family" => "inet6", "prefixlen" => "64"},
+ "2001:470:d:cb4::1" => {
+ "family" => "inet6",
+ "prefixlen" => "64"
+ },
"fe80::cafe:babe:dead:beef" => {
"family" => "inet6",
"zoneid" => "bridge0",
@@ -183,12 +202,14 @@ describe Ohai::System, "Network Plugin" do
}
},
"default_gateway" => "76.91.0.1",
- "default_interface" => "vr0"
+ "default_interface" => "vr0",
+ "default_inet6_gateway" => "2001:470:d:cb4::2",
+ "default_inet6_interface" => "bridge0"
}
},
"linux" => {
"network" => {
- # pp Hash[node['network']] from shef to get the network data
+ # pp Hash[node['network']] from chef-shell to get the network data
# have just removed the neighbour and route entries by hand
"interfaces" => {
"lo" => {
@@ -207,7 +228,8 @@ describe Ohai::System, "Network Plugin" do
}
},
"mtu" => "16436",
- "encapsulation" => "Loopback"
+ "encapsulation" => "Loopback",
+ "state" => "unknown"
},
"eth0" => {
"flags" => ["BROADCAST", "MULTICAST", "UP"],
@@ -218,7 +240,9 @@ describe Ohai::System, "Network Plugin" do
"prefixlen" => "64",
"family" => "inet6"
},
- "00:16:3E:2F:36:79" => {"family" => "lladdr"},
+ "00:16:3E:2F:36:79" => {
+ "family" => "lladdr"
+ },
"192.168.66.33" => {
"scope" => "Global",
"netmask" => "255.255.255.0",
@@ -229,7 +253,8 @@ describe Ohai::System, "Network Plugin" do
"3ffe:1111:2222::33" => {
"prefixlen" => "48",
"family" => "inet6",
- "scope" => "Global"
+ "scope" => "Global",
+ "state" => "up"
}
},
"mtu" => "1500",
@@ -245,7 +270,9 @@ describe Ohai::System, "Network Plugin" do
"prefixlen" => "64",
"family" => "inet6"
},
- "00:16:3E:2F:36:80" => {"family" => "lladdr"},
+ "00:16:3E:2F:36:80" => {
+ "family" => "lladdr"
+ },
"192.168.99.11" => {
"scope" => "Global",
"netmask" => "255.255.255.0",
@@ -301,14 +328,14 @@ describe Ohai::System, "Network Plugin" do
}
}
- describe "with linux" do
+ describe "on linux" do
before(:each) do
@plugin = get_plugin("network")
@plugin["network"] = basic_data["linux"]["network"]
end
describe "when the linux::network plugin hasn't set any of {ip,ip6,mac}address attributes" do
- describe "simple setup" do
+ describe "simple network setup" do
it_populates_ipaddress_attributes
it "detects {ip,ip6,mac}address" do
@@ -363,10 +390,9 @@ describe Ohai::System, "Network Plugin" do
expect(@plugin["ip6address"]).to eq("3ffe:1111:3333::1")
end
- it "doesn't set macaddress, ipv4 setup is valid and has precedence over ipv6" do
- expect(Ohai::Log).not_to receive(:warn).with(/^unable to detect macaddress/)
+ it "sets macaddress to the ipv6 interface because it hadn't set one for ipv4 first" do
@plugin.run
- expect(@plugin["macaddress"]).to be_nil
+ expect(@plugin["macaddress"]).to eq("00:16:3E:2F:36:80")
end
it "informs about this setup" do
@@ -393,10 +419,11 @@ describe Ohai::System, "Network Plugin" do
expect(@plugin["macaddress"]).to eq("00:16:3E:2F:36:80")
expect(@plugin["ip6address"]).to eq("3ffe:1111:3333::1")
end
-
+
it "warns about this conflict" do
expect(Ohai::Log).to receive(:debug).with(/^\[inet\] no ipaddress\/mask on eth1/).once
expect(Ohai::Log).to receive(:debug).with(/^\[inet6\] no ipaddress\/mask on eth1/).once
+ allow(Ohai::Log).to receive(:debug)
@plugin.run
end
end
@@ -434,9 +461,9 @@ describe Ohai::System, "Network Plugin" do
it "warns about this conflict" do
expect(Ohai::Log).to receive(:warn).with(/^unable to detect ipaddress/).once
- expect(Ohai::Log).to receive(:warn).with(/^unable to detect macaddress/).once
expect(Ohai::Log).to receive(:warn).with(/^\[inet\] no ip address on eth0/).once
expect(Ohai::Log).to receive(:debug).with(/^unable to detect ip6address/).once
+ expect(Ohai::Log).to receive(:debug).with(/^unable to detect macaddress/).twice # for each family
expect(Ohai::Log).to receive(:warn).with(/^\[inet6\] no ip address on eth0/).once
@plugin.run
end
@@ -465,7 +492,7 @@ describe Ohai::System, "Network Plugin" do
it "should warn about it" do
expect(Ohai::Log).to receive(:warn).with(/^unable to detect ipaddress/).once
- expect(Ohai::Log).to receive(:warn).with(/^unable to detect macaddress/).once
+ expect(Ohai::Log).to receive(:debug).with(/^unable to detect macaddress/).twice # for each family
expect(Ohai::Log).to receive(:debug).with(/^unable to detect ip6address/).once
@plugin.run
end
@@ -769,7 +796,9 @@ describe Ohai::System, "Network Plugin" do
it "warns about not being able to set {ip,mac}address (ipv4)" do
expect(Ohai::Log).to receive(:warn).with(/^unable to detect ipaddress/).once
- expect(Ohai::Log).to receive(:warn).with(/^unable to detect macaddress/).once
+ expect(Ohai::Log).to receive(:debug).with(/^unable to detect macaddress/) # for ipv4
+ expect(Ohai::Log).to receive(:debug).with(/^setting macaddress to/) # for ipv6
+ expect(Ohai::Log).to receive(:debug).with(/^\[inet6\] Using default interface eth0 and default gateway/) # for ipv6
@plugin.run
end
@@ -781,14 +810,46 @@ describe Ohai::System, "Network Plugin" do
end
it "informs about macaddress being set using the ipv6 setup" do
- expect(Ohai::Log).to receive(:debug).with(/^macaddress set to 00:16:3E:2F:36:79 from the ipv6 setup/).once
+ expect(Ohai::Log).to receive(:debug).with(/^setting macaddress to '00:16:3E:2F:36:79'/)
allow(Ohai::Log).to receive(:debug)
@plugin.run
end
end
+ describe "ipv6 only with ipv4 loopback" do
+ before do
+ @plugin["network"]["default_gateway"] = nil
+ @plugin["network"]["default_interface"] = nil
+ @plugin["network"]["interfaces"].each do |i,iv|
+ next if i == 'lo'
+ iv["addresses"].delete_if{|k,kv| kv["family"] == "inet" }
+ end
+ end
+
+ it_doesnt_fail
+
+ it "can't detect ipaddress" do
+ allow(Ohai::Log).to receive(:warn)
+ @plugin.run
+ expect(@plugin["ipaddress"]).to eq("127.0.0.1")
+ end
+
+ it "sets {ip6,mac}address" do
+ allow(Ohai::Log).to receive(:warn)
+ @plugin.run
+ expect(@plugin["ip6address"]).to eq("3ffe:1111:2222::33")
+ expect(@plugin["macaddress"]).to eq("00:16:3E:2F:36:79")
+ end
+
+ it "informs about macaddress being set using the ipv6 setup" do
+ expect(Ohai::Log).to receive(:debug).with(/^setting macaddress to '00:16:3E:2F:36:79'/)
+ allow(Ohai::Log).to receive(:debug)
+ @plugin.run
+ end
+ end
end
+ # specs using network plugin data for each mocked OS (freebsd,linux,windows)
basic_data.keys.sort.each do |os|
describe "the #{os}::network has already set some of the {ip,mac,ip6}address attributes" do
before(:each) do
@@ -801,13 +862,16 @@ describe Ohai::System, "Network Plugin" do
@plugin["macaddress"] = "00:AA:BB:CC:DD:EE"
@expected_results = {
"freebsd" => {
- "ip6address" => "::1"
+ "ip6address" => "2001:470:d:cb4::1",
+ "macaddress" => "02:20:6f:d2:c4:00"
},
"linux" => {
- "ip6address" => "3ffe:1111:2222::33"
+ "ip6address" => "3ffe:1111:2222::33",
+ "macaddress" => "00:16:3E:2F:36:79"
},
"windows" => {
- "ip6address" => "fe80::698d:3e37:7950:b28c"
+ "ip6address" => "fe80::698d:3e37:7950:b28c",
+ "macaddress" => "00:AA:BB:CC:DD:EE"
}
}
end
@@ -870,6 +934,17 @@ describe Ohai::System, "Network Plugin" do
end
end
@plugin["ip6address"] = "3ffe:8888:9999::1"
+ @expected_results = {
+ "freebsd" => {
+ "macaddress" => "02:20:6f:d2:c4:00"
+ },
+ "linux" => {
+ "macaddress" => "00:16:3E:2F:36:79"
+ },
+ "windows" => {
+ "macaddress" => "52:54:44:66:66:02"
+ }
+ }
end
it_doesnt_fail
@@ -880,15 +955,14 @@ describe Ohai::System, "Network Plugin" do
expect(@plugin["ipaddress"]).to be_nil
end
- it "can't detect macaddress either" do
+ it "takes the macaddress from ipv6" do
allow(Ohai::Log).to receive(:warn)
@plugin.run
- expect(@plugin["macaddress"]).to be_nil
+ expect(@plugin["macaddress"]).to eq(@expected_results[os]["macaddress"])
end
- it "warns about not being able to set {ip,mac}address" do
+ it "warns about not being able to set ipaddress" do
expect(Ohai::Log).to receive(:warn).with(/^unable to detect ipaddress/).once
- expect(Ohai::Log).to receive(:warn).with(/^unable to detect macaddress/).once
@plugin.run
end
@@ -923,10 +997,10 @@ describe Ohai::System, "Network Plugin" do
it_populates_ipaddress_attributes
- it "detects ipaddress and overwrite macaddress" do
+ it "detects ipaddress and does not overwrite macaddress" do
@plugin.run
expect(@plugin["ipaddress"]).to eq(@expected_results[os]["ipaddress"])
- expect(@plugin["macaddress"]).to eq(@expected_results[os]["macaddress"])
+ expect(@plugin["macaddress"]).to eq(@plugin["macaddress"])
end
it "doesn't overwrite ip6address" do
@@ -990,10 +1064,9 @@ describe Ohai::System, "Network Plugin" do
it_doesnt_fail
- it "doesn't overwrite {ip,mac,ip6}address" do
+ it "doesn't overwrite {ip,ip6}address" do
@plugin.run
expect(@plugin["ipaddress"]).to eq("10.11.12.13")
- expect(@plugin["macaddress"]).to eq(nil)
expect(@plugin["ip6address"]).to eq("3ffe:8888:9999::1")
end
end