#!/bin/bash
#------------------------------------------------------------------------------
set -u
#==============================================================================
# Declarations
declare ThisScript=${0##*/}
declare ThisUser=
declare Version=1.1.1
declare -i NoOp=1
declare -i SilentMode=0
declare -i ErrorCount=0
declare HelixBinDir="/p4/sdp/helix_binaries"
declare Cmd=
declare HelixUser=
declare LabelName=
declare Log=
declare H1="=============================================================================="
declare H2="------------------------------------------------------------------------------"
declare -a InstanceList
declare -i InstanceCount=0
#==============================================================================
# Local Functions
function msg () { echo -e "$*"; }
function errmsg () { msg "\\nError: ${1:-Unknown Error}\\n"; ErrorCount+=1; }
function bail () { errmsg "${1:-Unknown Error}"; exit "${2:-1}"; }
#------------------------------------------------------------------------------
# Function: usage (required function)
#
# Input:
# $1 - style, either -h (for short form) or -man (for man-page like format).
# The default is -h.
#
# $2 - error message (optional). Specify this if usage() is called due to
# user error, in which case the given message displayed first, followed by the
# standard usage message (short or long depending on $1). If displaying an
# error, usually $1 should be -h so that the longer usage message doesn't
# obscure the error message.
#
# Sample Usage:
# usage
# usage -h
# usage -man
# usage -h "Incorrect command line usage."
#------------------------------------------------------------------------------
function usage
{
declare style=${1:--h}
declare errorMessage=${2:-Unset}
if [[ "$errorMessage" != Unset ]]; then
echo -e "\\n\\nUsage Error:\\n\\n$errorMessage\\n\\n"
fi
echo "USAGE for $ThisScript v$Version:
$ThisScript [-l <label> -u <P4USER>] [-L <log>] [-si] [-n] [-D]
or
$ThisScript [-h|-man]
"
if [[ $style == -man ]]; then
echo -e "
DESCRIPTION:
This script runs Helix Core upgrades for all SDP instances on a given machine.
OPTIONS:
-l <label_name> -u <P4USER>
Specify the label name, if invoked as a trigger. This script can
be invoked as a trigger with 'p4 label do_upgrade' and saving the
spec. Processing only occurs if the Label name is 'do_upgrade'.
There is no significance to the label itself; it is just a creative
means of using the trigger table to fire this scripte remotely. The
label is neither referenced nor updated.
The P4USER must also be specified, and the user specified must have
a user name that starts with 'super-'.
The expected entry in the Triggers table is:
DoUpgrade form-out label "%//ra/main/scripts/run_upgrade.sh% -l %formname% -u %user%"
-v<n> Set verbosity 1-5 (-v1 = quiet, -v5 = highest).
-L <log>
Specify the path to a log file, or the special value 'off' to disable
logging. By default, all output (stdout and stderr) goes to
/tmp/run_upgrade.<timetamp>.log
NOTE: This script is self-logging. That is, output displayed on the screen
is simultaneously captured in the log file. Do not run this script with
redirection operators like '> log' or '2>&1', and do not use 'tee.'
-si Operate silently. All output (stdout and stderr) is redirected to the log
only; no output appears on the terminal. This cannot be used with
'-L off'.
-y Disable preview mode. By default, this scripts operates in preview mode,
not executing any data-affectingcommands. Specify '-y'for live operation.
-D Set extreme debugging verbosity.
HELP OPTIONS:
-h Display short help message
-man Display man-style help message
FILES:
EXAMPLES:
SEE ALSO:
"
fi
exit 1
}
#==============================================================================
# Command Line Processing
declare -i shiftArgs=0
set +u
while [[ $# -gt 0 ]]; do
case $1 in
(-l|--label) LabelName="$2"; shiftArgs=1;;
(-u|--user) HelixUser="$2"; shiftArgs=1;;
(-h|--help) usage -h;;
(-man|--manual) usage -man;;
(-L|--Log) Log="$2"; shiftArgs=1;;
(-si|--silent) SilentMode=1;;
(-y|--yes) NoOp=0;;
(-D|--DEBUG) set -x;; # Debug; use 'set -x' mode.
(*) usage -h "Unknown arg ($1).";;
esac
# Shift (modify $#) the appropriate number of times.
shift; while [[ $shiftArgs -gt 0 ]]; do
[[ $# -eq 0 ]] && usage -h "Incorrect number of arguments."
shiftArgs=$shiftArgs-1
shift
done
done
set -u
#==============================================================================
# Command Line Parsing
# For operation as a trigger with 'p4 label do_upgrade'. Exit silently if
# the label name is not 'do_upgrade'.
if [[ -n "$LabelName" ]]; then
[[ "$LabelName" == "do_upgrade" ]] || exit 0
fi
if [[ -n "$HelixUser" ]]; then
[[ "$HelixUser" == "super-"* ]] || exit 0
fi
[[ -z "$Log" ]] && Log="/tmp/${ThisScript%.sh}.$(date +'%Y%m%d-%H%M').log"
[[ "$SilentMode" -eq 1 && "$Log" == "off" ]] && usage -h "The '-si' option is not allowed with '-L off'."
[[ "$NoOp" -eq 0 && "$Log" == "off" ]] && usage -h "The '-y' option is not allowed with '-L off'."
#==============================================================================
# Main Program
ThisUser=$(id -u -n)
if [[ "${Log}" != off ]]; then
touch "$Log" || bail "Couldn't touch log file [$Log]."
# Redirect stdout and stderr to a log file.
if [[ "$SilentMode" -eq 0 ]]; then
exec > >(tee "$Log")
exec 2>&1
else
exec >"$Log"
exec 2>&1
fi
fi
msg "${H1}\\nStarting $ThisScript v$Version as $ThisUser@${HOSTNAME%%.*} at $(date)."
msg "SDP Version:\\n$(cat /p4/sdp/Version)"
#------------------------------------------------------------------------------
# Acquire Binaries.
cd "$HelixBinDir" || bail "Could not cd to: $HelixBinDir"
Cmd="./get_helix_binaries.sh"
[[ "$NoOp" -eq 1 ]] && Cmd+=" -n"
msg "Acquiring binaries in $PWD with this command:\\n\\t$Cmd"
if $Cmd; then
msg "Binaries staged OK."
else
bail "Failed to stage new binaries."
fi
#------------------------------------------------------------------------------
# Upgrading instances.
for i in /p4/*/root/db.domain; do
i=${i#/p4/}
i=${i%%/*}
InstanceList[$InstanceCount]="$i"
InstanceCount+=1
done
msg "Upgrading these instances: ${InstanceList[*]}"
for i in "${InstanceList[@]}"; do
Cmd="/p4/common/bin/upgrade.sh $i"
[[ "$NoOp" -eq 0 ]] && Cmd+=" -y"
msg "${H2}\\nUpgrading instance '$i' with this command:\\n\\t$Cmd"
if $Cmd; then
if [[ "$NoOp" -eq 1 ]]; then
msg "Instance $i upgraded OK (DRY RUN)."
else
msg "Instance $i upgraded OK."
fi
else
if [[ "$NoOp" -eq 1 ]]; then
errmsg "Failed to upgrade instance '$i' (DRY RUN)."
else
errmsg "Failed to upgrade instance '$i'."
fi
fi
done
if [[ "$ErrorCount" -eq 0 ]]; then
msg "All processing completed successfully."
else
errmsg "Processing completed, but $ErrorCount errors were encountered."
fi
msg "\\nAcquiring binaries and upgrading $InstanceCount instances took $((SECONDS/3600)) hours $((SECONDS%3600/60)) minutes $((SECONDS%60)) seconds.\\n"
[[ "$Log" != off ]] && msg "\\nLog is: $Log\\n${H1}"
exit "${ErrorCount}"