#!/bin/bash

# Script for setup intereface for internet connection
# v0.2.0 2012 Sergio Kviato sergey.kviato@onapp.com
#
# --add/del action to do, add or remove rule
# --int interface name
# --vlan vlan id if need
# --conf config file

### Setup ###
OVSVSCTL=$(whereis -b ovs-vsctl | awk '{print $2}')
OVSOFCTL=$(whereis -b ovs-ofctl | awk '{print $2}')
RUNPATH="/var/run/openvswitch"
OVSVSCTL="$OVSVSCTL --db=unix:$RUNPATH/db.sock"
SWITCH="onapp-ovs0"
INTERFACE=""
VLAN=""
ACTION=""
ADD=""
DEL=""
CONFIG="/etc/onapp.conf"
lock_file="/tmp/interface_run.lck"

# Public IP address to test route table
# by default one of Google public DNS
TEST_IP="8.8.8.8"

if [ -e $lock_file ] ; then
	# Assume 1 min old lock file as still working
	current_file=`find $lock_file -cmin -1`
	if [ -n "$current_file" ] ; then
		echo "Lock file found. Another copy of script is runing."
		echo "You cannot understand what will begin, if you write to file from"
		echo "two instances at the same time. You cannot bear to pay what it will cost you."
		exit 0
        else
		# Expired lock file found, remove old
		rm -f $lock_file
		# and recreate it again
		touch $lock_file
        fi

else
	touch $lock_file
fi

# Remove all temp files
trap "rm -f $lock_file; rm -f $CONFIG.tmp" 0 1 2 5 15

# In case it first run or just someone remove switch there no reson to run
if $OVSVSCTL br-exists $SWITCH; then
	:
else
	exit 0
fi

add_int() {
SWITCH=$1
INTERFACE=$2
VLAN=$3

	$OVSVSCTL -- --may-exist add-port $SWITCH $INTERFACE $VLAN
	sleep 1

	# Setup default rules
	PORT=$($OVSVSCTL -- get Interface $INTERFACE ofport)
	$OVSOFCTL add-flow $SWITCH "in_port=$PORT priority=1 action=normal"

}

del_int() {
SWITCH=$1
INTERFACE=$2
	
	PORT=$($OVSVSCTL -- get Interface $INTERFACE ofport)
	$OVSOFCTL del-flows $SWITCH "in_port=$PORT"
	$OVSVSCTL -- --if-exists del-port $SWITCH $INTERFACE
}

# Process command line arguments
for arg in {1..12}
do
    case "${!arg}" in
	"--del")
	DEL=1
	;;
	"--add")
	ADD=1
	;;
	"--int") 
	((argn=arg+1))
	INTERFACE=${!argn}
	;;
	"--vlan")
	((argn=arg+1))
	VLAN=${!argn}
	;;
	"--conf")
	((argn=arg+1))
	CONFIG=${!argn}
	;;
    esac
done

# Check interface wich we try to connect to bridge
# If we will connect systems default int, then all will go down
DEFROUTE=$(ip route get 8.8.8.8 | grep dev | awk '{print $5}')

if [ -e "$CONFIG" ] && [ -s "$CONFIG" ] && [ -f "$CONFIG" ]; then
:
else
	echo "I think we've got a problem. I need a working config file to proceed."
	echo "Possible problems: config file does not exists, empty or not regular file."
	exit 1
fi

# When passed options to command line, it indicate that we make changes in
# config file
if [ -n "$ADD" ]; then

	if /sbin/ifconfig -a | grep "^$INTERFACE " 1>/dev/null; then
		if [ -n "$VLAN" ]; then
    			if [ "$VLAN" -lt "0" ] || [ "$VLAN" -gt "4094" ]; then
    				echo "I think you make one of terrible mistakes."
    				echo "VLAN number can't be less than 1 or greater than 4094."
    				exit 1
    			fi
		fi
	# All seems to be fine, so lets add interface to config
	sed "/OVS_NETIF_NAMES/s/\"$/,$INTERFACE\ $VLAN\"/" $CONFIG > $CONFIG.tmp
	cat $CONFIG.tmp > $CONFIG

	else   
        	echo "Interface $INTERFACE may not exist on system"
        	exit 1
	fi

