#!/bin/sh
# -*- mode: shell-script -*-

pkgos_gen_pass () {
	i=$(dd if=/dev/random bs=64 count=1 2>|/dev/null | md5sum)
	echo ${i% *}
}

# This function removes a section, because we need that in the case
# of an upgrade from one version to the next. It is for example
# needed for keystone to upgrade from Grizzly to Havana.
# Params:
#    $1 Init file path
#    $2 Section to remove
pkgos_remove_section () {
	local REMOVESEC_INIFILE REMOVESEC_SEARCH_SECTION REMOVESEC_INIFILE_CNT REMOVESEC_LINE REMOVESEC_FOUND_SECTION REMOVESEC_START_LINE REMOVESEC_END_LINE
	REMOVESEC_INIFILE=${1}
	REMOVESEC_SEARCH_SECTION=${2}
	if [ ! -r ${REMOVESEC_INIFILE} ] ; then return ; fi

	# Iterate through all lines of the file to search for section start/end line number
	REMOVESEC_INIFILE_CNT=0
	REMOVESEC_FOUND_SECTION=""
	REMOVESEC_START_LINE=""
	REMOVESEC_END_LINE=""
	while read REMOVESEC_LINE ; do
		REMOVESEC_INIFILE_CNT=$((${REMOVESEC_INIFILE_CNT} + 1 ))
		if echo ${REMOVESEC_LINE} | grep -q '^[ \t]*\[.*\][ \t]*$' ; then
			REMOVESEC_FOUND_SECTION=`echo ${REMOVESEC_LINE} | sed -e 's/\[//' | sed -e 's/\]//'`
			echo "Found section: ${REMOVESEC_FOUND_SECTION}"
			if [ "${REMOVESEC_FOUND_SECTION}" = "${REMOVESEC_SEARCH_SECTION}" ] ; then
				REMOVESEC_START_LINE=$(( ${REMOVESEC_INIFILE_CNT} - 1 ))
			else
				if [ -n "${REMOVESEC_START_LINE}" ] && [ -z "${REMOVESEC_END_LINE}" ] ; then
					REMOVESEC_END_LINE=$(( ${REMOVESEC_INIFILE_CNT} -1 ))
				fi
			fi
		fi
	done < ${REMOVESEC_INIFILE}


	# Case where the section is last in the file
	if [ -n "${REMOVESEC_START_LINE}" ] && [ -z "${REMOVESEC_END_LINE}" ] ; then
		REMOVESEC_END_LINE=${REMOVESEC_INIFILE_CNT}
	fi

	# Section found, remove it!
	if [ -n "${REMOVESEC_START_LINE}" ] && [ -n "${REMOVESEC_END_LINE}" ] ; then
		REMOVESEC_CONF_LINES_NUM=`wc -l ${REMOVESEC_INIFILE} | cut -d" " -f1`
		REMOVESEC_CUT_END=$((${REMOVESEC_CONF_LINES_NUM} - ${REMOVESEC_END_LINE} ))
		REMOVESEC_TMPFILE=`mktemp -t pkgos_removesec.XXXXXX`
		head -n ${REMOVESEC_START_LINE} ${REMOVESEC_INIFILE} >${REMOVESEC_TMPFILE}
		tail -n ${REMOVESEC_CUT_END} ${REMOVESEC_INIFILE} >>${REMOVESEC_TMPFILE}
		cat <${REMOVESEC_TMPFILE} >${REMOVESEC_INIFILE}
		rm ${REMOVESEC_TMPFILE}
	fi
}

# Using sed to set passwords with arguments on the command line makes
# it possible to see the new passwords using ps. This function creates
# a temp file which is used as a script for sed (using the -f option).
# This is safe because what's put in the file is done with echo, which
# is a built-in shell command, so it will not appear in /proc.
# Params:
#    $1 Sed script to replace values in a config file
#    $2 Config file to change
pkgos_safesed () {
	local SAFESED_SCRIPT SAFESED_CONFIG_FILENAME SAFESED_TMPFILE
	SAFESED_SCRIPT=${1}
	SAFESED_CONFIG_FILENAME=${2}

	SAFESED_TMPFILE=`mktemp -t pkgos_safe_sed.XXXXXX`
	echo "${SAFESED_SCRIPT}" >${SAFESED_TMPFILE}
	sed -i -f ${SAFESED_TMPFILE} ${SAFESED_CONFIG_FILENAME}
	rm ${SAFESED_TMPFILE}
}

