#!/bin/sh
# Copyright (C) 1994-2018 Altair Engineering, Inc.
# For more information, contact Altair at www.altair.com.
#
# This file is part of the PBS Professional ("PBS Pro") software.
#
# Open Source License Information:
#
# PBS Pro is free software. You can redistribute it and/or modify it under the
# terms of the GNU Affero General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# PBS Pro is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.
# See the GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
# Commercial License Information:
#
# For a copy of the commercial license terms and conditions,
# go to: (http://www.pbspro.com/UserArea/agreement.html)
# or contact the Altair Legal Department.
#
# Altair’s dual-license business model allows companies, individuals, and
# organizations to create proprietary derivative works of PBS Pro and
# distribute them - whether embedded or bundled with other software -
# under a commercial license agreement.
#
# Use of Altair’s trademarks, including but not limited to "PBS™",
# "PBS Professional®", and "PBS Pro™" and Altair’s logos is subject to Altair's
# trademark licensing policies.

. ${PBS_CONF_FILE:-/etc/pbs.conf}


trap cleanup 1 2 3 15

# Source the file that sets PGSQL_LIBSTR
. "$PBS_EXEC"/libexec/pbs_pgsql_env.sh

# On some platforms LD_LIBRARY_PATH etc is not passed on after su
# so we set it again after the su. PGSQL_LIBSTR contains the line to
# set the variable again
export PGSQL_LIBSTR

dir=`dirname $0`
CWD=`pwd`

cleanup() {
  	cd ${CWD}
	rm -rf ${data_dir}
	rm -f ${schema}
	rm -f ${tmp_file}
}

get_db_user() {
  if [ ! -f "${db_user}" ]; then
    echo "pbsdata"
    return 0
  else
    cat "${db_user}"
    return $?
  fi
}

chk_dataservice_user() {
	chk_usr="$1"

	# do user-id related stuff first
	id=`id ${chk_usr} 2>&1`
	if [ $? -ne 0 ]; then
		echo "PBS Data Service user ${chk_usr} does not exist"
		return 1;
	fi

	id=`echo ${id} | cut -c5- | cut -d "(" -f1`
	if [ "$id" = "0" ]; then
		echo "User ${chk_usr} should not have root priviledges"
		return 1;
	fi

	if [ -n "$NASMODE" ] ; then
		# login as ${chk_usr} and try to cd to user home dir
		su - ${chk_usr} -s /bin/sh -c "cd" > /dev/null 2>&1
	else
		su - ${chk_usr} -c "cd" > /dev/null 2>&1
	fi

	if [ $? -ne 0 ]; then
		echo "Unable to login as user ${chk_usr}. Is the user enabled/home directory accessible?"
		return 1
	fi
	return 0
}

cleanup_on_finish () {
	# change back to our dir and quit
	cd ${CWD}
	err=`rm -f ${schema}`
	if [ $? -ne 0 ]; then
		echo "${err}"
	fi
}

# Check if this call is for datastore upgrade
upgrade=0
if [ "$1" = "upgrade" ]; then
	upgrade=1
fi

locale=""
if [ "$2" = "0" ]; then
	locale="--locale=C"
fi

if [ ! -z "${PBS_DATA_SERVICE_HOST}" ]; then
	echo "Custom data service host used...configure manually"
	exit 0
fi

if [ -z "${PBS_DATA_SERVICE_PORT}" ]; then
	PBS_DATA_SERVICE_PORT="15007"
fi
export PBS_DATA_SERVICE_PORT

bin_dir="${PGSQL_BIN}"
data_dir="${PBS_HOME}/datastore"
server_ctl="${PBS_EXEC}/sbin/pbs_dataservice"
tmp_file="${PBS_HOME}/spool/tmp_inst_$$"
db_user="${PBS_HOME}/server_priv/db_user"

# Get non symbolic absolute path of pgsql directory
real_inst_dir="`/bin/ls -l $PBS_EXEC | awk '{print $NF "/pgsql"}'`"

schema_in="${PBS_EXEC}/etc/pbs_db_schema.sql"
if [ ! -f "${schema_in}" ]; then
	echo "PBS datastore schema file not found"
	exit 1
fi

schema="${PBS_HOME}/spool/pbs_install_db_schema"
cat ${schema_in} > ${schema}
chmod 600 ${schema}
if [ $? -ne 0 ]; then
	echo "chmod of ${schema} failed"
	rm -f ${schema}
	exit 1
