#!/bin/bash
#------------------------------------------------------------------------------
# Copyright (c) Perforce Software, Inc., 2007-2014. All rights reserved
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1  Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
#
# 2.  Redistributions in binary form must reproduce the above copyright
#     notice, this list of conditions and the following disclaimer in the
#     documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PERFORCE
# SOFTWARE, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
# DAMAGE.
#------------------------------------------------------------------------------
#
# Change the first three variables below to match the volume names on the machine
# you are configuring the SDP on. 
# Set the remaining variables appropriately. The meaning of each should be obvious.
#
# In the SDP variable below, the sdp directory needs to contain the contents of:
# //depot/intranet/consulting/sw/MAIN/sdp
#
# Run this script as root, and pass in the instance number you are configuring.
# If you do not have root access, then remove the ID section and all the chown
# commands at the end of the script. You will need to have the /p4 directory created
# by the root user and the ownership changed to the OS user that you are planning
# to run Perforce under. The Metadata, Depotdata and Logs volumes will also need
# to be owned by the OS user as well in order for the script to work. You can then
# run this script as the OS user for Perforce and everything should work fine.
#
# This script creates an init script in the /p4/$INSTANCE/bin directory. You can use
# it from there if you are configuring a cluster, or you can link it in /etc/init.d
# if you are setting up a stand alone machine.
#
# After running this script, you also need to set up the crontab based on files
# in /p4/common/etc/cron.d.  For convenience, crontab files are copied to 
# /p4/crontab and /p4/crontab.replica.
#
# Now, put the license file in place and launch the server with the init script.
#
# Then run /p4/common/bin/p4master_run <instance> /p4/common/bin/live_checkpoint.sh
# and then run both the daily_backup.sh and weekly_backup.sh to make sure everything is
# working before setting up the crontab.
#
# Also run /p4/common/bin/p4master_run <instance> /p4/common/bin/p4review.py <instance>
# to make sure the review script is working properly.
#
# UPGRADING SDP
# Specify the -test parameter to the script.
# In this case the script will NOT make the various directories under /p4, but will instead
# create /tmp/p4 directory structure with the various files processed via templates etc.
# You can then manually compare this directory structure with your existing /p4 structure
# and manually copy the various files into it.
#
##############################################################################################
# CONFIGURATION VARIABLES:
#
# Do not prefix these paths with a /
MD=metadata
DD=depotdata
LG=logs
#
OSUSER=perforce
OSGROUP=perforce
SDP=/$DD/sdp
# Note that if the following is set to 1 then a trial run is done, into /tmp/p4
TEST=0

#
# CASEINSENSITIVE settings:
# 0 -- Server will run with case sensitivity default of the underlying platform (Unix is case sensitive).
# 1 -- Server will run in C1 mode, forcing case-insensitive mode on normally case-sensitive platforms
CASEINSENSITIVE=1
#
# CLUSTER settings:
# 0 -- Not a clustered environment (default)
# 1 -- Server in a clustered environment
CLUSTER=0

# Admin user's account name.
ADMINUSER=p4admin

# Admin user's password
P4ADMINPASS=adminpass

# Admin user's email
ADMINEMAIL=admin@company.com

# Set P4PORT_END to the typically 3-digit numeric value you prefer for the P4PORT
# for each instance, following the instance number.  So if P4PORT_END is 666,
# instance 1 will have P4PORT=1666.  As another example, if you want to run P4D
# on 1999 for instance 1 and have P4Broker to listen on 1666, set P4PORT_END=999
# and P4BROKER_PORT_END=666.
P4PORT_END=666
P4BROKER_PORT_END=667

# DNS Name or IP address of master server
P4DNSNAME=DNS_name_of_master_server
REPLICAHOST=DNS_name_of_replica_server
PROXYHOST=DNS_name_of_proxy_server

# Service user's account name.
SVCUSER=service

# Replication service user's password
P4SERVICEPASS=servicepass

# Replica TRUE or FALSE setting
REPLICA_TF=FALSE

# Name used in configure settings for the replica name.
REPLICANAME=replica1

# Mail Host Address
MAILHOST=mail.company.com

# Email address for p4review complaints for each instance
# look something like P4Review_1666@company.com.  Set
# the COMPLAINFROM_PREFIX (e.g. "P4Review") and
# COMPLAINFROM_DOMAIN (e.g. "company.com)" here.  Instance
# specific values are substituted below.
COMPLAINFROM_PREFIX=P4Review
COMPLAINFROM_DOMAIN=company.com

# END CONFIGURATION VARIABLES
##############################################################################################

