[CentOS] Scripting Oddity

Tue Feb 10 03:22:02 UTC 2009
David G. Miller <dave at davenjudy.org>

I've been playing around with qemu and wanted to make the guest OS 
instance visible on my network.  This meant getting bridging and tun/tap 
working.  After getting things working by pasting command from the 
CentOS wiki article plus adding a few enhancements, I decided to capture 
the process in a shell script that would be suitable for a user in the 
sudoers file to fire off.  Not sure why (which is why I'm posting this) 
but I couldn't get the same result from the shell script as I got from 
pasting commands onto the command line or using the shell history.

After a lot of very tedious debugging, I finally got the script to work 
by adding a couple of short sleeps at selected locations.  The script 
now looks like:

cat upBridge.sh
#!/bin/bash
#
# Script for setting up a bridge accessible by a qemu VM.
#
# First, make sure we're starting with a clean slate.
/usr/bin/sudo /sbin/rmmod bridge
/usr/bin/sudo /sbin/rmmod tun
/usr/bin/sudo /sbin/service network restart
#
# Grab the IP address of the given interface so we can restore it later.
#
oldIP=`/sbin/ifconfig $1 | /bin/grep 'inet addr' | /usr/bin/awk -F \: 
'{print substr($2,0,index($2, " ")) ; }'`
echo "$1 currently has IP address $oldIP"
#
# Create the bridge.
#
/usr/bin/sudo /usr/sbin/brctl addbr br0
/usr/bin/sudo /sbin/ifconfig $1 0.0.0.0

sleep 2

/usr/bin/sudo /usr/sbin/brctl addif br0 $1
#
# Stop any dhclient still running.
#
/usr/bin/sudo /usr/bin/killall dhclient
#
# Get and IP address and routing information for the bridge
#
/usr/bin/sudo /sbin/dhclient br0
#
# Make sure the tun module is loaded, assign it to our user and bring it up.
#
/usr/bin/sudo /sbin/modprobe tun
echo "Did tun load?"
lsmod | grep tun
/usr/bin/sudo /usr/sbin/tunctl -b -u $USER

sleep 2

/usr/bin/sudo /sbin/ifconfig tap0 up
#
# Connect the bridge and the tap.
#
/usr/bin/sudo /usr/sbin/brctl addif br0 tap0
/usr/bin/sudo /bin/chown $USER:users /dev/net/tun
/usr/bin/sudo /sbin/iptables -I RH-Firewall-1-INPUT -i br0 -j ACCEPT
#
# restore the IP address of our "normal" interface.
#
/usr/bin/sudo /sbin/ifconfig $1 $oldIP

So, my question is, why do I need to have a short sleep in these two 
locations in my script? 

Without a sleep after the "ifconfig eth0 0.0.0.0", eth0 retains its 
original IP address instead of having no address.  The qemu guest VM 
still functions correctly but the host system loses connectivity.  
Likewise, without a sleep after the tunctl command, the device 
/dev/net/tun isn't present when the next command executes.  With the 
sleeps the script executes as expected and sets up the bridge.  Without 
the sleeps the script fails.

Oh yeah.  There's another script called downBridge.sh that undoes the 
bridge if anyone is interested.

Cheers,
Dave

-- 
Politics, n. Strife of interests masquerading as a contest of principles.
-- Ambrose Bierce