fi

lwd=`pwd`

if [ ! -d "${bin_dir}" ]; then
	# Using the system installed Postgres instead
	initdb_loc=`type initdb 2>/dev/null | cut -d' ' -f3`
	if [ -z "$initdb_loc" ]; then
		echo "PBS Data Service directory ${bin_dir}"
		echo "not present and postgresql-server not installed."
		rm -f ${schema}
		exit 1
	fi
	bin_dir=`dirname $initdb_loc`
fi

user=`get_db_user`
if [ $? -ne 0 ]; then
  echo "Could not retrieve PBS Data Service User"
  exit 1
fi
port="${PBS_DATA_SERVICE_PORT}"

chk_dataservice_user "${user}"
if [ $? -ne 0 ]; then
	rm -f ${schema}
	exit 1
fi

chown ${user} ${schema}
if [ $? -ne 0 ]; then
	echo "chown of ${schema} to user ${user} failed"
	rm -f ${schema}
	exit 1
fi

if [ ! -x "${bin_dir}/initdb" ]; then
	echo "${bin_dir} exists, binaries missing...exiting"
	rm -f ${schema}
	exit 1
fi


if [ -d "${data_dir}/base" ]; then
	olduser=`ls -ld ${data_dir} | awk '{print $3}'`
	if [ $? -ne 0 ]; then
	  echo "Failed to stat directory ${data_dir}"
	  rm -f ${schema}
	  exit 1
	fi
	if [ "$olduser" != "$user" ]; then
	  echo "Existing PBS Data Store ${data_dir} owned by different user ${olduser}"
	  echo "Use the same user name or install in a different location"
	  rm -f ${schema}
	  exit 1
	fi
	rm -f ${schema}
	exit 2
fi

if [ ! -d "${data_dir}" ]; then
	mkdir -p "${data_dir}"
	if [ $? -ne 0 ]; then
		echo "Error creating dir ${data_dir}"
		rm -f ${schema}
		exit 1
	fi
fi

# delete the password file, if any, since we are creating new db
rm -f "${PBS_HOME}/server_priv/db_password"
passwd="${user}"

chown ${user} ${data_dir}
if [ $? -ne 0 ]; then
	echo "Chown of ${data_dir} to user ${user} failed"
	rm -f ${schema}
	exit 1
fi

chmod 700 ${data_dir}
if [ $? -ne 0 ]; then
	echo "chmod of ${data_dir} failed"
	rm -f ${schema}
	exit 1
fi

echo "Creating the PBS Data Service..."

# change directory to data_dir to ensure that we don't get cd errors from postgres later
cd ${data_dir}

if [ -n "$NASMODE" ] ; then
	# NAS localmod 006
	err=`su ${user} -s /bin/sh -c "/bin/sh -c '${PGSQL_LIBSTR} ${bin_dir}/initdb -D ${data_dir} -U \"${user}\" -E SQL_ASCII ${locale}'" 2>&1`
else
	err=`su ${user} -c "/bin/sh -c '${PGSQL_LIBSTR} ${bin_dir}/initdb -D ${data_dir} -U \"${user}\" -E SQL_ASCII ${locale}'" 2>&1`
fi

if [ $? -ne 0 ]; then
	echo "$err"
	echo "Error creating PBS datastore"
	cleanup
	exit 1
fi

# check for postgres config files existence
if [ ! -f "${data_dir}/postgresql.conf" ]; then
      echo "PBS Data Sevice Config files not found"
      cleanup
      exit 1
fi

if [ ! -f "${data_dir}/pg_hba.conf" ]; then
      echo "PBS Data Sevice Config files not found"
      cleanup
      exit 1
fi

# update postgresql.conf 
sed "{
	s/#checkpoint_segments = 3/checkpoint_segments = 20/g
	s/#port = 5432/port = ${port}/g
	s/#listen_addresses = 'localhost'/listen_addresses = '*'/g
	s/#standard_conforming_strings = off/standard_conforming_strings = on/g
	s/#logging_collector = off/logging_collector = on/g
	s/#log_directory = 'pg_log'/log_directory = 'pg_log'/g
	s/#log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'/log_filename = 'pbs_dataservice_log.%a'/g
	s/#log_truncate_on_rotation = off/log_truncate_on_rotation = on/g
	s/#log_rotation_age = 1d/log_rotation_age = 1440/g
	s/#log_line_prefix = ''/log_line_prefix = '%t'/g
    }" ${data_dir}/postgresql.conf > ${tmp_file}