SDP_VERSION="Rev. SDP/Unix/UNKNOWN"
[[ -r $SDP/Version ]] && SDP_VERSION="$(cat $SDP/Version)"

P4DIR=/p4

export AWK=awk
export ID=id
export MAIL=mail

OS=`uname`
if [[ "${OS}" = "SunOS" ]] ; then
  export AWK=/usr/xpg4/bin/awk
  export ID=/usr/xpg4/bin/id
  export MAIL=mailx
elif [[ "${OS}" = "AIX" ]] ; then
  export AWK=awk
  export ID=id
  export MAIL=mail
fi

if [[ `$ID -u` -eq 0 ]]; then
   echo "Verified: Running as root."
elif [[ `whoami` == $OSUSER ]]; then
   echo -e "\nWarning:  Not running as root; functionality is limited.\n"
else
   echo -e "\nError: $0 must be run as as root or $OSUSER.\n"
   exit 1
fi

# Verify instance value
INSTANCE=$1
if [[ -z "$INSTANCE" ]]; then
    echo "Error: An instance argument is required."
    exit 1
fi

if [[ "$2" = "-test" ]]; then
  TEST=1
  DD=tmp
  MD=tmp
  LG=tmp
  P4DIR=/tmp/p4
  echo "-test specified - will install to $DD/p4"
fi

COMPLAINFROM="${COMPLAINFROM_PREFIX}_${INSTANCE}${P4BROKER_PORT_END}\@${COMPLAINFROM_DOMAIN}"

[[ -f $SDP/Server/Unix/p4/common/bin/p4 ]] || { echo "No p4 in $SDP/Server/Unix/p4/common/bin" ; exit 1 ;}
[[ -f $SDP/Server/Unix/p4/common/bin/p4d ]] || { echo "No p4d in $SDP/Server/Unix/p4/common/bin" ; exit 1 ;}

chmod 755 $SDP/Server/Unix/p4/common/bin/p4
chmod 700 $SDP/Server/Unix/p4/common/bin/p4d
[[ -f $SDP/Server/Unix/p4/common/bin/p4broker ]] && chmod 700 $SDP/Server/Unix/p4/common/bin/p4broker
[[ -f $SDP/Server/Unix/p4/common/bin/p4web ]] && chmod 700 $SDP/Server/Unix/p4/common/bin/p4web
[[ -f $SDP/Server/Unix/p4/common/bin/p4p ]] && chmod 700 $SDP/Server/Unix/p4/common/bin/p4p

# Make sure you update the p4 and p4d versions in the sdp/Server/Unix/p4/common/bin directory when making
# new instances at a later date.
P4RELNUM=`$SDP/Server/Unix/p4/common/bin/p4 -V | grep -i Rev. | $AWK -F / '{print $3}'`
P4DRELNUM=`$SDP/Server/Unix/p4/common/bin/p4d -V | grep -i Rev. | $AWK -F / '{print $3}'`
P4BLDNUM=`$SDP/Server/Unix/p4/common/bin/p4 -V | grep -i Rev. | $AWK -F / '{print $4}' | $AWK '{print $1}'`
P4DBLDNUM=`$SDP/Server/Unix/p4/common/bin/p4d -V | grep -i Rev. | $AWK -F / '{print $4}' | $AWK '{print $1}'`

[[ -d $P4DIR ]] || mkdir $P4DIR

[[ -d /$DD/p4 ]] || mkdir /$DD/p4
[[ -d /$MD/p4 ]] || mkdir /$MD/p4
[[ -d /$LG/p4 ]] || mkdir /$LG/p4

mkdir -p /$DD/p4/$INSTANCE/bin
mkdir -p /$DD/p4/$INSTANCE/tmp
mkdir -p /$DD/p4/$INSTANCE/depots
mkdir -p /$DD/p4/$INSTANCE/checkpoints
mkdir -p /$DD/p4/$INSTANCE/ssl
[[ -d /$DD/p4/common/bin ]] || mkdir -p /$DD/p4/common/bin

mkdir -p /$MD/p4/$INSTANCE/root/save
mkdir -p /$MD/p4/$INSTANCE/offline_db

mkdir -p /$LG/p4/$INSTANCE/logs

cd /$DD/p4/$INSTANCE

if [[ $TEST -eq 0 ]]; then
    [[ -L root ]] || ln -s /$MD/p4/$INSTANCE/root
    [[ -L offline_db ]] || ln -s /$MD/p4/$INSTANCE/offline_db
    [[ -L logs ]] || ln -s /$LG/p4/$INSTANCE/logs
    cd $P4DIR
    ln -s /$DD/p4/$INSTANCE
    [[ -L sdp ]] || ln -s $SDP $P4DIR/sdp
