diff --git a/plugins/guests/linux/cap/network_interfaces.rb b/plugins/guests/linux/cap/network_interfaces.rb index defc6cb7f..c8b82376b 100644 --- a/plugins/guests/linux/cap/network_interfaces.rb +++ b/plugins/guests/linux/cap/network_interfaces.rb @@ -19,6 +19,7 @@ module VagrantPlugins machine.communicate.sudo("#{path} -o -0 addr | grep -v LOOPBACK | awk '{print $2}' | sed 's/://'") do |type, data| s << data if type == :stdout end + # In some cases net devices may be added to the guest and will not # properly show up when using `ip`. This pulls any device information # that can be found in /proc and adds it to the list of interfaces @@ -26,7 +27,17 @@ module VagrantPlugins machine.communicate.sudo("cat /proc/net/dev | grep -E '^[a-z0-9 ]+:' | awk '{print $1}' | sed 's/://'", error_check: false) do |type, data| s << data if type == :stdout end - ifaces = s.split("\n") + + # Collect all loopback interfaces + los = "" + machine.communicate.sudo("#{path} -o -0 addr | grep LOOPBACK | awk '{print $2}' | sed 's/://'") do |type, data| + los << data if type == :stdout + end + loifaces = los.split("\n") + @@logger.debug("loopback interfaces: #{loifaces.inspect}") + + ifaces = s.split("\n").reject { |x| x.empty? or loifaces.include?(x) } + @@logger.debug("Unsorted list: #{ifaces.inspect}") # Break out integers from strings and sort the arrays to provide # a natural sort for the interface names @@ -34,7 +45,7 @@ module VagrantPlugins # as expected. This is generally seen with veth* devices, and proper ordering # is currently not required ifaces = ifaces.map do |iface| - iface.scan(/(.+?)(\d+)/).flatten.map do |iface_part| + iface.scan(/(.+?)(\d+)?/).flatten.map do |iface_part| if iface_part.to_i.to_s == iface_part iface_part.to_i else diff --git a/test/unit/plugins/guests/linux/cap/network_interfaces_test.rb b/test/unit/plugins/guests/linux/cap/network_interfaces_test.rb index 230728cd7..fa64b6bbe 100644 --- a/test/unit/plugins/guests/linux/cap/network_interfaces_test.rb +++ b/test/unit/plugins/guests/linux/cap/network_interfaces_test.rb @@ -23,60 +23,84 @@ describe "VagrantPlugins::GuestLinux::Cap::NetworkInterfaces" do it "sorts discovered classic interfaces" do expect(comm).to receive(:sudo).twice.and_yield(:stdout, "eth1\neth2\neth0") + expect(comm).to receive(:sudo).and_yield(:stdout, "lo") result = cap.network_interfaces(machine) expect(result).to eq(["eth0", "eth1", "eth2"]) end + it "sorts discovered classic interfaces and handles trailing newline" do + expect(comm).to receive(:sudo).twice.and_yield(:stdout, "eth1\neth2\neth0\n") + expect(comm).to receive(:sudo).and_yield(:stdout, "lo") + result = cap.network_interfaces(machine) + expect(result).to eq(["eth0", "eth1", "eth2"]) + end + + it "filters out lo interface" do + expect(comm).to receive(:sudo).twice.and_yield(:stdout, "lo\neth0") + expect(comm).to receive(:sudo).and_yield(:stdout, "lo") + result = cap.network_interfaces(machine) + expect(result).to eq(["eth0"]) + end + it "sorts discovered predictable network interfaces" do expect(comm).to receive(:sudo).twice.and_yield(:stdout, "enp0s8\nenp0s3\nenp0s5") + expect(comm).to receive(:sudo).and_yield(:stdout, "lo") result = cap.network_interfaces(machine) expect(result).to eq(["enp0s3", "enp0s5", "enp0s8"]) end it "sorts discovered classic interfaces naturally" do expect(comm).to receive(:sudo).twice.and_yield(:stdout, "eth1\neth2\neth12\neth0\neth10") + expect(comm).to receive(:sudo).and_yield(:stdout, "lo") result = cap.network_interfaces(machine) expect(result).to eq(["eth0", "eth1", "eth2", "eth10", "eth12"]) end it "sorts discovered predictable network interfaces naturally" do expect(comm).to receive(:sudo).twice.and_yield(:stdout, "enp0s8\nenp0s3\nenp0s5\nenp0s10\nenp1s3") + expect(comm).to receive(:sudo).and_yield(:stdout, "lo") result = cap.network_interfaces(machine) expect(result).to eq(["enp0s3", "enp0s5", "enp0s8", "enp0s10", "enp1s3"]) end it "sorts ethernet devices discovered with classic naming first in list" do expect(comm).to receive(:sudo).twice.and_yield(:stdout, "eth1\neth2\ndocker0\nbridge0\neth0") + expect(comm).to receive(:sudo).and_yield(:stdout, "lo") result = cap.network_interfaces(machine) expect(result).to eq(["eth0", "eth1", "eth2", "bridge0", "docker0"]) end it "sorts ethernet devices discovered with predictable network interfaces naming first in list" do expect(comm).to receive(:sudo).twice.and_yield(:stdout, "enp0s8\ndocker0\nenp0s3\nbridge0\nenp0s5") + expect(comm).to receive(:sudo).and_yield(:stdout, "lo") result = cap.network_interfaces(machine) expect(result).to eq(["enp0s3", "enp0s5", "enp0s8", "bridge0", "docker0"]) end it "sorts ethernet devices discovered with predictable network interfaces naming first in list with less" do expect(comm).to receive(:sudo).twice.and_yield(:stdout, "enp0s3\nenp0s8\ndocker0") + expect(comm).to receive(:sudo).and_yield(:stdout, "lo") result = cap.network_interfaces(machine) expect(result).to eq(["enp0s3", "enp0s8", "docker0"]) end it "does not include ethernet devices aliases within prefix device listing" do expect(comm).to receive(:sudo).twice.and_yield(:stdout, "eth1\neth2\ndocker0\nbridge0\neth0\ndocker1\neth0:0") + expect(comm).to receive(:sudo).and_yield(:stdout, "lo") result = cap.network_interfaces(machine) expect(result).to eq(["eth0", "eth1", "eth2", "bridge0", "docker0", "docker1", "eth0:0"]) end it "does not include ethernet devices aliases within prefix device listing with dot separators" do expect(comm).to receive(:sudo).twice.and_yield(:stdout, "eth1\neth2\ndocker0\nbridge0\neth0\ndocker1\neth0.1@eth0") + expect(comm).to receive(:sudo).and_yield(:stdout, "lo") result = cap.network_interfaces(machine) expect(result).to eq(["eth0", "eth1", "eth2", "bridge0", "docker0", "docker1", "eth0.1@eth0"]) end it "properly sorts non-consistent device name formats" do expect(comm).to receive(:sudo).twice.and_yield(:stdout, "eth0\neth1\ndocker0\nveth437f7f9\nveth06b3e44\nveth8bb7081") + expect(comm).to receive(:sudo).and_yield(:stdout, "lo") result = cap.network_interfaces(machine) expect(result).to eq(["eth0", "eth1", "docker0", "veth8bb7081", "veth437f7f9", "veth06b3e44"]) end