if [ $? -ne 0 ]; then
	echo "Error creating PBS datastore"
	cleanup
	exit 1
fi
mv ${tmp_file} ${data_dir}/postgresql.conf
if [ $? -ne 0 ]; then
    echo "Error moving ${tmp_file} to ${data_dir}/postgresql.conf"
    cleanup
    exit 1
fi

chown ${user} ${data_dir}/postgresql.conf
if [ $? -ne 0 ]; then
    echo "Error setting ownership to file ${data_dir}/postgresql.conf"
    cleanup
    exit 1
fi

chmod 600 ${data_dir}/postgresql.conf
if [ $? -ne 0 ]; then
    echo "Error setting permissions to file ${data_dir}/postgresql.conf"
    cleanup
    exit 1
fi

if [ $upgrade -eq 1 ]; then
	cleanup_on_finish
	exit 0
fi

# Add IPV6 local address to pg_hba.conf so the pbs_ds_password is fine
echo "host    all             all             ::1/128                 trust" >> ${data_dir}/pg_hba.conf


${server_ctl} start 
if [ $? -ne 0 ]; then
	echo "Error starting PBS Data Service"
	cleanup
	exit 1
fi

if [ -n "$NASMODE" ] ; then
	# NAS localmod 006
	err=`su ${user} -s /bin/sh -c "/bin/sh -c '${PGSQL_LIBSTR} ${bin_dir}/createdb -p ${port} pbs_datastore'" 2>&1`
else
	err=`su ${user} -c "/bin/sh -c '${PGSQL_LIBSTR} ${bin_dir}/createdb -p ${port} pbs_datastore'" 2>&1`
fi

if [ $? -ne 0 ]; then
	echo "$err"
	echo "Error creating PBS datastore"
	${server_ctl} stop > /dev/null 2>&1
	cleanup
	exit 1
fi

# now install the pbs datastore schema onto the datastore

if [ -n "$NASMODE" ] ; then
	# NAS localmod 006
	err=`su ${user} -s /bin/sh -c "/bin/sh -c '${PGSQL_LIBSTR} ${bin_dir}/psql -p ${port} -d pbs_datastore -U \"${user}\" -f ${schema}'" 2>&1`
else
	err=`su ${user} -c "/bin/sh -c '${PGSQL_LIBSTR} ${bin_dir}/psql -p ${port} -d pbs_datastore -U \"${user}\" -f ${schema}'" 2>&1`
fi

if [ $? -ne 0 ]; then
	echo $err
	echo "Error initializing PBS datastore"
	${server_ctl} stop > /dev/null 2>&1
	cleanup
	exit 1
fi

err=`${PBS_EXEC}/sbin/pbs_ds_password -r`
if [ $? -ne 0 ]; then
	echo $err
	echo "Error setting password for PBS Data Service"
	${server_ctl} stop > /dev/null 2>&1
	cleanup
	exit 1
fi

# stop the dataservice
${server_ctl} stop
if [ $? -ne 0 ]; then
	echo $err
	echo "Error stopping PBS Data Service"
	kill -TERM `ps -ef | grep "${bin_dir}/postgres" | grep -v grep | awk '{if ($3 == 1) print $2}'`
	cleanup
	exit 1
fi

# update the pg_hba.conf, so that no passwordless entry is allowed
num=`grep -n "#.*TYPE.*DATABASE.*USER.*ADDRESS.*METHOD" ${data_dir}/pg_hba.conf | awk -F: '{print $1}'`
head -n $num ${data_dir}/pg_hba.conf > ${tmp_file}
mv ${tmp_file} ${data_dir}/pg_hba.conf

echo "# IPv4 local connections: " >> ${data_dir}/pg_hba.conf
echo "local   all             all                                     md5" >> ${data_dir}/pg_hba.conf
echo "host    all             all             0.0.0.0/0               md5" >> ${data_dir}/pg_hba.conf
echo "host    all             all             127.0.0.1/32            md5" >> ${data_dir}/pg_hba.conf
echo "# IPv6 local connections:" >> ${data_dir}/pg_hba.conf
echo "host    all             all             ::1/128                 md5" >> ${data_dir}/pg_hba.conf

chown ${user} ${data_dir}/pg_hba.conf
chmod 600 ${data_dir}/pg_hba.conf

cleanup_on_finish
exit 0
