#!/bin/bash
#
# Copyright (C) 2012, Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#

# The script supports the plugins below
declare -a SUPPORTED_PLUGINS=(cisco linuxbridge nicira openvswitch ryu)

#
# Print --help output and exit.
#
usage() {

cat << EOF
The helper script will install the necessary database support for the selected plugin.
Please note that some plugins do not require database support. These are addressed in the script.
The setup of MySQL with a multi-server OpenStack installation is outside of the scope of 
this simple helper script.

Usage: quantum-server-setup [options]
Options:
	--help        | -h
		Print usage information.
        --qpw <pw>    | -q <pw>
                Specify the password for the 'quantum' MySQL user that quantum will
                use to connect to the 'quantum' MySQL database.  By default,
                the password 'quantum' will be used.

	--rootpw <pw> | -r <pw>
		Specify the root MySQL password.  If the script installs
		the MySQL server, it will set the root password to this value
		instead of prompting for a password.  If the MySQL server is
		already installed, this password will be used to connect to the
		database instead of having to prompt for it.
	--yes         | -y
		In cases where the script would normally ask for confirmation
		before doing something, such as installing mysql-server,
		just assume yes.  This is useful if you want to run the script
		non-interactively.
        --user        | -u
		The quantum user. 
        --plugin      | -p
                The quantum plugin. Supported plugins:-
                    ${SUPPORTED_PLUGINS[*]}
EOF

	exit 0
}

install_mysql_server() {
	if [ -z "${ASSUME_YES}" ] ; then
		yum install mysql-server
	else
		yum install -y mysql-server
	fi
}

start_mysql_server() {
	service mysqld start
}

is_valid_plugin() {
	local i=
	for i in "${SUPPORTED_PLUGINS[@]}"; do
		if [ "$i" == "$1" ]; then
			return 0 
		fi
	done
	return 1
}

ASSUME_YES=""
QUANTUM_USER=quantum
MYSQL_Q_PW=quantum
CISCO_CONF=/etc/quantum/plugins/cisco/db_conn.ini
Q_CONF=/etc/quantum/plugins.ini
LB_CONF=/etc/quantum/plugins/linuxbridge/linuxbridge_conf.ini
OVS_CONF=/etc/quantum/plugins/openvswitch/ovs_quantum_plugin.ini

# Nova specific
NOVA_CONF=/etc/nova/nova.conf
SCHEDULER_DRIVER=""
LIBVIRT_VIF_DRIVER=""
LIBVIRT_VIF_TYPE=""
LINUX_INTERFACE_DRIVER=""

while [ $# -gt 0 ]
do
	case "$1" in
		-h|--help)
			usage
			;;
		-q|--qpw)
			shift
			MYSQL_Q_PW==${1}
			;;
		-r|--rootpw)
			shift
			MYSQL_ROOT_PW=${1}
			;;
		-y|--yes)
			ASSUME_YES="yes"
			;;
                -u|--user)
                        shift
                        QUANTUM_USER=${1}
                        ;;
                -p|--plugin)
                        shift
                        QUANTUM_PLUGIN=${1}
                        ;;
		*)
			# ignore
			shift
			;;
	esac
	shift
done

# if the plugin is not defined
if [ -z ${QUANTUM_PLUGIN} ] ; then
        echo "Please select a plugin from: ${SUPPORTED_PLUGINS[*]}"
	echo "Choice:"
        read QUANTUM_PLUGIN
fi

# check that the plugin is valid
is_valid_plugin ${QUANTUM_PLUGIN}
if [ $? -ne 0 ]; then
	echo "Plugin '${QUANTUM_PLUGIN}' not supported. Supported plugins:-"
	echo "    ${SUPPORTED_PLUGINS[*]}"
	exit 0
fi

echo "Quantum plugin: ${QUANTUM_PLUGIN}"

if ! [ -e "${Q_CONF}" ]; then
	echo "Please install the quantum package"
	exit 0
fi

if ! [ -e "/etc/quantum/plugins/${QUANTUM_PLUGIN}" ]; then
	echo "Please install the ${QUANTUM_PLUGIN} quantum plugin"
        exit 0
fi

case "${QUANTUM_PLUGIN}" in
"cisco")
	DB_NAME="quantum_l2network"
	openstack-config --set ${Q_CONF} PLUGIN provider quantum.plugins.cisco.l2network_plugin.L2Network
;;

"linuxbridge")
	DB_NAME="quantum_linux_bridge"
	openstack-config --set ${Q_CONF} PLUGIN provider quantum.plugins.linuxbridge.LinuxBridgePlugin.LinuxBridgePlugin
;;

"nicira")
	openstack-config --set ${Q_CONF} PLUGIN provider quantum.plugins.nicira.nicira_nvp_plugin.QuantumPlugin.NvpPlugin
        echo "No database support"
        exit 0;
;;

