#!/bin/sh

# Set up a federated environment on a client.  Unmount all local file systems,
# erase all local accounts and then bring in accounts and file systems from the
# master testbed.  Once all that's done, restore client communication to the
# local bossnode and execute any startup command passed in as arguments to this
# script.


# The file containing the DNS name of the current boss
BOSSNODE="/usr/local/etc/emulab/bossnode"

# Ports that the master gateway will forward
PORTS="139 7777"
# network cat command (to listen for the gateway)
NC="/usr/bin/nc"
# Emulab rc scripts directory
RCDIR="/usr/local/etc/emulab/rc"

# Emulab rc script to reset accounts and federation srcipt to start the smb
# automount process.
RCACCT="rc.accounts"
SMBMOUNT="smbmount.`uname`.pl"

# Find the right version of pkill.  For killing.
if [ -x "/usr/bin/pkill" ] ; then 
	PKILL="/usr/bin/pkill"
else
	if [ -x "/bin/pkill" ] ; then 
		PKILL="/bin/pkill"
	else
		PKILL="echo"
	fi
fi

if [ -x "/usr/bin/perl" ]; then
    PERL="/usr/bin/perl"
else
    if [ -x "/usr/local/bin/perl" ]; then
	PERL="/usr/local/bin/perl"
    else
	# Wing it...
	PERL="perl"
    fi
fi

# Find somewhere safe to stop
cd /tmp

if [ -f $BOSSNODE ]
then
	rm -f $BOSSNODE
fi

EMUDIR="/usr/local/etc/emulab/"

# Find this experiment's stashed scripts.  (Perl for advanced parsing)
PROJECT=`$EMUDIR/tmcc -b status | $PERL -ne '/ALLOCATED=([^\/]+)\/([^\s]+)/ && print "$1\n";'`
EXP=`$EMUDIR/tmcc -b status | $PERL -ne '/ALLOCATED=([^\/]+)\/([^\s]+)/ && print "$2\n";'`
CONFIGDIR="/proj/$PROJECT/exp/$EXP/tmp"
SCRIPTDIR="/usr/local/federation/bin"

# Die if Scripts are not where they should be.  NB, this is checked by the
# bootstrapper, too, so a failure here is unlikely.
if [ -z "$CONFIGDIR" ] ; then
    echo "Can't find federation configs.  Tmcc status says:"
    $EMUDIR/tmcc -b status
    exit 1;
fi

# Leave the client configuration information where clients can use it
mkdir -p "/usr/local/federation/etc"
cp "$CONFIGDIR/client.conf" "/usr/local/federation/etc"
chmod 644 "/usr/local/federation/etc/client.conf"

# Get our gateway, share, and mount user from the configuration file.
# There's probably a way to get all three at once, but this works.
GATEWAY=`$PERL -ne '/ControlGateway:\s+(.*)/i && print "$1\n";' $CONFIGDIR/client.conf`
SHARE=`$PERL -ne '/SMBShare:\s+(.*)/i && print "$1\n";' $CONFIGDIR/client.conf`
SMBUSER=`$PERL -ne '/ProjectUser:\s+(.*)/i && print "$1\n";' $CONFIGDIR/client.conf`
SMBPROJECT=`$PERL -ne '/ProjectName:\s+(.*)/i && print "$1\n";' $CONFIGDIR/client.conf`

# If this is empty confusion reigns.  Set a default.
if [ -z "$SHARE" ]; then
	SHARE="USERS"
fi

# XXX: modified seer daemon to read a config file.  Not in the tarfile yet.  If
# we see one, and there's a /usr/seer/backend/daemon.py, replace that one with
# the local one.
if [ -e /usr/seer/backend/daemon.py ] && [ -e $SCRIPTDIR/daemon.py ]; then
	/bin/cp $SCRIPTDIR/daemon.py /usr/seer/backend/daemon.py 
fi

if [ -e /usr/seer/backend/experiment-setup.py ] && [ -e $SCRIPTDIR/experiment-setup.py ]; then
	/bin/cp $SCRIPTDIR/experiment-setup.py /usr/seer/backend/experiment-setup.py 
fi

# Copy the seer.conf to the local /tmp if there is one

if [ -e $CONFIGDIR/seer.conf ]; then
	/bin/cp $CONFIGDIR/seer.conf /tmp
fi

while [ -z "$GWIP" ]; do
	GWIP=`host -N 10 $GATEWAY | $PERL -ne 's/.* has address // && print;'`
	echo "GWIP is $GWIP"
	sleep 10