# Params: $1 = set or get (set means read mode and return a directive value, get means write a new value in it)
#         $2 = config file path (example: /etc/nova/nova.conf)
#         $3 = .ini file section (example: DEFAULT)
#         $4 = directive name (example: sql_connection)
#         $5 = only present in "set" mode: new value to replace in the .ini file
# Note that if $3 = NO_SECTION, then get or set mode will not manage sections at all,
# and will totally ignore the sections in the .ini file.
#
# Example (get the value of keystone hostname in your Nova box):
# parse_ini_file /etc/nova/api-paste.ini filter:authtoken auth_host
#
# Returns: $RET: either NOT_FOUND, or the (previous, in the case of set) value of the searched directive
pkgos_inifile () {
	local INIFILE_SHELL_INCLUDE INIFILE_ACCESS_MODE INIFILE_MYCONFIG INIFILE_SEARCH_SECTION SEARCH_DIRECTIVE INIFILE_CNT INIFILE_DIRECTIVE INIFILE_VALUE INIFILE_SECTION INIFILE_LINE DIRECTIVE_TYPE INIFILE_NEW_VALUE
	if [ "${1}" = "-shinc" ] ; then
		INIFILE_SHELL_INCLUDE=yes
		shift
	else
		INIFILE_SHELL_INCLUDE=no
	fi
	INIFILE_ACCESS_MODE=${1} ; INIFILE_MYCONFIG=${2} ; INIFILE_SEARCH_SECTION=${3} ; SEARCH_DIRECTIVE=${4}
	if [ "${PKGOS_VERBOSE}" = "yes" ] ; then
		if [ "x${INIFILE_ACCESS_MODE}" = "xset" ] ; then
			echo "pkgos_inifile: Setting value in ${INIFILE_MYCONFIG}:[${INIFILE_SEARCH_SECTION}]/${SEARCH_DIRECTIVE}"
		else
			echo "pkgos_inifile: Getting value in ${INIFILE_MYCONFIG}:[${INIFILE_SEARCH_SECTION}]/${SEARCH_DIRECTIVE}"
		fi
	fi
	if [ "x${INIFILE_ACCESS_MODE}" = "xset" ] ; then INIFILE_NEW_VALUE=${5} ; else INIFILE_NEW_VALUE="pkgos_inifile_function_called_with_wrong_access_mode" ; fi

	INIFILE_CNT=0
	RET=NOT_FOUND
	if [ ! -r "${INIFILE_MYCONFIG}" ] ; then
		if [ "${PKGOS_VERBOSE}" = "yes" ] ; then echo "Config file ${INIFILE_MYCONFIG} not readable: exiting" ; fi
		return
	fi

	# Iterate through all lines of the file
	while read INIFILE_LINE ; do
		INIFILE_CNT=$((${INIFILE_CNT} + 1 ))
		# This is a section block: [DEFAULT]
		if echo ${INIFILE_LINE} | grep -q '^[ \t]*\[.*\][ \t]*$' ; then
			if [ ! "${INIFILE_SEARCH_SECTION}" = "NO_SECTION" ] ; then
				INIFILE_SECTION=`echo ${INIFILE_LINE} | sed -e 's/\[//' -e 's/\]//'`
				#echo "===> $INIFILE_SECTION"
			fi
			continue
		fi
		# If we aren't in the section we're searching for, let's end things here for this line
		if ! [ "${INIFILE_SECTION}" = "${INIFILE_SEARCH_SECTION}" ] ; then
			continue
		fi
		# This is a directive: auth_host = 127.0.0.1
		if echo ${INIFILE_LINE} | grep -q '^[;#]*[ \t]*[\._\/a-zA-Z0-9]*[ \t]*[=\:][ \t]*' ; then
			# This is a commented out directive, let's remove the comment
			# if there's no such active directive in the file
			if grep -q '^[#;][ \t]*[\._\/a-zA-Z0-9]*[ \t]*[=\:][ \t]*' ${INIFILE_MYCONFIG} ; then
				if echo ${INIFILE_LINE} | grep -q '^[#;][ \t]*'${SEARCH_DIRECTIVE}'[ \t]*[=\:][ \t]*' ; then
					INIFILE_LINE=`echo ${INIFILE_LINE} | sed -e 's/^#//'`
				fi
			fi
			# This is a directive which uses the equal sign (directive = value)
			if echo ${INIFILE_LINE} | grep -q '^[ \t]*[\._\/a-zA-Z0-9]*[ \t]*=[ \t]*' ; then
				INIFILE_DIRECTIVE=`echo ${INIFILE_LINE} | cut -d= -f1 | awk '{print $1}'`
				DIRECTIVE_TYPE="equal"
				INIFILE_VALUE=`echo ${INIFILE_LINE} | cut -d= -f2 | sed -e 's/^[ \t]//'`
				#echo ${INIFILE_DIRECTIVE}=${INIFILE_VALUE}
			# This one uses the semi-column sign (/directive: value)
			else
				INIFILE_DIRECTIVE=`echo ${INIFILE_LINE} | cut -d':' -f1 | awk '{print $1}'`
				DIRECTIVE_TYPE="dots"
				INIFILE_VALUE=`echo ${INIFILE_LINE} | cut -d':' -f2 | sed -e 's/^[ \t]//'`
				#echo ${INIFILE_DIRECTIVE}: ${INIFILE_VALUE}
			fi
			if [ "${INIFILE_SECTION}" = "${INIFILE_SEARCH_SECTION}" ] && [ "${INIFILE_DIRECTIVE}" = "${SEARCH_DIRECTIVE}" ] ; then
				RET=${INIFILE_VALUE}
				if [ "x${INIFILE_ACCESS_MODE}" = "xset" ] ; then
					if [ "${DIRECTIVE_TYPE}" = "equal" ] ; then
						if [ "${INIFILE_SHELL_INCLUDE}" = "yes" ] ; then
							pkgos_safesed ${INIFILE_CNT}' s|.*|'${INIFILE_DIRECTIVE}'='${INIFILE_NEW_VALUE}'|' ${INIFILE_MYCONFIG}
						else
							pkgos_safesed ${INIFILE_CNT}' s|.*|'${INIFILE_DIRECTIVE}' = '${INIFILE_NEW_VALUE}'|' ${INIFILE_MYCONFIG}
						fi
					else
						pkgos_safesed ${INIFILE_CNT}' s|.*|'${INIFILE_DIRECTIVE}': '${INIFILE_NEW_VALUE}'|' ${INIFILE_MYCONFIG}
					fi
				fi
				return
			fi
		# This is a comment block
		elif echo $INIFILE_LINE | grep -q '^[ \t]*#.*$' ; then
			echo -n ""
		fi
	done < ${INIFILE_MYCONFIG}
}

# Read the value of a directive in a config file,
# then prompt the user about it.
# Example (options in this order please...):
# pkgos_read_config -p medium /etc/keystone/keystone.conf auth_token keystone/auth-token DEFAULT
# To be used in: config
pkgos_read_config () {
	local READ_CONFIG_DIRECTIVE CONF_PATH READ_CONFIG_DEBCONF_NAME READ_CONFIG_SECTION FSET_SEEN READ_CONFIG_MY_PRIORITY
	if [ "${1}" = "-p" ] ; then
		READ_CONFIG_MY_PRIORITY=${2}
		shift
		shift
	else
		READ_CONFIG_MY_PRIORITY=high
	fi
	CONF_PATH=${1}
	READ_CONFIG_SECTION=${2}
	READ_CONFIG_DIRECTIVE=${3}
	READ_CONFIG_DEBCONF_NAME=${4}

	pkgos_inifile get ${CONF_PATH} ${READ_CONFIG_SECTION} ${READ_CONFIG_DIRECTIVE}
	if [ -n "${RET}" ] && [ ! "${RET}" = "NOT_FOUND" ] ; then
		db_set ${READ_CONFIG_DEBCONF_NAME} ${RET}
	fi
	db_input ${READ_CONFIG_MY_PRIORITY} ${READ_CONFIG_DEBCONF_NAME} || true
	db_go
	db_get ${READ_CONFIG_DEBCONF_NAME}
}