"openvswitch")
	if ! rpm -q openvswitch > /dev/null 
	then
		echo "Please install openvswitch"
		exit 0
	fi
	DB_NAME="ovs_quantum"
	openstack-config --set ${Q_CONF} PLUGIN provider quantum.plugins.openvswitch.ovs_quantum_plugin.OVSQuantumPlugin
;;

"ryu")
	openstack-config --set ${Q_CONF} PLUGIN provider quantum.plugins.ryu.ryu_quantum_plugin.RyuQuantumPlugin
	echo "No database support required"
        exit 0;
;;

esac
echo "Plugin: ${QUANTUM_PLUGIN} => Database: ${DB_NAME}"

# Make sure MySQL is installed.

NEW_MYSQL_INSTALL=0
if ! rpm -q mysql-server > /dev/null
then
	if [ -z "${ASSUME_YES}" ] ; then
		printf "mysql-server is not installed.  Would you like to install it now? (y/n): "
		read response
		case "$response" in
			y|Y)
				;;
			n|N)
				echo "mysql-server must be installed.  Please install it before proceeding."
				exit 0
				;;
			*)
				echo "Invalid response."
				exit 1
		esac
	fi

	NEW_MYSQL_INSTALL=1
	install_mysql_server
fi


# Make sure mysqld is running.

if ! service mysqld status > /dev/null
then
	if [ -z "${ASSUME_YES}" ] ; then
		printf "mysqld is not running.  Would you like to start it now? (y/n): "
		read response
		case "$response" in
			y|Y)
				;;
			n|N)
				echo "mysqld must be running.  Please start it before proceeding."
				exit 0
				;;
			*)
				echo "Invalid response."
				exit 1
		esac
	fi

	start_mysql_server

	# If we both installed and started, ensure it starts at boot
	[ $NEW_MYSQL_INSTALL -eq 1 ] && chkconfig mysqld on
fi

# Get MySQL root access.
if [ $NEW_MYSQL_INSTALL -eq 1 ]
then
	if [ ! "${MYSQL_ROOT_PW+defined}" ] ; then
		echo "Since this is a fresh installation of MySQL, please set a password for the 'root' mysql user."

		PW_MATCH=0
		while [ $PW_MATCH -eq 0 ]
		do
			printf "Enter new password for 'root' mysql user: "
			read -s MYSQL_ROOT_PW
			echo
			printf "Enter new password again: "
			read -s PW2
			echo
			if [ "${MYSQL_ROOT_PW}" = "${PW2}" ] ; then
				PW_MATCH=1
			else
				echo "Passwords did not match."
			fi
		done
	fi

	echo "UPDATE mysql.user SET password = password('${MYSQL_ROOT_PW}') WHERE user = 'root'; DELETE FROM mysql.user WHERE user = ''; flush privileges;" | mysql -u root
	if ! [ $? -eq 0 ] ; then
		echo "Failed to set password for 'root' MySQL user."
		exit 1
	fi
elif [ ! "${MYSQL_ROOT_PW+defined}" ] ; then
	printf "Please enter the password for the 'root' MySQL user: "
	read -s MYSQL_ROOT_PW
	echo
fi

# Sanity check MySQL credentials.

MYSQL_ROOT_PW_ARG=""
if [ "${MYSQL_ROOT_PW+defined}" ]
then
	MYSQL_ROOT_PW_ARG="--password=${MYSQL_ROOT_PW}"
fi
echo "SELECT 1;" | mysql -u root ${MYSQL_ROOT_PW_ARG} > /dev/null
if ! [ $? -eq 0 ]
then
	echo "Failed to connect to the MySQL server.  Please check your root user credentials."
	exit 1
fi
echo "Verified connectivity to MySQL."

# Create a database user - check if it does not exist prior
USER_EXISTS=$(mysql -u root ${MYSQL_ROOT_PW_ARG} -e "SELECT user FROM mysql.user WHERE user='${QUANTUM_USER}'"|grep ${QUANTUM_USER} | wc -l)
if [ ${USER_EXISTS} -ne 0 ]; then
	echo "User ${QUANTUM_USER} already exists"
else
	mysql -u root ${MYSQL_ROOT_PW_ARG} -e "create user '${QUANTUM_USER}'@'%' identified by '${MYSQL_Q_PW}'"
	mysql -u root ${MYSQL_ROOT_PW_ARG} -e "create user '${QUANTUM_USER}'@'localhost' identified by '${MYSQL_Q_PW}'"
fi

#create database
DB_EXISTS=$(mysql -u root ${MYSQL_ROOT_PW_ARG} -e "show databases"|grep ${DB_NAME}| wc -l)
if [ ${DB_EXISTS} -ne 0 ]; then
	mysql -u root ${MYSQL_ROOT_PW_ARG} -e "drop database ${DB_NAME}"
fi
mysql -u root ${MYSQL_ROOT_PW_ARG} -e "create database ${DB_NAME}"

