#!/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="
" done INFO=$(print -- "$INFO" | tail -$(( LINES - $FIRST_STANZA )) | \ perl -pe 's|\n*()(
)|\1\2\n\n|; s|(COMMAND:)|\n \1|; s|\;()|\;\n\1|;') INFO="$INFO
" 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 #==============================================================================