# Read the current configuration for rabbitMQ and sets that into debconf
# Params: $1 Path to config file
#         $2 Section in the config file
#         $3 prefix for the debconf template (eg: if we have nova/rabbit_host, then use "nova")
# To be used in: config
# Example call: pkgos_rabbit_read_conf /etc/nova/nova.conf DEFAULT nova
pkgos_rabbit_read_conf () {
	local RB_CONF_PATH RB_SECTION RB_DEBCONF_PREFIX
	RB_CONF_PATH=${1}
	RB_SECTION=${2}
	RB_DEBCONF_PREFIX=${3}

	pkgos_read_config ${RB_CONF_PATH} ${RB_SECTION} rabbit_host ${RB_DEBCONF_PREFIX}/rabbit_host
	pkgos_read_config ${RB_CONF_PATH} ${RB_SECTION} rabbit_userid ${RB_DEBCONF_PREFIX}/rabbit_userid
	pkgos_read_config ${RB_CONF_PATH} ${RB_SECTION} rabbit_password ${RB_DEBCONF_PREFIX}/rabbit_password
}

# Write the configuration for rabbitMQ
# Params: $1 Path to config file
#         $2 Section in the config file
#         $3 prefix for the debconf template (eg: if we have nova/rabbit_host, then use "nova")
# To be used in: postinst
# Example call: pkgos_rabbit_write_conf /etc/nova/nova.conf DEFAULT nova
pkgos_rabbit_write_conf () {
	local RB_CONF_PATH RB_SECTION RB_DEBCONF_PREFIX
	RB_CONF_PATH=${1}
	RB_SECTION=${2}
	RB_DEBCONF_PREFIX=${3}

	db_get ${RB_DEBCONF_PREFIX}/rabbit_host
	pkgos_inifile set ${RB_CONF_PATH} ${RB_SECTION} rabbit_host ${RET}

	db_get ${RB_DEBCONF_PREFIX}/rabbit_userid
	pkgos_inifile set ${RB_CONF_PATH} ${RB_SECTION} rabbit_userid ${RET}

	db_get ${RB_DEBCONF_PREFIX}/rabbit_password
	pkgos_inifile set ${RB_CONF_PATH} ${RB_SECTION} rabbit_password ${RET}
}