fi

[[ -f /$DD/p4/common/bin/p4_$P4RELNUM.$P4BLDNUM ]] || cp $SDP/Server/Unix/p4/common/bin/p4 /$DD/p4/common/bin/p4_$P4RELNUM.$P4BLDNUM
[[ -f /$DD/p4/common/bin/p4d_$P4DRELNUM.$P4DBLDNUM ]] || cp $SDP/Server/Unix/p4/common/bin/p4d /$DD/p4/common/bin/p4d_$P4DRELNUM.$P4DBLDNUM

if [[ $INSTANCE -eq 1 ]]; then
  cp -R $SDP/Server/Unix/p4/common/bin/* /$DD/p4/common/bin

  if [[ ! -d /$DD/p4/common/etc ]]; then
    cp -pr $SDP/Server/Unix/p4/common/etc /$DD/p4/common/.
  fi

  if [[ ! -d /$DD/p4/common/lib ]]; then
    cp -pr $SDP/Server/Unix/p4/common/lib /$DD/p4/common/.
  fi

  if [[ ! -d /$DD/p4/common/test ]]; then
    cp -pr $SDP/Server/Unix/p4/common/test /$DD/p4/common/.
  fi
  
  echo $P4ADMINPASS > /$DD/p4/common/bin/adminpass
  chmod 600 /$DD/p4/common/bin/adminpass
  echo $P4SERVICEPASS > /$DD/p4/common/bin/servicepass
  chmod 600 /$DD/p4/common/bin/servicepass

  cd $P4DIR

  if [[ $CLUSTER -eq 0 ]]; then
    [[ $TEST -eq 0 ]] && ln -s /$DD/p4/common
  else
    if [[ $TEST -eq 0 ]]; then
      mkdir -p /p4/common/bin
      cd $P4DIR/common/bin
      ln -s /$DD/p4/common/bin/* .
      unlink p4_$P4RELNUM.$P4BLDNUM
      unlink p4d_$P4DRELNUM.$P4DBLDNUM
      unlink p4_vars
      unlink p4master_run
      cp /$DD/p4/common/bin/p4_vars .
      cp /$DD/p4/common/bin/p4master_run .
      ln -s /$DD/p4/common/bin/p4_bin
    fi
  fi

  cd /$DD/p4/common/bin
  ln -s p4_$P4RELNUM.$P4BLDNUM p4_${P4RELNUM}_bin
  ln -s p4d_$P4DRELNUM.$P4DBLDNUM p4d_${P4DRELNUM}_bin
  ln -s p4_${P4RELNUM}_bin p4_bin

  sed "s/REPL_MAILTO/${ADMINEMAIL}/g" p4_vars.template |\
     sed "s/REPL_ADMINUSER/${ADMINUSER}/g" |\
     sed "s/REPL_SDP_CLUSTER/${CLUSTER}/g" |\
     sed "s/REPL_SVCUSER/${SVCUSER}/g"  |\
     sed "s:REPL_SDPVERSION:${SDP_VERSION}:g" |\
     sed "s:REPL_DNSNAME:${P4DNSNAME}:g" |\
     sed "s:REPL_REPNAME:${REPLICANAME}:g" |\
     sed "s:REPL_REPHOST:${REPLICAHOST}:g" |\
     sed "s:REPL_PROXYHOST:${PROXYHOST}:g" |\
     sed "s:REPL_P4PORT_END:${P4PORT_END}:g" |\
     sed "s:REPL_P4BROKER_PORT_END:${P4BROKER_PORT_END}:g" |\
     sed "s/REPL_OSUSER/${OSUSER}/g" > p4_vars

  sed "s/REPL_ADMINISTRATOR/${ADMINEMAIL}/g" p4review.cfg.template |\
     sed "s/REPL_COMPLAINFROM/${COMPLAINFROM}/g" |\
     sed "s/REPL_MAILHOST/${MAILHOST}/g" |\
     sed "s/REPL_DNSNAME/${P4DNSNAME}/g" > p4review.cfg
fi

cd /$DD/p4/common/bin

ln -s p4d_${P4DRELNUM}_bin p4d_${INSTANCE}_bin

# Create broker links if broker exists
if [[ -f ${SDP}/Server/Unix/p4/common/bin/p4broker ]]; then 
  P4BRELNUM=`${SDP}/Server/Unix/p4/common/bin/p4broker -V | grep -i Rev. | $AWK -F / '{print $3}'`
  P4BBLDNUM=`${SDP}/Server/Unix/p4/common/bin/p4broker -V | grep -i Rev. | $AWK -F / '{print $4}' | $AWK '{print $1}'`
  [[ -f /$DD/p4/common/bin/p4broker_$P4BRELNUM.$P4BBLDNUM ]] || cp $SDP/Server/Unix/p4/common/bin/p4broker /$DD/p4/common/bin/p4broker_$P4BRELNUM.$P4BBLDNUM
  [[ -L p4broker_${P4BRELNUM}_bin ]] && unlink p4broker_${P4BRELNUM}_bin 
  ln -s p4broker_$P4BRELNUM.$P4BBLDNUM p4broker_${P4BRELNUM}_bin 
  [[ -L p4broker_${INSTANCE}_bin ]] && unlink p4broker_${INSTANCE}_bin 
  ln -s p4broker_${P4BRELNUM}_bin p4broker_${INSTANCE}_bin
  cd $P4DIR/$INSTANCE/bin
  [[ -L p4broker_${INSTANCE} ]] || ln -s $P4DIR/common/bin/p4broker_${INSTANCE}_bin p4broker_${INSTANCE}
  sed "s/REPL_INSTANCE/${INSTANCE}/g" $SDP/Server/Unix/p4/common/etc/init.d/p4broker_instance_init.template > p4broker_${INSTANCE}_init
  chmod +x p4broker_${INSTANCE}_init
fi

# Create P4Web links if P4Web exists
cd /$DD/p4/common/bin
if [[ -x ${SDP}/Server/Unix/p4/common/bin/p4web ]]; then 
  P4WEBRELNUM=`${SDP}/Server/Unix/p4/common/bin/p4web -V | grep -i Rev. | $AWK -F / '{print $3}'`
  P4WEBBLDNUM=`${SDP}/Server/Unix/p4/common/bin/p4web -V | grep -i Rev. | $AWK -F / '{print $4}' | $AWK '{print $1}'`
  [[ -f /$DD/p4/common/bin/p4web_$P4WEBRELNUM.$P4WEBBLDNUM ]] || cp $SDP/Server/Unix/p4/common/bin/p4web /$DD/p4/common/bin/p4web_$P4WEBRELNUM.$P4WEBBLDNUM
  [[ -L p4web_${P4WEBRELNUM}_bin ]] && unlink p4web_${P4WEBRELNUM}_bin 
  ln -s p4web_$P4WEBRELNUM.$P4WEBBLDNUM p4web_${P4WEBRELNUM}_bin 
  [[ -L p4web_${INSTANCE}_bin ]] && unlink p4web_${INSTANCE}_bin 
  ln -s p4web_${P4WEBRELNUM}_bin p4web_${INSTANCE}_bin
  cd $P4DIR/$INSTANCE/bin
  [[ -L p4web_${INSTANCE} ]] || ln -s $P4DIR/common/bin/p4web_${INSTANCE}_bin p4web_${INSTANCE}
  sed "s/REPL_INSTANCE/${INSTANCE}/g" $SDP/Server/Unix/p4/common/etc/init.d/p4web_instance_init.template > p4web_${INSTANCE}_init
  chmod +x p4web_${INSTANCE}_init
fi

# Create p4p links if p4p exists
cd /$DD/p4/common/bin
if [[ -x ${SDP}/Server/Unix/p4/common/bin/p4p ]]; then 
  P4PRELNUM=`${SDP}/Server/Unix/p4/common/bin/p4p -V | grep -i Rev. | $AWK -F / '{print $3}'`
  P4PBLDNUM=`${SDP}/Server/Unix/p4/common/bin/p4p -V | grep -i Rev. | $AWK -F / '{print $4}' | $AWK '{print $1}'`
  [[ -f /$DD/p4/common/bin/p4p_$P4PRELNUM.$P4PBLDNUM ]] || cp $SDP/Server/Unix/p4/common/bin/p4p /$DD/p4/common/bin/p4p_$P4PRELNUM.$P4PBLDNUM
  [[ -L p4p_${P4PRELNUM}_bin ]] && unlink p4p_${P4PRELNUM}_bin 
  ln -s p4p_$P4PRELNUM.$P4PBLDNUM p4p_${P4PRELNUM}_bin 
  [[ -L p4p_${INSTANCE}_bin ]] && unlink p4p_${INSTANCE}_bin 
  ln -s p4p_${P4PRELNUM}_bin p4p_${INSTANCE}_bin
  cd $P4DIR/$INSTANCE/bin
  [[ -L p4p_${INSTANCE} ]] || ln -s $P4DIR/common/bin/p4p_${INSTANCE}_bin p4p_${INSTANCE}
  sed "s/REPL_INSTANCE/${INSTANCE}/g" $SDP/Server/Unix/p4/common/etc/init.d/p4p_instance_init.template | sed "s/REPL_DNSNAME/${P4DNSNAME}/g" > p4p_${INSTANCE}_init
  chmod +x p4p_${INSTANCE}_init
  mkdir -p /$DD/p4/$INSTANCE/cache
fi

if [[ $CLUSTER -eq 1 ]]; then
  cd $P4DIR/common/bin
  ln -s /$DD/p4/common/bin/p4d_${INSTANCE}_bin
fi

if [[ $INSTANCE -ne 1 ]]; then
  ln -s $P4DIR/1/root/license $P4DIR/$INSTANCE/root/license
fi

cd $P4DIR/$INSTANCE/bin
ln -s $P4DIR/common/bin/p4_bin p4_$INSTANCE

ETC_DIR=$SDP/Server/Unix/p4/common/etc

sed "s/REPL_INSTANCE/${INSTANCE}/g" $ETC_DIR/init.d/p4d_instance_init.template > p4d_${INSTANCE}_init
chmod +x p4d_${INSTANCE}_init

sed "s/REPL_INSTANCE/${INSTANCE}/g" $ETC_DIR/init.d/p4dtg_instance_init.template > p4dtg_${INSTANCE}_init
chmod +x p4dtg_${INSTANCE}_init

sed "s/REPL_INSTANCE/${INSTANCE}/g" $ETC_DIR/init.d/p4ftpd_instance_init.template > p4ftpd_${INSTANCE}_init
chmod +x p4ftpd_${INSTANCE}_init

if [ $CASEINSENSITIVE -eq 0 ]; then
  ln -s $P4DIR/common/bin/p4d_${INSTANCE}_bin p4d_$INSTANCE
else
  echo '#!/bin/bash' > p4d_$INSTANCE
  echo P4D=/p4/common/bin/p4d_${INSTANCE}_bin >> p4d_$INSTANCE
  echo 'exec $P4D -C1 "$@"' >> p4d_$INSTANCE
  chmod +x p4d_$INSTANCE
fi

cd $P4DIR
sed "s/REPL_MAILTO/${ADMINEMAIL}/g" /p4/common/etc/cron.d/crontab.template > crontab 
sed "s/REPL_MAILTO/${ADMINEMAIL}/g" /p4/common/etc/cron.d/crontab.replica.template > crontab.replica

cd $P4DIR/${INSTANCE}/bin

if [[ `$ID -u` -eq 0 ]]; then
   chown $OSUSER:$OSGROUP /$DD
   chown $OSUSER:$OSGROUP /$LG
   chown $OSUSER:$OSGROUP /$MD
   chown $OSUSER:$OSGROUP /$DD/p4
   chown $OSUSER:$OSGROUP /$LG/p4
   chown $OSUSER:$OSGROUP /$MD/p4

   chown -h $OSUSER:$OSGROUP /p4
   chown -h $OSUSER:$OSGROUP /p4/$INSTANCE
   chown -h $OSUSER:$OSGROUP /p4/common
   chown $OSUSER:$OSGROUP /p4/*
   
   chown -Rh $OSUSER:$OSGROUP /p4/common
   chown -Rh $OSUSER:$OSGROUP /$DD/p4/common
   chown -Rh $OSUSER:$OSGROUP /$DD/p4/$INSTANCE
   chown -Rh $OSUSER:$OSGROUP /$MD/p4/$INSTANCE
   chown -Rh $OSUSER:$OSGROUP /$LG/p4/$INSTANCE
else
   echo "Not running as root, so chown commands were skipped."
fi

chmod 700 /$DD/p4/$INSTANCE/ssl

chmod -R 750 /$MD/p4
chmod -R 750 /$DD/p4
chmod -R 750 /$LG/p4

if [[ $CLUSTER -eq 1 ]]; then
   touch /$MD/p4/$INSTANCE/root/cluster.active.node
fi

echo "It is recommended that the ${OSUSER}'s umask be changed to 0026 to block world access to Perforce files."
echo "Add umask 0026 to ${OSUSER}'s .bash_profile to make this change."

if [[ $TEST -eq 1 ]]; then
  echo ""
  echo "This was done in TEST mode - please run the following command to see any changes should be"
  echo "applied to your live environment (manually):"
  echo "  diff -r /tmp/p4/$INSTANCE/bin /p4/$INSTANCE/bin"
  echo "  diff -r /tmp/p4/common /p4/common"
  echo "  diff /tmp/p4/common/bin/p4_vars /p4/common/bin/p4_vars"
fi

exit 0
