#!/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=(linuxbridge openvswitch)

#
# 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
Q_CONF=/etc/quantum/quantum.conf
Q_API_PASTE=/etc/quantum/api-paste.ini
LB_CONF=/etc/quantum/plugins/linuxbridge/linuxbridge_conf.ini
OVS_CONF=/etc/quantum/plugins/openvswitch/ovs_quantum_plugin.ini
Q_HOST='localhost'
Q_PORT=9696

# Keystone specific
OS_USERNAME=${OS_USERNAME:-quantum}
OS_PASSWORD=${OS_PASSWORD:-servicepass}
OS_AUTH_URL=${OS_AUTH_URL:-http://127.0.0.1:35357/v2.0/}
OS_TENANT_NAME=${OS_TENANT_NAME:-service}

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

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
"linuxbridge")
	DB_NAME="quantum_linux_bridge"
        Q_PLUGIN_CLASS="quantum.plugins.linuxbridge.lb_quantum_plugin.LinuxBridgePluginV2"
;;

"openvswitch")
	if ! rpm -q openvswitch > /dev/null 
	then
		echo "Please install openvswitch"
		exit 0
	fi
	DB_NAME="ovs_quantum"
        Q_PLUGIN_CLASS="quantum.plugins.openvswitch.ovs_quantum_plugin.OVSQuantumPluginV2"
;;
esac

# Update quantum.conf
# Plugin
openstack-config --set ${Q_CONF} DEFAULT core_plugin $Q_PLUGIN_CLASS
# QPID
openstack-config --set ${Q_CONF} DEFAULT rpc_backend quantum.openstack.common.rpc.impl_qpid
openstack-config --set ${Q_CONF} DEFAULT qpid_hostname localhost
# Authentication
openstack-config --set ${Q_CONF} DEFAULT auth_strategy keystone

openstack-config --del ${Q_API_PASTE} filter:authtoken admin_tenant_name
openstack-config --del ${Q_API_PASTE} filter:authtoken admin_user
openstack-config --del ${Q_API_PASTE} filter:authtoken admin_password

openstack-config --set ${Q_API_PASTE} filter:authtoken admin_tenant_name ${OS_TENANT_NAME}
openstack-config --set ${Q_API_PASTE} filter:authtoken admin_user ${OS_USERNAME}
openstack-config --set ${Q_API_PASTE} filter:authtoken admin_password ${OS_PASSWORD}

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
"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_DRIVER=nova.virt.libvirt.vif.QuantumLinuxBridgeVIFDriver
	rm -f /etc/quantum/plugin.ini
	ln -s ${LB_CONF} /etc/quantum/plugin.ini
;;

"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_DRIVER=nova.virt.libvirt.vif.LibvirtHybridOVSBridgeDriver
	rm -f /etc/quantum/plugin.ini
	ln -s ${OVS_CONF} /etc/quantum/plugin.ini
;;
esac

if [ -z "${ASSUME_YES}" ] ; then
    echo "Would you like to update the nova configuration files? (y/n): "
    read response
    case "$response" in
    y|Y)
    	;;
    *)
    	echo "Complete!"
    	exit 0
    esac
fi

# 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_api_classi=nova.network.quantumv2.api.API"
        echo "    quantum_admin_username=${OS_USERNAME}"
        echo "    quantum_admin_password=${OS_PASSWORD}"
        echo "    quantum_admin_auth_url=${OS_AUTH_URL}"
        echo "    quantum_auth_strategy=keystone"
        echo "    quantum_admin_tenant_name=${OS_TENANT_NAME}"
        echo "    quantum_url=http://${Q_HOST}:${Q_PORT}/"
        echo "    libvirt_vif_driver=${LIBVIRT_VIF_DRIVER}"
else
        openstack-config --set ${NOVA_CONF} DEFAULT network_api_class nova.network.quantumv2.api.API
        openstack-config --set ${NOVA_CONF} DEFAULT quantum_admin_username ${OS_USERNAME}
        openstack-config --set ${NOVA_CONF} DEFAULT quantum_admin_password ${OS_PASSWORD}
        openstack-config --set ${NOVA_CONF} DEFAULT quantum_admin_auth_url ${OS_AUTH_URL}
        openstack-config --set ${NOVA_CONF} DEFAULT quantum_auth_strategy keystone 
        openstack-config --set ${NOVA_CONF} DEFAULT quantum_admin_tenant_name ${OS_TENANT_NAME}
        openstack-config --set ${NOVA_CONF} DEFAULT quantum_url http://${Q_HOST}:${Q_PORT}/
        openstack-config --set ${NOVA_CONF} DEFAULT libvirt_vif_driver ${LIBVIRT_VIF_DRIVER}
fi

echo "Configuration updates complete!"