# Read the connection directive from a config file
# and fills the dbc_* variable accordingly,
# then call dbconfig to do the actual configuration.
# To be used in: config
# Example call: pkgos_dbc_read_conf -pkg glance-common /etc/glance/glance-registry.conf glance DEFAULT sql_connection $@
pkgos_dbc_read_conf () {
	local ADDR BEFORE_AT AFTER_AT SERVER_PORT CONN_STRING PKG_NAME CONF_PATH PARSED_DB_TYPE PARSED_USER PARSED_PASS PARSED_DB_NAME PARSED_SERVER PARSED_PORT
	# This works around a bug in either dpkg, apt or debconf: in fact,
	# likely in debconf, the variable DPKG_MAINTSCRIPT_PACKAGE isn't
	# always set as it should.
	if [ "${1}" = "-pkg" ] ; then
		if [ -z "${DPKG_MAINTSCRIPT_PACKAGE}" ] ; then
			DPKG_MAINTSCRIPT_PACKAGE=$2
		fi
		shift
		shift
	fi
	CONF_PATH=${1}
	CONN_SECTION=${2}
	CONN_DIRECTIVE=${3}
	PKG_NAME=${4}
	# Do not remove what's bellow.
	# We need to shift, because we're using $@ in the dbc_go call later
	shift
	shift
	shift
	shift

	db_input high ${PKG_NAME}/configure_db || true
	db_go || true
	db_get ${PKG_NAME}/configure_db

	DEFAULT_DBNAME=$(echo ${PKG_NAME}db | sed s/-//g)
	if [ "$RET" = "true" ] && [ -f /usr/share/dbconfig-common/dpkg/config ] ; then
		. /usr/share/dbconfig-common/dpkg/config
		if [ -e "${CONF_PATH}" ] ; then
			pkgos_inifile get ${CONF_PATH} ${CONN_SECTION} ${CONN_DIRECTIVE}
			if [ -n "${RET}" ] && [ ! "${RET}" = "NOT_FOUND" ] ; then
				CONN_STRING=${RET}
			fi
		else
			CONN_STRING=""
		fi
		PARSED_DB_TYPE=${CONN_STRING%%:*}
		# If we have an undefined SQL type, we go back to a more sane default (eg: SQLite)
		case "${PARSED_DB_TYPE}" in
			"mysql+pymysql")
				PARSED_DB_TYPE=mysql
				;;
			sqlite|mysql|pgsql)
				;;
			postgresql*)
				PARSED_DB_TYPE=pgsql
				;;
			*)
				CONN_STRING="sqlite:///var/lib/${PKG_NAME}/${DEFAULT_DBNAME}"
				PARSED_DB_TYPE="sqlite"
				;;
		esac
		if [ "${PARSED_DB_TYPE}" = "sqlite" ] ; then
			if [ "${CONN_STRING}" = "sqlite:///${PKG_NAME}.db" ] ; then
				CONN_STRING="sqlite:///var/lib/${PKG_NAME}/${DEFAULT_DBNAME}"
			fi
			PARSED_DB_PATH=${CONN_STRING#sqlite://}
			if [ -z "${PARSED_DB_PATH}" ] ; then
				PARSED_DB_PATH=/var/lib/${PKG_NAME}/${DEFAULT_DBNAME}
			fi
			dbc_basepath=`dirname "${PARSED_DB_PATH}"`
			dbc_dbname=`basename "${PARSED_DB_PATH}"`
			dbc_dbtypes="sqlite3, mysql, pgsql"
		else
			ADDR=${CONN_STRING#*sql://}
			BEFORE_AT=${ADDR%%@*}
			AFTER_AT=${ADDR#*@}
			SERVER_PORT=${AFTER_AT%%/*}

			PARSED_USER=${BEFORE_AT%%:*}
			PARSED_PASS=${BEFORE_AT#*:}
			PARSED_DB_NAME=${AFTER_AT#*/}
			PARSED_SERVER=${SERVER_PORT%%:*}
			case "${SERVER_PORT}" in
			*:*)
				PARSED_PORT=${SERVER_PORT#*:}
				;;
			*)
				PARSED_PORT=""
				;;
			esac
			if [ -n "${PARSED_USER}" ] && [ -n "${PARSED_PASS}" ] && [ -n "${PARSED_SERVER}" ] && [ -n "${PARSED_DB_NAME}" ] ; then
				dbc_dbuser=${PARSED_USER}
				dbc_dbpass=${PARSED_PASS}
				dbc_dbserver=${PARSED_SERVER}
				dbc_dbport=${PARSED_PORT}
				dbc_dbname=${PARSED_DB_NAME}
			fi
			if [ "${PARSED_DB_TYPE}" = "mysql" ] ; then
				dbc_dbtypes="mysql, pgsql, sqlite3"
			else
				dbc_dbtypes="pgsql, mysql, sqlite3"
			fi
			dbc_authmethod_user="password"
		fi
		dbc_mysql_createdb_encoding="UTF8"
		dbc_pgsql_createdb_encoding="UTF8"
		echo "PKG-Openstack now calling: dbc_go "${DPKG_MAINTSCRIPT_PACKAGE} $@
		dbc_go "${DPKG_MAINTSCRIPT_PACKAGE}" $@
	fi
}

# Perform a MySQL query in a safe way (eg: no password or queries in the command line)
pkgos_mysql_query () {
	local MYSQL_Q_TMP MYSQL_P_TMP MYSQL_DBUSER MYSQL_DBPASS MYSQL_DBHOST MYSQL_DBPORT MYSQL_DBNAME MYSQL_QUERY MY_PORT
	MYSQL_DBUSER=${1}
	MYSQL_DBPASS=${2}
	MYSQL_DBHOST=${3}
	MYSQL_DBPORT=${4}
	MYSQL_DBNAME=${5}
	MYSQL_QUERY=${6}

	MYSQL_P_TMP=`mktemp -t OpenStack-mysql-statement.XXXXXXXXXX`
	MYSQL_Q_TMP=`mktemp -t OpenStack-mysql-statement.XXXXXXXXXX`
	echo "[client]
password=${MYSQL_DBPASS}" >${MYSQL_P_TMP}
	echo ${MYSQL_QUERY} >${MYSQL_Q_TMP}
	if [ -n "${MYSQL_DBPORT}" ] ; then
		MY_PORT="--port=${MYSQL_DBPORT}"
	fi
	mysql --defaults-file=${MYSQL_P_TMP} -h${MYSQL_DBHOST} ${MY_PORT} -u${MYSQL_DBUSER} -D${MYSQL_DBNAME} < ${MYSQL_Q_TMP}
	rm -f ${MYSQL_Q_TMP} ${MYSQL_P_TMP}
}


# Read values configured by dbconfig-common,
# and set a connection directive accordingly
# in a configuration file
#
# Caller should use something like this:
# pkgos_dbc_postinst /etc/keystone/keystone.conf keystone connection $@
# since dbc_go expect $@ as well.
pkgos_dbc_postinst () {
	local DBC_POST_CONF_PATH CONF_DIR DBC_POST_CONF_FNAME PKG_NAME SUITE
	if [ "${1}" = "--suite" ] ; then
		SUITE=${2}
		shift
		shift
	else
		SUITE=${4}
	fi
	DBC_POST_CONF_PATH=${1}
	CONN_SECTION=${2}
	CONN_DIRECTIVE=${3}
	PKG_NAME=${4}
	shift
	shift
	shift
	shift

	CONF_DIR=`dirname ${DBC_POST_CONF_PATH}`
	DBC_POST_CONF_FNAME=`basename ${DBC_POST_CONF_PATH}`

	# Create config files if they don't exist
	if [ ! -d ${CONF_DIR} ] ; then
		mkdir -p ${CONF_DIR}
	fi
	chmod 0770 ${CONF_DIR}
	chown ${SUITE}:${SUITE} ${CONF_DIR}
	if [ ! -e ${DBC_POST_CONF_PATH} ] ; then
		install -D -m 0660 -o ${SUITE} -g ${SUITE} /usr/share/${DPKG_MAINTSCRIPT_PACKAGE}/${DBC_POST_CONF_FNAME} ${DBC_POST_CONF_PATH}
	fi
	db_get ${PKG_NAME}/configure_db
	if [ "$RET" = "true" ] && [ -r /usr/share/dbconfig-common/dpkg/postinst ] ; then
		. /usr/share/dbconfig-common/dpkg/postinst
		dbc_dbfile_owner="${SUITE}:${SUITE}"
		dbc_mysql_createdb_encoding="UTF8"
		dbc_pgsql_createdb_encoding="UTF8"
		dbc_go "${DPKG_MAINTSCRIPT_PACKAGE}" $@
		if [ "$dbc_install" = "true" ] ; then
			case "$dbc_dbtype" in
				mysql)
					if [ -n "$dbc_dbport" ] ; then
						dbport=:$dbc_dbport
					fi
					SQL_CONNECTION="mysql+pymysql://$dbc_dbuser:$dbc_dbpass@${dbc_dbserver:-localhost}$dbport/$dbc_dbname"
					# Set the DB as UTF8
					Q="ALTER DATABASE \`${dbc_dbname}\` CHARACTER SET utf8 COLLATE utf8_unicode_ci"
					pkgos_mysql_query ${dbc_dbuser} ${dbc_dbpass} ${dbc_dbserver:-localhost} "${dbc_dbport}" ${dbc_dbname} "${Q}"
					;;
				postgresql*|pgsql)
					if [ -n "$dbc_dbport" ] ; then
						dbport=:$dbc_dbport
					fi
					SQL_CONNECTION="postgresql://$dbc_dbuser:$dbc_dbpass@${dbc_dbserver:-localhost}$dbport/$dbc_dbname"
					;;
				*)
					SQL_CONNECTION="sqlite:///$dbc_basepath/$dbc_dbname"
					;;
			esac
			pkgos_inifile set ${DBC_POST_CONF_PATH} ${CONN_SECTION} ${CONN_DIRECTIVE} ${SQL_CONNECTION}
		fi
	fi
}

