None
Cloning Linux VMs - Consistent Interfaces
When cloning a Linux virtual machine, reinitializing the MAC address renames the network interfaces. For example, "eth0" stops referencing a valid device and "eth1" now references the first ethernet device. This doesn't work well with clones though; I like reinitializing MAC addresses for concurrency, but I dislike new names and particularly dislike waiting 120+ seconds for "new" interfaces to "start".

The crux of the issue is easily shown with ifconfig -a and, in greater detail, by 70-persistent-net.rules [automatically generated by udev]. Here's the original "parent" VM-
> test@original~$ ifconfig -a | grep "Link\|inet"
eth0      Link encap:Ethernet  HWaddr 08:00:27:aa:af:eb
inet addr:192.168.0.2 Bcast:192.168.0.255 Mask:255.255.255.0
eth1 Link encap:Ethernet HWaddr 08:00:27:e9:c5:fd
inet addr:10.0.0.2 Bcast:10.255.255.255 Mask:255.0.0.0
> test@original~$ grep 'eth' /etc/udev/rules.d/70-persistent-net.rules
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="08:00:27:aa:af:eb", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="08:00:27:e9:c5:fd", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth1"

The clone, with a reinitialized MAC, looks like this after booting:
> test@clone:~$ ifconfig -a | grep "Link\inet"
eth2      Link encap:Ethernet  HWaddr 08:00:27:e3:dc:0d
eth3 Link encap:Ethernet HWaddr 08:00:27:73:2d:87
> test@clone:~$ grep 'eth' /etc/udev/rules.d/70-persistent-net.rules
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="08:00:27:aa:af:eb", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="08:00:27:e9:c5:fd", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth1"
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="08:00:27:e3:dc:0d", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth2"
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="08:00:27:73:2d:87", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth3"

UDEV automatically assigned a new name to each interface because they failed to match any previous rules (different ATTR{address}). Unfortunately, eth2 and eth3 weren't setup at all because /etc/network/interfaces had no mention of them. Even worse, for the impatient, /etc/network/interfaces directed the system to DHCP eth0 and eth1, but both failed (after 2 minutes) because the devices weren't mapped.

Previously, I applied a 10-second manual fix using "vim /etc/udev/rules.d/70-persistent-net.rules" and changing the offending lines:
> sudo cp /etc/udev/rules.d/70-persistent-net.rules{,.bak} # make a backup
> cat /etc/udev/rules.d/70-persistent-net.rules
# This file was automatically generated by the /lib/udev/write_net_rules
# program, run by the persistent-net-generator.rules rules file.
#
# You can modify it, as long as you keep each rule on a single
# line, and change only the value of the NAME= key.

# PCI device 0x8086:/sys/devices/pci0000:00/0000:00:08.0 (e1000)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="08:00:27:aa:af:eb", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"

# PCI device 0x8086:/sys/devices/pci0000:00/0000:00:03.0 (e1000)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="08:00:27:e9:c5:fd", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth1"

# PCI device 0x8086:/sys/devices/pci0000:00/0000:00:03.0 (e1000)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="08:00:27:e3:dc:0d", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth2"

# PCI device 0x8086:/sys/devices/pci0000:00/0000:00:08.0 (e1000)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="08:00:27:73:2d:87", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth3"
# notice that eth0 (pci...08.0) mapped to eth3 (pci...08.0) this time; it mapped to eth2 every other time, but concurrent driver startup causes random name selections
> sudo vim /etc/udev/rules.d/70-persistent-net.rules # delete eth0/eth1, change eth3 -> eth0, change eth2 -> eth1
> cat /etc/udev/rules.d/70-persistent-net.rules
# This file was automatically generated by the /lib/udev/write_net_rules
# program, run by the persistent-net-generator.rules rules file.
#
# You can modify it, as long as you keep each rule on a single
# line, and change only the value of the NAME= key.

# PCI device 0x8086:/sys/devices/pci0000:00/0000:00:03.0 (e1000)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="08:00:27:e3:dc:0d", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth1"

# PCI device 0x8086:/sys/devices/pci0000:00/0000:00:08.0 (e1000)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="08:00:27:73:2d:87", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"

After a quick reboot, everything works and looks like the original:
> ifconfig -a | grep "Link\|inet\|\n"
eth0      Link encap:Ethernet  HWaddr 08:00:27:e3:dc:0d
inet addr:192.168.0.3 Bcast:192.168.0.255 Mask:255.255.255.0
eth1 Link encap:Ethernet HWaddr 08:00:27:73:2d:87
inet addr:10.0.0.3 Bcast:10.255.255.255 Mask:255.0.0.0
> grep 'eth' /etc/udev/rules.d/70-persistent-net.rules
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="08:00:27:e3:dc:0d", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="08:00:27:73:2d:87", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth1"

This fix is quick and works great, but manually fixing every clone every time their reinitialized is a bad long-term fix. And fortunately, there's a very simple fix available. As we saw above, although the MAC address changed the PCI device ID (/sys/devices/pci0000:00/0000:00:03.0) stayed the same. We can fix the problem by directly modifying /etc/udev/rules.d/70-persistent-net.rules, but that's automatically generated and will be overwritten whenever we connect a new network device. The source of that file, /lib/udev/write_new_rules, is a far better target - especially for such an easy fix. (btw, there's a good tutorial on udev at http://www.reactivated.net/writing_udev_rules.html)

> sudo cp /lib/udev/write_new_rules{,.bak} # always make a backup
> sudo mv /etc/udev/rules.d/70-persistent-net.rules{,.old} # remove, but keep it handy
> sudo vi /lib/udev/write_new_rules # replace if [ "$MATCHADDR" ]; then +2 lines w/
if [ "$ID_MODEL_ID" ]; then
match="$match, DRIVERS==\"?*\", ATTR{device}==\"$ID_MODEL_ID\""
elif [ "$MATCHADDR" ]; then
match="$match, DRIVERS==\"?*\", ATTR{address}==\"$MATCHADDR\""
fi

After a quick reboot, everything works and looks like the original AND we can freely add/remove interfaces / reclone the VM.
> ifconfig -a | grep "Link\|inet\|\n"
eth0      Link encap:Ethernet  HWaddr 08:00:27:e3:dc:0d
inet addr:192.168.0.3 Bcast:192.168.0.255 Mask:255.255.255.0
eth1 Link encap:Ethernet HWaddr 08:00:27:73:2d:87
inet addr:10.0.0.3 Bcast:10.255.255.255 Mask:255.0.0.0
> grep 'eth' /etc/udev/rules.d/70-persistent-net.rules
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{device}=="/sys/devices/pci0000:00/0000:00:03.0", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{device}=="/sys/devices/pci0000:00/0000:00:08.0", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth1"

- Kelson (kelson@shysecurity.com)