On Linux, network interface device naming has been somewhat chaotic: depending on a number of factors, eth0 today might not be eth0 tomorrow. For me, this has never been a problem in practice. At work, our physical servers have a bank of on-mainboard network ports, all managed by the same driver and so are assigned names predictably. For our virtual machines, the same is true: 99% of the time they have one network interface, but when they have more than one, they are of the same type and so are assigned predictably. At home, even on desktops and laptops with multiple network devices being added and removed at a time, I've never actually hit a problem where one was mis-identified.

However, it must have been a problem for some people because it has been solved three times now. Sadly, these incompatible solutions cause headaches in all of my use cases.

At work we have a puppet snippet that relies on knowing the interface name for a host's "primary" interface. In our case, "primary" means something like "the one the default route is over". We used to hardcode eth0 into this recipe. I don't feel too bad about that, as the puppet folks do the exact same thing in many of their scripts.

This breaks for newer physical hosts where one of the three schemes are in play and the interfaces are named/numbered em1 and counting. We worked around it by parameterizing the interface name in our recipe and defining it in our nodes.pp for the troublesome hosts, but that just moves the problem around.

My more permanent solution is to define a facter fact primary_interface that tells puppet what the correct interface should be. Here's my first attempt:

Facter.add("primary_interface") do
  setcode do
    ifs = Dir.new("/sys/class/net").each.to_a - \
      Dir.new("/sys/devices/virtual/net").each.to_a

      # filter out ones with no link
      ifs.reject! do |i|
        begin
          File.read("/sys/class/net/#{i}/carrier") != "1\n"
        rescue Errno::EINVAL
          true
        end
      end
    ifs[0]
  end
end

Of course, there is plenty of room for improvement with this solution: if ifs has more than one element at the end, a lexographic sort may prove more accurate; if there is an existing network default route up, that might be a strong clue too. It's also very Linux specific. My question though is whether this is a sensible approach in the first place?