Search This Blog

Monday, April 7, 2014

Eth0 Getting Incremented while Cloning

Hi everybody,
Today i came across a situation, that my network interface(s) number gets incremented when ever i clone my virtual machine (by virtual box or other means). For some or the other reason certain people do not like their interfaces to be changed.
   Started investigating the cause and found that udev was the daemon which increments the number on the interface. It has certain set of rules written which reinitiate the device number. Here is the small patch that can be handy for some users.

Note: These commands has to be performed as root

Step 1: Edit the file /lib/udev/write_net_rules and make the following changes

# vi /lib/udev/write_net_rules

Orginally looks like this

#!/bin/sh -e

# This script is run to create persistent network device naming rules
# based on properties of the device.
# If the interface needs to be renamed, INTERFACE_NEW=<name> will be printed
# on stdout to allow udev to IMPORT it.

# variables used to communicate:
#   MATCHADDR             MAC address used for the match
#   MATCHID               bus_id used for the match
#   MATCHDEVID            dev_id used for the match
#   MATCHDRV              driver name used for the match
#   MATCHIFTYPE           interface type match
#   COMMENT               comment to add to the generated rule
#   INTERFACE_NAME        requested name supplied by external tool
#   INTERFACE_NEW         new interface name returned by rule writer

# Copyright (C) 2006 Marco d'Itri <md@Linux.IT>
# Copyright (C) 2007 Kay Sievers <kay.sievers@vrfy.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

# debug, if UDEV_LOG=<debug>
if [ -n "$UDEV_LOG" ]; then
if [ "$UDEV_LOG" -ge 7 ]; then
set -x
fi
fi

RULES_FILE='/etc/udev/rules.d/70-persistent-net.rules'
. /lib/udev/rule_generator.functions

interface_name_taken() {
local value="$(find_all_rules 'NAME=' $INTERFACE)"
if [ "$value" ]; then
return 0
else
return 1
fi
}

find_next_available() {
raw_find_next_available "$(find_all_rules 'NAME=' "$1")"
}

write_rule() {
local match="$1"
local name="$2"
local comment="$3"

{
if [ "$PRINT_HEADER" ]; then
PRINT_HEADER=
echo "# This file was automatically generated by the $0"
echo "# program, run by the persistent-net-generator.rules rules file."
echo "#"
echo "# You can modify it, as long as you keep each rule on a single"
echo "# line, and change only the value of the NAME= key."
fi

echo ""
[ "$comment" ] && echo "# $comment"
echo "SUBSYSTEM==\"net\", ACTION==\"add\"$match, NAME=\"$name\""
} >> $RULES_FILE
}

if [ -z "$INTERFACE" ]; then
echo "missing \$INTERFACE" >&2
exit 1
fi

# Prevent concurrent processes from modifying the file at the same time.
lock_rules_file

# Check if the rules file is writeable.
choose_rules_file

# the DRIVERS key is needed to not match bridges and VLAN sub-interfaces
if [ "$MATCHADDR" ]; then
match="$match, DRIVERS==\"?*\", ATTR{address}==\"$MATCHADDR\""
fi

if [ "$MATCHDRV" ]; then
match="$match, DRIVERS==\"$MATCHDRV\""
fi

if [ "$MATCHDEVID" ]; then
match="$match, ATTR{dev_id}==\"$MATCHDEVID\""
fi

if [ "$MATCHID" ]; then
match="$match, KERNELS==\"$MATCHID\""
fi

if [ "$MATCHIFTYPE" ]; then
match="$match, ATTR{type}==\"$MATCHIFTYPE\""
fi

if [ -z "$match" ]; then
echo "missing valid match" >&2
unlock_rules_file
exit 1
fi

basename=${INTERFACE%%[0-9]*}
match="$match, KERNEL==\"$basename*\""

if [ "$INTERFACE_NAME" ]; then
# external tools may request a custom name
COMMENT="$COMMENT (custom name provided by external tool)"
if [ "$INTERFACE_NAME" != "$INTERFACE" ]; then
INTERFACE=$INTERFACE_NAME;
echo "INTERFACE_NEW=$INTERFACE"
fi
else
# if a rule using the current name already exists, find a new name
if interface_name_taken; then
INTERFACE="$basename$(find_next_available "$basename[0-9]*")"
# prevent INTERFACE from being "eth" instead of "eth0"
[ "$INTERFACE" = "${INTERFACE%%[ \[\]0-9]*}" ] && INTERFACE=${INTERFACE}0
echo "INTERFACE_NEW=$INTERFACE"
fi
fi

