jmtd → log → Puppet and persistent network interface names
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?