#!/bin/ksh93
# ALTRAN_PROLOG_BEGIN_TAG
# This is an automatically generated prolog.
#
# Copyright (C) Altran ACT S.A.S. 2017,2018,2019,2020,2021. All rights reserved.
#
# ALTRAN_PROLOG_END_TAG
#
# @(#) 7d4c34b 43haes/lib/ksh93/hacmp/KLIB_HACMP_view_report.sh, 726, 2147A_aha726, Feb 05 2021 09:50 PM
#==============================================================================
#
# Name: KLIB_HACMP_view_report
#
# Description: This is the main, FPATH function that is invoked by clmgr
# to generate reports.
#
# Inputs: report Required. The type of report to create.
# file Optional. A file to store the report in. If this
# is not specified, the report is written to STDOUT.
# type Optional. Indicates if a textual report is desired
# ("text"), or a browser-enabled report ("html").
#
# >>> For the application availability report only. <<<
# begin Optional. A timestamp to use for indicating the
# earliest time a reports source data is to begin.
# end Optional. A timestamp to use for indicating the
# latest time reports data may end.
# targets Optional. One or more applications to include in
# the report.
#
# >>> For the HTML cluster report only. <<<
# company_name The name of the company to include in the report
# header. If a logo is specified, and can be loaded
# by the browser, it will be displayed instead.
# company_logo The graphical logo of the company, to include in
# the report header. If the logo cannot be found by
# browser, the company name will be displayed.
#
# Outputs: The report is written to the specified file, if possible.
# Otherwise it is written to STDOUT.
#
# Returns: Zero if no errors are detected. Otherwise, an appropriate
# non-zero value is returned. Refer to the "RETURN" section
# of the "devDoc()" function, above, for the standard return
# code values/meanings for clmgr.
#
#==============================================================================
function KLIB_HACMP_view_report {
trap 'on_exit_view_report' EXIT
. $HALIBROOT/log_entry "$0()" "$CL"
: version="@(#) 7d4c34b 43haes/lib/ksh93/hacmp/KLIB_HACMP_view_report.sh, 726, 2147A_aha726, Feb 05 2021 09:50 PM"
: INPUTS: $*
typeset -l report=${1//\"/}
shift
typeset file=${1//\"/}
typeset -l type=${2//\"/}
typeset begin=${3//\"/}
typeset end=${4//\"/}
typeset targets=${5//\"/}
targets=${targets//,/ }
typeset company_name=${6//\"/}
typeset company_logo=${7//\"/}
typeset snapshot=${8//\"/}
[[ $CLMGR_LOGGING == 'med' ]] && set +x # Only trace param values
#===================================
: Declare and initialize variables
#===================================
typeset -i stdout=1
rc=$RC_UNKNOWN # Declare globally, so it is visible in the exit function
typeset -i i=0
typeset output= target=
tmpfile=$TMPDIR/clmgr.KHvr.$$ # Declare globally, so it is visible in the exit function
#
: Default to 300 seconds. In a typical cluster, that is FAR more than
: enough time, but it also accommodates HUGE clusters, with maximum
: resources configured. However, if it should prove to not be enough
: for some reason, the time limit can be increased at the command line
: like this: CLMGR_TIMEOUT=### clmgr view report ...
: The timeout cannot be reduced below 60 seconds, though.
#
[[ $CLMGR_TIMEOUT != +([[:digit:]]) ]] && CLMGR_TIMEOUT=300
(( $CLMGR_TIMEOUT < 60 )) && CLMGR_TIMEOUT=60
KHVR_TIMEOUT=$CLMGR_TIMEOUT # Reassign to a new variable to ensure that a later call to
# KLIB_HACMP_get_cluster_attributes does not change the value
#
: Some reports are really big, for those customers who configure
: the maximum number of resources. In that case, we can get an
: "Out of memory" error. To avoid that, we attempt to increase
: the amount of memory allowed for this process.
#
print "$0()[$LINENO]($SECONDS): ulimit -d" >>$CLMGR_TMPLOG
integer DSEG=$(ulimit -d)
print "$0()[$LINENO]($SECONDS): Allocated data segment memory is $DSEG." >>$CLMGR_TMPLOG
if [[ $DSEG == +([0-9]) ]] && (( DSEG < 262144 ))
then
print "$0()[$LINENO]($SECONDS): Attempting to increase the data segment memory: ulimit -d 262144" >>$CLMGR_TMPLOG 2>&1
ulimit -d 262144 >>$CLMGR_TMPLOG 2>&1
print "$0()[$LINENO]($SECONDS): New allocated data segment memory is $(ulimit -d)." >>$CLMGR_TMPLOG
fi
#
: Set an alarm to prevent a hang by the "wait" command, below
#
typeset MAIN_PROC="$$"
(
sleep $KHVR_TIMEOUT &
alarmPID=$!
print -n $alarmPID >$TMPDIR/clmgr.KHvr.alarm.pid.$$
wait $alarmPID
cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 187 'Warning: the current operation has exceeded its allotted execution time (%1$s seconds).\n' "$KHVR_TIMEOUT" 1>&2
[[ -n $CLMGR_COMMAND ]] && print -u2 "\n\t${CLMGR_COMMAND/ -T $CLMGR_TRANSACTION_ID}\n"
if [[ -s $TMPDIR/clmgr.KHvr.procs.$$ ]]
then
CHCR_CHILDREN=$(cat $TMPDIR/clmgr.KHvr.procs.$$)
rm -f $TMPDIR/clmgr.KHvr.procs.$$
fi
if [[ -n $CHCR_CHILDREN ]]
then
cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 470 "Attempting to terminate any remaining, active processes...\n\n" "$KHVR_TIMEOUT" 1>&2
for pid in $CHCR_CHILDREN
do
: Try a "friendly" kill first
if ps -ef | grep -qw $pid
then
print "$0()[$LINENO]($SECONDS): kill \$pid ==> kill $pid" >>$CLMGR_TMPLOG
kill $pid >/dev/null 1>&2
fi
done
sleep 0.25
for pid in $CHCR_CHILDREN
do
: If necessary, try a forceful kill
if ps -ef | grep -qw $pid
then
print "$0()[$LINENO]($SECONDS): kill -9 \$pid ==> kill -9 $pid" >>$CLMGR_TMPLOG
kill -9 $pid >/dev/null 1>&2
fi
done
fi
[[ -n $MAIN_PROC ]] && kill -9 $MAIN_PROC 2>/dev/null
)&
export reaperPID=$!
#=====================
: Validate the input
#=====================
if [[ -z $report ]]; then
dspmsg -s $CLMGR_SET $CLMGR_MSGS 100 "\nERROR: a name/label must be provided.\n\n" 1>&2
typeset SET="
applications
availability
basic
cluster
dependencies
events
fsinfo
lvinfo
networks
nodeinfo
repositories
rginfo
software
status
topology
vginfo
roha"
dspmsg -s $CLMGR_SET $CLMGR_MSGS 3 "Valid values: %1\$s\n\n" "$SET" 1>&2
rc=$RC_MISSING_INPUT
else
report=$(CL=$LINENO KLIB_HACMP_is_known_report "$report" 2>/dev/null)
if (( $? != RC_SUCCESS )); then
/usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 135 "\nERROR: the specified report, \"%1\$s\", is not a known IBM PowerHA SystemMirror report.\n\n" "$report" 1>&2
/usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 155 "Available Reports:\n\n" 1>&2
print -u2 "\
\tapplications
\tavailability
\tbasic
\tcluster
\tdependencies
\tevents
\tfsinfo
\tlvinfo
\tnetworks
\tnodeinfo
\trepositories
\trginfo
\tsoftware
\tsnapshot
\tstatus
\ttopology
\tvginfo
\troha
"
rc=$RC_NOT_FOUND
fi
fi
if (( $rc == $RC_UNKNOWN )); then
if [[ -n $file ]]; then
if [[ $file != *([[:space:]])/* ]]; then
/usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 106 "\nERROR: the specified path/file does not appear to be in absolute format:\n %1\$s\n\n" "$file" 1>&2
rc=$RC_NOT_FOUND
else
typeset directory=$(/usr/bin/dirname "$file")
if [[ ! -d $directory ]]; then
/usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 136 "\nWarning: the directory in \"%1\$s\" does not yet exist.\n An attempt will be made to create that directory.\n\n" "$file"
/usr/bin/mkdir -p "$directory"
if [[ ! -d $directory ]]; then
/usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 201 "ERROR: failed to create \"%1\$s\".\n\n" "$directory" 1>&2
rc=$RC_NOT_FOUND
fi
fi
fi
fi
fi
if (( $rc == $RC_UNKNOWN )); then
if [[ -n $type && $type != @(t|h)* ]]; then
/usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 110 "\nERROR: invalid value specified for \"%1\$s\": \"%2\$s\".\n" TYPE "$type" 1>&2
/usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 3 "Valid values: %1\$s\n\n" \
"text, html" 1>&2
rc=$RC_INCORRECT_INPUT
elif [[ $type == t* ]]; then
type=text
elif [[ $type == h* ]]; then
type=html
else
type="text" # Set the default value
fi
fi
#======================
: Generate the report
#======================
if (( $rc == RC_UNKNOWN )); then
[[ -z $file ]] && file=$tmpfile
case "$report" in
ap*)
rc=$RC_SUCCESS
print -n >$file
[[ $type == html ]] && print_html_header >>$file
typeset -i headers=0
print "$0()[$LINENO]($SECONDS): $HAUTILS/cldisp" >>$CLMGR_TMPLOG
typeset OUTPUT=$($HAUTILS/cldisp)
cmd_rc=$?
print "$0()[$LINENO]($SECONDS): cldisp RC: $cmd_rc" >>$CLMGR_TMPLOG
(( rc |= $cmd_rc ))
print -- "$OUTPUT" |\
while IFS= read line; do
if [[ $line == '########'* ]]; then
(( headers++ ))
continue
fi
(( headers >= 3 )) && break
(( headers == 2 )) && print "$line" >>$file
done
[[ $type == html ]] && print_html_footer >>$file
;;
av*)
rc=$RC_SUCCESS
print -n >$file
[[ $type == html ]] && print_html_header >>$file
typeset apps=
if [[ $targets == *([[:space:]]) ]]; then
print "$0()[$LINENO]($SECONDS): $HAUTILS/cllsserv -c">>$CLMGR_TMPLOG
typeset OUTPUT=$($HAUTILS/cllsserv -c)
cmd_rc=$?
print "$0()[$LINENO]($SECONDS): cllsserv RC: $cmd_rc" >>$CLMGR_TMPLOG
(( rc |= $cmd_rc ))
print -- "$OUTPUT" |\
while read line; do
apps="$apps ${line%%:*}"
done
else
for target in ${targets//,/ }; do
CL=$LINENO KLIB_HACMP_is_known_appserver "$target" 2>>$CLMGR_TMPLOG
if (( $? == RC_SUCCESS )); then
apps="$apps $target"
else
CL=$LINENO KLIB_HACMP_is_known_rg "$target" 2>>$CLMGR_TMPLOG
if (( $? == RC_SUCCESS )); then
typeset -A rgprops
CL=$LINENO KLIB_HACMP_get_rg_attributes "$target" rgprops
apps="$apps ${rgprops[APPLICATIONS]}"
fi
fi
done
fi
: If no end time, default to current date
if [[ $end == *([[:space:]]) ]]; then
end=$(/usr/bin/date '+%Y:%m:%d'):23:59:59
fi
: If no begin time, default to 30 days prior to end time
if [[ $begin == *([[:space:]]) ]]; then
typeset parse_end=$end
typeset -i year=${parse_end%%:*}
parse_end=${parse_end#*:}
typeset -i month=${parse_end%%:*}
parse_end=${parse_end#*:}
typeset -i day=${parse_end%%:*}
if (( day-30 <= 0 )); then
(( month-- ))
if (( month <= 0 )); then
month=12
(( year-- ))
fi
if [[ $month == @(1|3|5|7|8|10|12) ]]; then
(( day = 31 - (30 - day) ))
elif [[ $month == 2 ]]; then
typeset leap=$(/usr/bin/expr $year % 4)
if (( leap == 0 )); then
(( day = 30 - (29 - day) ))
else
(( day = 30 - (28 - day) ))
fi
else
(( day = 30 - (30 - day) ))
fi
fi
begin="$year:$month:$day:00:00:00"
fi
typeset RPFILE=$TMPDIR/clmgr.KHvr.dirrpt.$$
for app in $apps; do
print "$0()[$LINENO]($SECONDS): $HAUTILS/clavan -a \"$app\" -b $begin -e $end" >>$CLMGR_TMPLOG
$HAUTILS/clavan -a "$app" -b $begin -e $end >>$RPFILE 2>&1
cmd_rc=$?
print "$0()[$LINENO]($SECONDS): clavan RC: $cmd_rc" >>$CLMGR_TMPLOG
(( rc |= $cmd_rc ))
done
typeset OUTPUT=$(/usr/bin/cat $RPFILE >>$file 2>>$CLMGR_TMPLOG)
/usr/bin/rm -f $RPFILE
if [[ -n $OUTPUT ]]; then
print -- "$OUTPUT" >$file
else
/usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 181 "No application data could be found for this report. This is often caused\nby a lack of, or problem with, application monitoring. Application monitors\nproduce the historical data needed for this report.\n"
fi
[[ $type == html ]] && print_html_footer >>$file
;;
ba*)
rc=$RC_SUCCESS
print -n >$file
[[ $type == html ]] && print_html_header >>$file
print "$0()[$LINENO]($SECONDS): $HAUTILS/cltopinfo" >>$CLMGR_TMPLOG
VERBOSE_LOGGING="" $HAUTILS/cltopinfo >>$file
cmd_rc=$?
print "$0()[$LINENO]($SECONDS): cltopinfo RC: $cmd_rc" >>$CLMGR_TMPLOG
(( rc |= $cmd_rc ))
[[ $type == html ]] && print_html_footer >>$file
;;
@(sn|cl)*)
rc=$RC_SUCCESS
if [[ $report == "snapshot" ]]
then
if [[ -z $snapshot ]]; then
dspmsg -s $CLMGR_SET $CLMGR_MSGS 100 "\nERROR: a name/label must be provided.\n\n" 1>&2
dspmsg -s $CLMGR_SET $CLMGR_MSGS 158 "Available Snapshots:\n\n" 1>&2
typeset available
CL=$LINENO KLIB_HACMP_list_snapshots available
for (( i=0; i<${#available[*]}; i++ )); do
if [[ ${available[$i]} != *([[:space:]]) ]]; then
print -u2 "\t${available[$i]}"
fi
done
print -u2 ""
log_return_msg "$RC_MISSING_INPUT" "$0()" "$LINENO"
return $?
else
CL=$LINENO KLIB_HACMP_is_known_snapshot "$snapshot" 2>/dev/null
if (( $? != RC_SUCCESS )); then
dspmsg -s $CLMGR_SET $CLMGR_MSGS 102 '\nERROR: "%1$s" does not appear to exist!\n\n' "$snapshot" 1>&2
dspmsg -s $CLMGR_SET $CLMGR_MSGS 158 "Available Snapshots:\n\n" 1>&2
typeset available
CL=$LINENO KLIB_HACMP_list_snapshots available
for (( i=0; i<${#available[*]}; i++ )); do
if [[ ${available[$i]} != *([[:space:]]) ]]; then
print -u2 "\t${available[$i]}"
fi
done
print -u2 ""
log_return_msg "$RC_NOT_FOUND" "$0()" "$LINENO"
return $?
fi
fi
CL=$LINENO create_html_report "$file" "" "" "$snapshot"
elif [[ $type == html ]]; then
CL=$LINENO create_html_report "$file" "$company_name" "$company_logo" ""
rc=$?
else
print -n >$file
print "$0()[$LINENO]($SECONDS): $HAUTILS/cldisp" >>$CLMGR_TMPLOG
$HAUTILS/cldisp >>$file
cmd_rc=$?
print "$0()[$LINENO]($SECONDS): cldisp RC: $cmd_rc" >>$CLMGR_TMPLOG
(( rc |= $cmd_rc ))
if [[ -n $(odmget HACMPsite) ]]; then
print >>$file
print "$0()[$LINENO]($SECONDS): $HAUTILS/cllssite" >>$CLMGR_TMPLOG
$HAUTILS/cllssite >>$file 2>>$CLMGR_TMPLOG
cmd_rc=$?
print "$0()[$LINENO]($SECONDS): cllssite RC: $cmd_rc" >>$CLMGR_TMPLOG
(( rc |= $cmd_rc ))
fi
fi
;;
de*)
rc=$RC_SUCCESS
print -n >$file
[[ $type == html ]] && print_html_header >>$file
typeset BANNER= OUTPUT=
BANNER=$(/usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 450 "PARENT_CHILD Dependencies, by Parent")
for (( i=0; i<${#BANNER}+6; i++ )); do print -n \# >>$file; done
print "\n $BANNER" >>$file
for (( i=0; i<${#BANNER}+6; i++ )); do print -n \# >>$file; done
print >>$file
print "$0()[$LINENO]($SECONDS): $HAUTILS/clrgdependency -t PARENT_CHILD -sp" >>$CLMGR_TMPLOG
process_temporal_data "$($HAUTILS/clrgdependency -t PARENT_CHILD -sp)" "$targets" >>$file
cmd_rc=$?
print "$0()[$LINENO]($SECONDS): clrgdependency RC: $cmd_rc" >>$CLMGR_TMPLOG
(( rc |= $cmd_rc ))
print >>$file
BANNER=$(/usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 451 "PARENT_CHILD Dependencies, by Child")
for (( i=0; i<${#BANNER}+6; i++ )); do print -n \# >>$file; done
print "\n $BANNER" >>$file
for (( i=0; i<${#BANNER}+6; i++ )); do print -n \# >>$file; done
print >>$file
print "$0()[$LINENO]($SECONDS): $HAUTILS/clrgdependency -t PARENT_CHILD -sc" >>$CLMGR_TMPLOG
process_temporal_data "$($HAUTILS/clrgdependency -t PARENT_CHILD -sc)" "$targets" >>$file
cmd_rc=$?
print "$0()[$LINENO]($SECONDS): clrgdependency RC: $cmd_rc" >>$CLMGR_TMPLOG
(( rc |= $cmd_rc ))
print >>$file
BANNER=$(/usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 452 "STOP_AFTER Dependencies, by Source")
for (( i=0; i<${#BANNER}+6; i++ )); do print -n \# >>$file; done
print "\n $BANNER" >>$file
for (( i=0; i<${#BANNER}+6; i++ )); do print -n \# >>$file; done
print >>$file
print "$0()[$LINENO]($SECONDS): $HAUTILS/clrgdependency -t STOP_AFTER -sp" >>$CLMGR_TMPLOG
process_temporal_data "$($HAUTILS/clrgdependency -t STOP_AFTER -sp 2>>$CLMGR_TMPLOG)" "$targets" >>$file
cmd_rc=$?
print "$0()[$LINENO]($SECONDS): clrgdependency RC: $cmd_rc" >>$CLMGR_TMPLOG
(( rc |= $cmd_rc ))
print >>$file
BANNER=$(/usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 453 "STOP_AFTER Dependencies, by Target")
for (( i=0; i<${#BANNER}+6; i++ )); do print -n \# >>$file; done
print "\n $BANNER" >>$file
for (( i=0; i<${#BANNER}+6; i++ )); do print -n \# >>$file; done
print >>$file
print "$0()[$LINENO]($SECONDS): $HAUTILS/clrgdependency -t STOP_AFTER -sc" >>$CLMGR_TMPLOG
process_temporal_data "$($HAUTILS/clrgdependency -t STOP_AFTER -sc 2>>$CLMGR_TMPLOG)" "$targets" >>$file
cmd_rc=$?
print "$0()[$LINENO]($SECONDS): clrgdependency RC: $cmd_rc" >>$CLMGR_TMPLOG
(( rc |= $cmd_rc ))
print >>$file
BANNER=$(/usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 454 "START_AFTER Dependencies, by Source")
for (( i=0; i<${#BANNER}+6; i++ )); do print -n \# >>$file; done
print "\n $BANNER" >>$file
for (( i=0; i<${#BANNER}+6; i++ )); do print -n \# >>$file; done
print >>$file
print "$0()[$LINENO]($SECONDS): $HAUTILS/clrgdependency -t START_AFTER -sc" >>$CLMGR_TMPLOG
process_temporal_data "$($HAUTILS/clrgdependency -t START_AFTER -sc 2>>$CLMGR_TMPLOG)" "$targets" >>$file
cmd_rc=$?
print "$0()[$LINENO]($SECONDS): clrgdependency RC: $cmd_rc" >>$CLMGR_TMPLOG
(( rc |= $cmd_rc ))
print >>$file
BANNER=$(/usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 455 "START_AFTER Dependencies, by Target")
for (( i=0; i<${#BANNER}+6; i++ )); do print -n \# >>$file; done
print "\n $BANNER" >>$file
for (( i=0; i<${#BANNER}+6; i++ )); do print -n \# >>$file; done
print >>$file
print "$0()[$LINENO]($SECONDS): $HAUTILS/clrgdependency -t START_AFTER -sp" >>$CLMGR_TMPLOG
process_temporal_data "$($HAUTILS/clrgdependency -t START_AFTER -sp 2>>$CLMGR_TMPLOG)" "$targets" >>$file
cmd_rc=$?
print "$0()[$LINENO]($SECONDS): clrgdependency RC: $cmd_rc" >>$CLMGR_TMPLOG
(( rc |= $cmd_rc ))
print >>$file
BANNER=$(/usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 456 "NODECOLLOCATION Dependencies")
for (( i=0; i<${#BANNER}+6; i++ )); do print -n \# >>$file; done
print "\n $BANNER" >>$file
for (( i=0; i<${#BANNER}+6; i++ )); do print -n \# >>$file; done
print >>$file
OUTPUT=$($HAUTILS/clrgdependency -t NODECOLLOCATION -sl)
cmd_rc=$?
print "$0()[$LINENO]($SECONDS): clrgdependency RC: $cmd_rc" >>$CLMGR_TMPLOG
(( rc |= $cmd_rc ))
process_location_data "$OUTPUT" "$targets" "NODECOLLOCATION" >>$file
[[ OUTPUT != *[[:space:]] ]] && print >>$file
if [[ -n $(odmget HACMPsite) ]]; then
BANNER=$(/usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 457 "SITECOLLOCATION Dependencies")
for (( i=0; i<${#BANNER}+6; i++ )); do print -n \# >>$file; done
print "\n $BANNER" >>$file
for (( i=0; i<${#BANNER}+6; i++ )); do print -n \# >>$file; done
print >>$file
print "$0()[$LINENO]($SECONDS): $HAUTILS/clrgdependency -t SITECOLLOCATION -sl" >>$CLMGR_TMPLOG
OUTPUT=$($HAUTILS/clrgdependency -t SITECOLLOCATION -sl)
cmd_rc=$?
print "$0()[$LINENO]($SECONDS): clrgdependency RC: $cmd_rc" >>$CLMGR_TMPLOG
(( rc |= $cmd_rc ))
process_location_data "$OUTPUT" "$targets" "SITECOLLOCATION" >>$file
[[ OUTPUT != *[[:space:]] ]] && print >>$file
fi
BANNER=$(/usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 458 "ANTICOLLOCATION Dependency")
for (( i=0; i<${#BANNER}+6; i++ )); do print -n \# >>$file; done
print "\n $BANNER" >>$file
for (( i=0; i<${#BANNER}+6; i++ )); do print -n \# >>$file; done
print >>$file
print "$0()[$LINENO]($SECONDS): $HAUTILS/clrgdependency -t ANTICOLLOCATION -sl" >>$CLMGR_TMPLOG
OUTPUT=$($HAUTILS/clrgdependency -t ANTICOLLOCATION -sl)
cmd_rc=$?
print "$0()[$LINENO]($SECONDS): clrgdependency RC: $cmd_rc" >>$CLMGR_TMPLOG
(( rc |= $cmd_rc ))
process_location_data "$OUTPUT" "$targets" "ANTICOLLOCATION" >>$file
[[ OUTPUT != *[[:space:]] ]] && print >>$file
[[ $type == html ]] && print_html_footer >>$file
;;
ev*)
rc=$RC_SUCCESS
print -n >$file
[[ $type == html ]] && print_html_header >>$file
print "$0()[$LINENO]($SECONDS): $HAUTILS/clevsummary" >>$CLMGR_TMPLOG
$HAUTILS/clevsummary >>$file
cmd_rc=$?
print "$0()[$LINENO]($SECONDS): clevsummary RC: $cmd_rc" >>$CLMGR_TMPLOG
(( rc |= $cmd_rc ))
[[ $type == html ]] && print_html_footer >>$file
;;
fs*)
rc=$RC_SUCCESS
print -n >$file
[[ $type == html ]] && print_html_header >>$file
print "$0()[$LINENO]($SECONDS): $HASBIN/cl_showfs2" >>$CLMGR_TMPLOG
if [[ $targets != *([[:space:]]) ]]; then
$HASBIN/cl_showfs2 | /usr/bin/grep -E "^#|${targets//+([[:space:]])/\|}" >>$file
else
$HASBIN/cl_showfs2 >>$file
fi
cmd_rc=$?
print "$0()[$LINENO]($SECONDS): cl_showfs2 RC: $cmd_rc" >>$CLMGR_TMPLOG
(( rc |= $cmd_rc ))
print >>$file
print "$0()[$LINENO]($SECONDS): $HASBIN/cl_lsfs" >>$CLMGR_TMPLOG
if [[ $targets != *([[:space:]]) ]]; then
$HASBIN/cl_lsfs | /usr/bin/grep -E "^Node:|${targets//+([[:space:]])/\|}" >>$file
else
$HASBIN/cl_lsfs >>$file
fi
cmd_rc=$?
print "$0()[$LINENO]($SECONDS): cl_lsfs RC: $cmd_rc" >>$CLMGR_TMPLOG
(( rc |= $cmd_rc ))
[[ $type == html ]] && print_html_footer >>$file
;;
lv*)
rc=$RC_SUCCESS
print -n >$file
[[ $type == html ]] && print_html_header >>$file
typeset -A LVS
typeset rg= lv=
print "$0()[$LINENO]($SECONDS): $HAUTILS/cllslv" >>$CLMGR_TMPLOG
$HAUTILS/cllslv 2>>$CLMGR_TMPLOG |\
while read rg lv; do
if [[ -z $targets || " $targets " == *\ $lv\ * ]]; then
LVS[$lv]=1
fi
done
cmd_rc=$?
print "$0()[$LINENO]($SECONDS): cllslv RC: $cmd_rc" >>$CLMGR_TMPLOG
(( rc |= $cmd_rc ))
if (( ${#LVS[*]} > 0 )); then
for name in ${!LVS[*]}; do
print >>$file
for (( i=0; i<${#name}+6; i++ )); do print -n \# >>$file; done
print -- "\n $name" >>$file
for (( i=0; i<${#name}+6; i++ )); do print -n \# >>$file; done
print >>$file
print "$0()[$LINENO]($SECONDS): $HASBIN/cl_lslv $name" >>$CLMGR_TMPLOG
$HASBIN/cl_lslv $name >>$file 2>>$CLMGR_TMPLOG
cmd_rc=$?
print "$0()[$LINENO]($SECONDS): cl_lslv RC: $cmd_rc" >>$CLMGR_TMPLOG
(( rc |= $cmd_rc ))
done
elif [[ -n $targets ]]; then
/usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 459 "No logical volumes were found in the cluster matching \"%1\$s\".\n" "$targets"
else
/usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 460 "No logical volumes were found in the cluster.\n"
fi
[[ $type == html ]] && print_html_footer >>$file
;;
ne*|nw)
rc=$RC_SUCCESS
print -n >$file
[[ $type == html ]] && print_html_header >>$file
print "$0()[$LINENO]($SECONDS): $HASBIN/cltopinfo -n" >>$CLMGR_TMPLOG
VERBOSE_LOGGING="" $HAUTILS/cltopinfo -n >>$file 2>>$CLMGR_TMPLOG
cmd_rc=$?
print "$0()[$LINENO]($SECONDS): cltopinfo RC: $cmd_rc" >>$CLMGR_TMPLOG
(( rc |= $cmd_rc ))
print >>$file
print "$0()[$LINENO]($SECONDS): $HASBIN/cllsnw" >>$CLMGR_TMPLOG
$HAUTILS/cllsnw >>$file
cmd_rc=$?
print "$0()[$LINENO]($SECONDS): cllsnw RC: $cmd_rc" >>$CLMGR_TMPLOG
(( rc |= $cmd_rc ))
print >>$file
print "$0()[$LINENO]($SECONDS): $HASBIN/cllsif" >>$CLMGR_TMPLOG
$HAUTILS/cllsif >>$file
cmd_rc=$?
print "$0()[$LINENO]($SECONDS): cllsif RC: $cmd_rc" >>$CLMGR_TMPLOG
(( rc |= $cmd_rc ))
[[ $type == html ]] && print_html_footer >>$file
;;
no*)
rc=$RC_SUCCESS
print -n >$file
[[ $type == html ]] && print_html_header >>$file
if [[ $targets == *([[:space:]]) ]]; then
print "$0()[$LINENO]($SECONDS): $HAUTILS/cllsnode" >>$CLMGR_TMPLOG
$HAUTILS/cllsnode >>$file
cmd_rc=$?
print "$0()[$LINENO]($SECONDS): cllsnode RC: $cmd_rc" >>$CLMGR_TMPLOG
(( rc |= $cmd_rc ))
else
for target in ${targets//,/ }; do
print "$0()[$LINENO]($SECONDS): $HAUTILS/cllsnode -i \"$target\"" >>$CLMGR_TMPLOG
cllsnode -i "$target" >>$file
cmd_rc=$?
print "$0()[$LINENO]($SECONDS): cllsnode RC: $cmd_rc" >>$CLMGR_TMPLOG
(( rc |= $cmd_rc ))
print "$0()[$LINENO]($SECONDS): $HAUTILS/clshowres -n \"$target\"" >>$CLMGR_TMPLOG
$HAUTILS/clshowres -n "$target" >>$file
cmd_rc=$?
print "$0()[$LINENO]($SECONDS): clshowres RC: $cmd_rc" >>$CLMGR_TMPLOG
(( rc |= $cmd_rc ))
done
fi
[[ $type == html ]] && print_html_footer >>$file
;;
rg*)
rc=$RC_SUCCESS
print -n >$file
[[ $type == html ]] && print_html_header >>$file
if [[ $targets == *([[:space:]]) ]]; then
print "$0()[$LINENO]($SECONDS): $HAUTILS/clshowres" >>$CLMGR_TMPLOG
$HAUTILS/clshowres >>$file
cmd_rc=$?
print "$0()[$LINENO]($SECONDS): clshowres RC: $cmd_rc" >>$CLMGR_TMPLOG
(( rc |= $cmd_rc ))
else
for target in ${targets//,/ }; do
print "$0()[$LINENO]($SECONDS): $HAUTILS/clshowres -g \"$target\"" >>$CLMGR_TMPLOG
$HAUTILS/clshowres -g "$target" >>$file
cmd_rc=$?
print "$0()[$LINENO]($SECONDS): clshowres RC: $cmd_rc" >>$CLMGR_TMPLOG
(( rc |= $cmd_rc ))
done
fi
[[ $type == html ]] && print_html_footer >>$file
;;
rp|rep*)
typeset -i lspv_rc=-1
rc=$RC_SUCCESS
[[ $type == html ]] && print_html_header >>$file
typeset SITE_SIRCOLS=""
print "$0()[$LINENO]($SECONDS): clodmget -n -f name HACMPsircol" >>$CLMGR_TMPLOG
SITE_SIRCOLS=$(clodmget -n -f name HACMPsircol)
cmd_rc=$?
print "$0()[$LINENO]($SECONDS): clodmget -n -f name HACMPsircol RC: $cmd_rc" >>$CLMGR_TMPLOG
for SITE_SIRCOL in ${SITE_SIRCOLS}; do
site=${SITE_SIRCOL/_sircol/}
print -- "$site :" >>$file
#
: Get the list of nodes to be considered for this sircol
#
typeset SITE_NODES=""
if [[ $CLUSTER_TYPE == @(NSC|SC) ]]
then
#
: One CAA cluster, so use all cluster nodes
#
SITE_NODES=$(clnodename)
SITE_NODES=${SITE_NODES//+([[:space:]])/ }
else
#
: Multiple CAA clusters, so use site-specific nodes
#
SITE_NODES=$(clodmget -n -f nodelist -q "name = ${SITE_SIRCOL%%_*}" HACMPsite)
SITE_NODES=${SITE_NODES//,/ }
fi
typeset SITE_NODE=${SITE_NODES%% *}
#
: Collect disk information from the appropriate node
#
typeset LSPV_OUT=""
if [[ " $SITE_NODE " == *\ $LOCAL_NODE\ * ]]
then
print "$0()[$LINENO]($SECONDS): /usr/sbin/lspv" >>$CLMGR_TMPLOG
LSPV_OUT=$(/usr/sbin/lspv)
else
print "$0()[$LINENO]($SECONDS): $CLRSH $SITE_NODE /usr/sbin/lspv" >>$CLMGR_TMPLOG
LSPV_OUT=$($CLRSH $SITE_NODE /usr/sbin/lspv)
fi
lspv_rc=$?
print "$0()[$LINENO]($SECONDS): lspv RC: $lspv_rc LSPV_OUT=$LSPV_OUT" >>$CLMGR_TMPLOG
(( rc |= $lspv_rc ))
#
: Collect and display the primary/active repository
#
typeset JUNK=""
typeset ACTIVE_REPOSITORY="" ACTIVE_REPOSITORY_NAME="" ACTIVE_REPOSITORY_PVID=""
print "$0()[$LINENO]($SECONDS): clodmget -n -f repository -q name=$SITE_SIRCOL HACMPsircol" >>$CLMGR_TMPLOG
ACTIVE_REPOSITORY=$(clodmget -n -f repository -q name=$SITE_SIRCOL HACMPsircol)
cmd_rc=$?
print "$0()[$LINENO]($SECONDS): clodmget -n -f repository -q name=$SITE_SIRCOL HACMPsircol RC: $cmd_rc" >>$CLMGR_TMPLOG
(( rc |= $cmd_rc ))
if [[ -n $ACTIVE_REPOSITORY ]]; then
if (( lspv_rc==0)); then
print -- "$LSPV_OUT" | grep -w "$ACTIVE_REPOSITORY" | read ACTIVE_REPOSITORY_NAME ACTIVE_REPOSITORY_PVID JUNK
else
ACTIVE_REPOSITORY_PVID=$ACTIVE_REPOSITORY
ACTIVE_REPOSITORY_NAME="-----"
fi
dspmsg -s $CLMGR_SET $CLMGR_MSGS 1100 "\t%1\$s %2\$s(%3\$s)\t active\n" "$ACTIVE_REPOSITORY_PVID" "$ACTIVE_REPOSITORY_NAME" "$SITE_NODE">>$file
#
: Collect and display the backup repositories, if any
#
typeset BACKUP_REPOSITORIES="" BACKUP_REPOSITORY_NAME="" BACKUP_REPOSITORY_PVID=""
print "$0()[$LINENO]($SECONDS): clodmget -n -f backup_repository -q name=$SITE_SIRCOL HACMPsircol" >>$CLMGR_TMPLOG
BACKUP_REPOSITORIES=$(clodmget -n -f backup_repository -q name=$SITE_SIRCOL HACMPsircol)
cmd_rc=$?
print "$0()[$LINENO]($SECONDS): clodmget -n -f backup_repository -q name=$SITE_SIRCOL HACMPsircol RC: $cmd_rc)" >>$CLMGR_TMPLOG
(( rc |= $cmd_rc ))
if [[ -n $BACKUP_REPOSITORIES ]]; then
for BACKUP_REPOSITORY in ${BACKUP_REPOSITORIES}; do
if (( lspv_rc==0)); then
print -- "$LSPV_OUT" | grep $BACKUP_REPOSITORY| read BACKUP_REPOSITORY_NAME BACKUP_REPOSITORY_PVID JUNK
else
BACKUP_REPOSITORY_PVID=$BACKUP_REPOSITORY
BACKUP_REPOSITORY_NAME="-----"
fi
dspmsg -s $CLMGR_SET $CLMGR_MSGS 1102 "\t%1\$s %2\$s(%3\$s)\t backup\n" "$BACKUP_REPOSITORY_PVID" "$BACKUP_REPOSITORY_NAME" "$SITE_NODE">>$file
done
else
dspmsg -s $CLMGR_SET $CLMGR_MSGS 1103 "\tNo backup repository\n">>$file
fi
else
dspmsg -s $CLMGR_SET $CLMGR_MSGS 1101 "\tNo active repository\n">>$file
fi
done
[[ $type == html ]] && print_html_header >>$file
;;
so*)
rc=$RC_SUCCESS
print -n >$file
[[ $type == html ]] && print_html_header >>$file
#
# clcmd is a cheap and easy way to collect from all nodes
# and prints its own header with the node name - if it
# works (i.e. a caa cluster exists) then use it, otherwise
# we just collect from the local node
#
typeset CLCMD="clcmd"
if ! clcmd /usr/bin/date >/dev/null 2>&1
then
CLCMD=""
fi
#
# Always report PowerHA, rsct and caa filesets.
# this is the only place we pay attention to the exit code
# from lslpp since these filesets must be installed.
#
echo "============================================" >> $file
echo "PowerHA, RSCT and CAA filesets">> $file
echo "============================================\n" >>$file
$CLCMD lslpp -h "cluster.*" "rsct.*" "bos.cluster*" >>$file 2>&1
(( rc |= $? ))
#
# Report glvm if installed, regardless of any rpv resources
#
if lslpp -l "glvm.rpv*" >/dev/null 2>&1; then
echo "\n\n============================================" >>$file
echo "GLVM filesets" >> $file
echo "============================================\n" >>$file
$CLCMD lslpp -h "glvm.rpv*" >>$file 2>&1
fi
#
# Ifixes are identified by the apar they are associated with
# so we have no way of knowing which ifixes are for what,
# so we grab everything - typically not many will exist
# anyway - and ignore the exit code since emgr returns 1 if
# no ifixes are installed.
#
echo "\n\n============================================" >> $file
echo "Emgr (ifix)">> $file
echo "============================================" >>$file
$CLCMD emgr -l >>$file 2>&1 # for verbose mode add -v3
#
# If the gui is installed, grab rpm info
#
if lslpp -l "cluster.es.smui.*" >/dev/null 2>&1; then
echo "\n\n============================================" >> $file
echo "Output from \"rpm -qa\"">> $file
echo "============================================" >>$file
$CLCMD rpm -qa >>$file 2>&1
fi
#
# If anything failed, record the problem
#
if (( $rc != 0 ))
then
dspmsg -s $CLMGR_SET $CLMGR_MSGS 1321 '\nERROR: A problem occurred trying to collect software information from\none or more nodes. This report may not be complete.\n' >>$file
rc=$RC_ERROR
fi
[[ $type == html ]] && print_html_footer >>$file
;;
st*)
rc=$RC_SUCCESS
print -n >$file
[[ $type == html ]] && print_html_header >>$file
print "$0()[$LINENO]($SECONDS): $HAUTILS/cldump" >>$CLMGR_TMPLOG
$HAUTILS/cldump >>$file
cmd_rc=$?
print "$0()[$LINENO]($SECONDS): cldump RC: $cmd_rc" >>$CLMGR_TMPLOG
(( rc |= $cmd_rc ))
print "\n" >>$file
print "$0()[$LINENO]($SECONDS): $HAUTILS/clshowsrv -v" >>$CLMGR_TMPLOG
$HAUTILS/clshowsrv -v >>$file
cmd_rc=$?
print "$0()[$LINENO]($SECONDS): clshowsrv RC: $cmd_rc" >>$CLMGR_TMPLOG
(( rc |= $cmd_rc ))
[[ $type == html ]] && print_html_footer >>$file
;;
to*)
rc=$RC_SUCCESS
print -n >$file
[[ $type == html ]] && print_html_header >>$file
print "$0()[$LINENO]($SECONDS): $HAUTILS/cltopinfo -c" >>$CLMGR_TMPLOG
VERBOSE_LOGGING="" $HAUTILS/cltopinfo -c >>$file 2>>$CLMGR_TMPLOG
cmd_rc=$?
print "$0()[$LINENO]($SECONDS): cltopinfo RC: $cmd_rc" >>$CLMGR_TMPLOG
(( rc |= $cmd_rc ))
if [[ -n $(odmget HACMPsite) ]]; then
print >>$file
print "$0()[$LINENO]($SECONDS): $HAUTILS/cllssite" >>$CLMGR_TMPLOG
$HAUTILS/cllssite >>$file 2>>$CLMGR_TMPLOG
cmd_rc=$?
print "$0()[$LINENO]($SECONDS): cllssite RC: $cmd_rc" >>$CLMGR_TMPLOG
(( rc |= $cmd_rc ))
fi
print >>$file
print "$0()[$LINENO]($SECONDS): $HAUTILS/cltopinfo -n" >>$CLMGR_TMPLOG
VERBOSE_LOGGING="" $HAUTILS/cltopinfo -n >>$file 2>>$CLMGR_TMPLOG
cmd_rc=$?
print "$0()[$LINENO]($SECONDS): cltopinfo RC: $cmd_rc" >>$CLMGR_TMPLOG
(( rc |= $cmd_rc ))
print >>$file
print "$0()[$LINENO]($SECONDS): $HAUTILS/cllsnw" >>$CLMGR_TMPLOG
$HAUTILS/cllsnw >>$file
cmd_rc=$?
print "$0()[$LINENO]($SECONDS): cllsnw RC: $cmd_rc" >>$CLMGR_TMPLOG
(( rc |= $cmd_rc ))
print >>$file
print "$0()[$LINENO]($SECONDS): $HAUTILS/cllsif" >>$CLMGR_TMPLOG
$HAUTILS/cllsif >>$file
cmd_rc=$?
print "$0()[$LINENO]($SECONDS): cllsif RC: $cmd_rc" >>$CLMGR_TMPLOG
(( rc |= $cmd_rc ))
[[ $type == html ]] && print_html_footer >>$file
;;
vg*)
rc=$RC_SUCCESS
print -n >$file
[[ $type == html ]] && print_html_header >>$file
print "$0()[$LINENO]($SECONDS): $HACSPOC/cl_ls_shared_vgs -c -C" >>$CLMGR_TMPLOG
typeset DATA=$($HACSPOC/cl_ls_shared_vgs -c -C 2>>$CLMGR_TMPLOG)
cmd_rc=$?
print "$0()[$LINENO]($SECONDS): cl_ls_shared_vgs RC: $cmd_rc" >>$CLMGR_TMPLOG
(( rc |= $cmd_rc ))
if [[ $targets != *([[:space:]]) ]]; then
print -- "$DATA" | /usr/bin/grep -E "^#|${targets//+([[:space:]])/\|}" >>$file
else
print -- "$DATA" >>$file
fi
typeset -A VGS
typeset name= nodelist=
print -- "$DATA" |\
while read LINE; do
[[ $LINE == \#* ]] && continue
name=${LINE##+([[:space:]])}
name=${name%%+([[:space:]])*}
nodelist=${LINE%%+([[:space:]])}
nodelist=${nodelist##*+([[:space:]])}
if [[ -z $targets || " $targets " == *\ $name\ * ]]; then
VGS[$name]=$nodelist
fi
done
if (( ${#VGS[*]} > 0 )); then
for name in ${!VGS[*]}; do
print >>$file
for (( i=0; i<${#name}+6; i++ )); do print -n \# >>$file; done
print -- "\n $name" >>$file
for (( i=0; i<${#name}+6; i++ )); do print -n \# >>$file; done
print >>$file
print "$0()[$LINENO]($SECONDS): $HASBIN/cl_ls_vgstatus -cspoc \"-n ${VGS[$name]}\" $name" >>$CLMGR_TMPLOG
$HASBIN/cl_ls_vgstatus -cspoc "-n ${VGS[$name]}" $name >>$file
cmd_rc=$?
print "$0()[$LINENO]($SECONDS): cl_ls_vgstatus RC: $cmd_rc" >>$CLMGR_TMPLOG
(( rc |= $cmd_rc ))
print >>$file
print "$0()[$LINENO]($SECONDS): $HASBIN/cl_lsvg -l $name" >>$CLMGR_TMPLOG
$HASBIN/cl_lsvg -l $name >>$file
cmd_rc=$?
print "$0()[$LINENO]($SECONDS): cl_ls_vgstatus RC: $cmd_rc" >>$CLMGR_TMPLOG
(( rc |= $cmd_rc ))
print >>$file
print "$0()[$LINENO]($SECONDS): /usr/sbin/lsattr -El $name" >>$CLMGR_TMPLOG
/usr/sbin/lsattr -El $name >>$file
cmd_rc=$?
print "$0()[$LINENO]($SECONDS): lsattr RC: $cmd_rc" >>$CLMGR_TMPLOG
(( rc |= $cmd_rc ))
done
fi
[[ $type == html ]] && print_html_footer >>$file
;;
ro*)
rc=$RC_SUCCESS
print "$0()[$LINENO]($SECONDS): Starting ROHA reporting into $file" >>$CLMGR_TMPLOG
print -n >$file
[[ $type == html ]] && print_html_header >>$file
print "$0()[$LINENO]($SECONDS): clreportroha -t text" >>$CLMGR_TMPLOG
typeset OUTPUT=$(clreportroha -t text)
cmd_rc=$?
print "$0()[$LINENO]($SECONDS): clreportroha -t text RC: $cmd_rc" >>$CLMGR_TMPLOG
(( rc |= $cmd_rc ))
print -- "$OUTPUT" |\
while IFS= read line; do
if [[ $line == '########'* ]]; then
continue
fi
print "$line" >>$file
done
[[ $type == html ]] && print_html_footer >>$file
print "$0()[$LINENO]($SECONDS): Finishing ROHA reporting into $file" >>$CLMGR_TMPLOG
;;
*)
rc=$RC_NOT_FOUND
/usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 135 "\nERROR: the specified report, \"%1\$s\", is not a known PowerHA report.\n\n" "$report" 1>&2
/usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 155 "Available Reports:\n\n" 1>&2
print -u2 "\
\tapplications
\tavailability
\tbasic
\tcluster
\tdependencies
\tevents
\tfsinfo
\tlvinfo
\tnetworks
\tnodeinfo
\trepositories
\trginfo
\tsoftware
\tstatus
\ttopology
\tvginfo
\troha
"
;;
esac
if [[ $file == $tmpfile && -f $file ]]; then
cat $file
rm -f $file
fi
fi
#=======================================================================
: If a user input error was detected, provide some helpful suggestions
#=======================================================================
if (( $rc == RC_MISSING_INPUT || $rc == RC_INCORRECT_INPUT )) && \
[[ $CLMGR_GUI == *([[:space:]]) ]]
then
CL=$LINENO cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 104 "For more information about available options and syntax, try\n\"$HAUTILS/clmgr %1\$s\". As an\nalternative, if the PowerHA SystemMirror man pages have been installed, invoke\n\"$HAUTILS/clmgr -hv\" (or \"/usr/bin/man clmgr\"),\nsearching for \"%2\$s\" in the displayed text.\n\n" \
"view report -h" "REPORT:" "$CLMGR_PROGNAME" 1>&2
fi
log_return_msg "$rc" "$0()" "$LINENO"
return $?
} # End of "KLIB_HACMP_view_report()"
#==============================================================================
#
# Name: on_exit_view_report
#
# Description: This is trap function that is always called on exit. It does
# a proper clean-up of any remaining processes or temporary
# files.
#
# Inputs: None.
#
# Outputs: None.
#
# Returns: Whatever return code was exited with is returned to the caller
# implicitly. This functions does not explicitly return anything
# because it would be ignored anyway.
#
#==============================================================================
function on_exit_view_report
{
[[ -n $tmpfile && -f $tmpfile ]] && /usr/bin/rm -f $tmpfile
#
: Check for the backgrounded functions that enforce the maximum allowed
: run-time limit via CLMGR_TIMEOUT.
#
if [[ $reaperPID == +([0-9]) ]] && \
ps -ef | grep -qw $reaperPID
then
print "$0()[$LINENO]($SECONDS): kill \$reaperPID ==> kill $reaperPID" >>$CLMGR_TMPLOG
kill $reaperPID >/dev/null 2>&1
fi
sleep 0.25
if [[ -s $TMPDIR/clmgr.KHvr.alarm.pid.$$ ]]
then
typeset ALARM_PID=$(cat $TMPDIR/clmgr.KHvr.alarm.pid.$$)
if [[ $ALARM_PID == +([0-9]) ]] && \
ps -ef | grep -qw $ALARM_PID
then
print "$0()[$LINENO]($SECONDS): kill \$ALARM_PID ==> kill $ALARM_PID" >>$CLMGR_TMPLOG
kill $ALARM_PID >/dev/null 2>&1
fi
fi
#
: Remove any lingering temporary files
#
for FILE in $CDATA_FILE $SITE_FILE $NODE_FILE $RG_FILE $DEP_PC_FILE \
$DEP_STARTA_FILE $DEP_STOPA_FILE $DEP_SNODE_FILE \
$DEP_DNODE_FILE $DEP_SSITE_FILE $NW_FILE $SIP_FILE $IF_FILE \
$VG_FILE $LV_FILE $MP_FILE $FS_FILE $PV_FILE $REPOS_FILE \
$TP_FILE $MG_FILE $STA_FILE $STS_FILE $MPAIR_FILE $AC_FILE \
$AM_FILE $EV_FILE $SS_METHODS_FILE $VER_METHODS_FILE \
$NT_METHODS_FILE $FC_FILE $INFO_FILE $RG_PROCSEQ_FILE \
$RP_FILE $TMPDIR/clmgr.KHvr.alarm.pid.$$ \
$TMPDIR/clmgr.KHvr.procs.$$
do
rm -f $FILE
done
(( $rc == RC_UNKNOWN )) && exit $RC_ERROR
} # End of "on_exit_view_report()"
#
# Displays a standard HTML file header
#
function print_html_header {
print "\
"
} # End of "print_html_header()"
#
# Displays a standard HTML file footer
#
function print_html_footer {
print "
"
} # End of "print_html_footer()"
#==============================================================================
#
# Name: process_temporal_data
#
# Description: Processes temporal dependency (i.e. parent/child, stop/after,
# ...) information.
#
# Inputs: DATA The raw data to be processed.
# targets The resource groups involved in the dependency.
#
# Outputs: None.
#
# Returns: Zero if no errors are detected. Otherwise, an appropriate
# non-zero value is returned. Refer to the "RETURN" section
# of the "devDoc()" function, above, for the standard return
# code values/meanings for clmgr.
#
#==============================================================================
function process_temporal_data {
typeset DATA="$1"
typeset targets="$2"
typeset -i cnt=0
typeset OUTPUT=
print -- "$DATA" |\
while IFS= read LINE; do
if [[ $LINE == *\'* ]]; then
if [[ $OUTPUT != *([[:space:]]) ]]; then
if [[ $targets != *([[:space:]]) ]]; then
for target in $targets; do
if [[ $OUTPUT == *$target* ]]; then
(( cnt++ > 0 )) && print
print -- "$OUTPUT"
break
fi
done
OUTPUT="$LINE"
else
(( cnt++ > 0 )) && print
print -- "$OUTPUT"
OUTPUT="$LINE"
fi
else
OUTPUT="$LINE"
fi
else
OUTPUT="$OUTPUT
$LINE"
fi
done
if [[ $OUTPUT != *([[:space:]]) ]]; then
if [[ $targets != *([[:space:]]) ]]; then
for target in $targets; do
if [[ $OUTPUT == *$target* ]]; then
(( cnt++ > 0 )) && print
print -- "$OUTPUT"
break
fi
done
else
(( cnt++ > 0 )) && print
print -- "$OUTPUT"
fi
fi
} # End of "process_temporal_data()"
#==============================================================================
#
# Name: get_list
#
# Description: Used by "process_location_data()" to extract the list of
# nodes involved in a location dependency.
#
# Inputs: LINE The data to be processed.
# type The type of location dependency.
#
# Outputs: None.
#
# Returns: Zero if no errors are detected. Otherwise, an appropriate
# non-zero value is returned. Refer to the "RETURN" section
# of the "devDoc()" function, above, for the standard return
# code values/meanings for clmgr.
#
#==============================================================================
function get_list {
typeset LINE="$1"
typeset type="$2"
typeset list=
if [[ $type == "NODECOLLOCATION" ]]; then
#===========================================
: Determine which nodes are common amongst
: the resource groups in this dependency.
#===========================================
for rg in $LINE; do
typeset -A attrs
CL=$LINENO KLIB_HACMP_get_rg_attributes "$rg" attrs 2>>$CLMGR_TMPLOG
if (( $? == RC_SUCCESS )); then
if [[ -n $list ]]; then
if [[ ${attrs[NODES]} == *([[:space:]]) ]]
then
list=
break
else
#================================
: Find the common list of nodes
#================================
typeset newlist=
for node in $list; do
if [[ " ${attrs[NODES]} " == *\ $node\ * ]]; then
newlist="$newlist $node"
fi
done
if [[ $newlist == *([[:space:]]) ]]
then
list=
break
else
list=$newlist
fi
fi
else
list=${attrs[NODES]}
fi
fi
done
elif [[ $type == "SITECOLLOCATION" ]]; then
if [[ -n $(odmget HACMPsite) ]]; then
typeset available
CL=$LINENO KLIB_HACMP_list_sites available 2>>$CLMGR_TMPLOG
for (( i=0; i<${#available[*]}; i++ )); do
list="$list ${available[$i]}"
done
fi
elif [[ $type == "ANTICOLLOCATION" ]]; then
LINE=${LINE//:/ }
for rg in $LINE; do
typeset -A attrs
CL=$LINENO KLIB_HACMP_get_rg_attributes "$rg" attrs 2>>$CLMGR_TMPLOG
if (( $? == RC_SUCCESS )); then
for node in ${attrs[NODES]}; do
[[ " $list " != *\ $node\ * ]] && list="$list $node"
done
fi
done
fi
if [[ $list != *([[:space:]]) ]]; then
print -- $list
fi
} # End of "get_list()"
#==============================================================================
#
# Name: process_location_data
#
# Description: Processes location dependency (i.e. same node, same site, ...)
# information.
#
# Inputs: DATA The raw data to be processed.
# targets The resource groups involved in the dependency.
# type The type of location dependency.
#
# Outputs: None.
#
# Returns: Zero if no errors are detected. Otherwise, an appropriate
# non-zero value is returned. Refer to the "RETURN" section
# of the "devDoc()" function, above, for the standard return
# code values/meanings for clmgr.
#
#==============================================================================
function process_location_data {
typeset DATA="$1"
typeset targets="$2"
typeset type="$3"
typeset -i cnt=0
print -- "$DATA" |\
while IFS= read LINE; do
if [[ $targets != *([[:space:]]) ]]; then
for target in $targets; do
if [[ $LINE == *$target* ]]; then
typeset LIST=
[[ $LINE != \#* ]] && LIST=$(get_list "$LINE" "$type")
[[ -n $LIST ]] && LIST=" (${LIST// /,})"
print -- "$LINE$LIST"
fi
done
else
typeset LIST=
[[ $LINE != \#* ]] && LIST=$(get_list "$LINE" "$type")
[[ -n $LIST ]] && LIST=" (${LIST// /,})"
print -- "$LINE$LIST"
fi
done
} # End of "process_location_data()"
#==============================================================================
#
# Name: create_html_report
#
# Description: Creates a comprehensive cluster report in HTML format.
#
# Inputs: OUTFILE The name of the file to write the report into.
# If not provided, the report is written to STDOUT
# instead.
# company_name The name of the company to include in the report
# header. If a logo is specified, and can be loaded
# by the browser, it will be displayed instead.
# company_logo The graphical logo of the company, to include in
# the report header. If the logo cannot be found by
# browser, the company name will be displayed.
#
# Outputs: The report is written to the specified file, if possible.
# Otherwise it is written to STDOUT.
#
# Returns: Zero if no errors are detected. Otherwise, an appropriate
# non-zero value is returned. Refer to the "RETURN" section
# of the "devDoc()" function, above, for the standard return
# code values/meanings for clmgr.
#
#==============================================================================
function create_html_report {
. $HALIBROOT/log_entry "$0()" "$CL"
: INPUTS: $*
typeset OUTFILE=$1
typeset company_name=$2
typeset company_logo=$3
typeset snapshot=$4
integer rc=$RC_UNKNOWN OBJECTS_FOUND=0
typeset LINES=0
typeset DATA=""
export CDATA_FILE="$TMPDIR/clmgr.KHvr.chcr.$$"
export SITE_FILE="$TMPDIR/clmgr.KHvr.chcr.site.$$"
export NODE_FILE="$TMPDIR/clmgr.KHvr.chcr.node.$$"
export RG_FILE="$TMPDIR/clmgr.KHvr.chcr.rg.$$"
export DEP_PC_FILE="$TMPDIR/clmgr.KHvr.chcr.dep_pc.$$"
export DEP_STARTA_FILE="$TMPDIR/clmgr.KHvr.chcr.dep_sta.$$"
export DEP_STOPA_FILE="$TMPDIR/clmgr.KHvr.chcr.dep_spa.$$"
export DEP_SNODE_FILE="$TMPDIR/clmgr.KHvr.chcr.dep_snode.$$"
export DEP_DNODE_FILE="$TMPDIR/clmgr.KHvr.chcr.dep_dnode.$$"
export DEP_SSITE_FILE="$TMPDIR/clmgr.KHvr.chcr.dep_ssite.$$"
export RG_PROCSEQ_FILE="$TMPDIR/clmgr.KHvr.chcr.proc_seq.$$"
export NW_FILE="$TMPDIR/clmgr.KHvr.chcr.nw.$$"
export SIP_FILE="$TMPDIR/clmgr.KHvr.chcr.sip.$$"
export IF_FILE="$TMPDIR/clmgr.KHvr.chcr.if.$$"
export VG_FILE="$TMPDIR/clmgr.KHvr.chcr.vg.$$"
export LV_FILE="$TMPDIR/clmgr.KHvr.chcr.lv.$$"
export MP_FILE="$TMPDIR/clmgr.KHvr.chcr.mpool.$$"
export FS_FILE="$TMPDIR/clmgr.KHvr.chcr.fs.$$"
export PV_FILE="$TMPDIR/clmgr.KHvr.chcr.pv.$$"
export REPOS_FILE="$TMPDIR/clmgr.KHvr.chcr.repos.$$"
export TP_FILE="$TMPDIR/clmgr.KHvr.chcr.tape.$$"
export MG_FILE="$TMPDIR/clmgr.KHvr.chcr.mgrp.$$"
export STA_FILE="$TMPDIR/clmgr.KHvr.chcr.stagt.$$"
export STS_FILE="$TMPDIR/clmgr.KHvr.chcr.stsys.$$"
export MPAIR_FILE="$TMPDIR/clmgr.KHvr.chcr.mpair.$$"
export AC_FILE="$TMPDIR/clmgr.KHvr.chcr.appctl.$$"
export AM_FILE="$TMPDIR/clmgr.KHvr.chcr.appmon.$$"
export EV_FILE="$TMPDIR/clmgr.KHvr.chcr.clev.$$"
export SS_METHODS_FILE="$TMPDIR/clmgr.KHvr.chcr.ssmd.$$"
export VER_METHODS_FILE="$TMPDIR/clmgr.KHvr.chcr.vrmd.$$"
export NT_METHODS_FILE="$TMPDIR/clmgr.KHvr.chcr.ntmd.$$"
export FC_FILE="$TMPDIR/clmgr.KHvr.chcr.fc.$$"
export INFO_FILE="$TMPDIR/clmgr.KHvr.chcr.info.$$"
export RP_FILE="$TMPDIR/clmgr.KHvr.chcr.template.$$"
typeset CHRC_CHILDREN=""
#
: Define the SVG graphics icons
#
typeset -r UP_ARROW_SVG=''
typeset -r DOWN_ARROW_SVG=''
typeset -r OPEN_LOCK=''
typeset -r CLOSED_LOCK=''
if [[ -n $snapshot ]]
then
#
: Collect and process the $snapshot.info file. Run this
: this in parallel with the even-slower snapshot data
: collection from KLIB_HACMP_get_cluster_attributes so
: that a performance hit is only taken once, not twice.
#
if [[ -s $SNAPSHOTPATH/$snapshot.info ]]
then
(
: Load the raw info file data
typeset INFO=$(cat $SNAPSHOTPATH/$snapshot.info)
typeset XMP=""
integer FIRST=0 SECOND=0 FIRST_STANZA=0
integer LINES=$(print -- "$INFO" | wc -l)
#
: This code takes advantage of the consistent format of each command header
: output in the $snapshot.info file. It leverages that to HTMLify them
: for display in the graphical snapshot report.
#
print -- "$INFO" | grep -n "^COMMAND: " |\
while IFS=: read LNUM COMMAND
do
(( FIRST = LNUM - 1 ))
(( SECOND = LNUM + 1 ))
HTML="$XMP
$COMMAND \ \⏬<\/DIV>\\\n
"
INFO=$(print -- "$INFO" | sed "${LNUM}d")
INFO=$(print -- "$INFO" | sed "${FIRST}s|^.*$|${HTML//\|/\\\|}|")
INFO=$(print -- "$INFO" | sed "${SECOND}s/^.*$/\/")
(( FIRST_STANZA == 0 )) && (( FIRST_STANZA = FIRST - 1 ))
XMP="
"
print -- "$INFO" >$INFO_FILE
)&
CHCR_CHILDREN="${CHCR_CHILDREN:+$CHCR_CHILDREN }$!"
fi
CL=$LINENO CLMGR_VERBOSE=1 KLIB_HACMP_get_cluster_attributes NULL "" "$snapshot" >$CDATA_FILE 2>>$CLMGR_TMPLOG
rc=$?
elif [[ -n $company_logo && -z $company_name ]]; then
dspmsg -s $CLMGR_SET $CLMGR_MSGS 180 '\nERROR: "%1$s" requires the following option(s): %2$s.\n\n' COMPANY_LOGO COMPANY_NAME 1>&2
rc=$RC_INCORRECT_INPUT
else
CL=$LINENO CLMGR_VERBOSE=1 KLIB_HACMP_get_cluster_attributes NULL "" "" >$CDATA_FILE
rc=$?
fi
if (( rc == RC_SUCCESS )); then
typeset REPORT="" TEMPLATE_FILE=""
if [[ -n $snapshot ]]
then
: A snapshot report
TEMPLATE_FILE="/usr/es/sbin/cluster/reports/templates/ss_report_template.htm"
else
: A cluster report
TEMPLATE_FILE="/usr/es/sbin/cluster/reports/templates/cl_report_template.htm"
fi
typeset TAG="" VAR="" VALUE=""
typeset -l LC_VAL=""
typeset CLUSTER_TYPE=$(egrep "^TYPE=\"(LC|SC|NSC)\"" $CDATA_FILE | cut -d\" -f2)
if [[ $CLUSTER_TYPE != "NSC" ]]; then
(
#============================================
: Construct the SITES section of the report
#============================================
#===============================================
: Load the data that is needed for this report
: from the clmgr verbose cluster output
#===============================================
typeset SITE_DATA="$(sed -n '//,/<\/SITES>/p' $CDATA_FILE | grep -v 'SITES>$')"
#
: Extract the template from the overall report
#
typeset LABEL="site_card_template"
typeset SITE_TEMPLATE=$(sed -n "/<%${LABEL}_start%>/,/<%${LABEL}_end%>/p" $TEMPLATE_FILE | grep -v "<%$LABEL")
#
: Extract the row separator from the template
#
# The SIZE value, below, must be set to the number of lines of HTML
# used for it in the (cl|ss)_report_template.htm files. For this
# one, search for the "hr" line near the "site_card_template_end"
# tag. The size should include the HTML code, plus any associated
# comments.
#
integer SITE_SEPARATOR_SIZE=8
typeset SITE_SEPARATOR=$(print -- "$SITE_TEMPLATE" | tail -$SITE_SEPARATOR_SIZE)
SITE_SEPARATOR=${SITE_SEPARATOR//\<\!--*--\>/} # Remove all comments
SITE_SEPARATOR=${SITE_SEPARATOR##*( )+(\n)}
SITE_SEPARATOR=${SITE_SEPARATOR%%*( )+(\n)}
#
: Remove the separator, then the template, from the overall report
#
integer LINES=$(print -- "$SITE_TEMPLATE" | wc -l)
SITE_TEMPLATE=$(print -- "$SITE_TEMPLATE" | head -n $(( LINES -= SITE_SEPARATOR_SIZE )))
SITE_TEMPLATE="${SITE_TEMPLATE%%+([[:space:]])}"
typeset SITE_REPORT=""
typeset -i SITE_COUNT=0
print -- "$SITE_DATA\n" | grep -p NAME= |\
while read LINE
do
#
: A blank line separator indicates the start of a new block of node data
#
if [[ $LINE == *([[:space:]]) ]]
then
(( SITE_COUNT++ ))
(( SITE_COUNT > 1 )) && SITE_REPORT="$SITE_REPORT$NL$NL$SITE_SEPARATOR$NL"
CARD="$SITE_TEMPLATE"
CARD=${CARD//\<%name%\>/$NAME}
CARD=${CARD//\<%status%\>/${STATE:--}}
CARD=${CARD//\<%site_ip%\>/${SITE_IP:--}}
CARD=${CARD//\<%site_nodes%\>/${NODES:--}}
CARD=${CARD//\<%recovery_priority%\>/${RECOVERY_PRIORITY:--}}
CARD=${CARD//\<%primary%\>/${PRIMARY:--}}\
SITE_REPORT="$SITE_REPORT$NL$CARD"
#
: Free the variables that were set for site "$NAME".
: This releases some memory, but more importantly, it ensures
: that data from one object does not get accidentally shown
: with another one.
#
unset NAME NAME STATE SITE_IP NODES RECOVERY_PRIORITY PRIMARY
elif [[ $LINE == *=* ]]; then
PVAR=${LINE%%=*}
PVAL=${LINE#*=}
eval "${PVAR//-/_}=$PVAL" # Store the value in an environment variable
fi
done # End of the "VG_DATA" loop
#
: Save the constructed report into a temporary file for later processing
#
print -- "$SITE_REPORT" >$SITE_FILE
)&
CHCR_CHILDREN="${CHCR_CHILDREN:+$CHCR_CHILDREN }$!"
fi
(
#===========================================
: Construct the NODE section of the report
#===========================================
#===============================================
: Load the data that is needed for this report
: from the clmgr verbose cluster output
#===============================================
typeset NODE_DATA="$(sed -n '//,/<\/NODES>/p' $CDATA_FILE | grep -v 'NODES>$')"
typeset INTERFACE_DATA="$(sed -n '//,/<\/INTERFACES>/p' $CDATA_FILE | grep -v 'INTERFACES>$')"
typeset RG_DATA="$(sed -n '//,/<\/RESOURCE_GROUPS>/p' $CDATA_FILE | grep -v 'RESOURCE_GROUPS>$')"
#
: Bulk/Fast load some labels
#
eval $(cl_batch_dspmsg -e -s $CLMGR_RPT_SET $CLMGR_MSGS \
43:STATUS_LBL "Status:" \
8:HOSTNAME_LBL "Host Name:" \
9:COMMPATH_LBL "Communication Path:" \
10:RGS_LBL "Resource Groups:" \
11:INTERFACES_LBL "Interfaces" \
12:PIPS_LBL "Persistent IP Addresses:" \
13:AIX_LEVEL_LBL "AIX Level:" \
14:SITE_LBL "Site Name:" \
15:HOST_LABEL_LBL "LPAR Host Name:")
#
: Extract the template from the overall report
#
typeset LABEL="node_card_template"
typeset NODE_TEMPLATE=$(sed -n "/<%${LABEL}_start%>/,/<%${LABEL}_end%>/p" $TEMPLATE_FILE | grep -v "<%$LABEL")
#
: Extract the row separator from the template
#
# The SIZE value, below, must be set to the number of lines of HTML
# used for it in the (cl|ss)_report_template.htm files. For this
# one, search for the "hr" line near the "node_card_template_end"
# tag. The size should include the HTML code, plus any associated
# comments.
#
integer NODE_SEPARATOR_SIZE=10
typeset NODE_SEPARATOR=$(print -- "$NODE_TEMPLATE" | tail -$NODE_SEPARATOR_SIZE)
NODE_SEPARATOR=${NODE_SEPARATOR//\<\!--*--\>/} # Remove all comments
NODE_SEPARATOR=${NODE_SEPARATOR##*( )+(\n)}
NODE_SEPARATOR=${NODE_SEPARATOR%%*( )+(\n)}
#
: Remove the separator, then the template, from the overall report
#
integer LINES=$(print -- "$NODE_TEMPLATE" | wc -l)
NODE_TEMPLATE=$(print -- "$NODE_TEMPLATE" | head -n $(( LINES -= NODE_SEPARATOR_SIZE )))
NODE_TEMPLATE="${NODE_TEMPLATE%%+([[:space:]])}"
typeset NODE_REPORT=""
typeset -i NODE_COUNT=0
print -- "$NODE_DATA\n" | grep -p NAME= |\
while read LINE
do
#
: A blank line separator indicates the start of a new block of node data
#
if [[ $LINE == *([[:space:]]) ]]
then
(( NODE_COUNT++ ))
(( NODE_COUNT > 1 )) && NODE_REPORT="$NODE_REPORT$NL$NL$NODE_SEPARATOR$NL"
CARD="$NODE_TEMPLATE"
CARD=${CARD//\<%node_name%\>/$NAME}
#=======================================================
: Find all the resource group for node "$NAME", if any
#=======================================================
typeset NODE_RGS=""
DATA=$(print -- "$RG_DATA" | egrep -e ^NAME= -e ^NODES=)
DATA=${DATA//${NL}NODES=/ NODES=}
print -- "$DATA" |\
while read LINE; do
typeset RG_NAME=${LINE%% *}
typeset RG_NODES=${LINE#* }
RG_NAME=${RG_NAME#*=}
RG_NAME=${RG_NAME//\"/}
RG_NODES=${RG_NODES#*=}
RG_NODES=${RG_NODES//\"/}
if [[ " $RG_NODES " == *\ $NAME\ * ]]; then
[[ -n $NODE_RGS ]] && NODE_RGS="$NODE_RGS, "
NODE_RGS="$NODE_RGS$RG_NAME"
fi
done
#===========================================
: Find all the interfaces for node "$NAME"
#===========================================
typeset NODE_IFS=""
print -- "$INTERFACE_DATA" | egrep -e ^NAME= -e ^NODE= |\
while read LINE; do
if [[ $LINE == NODE=* ]]; then
LINE=${LINE#*=}
LINE=${LINE//\"/}
if [[ $LINE == $NAME ]]; then
[[ -n $NODE_IFS ]] && NODE_IFS="$NODE_IFS, "
NODE_IFS="$NODE_IFS$VAL"
fi
VAL=""
else # An interface line
VAL=${LINE#*=}
VAL=${VAL//\"/}
fi
done
if [[ $CLUSTER_TYPE != "NSC" ]]; then
#=====================================
: Find the site this node belongs to
#=====================================
typeset SITE_DATA="$(sed -n '//,/<\/SITES>/p' $CDATA_FILE | grep -v 'SITES>$')"
typeset SITE_NODES=$(print -- "$SITE_DATA" |\
egrep -e "^NAME=" -e "^NODES=")
print -- "${SITE_NODES//${NL}NODES=/ NODES=}" |\
while read LINE; do
typeset SITE=${LINE#*\"}
SITE=${SITE%%\"*}
typeset NODES=${LINE##*=\"}
NODES=${NODES%\"}
if [[ " ${NODES//,/ } " == *\ $NAME\ * ]]; then
NODE_SITE=$SITE
break
fi
done
fi
CARD=${CARD//\<%node_status_lbl%\>/${STATUS_LBL%:}}
CARD=${CARD//\<%node_status%\>/${STATE:--}}
CARD=${CARD//\<%node_site_lbl%\>/${SITE_LBL%:}}
if [[ -n $NODE_SITE ]]
then
NODE_SITE="$NODE_SITE"
else
NODE_SITE="--"
fi
CARD=${CARD//\<%node_site%\>/$NODE_SITE}
CARD=${CARD//\<%node_host_lbl%\>/${HOSTNAME_LBL%:}}
CARD=${CARD//\<%node_host%\>/${HOSTNAME:--}}
CARD=${CARD//\<%node_commpath_lbl%\>/${COMMPATH_LBL%:}}
CARD=${CARD//\<%node_commpath%\>/${COMMPATH:--}}
CARD=${CARD//\<%node_rgs_lbl%\>/${RGS_LBL%:}}
typeset LINKS=""
for OBJECT in ${NODE_RGS//,/ }
do
LINKS="${LINKS:+$LINKS, }$OBJECT"
done
CARD=${CARD//\<%node_rgs%\>/${LINKS:--}}
CARD=${CARD//\<%node_ifs_lbl%\>/${INTERFACES_LBL%:}}
LINKS=""
for OBJECT in ${NODE_IFS//,/ }
do
LINKS="${LINKS:+$LINKS,}$OBJECT"
done
CARD=${CARD//\<%node_ifs%\>/${LINKS:--}}
CARD=${CARD//\<%node_platform_lbl%\>/${AIX_LEVEL_LBL%:}}
CARD=${CARD//\<%node_platform%\>/${AIX_LEVEL:--}}
NODE_REPORT="$NODE_REPORT$NL$CARD"
#
: Free the variables that were set for node "$NAME".
: This releases some memory, but more importantly, it ensures
: that data from one object does not get accidentally shown
: with another one.
#
for VAR in NAME HOSTNAME GID STATE RAW_STATE COMMPATH VERSION \
VERSION_NUMBER EDITION AIX_LEVEL UNSYNCED_CHANGES \
START_ON_BOOT BROADCAST_ON_START CLINFO_ON_START \
SITE NODES NODE_SITE LINE NODE_RGS \
NODE_IFS LINKS HOST_LABEL
do
unset $VAR
done
elif [[ $LINE == *=* ]]; then
PVAR=${LINE%%=*}
PVAL=${LINE#*=}
eval "${PVAR//-/_}=$PVAL" # Store the value in an environment variable
fi
done # End of the "NODE_DATA" loop
#
: Save the constructed report into a temporary file for later processing
#
print -- "$NODE_REPORT" >$NODE_FILE
)&
CHCR_CHILDREN="${CHCR_CHILDREN:+$CHCR_CHILDREN }$!"
(
#=========================================
: Construct the RG section of the report
#=========================================
#===============================================
: Load the data that is needed for this report
: from the clmgr verbose cluster output
#===============================================
typeset RG_DATA="$(sed -n '//,/<\/RESOURCE_GROUPS>/p' $CDATA_FILE | grep -v 'RESOURCE_GROUPS>$')"
#
: Extract the template from the overall report
#
typeset LABEL="rg_card_template"
typeset RG_TEMPLATE=$(sed -n "/<%${LABEL}_start%>/,/<%${LABEL}_end%>/p" $TEMPLATE_FILE | grep -v "<%$LABEL")
#
: Extract the row separator from the template
#
# The SIZE value, below, must be set to the number of lines of HTML
# used for it in the (cl|ss)_report_template.htm files. For this
# one, search for the "hr" line near the "rg_card_template_end"
# tag. The size should include the HTML code, plus any associated
# comments.
#
integer RG_SEPARATOR_SIZE=10
typeset RG_SEPARATOR=$(print -- "$RG_TEMPLATE" | tail -$RG_SEPARATOR_SIZE)
RG_SEPARATOR=${RG_SEPARATOR//\<\!--*--\>/} # Remove all comments
RG_SEPARATOR=${RG_SEPARATOR##*( )+(\n)}
RG_SEPARATOR=${RG_SEPARATOR%%*( )+(\n)}
#
: Remove the separator, then the template, from the overall report
#
integer LINES=$(print -- "$RG_TEMPLATE" | wc -l)
RG_TEMPLATE=$(print -- "$RG_TEMPLATE" | head -n $(( LINES -= RG_SEPARATOR_SIZE )))
RG_TEMPLATE="${RG_TEMPLATE%%+([[:space:]])}"
typeset RG_REPORT=""
typeset -i RG_COUNT=0
print -- "$RG_DATA\n" | grep -p NAME= |\
while read LINE
do
#
: A blank line separator indicates the start of a new block of node data
#
if [[ $LINE == *([[:space:]]) ]]
then
(( RG_COUNT++ ))
(( RG_COUNT > 1 )) && RG_REPORT="$RG_REPORT$NL$NL$RG_SEPARATOR$NL"
typeset CARD="$RG_TEMPLATE"
CARD=${CARD//\<%rg_name%\>/$NAME}
#
: Replace RG data targets within the report with data values
#
for DATA in "rg_name|NAME|$NAME" \
"rg_nodes|NODES|$NODES" "rg_status|STATE|$STATE" \
"rg_2ndry_nodes|SECONDARYNODES|$SECONDARYNODES" \
"rg_2ndry_status|SECONDARY_STATE|$SECONDARY_STATE" \
"fbtimer|FALLBACK_AT|$FALLBACK_AT" \
"sips|SERVICE_LABEL|$SERVICE_LABEL" \
"apps|APPLICATIONS|$APPLICATIONS" \
"vgs|VOLUME_GROUP|$VOLUME_GROUP" \
"fses|FILESYSTEM|$FILESYSTEM" \
"rdisks|DISK|$DISK" "mgrps|MIRROR_GROUP|$MIRROR_GROUP" \
"tapes|SHARED_TAPE_RESOURCES|$SHARED_TAPE_RESOURCES" \
"exp_fs_v3|EXPORT_FILESYSTEM|$EXPORT_FILESYSTEM" \
"exp_fs_v4|EXPORT_FILESYSTEM_V4|$EXPORT_FILESYSTEM_V4" \
"stable_storage|STABLE_STORAGE_PATH|$STABLE_STORAGE_PATH" \
"fs_mounts|MOUNT_FILESYSTEM|$MOUNT_FILESYSTEM" \
"nfs_network|NFS_NETWORK|$NFS_NETWORK" \
"rg_node_priority|NODE_PRIORITY_POLICY|$NODE_PRIORITY_POLICY" \
"site_rel|SITE_POLICY|$SITE_POLICY"
do
print -- "$DATA" | IFS=\| read TAG VAR VALUE
[[ -z $VALUE ]] && VALUE="-"
if [[ $VAR == @(SERVICE_LABEL|NODES|SECONDARYNODES|APPLICATIONS|VOLUME_GROUP|FILESYSTEM|MOUNT_FILESYSTEM|NFS_NETWORK|SHARED_TAPE_RESOURCES) ]]
then
typeset COPY="$VALUE"
for OBJECT in ${VALUE//,/ }
do
if [[ $OBJECT != "-" ]]
then
if [[ $VAR != *FILESYSTEM* || $OBJECT != "ALL" ]]
then
COPY=${COPY//$OBJECT/\$OBJECT\, }
fi
fi
done
CARD=${CARD//\<%$TAG%\>/${COPY%, }}
unset COPY
else
CARD=${CARD//\<%$TAG%\>/${VALUE%:}}
fi
#
: Free the variables that were set for resource group "$NAME".
: This releases some memory, but more importantly, it ensures
: that data from one object does not get accidentally shown
: with another one.
#
[[ -n $VAR ]] && unset $VAR
done
RG_REPORT="$RG_REPORT$NL$CARD"
typeset STRINGS=$(dspmsg -s 4 cluster.cat 991 "Online On Home Node Only,Online On First Available Node,Online Using Node Distribution Policy,Online On All Available Nodes")
case $STARTUP in
OHN) STARTUP=$(print -- "$STRINGS" | cut -f1 -d,) ;;
OFAN) STARTUP=$(print -- "$STRINGS" | cut -f2 -d,) ;;
OAAN) STARTUP=$(print -- "$STRINGS" | cut -f4 -d,) ;;
OUDP) STARTUP=$(print -- "$STRINGS" | cut -f3 -d,) ;;
esac
RG_REPORT=${RG_REPORT//\<%rg_startup%\>/$STARTUP}
STRINGS=$(dspmsg -s 4 cluster.cat 992 "Fallover To Next Priority Node In The List,Fallover Using Dynamic Node Priority,Bring Offline (On Error Node Only)")
case $FALLOVER in
FNPN) FALLOVER=$(print -- "$STRINGS" | cut -f1 -d,) ;;
FUDNP) FALLOVER=$(print -- "$STRINGS" | cut -f2 -d,) ;;
BO) FALLOVER=$(print -- "$STRINGS" | cut -f3 -d,) ;;
esac
RG_REPORT=${RG_REPORT//\<%rg_fallover%\>/$FALLOVER}
STRINGS=$(dspmsg -s 4 cluster.cat 993 "Fallback To Higher Priority Node In The List,Never Fallback")
case $FALLBACK in
NFB) FALLBACK=$(print -- "$STRINGS" | cut -f2 -d,) ;;
FBHPN) FALLBACK=$(print -- "$STRINGS" | cut -f1 -d,) ;;
esac
RG_REPORT=${RG_REPORT//\<%rg_fallback%\>/$FALLBACK}
STRINGS=$(dspmsg -s 4 cluster.cat 994 "ignore,Prefer Primary Site,Online On Either Site,Online On Both Sites")
case $SITE_POLICY in
ignore) SITE_POLICY=$(print -- "$STRINGS" | cut -f1 -d,) ;;
primary) SITE_POLICY=$(print -- "$STRINGS" | cut -f2 -d,) ;;
either) SITE_POLICY=$(print -- "$STRINGS" | cut -f3 -d,) ;;
both) SITE_POLICY=$(print -- "$STRINGS" | cut -f4 -d,) ;;
esac
RG_REPORT=${RG_REPORT//\<%site_rel%\>/$SITE_POLICY}
elif [[ $LINE == *=* ]]; then
PVAR=${LINE%%=*}
PVAL=${LINE#*=}
eval "${PVAR//-/_}=$PVAL" # Store the value in an environment variable
fi
done # End of the "RG_DATA" loop
cl_batch_dspmsg -e -s $CLMGR_RPT_SET $CLMGR_MSGS \
35:geninfo "General Information" \
53:nodes "Nodes:" \
54:rgs "Resource Groups" \
55:2ndry_nodes "Secondary Nodes:" \
56:2ndry_status "Secondary Status:" \
57:fbtimer "Delayed Fallback Timer:" \
58:manages "Manages" \
59:sips "Service IP Labels/Addresses:" \
60:apps "Applications:" \
61:fses "File Systems:" \
62:mgrps "Mirror Groups:" \
63:exp_fs_v3 "Exported File Systems (NFS v2/3):" \
64:exp_fs_v4 "Exported File Systems (NFS v4):" \
65:stable_storage "Stable Storage Path:" \
66:fs_mounts "File Systems to NFS Mount:" \
67:nfs_network "Network for NFS Mount:" \
68:startup_pol "Startup:" \
69:fallover_pol "Fallover:" \
70:fallback_pol "Fallback:" \
71:node_priority_pol "Node Priority:" \
72:site_rel "Site Relationship:" \
73:vgs "Volume Groups:" \
74:rdisks "Raw Disks:" \
75:tapes "Tapes:" \
76:policies "Policies" |\
while read LINE; do
TAG=${LINE%%=*}
TAG=${TAG#typeset }
TAG=${TAG#_}
LABEL=${LINE#*=}
LABEL=${LABEL#\"}
LABEL=${LABEL%\"}
LABEL="${LABEL%:}"
[[ $TAG != *_lbl ]] && TAG=${TAG}_lbl
RG_REPORT=${RG_REPORT//\<%$TAG%\>/$LABEL}
if [[ $TAG == @(type|status|nodes|fses|mgrps|vgs|rdisks|tapes)_lbl ]]
then
: For messages that have a minor variation. No colon.
TAG="${TAG%_lbl}_nocolon_lbl"
LABEL=${LABEL/:\ \;/\ \;}
RG_REPORT=${RG_REPORT//\<%$TAG%\>/$LABEL}
fi
done
#
: Save the constructed report into a temporary file for later processing
#
print -- "$RG_REPORT" >$RG_FILE
)&
CHCR_CHILDREN="${CHCR_CHILDREN:+$CHCR_CHILDREN }$!"
(
#===============================================
: Load the data that is needed for this report
: from the clmgr verbose cluster output
#===============================================
typeset DEP_DATA="$(sed -n '//,/<\/DEPENDENCIES>/p' $CDATA_FILE | grep -v 'DEPENDENCIES>$')"
#
: Extract the sequential dependency templates from the overall report
#
typeset LABEL="rg_parent_child_row_template"
typeset PC_ROW_TEMPLATE=$(sed -n "/<%${LABEL}_start%>/,/<%${LABEL}_end%>/p" $TEMPLATE_FILE | grep -v "<%$LABEL")
LABEL="rg_start_after_row_template"
typeset START_AFTER_ROW_TEMPLATE=$(sed -n "/<%${LABEL}_start%>/,/<%${LABEL}_end%>/p" $TEMPLATE_FILE | grep -v "<%$LABEL")
LABEL="rg_stop_after_row_template"
typeset STOP_AFTER_ROW_TEMPLATE=$(sed -n "/<%${LABEL}_start%>/,/<%${LABEL}_end%>/p" $TEMPLATE_FILE | grep -v "<%$LABEL")
#
: Extract the location dependency templates from the overall report
#
LABEL="rg_same_node_row_template"
typeset SAME_NODE_ROW_TEMPLATE=$(sed -n "/<%${LABEL}_start%>/,/<%${LABEL}_end%>/p" $TEMPLATE_FILE | grep -v "<%$LABEL")
LABEL="rg_different_node_row_template"
typeset DIFFERENT_NODE_ROW_TEMPLATE=$(sed -n "/<%${LABEL}_start%>/,/<%${LABEL}_end%>/p" $TEMPLATE_FILE | grep -v "<%$LABEL")
LABEL="rg_same_site_row_template"
typeset SAME_SITE_ROW_TEMPLATE=$(sed -n "/<%${LABEL}_start%>/,/<%${LABEL}_end%>/p" $TEMPLATE_FILE | grep -v "<%$LABEL")
#
: Extract the processing sequence template from the overall report
#
LABEL="rg_proc_seq_row_template"
typeset PSEQ_TEMPLATE=$(sed -n "/<%${LABEL}_start%>/,/<%${LABEL}_end%>/p" $TEMPLATE_FILE | grep -v "<%$LABEL")
cl_batch_dspmsg -e -s $CLMGR_RPT_SET $CLMGR_MSGS \
84:rgs_acq_par "Resource Groups Acquired in Parallel:" \
85:rgs_rel_par "Resource Groups Released in Parallel:" \
86:rgs_acq_ser "Resource Groups Acquired Serially:" \
87:rgs_rel_ser "Resource Groups Released Serially:" |\
while read LINE; do
TAG=${LINE%%=*}
TAG=${TAG#typeset }
TAG=${TAG#_}
LABEL=${LINE#*=}
LABEL=${LABEL#\"}
LABEL=${LABEL%\"}
LABEL="${LABEL%:}"
[[ $TAG != *_lbl ]] && TAG=${TAG}_lbl
PSEQ_TEMPLATE=${PSEQ_TEMPLATE//\<%$TAG%\>/$LABEL}
done
typeset RG_TDEP_REPORT="" RG_LDEP_REPORT="" RG_PARENT_CHILD_DEP_REPORT=""
typeset RG_START_AFTER_DEP_REPORT="" RG_STOP_AFTER_DEP_REPORT=""
typeset RG_SAME_NODE_DEP_REPORT="" RG_DIFFERENT_NODE_DEP_REPORT=""
typeset RG_SAME_SITE_DEP_REPORT=""
integer TOBJECTS_FOUND=0 PC_COUNT=0 START_AFTER_COUNT=0 STOP_AFTER_COUNT=0
integer SAME_NODE_FOUND=0 SAME_SITE_FOUND=0 DIFF_NODES_FOUND=0
integer ACQPAR=0 RELPAR=0 ACQSER=0 RELSER=0
print -- "$DEP_DATA\n" | grep -p NAME= |\
while read LINE; do
if [[ $LINE == *([[:space:]]) ]]; then
typeset LINKS=""
for OBJECT in ${GROUPS//,/ }
do
LINKS="${LINKS:+$LINKS, }$OBJECT"
done
GROUPS="$LINKS"
case $TYPE in
ACQ*PAR*)
ACQPAR=1
PSEQ_TEMPLATE=${PSEQ_TEMPLATE//\<%rgs_acq_par%\>/$GROUPS}
;;
ACQ*SER*)
ACQSER=1
PSEQ_TEMPLATE=${PSEQ_TEMPLATE//\<%rgs_acq_ser%\>/$GROUPS}
;;
REL*PAR*)
RELPAR=1
PSEQ_TEMPLATE=${PSEQ_TEMPLATE//\<%rgs_rel_par%\>/$GROUPS}
;;
REL*SER*)
RELSER=1
PSEQ_TEMPLATE=${PSEQ_TEMPLATE//\<%rgs_rel_ser%\>/$GROUPS}
;;
PARENT_CHILD)
(( TOBJECTS_FOUND++ ))
(( PC_COUNT++ ))
if [[ -n $RG_PARENT_CHILD_DEP_REPORT ]]; then
RG_PARENT_CHILD_DEP_REPORT="$RG_PARENT_CHILD_DEP_REPORT$NL"
fi
RG_PARENT_CHILD_DEP_REPORT="$RG_PARENT_CHILD_DEP_REPORT$PC_ROW_TEMPLATE$NL"
RG_PARENT_CHILD_DEP_REPORT=${RG_PARENT_CHILD_DEP_REPORT//\<%rg_parent%\>/\$PARENT\}
LINKS=""
for OBJECT in ${CHILD//,/ }
do
LINKS="${LINKS:+$LINKS, }$OBJECT"
done
CHILD="$LINKS"
RG_PARENT_CHILD_DEP_REPORT=${RG_PARENT_CHILD_DEP_REPORT//\<%rg_children%\>/$CHILD}
;;
START_AFTER)
(( TOBJECTS_FOUND++ ))
(( START_AFTER_COUNT++ ))
if [[ -n $RG_START_AFTER_DEP_REPORT ]]; then
RG_START_AFTER_DEP_REPORT="$RG_START_AFTER_DEP_REPORT$NL"
fi
RG_START_AFTER_DEP_REPORT="$RG_START_AFTER_DEP_REPORT$START_AFTER_ROW_TEMPLATE$NL"
LINKS=""
for OBJECT in ${START//,/ }
do
LINKS="${LINKS:+$LINKS, }$OBJECT"
done
START="$LINKS"
RG_START_AFTER_DEP_REPORT=${RG_START_AFTER_DEP_REPORT//\<%rg_start_after_source%\>/$START}
RG_START_AFTER_DEP_REPORT=${RG_START_AFTER_DEP_REPORT//\<%rg_start_after_target%\>/\$AFTER\}
;;
STOP_AFTER)
(( TOBJECTS_FOUND++ ))
(( STOP_AFTER_COUNT++ ))
if [[ -n $RG_STOP_AFTER_DEP_REPORT ]]; then
RG_STOP_AFTER_DEP_REPORT="$RG_STOP_AFTER_DEP_REPORT$NL"
fi
RG_STOP_AFTER_DEP_REPORT="$RG_STOP_AFTER_DEP_REPORT$STOP_AFTER_ROW_TEMPLATE$NL"
LINKS=""
for OBJECT in ${STOP//,/ }
do
LINKS="${LINKS:+$LINKS, }$OBJECT"
done
STOP="$LINKS"
RG_STOP_AFTER_DEP_REPORT=${RG_STOP_AFTER_DEP_REPORT//\<%rg_stop_after_source%\>/$STOP}
RG_STOP_AFTER_DEP_REPORT=${RG_STOP_AFTER_DEP_REPORT//\<%rg_stop_after_target%\>/\$AFTER\}
;;
SAME_NODE)
SAME_NODE_FOUND=1
if [[ -n $RG_SAME_NODE_DEP_REPORT ]]; then
RG_SAME_NODE_DEP_REPORT="$RG_SAME_NODE_DEP_REPORT$NL"
fi
RG_SAME_NODE_DEP_REPORT="$RG_SAME_NODE_DEP_REPORT$SAME_NODE_ROW_TEMPLATE$NL"
RG_SAME_NODE_DEP_REPORT=${RG_SAME_NODE_DEP_REPORT//\<%rg_same_node%\>/$GROUPS}
;;
SAME_SITE)
SAME_SITE_FOUND=1
if [[ -n $RG_SAME_SITE_DEP_REPORT ]]; then
RG_SAME_SITE_DEP_REPORT="$RG_SAME_SITE_DEP_REPORT$NL"
fi
RG_SAME_SITE_DEP_REPORT="$RG_SAME_SITE_DEP_REPORT$SAME_SITE_ROW_TEMPLATE$NL"
RG_SAME_SITE_DEP_REPORT=${RG_SAME_SITE_DEP_REPORT//\<%rg_same_site%\>/$GROUPS}
;;
DIFFERENT_NODES)
DIFF_NODES_FOUND=1
if [[ -n $RG_DIFFERENT_NODE_DEP_REPORT ]]; then
RG_DIFFERENT_NODE_DEP_REPORT="$RG_DIFFERENT_NODE_DEP_REPORT$NL"
fi
GROUPS="\
HIGH => \"${HIGH//,/, }\"
INTERMEDIATE => \"${INTERMEDIATE//,/, }\"
LOW => \"${LOW//,/, }\""
RG_DIFFERENT_NODE_DEP_REPORT="$RG_DIFFERENT_NODE_DEP_REPORT$DIFFERENT_NODE_ROW_TEMPLATE$NL"
RG_DIFFERENT_NODE_DEP_REPORT=${RG_DIFFERENT_NODE_DEP_REPORT//\<%rg_different_node%\>/$GROUPS}
;;
esac
#
: Free the variables that were set for dependency "$NAME".
: This releases some memory, but more importantly, it ensures
: that data from one object does not get accidentally shown
: with another one.
#
unset NAME TYPE GROUP GROUPS PARENT CHILD START STOP AFTER \
HIGH INTERMEDIATE LOW LINKS
elif [[ $LINE == *=* ]]; then
PVAR=${LINE%%=*}
PVAL=${LINE#*=}
eval "${PVAR//-/_}=$PVAL" # Store the value in an environment variable
fi
done # End of the dependency processing loop
#
: Make sure that if there were no sequential dependencies of
: one type or another, that we still display an empty row.
#
if (( PC_COUNT == 0 ))
then
RG_PARENT_CHILD_DEP_REPORT="$PC_ROW_TEMPLATE"
RG_PARENT_CHILD_DEP_REPORT=${RG_PARENT_CHILD_DEP_REPORT//\<%rg_parent%\>/--}
RG_PARENT_CHILD_DEP_REPORT=${RG_PARENT_CHILD_DEP_REPORT//\<%rg_children%\>/--}
fi
if (( START_AFTER_COUNT == 0 ))
then
RG_START_AFTER_DEP_REPORT="$START_AFTER_ROW_TEMPLATE"
RG_START_AFTER_DEP_REPORT=${RG_START_AFTER_DEP_REPORT//\<%rg_start_after_source%\>/--}
RG_START_AFTER_DEP_REPORT=${RG_START_AFTER_DEP_REPORT//\<%rg_start_after_target%\>/--}
fi
if (( STOP_AFTER_COUNT == 0 ))
then
RG_STOP_AFTER_DEP_REPORT="$STOP_AFTER_ROW_TEMPLATE"
RG_STOP_AFTER_DEP_REPORT=${RG_STOP_AFTER_DEP_REPORT//\<%rg_stop_after_source%\>/--}
RG_STOP_AFTER_DEP_REPORT=${RG_STOP_AFTER_DEP_REPORT//\<%rg_stop_after_target%\>/--}
fi
#
: Make sure that if any location dependencies were not used
: that we still display the "--" indicator.
#
if (( ! SAME_NODE_FOUND ))
then
RG_SAME_NODE_DEP_REPORT="$RG_SAME_NODE_DEP_REPORT$SAME_NODE_ROW_TEMPLATE$NL"
RG_SAME_NODE_DEP_REPORT=${RG_SAME_NODE_DEP_REPORT//\<%rg_same_node%\>/--}
fi
if (( ! SAME_SITE_FOUND ))
then
RG_SAME_SITE_DEP_REPORT="$RG_SAME_SITE_DEP_REPORT$SAME_SITE_ROW_TEMPLATE$NL"
RG_SAME_SITE_DEP_REPORT=${RG_SAME_SITE_DEP_REPORT//\<%rg_same_site%\>/--}
fi
if (( ! DIFF_NODES_FOUND ))
then
RG_DIFFERENT_NODE_DEP_REPORT="$RG_DIFFERENT_NODE_DEP_REPORT$DIFFERENT_NODE_ROW_TEMPLATE$NL"
RG_DIFFERENT_NODE_DEP_REPORT=${RG_DIFFERENT_NODE_DEP_REPORT//\<%rg_different_node%\>/--}
fi
#
: Make sure that if any acquisition/release policies are
: not used that we still display the "--" indicator.
#
(( ! ACQPAR )) && PSEQ_TEMPLATE=${PSEQ_TEMPLATE//\<%rgs_acq_par%\>/--}
(( ! ACQSER )) && PSEQ_TEMPLATE=${PSEQ_TEMPLATE//\<%rgs_acq_ser%\>/--}
(( ! RELPAR )) && PSEQ_TEMPLATE=${PSEQ_TEMPLATE//\<%rgs_rel_par%\>/--}
(( ! RELSER )) && PSEQ_TEMPLATE=${PSEQ_TEMPLATE//\<%rgs_rel_ser%\>/--}
print -- "$RG_PARENT_CHILD_DEP_REPORT" >$DEP_PC_FILE
print -- "$RG_START_AFTER_DEP_REPORT" >$DEP_STARTA_FILE
print -- "$RG_STOP_AFTER_DEP_REPORT" >$DEP_STOPA_FILE
print -- "$RG_SAME_NODE_DEP_REPORT" >$DEP_SNODE_FILE
print -- "$RG_DIFFERENT_NODE_DEP_REPORT" >$DEP_DNODE_FILE
print -- "$RG_SAME_SITE_DEP_REPORT" >$DEP_SSITE_FILE
print -- "$PSEQ_TEMPLATE" >$RG_PROCSEQ_FILE
)&
CHCR_CHILDREN="${CHCR_CHILDREN:+$CHCR_CHILDREN }$!"
(
#===============================================
: Construct the NETWORKS section of the report
#===============================================
#===============================================
: Load the data that is needed for this report
: from the clmgr verbose cluster output
#===============================================
typeset NETWORK_DATA="$(sed -n '//,/<\/NETWORKS>/p' $CDATA_FILE | grep -v 'NETWORKS>$')"
#
: Extract the template and separator from the overall report
#
typeset LABEL="network_card_template"
typeset NETWORK_TEMPLATE=$(sed -n "/<%${LABEL}_start%>/,/<%${LABEL}_end%>/p" $TEMPLATE_FILE | grep -v "<%$LABEL")
#
: Extract the row separator from the template
#
# The SIZE value, below, must be set to the number of lines of HTML
# used for it in the (cl|ss)_report_template.htm files. For this
# one, search for the "hr" line near the "network_card_template_end"
# tag. The size should include the HTML code, plus any associated
# comments.
#
integer NETWORK_SEPARATOR_SIZE=8
typeset NETWORK_SEPARATOR=$(print -- "$NETWORK_TEMPLATE" | tail -$NETWORK_SEPARATOR_SIZE)
NETWORK_SEPARATOR=${NETWORK_SEPARATOR//\<\!--*--\>/} # Remove all comments
NETWORK_SEPARATOR=${NETWORK_SEPARATOR##*( )+(\n)}
NETWORK_SEPARATOR=${NETWORK_SEPARATOR%%*( )+(\n)}
#
: Remove the separator, then the template, from the overall report
#
integer LINES=$(print -- "$NETWORK_TEMPLATE" | wc -l)
NETWORK_TEMPLATE=$(print -- "$NETWORK_TEMPLATE" | head -n $(( LINES -= NETWORK_SEPARATOR_SIZE )))
NETWORK_TEMPLATE="${NETWORK_TEMPLATE%%+([[:space:]])}"
typeset STRINGS=$(dspmsg -s 47 cluster.cat 36 "Anti-Collocation,Anti-Collocation with Source,Collocation,Collocation with Source,Collocation with Persistent Label,Anti-Collocation with Persistent Label,Anti-Collocation with Persistent Label and Source")
typeset NETWORK_REPORT=""
typeset -i NETWORK_COUNT=0
print -- "$NETWORK_DATA\n" | grep -p NAME= |\
while read LINE
do
#
: A blank line separator indicates the start of a new block of node data
#
if [[ $LINE == *([[:space:]]) ]]
then
(( NETWORK_COUNT++ ))
(( NETWORK_COUNT > 1 )) && NETWORK_REPORT="$NETWORK_REPORT$NL$NL$NETWORK_SEPARATOR$NL"
case $RESOURCE_DIST_PREF in
AC) RESOURCE_DIST_PREF=$(print -- "$STRINGS" | cut -f1 -d,) ;;
ACS) RESOURCE_DIST_PREF=$(print -- "$STRINGS" | cut -f2 -d,) ;;
C) RESOURCE_DIST_PREF=$(print -- "$STRINGS" | cut -f3 -d,) ;;
CS) RESOURCE_DIST_PREF=$(print -- "$STRINGS" | cut -f4 -d,) ;;
CPL) RESOURCE_DIST_PREF=$(print -- "$STRINGS" | cut -f5 -d,) ;;
ACPL) RESOURCE_DIST_PREF=$(print -- "$STRINGS" | cut -f6 -d,) ;;
ACPLS) RESOURCE_DIST_PREF=$(print -- "$STRINGS" | cut -f7 -d,) ;;
esac
CARD="$NETWORK_TEMPLATE"
CARD=${CARD//\<%name%\>/$NAME}
CARD=${CARD//\<%type%\>/${TYPE:--}}
CARD=${CARD//\<%netmask%\>/${NETMASK:--}}
CARD=${CARD//\<%rdpref%\>/${RESOURCE_DIST_PREF:--}}
if [[ $PUBLIC == @(pu|PU|Pu)* ]]
then
CARD=${CARD//\<%visibility%\>/$OPEN_LOCK" "${PUBLIC:--}}
else
CARD=${CARD//\<%visibility%\>/$CLOSED_LOCK" "${PUBLIC:--}}
fi
NETWORK_REPORT="$NETWORK_REPORT$NL$CARD"
#
: Free the variables that were set for network "$NAME".
: This releases some memory, but more importantly, it ensures
: that data from one object does not get accidentally shown
: with another one.
#
unset NAME GID NETMASK NET_FAMILY NETWORK_ID ALIAS \
RESOURCE_DIST_PREF POLLINTERVAL TYPE GLOBALNAME \
ALIAS_HB_NETMASK ALIAS_HB_ADDR MONITOR_METHOD PUBLIC \
GLOBALNAME
elif [[ $LINE == *=* ]]; then
PVAR=${LINE%%=*}
PVAL=${LINE#*=}
eval "${PVAR//-/_}=$PVAL" # Store the value in an environment variable
fi
done # End of the "NETWORK_DATA" loop
#
: Save the constructed report into a temporary file for later processing
#
print -- "$NETWORK_REPORT" >$NW_FILE
)&
CHCR_CHILDREN="${CHCR_CHILDREN:+$CHCR_CHILDREN }$!"
(
#==================================================
: Construct the SERVICE IPS section of the report
#==================================================
#===============================================
: Load the data that is needed for this report
: from the clmgr verbose cluster output
#===============================================
typeset SIP_DATA="$(sed -n '//,/<\/SERVICE_IPS>/p' $CDATA_FILE | grep -v 'SERVICE_IPS>$')"
#
: Extract the template from the overall report
#
typeset LABEL="service_ip_card_template"
typeset SERVICE_IP_TEMPLATE=$(sed -n "/<%${LABEL}_start%>/,/<%${LABEL}_end%>/p" $TEMPLATE_FILE | grep -v "<%$LABEL")
#
: Extract the row separator from the template
#
# The SIZE value, below, must be set to the number of lines of HTML
# used for it in the (cl|ss)_report_template.htm files. For this
# one, search for the "hr" line near the "service_ip_card_template_end"
# tag. The size should include the HTML code, plus any associated
# comments.
#
integer SERVICE_IP_SEPARATOR_SIZE=8
typeset SERVICE_IP_SEPARATOR=$(print -- "$SERVICE_IP_TEMPLATE" | tail -$SERVICE_IP_SEPARATOR_SIZE)
SERVICE_IP_SEPARATOR=${SERVICE_IP_SEPARATOR//\<\!--*--\>/} # Remove all comments
SERVICE_IP_SEPARATOR=${SERVICE_IP_SEPARATOR##*( )+(\n)}
SERVICE_IP_SEPARATOR=${SERVICE_IP_SEPARATOR%%*( )+(\n)}
#
: Remove the separator, then the template, from the overall report
#
integer LINES=$(print -- "$SERVICE_IP_TEMPLATE" | wc -l)
SERVICE_IP_TEMPLATE=$(print -- "$SERVICE_IP_TEMPLATE" | head -n $(( LINES -= SERVICE_IP_SEPARATOR_SIZE )))
SERVICE_IP_TEMPLATE="${SERVICE_IP_TEMPLATE%%+([[:space:]])}"
typeset SERVICE_IP_REPORT=""
typeset -i SERVICE_IP_COUNT=0
print -- "$SIP_DATA\n" | grep -p NAME= |\
while read LINE
do
#
: A blank line separator indicates the start of a new block of node data
#
if [[ $LINE == *([[:space:]]) ]]
then
(( SERVICE_IP_COUNT++ ))
(( SERVICE_IP_COUNT > 1 )) && SERVICE_IP_REPORT="$SERVICE_IP_REPORT$NL$NL$SERVICE_IP_SEPARATOR$NL"
CARD="$SERVICE_IP_TEMPLATE"
CARD=${CARD//\<%name%\>/$NAME}
CARD=${CARD//\<%nettype%\>/${NETTYPE:--}}
CARD=${CARD//\<%nwname%\>/${NETWORK:--}}
CARD=${CARD//\<%node%\>/${NODE:--}}
CARD=${CARD//\<%interface%\>/${INTERFACE:--}}
CARD=${CARD//\<%address%\>/${IPADDR:--}}
CARD=${CARD//\<%netmask%\>/${NETMASK:--}}
SERVICE_IP_REPORT="$SERVICE_IP_REPORT$NL$CARD"
#
: Free the variables that were set for service IP "$NAME".
: This releases some memory, but more importantly, it ensures
: that data from one object does not get accidentally shown
: with another one.
#
unset NAME INTERFACE IPADDR NETMASK NETWORK NODE NETTYPE \
TYPE ATTR NETM GLOBALNAME HADDR FONT_APPEARANCE
elif [[ $LINE == *=* ]]; then
PVAR=${LINE%%=*}
PVAL=${LINE#*=}
eval "${PVAR//-/_}=$PVAL" # Store the value in an environment variable
fi
done # End of the "SERVICE_IP_DATA" loop
#
: Save the constructed report into a temporary file for later processing
#
print -- "$SERVICE_IP_REPORT" >$SIP_FILE
)&
CHCR_CHILDREN="${CHCR_CHILDREN:+$CHCR_CHILDREN }$!"
(
#==================================================
: Construct the INTERFACES section of the report
#==================================================
#===============================================
: Load the data that is needed for this report
: from the clmgr verbose cluster output
#===============================================
typeset INTERFACE_DATA="$(sed -n '//,/<\/INTERFACES>/p' $CDATA_FILE | grep -v 'INTERFACES>$')"
#
: Extract the template from the overall report
#
typeset LABEL="interface_card_template"
typeset INTERFACE_TEMPLATE=$(sed -n "/<%${LABEL}_start%>/,/<%${LABEL}_end%>/p" $TEMPLATE_FILE | grep -v "<%$LABEL")
#
: Extract the row separator from the template
#
# The SIZE value, below, must be set to the number of lines of HTML
# used for it in the (cl|ss)_report_template.htm files. For this
# one, search for the "hr" line near the "interface_card_template_end"
# tag. The size should include the HTML code, plus any associated
# comments.
#
integer INTERFACE_SEPARATOR_SIZE=8
typeset INTERFACE_SEPARATOR=$(print -- "$INTERFACE_TEMPLATE" | tail -$INTERFACE_SEPARATOR_SIZE)
INTERFACE_SEPARATOR=${INTERFACE_SEPARATOR//\<\!--*--\>/} # Remove all comments
INTERFACE_SEPARATOR=${INTERFACE_SEPARATOR##*( )+(\n)}
INTERFACE_SEPARATOR=${INTERFACE_SEPARATOR%%*( )+(\n)}
#
: Remove the separator, then the template, from the overall report
#
integer LINES=$(print -- "$INTERFACE_TEMPLATE" | wc -l)
INTERFACE_TEMPLATE=$(print -- "$INTERFACE_TEMPLATE" | head -n $(( LINES -= INTERFACE_SEPARATOR_SIZE )))
INTERFACE_TEMPLATE="${INTERFACE_TEMPLATE%%+([[:space:]])}"
typeset INTERFACE_REPORT=""
typeset -i INTERFACE_COUNT=0
print -- "$INTERFACE_DATA\n" | grep -p NAME= |\
while read LINE
do
#
: A blank line separator indicates the start of a new block of node data
#
if [[ $LINE == *([[:space:]]) ]]
then
[[ $TYPE == "service" ]] && continue # These are displayed in a separate section
(( INTERFACE_COUNT++ ))
(( INTERFACE_COUNT > 1 )) && INTERFACE_REPORT="$INTERFACE_REPORT$NL$NL$INTERFACE_SEPARATOR$NL"
CARD="$INTERFACE_TEMPLATE"
CARD=${CARD//\<%name%\>/$NAME}
CARD=${CARD//\<%nettype%\>/${NETTYPE:--}}
CARD=${CARD//\<%type%\>/${TYPE:--}}
CARD=${CARD//\<%nwname%\>/${NETWORK:--}}
CARD=${CARD//\<%node%\>/${NODE:--}}
CARD=${CARD//\<%interface%\>/${INTERFACE:--}}
CARD=${CARD//\<%address%\>/${IPADDR:--}}
CARD=${CARD//\<%netmask%\>/${NETMASK:--}}
if [[ $STATE == @(up|Up|UP) ]]
then
CARD=${CARD//\<%state%\>/$UP_ARROW_SVG" "${STATE:--}}
else
CARD=${CARD//\<%state%\>/$DOWN_ARROW_SVG" "${STATE:--}}
fi
INTERFACE_REPORT="$INTERFACE_REPORT$NL$CARD"
#
: Free the variables that were set for interface "$NAME".
: This releases some memory, but more importantly, it ensures
: that data from one object does not get accidentally shown
: with another one.
#
unset NAME INTERFACE IPADDR NETMASK NETWORK NODE NETTYPE \
TYPE ATTR NETM GLOBALNAME HADDR FONT_APPEARANCE STATE \
PVAR PVAL
elif [[ $LINE == *=* ]]; then
PVAR=${LINE%%=*}
PVAL=${LINE#*=}
eval "${PVAR//-/_}=$PVAL" # Store the value in an environment variable
fi
done # End of the "INTERFACE_DATA" loop
#
: Save the constructed report into a temporary file for later processing
#
print -- "$INTERFACE_REPORT" >$IF_FILE
)&
CHCR_CHILDREN="${CHCR_CHILDREN:+$CHCR_CHILDREN }$!"
(
#====================================================
: Construct the VOLUME GROUPS section of the report
#====================================================
#===============================================
: Load the data that is needed for this report
: from the clmgr verbose cluster output
#===============================================
typeset VG_DATA="$(sed -n '//,/<\/VOLUME_GROUPS>/p' $CDATA_FILE | grep -v 'VOLUME_GROUPS>$')"
#
: Extract the template from the overall report
#
typeset LABEL="vg_card_template"
typeset VG_TEMPLATE=$(sed -n "/<%${LABEL}_start%>/,/<%${LABEL}_end%>/p" $TEMPLATE_FILE | grep -v "<%$LABEL")
#
: Extract the row separator from the template
#
# The SIZE value, below, must be set to the number of lines of HTML
# used for it in the (cl|ss)_report_template.htm files. For this
# one, search for the "hr" line near the "vg_card_template_end"
# tag. The size should include the HTML code, plus any associated
# comments.
#
integer VG_SEPARATOR_SIZE=8
typeset VG_SEPARATOR=$(print -- "$VG_TEMPLATE" | tail -$VG_SEPARATOR_SIZE)
VG_SEPARATOR=${VG_SEPARATOR//\<\!--*--\>/} # Remove all comments
VG_SEPARATOR=${VG_SEPARATOR##*( )+(\n)}
VG_SEPARATOR=${VG_SEPARATOR%%*( )+(\n)}
#
: Remove the separator, then the template, from the overall report
#
integer LINES=$(print -- "$VG_TEMPLATE" | wc -l)
VG_TEMPLATE=$(print -- "$VG_TEMPLATE" | head -n $(( LINES -= VG_SEPARATOR_SIZE )))
VG_TEMPLATE="${VG_TEMPLATE%%+([[:space:]])}"
typeset VG_REPORT=""
typeset -i VG_COUNT=0
print -- "$VG_DATA\n" | grep -p NAME= |\
while read LINE
do
#
: A blank line separator indicates the start of a new block of node data
#
if [[ $LINE == *([[:space:]]) ]]
then
(( VG_COUNT++ ))
(( VG_COUNT > 1 )) && VG_REPORT="$VG_REPORT$NL$NL$VG_SEPARATOR$NL"
CARD="$VG_TEMPLATE"
CARD=${CARD//\<%name%\>/$NAME}
CARD=${CARD//\<%type%\>/${TYPE:--}}
CARD=${CARD//\<%rg%\>/${RESOURCE_GROUP:--}}
CARD=${CARD//\<%major%\>/${MAJOR_NUMBER:--}}
CARD=${CARD//\<%mpool_strictness%\>/${STRICT_MIRROR_POOLS:--}}
LINKS=""
for OBJECT in ${NODES//,/ }
do
LINKS="${LINKS:+$LINKS,}$OBJECT"
done
CARD=${CARD//\<%nodes%\>/${LINKS:--}}
LINKS=""
for OBJECT in ${LOGICAL_VOLUMES//,/ }
do
LINKS="${LINKS:+$LINKS,}$OBJECT"
done
CARD=${CARD//\<%lvs%\>/${LINKS:--}}
LINKS=""
for OBJECT in ${MIRROR_POOLS//,/ }
do
LINKS="${LINKS:+$LINKS,}$OBJECT"
done
CARD=${CARD//\<%mpools%\>/${LINKS:--}}
typeset FMTD_PVS="" LINKS=""
for DATA in ${PHYSICAL_VOLUMES//,/ }; do
print -- "$DATA" | IFS=@ read name node pvid rest
LINKS="${LINKS:+$LINKS }$name@$node ($pvid)"
done
CARD=${CARD//\<%pvs%\>/${LINKS:--}}
unset DATA name node pvid rest
VG_REPORT="$VG_REPORT$NL$CARD"
#
: Free the variables that were set for volume group "$NAME".
: This releases some memory, but more importantly, it ensures
: that data from one object does not get accidentally shown
: with another one.
#
unset NAME TYPE NODES LOGICAL_VOLUMES PHYSICAL_VOLUMES \
MIRROR_POOLS STRICT_MIRROR_POOLS RESOURCE_GROUP \
AUTO_ACTIVATE QUORUM CONCURRENT_ACCESS CRITICAL \
FAILUREACTION NOTIFYMETHOD MIGRATE_FAILED_DISKS \
SYNCHRONIZE LOGICAL_TRACK_GROUP_SIZE \
MAX_PHYSICAL_PARTITIONS PPART_SIZE MAX_LOGICAL_VOLUMES \
MAJOR_NUMBER IDENTIFIER TIMESTAMP
elif [[ $LINE == *=* ]]; then
PVAR=${LINE%%=*}
PVAL=${LINE#*=}
eval "${PVAR//-/_}=$PVAL" # Store the value in an environment variable
fi
done # End of the "VG_DATA" loop
#
: Save the constructed report into a temporary file for later processing
#
print -- "$VG_REPORT" >$VG_FILE
)&
CHCR_CHILDREN="${CHCR_CHILDREN:+$CHCR_CHILDREN }$!"
if [[ -z $CL_SNAPSHOT ]]
then
(
#======================================================
: Construct the LOGICAL VOLUMES section of the report
#======================================================
#===============================================
: Load the data that is needed for this report
: from the clmgr verbose cluster output
#===============================================
typeset LV_DATA="$(sed -n '//,/<\/LOGICAL_VOLUMES>/p' $CDATA_FILE | grep -v 'LOGICAL_VOLUMES>$')"
#
: Extract the template from the overall report
#
typeset LABEL="lv_card_template"
typeset LV_TEMPLATE=$(sed -n "/<%${LABEL}_start%>/,/<%${LABEL}_end%>/p" $TEMPLATE_FILE | grep -v "<%$LABEL")
#
: Extract the row separator from the template
#
# The SIZE value, below, must be set to the number of lines of HTML
# used for it in the (cl|ss)_report_template.htm files. For this
# one, search for the "hr" line near the "lv_card_template_end"
# tag. The size should include the HTML code, plus any associated
# comments.
#
integer LV_SEPARATOR_SIZE=8
typeset LV_SEPARATOR=$(print -- "$LV_TEMPLATE" | tail -$LV_SEPARATOR_SIZE)
LV_SEPARATOR=${LV_SEPARATOR//\<\!--*--\>/} # Remove all comments
LV_SEPARATOR=${LV_SEPARATOR##*( )+(\n)}
LV_SEPARATOR=${LV_SEPARATOR%%*( )+(\n)}
#
: Remove the separator, then the template, from the overall report
#
integer LINES=$(print -- "$LV_TEMPLATE" | wc -l)
LV_TEMPLATE=$(print -- "$LV_TEMPLATE" | head -n $(( LINES -= LV_SEPARATOR_SIZE )))
LV_TEMPLATE="${LV_TEMPLATE%%+([[:space:]])}"
typeset LV_REPORT=""
typeset -i LV_COUNT=0
print -- "$LV_DATA\n" | grep -p NAME= |\
while read LINE
do
#
: A blank line separator indicates the start of a new block of node data
#
if [[ $LINE == *([[:space:]]) ]]
then
typeset FMTD_PVS=""
for DATA in ${PHYSICAL_VOLUMES//,/ }; do
print -- "$DATA" | IFS=@ read name node pvid rest
[[ -n $FMTD_PVS ]] && FMTD_PVS="$FMTD_PVS "
FMTD_PVS="$FMTD_PVS$name@$node ($pvid)"
done
unset DATA name node pvid rest
(( LV_COUNT++ ))
(( LV_COUNT > 1 )) && LV_REPORT="$LV_REPORT$NL$NL$LV_SEPARATOR$NL"
CARD="$LV_TEMPLATE"
CARD=${CARD//\<%name%\>/$NAME}
CARD=${CARD//\<%type%\>/${TYPE:--}}
CARD=${CARD//\<%vg%\>/${VOLUME_GROUP:--}}
CARD=${CARD//\<%rg%\>/${RESOURCE_GROUP:--}}
CARD=${CARD//\<%pparts%\>/${PPS:--}}
CARD=${CARD//\<%ppart_size%\>/${PP_SIZE:--}}
CARD=${CARD//\<%lparts%\>/${LPS:--}}
CARD=${CARD//\<%lpart_copies%\>/${COPIES:--}}
typeset LINKS=""
for OBJECT in ${NODES//,/ }
do
LINKS="${LINKS:+$LINKS,}$OBJECT"
done
CARD=${CARD//\<%nodes%\>/${LINKS:--}}
LINKS=""
for OBJECT in ${MOUNT_POINT//,/ }
do
if [[ $OBJECT != /* ]]
then
LINKS="${LINKS:+$LINKS,}$OBJECT"
else
LINKS="${LINKS:+$LINKS,}$OBJECT"
fi
done
CARD=${CARD//\<%mount_point%\>/${LINKS:--}}
LV_REPORT="$LV_REPORT$NL$CARD"
#
: Free the variables that were set for logical volume "$NAME".
: This releases some memory, but more importantly, it ensures
: that data from one object does not get accidentally shown
: with another one.
#
unset NAME TYPE NODES VOLUME_GROUP RESOURCE_GROUP \
MOUNT_POINT LABEL PERMISSION VG_STATE LV_STATE MAX_LPS \
COPIES LPS PPS PP_SIZE STALE_PPS WRITE_VERIFY \
MIRROR_WRITE_CONSISTENCY INTERPOLICY INTRAPOLICY \
RELOCATABLE UPPER_BOUND SCHED_POLICY BB_POLICY \
EACH_LP_COPY_ON_A_SEPARATE_PV SERIALIZE_IO IDENTIFIER
elif [[ $LINE == *=* ]]; then
PVAR=${LINE%%=*}
PVAL=${LINE#*=}
eval "${PVAR//-/_}=$PVAL" # Store the value in an environment variable
fi
done # End of the "LV_DATA" loop
#
: Save the constructed report into a temporary file for later processing
#
print -- "$LV_REPORT" >$LV_FILE
)&
CHCR_CHILDREN="${CHCR_CHILDREN:+$CHCR_CHILDREN }$!"
(
#===================================================
: Construct the MIRROR POOLS section of the report
#===================================================
#===============================================
: Load the data that is needed for this report
: from the clmgr verbose cluster output
#===============================================
typeset MP_DATA="$(sed -n '//,/<\/MIRROR_POOLS>/p' $CDATA_FILE | grep -v 'MIRROR_POOLS>$')"
#
: Extract the template from the overall report
#
typeset LABEL="mp_card_template"
typeset MP_TEMPLATE=$(sed -n "/<%${LABEL}_start%>/,/<%${LABEL}_end%>/p" $TEMPLATE_FILE | grep -v "<%$LABEL")
#
: Extract the row separator from the template
#
# The SIZE value, below, must be set to the number of lines of HTML
# used for it in the (cl|ss)_report_template.htm files. For this
# one, search for the "hr" line near the "mp_card_template_end"
# tag. The size should include the HTML code, plus any associated
# comments.
#
integer MP_SEPARATOR_SIZE=8
typeset MP_SEPARATOR=$(print -- "$MP_TEMPLATE" | tail -$MP_SEPARATOR_SIZE)
MP_SEPARATOR=${MP_SEPARATOR//\<\!--*--\>/} # Remove all comments
MP_SEPARATOR=${MP_SEPARATOR##*( )+(\n)}
MP_SEPARATOR=${MP_SEPARATOR%%*( )+(\n)}
#
: Remove the separator, then the template, from the overall report
#
integer LINES=$(print -- "$MP_TEMPLATE" | wc -l)
MP_TEMPLATE=$(print -- "$MP_TEMPLATE" | head -n $(( LINES -= MP_SEPARATOR_SIZE )))
MP_TEMPLATE="${MP_TEMPLATE%%+([[:space:]])}"
typeset MP_REPORT=""
typeset -i MP_COUNT=0
print -- "$MP_DATA\n" | grep -p NAME= |\
while read LINE
do
#
: A blank line separator indicates the start of a new block of node data
#
if [[ $LINE == *([[:space:]]) ]]
then
(( MP_COUNT++ ))
(( MP_COUNT > 1 )) && MP_REPORT="$MP_REPORT$NL$NL$MP_SEPARATOR$NL"
CARD="$MP_TEMPLATE"
CARD=${CARD//\<%name%\>/$NAME}
CARD=${CARD//\<%vg%\>/${VOLUME_GROUP:--}}
CARD=${CARD//\<%strict%\>/${SUPER_STRICT:--}}
CARD=${CARD//\<%mode%\>/${MODE:--}}
CARD=${CARD//\<%async_clv%\>/${ASYNC_CACHE_LV:--}}
CARD=${CARD//\<%async_chwm%\>/${ASYNC_CACHE_HW_MARK:--}}
typeset LINKS=""
for OBJECT in ${PHYSICAL_VOLUMES//,/ }
do
LINKS="${LINKS:+$LINKS,}$OBJECT"
done
CARD=${CARD//\<%pvs%\>/${LINKS:--}}
MP_REPORT="$MP_REPORT$NL$CARD"
#
: Free the variables that were set for mirror pool "$NAME".
: This releases some memory, but more importantly, it ensures
: that data from one object does not get accidentally shown
: with another one.
#
unset NAME VOLUME_GROUP PHYSICAL_VOLUMES SUPER_STRICT MODE \
ASYNC_CACHE_LV ASYNC_CACHE_HW_MARK
elif [[ $LINE == *=* ]]; then
PVAR=${LINE%%=*}
PVAL=${LINE#*=}
eval "${PVAR//-/_}=$PVAL" # Store the value in an environment variable
fi
done # End of the "MP_DATA" loop
#
: Save the constructed report into a temporary file for later processing
#
print -- "$MP_REPORT" >$MP_FILE
)&
CHCR_CHILDREN="${CHCR_CHILDREN:+$CHCR_CHILDREN }$!"
fi
(
#===================================================
: Construct the FILE SYSTEMS section of the report
#===================================================
#===============================================
: Load the data that is needed for this report
: from the clmgr verbose cluster output
#===============================================
typeset FS_DATA="$(sed -n '//,/<\/FILE_SYSTEMS>/p' $CDATA_FILE | grep -v 'FILE_SYSTEMS>$')"
#
: Extract the template from the overall report
#
typeset LABEL="fs_card_template"
typeset FS_TEMPLATE=$(sed -n "/<%${LABEL}_start%>/,/<%${LABEL}_end%>/p" $TEMPLATE_FILE | grep -v "<%$LABEL")
#
: Extract the row separator from the template
#
# The SIZE value, below, must be set to the number of lines of HTML
# used for it in the (cl|ss)_report_template.htm files. For this
# one, search for the "hr" line near the "fs_card_template_end"
# tag. The size should include the HTML code, plus any associated
# comments.
#
integer FS_SEPARATOR_SIZE=8
typeset FS_SEPARATOR=$(print -- "$FS_TEMPLATE" | tail -$FS_SEPARATOR_SIZE)
FS_SEPARATOR=${FS_SEPARATOR//\<\!--*--\>/} # Remove all comments
FS_SEPARATOR=${FS_SEPARATOR##*( )+(\n)}
FS_SEPARATOR=${FS_SEPARATOR%%*( )+(\n)}
#
: Remove the separator, then the template, from the overall report
#
integer LINES=$(print -- "$FS_TEMPLATE" | wc -l)
FS_TEMPLATE=$(print -- "$FS_TEMPLATE" | head -n $(( LINES -= FS_SEPARATOR_SIZE )))
FS_TEMPLATE="${FS_TEMPLATE%%+([[:space:]])}"
typeset FS_REPORT=""
typeset -i FS_COUNT=0
print -- "$FS_DATA\n" | grep -p NAME= |\
while read LINE
do
#
: A blank line separator indicates the start of a new block of node data
#
if [[ $LINE == *([[:space:]]) ]]
then
(( FS_COUNT++ ))
(( FS_COUNT > 1 )) && FS_REPORT="$FS_REPORT$NL$NL$FS_SEPARATOR$NL"
CARD="$FS_TEMPLATE"
if [[ $NAME == "ALL" ]]
then
NAME="<ALL>"
fi
CARD=${CARD//\<%name%\>/$NAME}
CARD=${CARD//\<%type%\>/${TYPE/$VFS:--}}
CARD=${CARD//\<%vg%\>/${VOLUME_GROUP:--}}
CARD=${CARD//\<%rg%\>/${RESOURCE_GROUP:--}}
CARD=${CARD//\<%size%\>/${SIZE:--}}
CARD=${CARD//\<%quota%\>/${ENABLE_QUOTA_MGMT:--}}
CARD=${CARD//\<%efs%\>/${EFS:--}}
CARD=${CARD//\<%mountguard%\>/${MOUNTGUARD:--}}
typeset LINKS=""
for OBJECT in ${NODES//,/ }
do
LINKS="${LINKS:+$LINKS,}$OBJECT"
done
CARD=${CARD//\<%nodes%\>/${LINKS:--}}
FS_REPORT="$FS_REPORT$NL$CARD"
#
: Free the variables that were set for file system "$NAME".
: This releases some memory, but more importantly, it ensures
: that data from one object does not get accidentally shown
: with another one.
#
unset NAME TYPE VFS NODES VOLUME_GROUP RESOURCE_GROUP DEVICE \
SIZE OPTIONS AUTOMOUNT BLOCK_SIZE LV_FOR_LOG \
INLINE_LOG_SIZE EXT_ATTR_FORMAT ENABLE_QUOTA_MGMT \
EFS MOUNTGUARD
elif [[ $LINE == *=* ]]; then
PVAR=${LINE%%=*}
PVAL=${LINE#*=}
eval "${PVAR//-/_}=$PVAL" # Store the value in an environment variable
fi
done # End of the "FS_DATA" loop
#
: Save the constructed report into a temporary file for later processing
#
print -- "$FS_REPORT" >$FS_FILE
)&
CHCR_CHILDREN="${CHCR_CHILDREN:+$CHCR_CHILDREN }$!"
if [[ -z $CL_SNAPSHOT ]]
then
(
#=======================================================
: Construct the PHYSICAL VOLUMES section of the report
#=======================================================
#===============================================
: Load the data that is needed for this report
: from the clmgr verbose cluster output
#===============================================
typeset PV_DATA="$(sed -n '//,/<\/PHYSICAL_VOLUMES>/p' $CDATA_FILE | grep -v 'PHYSICAL_VOLUMES>$')"
#
: Extract the template from the overall report
#
typeset LABEL="pv_card_template"
typeset PV_TEMPLATE=$(sed -n "/<%${LABEL}_start%>/,/<%${LABEL}_end%>/p" $TEMPLATE_FILE | grep -v "<%$LABEL")
#
: Extract the row separator from the template
#
# The SIZE value, below, must be set to the number of lines of HTML
# used for it in the (cl|ss)_report_template.htm files. For this
# one, search for the "hr" line near the "pv_card_template_end"
# tag. The size should include the HTML code, plus any associated
# comments.
#
integer PV_SEPARATOR_SIZE=8
typeset PV_SEPARATOR=$(print -- "$PV_TEMPLATE" | tail -$PV_SEPARATOR_SIZE)
PV_SEPARATOR=${PV_SEPARATOR//\<\!--*--\>/} # Remove all comments
PV_SEPARATOR=${PV_SEPARATOR##*( )+(\n)}
PV_SEPARATOR=${PV_SEPARATOR%%*( )+(\n)}
#
: Remove the separator, then the template, from the overall report
#
integer LINES=$(print -- "$PV_TEMPLATE" | wc -l)
PV_TEMPLATE=$(print -- "$PV_TEMPLATE" | head -n $(( LINES -= PV_SEPARATOR_SIZE )))
PV_TEMPLATE="${PV_TEMPLATE%%+([[:space:]])}"
typeset PV_REPORT=""
typeset -i PV_COUNT=0
print -- "$PV_DATA\n" | grep -p NAME= |\
while read LINE
do
#
: A blank line separator indicates the start of a new block of node data
#
if [[ $LINE == *([[:space:]]) ]]
then
(( PV_COUNT++ ))
(( PV_COUNT > 1 )) && PV_REPORT="$PV_REPORT$NL$NL$PV_SEPARATOR$NL"
CARD="$PV_TEMPLATE"
CARD=${CARD//\<%name%\>/$NAME}
CARD=${CARD//\<%pvid%\>/${PVID:--}}
CARD=${CARD//\<%vg%\>/${VOLUME_GROUP:--}}
CARD=${CARD//\<%type%\>/${TYPE:--}}
CARD=${CARD//\<%size%\>/${SIZE:--}}
CARD=${CARD//\<%avail%\>/${AVAILABLE:--}}
PV_REPORT="$PV_REPORT$NL$CARD"
#
: Free the variables that were set for physical volume "$NAME".
: This releases some memory, but more importantly, it ensures
: that data from one object does not get accidentally shown
: with another one.
#
unset NAME PVID UUID VOLUME_GROUP TYPE DESCRIPTION SIZE \
AVAILABLE CONCURRENT ENHANCED_CONCURRENT_MODE STATUS
elif [[ $LINE == *=* ]]; then
PVAR=${LINE%%=*}
PVAL=${LINE#*=}
eval "${PVAR//-/_}=$PVAL" # Store the value in an environment variable
fi
done # End of the "PV_DATA" loop
#
: Save the constructed report into a temporary file for later processing
#
print -- "$PV_REPORT" >$PV_FILE
)&
CHCR_CHILDREN="${CHCR_CHILDREN:+$CHCR_CHILDREN }$!"
fi
(
#===================================================
: Construct the REPOSITORIES section of the report
#===================================================
#===============================================
: Load the data that is needed for this report
: from the clmgr verbose cluster output
#===============================================
typeset REPOSITORY_DATA="$(sed -n '/REPOSITORIES>/,/<\/REPOSITORIES>/p' $CDATA_FILE | grep -v 'REPOSITORIES>$')"
#
: Extract the template from the overall report
#
typeset LABEL="repository_card_template"
typeset REPOSITORY_TEMPLATE=$(sed -n "/<%${LABEL}_start%>/,/<%${LABEL}_end%>/p" $TEMPLATE_FILE | grep -v "<%$LABEL")
#
: Extract the row separator from the template
#
# The SIZE value, below, must be set to the number of lines of HTML
# used for it in the (cl|ss)_report_template.htm files. For this
# one, search for the "hr" line near the "repository_card_template_end"
# tag. The size should include the HTML code, plus any associated
# comments.
#
integer REPOSITORY_SEPARATOR_SIZE=8
typeset REPOSITORY_SEPARATOR=$(print -- "$REPOSITORY_TEMPLATE" | tail -$REPOSITORY_SEPARATOR_SIZE)
REPOSITORY_SEPARATOR=${REPOSITORY_SEPARATOR//\<\!--*--\>/} # Remove all comments
REPOSITORY_SEPARATOR=${REPOSITORY_SEPARATOR##*( )+(\n)}
REPOSITORY_SEPARATOR=${REPOSITORY_SEPARATOR%%*( )+(\n)}
#
: Remove the separator, then the template, from the overall report
#
integer LINES=$(print -- "$REPOSITORY_TEMPLATE" | wc -l)
REPOSITORY_TEMPLATE=$(print -- "$REPOSITORY_TEMPLATE" | head -n $(( LINES -= REPOSITORY_SEPARATOR_SIZE )))
REPOSITORY_TEMPLATE="${REPOSITORY_TEMPLATE%%+([[:space:]])}"
cl_batch_dspmsg -e -s $CLMGR_RPT_SET $CLMGR_MSGS \
407:no "No (active)" \
408:yes "Yes" |\
while read LINE; do
TAG=${LINE%%=*}
TAG=${TAG#typeset }
TAG=${TAG#_}
LABEL=${LINE#*=}
LABEL=${LABEL#\"}
LABEL=${LABEL%\"}
LABEL="${LABEL%:}"
eval "$TAG=\"$LABEL\""
done
typeset REPOSITORY_REPORT=""
typeset -i REPOSITORY_COUNT=0
print -- "$REPOSITORY_DATA\n" | grep -p NAME= |\
while read LINE
do
#
: A blank line separator indicates the start of a new block of node data
#
if [[ $LINE == *([[:space:]]) ]]
then
(( REPOSITORY_COUNT++ ))
(( REPOSITORY_COUNT > 1 )) && REPOSITORY_REPORT="$REPOSITORY_REPORT$NL$NL$REPOSITORY_SEPARATOR$NL"
CARD="$REPOSITORY_TEMPLATE"
CARD=${CARD//\<%name%\>/$NAME}
CARD=${CARD//\<%pvid%\>/${PVID:--}}
CARD=${CARD//\<%vg%\>/${VOLUME_GROUP:--}}
CARD=${CARD//\<%type%\>/${TYPE:--}}
CARD=${CARD//\<%size%\>/${SIZE:--}}
CARD=${CARD//\<%avail%\>/${AVAILABLE:--}}
CARD=${CARD//\<%status%\>/${STATUS:--}}
if [[ $BACKUP == "0" ]]
then
CARD=${CARD//\<%backup%\>/${no:--}}
else
CARD=${CARD//\<%backup%\>/${yes:--}}
fi
REPOSITORY_REPORT="$REPOSITORY_REPORT$NL$CARD"
#
: Free the variables that were set for repository "$NAME".
: This releases some memory, but more importantly, it ensures
: that data from one object does not get accidentally shown
: with another one.
#
unset NAME PVID UUID VOLUME_GROUP TYPE DESCRIPTION SIZE \
AVAILABLE CONCURRENT ENHANCED_CONCURRENT_MODE STATUS \
BACKUP
elif [[ $LINE == *=* ]]; then
PVAR=${LINE%%=*}
PVAL=${LINE#*=}
eval "${PVAR//-/_}=$PVAL" # Store the value in an environment variable
fi
done # End of the "REPOSITORY_DATA" loop
#
: Save the constructed report into a temporary file for later processing
#
print -- "$REPOSITORY_REPORT" >$REPOS_FILE
)&
CHCR_CHILDREN="${CHCR_CHILDREN:+$CHCR_CHILDREN }$!"
(
#============================================
: Construct the TAPES section of the report
#============================================
#===============================================
: Load the data that is needed for this report
: from the clmgr verbose cluster output
#===============================================
typeset TP_DATA="$(sed -n '//,/<\/TAPES>/p' $CDATA_FILE | grep -v 'TAPES>$')"
#
: Extract the template from the overall report
#
typeset LABEL="tp_card_template"
typeset TP_TEMPLATE=$(sed -n "/<%${LABEL}_start%>/,/<%${LABEL}_end%>/p" $TEMPLATE_FILE | grep -v "<%$LABEL")
#
: Extract the row separator from the template
#
# The SIZE value, below, must be set to the number of lines of HTML
# used for it in the (cl|ss)_report_template.htm files. For this
# one, search for the "hr" line near the "tp_card_template_end"
# tag. The size should include the HTML code, plus any associated
# comments.
#
integer TP_SEPARATOR_SIZE=8
typeset TP_SEPARATOR=$(print -- "$TP_TEMPLATE" | tail -$TP_SEPARATOR_SIZE)
TP_SEPARATOR=${TP_SEPARATOR//\<\!--*--\>/} # Remove all comments
TP_SEPARATOR=${TP_SEPARATOR##*( )+(\n)}
TP_SEPARATOR=${TP_SEPARATOR%%*( )+(\n)}
#
: Remove the separator, then the template, from the overall report
#
integer LINES=$(print -- "$TP_TEMPLATE" | wc -l)
TP_TEMPLATE=$(print -- "$TP_TEMPLATE" | head -n $(( LINES -= TP_SEPARATOR_SIZE )))
TP_TEMPLATE="${TP_TEMPLATE%%+([[:space:]])}"
typeset TP_REPORT=""
typeset -i TP_COUNT=0
print -- "$TP_DATA\n" | grep -p NAME= |\
while read LINE
do
#
: A blank line separator indicates the start of a new block of node data
#
if [[ $LINE == *([[:space:]]) ]]
then
(( TP_COUNT++ ))
(( TP_COUNT > 1 )) && TP_REPORT="$TP_REPORT$NL$NL$TP_SEPARATOR$NL"
CARD="$TP_TEMPLATE"
CARD=${CARD//\<%name%\>/$NAME}
CARD=${CARD//\<%device%\>/${DEVICE:--}}
CARD=${CARD//\<%start_script%\>/${STARTSCRIPT:--}}
CARD=${CARD//\<%start_sync%\>/${START_SYNCHRONOUSLY:--}}
CARD=${CARD//\<%stop_script%\>/${STOPSCRIPT:--}}
CARD=${CARD//\<%stop_sync%\>/${STOP_SYNCHRONOUSLY:--}}
TP_REPORT="$TP_REPORT$NL$CARD"
#
: Free the variables that were set for tape drive "$NAME".
: This releases some memory, but more importantly, it ensures
: that data from one object does not get accidentally shown
: with another one.
#
unset NAME TPID UUID VOLUME_GROUP TYPE DESCRIPTION SIZE \
AVAILABLE CONCURRENT ENHANCED_CONCURRENT_MODE STATUS \
STARTSCRIPT START_SYNCHRONOUSLY STOPSCRIPT DEVICE \
STOP_SYNCHRONOUSLY
elif [[ $LINE == *=* ]]; then
PVAR=${LINE%%=*}
PVAL=${LINE#*=}
eval "${PVAR//-/_}=$PVAL" # Store the value in an environment variable
fi
done # End of the "TP_DATA" loop
#
: Save the constructed report into a temporary file for later processing
#
print -- "$TP_REPORT" >$TP_FILE
)&
CHCR_CHILDREN="${CHCR_CHILDREN:+$CHCR_CHILDREN }$!"
if [[ -z $CL_SNAPSHOT ]]
then
(
#===================================================
: Construct the MIRROR GROUP section of the report
#===================================================
#===============================================
: Load the data that is needed for this report
: from the clmgr verbose cluster output
#===============================================
typeset MG_DATA="$(sed -n '//,/<\/MIRROR_GROUPS>/p' $CDATA_FILE | grep -v 'MIRROR_GROUPS>$')"
#========================================
: Load the mirror group-related strings
#========================================
eval $(cl_batch_dspmsg -e -s $CLMGR_RPT_SET $CLMGR_MSGS \
6:SITE_LBL "Site" \
23:MODE_LBL "Mode" \
37:TYPE_LBL "Type:" \
73:VGS_LBL "Volume Groups:" \
74:RDS_LBL "Raw Disks:" \
99:NODE_LBL "Node" \
106:RG_LBL "Resource Group" \
169:MG_TYPE_LBL "Mirror Group Type" \
170:RECOVERY_LBL "Recovery" \
171:STS_LBL "Storage Systems" \
172:CONSISTENT_LBL "Consistent" \
173:VENDOR_LBL "Vendor Identifier" \
174:HS_ENABLED_LBL "HyperSwap Status" \
175:HS_PRIORITY_LBL "HyperSwap Priority" \
176:HS_UNPL_TO_LBL "HyperSwap Unplanned Timeout" \
177:HS_DISK_LBL "HyperSwap Disk" \
178:NON_HS_DISK_LBL "Non-HyperSwap Disk" \
179:MPAIRS_LBL "Mirror Pairs" \
180:HORCM_INST_LBL "HORCM Instance" \
181:HORCM_TO_LBL "HORCM Timeout" \
182:PE_TO_LBL "Pair Event Timeout")
TYPE_LBL=${TYPE_LBL%:}
#
: Extract the template from the overall report
#
typeset LABEL="mg_card_template"
typeset MG_TEMPLATE=$(sed -n "/<%${LABEL}_start%>/,/<%${LABEL}_end%>/p" $TEMPLATE_FILE | grep -v "<%$LABEL")
#
: Extract the row separator from the template
#
# The SIZE value, below, must be set to the number of lines of HTML
# used for it in the (cl|ss)_report_template.htm files. For this
# one, search for the "hr" line near the "mg_card_template_end"
# tag. The size should include the HTML code, plus any associated
# comments.
#
integer MG_SEPARATOR_SIZE=8
typeset MG_SEPARATOR=$(print -- "$MG_TEMPLATE" | tail -$MG_SEPARATOR_SIZE)
MG_SEPARATOR=${MG_SEPARATOR//\<\!--*--\>/} # Remove all comments
MG_SEPARATOR=${MG_SEPARATOR##*( )+(\n)}
MG_SEPARATOR=${MG_SEPARATOR%%*( )+(\n)}
#
: Remove the separator, then the template, from the overall report
#
integer LINES=$(print -- "$MG_TEMPLATE" | wc -l)
MG_TEMPLATE=$(print -- "$MG_TEMPLATE" | head -n $(( LINES -= MG_SEPARATOR_SIZE )))
MG_TEMPLATE="${MG_TEMPLATE%%+([[:space:]])}"
typeset MG_REPORT=""
typeset -i MG_COUNT=0
print -- "$MG_DATA\n" | grep -p NAME= |\
while read LINE; do
#
: A blank line separator indicates the start of a new block of node data
#
if [[ $LINE == *([[:space:]]) ]]; then
#=============================================
: Add the mirror group "$NAME" to the report
#=============================================
(( MG_COUNT++ ))
(( MG_COUNT > 1 )) && MG_REPORT="$MG_REPORT$NL$NL$MG_SEPARATOR$NL"
typeset CARD="$MG_TEMPLATE"
integer ADD=0
for DATA in "$TYPE_LBL|$TYPE||" \
"$MG_TYPE_LBL|$MG_TYPE|ds8k_inband_mm,emc|" \
"$RG_LBL|$RESOURCE_GROUP|" \
"$MODE_LBL|$MODE|" \
"$CONSISTENT_LBL|$CONSISTENT|" \
"$STS_LBL|$STORAGE_SYSTEMS|ds8k_gm,ds8k_inband_mm,svc,xiv_rm" \
"$VENDOR_LBL|$VENDOR_ID|ds8k_gm,emc,hitachi,xiv_rm" \
\
"$HS_ENABLED_LBL|$HYPERSWAP_ENABLED|ds8k_inband_mm|" \
"$HS_PRIORITY_LBL|$HYPERSWAP_PRIORITY|ds8k_inband_mm|" \
"$HS_UNPL_TO_LBL|$UNPLANNED_HS_TIMEOUT|ds8k_inband_mm|" \
"$VGS_LBL|$VOLUME_GROUPS|ds8k_inband_mm|system,user" \
"$RDS_LBL|$DISKS|ds8k_inband_mm|system,user" \
"$RECOVERY_LBL|$RECOVERY|ds8k_gm,ds8k_inband_mm,emc,hitachi,svc,xiv_rm|user" \
"$NODE_LBL|$NODE|ds8k_inband_mm|system" \
"$SITE_LBL|$REPOSITORY_MG_SITES|ds8k_inband_mm|repository" \
"$NON_HS_DISK_LBL|$REPOSITORY_MG_NONHS_DISK|ds8k_inband_mm|repository" \
"$HS_DISK_LBL|$REPOSITORY_MG_HS_DISK|ds8k_inband_mm|repository" \
\
"$MPAIRS_LBL|$MIRROR_PAIRS|svc" \
\
"$HORCM_INST_LBL|$HORCM_INSTANCE|hitachi" \
"$HORCM_TO_LBL|$HORCM_TIMEOUT|hitachi" \
"$PE_TO_LBL|$PAIR_EVENT_TIMEOUT|hitachi"
do
print -- "$DATA" | IFS=\| read _LBL _VAL _TYP _SUBTYP
ADD=0
if [[ -z $_TYP ]]; then
ADD=1
elif [[ " ${_TYP//,/ } " == *\ $TYPE\ * ]]; then
if [[ $TYPE == "ds8k_inband_mm" ]]; then
if [[ -z $_SUBTYP ]]; then
ADD=1
elif [[ " ${_SUBTYP//,/ } " == *\ $MG_TYPE\ * ]]
then
ADD=1
fi
else
ADD=1
fi
fi
if (( ADD )); then
CARD=${CARD//\<%$_LBL%\>/${_VAL:--}}
fi
done
if (( MG_COUNT % 2 == 0 )); then
# Close the row
MG_REPORT="$MG_REPORT$NL$CARD"
else
MG_REPORT="$MG_REPORT$NL$NL"
fi
#
: Free the variables that were set for mirror group "$NAME".
: This releases some memory, but more importantly, it ensures
: that data from one object does not get accidentally shown
: with another one.
#
for VAR in NAME TYPE RESOURCE_GROUP MODE RECOVERY \
STORAGE_SYSTEMS CONSISTENT VENDOR_ID ATTRIBUTES MG_TYPE \
HYPERSWAP_ENABLED HYPERSWAP_PRIORITY UNPLANNED_HS_TIMEOUT \
VOLUME_GROUPS RAW_DISKS SYS_MG_NODE REPOSITORY_MG_SITES \
REPOSITORY_MG_HS_DISK REPOSITORY_MG_NONHS_DISK \
MIRROR_PAIRS HORCM_INSTANCE HORCM_TIMEOUT \
PAIR_EVENT_TIMEOUT
do
unset $VAR
done
elif [[ $LINE == *=* ]]; then
PVAR=${LINE%%=*}
PVAL=${LINE#*=}
eval "${PVAR//-/_}=$PVAL" # Store the value in an environment variable
fi
done # End of the mirror group processing loop
#
: Save the constructed report into a temporary file for later processing
#
print -- "$MG_REPORT" > $MG_FILE
)&
CHCR_CHILDREN="${CHCR_CHILDREN:+$CHCR_CHILDREN }$!"
(
#=====================================================
: Construct the STORAGE AGENTS section of the report
#=====================================================
#===============================================
: Load the data that is needed for this report
: from the clmgr verbose cluster output
#===============================================
typeset STA_DATA="$(sed -n '//,/<\/STORAGE_AGENTS>/p' $CDATA_FILE | grep -v 'STORAGE_AGENTS>$')"
#
: Extract the template from the overall report
#
typeset LABEL="sta_card_template"
typeset STA_TEMPLATE=$(sed -n "/<%${LABEL}_start%>/,/<%${LABEL}_end%>/p" $TEMPLATE_FILE | grep -v "<%$LABEL")
#
: Extract the row separator from the template
#
# The SIZE value, below, must be set to the number of lines of HTML
# used for it in the (cl|ss)_report_template.htm files. For this
# one, search for the "hr" line near the "sta_card_template_end"
# tag. The size should include the HTML code, plus any associated
# comments.
#
integer STA_SEPARATOR_SIZE=8
typeset STA_SEPARATOR=$(print -- "$STA_TEMPLATE" | tail -$STA_SEPARATOR_SIZE)
STA_SEPARATOR=${STA_SEPARATOR//\<\!--*--\>/} # Remove all comments
STA_SEPARATOR=${STA_SEPARATOR##*( )+(\n)}
STA_SEPARATOR=${STA_SEPARATOR%%*( )+(\n)}
#
: Remove the separator, then the template, from the overall report
#
integer LINES=$(print -- "$STA_TEMPLATE" | wc -l)
STA_TEMPLATE=$(print -- "$STA_TEMPLATE" | head -n $(( LINES -= STA_SEPARATOR_SIZE )))
STA_TEMPLATE="${STA_TEMPLATE%%+([[:space:]])}"
typeset STA_REPORT=""
typeset -i STA_COUNT=0
print -- "$STA_DATA\n" | grep -p NAME= |\
while read LINE
do
#
: A blank line separator indicates the start of a new block of node data
#
if [[ $LINE == *([[:space:]]) ]]
then
(( STA_COUNT++ ))
(( STA_COUNT > 1 )) && STA_REPORT="$STA_REPORT$NL$NL$STA_SEPARATOR$NL"
CARD="$STA_TEMPLATE"
CARD=${CARD//\<%name%\>/$NAME}
CARD=${CARD//\<%type%\>/${TYPE:--}}
CARD=${CARD//\<%addresses%\>/${ADDRESSES:--}}
CARD=${CARD//\<%user%\>/${USER:--}}
CARD=${CARD//\<%password%\>/${PASSWORD:--}}
STA_REPORT="$STA_REPORT$NL$CARD"
#
: Free the variables that were set for storage agent "$NAME".
: This releases some memory, but more importantly, it ensures
: that data from one object does not get accidentally shown
: with another one.
#
unset NAME TYPE ADDRESSES USER PASSWORD ATTRIBUTES
elif [[ $LINE == *=* ]]; then
PVAR=${LINE%%=*}
PVAL=${LINE#*=}
eval "${PVAR//-/_}=$PVAL" # Store the value in an environment variable
fi
done # End of the "STA_DATA" loop
#
: Save the constructed report into a temporary file for later processing
#
print -- "$STA_REPORT" >$STA_FILE
)&
CHCR_CHILDREN="${CHCR_CHILDREN:+$CHCR_CHILDREN }$!"
(
#======================================================
: Construct the STORAGE SYSTEMS section of the report
#======================================================
#===============================================
: Load the data that is needed for this report
: from the clmgr verbose cluster output
#===============================================
typeset STS_DATA="$(sed -n '//,/<\/STORAGE_SYSTEMS>/p' $CDATA_FILE | grep -v 'STORAGE_SYSTEMS>$')"
#
: Extract the template from the overall report
#
typeset LABEL="sts_card_template"
typeset STS_TEMPLATE=$(sed -n "/<%${LABEL}_start%>/,/<%${LABEL}_end%>/p" $TEMPLATE_FILE | grep -v "<%$LABEL")
#
: Extract the row separator from the template
#
# The SIZE value, below, must be set to the number of lines of HTML
# used for it in the (cl|ss)_report_template.htm files. For this
# one, search for the "hr" line near the "sts_card_template_end"
# tag. The size should include the HTML code, plus any associated
# comments.
#
integer STS_SEPARATOR_SIZE=8
typeset STS_SEPARATOR=$(print -- "$STS_TEMPLATE" | tail -$STS_SEPARATOR_SIZE)
STS_SEPARATOR=${STS_SEPARATOR//\<\!--*--\>/} # Remove all comments
STS_SEPARATOR=${STS_SEPARATOR##*( )+(\n)}
STS_SEPARATOR=${STS_SEPARATOR%%*( )+(\n)}
#
: Remove the separator, then the template, from the overall report
#
integer LINES=$(print -- "$STS_TEMPLATE" | wc -l)
STS_TEMPLATE=$(print -- "$STS_TEMPLATE" | head -n $(( LINES -= STS_SEPARATOR_SIZE )))
STS_TEMPLATE="${STS_TEMPLATE%%+([[:space:]])}"
typeset STS_REPORT=""
typeset -i STS_COUNT=0
print -- "$STS_DATA\n" | grep -p NAME= |\
while read LINE
do
#
: A blank line separator indicates the start of a new block of node data
#
if [[ $LINE == *([[:space:]]) ]]
then
(( STS_COUNT++ ))
(( STS_COUNT > 1 )) && STS_REPORT="$STS_REPORT$NL$NL$STS_SEPARATOR$NL"
CARD="$STS_TEMPLATE"
CARD=${CARD//\<%name%\>/$NAME}
CARD=${CARD//\<%type%\>/${TYPE:--}}
CARD=${CARD//\<%vendor%\>/${VENDOR_ID:--}}
CARD=${CARD//\<%wwnn%\>/${WWNN:--}}
CARD=${CARD//\<%site%\>/${SITE:--}}
CARD=${CARD//\<%storage_agents%\>/${AGENTS:--}}
STS_REPORT="$STS_REPORT$NL$CARD"
#
: Free the variables that were set for storage system "$NAME".
: This releases some memory, but more importantly, it ensures
: that data from one object does not get accidentally shown
: with another one.
#
unset NAME TYPE VENDOR_ID WWNN SITE STORAGE_AGENTS ATTRIBUTES
elif [[ $LINE == *=* ]]; then
PVAR=${LINE%%=*}
PVAL=${LINE#*=}
eval "${PVAR//-/_}=$PVAL" # Store the value in an environment variable
fi
done # End of the "STS_DATA" loop
#
: Save the constructed report into a temporary file for later processing
#
print -- "$STS_REPORT" >$STS_FILE
)&
CHCR_CHILDREN="${CHCR_CHILDREN:+$CHCR_CHILDREN }$!"
(
#===================================================
: Construct the MIRROR PAIRS section of the report
#===================================================
#===============================================
: Load the data that is needed for this report
: from the clmgr verbose cluster output
#===============================================
typeset MPAIR_DATA="$(sed -n '//,/<\/MIRROR_PAIRS>/p' $CDATA_FILE | grep -v 'MIRROR_PAIRS>$')"
#
: Extract the template from the overall report
#
typeset LABEL="mpair_card_template"
typeset MPAIR_TEMPLATE=$(sed -n "/<%${LABEL}_start%>/,/<%${LABEL}_end%>/p" $TEMPLATE_FILE | grep -v "<%$LABEL")
#
: Extract the row separator from the template
#
# The SIZE value, below, must be set to the number of lines of HTML
# used for it in the (cl|ss)_report_template.htm files. For this
# one, search for the "hr" line near the "mpair_card_template_end"
# tag. The size should include the HTML code, plus any associated
# comments.
#
integer MPAIR_SEPARATOR_SIZE=8
typeset MPAIR_SEPARATOR=$(print -- "$MPAIR_TEMPLATE" | tail -$MPAIR_SEPARATOR_SIZE)
MPAIR_SEPARATOR=${MPAIR_SEPARATOR//\<\!--*--\>/} # Remove all comments
MPAIR_SEPARATOR=${MPAIR_SEPARATOR##*( )+(\n)}
MPAIR_SEPARATOR=${MPAIR_SEPARATOR%%*( )+(\n)}
#
: Remove the separator, then the template, from the overall report
#
integer LINES=$(print -- "$MPAIR_TEMPLATE" | wc -l)
MPAIR_TEMPLATE=$(print -- "$MPAIR_TEMPLATE" | head -n $(( LINES -= MPAIR_SEPARATOR_SIZE )))
MPAIR_TEMPLATE="${MPAIR_TEMPLATE%%+([[:space:]])}"
typeset MPAIR_REPORT=""
typeset -i MPAIR_COUNT=0
print -- "$MPAIR_DATA\n" | grep -p NAME= |\
while read LINE
do
#
: A blank line separator indicates the start of a new block of node data
#
if [[ $LINE == *([[:space:]]) ]]
then
(( MPAIR_COUNT++ ))
(( MPAIR_COUNT > 1 )) && MPAIR_REPORT="$MPAIR_REPORT$NL$NL$MPAIR_SEPARATOR$NL"
CARD="$MPAIR_TEMPLATE"
CARD=${CARD//\<%name%\>/$NAME}
CARD=${CARD//\<%first_disk%\>/${FIRST_DISK:--}}
CARD=${CARD//\<%second_disk%\>/${SECOND_DISK:--}}
MPAIR_REPORT="$MPAIR_REPORT$NL$CARD"
#
: Free the variables that were set for mirror pair "$NAME".
: This releases some memory, but more importantly, it ensures
: that data from one object does not get accidentally shown
: with another one.
#
unset NAME FIRST_DISK SECOND_DISK
elif [[ $LINE == *=* ]]; then
PVAR=${LINE%%=*}
PVAL=${LINE#*=}
eval "${PVAR//-/_}=$PVAL" # Store the value in an environment variable
fi
done # End of the "MPAIRS_DATA" loop
#
: Save the constructed report into a temporary file for later processing
#
print -- "$MPAIR_REPORT" >$MPAIR_FILE
)&
CHCR_CHILDREN="${CHCR_CHILDREN:+$CHCR_CHILDREN }$!"
fi
(
#==============================================================
: Construct the APPLICATION CONTROLLERS section of the report
#==============================================================
#===============================================
: Load the data that is needed for this report
: from the clmgr verbose cluster output
#===============================================
typeset AC_DATA="$(sed -n '//,/<\/APPLICATION_CONTROLLERS>/p' $CDATA_FILE | grep -v 'DEPENDENCIES>$')"
#
: Extract the template from the overall report
#
typeset LABEL="ac_card_template"
typeset AC_TEMPLATE=$(sed -n "/<%${LABEL}_start%>/,/<%${LABEL}_end%>/p" $TEMPLATE_FILE | grep -v "<%$LABEL")
#
: Extract the row separator from the template
#
# The SIZE value, below, must be set to the number of lines of HTML
# used for it in the (cl|ss)_report_template.htm files. For this
# one, search for the "hr" line near the "ac_card_template_end"
# tag. The size should include the HTML code, plus any associated
# comments.
#
integer AC_SEPARATOR_SIZE=8
typeset AC_SEPARATOR=$(print -- "$AC_TEMPLATE" | tail -$AC_SEPARATOR_SIZE)
AC_SEPARATOR=${AC_SEPARATOR//\<\!--*--\>/} # Remove all comments
AC_SEPARATOR=${AC_SEPARATOR##*( )+(\n)}
AC_SEPARATOR=${AC_SEPARATOR%%*( )+(\n)}
typeset AC_REPORT=""
typeset -i AC_COUNT=0
print -- "$AC_DATA\n" | grep -p NAME= |\
while read LINE
do
#
: A blank line separator indicates the start of a new block of node data
#
if [[ $LINE == *([[:space:]]) ]]
then
(( AC_COUNT++ ))
CARD="$AC_TEMPLATE"
CARD=${CARD//\<%name%\>/$NAME}
CARD=${CARD//\<%monitors%\>/${MONITORS:--}}
CARD=${CARD//\<%start_script%\>/${STARTSCRIPT:--}}
CARD=${CARD//\<%stop_script%\>/${STOPSCRIPT:--}}
AC_REPORT="$AC_REPORT$NL$CARD"
#
: Free the variables that were set for application controller "$NAME".
: This releases some memory, but more importantly, it ensures
: that data from one object does not get accidentally shown
: with another one.
#
unset NAME MONITORS STARTSCRIPT STOPSCRIPT
elif [[ $LINE == *=* ]]; then
PVAR=${LINE%%=*}
PVAL=${LINE#*=}
eval "${PVAR//-/_}=$PVAL" # Store the value in an environment variable
fi
done # End of the "AC_DATA" loop
#
: Save the constructed report into a temporary file for later processing
#
print -- "$AC_REPORT" >$AC_FILE
)&
CHCR_CHILDREN="${CHCR_CHILDREN:+$CHCR_CHILDREN }$!"
(
#===========================================================
: Construct the APPLICATION MONITORS section of the report
#===========================================================
#===============================================
: Load the data that is needed for this report
: from the clmgr verbose cluster output
#===============================================
typeset AM_DATA="$(sed -n '//,/<\/APPLICATION_MONITORS>/p' $CDATA_FILE | grep -v 'APPLICATION_MONITORS>$')"
#====================================================
: Get the labels for the application monitors table
#====================================================
eval $(cl_batch_dspmsg -e -s $CLMGR_RPT_SET $CLMGR_MSGS \
16:PROCESSES_LBL "Processes" \
17:OWNER_LBL "Owner" \
18:INSTANCES_LBL "Instances" \
19:MONMETH_LBL "Monitor Method" \
20:MONINT_LBL "Monitoring Interval" \
21:HUNGSIGNAL_LBL "Hung Process Signal" \
22:APPS_LBL "Applications Monitored" \
23:MODE_LBL "Mode" \
24:FAILUREACTION_LBL "Failure Action" \
25:NOTIFY_METHOD_LBL "Notification Method" \
26:STABILIZATION_LBL "Stabilization Interval" \
27:RESTARTMETHOD_LBL "Restart Method" \
28:RESTARTCOUNT_LBL "Restart Count" \
29:RESTARTINT_LBL "Restart Interval" \
30:CLEANUPMETHOD_LBL "Cleanup Method" \
37:TYPE_LBL "Type:")
#
: Extract the template from the overall report
#
typeset LABEL="am_card_template"
typeset AM_TEMPLATE=$(sed -n "/<%${LABEL}_start%>/,/<%${LABEL}_end%>/p" $TEMPLATE_FILE | grep -v "<%$LABEL")
#
: Extract the row separator from the template
#
# The SIZE value, below, must be set to the number of lines of HTML
# used for it in the (cl|ss)_report_template.htm files. For this
# one, search for the "hr" line near the "am_card_template_end"
# tag. The size should include the HTML code, plus any associated
# comments.
#
integer AM_SEPARATOR_SIZE=8
typeset AM_SEPARATOR=$(print -- "$AM_TEMPLATE" | tail -$AM_SEPARATOR_SIZE)
AM_SEPARATOR=${AM_SEPARATOR//\<\!--*--\>/} # Remove all comments
AM_SEPARATOR=${AM_SEPARATOR##*( )+(\n)}
AM_SEPARATOR=${AM_SEPARATOR%%*( )+(\n)}
#
: Remove the separator, then the template, from the overall report
#
integer LINES=$(print -- "$AM_TEMPLATE" | wc -l)
AM_TEMPLATE=$(print -- "$AM_TEMPLATE" | head -n $(( LINES -= AM_SEPARATOR_SIZE )))
AM_TEMPLATE="${AM_TEMPLATE%%+([[:space:]])}"
typeset AM_REPORT=""
typeset -i AM_COUNT=0
print -- "$AM_DATA\n" | grep -p NAME= |\
while read LINE
do
#
: A blank line separator indicates the start of a new block of node data
#
if [[ $LINE == *([[:space:]]) ]]
then
(( AM_COUNT++ ))
case $MODE in
@(l|L)*) MODE=$(dspmsg -s 24 cluster.cat 213 "Long-running monitoring,Startup Monitoring,Both" | cut -f1 -d,) ;;
@(s|S)*) MODE=$(dspmsg -s 24 cluster.cat 213 "Long-running monitoring,Startup Monitoring,Both" | cut -f2 -d,) ;;
@(b|B)*) MODE=$(dspmsg -s 24 cluster.cat 213 "Long-running monitoring,Startup Monitoring,Both" | cut -f3 -d,) ;;
esac
case $TYPE in
@(p|P)*) TYPE=$(dspmsg -s $CLMGR_RPT_SET $CLMGR_MSGS 31 "Process Monitor") ;;
*) TYPE=$(dspmsg -s $CLMGR_RPT_SET $CLMGR_MSGS 32 "Custom Monitor") ;;
esac
CARD="$AM_TEMPLATE"
CARD=${CARD//\<%name%\>/$NAME}
CARD=${CARD//\<%type_lbl%\>/${TYPE_LBL:--}}
CARD=${CARD//\<%type%\>/${TYPE:--}}
if [[ $TYPE == @(p|P)* ]]; then
CARD=${CARD//\<%PROCESSES_LBL%\>/${PROCESSES_LBL:--}}
CARD=${CARD//\<%OWNER_LBL%\>/${OWNER_LBL:--}}
CARD=${CARD//\<%INSTANCES_LBL%\>/${INSTANCES_LBL:--}}
else
CARD=${CARD//\<%MONMETH_LBL%\>/${MONMETH_LBL:--}}
CARD=${CARD//\<%MONINT_LBL%\>/${MONINT_LBL:--}}
CARD=${CARD//\<%HUNGSIGNAL_LBL%\>/${HUNGSIGNAL_LBL:--}}
fi
CARD=${CARD//\<%APPS_LBL%\>/${APPS_LBL:--}}
CARD=${CARD//\<%MODE_LBL%\>/${MODE_LBL:--}}
CARD=${CARD//\<%FAILUREACTION_LBL%\>/${FAILUREACTION_LBL:--}}
CARD=${CARD//\<%NOTIFY_METHOD_LBL%\>/${NOTIFY_METHOD_LBL:--}}
CARD=${CARD//\<%STABILIZATION_LBL%\>/${STABILIZATION_LBL:--}}
CARD=${CARD//\<%RESTARTMETHOD_LBL%\>/${RESTARTMETHOD_LBL:--}}
CARD=${CARD//\<%RESTARTCOUNT_LBL%\>/${RESTARTCOUNT_LBL:--}}
CARD=${CARD//\<%RESTARTINT_LBL%\>/${RESTARTINT_LBL:--}}
CARD=${CARD//\<%CLEANUPMETHOD_LBL%\>/${CLEANUPMETHOD_LBL:--}}
if [[ $TYPE == @(p|P)* ]]; then
CARD=${CARD//\<%PROCESSES%\>/${PROCESSES:--}}
CARD=${CARD//\<%OWNER%\>/${OWNER:--}}
CARD=${CARD//\<%INSTANCECOUNT%\>/${INSTANCECOUNT:--}}
else
CARD=${CARD//\<%MONITORMETHOD%\>/${MONITORMETHOD:--}}
CARD=${CARD//\<%MONITORINTERVAL%\>/${MONITORINTERVAL:--}}
CARD=${CARD//\<%HUNGSIGNAL%\>/${HUNGSIGNAL:--}}
fi
CARD=${CARD//\<%APPLICATIONS%\>/${APPLICATIONS:--}}
CARD=${CARD//\<%MODE%\>/${MODE:--}}
CARD=${CARD//\<%FAILUREACTION%\>/${FAILUREACTION:--}}
CARD=${CARD//\<%NOTIFYMETHOD%\>/${NOTIFYMETHOD:--}}
CARD=${CARD//\<%STABILIZATION%\>/${STABILIZATION:--}}
CARD=${CARD//\<%RESTARTMETHOD%\>/${RESTARTMETHOD:--}}
CARD=${CARD//\<%RESTARTCOUNT%\>/${RESTARTCOUNT:--}}
CARD=${CARD//\<%RESTARTINT%\>/${RESTARTINT:--}}
CARD=${CARD//\<%CLEANUPMETHOD%\>/${CLEANUPMETHOD:--}}
AM_REPORT="$AM_REPORT$NL$CARD"
#
: Free the variables that were set for application monitor "$NAME".
: This releases some memory, but more importantly, it ensures
: that data from one object does not get accidentally shown
: with another one.
#
unset NAME TYPE APPLICATIONS MODE STABILIZATION RESTARTCOUNT \
FAILUREACTION NOTIFYMETHOD PROCESSES OWNER INSTANCECOUNT \
RESTARTINTERVAL CLEANUPMETHOD RESTARTMETHOD \
RESTARTINTERVAL MONITORMETHOD MONITORINTERVAL HUNGSIGNAL
elif [[ $LINE == *=* ]]; then
PVAR=${LINE%%=*}
PVAL=${LINE#*=}
eval "${PVAR//-/_}=$PVAL" # Store the value in an environment variable
fi
done # End of the "AM_DATA" loop
#
: Save the constructed report into a temporary file for later processing
#
print -- "$AM_REPORT" >$AM_FILE
)&
CHCR_CHILDREN="${CHCR_CHILDREN:+$CHCR_CHILDREN }$!"
(
#====================================================
: Construct the CUSTOM EVENTS section of the report
#====================================================
#===============================================
: Load the data that is needed for this report
: from the clmgr verbose cluster output
#===============================================
typeset EV_DATA="$(sed -n '//,/<\/EVENTS>/p' $CDATA_FILE | grep -v 'EVENTS>$')"
#
: Extract the template from the overall report
#
typeset LABEL="ev_card_template"
typeset EV_TEMPLATE=$(sed -n "/<%${LABEL}_start%>/,/<%${LABEL}_end%>/p" $TEMPLATE_FILE | grep -v "<%$LABEL")
#
: Extract the row separator from the template
#
# The SIZE value, below, must be set to the number of lines of HTML
# used for it in the (cl|ss)_report_template.htm files. For this
# one, search for the "hr" line near the "ev_card_template_end"
# tag. The size should include the HTML code, plus any associated
# comments.
#
integer EV_SEPARATOR_SIZE=8
typeset EV_SEPARATOR=$(print -- "$EV_TEMPLATE" | tail -$EV_SEPARATOR_SIZE)
EV_SEPARATOR=${EV_SEPARATOR//\<\!--*--\>/} # Remove all comments
EV_SEPARATOR=${EV_SEPARATOR##*( )+(\n)}
EV_SEPARATOR=${EV_SEPARATOR%%*( )+(\n)}
#
: Remove the separator, then the template, from the overall report
#
integer LINES=$(print -- "$EV_TEMPLATE" | wc -l)
EV_TEMPLATE=$(print -- "$EV_TEMPLATE" | head -n $(( LINES -= EV_SEPARATOR_SIZE )))
EV_TEMPLATE="${EV_TEMPLATE%%+([[:space:]])}"
typeset EV_REPORT=""
typeset -i EV_COUNT=0
print -- "$EV_DATA\n" | grep -p NAME= |\
while read LINE
do
#
: A blank line separator indicates the start of a new block of node data
#
if [[ $LINE == *([[:space:]]) ]]
then
(( EV_COUNT++ ))
(( EV_COUNT > 1 )) && EV_REPORT="$EV_REPORT$NL$NL$EV_SEPARATOR$NL"
typeset ASSOC=""
#============================================================
: Find all core events where $NAME is used as a pre command
#============================================================
DATA=$(clmgr -v q event TYPE="PREDEFINED")
CEV=$(print -- "$DATA" |\
egrep -e "^NAME=" -e "PRE_EVENT_COMMAND=")
CEV=${CEV//${NL}PRE_EVENT_COMMAND=/ PRE_EVENT_COMMAND=}
print -- "$CEV" | grep -v "PRE_EVENT_COMMAND=\"\"" |\
while read LINE; do
PRE=${LINE##*EVENT_COMMAND=}
PRE=${PRE//\"/ }
if [[ " $PRE " == *\ $NAME\ * ]]; then
[[ -n $ASSOC ]] && ASSOC="$ASSOC "
LINE=${LINE#*\"}
MSG=$(dspmsg -s $CLMGR_RPT_SET $CLMGR_MSGS 33 'Executes before "%1$s"' "${LINE%%\"*}")
ASSOC="$ASSOC$MSG"
fi
done
#=============================================================
: Find all core events where $NAME is used as a post command
#=============================================================
CEV=$(print -- "$DATA" |\
egrep -e "^NAME=" -e "POST_EVENT_COMMAND=")
CEV=${CEV//${NL}POST_EVENT_COMMAND=/ POST_EVENT_COMMAND=}
print -- "$CEV" | grep -v "POST_EVENT_COMMAND=\"\"" |\
while read LINE; do
POST=${LINE##*EVENT_COMMAND=}
POST=${POST//\"/ }
if [[ " $POST " == *\ $NAME\ * ]]; then
[[ -n $ASSOC ]] && ASSOC="$ASSOC "
LINE=${LINE#*\"}
MSG=$(dspmsg -s $CLMGR_RPT_SET $CLMGR_MSGS 34 'Executes after "%1$s"' "${LINE%%\"*}")
ASSOC="$ASSOC$MSG"
fi
done
unset LINE CEV DATA PRE POST
[[ -z $ASSOC ]] && ASSOC=" "
CARD="$EV_TEMPLATE"
CARD=${CARD//\<%name%\>/$NAME}
CARD=${CARD//\<%file%\>/${FILE:--}}
CARD=${CARD//\<%core_assoc%\>/${ASSOC:--}}
CARD=${CARD//\<%desc%\>/${DESCRIPTION:--}}
EV_REPORT="$EV_REPORT$NL$CARD"
#
: Free the variables that were set for custom event "$NAME".
: This releases some memory, but more importantly, it ensures
: that data from one object does not get accidentally shown
: with another one.
#
unset NAME TYPE FILE ASSOC DESCRIPTION
elif [[ $LINE == *=* ]]; then
PVAR=${LINE%%=*}
PVAL=${LINE#*=}
eval "${PVAR//-/_}=$PVAL" # Store the value in an environment variable
fi
done # End of the "EV_DATA" loop
#
: Save the constructed report into a temporary file for later processing
#
print -- "$EV_REPORT" >$EV_FILE
)&
CHCR_CHILDREN="${CHCR_CHILDREN:+$CHCR_CHILDREN }$!"
(
#=======================================================
: Construct the SNAPSHOT METHODS section of the report
#=======================================================
#===============================================
: Load the data that is needed for this report
: from the clmgr verbose cluster output
#===============================================
typeset METHOD_DATA="$(sed -n '//,/<\/METHODS>/p' $CDATA_FILE | grep -v 'METHODS>$')"
#
: Extract the template from the overall report
#
typeset LABEL="snapshot_method_card_template"
typeset SS_TEMPLATE=$(sed -n "/<%${LABEL}_start%>/,/<%${LABEL}_end%>/p" $TEMPLATE_FILE | grep -v "<%$LABEL")
typeset SS_REPORT=""
typeset -i SS_COUNT=0
print -- "$METHOD_DATA\n" | grep -p "TYPE=\"snapshot\"" |\
while read LINE; do
if [[ $LINE == *([[:space:]]) ]]; then
(( SS_COUNT++ ))
(( SS_COUNT > 1 )) && SS_REPORT="$SS_REPORT$NL$NL$SS_SEPARATOR$NL"
CARD="$SS_TEMPLATE"
CARD=${CARD//\<%name%\>/$NAME}
CARD=${CARD//\<%file%\>/${FILE:--}}
CARD=${CARD//\<%desc%\>/${DESCRIPTION:--}}
SS_REPORT="$SS_REPORT$NL$CARD"
#
: Free the variables that were set for snapshot method "$NAME".
: This releases some memory, but more importantly, it ensures
: that data from one object does not get accidentally shown
: with another one.
#
unset NAME FILE DESCRIPTION
elif [[ $LINE == *=* ]]; then
PVAR=${LINE%%=*}
PVAL=${LINE#*=}
eval "${PVAR//-/_}=$PVAL" # Store the value in an environment variable
fi
done # End of the "METHOD_DATA - SNAPSHOT" loop
#
: Save the constructed report into a temporary file for later processing
#
print -- "$SS_REPORT" >$SS_METHODS_FILE
)&
CHCR_CHILDREN="${CHCR_CHILDREN:+$CHCR_CHILDREN }$!"
(
#===========================================================
: Construct the VERIFICATION METHODS section of the report
#===========================================================
#===============================================
: Load the data that is needed for this report
: from the clmgr verbose cluster output
#===============================================
typeset METHOD_DATA="$(sed -n '//,/<\/METHODS>/p' $CDATA_FILE | grep -v 'METHODS>$')"
#
: Extract the template from the overall report
#
LABEL="verify_method_card_template"
typeset VER_TEMPLATE=$(sed -n "/<%${LABEL}_start%>/,/<%${LABEL}_end%>/p" $TEMPLATE_FILE | grep -v "<%$LABEL")
typeset VER_REPORT=""
typeset -i VER_COUNT=0
print -- "$METHOD_DATA\n" | grep -p "TYPE=\"verify\"" |\
while read LINE; do
if [[ $LINE == *([[:space:]]) ]]; then
(( VER_COUNT++ ))
(( VER_COUNT > 1 )) && VER_REPORT="$VER_REPORT$NL$NL$VER_SEPARATOR$NL"
CARD="$VER_TEMPLATE"
CARD=${CARD//\<%name%\>/$NAME}
CARD=${CARD//\<%file%\>/${FILE:--}}
CARD=${CARD//\<%source%\>/${SOURCE:--}}
CARD=${CARD//\<%desc%\>/${DESCRIPTION:--}}
VER_REPORT="$VER_REPORT$NL$CARD"
#
: Free the variables that were set for verification method "$NAME".
: This releases some memory, but more importantly, it ensures
: that data from one object does not get accidentally shown
: with another one.
#
unset NAME FILE SOURCE DESCRIPTION
elif [[ $LINE == *=* ]]; then
PVAR=${LINE%%=*}
PVAL=${LINE#*=}
eval "${PVAR//-/_}=$PVAL" # Store the value in an environment variable
fi
done # End of the "METHOD_DATA - VERIFY" loop
#
: Save the constructed report into a temporary file for later processing
#
print -- "$VER_REPORT" >$VER_METHODS_FILE
)&
CHCR_CHILDREN="${CHCR_CHILDREN:+$CHCR_CHILDREN }$!"
(
#===========================================================
: Construct the NOTIFICATION METHODS section of the report
#===========================================================
#===============================================
: Load the data that is needed for this report
: from the clmgr verbose cluster output
#===============================================
typeset METHOD_DATA="$(sed -n '//,/<\/METHODS>/p' $CDATA_FILE | grep -v 'METHODS>$')"
#
: Extract the template from the overall report
#
LABEL="notify_method_card_template"
typeset NT_TEMPLATE=$(sed -n "/<%${LABEL}_start%>/,/<%${LABEL}_end%>/p" $TEMPLATE_FILE | grep -v "<%$LABEL")
typeset NT_REPORT=""
typeset -i NT_COUNT=0
print -- "$METHOD_DATA\n" | grep -p "TYPE=\"notify\"" |\
while read LINE; do
if [[ $LINE == *([[:space:]]) ]]; then
(( NT_COUNT++ ))
(( NT_COUNT > 1 )) && NT_REPORT="$NT_REPORT$NL$NL$NT_SEPARATOR$NL"
CARD="$NT_TEMPLATE"
CARD=${CARD//\<%name%\>/$NAME}
CARD=${CARD//\<%file%\>/${FILE:--}}
CARD=${CARD//\<%desc%\>/${DESCRIPTION:--}}
CARD=${CARD//\<%contact%\>/${CONTACT:--}}
CARD=${CARD//\<%events%\>/${EVENTS:--}}
CARD=${CARD//\<%retry%\>/${RETRY:--}}
CARD=${CARD//\<%timeout%\>/${TIMEOUT:--}}
typeset LINKS=""
for OBJECT in ${NODES//,/ }
do
LINKS="${LINKS:+$LINKS,}$OBJECT"
done
CARD=${CARD//\<%nodes%\>/${LINKS:--}}
NT_REPORT="$NT_REPORT$NL$CARD"
#
: Free the variables that were set for notification method "$NAME".
: This releases some memory, but more importantly, it ensures
: that data from one object does not get accidentally shown
: with another one.
#
unset NAME FILE DESCRIPTION CONTACT EVENTS RETRY TIMEOUT
elif [[ $LINE == *=* ]]; then
PVAR=${LINE%%=*}
PVAL=${LINE#*=}
eval "${PVAR//-/_}=$PVAL" # Store the value in an environment variable
fi
done # End of the "METHOD_DATA - NOTIFY" loop
#
: Save the constructed report into a temporary file for later processing
#
print -- "$NT_REPORT" >$NT_METHODS_FILE
)&
CHCR_CHILDREN="${CHCR_CHILDREN:+$CHCR_CHILDREN }$!"
(
#=======================================================
: Construct the FILE COLLECTIONS section of the report
#=======================================================
#===============================================
: Load the data that is needed for this report
: from the clmgr verbose cluster output
#===============================================
typeset FC_DATA="$(sed -n '//,/<\/FILE_COLLECTIONS>/p' $CDATA_FILE | grep -v 'FILE_COLLECTIONS>$')"
#
: Extract the template from the overall report
#
typeset LABEL="fc_card_template"
typeset FC_TEMPLATE=$(sed -n "/<%${LABEL}_start%>/,/<%${LABEL}_end%>/p" $TEMPLATE_FILE | grep -v "<%$LABEL")
#
: Extract the row separator from the template
#
# The SIZE value, below, must be set to the number of lines of HTML
# used for it in the (cl|ss)_report_template.htm files. For this
# one, search for the "hr" line near the "fc_card_template_end"
# tag. The size should include the HTML code, plus any associated
# comments.
#
integer FC_SEPARATOR_SIZE=8
typeset FC_SEPARATOR=$(print -- "$FC_TEMPLATE" | tail -$FC_SEPARATOR_SIZE)
FC_SEPARATOR=${FC_SEPARATOR//\<\!--*--\>/} # Remove all comments
FC_SEPARATOR=${FC_SEPARATOR##*( )+(\n)}
FC_SEPARATOR=${FC_SEPARATOR%%*( )+(\n)}
#
: Remove the separator, then the template, from the overall report
#
integer LINES=$(print -- "$FC_TEMPLATE" | wc -l)
FC_TEMPLATE=$(print -- "$FC_TEMPLATE" | head -n $(( LINES -= FC_SEPARATOR_SIZE )))
FC_TEMPLATE="${FC_TEMPLATE%%+([[:space:]])}"
typeset FC_REPORT=""
typeset -i FC_COUNT=0
print -- "$FC_DATA\n" | grep -p NAME= |\
while read LINE; do
if [[ $LINE == *([[:space:]]) ]]; then
(( FC_COUNT++ ))
(( FC_COUNT > 1 )) && FC_REPORT="$FC_REPORT$NL$NL$FC_SEPARATOR$NL"
#========================================================
: Find all the files/directories for collection "$NAME"
#========================================================
typeset FILES=""
FOUND=0
print -- "$FC_DATA" | egrep -e ^NAME= -e ^FILE= |\
while read LINE; do
if (( ! FOUND )); then
VAL=""
[[ $LINE == NAME=* ]] && VAL=${LINE#*=}
[[ ${VAL//\"/} == $NAME ]] && FOUND=1
else
[[ $LINE == NAME=* ]] && break # Next node. Done.
VAL=${LINE#*=}
VAL=${VAL//\"/}
[[ -n $FILES ]] && FILES="$FILES, "
FILES="$FILES$VAL"
fi
done
[[ -z $FILES ]] && FILES=" "
CARD="$FC_TEMPLATE"
CARD=${CARD//\<%name%\>/$NAME}
CARD=${CARD//\<%desc%\>/${DESCRIPTION:--}}
CARD=${CARD//\<%sync_prop%\>/${SYNC_WITH_CLUSTER:--}}
CARD=${CARD//\<%auto_prop%\>/${SYNC_WHEN_CHANGED:--}}
CARD=${CARD//\<%files_dirs%\>/${FILES:--}}
FC_REPORT="$FC_REPORT$NL$CARD"
#
: Free the variables that were set for file collection "$NAME".
: This releases some memory, but more importantly, it ensures
: that data from one object does not get accidentally shown
: with another one.
#
unset NAME TYPE DESCRIPTION SYNC_WITH_CLUSTER \
SYNC_WHEN_CHANGED FILES
elif [[ $LINE == *=* ]]; then
PVAR=${LINE%%=*}
PVAL=${LINE#*=}
eval "${PVAR//-/_}=$PVAL" # Store the value in an environment variable
fi
done # End of the "FC_DATA" loop
#
: Save the constructed report into a temporary file for later processing
#
print -- "$FC_REPORT" >$FC_FILE
)&
CHCR_CHILDREN="${CHCR_CHILDREN:+$CHCR_CHILDREN }$!"
(
typeset REPORT=$(cat $TEMPLATE_FILE)
#===========================================================
: Replace all non-template label targets within the report
#===========================================================
cl_batch_dspmsg -e -s $CLMGR_RPT_SET $CLMGR_MSGS \
35:geninfo "General Information" \
36:cluster_name "Cluster Name:" \
37:type "Type:" \
38:ha_edition "Edition:" \
39:ha_version "Version:" \
40:heartbeat_type "Heartbeat Type:" \
41:cluster_ip "Cluster IP Address:" \
42:cluster_id "Cluster ID:" \
43:status "Status:" \
44:unsynced_changes "Unsynchronized Changes?" \
45:max_event_time "Maximum Event Processing Time:" \
46:max_rg_proc_time "Maximum Resource Group Processing Time:" \
47:config_too_long "CONFIG_TOO_LONG Time Limit:" \
\
48:sites "Sites" \
49:site_ip "Site IP Address" \
50:site_nodes "Nodes at This Site" \
51:recovery_priority "Recovery Priority" \
7:primary "Primary" \
\
52:name "Name" \
53:nodes "Nodes:" \
54:rgs "Resource Groups" \
60:apps "Applications:" \
61:fses "File Systems:" \
73:vgs "Volume Groups:" \
75:tapes "Tapes:" \
\
77:rg_deps "Resource Group Dependencies" \
78:rg_temp_deps "Temporal Dependencies" \
79:rg_loc_deps "Location Dependencies" \
80:rg_parent "Parent Resource Group" \
81:rg_children "Child Resource Groups" \
82:rg_loc_policy "Location Policy" \
83:rg_processing "Resource Group Processing" \
301:rg_sequential_deps "Sequential Dependencies" \
302:rg_start_after_source "'Start after' source resource group" \
303:rg_start_after_target "'Start after' target resource groups" \
304:rg_stop_after_source "'Stop after' source resource group" \
305:rg_stop_after_target "'Stop after' target resource groups" \
306:rg_same_node "Resources which are online on same node" \
307:rg_different_node "Resources which are online on different node" \
308:rg_same_site "Resources which are online on same site" \
\
88:rg_global "Global Resource Group Settings" \
89:rg_settling_time "Settling Time" \
90:rg_dist_policy "Distribution Policy" \
\
91:networks "Networks" \
92:netmask "Netmask" \
93:rdpref "Resource Distribution Preference" \
94:visibility "Visibility" \
95:ip_labels "IP Labels" \
96:ip_label "IP Label" \
97:nwname "Network Name" \
98:nettype "Network Type" \
99:node "Node" \
100:interface "Interface" \
101:address "Address" \
102:interfaces "Interfaces" \
\
103:vg "Volume Group" \
104:pvs "Physical Volumes" \
105:lvs "Logical Volumes" \
106:rg "Resource Group" \
107:mpools "Mirror Pools" \
108:mpool_strictness "Mirror Pool Strictness" \
109:major "Major Number" \
\
110:mount_point "Mount Point" \
111:pparts "Physical Partitions" \
112:ppart_size "Physical Partition Size" \
113:lparts "Logical Partitions" \
114:lpart_copies "Logical Partition Copies" \
\
115:strict "Super Strict?" \
116:mode "Mode" \
117:async_clv "Async Cache Logical Volume" \
118:async_chwm "Async Cache High Water Mark" \
\
119:expdir "Exported Directory" \
120:size "Size" \
121:quota "Quota Management?" \
122:efs "EFS Enabled?" \
123:mountguard "Mountguard?" \
124:avail "Available Space" \
\
125:device "Device" \
126:start_script "Start Script" \
127:start_sync "Start Synchronously?" \
128:stop_script "Stop Script" \
129:stop_sync "Stop Synchronously?" \
\
130:appctlrs "Application Controllers" \
131:monitors "Monitors" \
132:appmons "Application Monitors" \
\
133:custclev "Custom Cluster Events" \
134:file "File" \
135:core_assoc "Core Event Associations" \
136:desc "Description" \
\
137:fcs "File Collections" \
138:sync_prop "Propagate Files During Sync?" \
139:auto_prop "Propagate Files When Changed?" \
140:files_dirs "Files/Directories" \
\
141:cluster_security "Cluster Security" \
142:security_level "Level:" \
143:security_algorithm "Algorithm:" \
144:security_refresh "Refresh:" \
145:security_mechanism "Mechanism:" \
146:security_certificate "Certificate:" \
147:security_key "Private Key:" \
\
148:cluster_tuning "Cluster Tuning" \
149:hbt_freq "Heartbeat Frequency:" \
150:grace_period "Grace Period:" \
151:hb_cycle "Site Heartbeat Cycle:" \
152:site_grace_period "Site Grace Period:" \
\
153:split_merge "Cluster Split / Merge Policies" \
154:split_policy "Split Policy:" \
155:merge_policy "Merge Policy:" \
156:action_plan "Action Plan:" \
202:nfs_quorum_server "NFS Quorum Server:" \
203:local_quorum_directory "Local Quorum Directory:" \
204:remote_quorum_directory "Remote Quorum Directory:" \
157:tie_breaker "Tie Breaker:" \
158:notify_method "Notify Method:" \
159:notify_interval "Notify Interval:" \
160:max_notify "Maximum Notifications:" \
161:surviving_site "Default Surviving Site:" \
162:pprc_takeover "Apply to PPRC Takover:" \
\
163:cluster_ver "Cluster Verification" \
164:daily_ver "Automatic Daily Cluster Verification" \
165:ver_node "Verification Node" \
166:ver_hour "Verification Hour" \
167:ver_debug "Verification Debugging" \
\
168:tape_devices "Tape Devices" \
171:storage_systems "Storage Systems" \
183:storage_agents "Storage Agents" \
179:mirror_pairs "Mirror Pairs" \
184:addresses "Addresses" \
185:user "User Login" \
186:password "User Password" \
173:vendor "Vendor Identifier" \
188:wwnn "World Wide Node Name" \
6:site "Site" \
189:first_disk "First Disk" \
190:second_disk "Second Disk" \
\
400:print "Print" \
401:download "Download" \
402:snapshot "Cluster Snapshot" \
403:print "Print" \
404:platform "Platform" \
99999:os_name "$(uname)" \
405:ss_created "Snapshot captured on" \
406:service_ips "Service IPs" \
407:no "No (active)" \
408:yes "Yes" \
409:repositories "Repositories" \
410:configuration "Configuration" \
411:rpt_created "Report created on" \
412:policies "Policies" \
413:backup "Backup" \
\
414:snapshot_methods "Snapshot Methods" \
415:verify_methods "Verification Methods" \
416:notify_methods "Notification Methods" \
417:source "Source" \
418:contact "Contact" \
419:events "Events" \
420:retry "Retry" \
421:timeout "Timeout" \
422:auto_file_update "Automatic File Update (minutes):" |\
while read LINE; do
TAG=${LINE%%=*}
TAG=${TAG#typeset }
TAG=${TAG#_}
LABEL=${LINE#*=}
LABEL=${LABEL#\"}
LABEL=${LABEL%\"}
LABEL="${LABEL%:}"
if [[ $TAG == @(auto|sync)_prop ]]
then
LABEL=${LABEL// /\ \;}
fi
[[ $TAG != *_lbl ]] && TAG=${TAG}_lbl
REPORT=${REPORT//\<%$TAG%\>/$LABEL}
if [[ $TAG == @(type|status|nodes|fses|mgrps|vgs|rdisks|tapes)_lbl ]]
then
: For messages that have a minor variation. No colon.
TAG="${TAG%_lbl}_nocolon_lbl"
LABEL=${LABEL/:\ \;/\ \;}
REPORT=${REPORT//\<%$TAG%\>/$LABEL}
fi
done
#============================================================
: Load the cluster-related information into the environment
#============================================================
VARS=$(grep -p "" $CDATA_FILE | grep =)
eval "$VARS"
typeset report_title=$(dspmsg -s $CLMGR_RPT_SET $CLMGR_MSGS 1 '"%1$s" Configuration' "$CLUSTER_NAME")
report_title="IBM PowerHA SystemMirror $report_title"
REPORT=${REPORT//\<%report_title%\>/$report_title}
report_title=${report_title//\<[bB][rR]?(\/)\>/ } # Eliminate " "
report_title=${report_title//\<+([a-zA-Z0-9\/])\>/} # Any other elems
REPORT=${REPORT//\<%browser_title%\>/$report_title}
if [[ -n $company_logo ]]; then
#=============================================================
# If no other protocol is already specified, and an absolute
# path was given, specify the "file" protocol, to ensure
# proper display.
#=============================================================
company_logo=${company_logo//\\//} # Convert Windows paths
if [[ $company_logo != @(file|http|https):* &&
$company_logo == @([a-zA-Z]:/|/)* ]]
then
company_logo="file://${company_logo//\\//}"
fi
company_logo="/$company_logo}
elif [[ -n $company_name ]]; then
REPORT=${REPORT//\<%company_logo%\>/\$company_name\}
else
REPORT=${REPORT//\<%company_logo%\>/}
fi
if [[ -n $snapshot ]]
then
typeset CAPTURE_DATE=""
if [[ -z $SNAPSHOTPATH || ! -d $SNAPSHOTPATH ]]; then
SNAPSHOTPATH=/usr/es/sbin/cluster/snapshots
fi
if [[ -f $SNAPSHOTPATH/$snapshot.odm && -s $SNAPSHOTPATH/$snapshot.odm ]]
then
CAPTURE_DATE=$(grep -w capture_date $SNAPSHOTPATH/$snapshot.odm)
CAPTURE_DATE=${CAPTURE_DATE#*=}
[[ -z $CAPTURE_DATE ]] && CAPTURE_DATE="???"
fi
REPORT=${REPORT//\<%date_time%\>/\$CAPTURE_DATE\}
else
REPORT=${REPORT//\<%date_time%\>/\$(date)\}
fi
typeset -i CONFIG_TOO_LONG=$MAX_EVENT_TIME
(( CONFIG_TOO_LONG += MAX_RG_PROCESSING_TIME ))
case $TYPE in
"LC") TYPE=$(dspmsg -s $CLMGR_RPT_SET $CLMGR_MSGS 3 "Linked") ;;
"SC") TYPE=$(dspmsg -s $CLMGR_RPT_SET $CLMGR_MSGS 4 "Stretched") ;;
"NSC") TYPE=$(dspmsg -s $CLMGR_RPT_SET $CLMGR_MSGS 5 "Standard") ;;
*) TYPE="" ;;
esac
#=======================================
# Eliminate items from the report that
# are not appropriate for this cluster
#=======================================
if [[ $HEARTBEAT_TYPE == "UNICAST" && \
$CLUSTER_TYPE != "LC" ]]
then
REPORT=${REPORT//\<%cluster_ip_lbl%\>/}
CLUSTER_IP=""
fi
if [[ $CLUSTER_TYPE == "NSC" ]]; then
REPORT=${REPORT/\<%sites_start%\>*\<%sites_end%\>*([[:space:]])/}
REPORT=${REPORT/\<%site_data1_start%\>*\<%site_data1_end%\>*([[:space:]])/}
REPORT=${REPORT/\<%site_data2_start%\>*\<%site_data2_end%\>*([[:space:]])/}
REPORT=${REPORT/\<%site_data3_start%\>*\<%site_data3_end%\>*([[:space:]])/}
SITE_HEARTBEAT_CYCLE=""
SITE_GRACE_PERIOD=""
SITE_POLICY_FAILURE_ACTION=""
SITE_POLICY_NOTIFY_METHOD=""
fi
#==================================================================
# Replace CLUSTER data targets within the report with data values
#==================================================================
for DATA in "cluster_name|CLUSTER_NAME|$CLUSTER_NAME" \
"cluster_type|TYPE|$TYPE" "ha_edition|EDITION|$EDITION" \
"ha_version|VERSION|$VERSION" "cluster_id|CLUSTER_ID|$CLUSTER_ID" \
"heartbeat_type|HEARTBEAT_TYPE|$HEARTBEAT_TYPE" \
"unsynced_changes|UNSYNCED_CHANGES|$UNSYNCED_CHANGES" \
"max_event_time|MAX_EVENT_TIME|$MAX_EVENT_TIME" \
"config_too_long|CONFIG_TOO_LONG|$CONFIG_TOO_LONG" \
"max_rg_proc_time|MAX_RG_PROCESSING_TIME|$MAX_RG_PROCESSING_TIME" \
"cluster_ip|CLUSTER_IP|$CLUSTER_IP" \
"daily_ver|DAILY_VERIFICATION|$DAILY_VERIFICATION" \
"ver_node|VERIFICATION_NODE|$VERIFICATION_NODE" \
"ver_hour|VERIFICATION_HOUR|$VERIFICATION_HOUR" \
"ver_debug|VERIFICATION_DEBUGGING|$VERIFICATION_DEBUGGING" \
"cluster_state|STATE|$STATE" \
"fc_sync_interval|FC_SYNC_INTERVAL|$FC_SYNC_INTERVAL" \
"rg_settling_time|RG_SETTLING_TIME|$RG_SETTLING_TIME" \
"rg_dist_policy|RG_DIST_POLICY|$RG_DIST_POLICY" \
\
"security_level|LEVEL|${LEVEL:--}" \
"security_algorithm|ALGORITHM|${ALGORITHM:--}" \
"security_refresh|REFRESH|${REFRESH:--}" \
"security_mechanism|MECHANISM|${MECHANISM:--}" \
"security_certificate|CERTIFICATE|${CERTIFICATE:--}" \
"security_key|PRIVATE_KEY|${PRIVATE_KEY:--}" \
\
"heartbeat_frequency|HEARTBEAT_FREQUENCY|${HEARTBEAT_FREQUENCY:--}" \
"grace_period|GRACE_PERIOD|${GRACE_PERIOD:--}" \
"site_heartbeat_cycle|SITE_HEARTBEAT_CYCLE|${SITE_HEARTBEAT_CYCLE:--}" \
"site_grace_period|SITE_GRACE_PERIOD|${SITE_GRACE_PERIOD:--}" \
\
"site_policy_failure_action|SITE_POLICY_FAILURE_ACTION|$SITE_POLICY_FAILURE_ACTION" \
"site_policy_notify_method|SITE_POLICY_NOTIFY_METHOD|$SITE_POLICY_NOTIFY_METHOD" \
\
"split_policy|SPLIT_POLICY|${SPLIT_POLICY:--}" \
"merge_policy|MERGE_POLICY|${MERGE_POLICY:--}" \
"action_plan|ACTION_PLAN|${ACTION_PLAN:--}" \
"nfs_quorum_server|NFS_QUORUM_SERVER|${NFS_QUORUM_SERVER:--}" \
"local_quorum_directory|LOCAL_QUORUM_DIRECTORY|${LOCAL_QUORUM_DIRECTORY:--}" \
"remote_quorum_directory|REMOTE_QUORUM_DIRECTORY|${REMOTE_QUORUM_DIRECTORY:--}" \
"tie_breaker|TIEBREAKER|${TIEBREAKER:--}" \
"notify_method|NOTIFY_METHOD|${NOTIFY_METHOD:--}" \
"notify_interval|NOTIFY_INTERVAL|${NOTIFY_INTERVAL:--}" \
"max_notify|MAXIMUM_NOTIFICATIONS|${MAXIMUM_NOTIFICATIONS:--}" \
"surviving_site|DEFAULT_SURVIVING_SITE|${DEFAULT_SURVIVING_SITE--}" \
"pprc_takeover|APPLY_TO_PPRC_TAKEOVER|${APPLY_TO_PPRC_TAKEOVER:--}" \
"snapshot_name|snapshot|$snapshot"
do
print -- "$DATA" | IFS=\| read TAG VAR VALUE
[[ -z $VALUE ]] && VALUE=" "
REPORT=${REPORT//\<%$TAG%\>/$VALUE}
: Free some memory, plus avoid any data mixups
[[ -n $VAR ]] && unset $VAR
done
#
: Save the constructed report into a temporary file for later processing
#
print -- "$REPORT" >$RP_FILE
)&
CHCR_CHILDREN="${CHCR_CHILDREN:+$CHCR_CHILDREN }$!"
if [[ -n $CHCR_CHILDREN ]]
then
#
: Wait for all the backgrounded processes to complete...
#
print -- "$CHCR_CHILDREN" > $TMPDIR/clmgr.KHvr.procs.$$
wait $CHCR_CHILDREN
fi
REPORT=$(cat $RP_FILE)
rm -f $RP_FILE
#
: Construct the PERL code that will be used to create the report
# ----
# NOTE: This was originally done in native ksh93 code instead of PERL.
# However, there were performance complaints, so PERL was tried
# to see if it would improve the performance. It did, by nearly
# 50%. Hence the reason for using PERL here instead of shell.
# ----
# $t holds the template, $r holds the report data
typeset PERL_CODE='my $t = join("", ); my $r = "";'
typeset DATA="" LABEL="" FILE=""
for DATA in site:$SITE_FILE \
node:$NODE_FILE \
rg:$RG_FILE \
rg_parent_child:$DEP_PC_FILE \
rg_start_after:$DEP_STARTA_FILE \
rg_stop_after:$DEP_STOPA_FILE \
rg_same_node:$DEP_SNODE_FILE \
rg_different_node:$DEP_DNODE_FILE \
rg_same_site:$DEP_SSITE_FILE \
rg_proc_seq:$RG_PROCSEQ_FILE \
network:$NW_FILE \
service_ip:$SIP_FILE \
interface:$IF_FILE \
vg:$VG_FILE \
lv:$LV_FILE \
mp:$MP_FILE \
fs:$FS_FILE \
pv:$PV_FILE \
repository:$REPOS_FILE \
tp:$TP_FILE \
mg:$MG_FILE \
sta:$STA_FILE \
sts:$STS_FILE \
mpair:$MPAIR_FILE \
mgrp:$MG_FILE \
ac:$AC_FILE \
am:$AM_FILE \
ev:$EV_FILE \
snapshot_method:$SS_METHODS_FILE \
verify_method:$VER_METHODS_FILE \
notify_method:$NT_METHODS_FILE \
fc:$FC_FILE
do
print -- "$DATA" | IFS=: read LABEL FILE
if [[ -e $FILE ]] # Avoid "-s" here, since we need to remove the placeholder tags from the template no matter what
then
if [[ $LABEL == rg_* ]]
then
: Dependencies use a different format for their tags
PERL_CODE="$PERL_CODE open my \$fh, '<', '$FILE'; \$r = join '', <\$fh>; close \$fh; \$t =~ s/\\s+<%${LABEL}_row_template_start%>.*<%${LABEL}_row_template_end%>//ms;"
if [[ $LABEL == *proc_seq* ]]
then # Processing order
PERL_CODE="$PERL_CODE \$t =~ s/\\s+<%rg_processing_sequence%>/\\\n\$r/ms;"
else # Dependencies
PERL_CODE="$PERL_CODE \$t =~ s/\\s+<%${LABEL}_dependencies%>/\\\n\$r/ms;"
fi
elif [[ $LABEL == rgglbl_* ]]
then
: RG global settings use a different format for their tags
PERL_CODE="$PERL_CODE open my \$fh, '<', '$FILE'; \$r = join '', <\$fh>; close \$fh; \$t =~ s/\\s+<%${LABEL}_start%>.*<%${LABEL}_end%>//ms; \$t =~ s/\\s+<%${LABEL}%>/\\\n\$r/ms;"
else
PERL_CODE="$PERL_CODE open my \$fh, '<', '$FILE'; \$r = join '', <\$fh>; close \$fh; \$t =~ s/\\s+<%${LABEL}_card_template_start%>.*<%${LABEL}_card_template_end%>//ms; \$t =~ s/\\s+<%${LABEL}_cards%>/\\\n\$r/ms;"
fi
TEMP_FILES=${TEMP_FILES:+$TEMP_FILES }$FILE
fi
done
if [[ -n $CL_SNAPSHOT ]]
then
PERL_CODE="$PERL_CODE open my \$fh, '<', '$INFO_FILE'; \$r = join '', <\$fh>; close \$fh; \$t =~ s/\\s+<%snapshot_info_content%>/\$r/ms;"
[[ -e $INFO_FILE ]] && TEMP_FILES=${TEMP_FILES:+$TEMP_FILES }$INFO_FILE
fi
#
: Create the report
#
REPORT=$(print -- "$REPORT" | perl -e "$PERL_CODE print \$t;")
[[ -n $TEMP_FILES ]] && rm -f "$TEMP_FILES" # Clean up
#=======================================================
: Remove any stray, unsubstituted replacement targets.
# I used PERL for this search-and-replace operation,
# because it was a LOT faster than using ksh93 for it.
#=======================================================
REPORT=$(print -- "$REPORT" | perl -pe 's|<\%.*?\%>||msg')
#===================================================
# Make sure any empty cells have at least on space
# in them, to make the table spacing more regular.
#===================================================
REPORT=${REPORT//\
\<\/TD\>/\
\ \;\
}
print -- "$REPORT" >$OUTFILE
fi
rm -f $CDATA_FILE
log_return_msg "$rc" "$0()" "$LINENO"
return $?
} # End of "create_html_report()"
#============================================================================
#
# Name: devDoc
#
# Description: This is a never-to-be-called, wrapper function that all the
# clmgr FPATH functions implement in order to hide embedded
# syntax from trace logging. This information is implemented
# in POD format, and can be viewed in a number of ways using
# POD tools. Some viewing suggestions for this function's POD-
# formatted information are:
#
# perldoc
# pod2text -c
# pod2text -c --code
# pod2html
#
# However, the more important use for this information is that
# it is parsed by clmgr to display the syntax for this file's
# operation. The information in the "SYNOPSIS" section is used
# for this purpose. This feature was originally implemented
# using the man page information. However, in a code review it
# was pointed out that this approach had to be changed because
# customers do not have to install the man pages! Therefore, a
# built-in dependency on man page information would break the
# automatic help feature of clmgr. So the SYNPOSIS section must
# be used instead.
#
# IMPORTANT: As a result of this, it is imperative that the
# information in this SYNOPSIS be kept in sync
# with the man page information, which is owned
# by the IDD team.
#
# Inputs: None.
#
# Outputs: None.
#
# Returns: n/a (not intended to be invoked)
#
#============================================================================
function devDoc {
: <<'=cut' >/dev/null 2>&1
=head1 NAME
KLIB_HACMP_view_report
=head1 SYNOPSIS
clmgr view report [] \
[ FILE= ] \
[ TYPE={text|html} ]
clmgr view report cluster
clmgr view report cluster \
TYPE=html \
[ FILE= ] \
[ COMPANY_NAME="" ] \
[ COMPANY_LOGO="" ]
clmgr view report snapshot \
SNAPSHOT= \
[ FILE= ]
clmgr view report {nodeinfo|rginfo|lvinfo|
fsinfo|vginfo|dependencies} \
[ TARGETS=[,,,...] ] \
[ FILE= ] \
[ TYPE={text|html} ]
clmgr view report repositories \
[ TYPE={text|html} ]
clmgr view report software \
[ TYPE={text|html} ]
clmgr view report availability \
[ TARGETS=[,,,...] ] \
[ FILE= ] \
[ TYPE={text|html} ] \
[ BEGIN_TIME="YYYY:MM:DD" ] \
[ END_TIME="YYYY:MM:DD" ]
clmgr view report roha \
[ TYPE={text|html} ]
NOTE: the currently supported reports are "basic", "cluster",
"status", "topology", "applications", "availability",
"events", "nodeinfo", "repositories", "rginfo", "networks",
"vginfo", "lvinfo", "fsinfo", "dependencies", "software" and "roha".
Some of these reports provide overlapping information, but
each also provides its own, unique information, as well.
NOTE: "MM" must be 1 - 12. "DD" must be 1 - 31.
NOTE: if no "BEGIN_TIME" is provided, then a report will be
generated for the last 30 days prior to "END_TIME".
NOTE: if no "END_TIME" is provided, then the current time will
be the default.
NOTE: the alias for "report" is "re".
=head1 DESCRIPTION
Runs and displays the specified report, in compliance with the provided
parameters. If a viable "FILE" location is specified, then the an attempt
is made to write the report to that file ,*overwriting* that file if it
already exists. In that case, no output is written to STDOUT. If "TYPE"
is specified, which defaults to plain text, then the report is displayed
in a format that is a bit more web browser friendly.
=head1 ARGUMENTS
1. report [REQUIRED] [string]
The label of the PowerHA report that is to be run and viewed.
2. file [OPTIONAL] [string]
The full path to a file in which to write the report (resulting
in the report *not* being displayed to STDOUT at all).
3. type [OPTIONAL] [string]
An indicator of what style to apply to the report output.
Valid values include: {text|html}
4. begin [OPTIONAL] [string]
An optional begin time, that *must* be properly formatted.
5. end [OPTIONAL] [string]
An optional end time, that *must* be properly formatted.
6. targets [OPTIONAL] [string]
A list of specific applications or nodes to query. Default is all.
=head1 RETURN
0: no errors were detected; the operation appears to have been successful
1: a general error has occurred
2: a specified resource does not exist, or could not be found
3: some required input was missing
4: some detected input was incorrect in some way
5: a required dependency does not exist
6: a specified search failed to match any data
=cut
} # End of "devDoc()"
#==============================================================================
# The following, comment block attempts to enforce coding standards when this
# file is edited via emacs or vim. This block _must_ appear at the very end
# of the file, or the editor will not find it, and it will be ignored.
#==============================================================================
# Local Variables:
# indent-tabs-mode: nil
# tab-width: 4
# End:
#==============================================================================
# vim: tabstop=4 shiftwidth=4 expandtab
#==============================================================================