# Configure database specifics
case "${QUANTUM_PLUGIN}" in
"cisco")
        openstack-config --set ${CISCO_CONF} DATABASE user ${QUANTUM_USER}
        openstack-config --set ${CISCO_CONF} DATABASE pass ${MYSQL_Q_PW}
        openstack-config --set ${CISCO_CONF} DATABASE host `hostname`
 	SCHEDULER_DRIVER=quantum.plugins.cisco.nova.quantum_port_aware_scheduler.QuantumPortAwareScheduler
	LIBVIRT_VIF_DRIVER=quantum.plugins.cisco.nova.vifdirect.Libvirt802dot1QbhDriver
	LIBVIRT_VIF_TYPE=802.1Qbh
;;

"linuxbridge")
	mysql -u root ${MYSQL_ROOT_PW_ARG} -e "grant all on quantum_linux_bridge.* to '${QUANTUM_USER}'@'%'"
	mysql -u root ${MYSQL_ROOT_PW_ARG} -e "grant all on quantum_linux_bridge.* to '${QUANTUM_USER}'@'localhost'"
	openstack-config --set ${LB_CONF} DATABASE sql_connection mysql://${QUANTUM_USER}:${MYSQL_Q_PW}@`hostname`/quantum_linux_bridge
	
	echo "Please enter network device for VLAN trunking:"
	read NETWORK_DEVICE
        openstack-config --set ${LB_CONF} LINUX_BRIDGE physical_interface ${NETWORK_DEVICE}

	LIBVIRT_VIF_TYPE=ethernet
	LIBVIRT_VIF_DRIVER=nova.virt.libvirt.vif.QuantumLinuxBridgeVIFDriver
	LINUX_INTERFACE_DRIVER=nova.network.linux_net.QuantumLinuxBridgeInterfaceDriver
;;

"openvswitch")
	mysql -u root ${MYSQL_ROOT_PW_ARG} -e "grant all on ovs_quantum.* to '${QUANTUM_USER}'@'%'"
	mysql -u root ${MYSQL_ROOT_PW_ARG} -e "grant all on ovs_quantum.* to '${QUANTUM_USER}'@'localhost'"
        openstack-config --set ${OVS_CONF} DATABASE sql_connection mysql://${QUANTUM_USER}:${MYSQL_Q_PW}@`hostname`/ovs_quantum
	LIBVIRT_VIF_TYPE=ethernet
	LIBVIRT_VIF_DRIVER=nova.virt.libvirt.vif.LibvirtOpenVswitchDriver
	LINUX_INTERFACE_DRIVER=nova.network.linux_net.LinuxOVSInterfaceDriver
;;
esac

echo "Would you like to update the nova configuration files? (y/n): "
read response
case "$response" in
y|Y)
	;;
*)
	echo "Complete!"
	exit 0
esac

# If OpenStack is installed then configure nova.conf
if ! [ -e "${NOVA_CONF}" ]; then
        echo "Please install OpenStack compute and then set the values"
	echo "in /etc/nova/nova.conf DEFAULT section"
	echo "    network_manager=nova.network.quantum.manager.QuantumManager"
        echo "    quantum_connection_host=`hostname`"
        echo "    quantum_connection_port=9696"
        echo "    quantum_use_dhcp=True"
        echo "    scheduler_driver=${SCHEDULER_DRIVER}"
        echo "    libvirt_vif_driver=${LIBVIRT_VIF_DRIVER}"
        echo "    libvirt_vif_type=${LIBVIRT_VIF_TYPE}"
        echo "    linuxnet_interface_driver=${LINUX_INTERFACE_DRIVER}"
else
        openstack-config --set ${NOVA_CONF} DEFAULT network_manager nova.network.quantum.manager.QuantumManager
        openstack-config --set ${NOVA_CONF} DEFAULT quantum_connection_host `hostname`
        openstack-config --set ${NOVA_CONF} DEFAULT quantum_connection_port 9696
        openstack-config --set ${NOVA_CONF} DEFAULT quantum_use_dhcp True
        if [ ${SCHEDULER_DRIVER} ]; then
                openstack-config --set ${NOVA_CONF} DEFAULT scheduler_driver ${SCHEDULER_DRIVER}
        fi
        if [ ${LIBVIRT_VIF_DRIVER} ]; then
                openstack-config --set ${NOVA_CONF} DEFAULT libvirt_vif_driver ${LIBVIRT_VIF_DRIVER}
        fi
        if [ ${LIBVIRT_VIF_TYPE} ]; then
                openstack-config --set ${NOVA_CONF} DEFAULT libvirt_vif_type ${LIBVIRT_VIF_TYPE}
        fi
        if [ ${LINUX_INTERFACE_DRIVER} ]; then
                openstack-config --set ${NOVA_CONF} DEFAULT linuxnet_interface_driver ${LINUX_INTERFACE_DRIVER}
        fi
fi

echo "Configuration updates complete!"
