blob: 6113190176a6684b509eade43bca4182088d411c [file] [log] [blame]
#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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.
#
# pxf-service start/stop/initialize/status the PXF instance
#
if [ -z ${PXF_HOME} ]; then
parent_script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )"
env_script=${parent_script_dir}/conf/pxf-env.sh
else
env_script=${PXF_HOME}/conf/pxf-env.sh
fi
# load pxf-env.sh script
if [ ! -f ${env_script} ]; then
echo WARNING: failed to find $env_script
else
source ${env_script}
fi
pxf_user=${PXF_USER}
instance_port=${PXF_PORT:-@pxfPortNum@}
instance_name=pxf-service
if [ -z ${PXF_HOME} ]; then
# RPM based setup
pxf_root=/usr/lib/pxf
tomcat_root=/opt/apache-tomcat
tomcat_templates=/opt/pxf/tomcat-templates
instance_root=/var/pxf
instance_owner=$pxf_user:$pxf_user
else
# OSS/Source code based setup
pxf_root=${PXF_HOME}/lib
tomcat_root=${PXF_HOME}/apache-tomcat
tomcat_templates=${PXF_HOME}/tomcat-templates
instance_root=${PXF_HOME}
instance_owner=${pxf_user}
fi
curl=`which curl`
# print error message and return with error code
function fail()
{
echo "ERROR: $1"
exit 1
}
#
# createInstance creates a tomcat instance and
# configures based on pre-configured template files.
#
function createInstance()
{
mkdir -p ${instance_root}
mkdir -p ${instance_root}/${instance_name}
cp -r ${tomcat_root}/* ${instance_root}/${instance_name}/.
if [ $? -gt 0 ]; then
echo ERROR: instance creation failed
return 1
fi
if [ ! -z ${pxf_user} ]; then
chown -R ${instance_owner} ${instance_root}
fi
chmod 700 ${instance_root}/${instance_name}
# copy configuration files into instance
cp ${tomcat_templates}/bin/setenv.sh ${instance_root}/${instance_name}/bin/setenv.sh
cp ${tomcat_templates}/conf/catalina.properties ${instance_root}/${instance_name}/conf/.
cp ${tomcat_templates}/conf/server.xml ${instance_root}/${instance_name}/conf/.
cp ${tomcat_templates}/conf/web.xml ${instance_root}/${instance_name}/conf/.
return 0
}
#
# deployWebapp adds the pxf-webapp to the new instance's webapps folder
# and the custom loader to the instance's lib directory
#
function deployWebapp()
{
cp ${pxf_root}/pxf.war ${instance_root}/${instance_name}/webapps/ || return 1
cp ${pxf_root}/pxf-service-*[0-9].jar ${instance_root}/${instance_name}/lib/ || return 1
return 0
}
#
# waitForTomcat waits for tomcat to finish loading
# for given attempts number.
#
function waitForTomcat()
{
attempts=0
max_attempts=$1 # number of attempts to connect
sleep_time=1 # sleep 1 second between attempts
# wait until tomcat is up:
echo Checking if tomcat is up and running...
until [[ "`curl --silent --connect-timeout 1 -I http://localhost:${instance_port} | grep 'Coyote'`" != "" ]];
do
let attempts=attempts+1
if [[ "$attempts" -eq "$max_attempts" ]]; then
echo ERROR: PXF is down - tomcat is not running
return 1
fi
echo "tomcat not responding, re-trying after ${sleep_time} second (attempt number ${attempts})"
sleep ${sleep_time}
done
return 0
}
#
# checkWebapp checks if tomcat is up for $1 attempts and then
# verifies PXF webapp is functional
#
function checkWebapp()
{
waitForTomcat $1 || return 1
echo Checking if PXF webapp is up and running...
curlResponse=$(${curl} -s "http://localhost:${instance_port}/pxf/v0")
expectedResponse="Wrong version v0, supported version is v[0-9]+"
if [[ ${curlResponse} =~ $expectedResponse ]]; then
echo PXF webapp is listening on port ${instance_port}
return 0
fi
echo ERROR: PXF webapp is inaccessible but tomcat is up. Check logs for more information
return 1
}
# instanceExists returns 0 when the instance exists
# non zero otherwise
function instanceExists()
{
if [ ! -d "$instance_root/$instance_name" ]; then
return 1
fi
${instance_root}/${instance_name}/bin/catalina.sh version > /dev/null 2>&1
return $?
}
# doInit handles the init command
function doInit()
{
instanceExists
if [ $? -eq 0 ]; then
echo WARNING: instance already exists in ${instance_root}, nothing to do...
return 0
fi
determineHadoopDistro
generatePrivateClasspath || return 1
createInstance || return 1
deployWebapp || return 1
createLogsDir || return 1
createRunDir || return 1
}
#
# configureWebapp patches the webapp with pxf and user overriden configs
# applied only if PXF_HOME is defined
#
function configureWebapp()
{
if [ -z ${PXF_HOME} ]; then
# webapp doesn't require patch
return 0
fi
pushd ${instance_root}/${instance_name}/webapps > /dev/null || return 1
rm -rf pxf
mkdir pxf
cd pxf
unzip -q ../pxf.war
popd > /dev/null
context_file=${instance_root}/${instance_name}/webapps/pxf/META-INF/context.xml
sed -i -e "s:classpathFiles=\"[a-zA-Z0-9\/\;.-]*\":classpathFiles=\"${PXF_HOME}\/conf\/pxf-private.classpath\":" ${context_file}
sed -i -e "s:secondaryClasspathFiles=\"[a-zA-Z0-9\/\;.-]*\":secondaryClasspathFiles=\"${PXF_HOME}\/conf\/pxf-public.classpath\":" ${context_file}
web_file=${instance_root}/${instance_name}/webapps/pxf/WEB-INF/web.xml
sed -i -e "s:<param-value>.*pxf-log4j.properties<\/param-value>:<param-value>$PXF_HOME\/conf\/pxf-log4j.properties<\/param-value>:" ${web_file}
# set port
catalinaProperties=${instance_root}/${instance_name}/conf/catalina.properties
sed -i -e "s|^[[:blank:]]*connector.http.port=.*$|connector.http.port=$instance_port|g" ${catalinaProperties}
# set container configs
catalinaEnv=${instance_root}/${instance_name}/bin/setenv.sh
sed -i -e "s|JVM_OPTS=.*$|JVM_OPTS=\"${PXF_JVM_OPTS}\"|g" ${catalinaEnv}
sed -i -e "s|-Dpxf.log.dir=[^[:space:]^\"]*|-Dpxf.log.dir=${PXF_LOGDIR} |g" ${catalinaEnv}
sed -i -e "s|^[[:blank:]]*PXF_USER_IMPERSONATION=.*$|PXF_USER_IMPERSONATION=\"${PXF_USER_IMPERSONATION}\"|g" ${catalinaEnv}
sed -i -e "s|^[[:blank:]]*CATALINA_PID=.*$|CATALINA_PID=${PXF_RUNDIR}/catalina.pid|g" ${catalinaEnv}
sed -i -e "s|^[[:blank:]]*CATALINA_OUT=.*$|CATALINA_OUT=${PXF_LOGDIR}/catalina.out|g" ${catalinaEnv}
# set log directories
catalinaLog=${instance_root}/$instance_name/conf/logging.properties
sed -i -e "s|juli.FileHandler.directory\s*=.*$|juli.FileHandler.directory = ${PXF_LOGDIR}|g" ${catalinaLog}
}
function commandWebapp()
{
command=$1
pushd ${instance_root} > /dev/null
if [ ! -z ${pxf_user} ]; then
# Run command as a pxf_user
su ${pxf_user} -c "$instance_root/$instance_name/bin/catalina.sh $command"
else
# Run command as a current user
${instance_root}/${instance_name}/bin/catalina.sh ${command}
fi
if [ $? -ne 0 ]; then
return 1
fi
popd > /dev/null
}
function createLogsDir()
{
mkdir -p ${PXF_LOGDIR}
if [ ! -z ${pxf_user} ]; then
chown -R ${instance_owner} ${PXF_LOGDIR}
fi
chmod 700 ${PXF_LOGDIR}
return 0
}
function createRunDir()
{
mkdir -p ${PXF_RUNDIR}
if [ ! -z ${pxf_user} ]; then
chown -R ${instance_owner} ${PXF_RUNDIR}
fi
chmod 700 ${PXF_RUNDIR}
return 0
}
function check_hadoop_install()
{
local distro_type=${1}
case "${distro_type}" in
hdp|HDP)
if [ -d "/usr/hdp/current/hadoop-client/client" ]; then
DISTRO="hdp"
return 0;
fi
;;
cdh|CDH)
if [ -d "/usr/lib/hadoop/client" ]; then
DISTRO="cdh"
return 0;
fi
;;
tar|TAR)
if [ -n "${HADOOP_ROOT}" ] && [ -d "${HADOOP_ROOT}/hadoop/share/hadoop/common/lib" ]; then
DISTRO="tar"
return 0;
fi
;;
custom|CUSTOM)
# use tarball template for custom distro, do not require HADOOP_ROOT to be set
DISTRO="tar"
return 0;
;;
*)
fail "Unknown hadoop distribution type: HADOOP_DISTRO=${distro_type}"
;;
esac
# the distro type was not found installed, return failure code
return 1
}
function determineHadoopDistro()
{
DISTRO=""
# check if the distro is explicitly specified
if [ -z "${HADOOP_DISTRO}" ]; then
# if distro is not specified, try checking for HDP and then CDH
check_hadoop_install "hdp" || check_hadoop_install "cdh"
else
# check distro specified in the config file
check_hadoop_install "${HADOOP_DISTRO}"
fi
# if still not determined, check tarball-based install
if [ -z "${DISTRO}" ]; then
check_hadoop_install "tar"
# if still unknown, then error out
if [ -z "${DISTRO}" ]; then
fail "Can not determine Hadoop distribution, please install Hadoop clients."
fi
fi
}
function generatePrivateClasspath()
{
# distro must have been determined by now, but double check
if [ -z "${DISTRO}" ]; then
fail "Hadoop distribution was not determined"
fi
# verify that a template file for the distribution exists
local template_file="${PXF_HOME}/conf-templates/pxf-private-${DISTRO}.classpath.template"
if [ ! -f "${template_file}" ]; then
fail "Template file ${template_file} not found"
fi
echo "Generating ${PXF_HOME}/conf/pxf-private.classpath file from ${template_file} ..."
# create initial version of the file by replacing PXF_HOME token (applicable to all templates)
sed -e "s|PXF_HOME|${PXF_HOME}|g" ${template_file} > ${PXF_HOME}/conf/pxf-private.classpath
# substitute HADOOP_ROOT value if defined
if [ -n "${HADOOP_ROOT}" ]; then
sed -i -e "s|HADOOP_ROOT|${HADOOP_ROOT}|g" ${PXF_HOME}/conf/pxf-private.classpath
fi
}
function printUsage()
{
echo $"Usage: $0 {start|stop|restart|init|status}"
}
function validateParameters()
{
# validate curl
which curl &> /dev/null
if [ "$?" -ne "0" ]
then
echo "ERROR: curl is not installed, please install"
exit 1
fi
# validate unzip
which unzip &> /dev/null
if [ "$?" -ne "0" ]
then
echo "ERROR: unzip is not installed, please install"
exit 1
fi
# validate pxf user
if [ ! -z ${pxf_user} ]; then
id ${pxf_user} &> /dev/null;
if [ "$?" -ne "0" ]
then
echo "ERROR: User $pxf_user doesn't exist. Please set valid user via \$PXF_USER variable"
exit 1
fi
fi
# make sure current user is not root
if [ $EUID -eq 0 ]; then
echo "ERROR: Cannot run as root user"
exit 1
fi
# validate JAVA_HOME
if [ ! -x ${JAVA_HOME}/bin/java ]; then
echo ERROR: \$JAVA_HOME is invalid
exit 1
fi
return 0
}
#
# doStart handles start command
# command is executed as the user $pxf_user
#
# after start, uses checkWebapp to verify the PXF webapp was loaded
# successfully
#
function doStart()
{
instanceExists
if [ $? -ne 0 ]; then
echo ERROR: cant find PXF instance, maybe call init?
return 1
fi
configureWebapp || return 1
commandWebapp start || return 1
checkWebapp 300 || return 1
}
#
# doStart handles stop command
# command is executed as the user $pxf_user
#
#
function doStop()
{
instanceExists
if [ $? -ne 0 ]; then
echo "ERROR: can't find PXF instance, maybe call init?"
return 1
fi
commandWebapp stop || return 1
}
function doStatus()
{
checkWebapp 1 || return 1
}
command=$1
case "$command" in
"init" )
validateParameters
doInit
;;
"start" )
validateParameters
doStart
;;
"stop" )
validateParameters
doStop
;;
"restart" )
validateParameters
doStop
sleep 1s
doStart
;;
"status" )
validateParameters
doStatus
;;
* )
printUsage
exit 2
;;
esac
exit $?