done
# Copy the global hostnames file into /etc/hosts so this node can address
# others in the experiment on other testbeds.  The extra steps preserves teh
# localhost entry that's aliased to this host's name. 
grep 127\\.0\\.0\\.1 /etc/hosts > /tmp/hosts
cat "$CONFIGDIR/hosts" >> /tmp/hosts
# If there's no node in this experiment called control, fake one so
# that SEER events get through (if SEER's in use)
if ! grep -q control $CONFIGDIR/hosts; then
	echo "$GWIP	control.$EXP.$PROJECT" >> /tmp/hosts
fi
cp /tmp/hosts /etc/hosts && rm /tmp/hosts

# XXX:
# The standard emulab rc.accounts script won't replace existing user accounts
# with our new ones, so we have to patch it to do so.  This is obviously pretty
# fragile and needs to change.  To make matters worse, our FBSD62-SMB images
# contain the patched rc.accounts, so this patching step will fail there.

if [ -e /usr/local/federation/etc/rc.accounts.patch ]; then
	cd "$EMUDIR/rc"
	patch -f < /usr/local/federation/etc/rc.accounts.patch
	cd /tmp
fi

#
# Spin on our gateway!
#

echo "Waiting for the tunnel to come online."

for port in $PORTS
do
        until $NC -z $GATEWAY $port
        do
                sleep 5
        done
done

#
# Setup TMCC to use our gateway
#

echo "Configuring TMCC."
echo $GATEWAY > $BOSSNODE


#
# Unmount stuff before messing with accounts 
#

case `uname` in
	"FreeBSD")
		umount -A -f -t nfs,smbfs,cifs
		;;
	"Linux")
		# Linux doesn't believe in -A so pull the filesystems out of
		# /etc/mtab and umount them individually
		for f in `$PERL -nae 'print "$F[1]\n" if $F[2] =~ /(nfs|cifs|smbfs)/;' /etc/mtab`; do
			umount -f $f
		done
		;;
esac

#
# Setup new accounts
#

# Clear the cache, just in case:
rm -f /var/emulab/boot/tmcc/accounts

$RCDIR/rc.accounts reconfig

#
# Call the smbmount perl script, this invokes the automounter to mount the
# needed smb filesystems.
#
echo "Mounting via SMB."
$PERL "/usr/local/federation/bin/$SMBMOUNT" $SHARE $GATEWAY $SMBUSER $SMBPROJECT

echo "Restoring old bossnode"
# remove bossnode override
/bin/rm -f $BOSSNODE
# Also clear any cached data that might interfere with rourte construction.
/bin/rm -f /var/emulab/boot/tmcc/ifconfig

# I remain unclear why ospfd seems screwed up after the resetting of accounts
# and mounts.  This seems to fix it, but it's not very satisfying.  At this
# point the federated topology is complete, so any problems with routing in a
# partial topology -e.g. failed or partial bridging - that might have confused
# the router should be gone.
$PKILL ospf
$PKILL gated
# XXX Danger, hack ahead.  Apparently our FC6-SMB image and emulab disagree
# about where gated lives.  This will alias it.
if [ ! -x /usr/sbin/gated ] ; then 
	if [ -x /sbin/gated ] ; then
		ln /sbin/gated /usr/sbin/gated
	fi
fi
/usr/local/etc/emulab/rc/rc.route boot

# And restore the ifconfig information because SEER wants it. (SEER pulls this
# from tmcc now
# "$EMUDIR/tmcc" ifconfig > /var/emulab/boot/tmcc/ifconfig

# SEER feels pain and confusion if times are wrong.  This lays a big lick on
# ntp sets the time directly and then restarts it.  XXX FreeBSD incantation is
# untested.

case `uname` in 
	"FreeBSD")
		/etc/rc.d/ntpd stop
		/usr/sbin/ntpdate boss
		/etc/rc.d/ntpd start
		;;
	"Linux")
		/etc/rc.d/init.d/ntpd stop
		/usr/sbin/ntpdate boss
		/etc/rc.d/init.d/ntpd start
		;;
esac

# Execute any command passed in as a startcmd.  This basically daisy chains the
# startcmd.  This needs to become a perl script to have uniform behavior here.
echo "*$1* *$2*"
if [ ! -z "$1" ]; then 
	echo "calling *$1* *$2*"
	case `uname` in
		"FreeBSD")
			su -l "$1" -c "$2"
			;;
		"Linux")
			su "$1" --command="$2"
			;;
	esac
fi