# Reads auth_host, admin_tenant_name, admin_user and admin_password
# values with debconf
# Prototype: pkgos_read_admin_creds <conf-file> <PKG_NAME> <section>
# Example calls:
# pkgos_read_admin_creds /etc/glance/glance-api.conf glance keystone_authtoken
# To be used in: config
pkgos_read_admin_creds () {
	local READ_ADMIN_CRED_CONF_FNAME READ_ADMIN_CRED_PKG_NAME READ_ADMIN_CRED_SEARCH_SECTION
	READ_ADMIN_CRED_CONF_FNAME=${1}
	READ_ADMIN_CRED_SEARCH_SECTION=${2}
	READ_ADMIN_CRED_PKG_NAME=${3}

	if [ ! -r "${READ_ADMIN_CRED_CONF_FNAME}" ] ; then
		# If the file doesn't exist, just ask...
		db_input high ${READ_ADMIN_CRED_PKG_NAME}/auth-host || true
	else
		if grep -q auth_host ${READ_ADMIN_CRED_CONF_FNAME} ; then
			pkgos_read_config ${READ_ADMIN_CRED_CONF_FNAME} ${READ_ADMIN_CRED_SEARCH_SECTION} auth_host ${READ_ADMIN_CRED_PKG_NAME}/auth-host
		else
			# This is needed for l3_agent.ini
			if grep -q auth_url ${READ_ADMIN_CRED_CONF_FNAME} ; then
				pkgos_inifile get ${READ_ADMIN_CRED_CONF_FNAME} ${READ_ADMIN_CRED_SEARCH_SECTION} auth_url
				if [ -n "${RET}" ] && [ ! "${RET}" = "NOT_FOUND" ] ; then
					NO_PROTO=${RET#http://}
					if [ ${NO_PROTO} = ${RET} ] ; then
						NO_PROTO=${RET#https://}
					fi
					BEFORE_PORT=$(echo ${NO_PROTO} | cut -d":" -f1)
					if [ -n "${BEFORE_PORT}" ] ; then
						db_set ${READ_ADMIN_CRED_PKG_NAME}/auth-host ${BEFORE_PORT}
					fi
				fi
				db_input high ${READ_ADMIN_CRED_PKG_NAME}/auth-host || true
				db_go
			else
				echo "Couldn't find either auth_host or auth_url :("
			fi
		fi
	fi

        pkgos_read_config -p medium ${READ_ADMIN_CRED_CONF_FNAME} ${READ_ADMIN_CRED_SEARCH_SECTION} admin_tenant_name ${READ_ADMIN_CRED_PKG_NAME}/admin-tenant-name
        pkgos_read_config -p medium ${READ_ADMIN_CRED_CONF_FNAME} ${READ_ADMIN_CRED_SEARCH_SECTION} admin_user ${READ_ADMIN_CRED_PKG_NAME}/admin-user
        pkgos_read_config ${READ_ADMIN_CRED_CONF_FNAME} ${READ_ADMIN_CRED_SEARCH_SECTION} admin_password ${READ_ADMIN_CRED_PKG_NAME}/admin-password
}

# To be used in: postinst
pkgos_write_admin_creds () {
	local WRITE_CRED_CONF_FNAME WRITE_CRED_PKG_NAME WRITE_CRED_SECTION NO_PROTO AFTER_PORT WRITE_CRED_URL WRITE_CRED_PROTO
	WRITE_CRED_CONF_FNAME=${1}
	WRITE_CRED_SECTION=${2}
	WRITE_CRED_PKG_NAME=${3}

	db_get ${WRITE_CRED_PKG_NAME}/auth-host
	WRITE_CRED_AUTH_HOST=${RET}
	if grep -q auth_host ${WRITE_CRED_CONF_FNAME} ; then
		pkgos_inifile set ${WRITE_CRED_CONF_FNAME} ${WRITE_CRED_SECTION} auth_host ${RET}
	else
		# This is needed for l3_agent.ini
		if grep -q auth_url ${WRITE_CRED_CONF_FNAME} ; then
			pkgos_inifile get ${WRITE_CRED_CONF_FNAME} ${WRITE_CRED_SECTION} auth_url
			if [ -n "${RET}" ] && [ ! "${RET}" = "NOT_FOUND" ] ; then
				NO_PROTO=${RET#http://}
				WRITE_CRED_PROTO="http"
				if [ ${NO_PROTO} = ${RET} ] ; then
					WRITE_CRED_PROTO="https"
					NO_PROTO=${RET#https://}
				fi
				AFTER_PORT=$(echo ${NO_PROTO} | cut -d":" -f2)
			else
				WRITE_CRED_PROTO="http"
				AFTER_PORT="35357/"
			fi
			WRITE_CRED_URL="${WRITE_CRED_PROTO}://${WRITE_CRED_AUTH_HOST}:${AFTER_PORT}"
			pkgos_inifile set ${WRITE_CRED_CONF_FNAME} ${WRITE_CRED_SECTION} auth_url ${WRITE_CRED_URL}
		else
			echo "Couldn't find either auth_host or auth_url :("
		fi
	fi
	db_get ${WRITE_CRED_PKG_NAME}/admin-tenant-name
	pkgos_inifile set ${WRITE_CRED_CONF_FNAME} ${WRITE_CRED_SECTION} admin_tenant_name ${RET}
	db_get ${WRITE_CRED_PKG_NAME}/admin-user
	pkgos_inifile set ${WRITE_CRED_CONF_FNAME} ${WRITE_CRED_SECTION} admin_user ${RET}
	db_get ${WRITE_CRED_PKG_NAME}/admin-password
	pkgos_inifile set ${WRITE_CRED_CONF_FNAME} ${WRITE_CRED_SECTION} admin_password ${RET}
}

pkgos_write_new_conf () {
	local WRITE_N_CONF_PKG_NAME CONF_FNAME
	WRITE_N_CONF_PKG_NAME=${1}
	CONF_FNAME=${2}

	SRC_PATH=/usr/share/${DPKG_MAINTSCRIPT_PACKAGE}/${CONF_FNAME}
	DST_DIR=/etc/${WRITE_N_CONF_PKG_NAME}
	DST_PATH=${DST_DIR}/${CONF_FNAME}
	if [ ! -d ${DST_DIR} ] ; then
		mkdir -p ${DST_DIR}
	fi
	chmod 0750 ${DST_DIR}
	chown ${WRITE_N_CONF_PKG_NAME}:${WRITE_N_CONF_PKG_NAME} ${DST_DIR}
	if [ ! -e ${DST_PATH} ] ; then
		install -D -m 640 -o ${WRITE_N_CONF_PKG_NAME} -g ${WRITE_N_CONF_PKG_NAME} ${SRC_PATH} ${DST_PATH}
	fi
}

pkgos_adduser () {
	local VAR_UG_PKG_NAME
	local VAR_UG_SHELL
	VAR_UG_PKG_NAME=${1}
	VAR_UG_SHELL=${2}

	if [ -z "${VAR_UG_SHELL}" ] ; then
		VAR_UG_SHELL='/bin/false'
	fi

	# Create user and groups if they don't exist
	if ! getent group ${VAR_UG_PKG_NAME} > /dev/null 2>&1 ; then
		addgroup --quiet --system ${VAR_UG_PKG_NAME}
	fi
	if ! getent passwd ${VAR_UG_PKG_NAME} > /dev/null 2>&1 ; then
		adduser --system \
			--home /var/lib/${VAR_UG_PKG_NAME} \
			--no-create-home \
			--quiet \
			--disabled-password \
			--shell ${VAR_UG_SHELL} \
			--group ${VAR_UG_PKG_NAME}
	else
		usermod \
			--shell ${VAR_UG_SHELL} \
			${VAR_UG_PKG_NAME} >/dev/null 2>&1
	fi
}

pkgos_var_user_group () {
	local VAR_UG_PKG_NAME
	local VAR_UG_SHELL
	VAR_UG_PKG_NAME=${1}
	VAR_UG_SHELL=${2}

	# Remove user from adm group, because we was adding it nonintentionally
	deluser -q ${VAR_UG_PKG_NAME} adm 2>/dev/null || true

	pkgos_adduser ${VAR_UG_PKG_NAME} ${VAR_UG_SHELL}

	# Create /var/{lib,log}/<package> with that user/group if it doesn't exist
	if [ ! -d /var/lib/${VAR_UG_PKG_NAME} ] ; then
		mkdir -p /var/lib/${VAR_UG_PKG_NAME}/cache
	fi
	chown ${VAR_UG_PKG_NAME}:${VAR_UG_PKG_NAME} /var/lib/${VAR_UG_PKG_NAME}
	if [ "${VAR_UG_PKG_NAME}" = "nova" ] ; then
		chmod 755 /var/lib/nova
	else
		chmod 0750 /var/lib/${VAR_UG_PKG_NAME}
	fi
	if [ ! -d /var/log/${VAR_UG_PKG_NAME} ] ; then
		mkdir -p /var/log/${VAR_UG_PKG_NAME}
	fi
	chown ${VAR_UG_PKG_NAME}:adm /var/log/${VAR_UG_PKG_NAME}
	chmod 0750 /var/log/${VAR_UG_PKG_NAME}
}

pkgos_init () {
	INIT_SCRIPT_NAME=${1}
	if [ -x /etc/init.d/${INIT_SCRIPT_NAME} ] ; then
		update-rc.d ${INIT_SCRIPT_NAME} defaults >/dev/null
		invoke-rc.d ${INIT_SCRIPT_NAME} start || true
	fi
}

pkgos_get_id () {
    SERVICE_ENDPOINT=${SERVICE_ENDPOINT:-http://127.0.0.1:35357/v2.0/} SERVICE_TOKEN=${AUTH_TOKEN} "$@" | awk '/ id / { print $4 }'
}

# Asks the debconf questions for registering a service and its endpoint in keystone
# Prototype: pkgos_register_endpoint_config <pkg-name>
# Example: pkgos_register_endpoint_config glance
# To be used in: config
pkgos_register_endpoint_config () {
	local REG_ENDP_PKG_NAME DEFROUTE_IF DEFROUTE_IP
	REG_ENDP_PKG_NAME=${1}

	db_input high ${REG_ENDP_PKG_NAME}/register-endpoint || true
	db_go
	db_get ${REG_ENDP_PKG_NAME}/register-endpoint
	if [ "${RET}" = "true" ] ; then
		db_get ${REG_ENDP_PKG_NAME}/keystone-ip
		if [ -z "${RET}" ] ; then
			db_set ${REG_ENDP_PKG_NAME}/keystone-ip 127.0.0.1
		fi
		db_input medium ${REG_ENDP_PKG_NAME}/keystone-ip || true

		# Attempt to use keystone project, admin-name and passwrod if there's
		# no ${REG_ENDP_PKG_NAME}/keystone-auth-token, so that we stay backward
		# compatible with older version of openstack-pkg-tools.
		if db_get ${REG_ENDP_PKG_NAME}/keystone-auth-token ; then
			db_input high ${REG_ENDP_PKG_NAME}/keystone-auth-token || true
		else
			db_input low ${REG_ENDP_PKG_NAME}/keystone-project-name || true
			db_input low ${REG_ENDP_PKG_NAME}/keystone-admin-name || true
			db_input high ${REG_ENDP_PKG_NAME}/keystone-admin-password || true
		fi

		db_get ${REG_ENDP_PKG_NAME}/endpoint-ip || true
		if [ -z "${RET}" ] ; then
			if [ -x /bin/ip ] ; then
				DEFROUTE_IF=`awk '{ if ( $2 == "00000000" ) print $1 }' /proc/net/route`
				DEFROUTE_IP=`LC_ALL=C ip addr show "${DEFROUTE_IF}" | grep inet | head -n 1 | awk '{print $2}' | cut -d/ -f1 | grep -E '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$'`
			else
				DEFROUTE_IP=`hostname -i | grep -E '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$'`
			fi
			if [ -n "${DEFROUTE_IP}" ] ; then
				db_set ${REG_ENDP_PKG_NAME}/endpoint-ip ${DEFROUTE_IP}
			fi
		fi
		db_input medium ${REG_ENDP_PKG_NAME}/endpoint-ip || true
		db_input medium ${REG_ENDP_PKG_NAME}/region-name || true
		db_go
	fi
}

# Register a service and its endpoint in keystone
# Prototype: <pkg-name> <service-name> <service-type> <service-description> <serivce-port> <service-uri>
# Example: pkgos_register_endpoint_postinst glance glance image "Glance Image Service" 9292 /v1
# To be used in: postinst
pkgos_register_endpoint_postinst () {
	local PKG_NAME SERVICE_NAME SERVICE_TYPE SERVICE_DESC SERVICE_PORT SERVICE_URL KEYSTONE_ENDPOINT_IP AUTH_TOKEN PKG_ENDPOINT_IP REGION_NAME PKG_SERVICE_ID
	PKG_NAME=${1}
	SERVICE_NAME=${2}
	SERVICE_TYPE=${3}
	SERVICE_DESC=${4}
	SERVICE_PORT=${5}
	SERVICE_URL=${6}


	db_get ${PKG_NAME}/register-endpoint
	if [ "${RET}" = "true" ] ; then
		db_get ${PKG_NAME}/keystone-ip
		KEYSTONE_ENDPOINT_IP=`echo ${RET} | egrep '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$'`
		db_get ${PKG_NAME}/endpoint-ip
		PKG_ENDPOINT_IP=`echo ${RET} | egrep '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$'`
		db_get ${PKG_NAME}/region-name
		REGION_NAME=${RET}

		if db_get ${PKG_NAME}/keystone-auth-token ; then
			AUTH_TOKEN=${RET}
			if [ -n "${KEYSTONE_ENDPOINT_IP}" ] && [ -n "${PKG_ENDPOINT_IP}" ] && [ -n "${REGION_NAME}" ] && [ -n "${AUTH_TOKEN}" ] ; then
				echo "Registering service and endpoints for ${SERVICE_NAME} with type ${SERVICE_TYPE} at http://${PKG_ENDPOINT_IP}:${SERVICE_PORT}${SERVICE_URL}"
				NUM_LINES=$(openstack --os-token ${AUTH_TOKEN} --os-url=http://${KEYSTONE_ENDPOINT_IP}:35357/v3/ --os-domain-name default --os-identity-api-version=3 service list --format=csv | q -d , -H 'SELECT ID FROM - WHERE `Type`="'${SERVICE_TYPE}'"' | wc -l)
				if [ "${NUM_LINES}" = "0" ] ; then
					openstack --os-token ${AUTH_TOKEN} --os-url=http://${KEYSTONE_ENDPOINT_IP}:35357/v3/ --os-domain-name default --os-identity-api-version=3 service create \
						--name=${SERVICE_NAME} --description="${SERVICE_DESC}" ${SERVICE_TYPE}

					openstack --os-token ${AUTH_TOKEN} --os-url=http://${KEYSTONE_ENDPOINT_IP}:35357/v3/ --os-domain-name default --os-identity-api-version=3 endpoint create \
						--region "${REGION_NAME}" \
						${SERVICE_NAME} public http://${PKG_ENDPOINT_IP}:${SERVICE_PORT}${SERVICE_URL}

					openstack --os-token ${AUTH_TOKEN} --os-url=http://${KEYSTONE_ENDPOINT_IP}:35357/v3/ --os-domain-name default --os-identity-api-version=3 endpoint create \
						--region "${REGION_NAME}" \
						${SERVICE_NAME} internal http://${PKG_ENDPOINT_IP}:${SERVICE_PORT}${SERVICE_URL}

					openstack --os-token ${AUTH_TOKEN} --os-url=http://${KEYSTONE_ENDPOINT_IP}:35357/v3/ --os-domain-name default --os-identity-api-version=3 endpoint create \
						--region "${REGION_NAME}" \
						${SERVICE_NAME} admin http://${PKG_ENDPOINT_IP}:${SERVICE_PORT}${SERVICE_URL}
				else
					echo "Service already registered: skipping service endpoint creation. Will skip service endpoint creation."
				fi
			else
				echo "Problem in endpoint parameter (IPs or otherwise)."
			fi
		else
			db_get ${PKG_NAME}/keystone-project-name
			KEYSTONE_PROJECT_NAME=${RET}
			db_get ${PKG_NAME}/keystone-admin-name
			KEYSTONE_ADMIN_NAME=${RET}
			db_get ${PKG_NAME}/keystone-admin-password
			KEYSTONE_ADMIN_PASSWORD=${RET}

			if [ -n "${KEYSTONE_ENDPOINT_IP}" ] && [ -n "${PKG_ENDPOINT_IP}" ] && [ -n "${REGION_NAME}" ] && [ -n "${KEYSTONE_PROJECT_NAME}" ] && [ -n "${KEYSTONE_ADMIN_NAME}" ]  && [ -n "${KEYSTONE_ADMIN_PASSWORD}" ]; then
				echo "Registering service and endpoints for ${SERVICE_NAME} with type ${SERVICE_TYPE} at http://${PKG_ENDPOINT_IP}:${SERVICE_PORT}${SERVICE_URL}"
				export OS_PROJECT_DOMAIN_ID=default
				export OS_USER_DOMAIN_ID=default
				export OS_TENANT_NAME=${KEYSTONE_PROJECT_NAME}
				export OS_PROJECT_NAME=${KEYSTONE_PROJECT_NAME}
				export OS_USERNAME=${KEYSTONE_ADMIN_NAME}
				export OS_PASSWORD=${KEYSTONE_ADMIN_PASSWORD}
				export OS_AUTH_URL=http://${KEYSTONE_ENDPOINT_IP}:35357/v3/
				export OS_IDENTITY_API_VERSION=3
				export OS_AUTH_VERSION=3
				export OS_PROJECT_DOMAIN_ID=default
				export OS_USER_DOMAIN_ID=default
				export OS_NO_CACHE=1
				NUM_LINES=$(OS_PASSWORD=${KEYSTONE_ADMIN_PASSWORD} openstack service list --format=csv | q -d , -H 'SELECT ID FROM - WHERE `Type`="'${SERVICE_TYPE}'"' | wc -l)
				if [ "${NUM_LINES}" = "0" ] ; then
					openstack service create --name=${SERVICE_NAME} --description="${SERVICE_DESC}" ${SERVICE_TYPE}
					openstack endpoint create --region "${REGION_NAME}" ${SERVICE_NAME} public   http://${PKG_ENDPOINT_IP}:${SERVICE_PORT}${SERVICE_URL}
					openstack endpoint create --region "${REGION_NAME}" ${SERVICE_NAME} internal http://${PKG_ENDPOINT_IP}:${SERVICE_PORT}${SERVICE_URL}
					openstack endpoint create --region "${REGION_NAME}" ${SERVICE_NAME} admin    http://${PKG_ENDPOINT_IP}:${SERVICE_PORT}${SERVICE_URL}
				else
					echo "Service already registered: skipping service endpoint creation."
				fi
			else
				echo "Problem in endpoint parameter (IPs or otherwise). Will skip service endpoint creation."
			fi
		fi
		# Since there's very little chance a 2nd registration of the
		# endpoint will be needed, we forget the value of
		# ${PKG_NAME}/register-endpoint. If later on the
		# administrator of the server upgrades, it will be asked
		# again, or eventually, dpkg-reconfigure <package-name> can
		# be used.
		db_unregister ${PKG_NAME}/register-endpoint
	else
		echo "Will not register "${SERVICE_NAME}" endpoint this time (no user request for it)."
	fi
	# For security reasons, we don't keep the auth-token in the debconf
	# memory, so we purge it with db_unregister.
	# And same for the new system: we must forget keystone-admin-password.
	if db_get ${PKG_NAME}/keystone-auth-token ; then
		db_unregister ${PKG_NAME}/keystone-auth-token
	else
		db_unregister ${PKG_NAME}/keystone-admin-password
	fi
}

# Before removing the package, ask if we should remove the db
# Prototype: pkgos_prerm_db_clean ${1} <template-prefix> <package-name>
# Example:   pkgos_prerm_db_clean ${1} neutron neutron-common
pkgos_prerm_db_clean () {
	local PKPRM_TEMPLATE_PREFIX PKPRM_PACKAGE_NAME
	PKPRM_TEMPLATE_PREFIX=${1}
	PKPRM_PACKAGE_NAME=${2}
	shift
	shift
	DPKG_COMMAND=${1}

	if [ "${1}" = "remove" ] ; then
		. /usr/share/debconf/confmodule

		# We unregister the value, since we don't want to use
		# debconf as a register, and prefer a volatile thing.
		db_unregister ${PKPRM_TEMPLATE_PREFIX}/configure_db
		db_input ${PKPRM_TEMPLATE_PREFIX}/configure_db || true
		db_get ${PKPRM_TEMPLATE_PREFIX}/configure_db
		if [ "$RET" = "true" ]; then
			if [ -e /usr/share/dbconfig-common/dpkg/prerm ] ; then
				. /usr/share/dbconfig-common/dpkg/prerm
				dbc_go ${neutron-common} $@
			fi
		fi
	fi
}

# Perform dbconfig-common cleanups when removing a package
# Prototype: pkgos_postrm_db_clean <template-prefix-name> <package-name> $@
# Example:   pkgos_postrm_db_clean neutron                neutron-common $@
pkgos_postrm_db_clean () {
	local PKPRM_TEMPLATE_PREFIX PKPRM_PACKAGE_NAME
	PKPRM_TEMPLATE_PREFIX=${1}
	PKPRM_PACKAGE_NAME=${2}
	shift
	shift
        # Purge db on purge
        if [ -f /usr/share/debconf/confmodule ] ; then
                . /usr/share/debconf/confmodule
                db_get ${PKPRM_TEMPLATE_PREFIX}/configure_db
                if [ "$RET" = "true" ] ; then
                        if [ -f /usr/share/dbconfig-common/dpkg/postrm ] ; then
                                . /usr/share/dbconfig-common/dpkg/postrm
                                dbc_go ${PKPRM_PACKAGE_NAME} $@
                        else
                                rm -f /etc/dbconfig-common/${PKPRM_PACKAGE_NAME}.conf
                                if which ucf >/dev/null 2>&1; then
                                        ucf --purge /etc/dbconfig-common/${PKPRM_PACKAGE_NAME}.conf
                                        ucfr --purge ${PKPRM_PACKAGE_NAME} /etc/dbconfig-common/${PKPRM_PACKAGE_NAME}.conf
                                fi
                        fi
                fi
        fi
}

# Perform cleanups when removing a package
# Prototype: pkgos_postrm <template-prefix-name> <package-name> $@
# Example:   pkgos_postrm neutron                neutron-common $@
pkgos_postrm () {
	local PKPRM_TEMPLATE_PREFIX PKPRM_PACKAGE_NAME
	pkgos_postrm_db_clean $@

	PKPRM_TEMPLATE_PREFIX=${1}
	PKPRM_PACKAGE_NAME=${2}
	shift
	shift

	rm -rf /var/lib/${PKPRM_TEMPLATE_PREFIX} /var/log/${PKPRM_TEMPLATE_PREFIX} /var/lock/${PKPRM_TEMPLATE_PREFIX}
}
