# hms_actions.sh
Version=1.0.23
#==============================================================================
# Copyright and license info is available in the LICENSE file included with
# the Server Deployment Package (SDP), and also available online:
# https://swarm.workshop.perforce.com/projects/perforce-software-sdp/view/main/LICENSE
#------------------------------------------------------------------------------
#==============================================================================
# HMS Library Functions.
#------------------------------------------------------------------------------
# change_component_status (start/stop, $component, $tag)
# $1 - start or stop
# $2 - fully qualified component name (<instance>:<component>, e.g.
# 1:p4broker01).
# $3 - optional tag, used only for brokers, e.g. "dfm"
#------------------------------------------------------------------------------
function change_component_status () {
vvmsg "CALL: change_component_status ($*)"
declare command=${1:-Unset}
declare fqComponent=${2:-Unset}
declare tag=${3:-""}
declare componentType=
declare componentCommand=
declare componentMasterHost=
declare instance=
declare initScript=
declare output=$P4U_TMPDIR/ccs.${fqComponent/:/_}.$RANDOM$RANDOM
declare -i exitCode=0
if [[ $fqComponent != *":"* ]]; then
errmsg "Unable to start/stop entire instance yet; this will be implemented later."
return 1
fi
instance=${fqComponent%%:*}
if [[ $command =~ ^(start|stop)$ ]]; then
componentType=${ComponentType[$fqComponent]:-Unset}
componentMasterHost=${ComponentMasterHost[$fqComponent]:-Unset}
case "$componentType" in
(p4d-*) initScript="/p4/$instance/bin/p4d_${instance}_init";;
(p4broker) initScript="/p4/$instance/bin/p4broker_${instance}_init";;
(p4p) initScript="/p4/$instance/bin/p4p_${instance}_init";;
(*)
errmsg "Don't know how to start component [$fqComponent] of type [$componentType]."
return 1
;;
esac
if [[ -n "$initScript" ]]; then
componentCommand="$initScript $command $tag"
else
errmsg "No init script for component [$fqComponent]."
return 1
fi
runRemoteCmd "$componentMasterHost" "$componentCommand" \
"Executing $command on $componentType $fqComponent on $componentMasterHost" 1 1 0
exitCode=$RCMDEXITCODE
[[ $exitCode -eq 0 ]] || return 1
else
errmsg "Unrecognized start/stop command [$command]."
return 1
fi
return 0
}
#------------------------------------------------------------------------------
# Function: down_for_maintenance ($subCommand, $instance)
# $1 - on, off, or status
# $2 - Instance
#------------------------------------------------------------------------------
function down_for_maintenance () {
vvmsg "CALL: down_for_maintenance ($*)"
declare subCommand=${1:-Unset}
declare instance=${2:-Unset}
declare -i summaryExitCode=0
[[ $instance == Unset || $subCommand == Unset ]] && return 1
msg "Getting list of managed components for instance $instance."
componentList=$(get_component_list "$instance" 1)
if [[ $? -ne 0 ]]; then
errmsg "Could not get a list of valid components for instance $instance. Aborting dfm."
return 1
fi
# Put all brokers into Down For Maintenance mode (on), or bring
# them out (off), or check on them (status).
msg "Setting Down For Maintenance message on all available brokers."
for fqComponent in $componentList; do
componentType=${ComponentType[$fqComponent]:-Unset}
[[ $componentType == p4broker ]] || continue
componentMasterHost=${ComponentMasterHost[$fqComponent]:-Unset}
if [[ $subCommand == on ]]; then
change_component_status stop "$fqComponent"
change_component_status start "$fqComponent" dfm
elif [[ $subCommand == off ]]; then
change_component_status stop "$fqComponent" dfm
change_component_status start "$fqComponent"
elif [[ $subCommand == status ]]; then
get_component_status "$fqComponent" 1 dfm
else
errmsg "Unknown dfm subcommand [$subCommand]."
return 1
fi
done
}
#------------------------------------------------------------------------------
# Function: failover_instance ($instance, $path, $style)
#
# This function executes failover of all managed components for the instance.
#
# This is called by failover(), which does data verification. This routine
# can thus dispense with some of the "defensive programming" done in
# failover(), allowing us to assume our data model (implemenented primarily
# with associative arrays) has what we need.
#------------------------------------------------------------------------------
function failover_instance () {
vvmsg "CALL: failover_instance ($*)"
declare instance=${1:-Unset}
declare path=${2:-Unset}
declare style=${3:-Unset}
declare componentList=
declare componentType=
declare componentMasterHost=
declare brokerDfmOutput=
declare cmd=
declare -i summaryExitCode=0
[[ $instance == Unset || $path == Unset || $style == Unset ]] && return 1
msg "Getting list of managed components for instance $instance."
componentList=$(get_component_list "$instance" 1)
if [[ $? -ne 0 ]]; then
errmsg "Could not get a list of valid components for instance $instance. Aborting failover."
return 1
fi
# Put all (available) brokers in Down For Maintenance mode.
msg "Setting Down For Maintenance message on all available brokers."
down_for_maintenance on $instance
for fqComponent in $componentList; do
componentType=${ComponentType[$fqComponent]:-Unset}
[[ $componentType == p4d-e ]] || break
failover_p4d_edge "$path" "$fqComponent" "$style" ||\
summaryExitCode=1
done
for fqComponent in $componentList; do
componentType=${ComponentType[$fqComponent]:-Unset}
[[ $componentType == p4d-mc ]] || break
failover_p4d_master "$path" "$fqComponent" "$style" ||\
summaryExitCode=1
done
for fqComponent in $componentList; do
componentType=${ComponentType[$fqComponent]:-Unset}
case "$componentType" in
(p4p|p4dtg|p4web|p4gf|swarm)
warnmsg "Failover for component type [$componentType] not impelmented."
;;
(Unset)
errmsg "ComponentType not defined for component $component."
summaryExitCode=1
;;
esac
done
# Finally, bring all (available) brokers back online.
down_for_maintenance off $instance
return $summaryExitCode
}
#------------------------------------------------------------------------------
# Function: failover_p4d_edge ($path, $fqComponent, $style)
#------------------------------------------------------------------------------
function failover_p4d_edge () {
vvmsg "CALL: failover_p4d_edge ($*)"
declare path=${1:-Unset}
declare fqComponent=${2:-Unset}
declare style=${3:-Unset}
declare backupHost=
declare instance=
[[ $path == Unset || $fqComponent == Unset || $style == Unset ]] && return 1
instance=${fqComponent%%:*}
### THIS IS A STUB FUNCTION.
### WORK IN PROGRESS.
}
#------------------------------------------------------------------------------
# Function: failover_p4d_master ($path, $fqComponent, $style)
#------------------------------------------------------------------------------
function failover_p4d_master () {
vvmsg "CALL: failover_p4d_master ($*)"
declare path=${1:-Unset}
declare fqComponent=${2:-Unset}
declare style=${3:-Unset}
declare masterHost=
declare backupHost=
declare instance=
declare failoverOutput=
declare fqPath=
### DEMO NOTE: This ServerID of the master, typically 'master'. Hard coded here for demo,
### but this needs to determined from the master server and persisted/configured, since
### it won't always be 'master' (e.g. in servers with P4AUTH set, it must be different). EDITME
declare newServerID=master
declare -i exitCode=0 summaryExitCode=0
[[ $path == Unset || $fqComponent == Unset || $style == Unset ]] && return 1
instance=${fqComponent%%:*}
fqPath=$instance:$path
masterHost=${ComponentMasterHost[$fqComponent]:-Unset}
backupHost=${ComponentBackupHost[$fqComponent]:-Unset}
failoverType=${FailoverType[$fqPath]:-Unset}
if [[ $failoverType == Local ]]; then
failoverOutput=$LOGS/failover.${fqComponent/:/_}.Local.out
vmsg "Running: ssh -q -l $OSUSER $masterHost \"$HMS_SCRIPTS/failover_p4d_local.sh I=$instance S=$style NO_OP=$NO_OP\""
ssh -q -l $OSUSER $masterHost "$HMS_SCRIPTS/failover_p4d_local.sh $instance $style $NO_OP" > $failoverOutput 2>&1
exitCode=$?
cat $failoverOutput
msg "\nEXIT_CODE: $exitCode"
summaryExitCode=$exitCode
elif [[ $failoverType == MO || $failoverType == Full ]]; then
failoverOutput=$LOGS/failover.${fqComponent/:/_}.$failoverType.old_master.log
# The difference between Scheduled and Unscheduled failover is partly one
# of expectations. In Unscheduled Failover, we don't expect the master
# to respond. But in either case, we do our best to avoid split brain,
# and try to shut it down.
if [[ $style == Scheduled ]]; then
msg "Shutting down master server for Scheduled Failover. We expect it to shutdown cleanly."
else
msg "Attempting shutdown of master server for Unscheduled Failover. It may or may not respond."
fi
runRemoteCmd "$masterHost" \
"$HMS_SCRIPTS/failover_p4d_from_this_host.sh $instance $style $failoverType $backupHost $NO_OP" \
"Failing over from $masterHost. Running: failover_p4d_from_this_host.sh I=$instance S=$style T=$failoverType BH=$backupHost NO_OP=$NO_OP" 1 1 0
exitCode=$RCMDEXITCODE
if [[ $exitCode -ne 0 ]]; then
if [[ $style == Scheduled ]]; then
errmsg "Shutdown of master server FAILED during Scheduled Failover. Aborting failover of $fqComponent."
return 1
else
warnmsg "Shutdown of master server failed during Unscheduled Failover. Continuing with failover of $fqComponent."
fi
fi
runRemoteCmd "$backupHost" \
"$HMS_SCRIPTS/failover_p4d_to_this_host.sh $instance $style $failoverType $newServerID $NO_OP" \
"Failing over to $backupHost. Running: $HMS_SCRIPTS/failover_p4d_to_this_host.sh I=$instance S=$style T=$failoverType SID=$newServerID NO_OP=$NO_OP" 1 1 0
exitCode=$RCMDEXITCODE
if [[ $exitCode -ne 0 ]]; then
errmsg "Failover of $fqComponent to backup host [$backupHost] failed."
summaryExitCode=1
fi
else
errmsg "Unknown failover type ($failoverType), aborting failover of component $fqComponent."
return 1
fi
return $summaryExitCode
}
#------------------------------------------------------------------------------
# Function: failover ($path, $scope, $style)
#------------------------------------------------------------------------------
function failover () {
vvmsg "CALL: failover ($*)"
declare path=${1:-Unset}
declare scope=${2:-Unset}
declare style=${3:-Unset}
declare scopeType=
declare scopeHost=
declare scopeInstance=
declare fqPath=
declare instance=
declare instanceList=
declare iPath=
declare pathActive=
declare failoverType=
declare masterHost=
declare backupHost=
declare reply=Unset
declare -i found
declare -i status=0
# Validate instance scope.
if [[ $scope == "i:"* ]]; then
scopeType=Instance
scopeInstance=${scope#i:}
found=0; for instance in ${!InstanceManaged[*]}; do
if [[ $scopeInstance == $instance ]]; then
found=1
break
fi
done
if [[ $found -eq 0 ]]; then
errmsg "Invalid SDP instance specified with scope of $scope."
return 1
fi
# Validate host scope.
elif [[ $scope == "h:"* ]]; then
scopeType=Host
scopeHost=${scope#h:}
found=0; for host in ${FailoverMasterHost[*]}; do
if [[ $scopeHost == $host ]]; then
found=1
break
fi
done
if [[ $found -eq 0 ]]; then
errmsg "Invalid failover host specified with scope of $scope."
return 1
fi
else
errmsg "Badly formatted scope value [$scope]."
return 1
fi
if [[ $scopeType == Instance ]]; then
msg "Verified: Scope instance [$scopeInstance] is valid."
else
msg "Verified: Scope host [$scopeHost] is valid."
fi
# Verify the specified path is valid and active for each instance.
if [[ $scopeType == Host ]]; then
msg "Finding instances mastered on host $scopeHost."
found=0; for instance in ${!InstanceManaged[*]}; do
fqPath="$instance:$path"
pathActive=${FailoverActive[$fqPath]:-Unset}
instanceMasterHost="${InstanceMasterHost[$instance]:-Unset}"
[[ $scopeHost == $instanceMasterHost ]] || continue
if [[ $pathActive == 1 ]]; then
msg "Verified: Failover path [$path] is active for instance [$instance]."
elif [[ $pathActive == 0 ]]; then
warnmsg "Failover path [$path] is inactive for instance [$instance]. Skipping it."
continue
else
errmsg "No failover path [$path] is configured for instance [$instance]. Skipping it."
status=1
continue
fi
# Next, confirm we have a configured target failover host (unless
# FailoverType is 'local').
failoverType=${FailoverType[$fqPath]:-Unset}
if [[ $failoverType =~ ^(Full|MO)$ ]]; then
backupHost=${FailoverBackupHost[$fqPath]:-Unset]}
if [[ $backupHost == Unset ]]; then
errmsg "No backup host configured for instance:path [$fqPath]. Skipping it."
status=1
continue
else
msg "Instance $instance will failover from $scopeHost to $backupHost."
fi
elif [[ $failoverType == Local ]]; then
msg "Local Failover will use offline databases for instance $instance on host [$masterHost]."
backupHost=localhost
else
errmsg "Could not determine failover type for [$fqPath]. Skipping it."
status=1
continue
fi
if [[ $found -eq 0 ]]; then
found+=1
instanceList="$instance"
else
instanceList+=" $instance"
fi
done
if [[ $found -gt 0 ]]; then
msg "$found instance(s) masterd on $scopeHost are targeted for failover: $instanceList."
else
errmsg "No instances mastered on host $scopeHost. Aborting failover."
return 1
fi
else
instance=$scopeInstance
instanceList="$instance"
fqPath="$instance:$path"
pathActive=${FailoverActive[$fqPath]:-Unset}
if [[ $pathActive == 1 ]]; then
msg "Verified: Failover path [$path] is active for instance [$instance]."
elif [[ $pathActive == 0 ]]; then
errmsg "Failover path [$path] is inactive for instance [$instance]. Aborting."
return 1
else
errmsg "No failover path [$path] is configured for instance [$instance]. Aborting."
return 1
fi
failoverType=${FailoverType[$fqPath]:-Unset}
masterHost=${InstanceMasterHost[$instance]:-Unset}
if [[ $masterHost == Unset ]]; then
errmsg "No master host is configured for instance [$instance]. Aborting."
return 1
fi
if [[ $failoverType =~ ^(Full|MO)$ ]]; then
backupHost=${FailoverBackupHost[$fqPath]:-Unset]}
if [[ $backupHost == Unset ]]; then
errmsg "No backup host configured for instance:path [$fqPath]. Aborting."
return 1
else
msg "Instance $instance will failover from $masterHost to $backupHost."
fi
elif [[ $failoverType == Local ]]; then
msg "Local Failover will use offline databases for instance $instance on host [$masterHost]."
backupHost=localhost
else
errmsg "Could not determine failover type for [$fqPath]. Skipping it."
return 1
fi
fi
# Confirm user intent.
if [[ $Interactive -eq 1 ]]; then
while [[ $reply == Unset ]]; do
echo -n -e "\nConfirm your intent to initiate failover: [Y/y/N/n]: "
read -e reply
[[ ${reply^^} == Y || ${reply^^} == N ]] && break
msg "\nInvalid input specified ('$reply'), specify Y or N only.\n"
reply=Unset
done
else
msg "Failover intent confirmed non-interactively with '-y'."
reply=Y
fi
if [[ ${reply^^} == N ]]; then
msg "Failover not confirmed. Failover aborted."
return 1
fi
msg "Starting Failover for SDP instance(s): $instanceList."
for instance in $instanceList; do
failover_instance "$instance" "$path" "$style"
done
return $status
}
#------------------------------------------------------------------------------
# Function: get_component_list ($target, $onlyManaged)
#
# Given a target as specified on the command line, return a valid list of
# components, or return 1 if we fail to return a valid list of components.
#
# The target may look like: all|<instance>[:<component>]
#
# If called with a specified component, i.e. something like 1:p4d01, then
# show a warning if that component is not managed.
#
# If called with 'all' or an instance name, get the list of all defined
# components (globally or for the specified instance), regardless of whether
# they are managed.
#
# Output: The output to stdout is the valid component list. Any warnings or
# errors are sent to stderr. An exit code of 0 indicates valid components
# were returned.
#
# Sample Usage: list=$(get_component_list "abc") || bail "No valid instances!"
#
#------------------------------------------------------------------------------
function get_component_list () {
vvmsg "CALL: get_component_list ($*)"
declare target=${1:-Unset}
declare onlyManaged=${2:-0}
declare component=
declare fqComponent=
declare instanceComponents=
declare componentList=
declare componentManaged=
[[ $target == Unset ]] && return 1
if [[ $target == "all" ]]; then
componentList=""
for component in ${!ComponentManaged[*]}; do
# Build a list of all define components, or only managed ones,
# depending on whether $onlyManaged.
if [[ $onlyManaged -eq 1 ]]; then
componentManaged=${ComponentManaged[$component]:-Invalid}
if [[ $componentManaged == 1 ]]; then
componentList+=" $component"
elif [[ $componentManaged == Invalid ]]; then
errnmsg "Component $target is invalid." >&2
fi
else
componentList+=" $component"
fi
done
componentList=$(echo $componentList)
elif [[ $target == *":"* ]]; then
# If target contains a colon, user specified a single component
# named as "instance:component".
componentList=$target
componentManaged=${ComponentManaged[$target]:-Invalid}
if [[ $componentManaged != Invalid ]]; then
if [[ $componentManaged -eq 0 ]]; then
warnmsg "Component $target is not managed by HMS." >&2
fi
else
errmsg "The specified component $target is invalid." >&2
return 1
fi
else
# Get all components for a given instance. In this case, the
# $target was specified as just an SDP instance name.
instanceComponents=${InstanceComponents[$target]:-Unset}
if [[ $instanceComponents == Unset ]]; then
errmsg "No components configured for instance $target." >&2
return 1
fi
componentList=
for component in $instanceComponents; do
fqComponent=$target:$component
# Build a list of all define components, or only managed ones,
# depending on whether $onlyManaged.
if [[ $onlyManaged -eq 1 ]]; then
componentManaged=${ComponentManaged[$fqComponent]:-Invalid}
if [[ $componentManaged == 1 ]]; then
componentList+=" $fqComponent"
elif [[ $componentManaged == Invalid ]]; then
errnmsg "Component $fqComponent is invalid." >&2
fi
else
componentList+=" $fqComponent"
fi
done
componentList=$(echo $componentList)
fi
if [[ -n "$componentList" ]]; then
echo $componentList
else
return 1
fi
return 0
}
#------------------------------------------------------------------------------
# Function: get_component_status ($component, $optimistic, $tag)
#
# Input:
# $1 - A fully qualified component name of the form <Instance>:<ComponentName>
#
# $2 - "Optimistic" setting, 1 or 0 (the default). By default, components that
# don't yet have status logic coded report as failed. If 1, components of
# known types report as OK. Components of unknown type always report as
# failed. (Any such components should be marked inactive in the topology
# config file).
#
# $3 - optional tag for broker components, e.g. 'dfm'.
#------------------------------------------------------------------------------
function get_component_status () {
vvmsg "CALL: get_component_status ($*)"
declare component=${1:-Unset}
declare optimistic=${2:-0}
declare tag=${3:-default}
declare instance=
declare componentType=
declare componentHost=
declare componentURL=
declare componentP4PORT=
declare componentStatusCmd=
declare -i componentStatusCode=
declare componentStatusMsg=
declare componentVersion=
declare brokerStatusFile=$P4U_TMPDIR/broker_status.${component/:/_}.out
[[ $component == Unset ]] && return 1
get_component_version "$component"
componentVersion=${ComponentVersion[$component]}
instance=${component%%:*}
componentType=${ComponentType[$component]:-Unset}
componentURL=${ComponentURL[$component]:-Unset}
componentManaged=${ComponentManaged[$component]:-Unset}
componentMasterHost=${ComponentMasterHost[$component]:-Unset}
if [[ $componentManaged == 1 ]]; then
case "$componentType" in
(p4d-mc|p4d-e|p4d-r)
componentP4PORT="${ComponentMasterHost[$component]:-Unset}:$componentURL"
componentStatusCmd="$P4BIN -s -p $componentP4PORT info -s"
componentStatusCode=0
run "$componentStatusCmd" \
"3:Checking status for $component of type $componentType.|4:Checking with command: $componentStatusCmd" 0 0 ||\
componentStatusCode=1
;;
(p4broker)
componentStatusCmd="/p4/${instance}/bin/p4broker_${instance}_init status $tag"
if [[ $componentMasterHost != Unset ]]; then
msg "Checking status of $component on $componentMasterHost"
vmsg "Executing: ssh -q -n -l $OSUSER $componentMasterHost \"$componentStatusCmd\""
ssh -q -n -l $OSUSER $componentMasterHost "$componentStatusCmd" > $brokerStatusFile 2>&1
[[ $VERBOSITY -gt 3 ]] && cat $brokerStatusFile
fgrep "is running as" $brokerStatusFile > /dev/null 2>&1
if [[ $? -eq 0 ]]; then
componentStatusCode=0
msg "Verified: $component is OK."
else
fgrep "is NOT running" $brokerStatusFile > /dev/null 2>&1
if [[ $? -eq 0 ]]; then
componentStatusCode=2
msg "Verified: $component is offline."
else
componentStatusCode=1
errmsg "Component $component status unknown."
fi
fi
rm -f $brokerStatusFile
else
errmsg "No master host configured for component $component."
componentStatusCode=-3
fi
;;
(p4p|p4dtg|p4web|p4gf)
warnmsg "Sorry, can't status components of type $componentType just yet."
componentStatusCode=-1
[[ $optimistic -eq 1 ]] && componentStatusCode=0
;;
(swarm)
warnmsg "Sorry, can't status components of type swarm just yet."
msg "Check the Swarm worker queue with wget using the configured URL ($componentURL)."
componentStatusCode=-1
[[ $optimistic -eq 1 ]] && componentStatusCode=0
;;
(*)
warnmsg "Unknown component type ($componentType) configured."
componentStatusCode=-1
;;
(Unset)
errmsg "ComponentType not defined for component $component."
componentStatusCode=-2
;;
esac
else
warnmsg "Component $component is not managed by HMS. Assuming it is OK."
componentStatusCode=0
fi
case "$componentStatusCode" in
(-3) componentStatusMsg="Component host not configured.";;
(-2) componentStatusMsg="Unknown component type.";;
(-1) componentStatusMsg="Status not yet implemented for this component type.";;
(0) componentStatusMsg=OK;;
(1) componentStatusMsg=FAILED;;
(2) componentStatusMsg=Offline;;
(*) componentStatusMsg="Unknown Status Code [$componentStatusCode]";;
esac
ComponentStatusCode[$component]=$componentStatusCode
ComponentStatusMsg[$component]=$componentStatusMsg
if [[ "$componentType" == p4broker ]]; then
msg "Component $component v$componentVersion ($tag config) status is $componentStatusMsg (code $componentStatusCode)."
else
msg "Component $component v$componentVersion status is $componentStatusMsg (code $componentStatusCode)."
fi
return $componentStatusCode
}
#------------------------------------------------------------------------------
# Function: get_component_version ($component)
#
# Set values in ComponentMajorVersion, ComponentMinorVersion, and
# ComponentVersion associative arrays, indexed by the fully qualified
# component name (i.e. <instance>:<compoment_name>).
#
# Output: This get_component_version() is a quiet function. It does its work
# silently. In event of problems, it just sets the version values to UNKNOWN.
# It doesn't complain. This is called by get_component_status, which takes
# care of notifying the user of problems.
#------------------------------------------------------------------------------
function get_component_version () {
vvmsg "CALL: get_component_version ($*)"
declare component=${1:-Unset}
declare componentMasterHost=
declare componentType=
declare componentExe=
declare componentMajorVersion=
declare componentMinorVersion=
declare componentVersionFile=$P4U_TMPDIR/component_version.${component/:/_}.out
declare componentVersionCmd=
instance=${component%%:*}
componentType=${ComponentType[$component]:-Unset}
componentManaged=${ComponentManaged[$component]:-Unset}
componentMasterHost=${ComponentMasterHost[$component]:-Unset}
case "$componentType" in
(p4d-*|p4broker|p4p)
componentP4PORT="${ComponentMasterHost[$component]:-Unset}:$componentURL"
componentExe="/p4/$instance/bin/${componentType%-*}_${instance}"
ssh -q -l $OSUSER $componentMasterHost "$componentExe -V" > $componentVersionFile 2>&1
componentMajorVersion=$(fgrep "Rev. " $componentVersionFile 2>/dev/null)
if [[ -n "$componentMajorVersion" ]]; then
componentMinorVersion=$(echo $componentMajorVersion|cut -d '/' -f 4)
componentMinorVersion=${componentMinorVersion%% *}
componentMajorVersion=$(echo $componentMajorVersion|cut -d '/' -f 3)
else
componentMajorVersion="UNKNOWN"
componentMinorVersion="UNKNOWN"
fi
;;
(p4dtg|p4web|p4gf)
warnmsg "Sorry, can't get version for component of type $componentType just yet."
componentMajorVersion="UNKNOWN"
componentMinorVersion="UNKNOWN"
;;
(swarm)
ssh -q -l $OSUSER $componentMasterHost "cat /p4/$instance/swarm/Version" > $componentVersionFile 2>&1
# A Swarm version file has 3 lines and looks like this:
# RELEASE = 2016 1 ;
# PATCHLEVEL = 1400259 ;
# SUPPDATE = 2016 06 13 ;
# Extract the RELEASE and PATCHLEVEL and normalized to our standard format.
componentMajorVersion=$(fgrep RELEASE $componentVersionFile 2>/dev/null)
if [[ -n "$componentMajorVersion" ]]; then
componentMajorVersion=${componentMajorVersion##* = }
componentMajorVersion=${componentMajorVersion% ;}
componentMajorVersion=${componentMajorVersion/ /.}
else
componentMajorVersion="UNKNOWN"
fi
componentMinorVersion=$(fgrep PATCHLEVEL $componentVersionFile 2>/dev/null)
if [[ -n "$componentMinorVersion" ]]; then
componentMinorVersion=${componentMinorVersion##* = }
componentMinorVersion=${componentMinorVersion% ;}
else
componentMinorVersion="UNKNOWN"
fi
rm -f $componentVersionFile
;;
esac
ComponentMajorVersion[$component]=$componentMajorVersion
ComponentMinorVersion[$component]=$componentMinorVersion
if [[ $componentMajorVersion != UNKNOWN ]]; then
ComponentVersion[$component]="$componentMajorVersion.$componentMinorVersion"
else
ComponentVersion[$component]=UNKNOWN
fi
}
| # | Change | User | Description | Committed | |
|---|---|---|---|---|---|
| #10 | 25550 | C. Thomas Tyler |
Split HMS from SDP, such that HMS will live on as a separate product, layered on the SDP. See: https://swarm.workshop.perforce.com/jobs/SDP-356 Many of the files deleted here have already been copied to HMS. See these HMS changes: https://swarm.workshop.perforce.com/changes/25531 https://swarm.workshop.perforce.com/changes/25533 And this branch spec: SDP_Split_2019.2_HMS In mkrep.sh, HMS-awareness is removed from mkrep.sh, a core SDP script, and the '-f' (Full Setup) flag has been temporarily removed. This useful functionality will be restored in an HMS script. This is a big change, so shellcheck v0.6.0 was implemented to support it. |
||
| #9 | 24224 | C. Thomas Tyler |
Enhanced HMS failover to support failover of edge server. Bypassing pre-commit review as this has been tested in the Battle School alb and contains a needed fix. #review-24225 |
||
| #8 | 23747 | C. Thomas Tyler |
Fixed hms status issues. Fixed issue getting status of SSL-enabled servers requiring SDP environment (including P4TRUST) to be set, incorporating new irun utility. Fixed issue with illegal negative exit codes in get_component_status(). Added in-code docs for component status values. Fixed get_component_list() to remove call-stack info in high-verbosity mode, due to text output being interpreted as data. |
||
| #7 | 23454 | cgeen |
Update to hms script to do two new functions: pull and df. Pull issues a pull -lj on all the edge/replica servers to get the status df issues a diskspace on all the servers. The reason for this is with a hardened edge environment the P4USER does not have permissions to run these commands on the edge servers. Therefore we need to run them centrally as a super. This replaces the replica_status commands on the edge. The updates also includes an update to the p4_vars to change the P4USER on an edge server. The idea is that P4USER only has super privs on the master on the replica edge servers the default user can only have admin privs. This is so the box adminstrator in restricted regions can't change the protection table. Hence the need for pull df centrally as these are the only commands that can't be run on the replicas/edges from the maintance scripts. It also goes without saying that ssh should only go out from the commit and never back. |
||
| #6 | 21720 | C. Thomas Tyler |
Fixed bug where a sophsticated topology with mulitple failover targets defined (e.g. 'ha' and 'dr' options) could failover to the wrong host, using the component backup host rather than the one associated with the specified failover target. Bypassing pre-commit review as this has been tested in the Battle School Lab, and I need to push this fix out. #review-21721 |
||
| #5 | 21410 | C. Thomas Tyler | Tweaked to support SSL usage. | ||
| #4 | 21033 | C. Thomas Tyler |
Fixed hms hang issue during local failover by replacing raw ssh call with a call to the robust runRemoteCmd() function. Also enhanced to detect ServerID based on configured server spec name rather hard-coded value of 'master' used during development. |
||
| #3 | 20853 | C. Thomas Tyler | Fixed hms bug discovered in failback testing; master host was wrong. | ||
| #2 | 20804 | C. Thomas Tyler | Fixed ssh hang issues. | ||
| #1 | 20745 | C. Thomas Tyler |
Approving as is since it isn't changing core SDP functionality, and reviewing it all line by line will take some time. We can do that as we move forward with it. First addition of HMS v1.0 files. This change is a soft launch HMS for initial deployment and testing. Updates to HMS-related files are expected and will bypass pre-commit code review until stabilized. |