write_rule "$match" "$INTERFACE" "$COMMENT"

unlock_rules_file

exit 0


Change it as follows

#!/bin/sh -e

# This script is run to create persistent network device naming rules
# based on properties of the device.
# If the interface needs to be renamed, INTERFACE_NEW=<name> will be printed
# on stdout to allow udev to IMPORT it.

# variables used to communicate:
#   MATCHADDR             MAC address used for the match
#   MATCHID               bus_id used for the match
#   MATCHDEVID            dev_id used for the match
#   MATCHDRV              driver name used for the match
#   MATCHIFTYPE           interface type match
#   COMMENT               comment to add to the generated rule
#   INTERFACE_NAME        requested name supplied by external tool
#   INTERFACE_NEW         new interface name returned by rule writer

# Copyright (C) 2006 Marco d'Itri <md@Linux.IT>
# Copyright (C) 2007 Kay Sievers <kay.sievers@vrfy.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

# debug, if UDEV_LOG=<debug>
if [ -n "$UDEV_LOG" ]; then
if [ "$UDEV_LOG" -ge 7 ]; then
set -x
fi
fi

RULES_FILE='/etc/udev/rules.d/70-persistent-net.rules'
dnc='/etc/udev/rules.d/dnc-network'
. /lib/udev/rule_generator.functions

interface_name_taken() {
local value="$(find_all_rules 'NAME=' $INTERFACE)"
if [ "$value" ]; then
return 0
else
return 1
fi
}

find_next_available() {
raw_find_next_available "$(find_all_rules 'NAME=' "$1")"
}

write_rule() {
local match="$1"
local name="$2"
local comment="$3"

{
if [ "$PRINT_HEADER" ]; then
PRINT_HEADER=
echo "# This file was automatically generated by the $0"
echo "# program, run by the persistent-net-generator.rules rules file."
echo "#"
echo "# You can modify it, as long as you keep each rule on a single"
echo "# line, and change only the value of the NAME= key."
fi

echo ""
[ "$comment" ] && echo "# $comment"
echo "SUBSYSTEM==\"net\", ACTION==\"add\"$match, NAME=\"$name\""
} >> $RULES_FILE
}

if [ -z "$INTERFACE" ]; then
echo "missing \$INTERFACE" >&2
exit 1
fi

# Prevent concurrent processes from modifying the file at the same time.
lock_rules_file

# Check if the rules file is writeable.
choose_rules_file

# the DRIVERS key is needed to not match bridges and VLAN sub-interfaces
if [ "$MATCHADDR" ]; then
match="$match, DRIVERS==\"?*\", ATTR{address}==\"$MATCHADDR\""
fi

if [ "$MATCHDRV" ]; then
match="$match, DRIVERS==\"$MATCHDRV\""
fi

if [ "$MATCHDEVID" ]; then
match="$match, ATTR{dev_id}==\"$MATCHDEVID\""
fi

if [ "$MATCHID" ]; then
match="$match, KERNELS==\"$MATCHID\""
fi

if [ "$MATCHIFTYPE" ]; then
match="$match, ATTR{type}==\"$MATCHIFTYPE\""
fi

if [ -z "$match" ]; then
echo "missing valid match" >&2
unlock_rules_file
exit 1
fi

basename=${INTERFACE%%[0-9]*}
match="$match, KERNEL==\"$basename*\""

if [ "$INTERFACE_NAME" ]; then
# external tools may request a custom name
COMMENT="$COMMENT (custom name provided by external tool)"
if [ "$INTERFACE_NAME" != "$INTERFACE" ]; then
INTERFACE=$INTERFACE_NAME;
echo "INTERFACE_NEW=$INTERFACE"
fi
else
# if a rule using the current name already exists, find a new name
if interface_name_taken; then
  if ! [ -e $dnc ]; then
INTERFACE="$basename$(find_next_available "$basename[0-9]*")"
# prevent INTERFACE from being "eth" instead of "eth0"
[ "$INTERFACE" = "${INTERFACE%%[ \[\]0-9]*}" ] && INTERFACE=${INTERFACE}0
echo "INTERFACE_NEW=$INTERFACE"
  fi
fi
fi

write_rule "$match" "$INTERFACE" "$COMMENT"

unlock_rules_file

exit 0


Step 2: Create a file named /etc/udev/rules.d/dnc-network

# touch /etc/udev/rules.d/dnc-network

Step 3: Shutdown the virtual machine and clone the machine to test

Enjoy :)