diff options
author | Tim Smith <tsmith@chef.io> | 2015-12-14 11:25:33 -0800 |
---|---|---|
committer | Tim Smith <tsmith@chef.io> | 2015-12-14 11:25:33 -0800 |
commit | 975d8e7186484a4208034fef5ad42b8ae22d3fac (patch) | |
tree | 3f82f26e68840b87c4120c1ce2d3522e8191e537 | |
parent | de20410be19e8b88a17d0a4a27b9e5c16875baeb (diff) | |
parent | c2051dcb50872462ca3df19f13ca9cd513ccc18c (diff) | |
download | ohai-975d8e7186484a4208034fef5ad42b8ae22d3fac.tar.gz |
Merge pull request #680 from phreakocious/master
Add support for collecting ethernet layer one information from ethtool on linux
-rw-r--r-- | lib/ohai/plugins/linux/network.rb | 28 | ||||
-rw-r--r-- | spec/unit/plugins/linux/network_spec.rb | 48 |
2 files changed, 76 insertions, 0 deletions
diff --git a/lib/ohai/plugins/linux/network.rb b/lib/ohai/plugins/linux/network.rb index 51eff9dd..689001dc 100644 --- a/lib/ohai/plugins/linux/network.rb +++ b/lib/ohai/plugins/linux/network.rb @@ -41,6 +41,10 @@ Ohai.plugin(:Network) do ["/sbin/ip", "/usr/bin/ip", "/bin/ip"].any? { |path| File.exist?(path) } end + def find_ethtool_binary + ["/sbin/ethtool", "/usr/sbin/ethtool"].find { |path| File.exist?(path) } + end + def is_openvz? ::File.directory?('/proc/vz') end @@ -134,6 +138,28 @@ Ohai.plugin(:Network) do end.compact.flatten end + def ethernet_layer_one(iface) + return iface unless ethtool_binary = find_ethtool_binary + keys = %w[ Speed Duplex Port Transceiver Auto-negotiation MDI-X ] + iface.each_key do |tmp_int| + next unless iface[tmp_int][:encapsulation] == 'Ethernet' + so = shell_out("#{ethtool_binary} #{tmp_int}") + so.stdout.lines do |line| + line.chomp! + Ohai::Log.debug("Parsing ethtool output: #{line}") + line.lstrip! + k, v = line.split(': ') + next unless keys.include? k + k.downcase!.tr!('-', '_') + if k == 'speed' + k = 'link_speed' # This is not necessarily the maximum speed the NIC supports + v = v[/\d+/].to_i + end + iface[tmp_int][k] = v + end + end + iface + end def link_statistics(iface, net_counters) so = shell_out("ip -d -s link") @@ -477,6 +503,8 @@ Ohai.plugin(:Network) do end end end + + iface = ethernet_layer_one(iface) counters[:network][:interfaces] = net_counters network["interfaces"] = iface end diff --git a/spec/unit/plugins/linux/network_spec.rb b/spec/unit/plugins/linux/network_spec.rb index 7b5dcbde..de5a89ce 100644 --- a/spec/unit/plugins/linux/network_spec.rb +++ b/spec/unit/plugins/linux/network_spec.rb @@ -298,6 +298,31 @@ fe80::21c:eff:fe12:3456 dev eth0.153 lladdr 00:1c:0e:30:28:00 router REACHABLE ' } + let(:linux_ethtool) { +'Settings for eth0: + Supported ports: [ FIBRE ] + Supported link modes: 1000baseT/Full + 10000baseT/Full + Supported pause frame use: No + Supports auto-negotiation: Yes + Advertised link modes: 1000baseT/Full + 10000baseT/Full + Advertised pause frame use: No + Advertised auto-negotiation: Yes + Speed: 10000Mb/s + Duplex: Full + Port: FIBRE + PHYAD: 0 + Transceiver: external + Auto-negotiation: on + Supports Wake-on: d + Wake-on: d + Current message level: 0x00000007 (7) + drv probe link + Link detected: yes +' + } + before(:each) do allow(plugin).to receive(:collect_os).and_return(:linux) @@ -311,6 +336,7 @@ fe80::21c:eff:fe12:3456 dev eth0.153 lladdr 00:1c:0e:30:28:00 router REACHABLE allow(plugin).to receive(:shell_out).with("route -n").and_return(mock_shell_out(0, linux_route_n, "")) allow(plugin).to receive(:shell_out).with("ifconfig -a").and_return(mock_shell_out(0, linux_ifconfig, "")) allow(plugin).to receive(:shell_out).with("arp -an").and_return(mock_shell_out(0, linux_arp_an, "")) + allow(plugin).to receive(:shell_out).with(/ethtool/).and_return(mock_shell_out(0, linux_ethtool, "")) end describe "#iproute2_binary_available?" do @@ -323,11 +349,23 @@ fe80::21c:eff:fe12:3456 dev eth0.153 lladdr 00:1c:0e:30:28:00 router REACHABLE end end + describe "#find_ethtool_binary" do + ["/sbin/ethtool", "/usr/sbin/ethtool"].each do |path| + it "accepts #{path}" do + allow(File).to receive(:exist?).and_return(false) + allow(File).to receive(:exist?).with(path).and_return(true) + expect(plugin.find_ethtool_binary).to end_with("/ethtool") + end + end + end + + ["ifconfig","iproute2"].each do |network_method| describe "gathering IP layer address info via #{network_method}" do before(:each) do allow(plugin).to receive(:iproute2_binary_available?).and_return( network_method == "iproute2" ) + allow(plugin).to receive(:find_ethtool_binary).and_return( '/sbin/ethtool' ) plugin.run end @@ -340,6 +378,15 @@ fe80::21c:eff:fe12:3456 dev eth0.153 lladdr 00:1c:0e:30:28:00 router REACHABLE expect(plugin['network']['interfaces'].keys.sort).to eq(["eth0", "eth0.11", "eth0.151", "eth0.152", "eth0.153", "eth0:5", "eth3", "foo:veth0@eth0", "lo", "ovs-system", "tun0", "venet0", "venet0:0", "xapi1"]) end + it "detects the layer one details of an ethernet interface" do + expect(plugin['network']['interfaces']['eth0']['link_speed']).to eq(10000) + expect(plugin['network']['interfaces']['eth0']['duplex']).to eq('Full') + expect(plugin['network']['interfaces']['eth0']['port']).to eq('FIBRE') + expect(plugin['network']['interfaces']['eth0']['transceiver']).to eq('external') + expect(plugin['network']['interfaces']['eth0']['auto_negotiation']).to eq('on') + expect(plugin['network']['interfaces']['eth0']['mdi_x']).to be_nil + end + it "detects the ipv4 addresses of the ethernet interface" do expect(plugin['network']['interfaces']['eth0']['addresses'].keys).to include('10.116.201.76') expect(plugin['network']['interfaces']['eth0']['addresses']['10.116.201.76']['netmask']).to eq('255.255.255.0') @@ -547,6 +594,7 @@ Destination Gateway Genmask Flags Metric Ref Use Iface before(:each) do allow(File).to receive(:exist?).with("/sbin/ip").and_return(true) # iproute2 only allow(File).to receive(:exist?).with("/proc/net/if_inet6").and_return(true) # ipv6 is enabled + allow(File).to receive(:exist?).with("/sbin/ethtool").and_return(true) # ethtool is available plugin.run end |