elif [ -n "$DEL" ]; then

	if grep OVS_NETIF_NAMES $CONFIG | grep "$INTERFACE" 1>/dev/null; then
		if [ -n "$VLAN" ]; then
    			if grep OVS_NETIF_NAMES $CONFIG | grep "$VLAN" 1>/dev/null; then
    				:
			else
				echo "VLAN number $VLAN may not exist on config"
    				exit 1
    			fi
		fi
	# All seems to be fine, so lets delete interface from config
	sed "/OVS_NETIF_NAMES/s/\s*,\s*/,/g;/OVS_NETIF_NAMES/s/\s*\"\s*/\"/g;/OVS_NETIF_NAMES/s/\,*$INTERFACE\s*$VLAN//g;/OVS_NETIF_NAMES/s/,*\",*/\"/g" $CONFIG > $CONFIG.tmp
	cat $CONFIG.tmp > $CONFIG

	else   
        	echo "Interface $INTERFACE may not exist on config"
        	exit 1
	fi
fi

# Read config
if [ -e "$CONFIG" ] && [ -s "$CONFIG" ] && [ -f "$CONFIG" ]; then
. $CONFIG
else
	echo "I think we've got a problem. Cant read config file."
	exit 1
fi

# Just remove all ports and flows, then add ports from config file
for port in $($OVSVSCTL list-ports $SWITCH); do
        del_int $SWITCH $port
done

# Now parse config file, and apply all acceptable information
interfaces=$(echo $OVS_NETIF_NAMES | sed 's/\s*,\s*/,/g;s/\s*"\s*/"/g;s/\s/\./g;s/,/\ /g')
for int in $interfaces; do

	INTERFACE=`echo $int | awk -F\. '{print $1}'`
	VLAN=`echo $int | awk -F\. '{print $2}'`

	if /sbin/ifconfig -a | grep "^$INTERFACE " 1>/dev/null; then
        	:
	else   
        	echo "Interface $INTERFACE may not exist on system"
        	continue
	fi

	if [ -n "$VLAN" ]; then
		if [ "$VLAN" -lt "1" ] || [ "$VLAN" -gt "4094" ]; then
			echo "I think you make one of terrible mistakes."
			echo "VLAN number can't be less than 1 or greater than 4094."
			continue
		fi

#    if [ "$DEFROUTE" == "$INTERFACE" ]; then
    #You try to connect default system interface to bridge.
    # Okey, we can use OVS to setup VLAN on primary interface.
    # But this kind of operation rather different.
    # We need to use bridge as primary interface for internet routing.
    # Otherwise HV will stop respond by network.
    # Its nice story, but quite easy use vconfig for this task.
    #ip /sbin/ifconfig | grep "inet addr:" | awk '{ print $2}' | cut -c 6-
    #mask /sbin/ifconfig | grep "inet addr:" | awk '{ print $4}' | cut -c 6-
	if /sbin/ifconfig -a | grep "$INTERFACE.$VLAN " 1>/dev/null; then
    		:
	else
		/sbin/vconfig add $INTERFACE $VLAN > /dev/null 2>&1
		sleep 1
	fi
    
	/sbin/ifconfig $INTERFACE.$VLAN up > /dev/null 2>&1
	INTERFACE="$INTERFACE.$VLAN"
	VLAN=""
    
#    else
#    VLAN="tag=$VLAN"
#    fi
	else
		if [ "$DEFROUTE" = "$INTERFACE" ]; then
			echo "You try to connect default system interface to bridge with no VLAN."
			echo "You're going to find that rather difficult. If you do so, HV will stop respond by network."
			exit 1
		fi
	fi

	# After all checks, add interface to switch, at last.
	add_int $SWITCH $INTERFACE $VLAN
done

exit 0


