- #!/bin/bash
- #==============================================================================
- # Copyright and license info is available in the LICENSE file included with
- # the Helix Management System (HMS), and also available online:
- # https://swarm.workshop.perforce.com/projects/perforce_software-hms/view/main/LICENSE
- #------------------------------------------------------------------------------
- #==============================================================================
- # Declarations and Environment
- # Allow override of P4U_HOME, which is set only when testing P4U scripts.
- export P4U_HOME=${P4U_HOME:-/p4/common/bin}
- export P4U_LIB=${P4U_LIB:-/p4/common/lib}
- export P4U_ENV=$P4U_LIB/p4u_env.sh
- export P4U_LOG=off
- export VERBOSITY=${VERBOSITY:-3}
- # Environment isolation. For stability and security reasons, prepend
- # PATH to include dirs where known-good scripts exist.
- # known/tested PATH and, by implication, executables on the PATH.
- export PATH=$P4U_HOME:$PATH:~/bin:.
- export P4CONFIG=${P4CONFIG:-.p4config}
- [[ -r "$P4U_ENV" ]] || {
- echo -e "\\nError: Cannot load environment from: $P4U_ENV\\n\\n"
- exit 1
- }
- declare BASH_LIBS=$P4U_ENV
- BASH_LIBS+=" $P4U_LIB/libcore.sh"
- BASH_LIBS+=" $P4U_LIB/libp4u.sh"
- for bash_lib in $BASH_LIBS; do
- # shellcheck disable=SC1090
- source "$bash_lib" ||\
- { echo -e "\\nFATAL: Failed to load bash lib [$bash_lib]. Aborting.\\n"; exit 1; }
- done
- declare Version=1.5.0
- declare -i SilentMode=0
- declare TicketExpiration=
- declare TicketStatus=
- declare SuperAccessStatus=
- declare SkipInstanceList=sample
- declare NewInstanceList=
- declare -i DoPreflight=1
- declare -i PreflightAccessOK=1
- declare -i PreflightEnvOK=1
- declare -i Skipped=0
- declare HTCfgFile=/p4/common/config/HelixTopology.cfg
- declare SDPEnvFile=/p4/common/bin/p4_vars
- declare InstanceEnvFile=
- declare InstanceList=
- declare Program=Unset
- declare ProgramPath=
- declare ProgramArgs=
- export P4USER=
- export P4TICKETS=/p4/hms/.p4tickets
- export P4TRUST=/p4/hms/.p4trust
- export P4ENVIRO=/dev/null/.p4enviro
- # shellcheck disable=SC1090 disable=SC2146 disable=SC2116
- P4USER=$(echo "$(source "$SDPEnvFile" hms; echo "$P4USER")")
- unset P4CONFIG
- export VERBOSITY=3
- #==============================================================================
- # Local Functions
- #------------------------------------------------------------------------------
- # Function: terminate
- function terminate
- {
- # Disable signal trapping.
- trap - EXIT SIGINT SIGTERM
- vvmsg "$THISSCRIPT: EXITCODE: $OverallReturnStatus"
- # Stop logging.
- [[ "${P4U_LOG}" == off ]] || stoplog
- # Don't litter.
- cleanTrash
- # With the trap removed, exit.
- exit "$OverallReturnStatus"
- }
- #------------------------------------------------------------------------------
- # 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
- # errror, usually $1 should be -h so that the longer usage message doesn't
- # obsure 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 [[-i <instance1>[,<instance2>,...]] [-sk <instance1>[,<instance2>,...]]] [-L <log>] [-si] [-v<n>] [-n] [-D] [<program> [<program arguments ...>]]
- or
- $THISSCRIPT [-h|-man|-V]
- "
- if [[ $style == -man ]]; then
- echo -e "
- DESCRIPTION:
- This script runs a preflight check, or a command you specify, against
- all Helix instances defined in the Helix Topology configuration file.
- If no arguments are supplied, verifies that all instances can be
- centrally managed with 'p4' commands from the current host. It does
- this by verifying that a Perforce command can execute with super user
- access and has a long-term ticket for each instance. The $P4TICKETS
- and $P4TRUST files are effectively verified with the preflight
- check.
- OPTIONS:
- -i <instance1>[,<instance2>,...]
- Specify a comma-delimited list of instances to operate on.
- By default, all instances defined in the Helix Topology configuration
- file are operated on.
- -sk <instance1>[,<instance2>,...]
- Specify a comma-delimited list of instances to ignore for processing purposes.
- By default, the instance named 'sample' is skipped, the equivalent of specifying
- '-sk sample'. Specify '-i none' to to process all instances including the 'sample'
- instance (if defined).
- -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, output (stdout and stderr) are not captured.
- When -L is used, this script is self-logging. That is, output displayed
- on the screen is simultaneously captured in the log file. When -L is used,
- 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'.
- This is useful when running from cron, as it prevents automatic
- email from being sent by cron directly, as it does when a script called
- from cron generates any output.
- -n No-Op. Prints commands instead of running them.
- -D Set extreme debugging verbosity.
- HELP OPTIONS:
- -h Display short help message
- -man Display man-style help message
- -V Dispay version info for this script and its libraries.
- FILES:
- Helix Topology Config file:
- $HTCfgFile
- Cental tickets file:
- $P4TICKETS
- Cental trust file:
- $P4TRUST
- EXAMPLES:
- Example 1: Preflight Chcek
- With no arguments, do a quick preflight check to ensure that
- all configured instances can be managed, and that shell envionment
- files for all instances exist:
- $THISSCRIPT
- Example 2: Shell Envionment Check
- Check the envionment for instance 1:
- $THISSCRIPT -i 1 p4 set
- WARNING: This script overrides environment settings for
- P4PORT, P4TICKETS, P4TRUST, and P4ENVIRO, so settings for
- these values may not match what is defined by setting the
- SDP environment in the usual way, i.e.:
- source $SDPEnvFile N # where N is the instance
- Example 3: Server Version Check for all instances
- $THISSCRIPT p4 -ztag -F %serverVersion% info -s
- Example 4: Server Version Check for all instances, with
- higher verbosity ('-v4') to display each instance as the command is run:
- $THISSCRIPT p4 -v4 -ztag -F %serverVersion% info -s
- "
- fi
- exit 1
- }
- #==============================================================================
- # Command Line Processing
- declare -i shiftArgs=0
- set +u
- while [[ $# -gt 0 ]]; do
- case $1 in
- (-i) InstanceList="${2//,/ }"; shiftArgs=1;;
- (-sk) SkipInstanceList="${2/,/ }"; shiftArgs=1;;
- (-h) usage -h;;
- (-man) usage -man;;
- (-V) show_versions; exit 1;;
- (-v1) export VERBOSITY=1;;
- (-v2) export VERBOSITY=2;;
- (-v3) export VERBOSITY=3;;
- (-v4) export VERBOSITY=4;;
- (-v5) export VERBOSITY=5;;
- (-L) export P4U_LOG=$2; shiftArgs=1;;
- (-si) SilentMode=1;;
- (-n) export NO_OP=1;;
- (-D) set -x;; # Debug; use 'set -x' mode.
- (-*) usage -h "Unknown arg ($1).";;
- (*)
- Program="$1"
- shift
- # shellcheck disable=SC2124
- ProgramArgs=$@
- break
- ;;
- 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 Verification
- [[ $SilentMode -eq 1 && $P4U_LOG == off ]] && \
- usage -h "Cannot use '-si' with '-L off'."
- [[ "$Program" == Unset ]] || DoPreflight=0
- # Determine the list of instances to process, accounting for any instances
- # skipped.
- [[ -n "$InstanceList" ]] ||\
- InstanceList=$(grep '^INSTANCE' "$HTCfgFile" | cut -d '|' -f 2)
- if [[ $SkipInstanceList != "none" ]]; then
- NewInstanceList=
- for i in $InstanceList; do
- Skipped=0
- for s in $SkipInstanceList; do
- if [[ "$s" == "$i" ]]; then
- Skipped=1
- break
- fi
- done
- # If the instance isn't in the skip list, add it to the list of instances.
- [[ $Skipped -eq 1 ]] || NewInstanceList+=" $i"
- done
- # shellcheck disable=SC2116
- InstanceList="$(echo "$NewInstanceList")"
- vmsg "Instance List: $InstanceList (excluding $SkipInstanceList)"
- fi
- #==============================================================================
- # Main Program
- trap terminate EXIT SIGINT SIGTERM
- declare -i OverallReturnStatus=0
- declare -i ExitCode=0
- if [[ "${P4U_LOG}" != off ]]; then
- touch "${P4U_LOG}" || bail "Couldn't touch log file [${P4U_LOG}]."
- # Redirect stdout and stderr to a log file.
- if [[ $SilentMode -eq 0 ]]; then
- exec > >(tee "${P4U_LOG}")
- exec 2>&1
- else
- exec >"${P4U_LOG}"
- exec 2>&1
- fi
- initlog
- fi
- if [[ "$DoPreflight" -eq 1 ]]; then
- # shellcheck disable=SC2116
- msg "${H1}\\nPreflight Check for instances:\\n$(echo "$InstanceList")\\n"
- msg "Accesss Preflight Check\\n${H2}"
- printf "%-12s %-24s %-5s %-s\\n" "Instance" "P4PORT" "Super" "Ticket Status"
- printf "%-12s %-24s %-5s %-s\\n" "------------" "------------------------" "-----" "-----------------------------------------"
- for i in $InstanceList; do
- active=$(grep "COMPONENT|$i|p4d-mc|" "$HTCfgFile"|cut -d '|' -f 7)
- [[ $active == 0 ]] && continue
- host=$(grep "COMPONENT|$i|p4d-mc|" "$HTCfgFile"|cut -d '|' -f 5)
- port=$(grep "COMPONENT|$i|p4d-mc|" "$HTCfgFile"|cut -d '|' -f 8)
- if [[ $port == "ssl:"* ]]; then
- export P4PORT="ssl:$host:${port#ssl:}"
- else
- export P4PORT="$host:$port"
- fi
- TicketExpiration=$(p4 -ztag -F %TicketExpiration% -p "$P4PORT" -u "$P4USER" login -s 2>/dev/null)
- if [[ -n "$TicketExpiration" && "$TicketExpiration" -gt "$((60*60*24*31))" ]]; then
- TicketStatus="OK with long-term ticket."
- elif [[ -n "$TicketExpiration" && "$TicketExpiration" -gt "60" ]]; then
- TicketStatus="OK with short-term ticket ($TicketExpiration seconds)."
- else
- TicketStatus="ERROR, ticket not available for $P4USER on $P4PORT."
- PreflightAccessOK=0
- fi
- if [[ "$TicketStatus" == "OK"* ]]; then
- ProtectCheck=$(p4 -ztag -F %Protections0% -u "$P4USER" -p "$P4PORT" protect -o 2>/dev/null)
- if [[ -n "$ProtectCheck" ]]; then
- SuperAccessStatus="OK"
- else
- SuperAccessStatus="Error"
- PreflightAccessOK=0
- fi
- else
- SuperAccessStatus="Unknown"
- PreflightAccessOK=0
- fi
- printf "%-12s %-24s %-5s %-s\\n" "$i" "$P4PORT" "$SuperAccessStatus" "$TicketStatus"
- done
- if [[ "$PreflightAccessOK" -eq 1 ]]; then
- msg "\\nVerified: Access OK. All instances can be accessed as super from this host."
- else
- errmsg "Preflight Access check failed. See results above."
- OverallReturnStatus=1
- fi
- msg "Environment Preflight Check\\n${H2}"
- for i in $InstanceList; do
- active=$(grep "COMPONENT|$i|p4d-mc|" "$HTCfgFile"|cut -d '|' -f 7)
- [[ $active == 0 ]] && continue
- InstanceEnvFile=/p4/common/config/p4_${i}.vars
- if [[ ! -r "$InstanceEnvFile" ]]; then
- errmsg "Missing instance-specific environment file: $InstanceEnvFile"
- PreflightEnvOK=0
- fi
- done
- if [[ "$PreflightEnvOK" -eq 1 ]]; then
- msg "\\nVerified: Environment is OK, all instances have environment files."
- else
- errmsg "Preflight Environment check failed. See missing files listed above."
- OverallReturnStatus=1
- fi
- fi
- if [[ "$Program" != Unset ]]; then
- if [[ $Program == /* || $Program == \.* ]]; then
- # Non-path depedent, absolute or relative path specified.
- ProgramPath=$Program
- else
- # Path-dependent path specified.
- ProgramPath="$(command -v "$Program")"
- fi
- [[ -z "$ProgramPath" ]] && \
- bail "The specified program [$Program] cannot be found. Aborting.\\n"
- [[ ! -r "$ProgramPath" ]] && \
- bail "The specified program [$Program] cannot be found. Aborting.\\n"
- [[ ! -x "$ProgramPath" ]] && \
- bail "The specified program [$Program] is not executable. Aborting.\\n"
- for i in $InstanceList; do
- active=$(grep "COMPONENT|$i|p4d-mc|" "$HTCfgFile"|cut -d '|' -f 7)
- [[ $active == 0 ]] && continue
- vmsg "For instance $i calling $Program $ProgramArgs"
- InstanceEnvFile=/p4/common/config/p4_${i}.vars
- if [[ -r "$InstanceEnvFile" ]]; then
- if [[ $NO_OP -eq 0 ]]; then
- # shellcheck disable=SC1090
- source "$SDPEnvFile" "$i"
- export P4ENVIRO=/dev/null/.p4enviro
- export P4CONFIG=FileThatDoesNotExist
- export P4TICKETS=/p4/hms/.p4tickets
- export P4TRUST=/p4/hms/.p4trust
- host=$(grep "COMPONENT|$i|p4d-mc|" "$HTCfgFile"|cut -d '|' -f 5)
- port=$(grep "COMPONENT|$i|p4d-mc|" "$HTCfgFile"|cut -d '|' -f 8)
- if [[ $port == "ssl:"* ]]; then
- export P4PORT="ssl:$host:${port#ssl:}"
- else
- export P4PORT="$host:$port"
- fi
- $Program $ProgramArgs
- ExitCode=$?
- if [[ $ExitCode -ne 0 ]]; then
- warnmsg "Non-zero exit code returned: $ExitCode"
- OverallReturnStatus=1
- fi
- else
- msg "NO_OP: For instance $i, would run: $Program $ProgramArgs"
- fi
- else
- errmsg "Missing instance-specific environment file: $InstanceEnvFile"
- OverallReturnStatus=1
- fi
- done
- fi
- if [[ $OverallReturnStatus -eq 0 ]]; then
- msg "${H}\\nAll processing completed successfully.\\n"
- else
- msg "${H}\\nProcessing completed, but with errors. Scan above output carefully.\\n"
- fi
- msg "That took $((SECONDS/3600)) hours $((SECONDS%3600/60)) minutes $((SECONDS%60)) seconds.\\n"
- # See the terminate() function, which is really where this script exits.
- exit $OverallReturnStatus
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#2 | 30242 | C. Thomas Tyler | Updated package reference in LICENSE to refer to HMS rather than SDP license. | 12 months ago | |
#1 | 29182 | C. Thomas Tyler | Moved HMS files from /p4/common/bin -> /p4/common/site/bin. Moved HMS files from /p4/c...ommon/lib -> /p4/common/site/lib. Removed dependency on SDP libs so that HMS can be deployed with a wider variety of SDP versions. « |
2 years ago | |
//guest/perforce_software/hms/dev/p4/common/bin/irun | |||||
#4 | 27694 | C. Thomas Tyler | Copyright Update; non-functional change. | 4 years ago | |
#3 | 25748 | C. Thomas Tyler | Made irun shellcheck compliant. | 6 years ago | |
#2 | 25683 | C. Thomas Tyler | Tweaked to honor 'Active' setting for components in the Helix Topology File -- if inactiv...e, ignore it. « |
6 years ago | |
#1 | 25682 | C. Thomas Tyler | Added 'irun' (instance run) to simplfy SDP Fleet Management. | 6 years ago |