# IBM_PROLOG_BEGIN_TAG # This is an automatically generated prolog. # # # # Licensed Materials - Property of IBM # # (C) COPYRIGHT International Business Machines Corp. 2000,2019 # All Rights Reserved # # US Government Users Restricted Rights - Use, duplication or # disclosure restricted by GSA ADP Schedule Contract with IBM Corp. # # IBM_PROLOG_END_TAG package ERRM_cli_utils; # sccsid = "@(#)43 1.49 src/rsct/rm/ER/cli/pm/ERRM_cli_utils.pm.perl, errmcli, rsct_rady, rady2035a 11/12/15 16:39:00" ###################################################################### # # # Package: ERRM_cli_utils.pm # # # # Description: # # This package contains utility/common subroutines for the # # Event Response Resource Manager (ERRM) CLI commands. # # # # Subroutines Available: # # # # error_exit - performs required cleanup and exits with the # # appropriate ERRM CLI error exit code. # # # # printCIMsg - print common informational message to STDOUT. # # Requires the program name and message mnemonic as inputs. # # # # printCEMsg - print common error message to STDERR. # # Requires the program name and message mnemonic as inputs. # # # # find_resource_name - find the resource name in a specified # # class to determine if it exists. # # Requires the resource name and class as inputs. # # # # find_resource_handle - find the resource handle in the # # Association class to determine if it exists. # # Requires the resource handle and original class as inputs. # # # # find_association_handle - find the condition and response # # handles in the Association class to determine if it exists. # # Requires the condition and response handles as inputs. # # # # get_handle - find the handle for a resource name. # # Requires the resource name and class as inputs. # # # # get_assoc_handles - find the Association class handles and # # active flags for a condition and/or response handle. # # Requires condiion handle and/or response handle. # # # # parse_days_string - parse the day string for the response # # commands. # # Requires the specified day string as input. # # # # parse_time_string - parse the time string for the response # # commands. # # Requires the specified time string as input. # # # # get_source_node - returns a string that is the resolved node # # name of this node (the node the command is running on). # # No parameters. # # # # resolve_node - returns a string that is the resolved node name # # of an input node name. # # Requires the node name to resolve. # # # # get_locator_node - returns the resource name and it's locator # # node from a resource name/locator combination. # # Requires the resource name. # # # # process_monitor_status - returns the MonitorStatus portion of # # the MonitorStatus SD and its description. # # Requires the MonitorStatus SD and the text description hash. # # # # process_active_status - returns the translated value of the # # association active flag. # # Requires the active flag value and the text description hash. # # # # set_orig_rmc_scope - sets CT_MANAGEMENT_SCOPE back to the value # # it originally had when the ERRM command was invoked. # # # # check_set_cluster_scope - checks CT_MANAGEMENT_SCOPE to see if # # it is valid for a cluster operation. If not, it is set to # # DM/SR/Local scope. # # # # find_names_from_assoc - finds condition and response names from # # Association handle. # # # # change_locked_attr - changes the locked attribute for an ERRM # # resource. # # Requires lock value, locator, class, resource. # # # # process_exit_code - returns either 0, the signal exit code, # # or the process error code for the called process. # # Requires the exit code to examine. # # # # process_api_error - extracts and prints errors from the output # # of a c-api command (mkrsrc-api, etc..). # # Requires the command output including STDERR. # # # # remove_api_error - removes error messages from the output of a # # c-api command (mkrsrc-api, etc..). # # Requires the command output including STDERR. # # # # escape_selstr - modify a selection string so that special SQL # # characters are escaped in the string so they do not perform # # special SQL functions (%#_). # # # # in_cluster - returns true if in a cluster, false if not. # # No parameters. # # # # getIMsg - returns the text of a message. Used for NLS. # # Requires the program name and message mnemonic as inputs. # # # # Examples: # # printCEMsg("EMsgCUcliBadOperand", $rsrc_class); # # # #--------------------------------------------------------------------# # Inputs: # # /opt/rsct/msgmaps/errmcli.errmcli.map - message mapping # # # # Outputs: # # stdout - common informational messages that get displayed. # # stderr - common error messages that get displayed. # # # # External References: # # Commands: ctdspmsg # # # # Tab Settings: # # 4 and tabs should be expanded to spaces before saving this file. # # in vi: (:set ts=4 and :%!expand -4) # # # # Change Activity: # # 000921 JAC 67664: Initial design & write. # # 001013 JAC 67469: Add varaibles for condition commands. # # 010102 JAC 67470: Updates for mk and rm commands. # # 010119 JAC 67471: Updates for start and stop commands. # # 010215 JAC 71203: Fix parse_days_string when in a date range. # # 010308 JAC 71005: Escape some special characters in strings. # # 010420 JAC 73421: Change get_handle to check for null handle. # # (above should have been part of 72894) # # 010501 JAC 73619: Do not send any RMC CLI std err to garbage. # # 010507 JAC 73620: Check for RMC CLI user error (rc=5) and # # return ERRM user error for this case. # # 011119 JAC 77597: Changes for distributed RMC # # 011128 JAC 77596: Add routine to process MonitorStatus attribute.# # 011206 JAC 78841: Fix selection strings for specifying locator. # # 011213 JAC 78976: Fix selection strings for specifying locator. # # 020121 JAC 79558: Fix selection strings for specifying locator. # # 020128 JAC 79559: Add constant for rmc local scope. # # 020208 JAC 71728: Add NLS support for headers and xlating values.# # 020411 JAC 81754: Add signal checking and switch to xxx-api. # # 020424 JAC 81488: Modify in_cluster routine. # # 020425 JAC 82407: Fix return code from get_assoc_handles. # # 020428 JAC 82364: Change mgt scopes to l,d,p from l,c,s. # # 020523 JAC 83318: Fix in_cluster to ignore IBM.Host errors and # # do not resolve hostname in get_soure_node. # # 020603 JAC 83676: Set local scope before listing IBM.Host. # # 020607 JAC 83317: Change process_exit_code to write error msg # # if a signal has occurred. # # 020719 JAC 84425: Add $rc to process_api_error. # # 020723 JAC 85048: Fix parse_time_string changing gt to >. # # 020725 JAC 85139: Count not found error in process_api_error. # # 020725 JAC 84654: Change mgt scopes to l,m,p from l,d,p. # # 020729 JAC 85061: Add check_set_cluster_scope to use 4 (DM/SR/ # # local) for scope if scope not set. # # 030610 JAC 95615: Add support for locked attribute. # # 030619 JAC 96060: Add function to change locked attribute. # # 040408 JAC 105863: Use unescape_chars to change \\\" to \". # # 040428 JAC 108194: Add escape_selstr function. # # 071016 JAC 146726: Set delimiter for -api calls. # # 080104 JAC 148354: Don't export resolve_node. # # 081103 JAC 153203: Add error events. # ###################################################################### use Exporter (); @ISA = qw(Exporter); @EXPORT_OK = qw( error_exit printCIMsg printCEMsg find_resource_name find_resource_handle find_association_handle find_names_from_assoc get_handle get_assoc_handles parse_days_string parse_time_string get_source_node get_locator_node process_monitor_status process_active_status set_orig_rmc_scope process_exit_code process_api_error remove_api_error check_set_cluster_scope change_locked_attr getIMsg in_cluster escape_selstr $TRUE $FALSE $CTDIR $CTBINDIR $MKRSRC $RMRSRC $CHRSRC $LSRSRC $RUNACT $RSCCOND $RSCEVRS $RSCASSC $MKCNDCRIT $MKCNDWARN $MKCNDINFO $SEVCRIT $SEVWARN $SEVINFO $DELIMITERI $DELIMITERO $RMC_CLI_USER_ERROR $RMC_CLI_RSRC_NOT_FOUND @EVENTTYPE @EVENTTPCD $GARBAGE $LSNOTFND $STARTMON $STOPMON $LCL_SCOPE $LCL_SCOPE_VAL $SR_SCOPE $SR_SCOPE_VAL $SR_SCOPE_OLD $CSM_SCOPE $CSM_SCOPE_VAL $CSM_SCOPE_OLD $CSM_SCOPE_OLD2 $MAX_UINT32 $EVENT_BATCHING_ON $EVENT_BATCHING_OFF $RMC_LOCAL_SCOPE ); use lib "/opt/rsct/pm"; use locale; use CT_cli_input_utils qw(unescape_chars); use ERRM_cli_rc qw(ERRM_CLI_RMC_ERROR ERRM_CLI_ERROR ERRM_CLI_BAD_FLAG ERRM_CLI_BAD_OPERAND ERRM_CLI_USER_ERROR); #--------------------------------------------------------------------# # Global Variables # #--------------------------------------------------------------------# $MSGCAT = "errmcli.cat"; # msg catalogue for this cmd $MSGSET = "errmcli"; # common message set $CTDIR = "/opt/rsct"; # RSCT root directory $CTBINDIR = "$CTDIR/bin"; # Cluster Bin directory path $LSMSG = "$CTBINDIR/ctdspmsg"; # list / display message rtn $ENV{'MSGMAPPATH'} = "$CTDIR/msgmaps"; # msg maps used by $LSMSG $MKRSRC = "mkrsrc"; # RMC make resource command $RMRSRC = "rmrsrc"; # RMC remove resource command $CHRSRC = "chrsrc"; # RMC change resource command $LSRSRC = "lsrsrc"; # RMC list resource command $RUNACT = "runact"; # RMC run action command $RSCCOND = "IBM.Condition"; # Condition Resource class name $RSCEVRS = "IBM.EventResponse"; # Event Resp Resource class $RSCASSC = "IBM.Association"; # Association Resource class $LSNOTFND = 0; # number of last index on # lsrsrc if no condition found $MKCNDCRIT = 2; # sev for mkcond critical $MKCNDWARN = 1; # sev for mkcond warning $MKCNDINFO = 0; # sev for mkcond informational $SEVCRIT = "c"; # sev for mkcond critical flag $SEVWARN = "w"; # sev for mkcond warning flag $SEVINFO = "i"; # sev for mkcond info flag $DAYSNUM = "1234567"; # days of the week (1=Sun) @DAYSNUMCD = (1,2,4,8,16,32,64); # bit map for days encoded @EVENTTYPE = ("a","r","b","e","A"); # event types for mkresp @EVENTTPCD = (1,2,3,4,7); # encoded types for mkresp $STARTMON = 1; # start monitoring condition $STOPMON = 0; # stop monitoring condition $DELIMITERI = "tvitvitvi"; # input delimiter to use $DELIMITERO = "tvotvotvo"; # output delimiter to use $GARBAGE = "/dev/null"; # place to put garbage $RMC_CLI_USER_ERROR = 5; # to check for RMC CLI user error $RMC_CLI_RSRC_NOT_FOUND = 6; # resource not found error $LCL_SCOPE = "l"; # -m local scope $SR_SCOPE = "p"; # -m shared resource cluster scope $CSM_SCOPE = "m"; # -m csm scope $SR_SCOPE_OLD = "s"; # -m shared resource cluster scope $CSM_SCOPE_OLD = "c"; # -m csm scope $CSM_SCOPE_OLD2 = "d"; # -m csm scope $LCL_SCOPE_VAL = 1; # attribute value for local $SR_SCOPE_VAL = 2; # attribute value for sr $CSM_SCOPE_VAL = 4; # attribute value for csm $RMC_LOCAL2_SCOPE = 0; # local management scope $RMC_LOCAL_SCOPE = 1; # rmc local management scope $RMC_SR_SCOPE = 2; # SR management scope $RMC_DM_SCOPE = 3; # DM management scope $RMC_DM_SR_LOCAL_SCOPE = 4; # DM/SR/local management scope $MAX_UINT32 = 4294967295; # max unsigned i32 $EVENT_BATCHING_ON = 1; # turn event batching on $EVENT_BATCHING_OFF = 0; # turn event batching off $FALSE = 0; $TRUE = 1; #--------------------------------------------------------------------# # Exported Subroutines (with @EXPORT_OK, -> on demand). # #--------------------------------------------------------------------# #--------------------------------------------------------------------# # Common message handling (error, informational) routines: # #--------------------------------------------------------------------# #--------------------------------------------------------------------# # error_exit - performs required cleanup and exits. # # Parameters: # # $badrc in Bad return code - bad enough to exit # # processing of this command. # # Exit: # # 1 ERRM_CLI_RMC_ERROR Underlying RMC error. # # 2 ERRM_CLI_ERROR Unexpected error in the command script.# # 3 ERRM_CLI_BAD_FLAG Input flag error. # # 4 ERRM_CLI_BAD_OPERAND Input operand error. # # 5 ERRM_CLI_USER_ERROR User error. # # # # Global References: # # $main::Cleanup. in Hash indicating what needs to be # # cleaned up. # # if {Session} defined - value is # # session that must terminate. # # terminate. # #--------------------------------------------------------------------# sub error_exit { my ($badrc) = @_; SWITCH: { ($badrc == ERRM_CLI_RMC_ERROR) && exit($badrc); ($badrc == ERRM_CLI_ERROR) && exit($badrc); ($badrc == ERRM_CLI_BAD_FLAG) && exit($badrc); ($badrc == ERRM_CLI_BAD_OPERAND) && exit($badrc); ($badrc == ERRM_CLI_USER_ERROR) && exit($badrc); # At this point all return codes should have been converted to # a valid ERRM CLI return code. But if one wasn't write an # error message. printCEMsg("EMsgERRMcliBadRC", $badrc); exit(ERRM_CLI_ERROR); } # end switch } # end error_exit #--------------------------------------------------------------------# # printCIMsg : Calls $LSMSG to print out the common cluster # # ERRM CLI information messages with the required parameters. # # Messages printed to stdout. # # This subroutine is like printIMsg except it is used to print # # the common ERRM CLI messages which are in the errmcli message # # set. # # # # Parameters: # # $msg in Message mnemonic / message number in a sense. # # $optargs in Extra arguments/parameters to send to $LSMSG. # # # # Returns: None. # # # # Global Variables: # # $main::Trace in Prints extra info when trace is on. # # $LSMSG in Path & Command to display messages. # # $MSGCAT in MC CLI Message catalogue. # # $MSGSET in MC CLI common message set "mccli". # #--------------------------------------------------------------------# sub printCIMsg { my ($msg, @optargs) = @_; my ($optarg, $optargs); $main::Trace && print STDERR "$LSMSG $MSGSET $MSGCAT $msg @optargs\n"; # Keep the args to LSMSG separate by separating with single quotes # but must replace internal single quotes with blanks or get an error. # Must escape internal double quotes for the system call. foreach $optarg (@optargs) { $optarg =~ s/'/\/g; $optarg =~ s/"/\\"/g; } $optargs = "'" . join("' '",@optargs) . "'"; (scalar @optargs > 0) ? system "$LSMSG $MSGSET $MSGCAT $msg $optargs | /bin/sed \"s/\/'/g\"" : system "$LSMSG $MSGSET $MSGCAT $msg"; return; } # end printCIMsg #--------------------------------------------------------------------# # printCEMsg : Calls $LSMSG to print out the common cluster # # ERRM CLI error messages with the required parameters. # # Messages printed to stderr. # # This subroutine is like printEMsg except it is used to print # # the common ERRM CLI messages which are in the errmcli message # # set and it prefixes the message with the appropriate program # # name. # # # # Parameters: # # $msg in Message mnemonic / message number in a sense. # # $optargs in Extra arguments/parameters to send to $LSMSG. # # # # Returns: None. # # # # Global Variables: # # $main::PROGNAME in Calling program/command for error message. # # $main::Trace in Prints extra info when trace is on. # # $LSMSG in Path and command to display messages. # # $MSGCAT in CU CLI Message catalogue. # # $MSGSET in CU CLI common message set "cucli". # #--------------------------------------------------------------------# sub printCEMsg { my ($msg, @optargs) = @_; my ($optarg, $optargs); $main::Trace && print STDERR "$LSMSG $MSGSET $MSGCAT $msg $main::PROGNAME @optargs\n"; # Keep the args to LSMSG separate by separating with single quotes # but must replace internal single quotes with blanks or get an error. # Must escape internal double quotes for the system call. foreach $optarg (@optargs) { $optarg =~ s/'/\/g; $optarg =~ s/"/\\"/g; } $optargs = "'" . join("' '",@optargs) . "'"; (scalar @optargs > 0) ? system "$LSMSG $MSGSET $MSGCAT $msg $main::PROGNAME $optargs | /bin/sed \"s/\/'/g\" 1>&2" : system "$LSMSG $MSGSET $MSGCAT $msg $main::PROGNAME 1>&2"; return; } # end printCEMsg #--------------------------------------------------------------------# # find_resource_name : Uses the list resource RMC CLI command to # # determine if a condition name or response name exists. It is # # determined to exist if there is information returned from the # # list command. # # # # Parameters: # # $resource_name the condition or response name to find # # the resource name may or may not be followed # # by :Node_name. # # $resource_class the class to look in (Condition, EventResponse) # # $resource_loc the location or node to look on for the resource# # # # Returns: # # 0 if the name is found # # -1 if the name is not found # # ERRM_CLI_USER_ERROR if there was an RMC_CLI_USER_ERROR # # # # Global Variables: # # $main::Trace in case trace is on # # $main::PROGNAME for trace message # # $CTBINDIR where list command resides # # $LSRSRC RMC CLI list command # # $LSNOTFND number of output line for name not found # #--------------------------------------------------------------------# sub find_resource_name { my $resource_name = shift(@_); my $resource_class = shift(@_); my $resource_loc = shift(@_); my @listout = (); my $trace_opt = ""; my $node_select = ""; my $rc = 0; # re-establish original CT_MANAGEMENT_SCOPE &set_orig_rmc_scope; # check to see if resource name has a Node_name to locate it. # if not, set rmc local scope. if it does, use it in select string. if ($resource_loc eq "") { # set CT_MANAGEMENT_SCOPE to local for query $ENV{CT_MANAGEMENT_SCOPE} = $RMC_LOCAL_SCOPE; } # else use location is select string else { $node_select = " && NodeNameList |< {\\\"$resource_loc\\\"}"; # use DM/SR/Local scope if scope not set and there's a locator &check_set_cluster_scope; } $main::Trace && print STDERR "$main::PROGNAME: calling lsrsrc-api\n"; $main::Trace && ($trace_opt = " -T "); # determine if the resource exists #@listout = `$CTBINDIR/$LSRSRC $trace_opt -x -s "Name == \\\"$resource_name\\\" $node_select" $resource_class`; @listout = `$CTBINDIR/lsrsrc-api -I $DELIMITERI -D $DELIMITERO -s ${resource_class}${DELIMITERI}\"Name==\\\"$resource_name\\\"$node_select\"${DELIMITERI}${DELIMITERI}${DELIMITERI}Name 2>&1`; $rc = $?; $rc = &process_exit_code($rc); $main::Trace && print STDERR "lsrsrc-api results:\n"; $main::Trace && print STDERR "@listout"; $main::Trace && print STDERR "$main::PROGNAME: lsrsrc-api returned $rc\n"; # show any errors if there was a bad rc except for not found if (($rc != 0) && ($rc != $RMC_CLI_RSRC_NOT_FOUND)) { &process_api_error($DELIMITERO,$rc,@listout); } # return ERRM CLI user error if it's an RMC CLI user error if ($rc == $RMC_CLI_USER_ERROR) { exit(ERRM_CLI_USER_ERROR);} # return -1 if resource not found if ($rc == $RMC_CLI_RSRC_NOT_FOUND) { return(-1); } # if list command failed, print RMC error message and exit if ($rc != 0) { exit(ERRM_CLI_RMC_ERROR); } # must have been found return (0); } #--------------------------------------------------------------------# # find_resource_handle : Uses the list resource RMC CLI command to # # determine if a condition or response handle exists in the # # Association resource class. # # # # Parameters: # # $resource_handle the condition or response handle to find # # $resource_type "c" for condition, "r" for response # # $locator where condition is # # # Returns: # # 0 if the handle is found in the Association class # # -1 if the handle is not found # # ERRM_CLI_USER_ERROR if lsrsrc returns RMC_CLI_USER_ERROR # # # # Global Variables: # # $main::Trace in case trace is on # # $main::PROGNAME for trace message # # $CTBINDIR where list command resides # # $LSRSRC RMC CLI list command # # $RSCASSC Association class # # $LSNOTFND number of output line for name not found # #--------------------------------------------------------------------# sub find_resource_handle { my $resource_handle = shift(@_); my $resource_type = shift(@_); my $locator = shift(@_); my @listout = (); my $trace_opt = ""; my $node_select = ""; my $rc = 0; # re-establish original CT_MANAGEMENT_SCOPE &set_orig_rmc_scope; # check to see if locator has a Node_name to locate it. # if not, set rmc local scope. if it does, use it in select string. if ($locator eq "") { # set CT_MANAGEMENT_SCOPE to local for query $ENV{CT_MANAGEMENT_SCOPE} = $RMC_LOCAL_SCOPE; } # else use location is select string else { $node_select = " && NodeNameList |< {\\\"$locator\\\"}"; # use DM/SR/Local scope if scope not set and there's a locator &check_set_cluster_scope; } # get rid of quotes in handle $resource_handle =~ s/"//g; $main::Trace && print STDERR "$main::PROGNAME: calling lsrsrc-api\n"; $main::Trace && ($trace_opt = " -T "); # list resource_name using the RMC CLI list command to see if it exists if ($resource_type eq "c") { # @listout = `$CTBINDIR/$LSRSRC $trace_opt -x -s "ConditionHandle==\\\"$resource_handle\\\" $node_select" $RSCASSC`; @listout = `$CTBINDIR/lsrsrc-api -I $DELIMITERI -D $DELIMITERO -s ${RSCASSC}${DELIMITERI}\"ConditionHandle==\\\"$resource_handle\\\"$node_select\"${DELIMITERI}${DELIMITERI}${DELIMITERI}ConditionHandle 2>&1`; $rc = $?; } else { # @listout = `$CTBINDIR/$LSRSRC $trace_opt -x -s "EventResponseHandle==\\\"$resource_handle\\\" $node_select" $RSCASSC`; @listout = `$CTBINDIR/lsrsrc-api -I $DELIMITERI -D $DELIMITERO -s ${RSCASSC}${DELIMITERI}\"EventResponseHandle==\\\"$resource_handle\\\"$node_select\"${DELIMITERI}${DELIMITERI}${DELIMITERI}EventResponseHandle 2>&1`; $rc = $?; } $rc = &process_exit_code($rc); $main::Trace && print STDERR "lsrsrc-api results:\n"; $main::Trace && print STDERR "@listout"; $main::Trace && print STDERR "$main::PROGNAME: lsrsrc-api returned $rc\n"; # show any errors if there was a bad rc except for not found if (($rc != 0) && ($rc != $RMC_CLI_RSRC_NOT_FOUND)) { &process_api_error($DELIMITERO,$rc,@listout); } # return ERRM CLI user error if it's an RMC CLI user error if ($rc == $RMC_CLI_USER_ERROR) { exit(ERRM_CLI_USER_ERROR);} # return -1 if resource not found if ($rc == $RMC_CLI_RSRC_NOT_FOUND) { return(-1); } # if list command failed, print RMC error message and exit if ($rc != 0) { exit(ERRM_CLI_RMC_ERROR); } # must have been found return (0); } #--------------------------------------------------------------------# # find_association_handle : Uses the list resource RMC CLI command # # to determine if a condition/response handle exists in the # # Association resource class. # # # # Parameters: # # $cond_handle the condition handle # # $resp_handle the response handle # # $locator where the condition/response is defined # # # # Returns: # # 0 if the condition/response handles are found # # in the Association class # # -1 if the handle is not found # # ERRM_CLI_USER_ERROR if RMC_CLI_USER_ERROR # # # # Global Variables: # # $main::Trace in case trace is on # # $main::PROGNAME for trace message # # $CTBINDIR where list command resides # # $LSRSRC RMC CLI list command # # $RSCASSC Association class # # $LSNOTFND number of output line for name not found # #--------------------------------------------------------------------# sub find_association_handle { my $cond_handle = shift(@_); my $resp_handle = shift(@_); my $locator = shift(@_); my @listout = (); my $trace_opt = ""; my $node_select = ""; my $rc = 0; # get rid of quotes in handles $cond_handle =~ s/"//g; $resp_handle =~ s/"//g; # re-establish original CT_MANAGEMENT_SCOPE &set_orig_rmc_scope; # check to see if resource name has a Node_name to locate it. # if not, set rmc local scope. if it does, use it in select string. if ($locator eq "") { # set CT_MANAGEMENT_SCOPE to local for query $ENV{CT_MANAGEMENT_SCOPE} = $RMC_LOCAL_SCOPE; } # else use location is select string else { $node_select = " && NodeNameList |< {\\\"$locator\\\"}"; # use DM/SR/Local scope if scope not set and there's a locator &check_set_cluster_scope; } $main::Trace && print STDERR "$main::PROGNAME: calling lsrsrc-api\n"; $main::Trace && ($trace_opt = " -T "); # check to see if the condition - resource are already in Association #@listout = `$CTBINDIR/$LSRSRC $trace_opt -x -s "ConditionHandle==\\\"$cond_handle\\\" && EventResponseHandle==\\\"$resp_handle\\\" $node_select" $RSCASSC`; @listout = `$CTBINDIR/lsrsrc-api -I $DELIMITERI -D $DELIMITERO -s ${RSCASSC}${DELIMITERI}\"ConditionHandle==\\\"$cond_handle\\\" && EventResponseHandle==\\\"$resp_handle\\\"$node_select\"${DELIMITERI}${DELIMITERI}${DELIMITERI}ResourceHandle 2>&1`; $rc = $?; $rc = &process_exit_code($rc); $main::Trace && print STDERR "lsrsrc-api results:\n"; $main::Trace && print STDERR "@listout"; $main::Trace && print STDERR "$main::PROGNAME: lsrsrc-api returned $rc\n"; # show any errors if there was a bad rc except for not found if (($rc != 0) && ($rc != $RMC_CLI_RSRC_NOT_FOUND)) { &process_api_error($DELIMITERO,$rc,@listout); } # return ERRM CLI user error if it's an RMC CLI user error if ($rc == $RMC_CLI_USER_ERROR) { exit(ERRM_CLI_USER_ERROR);} # return -1 if resource not found if ($rc == $RMC_CLI_RSRC_NOT_FOUND) { return(-1); } # if list command failed, print RMC error message and exit if ($rc != 0) { exit(ERRM_CLI_RMC_ERROR); } # must have been found return (0); } #--------------------------------------------------------------------# # get_handle: Obtain the resource handle for the named resource in # # the class given. Uses the RMC CLI lsrsrc command. # # # # Parameters: # # $resource_name the existing condition or response name # # $resource_class the class to look in (Condition, EventResponse) # # $locator the node to look on # # # # Returns: # # $rc 0 if resource handle found # # ERRM_CLI_USER_ERROR if RMC_CLI_USER_ERROR # # $resource_handle the resource handle # # # # Global Variables: # # $main::Trace in case trace is on # # $main::PROGNAME for trace message # # $CTBINDIR where list command resides # # $LSRSRC RMC CLI list command # #--------------------------------------------------------------------# sub get_handle { my $resource_name = shift(@_); my $resource_class = shift(@_); my $locator = shift(@_); my $resource_handle = ""; my $node_select = ""; my @listout = (); my $rc = 0; # re-establish original CT_MANAGEMENT_SCOPE &set_orig_rmc_scope; # check to see if resource name has a Node_name to locate it. # if not, set rmc local scope. if it does, use it in select string. if ($locator eq "") { # set CT_MANAGEMENT_SCOPE to local for query $ENV{CT_MANAGEMENT_SCOPE} = $RMC_LOCAL_SCOPE; } # else use location is select string else { $node_select = " && NodeNameList |< {\\\"$locator\\\"}"; # use DM/SR/Local scope if scope not set and there's a locator &check_set_cluster_scope; } $main::Trace && print STDERR "$main::PROGNAME: calling lsrsrc-api\n"; # list resource_name using the RMC CLI list command to get the handle #$resource_handle = `$CTBINDIR/$LSRSRC -t -x -s "Name == \\\"$resource_name\\\" $node_select" $resource_class ResourceHandle`; @listout = `$CTBINDIR/lsrsrc-api -I $DELIMITERI -D $DELIMITERO -s ${resource_class}${DELIMITERI}\"Name==\\\"$resource_name\\\"$node_select\"${DELIMITERI}${DELIMITERI}${DELIMITERI}ResourceHandle 2>&1`; $rc = $?; $rc = &process_exit_code($rc); $main::Trace && print STDERR "lsrsrc-api results:\n"; $main::Trace && print STDERR "@listout"; $main::Trace && print STDERR "$main::PROGNAME: lsrsrc-api returned $rc\n"; # show any errors if there was a bad rc except for not found if (($rc != 0) && ($rc != $RMC_CLI_RSRC_NOT_FOUND)) { &process_api_error($DELIMITERO,$rc,@listout); } # return ERRM CLI user error if it's an RMC CLI user error if ($rc == $RMC_CLI_USER_ERROR) { exit(ERRM_CLI_USER_ERROR);} # return -1 if resource not found if ($rc == $RMC_CLI_RSRC_NOT_FOUND) { return (-1,""); } # if list command failed, print RMC error message and exit if ($rc != 0) { exit(ERRM_CLI_RMC_ERROR); } # must have been found $resource_handle = $listout[0]; chomp($resource_handle); $resource_handle = "\"".$resource_handle."\""; return (0,$resource_handle); } #--------------------------------------------------------------------# # parse_days_string - Parse the days of the week string returning # # the encoded days for the Actions attribute of EventResponse. # # The default of 1-7 is filled in if no value is specified (for # # example: 3,4,,8.) # # # # Input: # # $days_string valid user input for -d # # Return: # # $ndays the number of coded days found # # $days_code the coded days value # # # #--------------------------------------------------------------------# sub parse_days_string { my $days_string = shift @_; # input days string my $ndays = 0; # count the number of coded days my $days_code = ""; # will return coded days my $day = ""; # part of $day_string my $lendays = 0; # length of $days_string my $range = $FALSE; # looks for a - in $days_string my $tot_code = 0; # keeps count of coded days my $i = 0; # loop counter my $k = 0; # loop counter my $pos = 0; # find coded values my $range_num = 0; # next number for range my $comma = ""; # when >1 days, need a comma # look for any ,, used. Fill them in with 1-7 (default) while($days_string =~ /,,/) { $days_string =~ s/,,/,1-7,/;} # find the length of day string $lendays = length $days_string; # look for an ending comma. Fill in with 1-7 (default) if (substr($days_string,$lendays-1,1) eq ",") { $days_string = $days_string . "1-7"; } # look for a beginning comma. Fill in with 1-7 (default) if (substr($days_string,0,1) eq ",") { $days_string = "1-7" . $days_string; } # make sure we have the corrected length of day string $lendays = length $days_string; # loop looking at each character in day string. # make sure it's 1-7, a -, or a comma and process accordingly. for ($i=0;$i<$lendays;$i++){ $day = substr($days_string,$i,1); # is day character a number 1 to 7? if ($day =~ /[1-7]/){ # it's a number. are we in a range that was specified? if ($range){ # it's in a range. is the next number in the range valid? if ($day lt $range_num) { # 71203 lt, not le printCEMsg("EMsgERRMcliImproperUsageOperand","-d"); exit(ERRM_CLI_USER_ERROR); } # in a valid range, add days until we come to the end of the range for ($k=$range_num;$k<=$day;$k++){ $pos = index $DAYSNUM,$k; # determine coded value $tot_code = $tot_code + $DAYSNUMCD[$pos]; # add to total } $range = $FALSE; # reset back after processing done } # it's a number, but not part of a range else { $pos = index $DAYSNUM,$day; # determine coded value $tot_code = $tot_code + $DAYSNUMCD[$pos]; # add to total } # in case this is the start of a range, keep track of what should be next $range_num = $day + 1; } # end of if it's 1-7 # is day character a hyphen? elsif ($day eq "-") { # if we're in a range, it can't be a hyphen if ($range) { printCEMsg("EMsgERRMcliImproperUsageOperand","-d"); exit(ERRM_CLI_USER_ERROR); } # set the range flag so we know we're in a range specification $range = $TRUE; } # end of it's a hyphen # is day character a plus? (multiple days but not a range) elsif ($day eq "+") { # don't need to do anything. move on to next day . } # end of it's a plus # is day character a comma? elsif ($day eq ",") { # if we're in a range, it can't be a comma if ($range) { printCEMsg("EMsgERRMcliImproperUsageOperand","-d"); exit(ERRM_CLI_USER_ERROR); } # end of previous day specification. concatenate to coded string and # reset some things $days_code = $days_code . $comma . $tot_code; $tot_code = 0; $range = $FALSE; $comma = ","; $ndays++; # count the number of coded values } # end of it's a comma # an invalid character else { printCEMsg("EMsgERRMcliImproperUsageOperand","-d"); exit(ERRM_CLI_USER_ERROR); } } # add the last coded value to the coded value string $days_code = $days_code . $comma . $tot_code; $ndays++; # count the last value return ($ndays,$days_code); } #--------------------------------------------------------------------# # parse_time_string - Parse the times of the day string returning # # the encoded times for the Actions attribute of EventResponse. # # The default of 0000-2400 is filled in if no value is specified # # (for example: 0800-1600,,0800-1800) # # # # Input: # # $time_string valid user input for -t # # Return: # # $ntimes the number of coded times found # # $start_time the coded start times # # $end_time the coded end times # # # #--------------------------------------------------------------------# sub parse_time_string { my $time_string = shift @_; # input times string my $time_code = 0; # coded time my $ntimes = 0; # number of coded times my $start_time = ""; # coded start times my $end_time = ""; # coded end times my $this_is_start_time = $TRUE; # flag to know what time my $hhmm = ""; # substring of time_string my $hours = ""; # substring of hhmm my $minutes = ""; # substring of hhmm my $lentime = 0; # length of time_string my $i = 0; # loop counter my $prev_start_time = 0; # remember start time my $comma = ""; # separates multiple times # look for ending any comma. Fill in with 0000-2400 (default) while($time_string =~ /,,/) { $time_string =~ s/,,/,0000-2400,/; } # get the length of the time string $lentime = length $time_string; # look for ending comma. Fill in with 0000-2400 (default) if (substr($time_string,$lentime-1,1) eq ",") { $time_string = $time_string . "0000-2400"; } # look for beginning comma. Fill in with 0000-2400 (default) if (substr($time_string,0,1) eq ",") { $time_string = "0000-2400" . $time_string; } # get possibly new length $lentime = length $time_string; # loop through time string pulling off start and stop time. # validate the times and convert to coded times for ($i=0;$i<$lentime;$i=$i+5){ if ($i>=10) { $comma = ",";} # have >1 time specified # check the time format (hh:mm). enough characters? if ( ($i+3)>($lentime-1) ) { printCEMsg("EMsgERRMcliImproperUsageOperand","-t"); exit(ERRM_CLI_USER_ERROR); } # get a time $hhmm = substr($time_string,$i,4); # extract the hours and check them $hours = substr($hhmm,0,2); if ($hours lt "00" | $hours gt "24") { printCEMsg("EMsgERRMcliImproperUsageOperand","-t"); exit(ERRM_CLI_USER_ERROR); } # extract the times and check them $minutes = substr($hhmm,2,2); if ($minutes lt "00" | $minutes gt "59") { printCEMsg("EMsgERRMcliImproperUsageOperand","-t"); exit(ERRM_CLI_USER_ERROR); } # calculate the coded time in seconds $time_code = ($hours * 60 * 60) + ($minutes * 60); # for start time, add to coded start times and save to compare # against the end time if ($this_is_start_time){ $this_is_start_time = $FALSE; $start_time = $start_time . $comma . $time_code; $prev_start_time = $time_code; } # for end time, verify it's more than start time, then add to # coded end times. else { if ($prev_start_time > $time_code) { printCEMsg("EMsgERRMcliImproperUsageOperand","-t"); exit(ERRM_CLI_USER_ERROR); } $this_is_start_time = $TRUE; $end_time = $end_time . $comma . $time_code; $ntimes++; # count the number of times } } return ($ntimes,$start_time,$end_time); } #--------------------------------------------------------------------# # get_assoc_handles : Uses the list resource RMC CLI command to # # find all association resource handles from a condition handle # # and / or a response handle in the Association resource class. # # # # Parameters: # # $cond_handle the condition handle to find, or "" # # $resp_handle the response handle to find, or "" # # $locator where the condition/response is # # # # Returns: # # $rc return code # # 0 if one or more Association handles are found # # -1 if no Association handles are found # # ERRM_CLI_USER_ERROR if RMC_CLI_USER_ERROR # # \@handles all Association handles that were found # # (by reference) # # \@actflags the corresponding ActiveFlag values # # (by reference) # # # # Global Variables: # # $main::Trace in case trace is on # # $main::PROGNAME for trace message # # $CTBINDIR where list command resides # # $LSRSRC RMC CLI list command # # $RSCASSC Association class # # $LSNOTFND number of output line for name not found # #--------------------------------------------------------------------# sub get_assoc_handles { my $cond_handle = shift(@_); # condition resource handle my $resp_handle = shift(@_); # response resource handle my $locator = shift(@_); # locator my $rc = 0; # return code my @handles = (); # array to keep handles my @act_flags = (); # array to keep active flags my @listout = (); # lsrsrc output my $i = 0; # loop counter my $pos = 0; # look through output my $handle = ""; # a single handle from output my $active = 0; # a single flag from output my $node_select = ""; my $trace_opt = ""; # get rid of quotes in handles $cond_handle =~ s/"//g; $resp_handle =~ s/"//g; # re-establish original CT_MANAGEMENT_SCOPE &set_orig_rmc_scope; # check to see if resource name has a Node_name to locate it. # if not, set rmc local scope. if it does, use it in select string. if ($locator eq "") { # set CT_MANAGEMENT_SCOPE to local for query $ENV{CT_MANAGEMENT_SCOPE} = $RMC_LOCAL_SCOPE; } # else use location is select string else { $node_select = " && NodeNameList |< {\\\"$locator\\\"}"; # use DM/SR/Local scope if scope not set and there's a locator &check_set_cluster_scope; } $main::Trace && print STDERR "$main::PROGNAME: calling lsrsrc-api\n"; $main::Trace && ($trace_opt = " -T "); # list the Association resource depending on whether you have just a condition, # just a response, or both if ($resp_handle eq "") { # have only a condition # @listout = `$CTBINDIR/$LSRSRC $trace_opt -x -s "ConditionHandle==\\\"$cond_handle\\\" $node_select" $RSCASSC ResourceHandle ActiveFlag`; @listout = `$CTBINDIR/lsrsrc-api -I $DELIMITERI -D $DELIMITERO -s ${RSCASSC}${DELIMITERI}\"ConditionHandle==\\\"$cond_handle\\\"$node_select\"${DELIMITERI}${DELIMITERI}${DELIMITERI}ResourceHandle${DELIMITERI}ActiveFlag 2>&1`; $rc = $?; } elsif ($cond_handle eq "") { # have only a response # @listout = `$CTBINDIR/$LSRSRC $trace_opt -x -s "EventResponseHandle==\\\"$resp_handle\\\" $node_select" $RSCASSC ResourceHandle ActiveFlag`; @listout = `$CTBINDIR/lsrsrc-api -I $DELIMITERI -D $DELIMITERO -s ${RSCASSC}${DELIMITERI}\"EventResponseHandle==\\\"$resp_handle\\\"$node_select\"${DELIMITERI}${DELIMITERI}${DELIMITERI}ResourceHandle${DELIMITERI}ActiveFlag 2>&1`; $rc = $?; } else { # have both condition and response # @listout = `$CTBINDIR/$LSRSRC $trace_opt -x -s "ConditionHandle==\\\"$cond_handle\\\" && EventResponseHandle==\\\"$resp_handle\\\" $node_select" $RSCASSC ResourceHandle ActiveFlag`; @listout = `$CTBINDIR/lsrsrc-api -I $DELIMITERI -D $DELIMITERO -s ${RSCASSC}${DELIMITERI}\"ConditionHandle==\\\"$cond_handle\\\" && EventResponseHandle==\\\"$resp_handle\\\"$node_select\"${DELIMITERI}${DELIMITERI}${DELIMITERI}ResourceHandle${DELIMITERI}ActiveFlag 2>&1`; $rc = $?; } $rc = &process_exit_code($rc); $main::Trace && print STDERR "lsrsrc-api results:\n"; $main::Trace && print STDERR "@listout"; $main::Trace && print STDERR "$main::PROGNAME: lsrsrc-api returned $rc\n"; # show any errors if there was a bad rc except for not found if (($rc != 0) && ($rc != $RMC_CLI_RSRC_NOT_FOUND)) { &process_api_error($DELIMITERO,$rc,@listout); } # return ERRM CLI user error if it's an RMC CLI user error if ($rc == $RMC_CLI_USER_ERROR) { exit(ERRM_CLI_USER_ERROR);} # if list command failed, print RMC error message and exit if (($rc != 0) && ($rc != $RMC_CLI_RSRC_NOT_FOUND)) { exit(ERRM_CLI_RMC_ERROR); } # return -1 if resource not found if ($rc == $RMC_CLI_RSRC_NOT_FOUND) { $rc = -1; } # if it was found if ($rc == 0) { $rc = 0; # parse the output to find the handles and the active flags for ($i=0;$i<=$#listout;$i++) { # each line of output # split the line into handle and flag ($handle,$active) = split /$DELIMITERO/,$listout[$i]; chomp($handle); chomp($active); $handle = "\"".$handle."\""; push @handles, $handle; # save the handle push @act_flags, $active; # save the flag } } # return the arrays back as references return ($rc, \@handles, \@act_flags); } #--------------------------------------------------------------------# # find_names_from_assoc - uses the list resource RMC CLI command to # # find the names of the conditions and responses for an Association# # resource. # # # # Parameters: # # $locator where the condition/response is # # @assoc_handles the list of Association resource handles # # # # Returns: # # $rc return code # # 0 if names are found # # -1 if no names are found # # ERRM_CLI_USER_ERROR if RMC_CLI_USER_ERROR # # \@cond_names reference to a list of condition names. # # \@resp_names reference to a list of response names. # # # # Global Variables: # # $main::Trace in case trace is on # # $main::PROGNAME for trace message # # $CTBINDIR where list command resides # # $LSRSRC RMC CLI list command # # $RSCASSC Association class # # $LSNOTFND number of output line for name not found # #--------------------------------------------------------------------# sub find_names_from_assoc { my $locator = shift(@_); # locator my @assoc_handles = @_; # assoc handle array my $rc = 0; # return code my @cond_rhs = (); # condition handles my @resp_rhs = (); # response handles my @cond_names = (); # condition names my @resp_names = (); # response names my $rh = ""; # Assoc RH my $rh_str = ""; # handles for cmd text my $cmd_rhs = ""; # handles for lsrsrc-api my $cond_rh = ""; # condition handle my $resp_rh = ""; # response handle my $name = ""; # resource name my @listout = (); # result from lsrsrc my $i = 0; # counter # find condition and response handles from association handles foreach $rh (@assoc_handles) { chomp($rh); # make sure we know where the quotes are $rh =~ s/"//g; # build lsrsrc-api command using -r format for resource handle. # handle is unique is cluster so locator is not needed. $cmd_rhs = $cmd_rhs . " -r \"$rh\""; } # re-establish original CT_MANAGEMENT_SCOPE &set_orig_rmc_scope; # if no locator, use local scope. if ($locator eq "") { # set CT_MANAGEMENT_SCOPE to local for query $ENV{CT_MANAGEMENT_SCOPE} = $RMC_LOCAL_SCOPE; } # use DM/SR/Local scope if scope not set and there's a locator else { &check_set_cluster_scope; } $main::Trace && print STDERR "$main::PROGNAME: calling lsrsrc-api\n"; $main::Trace && ($trace_opt = " -T "); # find the condition and response handles. @listout = `$CTBINDIR/lsrsrc-api -I $DELIMITERI -D $DELIMITERO -a ConditionHandle${DELIMITERI}EventResponseHandle $cmd_rhs 2>&1`; $rc = $?; $rc = &process_exit_code($rc); $main::Trace && print STDERR "lsrsrc-api results:\n"; $main::Trace && print STDERR "@listout"; $main::Trace && print STDERR "$main::PROGNAME: lsrsrc-api returned $rc\n"; # show any errors if ($rc != 0) { &process_api_error($DELIMITERO,$rc,@listout); } # output from lsrsrc-api is cond_rh::resp_rh except for delimiter # one line per pair $cmd_rhs = ""; foreach $rh_str (@listout) { # split the line into condition and response handles ($cond_rh,$resp_rh) = split /$DELIMITERO/,$rh_str; chomp($cond_rh); chomp($resp_rh); # build lsrsrc-api command using -r format for resource handle. $cmd_rhs = $cmd_rhs . " -r \"$cond_rh\" -r \"$resp_rh\""; } # find condition names from condition handles and response names # from response handles # re-establish original CT_MANAGEMENT_SCOPE &set_orig_rmc_scope; # if no locator, use local scope. if ($locator eq "") { # set CT_MANAGEMENT_SCOPE to local for query $ENV{CT_MANAGEMENT_SCOPE} = $RMC_LOCAL_SCOPE; } # use DM/SR/Local scope if scope not set and there's a locator else { &check_set_cluster_scope; } $main::Trace && print STDERR "$main::PROGNAME: calling lsrsrc-api\n"; $main::Trace && ($trace_opt = " -T "); # find the condition and response handles. @listout = `$CTBINDIR/lsrsrc-api -D $DELIMITERO -a Name $cmd_rhs 2>&1`; $rc = $?; $rc = &process_exit_code($rc); $main::Trace && print STDERR "lsrsrc-api results:\n"; $main::Trace && print STDERR "@listout"; $main::Trace && print STDERR "$main::PROGNAME: lsrsrc-api returned $rc\n"; # show any errors if ($rc != 0) { &process_api_error($DELIMITERO,$rc,@listout); } # output from lsrsrc-api is name # 1st line is condition, next line response, repeat in this pattern # get condition names for ($i=0; $i <= $#listout; $i = $i + 2) { $name = $listout[$i]; chomp($name); push @cond_names, $name; } # get response names for ($i=1; $i <= $#listout; $i = $i + 2) { $name = $listout[$i]; chomp($name); push @resp_names, $name; } # return the arrays back as references return ($rc, \@cond_names, \@resp_names); } #--------------------------------------------------------------------# # change_locked_attr - changes the value of the Locked attribute for # # the resource specified. # # # # Parameters: # # $lock_val Value to set. 0 for unlock, 1 for lock. # # $locator Node where resource is, if not local. # # $class Resource class. # # $resource Resource name if condition or responce class. # # Association handle if association class. # # # # Returns: # # $rc return code # # 0 if chrsrc-api successful. # # -1 otherwise. # # # # Global Variables: # # $main::Trace in case trace is on # # $main::PROGNAME for trace message # # $CTBINDIR where list command resides # #--------------------------------------------------------------------# sub change_locked_attr { my $lock_val = shift(@_); # value to set Locked to my $locator = shift(@_); # locator my $class = shift(@_); # resource class my $resource = shift(@_); # resource to change my $rc = 0; # return code my @cmd_out = (); # chrsrc-api output my $cond_rh = ""; # condition handle my $resp_rh = ""; # response handle my $node_select = ""; # for locator # set CT_MANAGEMENT_SCOPE to original setting, in case it was used &set_orig_rmc_scope; # if the destination node was not specified, change the local definition. # Make sure rmc scope is set to local scope. if ($locator eq "") { $ENV{CT_MANAGEMENT_SCOPE} = $RMC_LOCAL_SCOPE; } # a locator was specified, use it for NodeNameList else { $node_select = " && NodeNameList |< {\\\"$locator\\\"}"; # use DM/SR/Local scope if scope not set &check_set_cluster_scope; } # if class is Condition or EventResponse, use chrsrc-api for # name=resource if (($class eq $RSCCOND) || ($class eq $RSCEVRS)) { if ($main::Trace) { print STDERR "$PROGNAME: calling chrsrc-api\n";} @cmd_out = `$CTBINDIR/chrsrc-api -I $DELIMITERI -D $DELIMITERO -s ${class}${DELIMITERI}"Name==\\\"$resource\\\" $node_select"${DELIMITERI}Locked${DELIMITERI}$lock_val 2>&1`; $rc = $?; $rc = &process_exit_code($rc); if ($main::Trace) { print STDERR "chrsrc-api results:\n"; print STDERR "@cmd_out"; print STDERR "$main::$PROGNAME: chrsrc-api returned $rc\n"; } # show any errors if there was a bad rc except for not found if ($rc != 0) { process_api_error($DELIMITERO,$rc,@cmd_out); } } # if association class, use chrsrc-api -r for association handle ($resource) if ($class eq $RSCASSC) { # get rid of the quotes so we know where they are $resource =~ s/\"//g; if ($main::Trace) { print STDERR "$PROGNAME: calling chrsrc-api\n";} @cmd_out = `$CTBINDIR/chrsrc-api -I $DELIMITERI -D $DELIMITERO -r "$resource"${DELIMITERI}Locked${DELIMITERI}$lock_val 2>&1`; $rc = $?; $rc = &process_exit_code($rc); if ($main::Trace) { print STDERR "chrsrc-api results:\n"; print STDERR "@cmd_out"; print STDERR "$main::$PROGNAME: chrsrc-api returned $rc\n"; } # show any errors if there was a bad rc except for not found if ($rc != 0) { process_api_error($DELIMITERO,$rc,@cmd_out); } } # end class=association # return return ($rc); } #--------------------------------------------------------------------# # get_source_node : Returns a string that is the resolved node name # # for the node where the rmc session would (may) be. That is, if # # CT_CONTACT is set, it's that node, otherwise, it's the node # # you're on. # # # # Parameters: # # None. # # # # Returns: # # local_node Resolved name of the node the rmc session would # # or may be on. # # # # Global Variables: # #--------------------------------------------------------------------# sub get_source_node { my $local_node = ""; # node command runs on my $hname = ""; # used by gethost my $haliases = ""; # used by gethost my $haddrtype = ""; # used by gethost my $hlength = 0; # used by gethost my @haddrs = (); # used by gethost # see if CT_CONTACT is defined. If so, use it. # if not, use the node you're on. if (defined $ENV{CT_CONTACT}) { $local_node = $ENV{CT_CONTACT}; } else { # get the name of the node you're on $local_node = `/bin/hostname`; } chomp($local_node); # resolve the name #($hname, $haliases, $haddrtype, $hlength, @haddrs) = gethostbyname($local_node); #$local_node = $hname; # return the resolved name return($local_node); } # end of get_source_node #--------------------------------------------------------------------# # resolve_node : Returns a string that is the resolved node name of # # the input node name. # # # # Parameters: # # node_name string that is the node name to be resolved. # # # # Returns: # # resolved_name Resolved name of the node. "" if not resolved. # # # # Global Variables: # #--------------------------------------------------------------------# sub resolve_node { my $node_name = shift(@_); # node name to resolve my $resolved_name = ""; # output resolved name my $hname = ""; # used by gethost my $haliases = ""; # used by gethost my $haddrtype = ""; # used by gethost my $hlength = 0; # used by gethost my @haddrs = (); # used by gethost # resolve the name ($hname, $haliases, $haddrtype, $hlength, @haddrs) = gethostbyname($node_name); # set the resolved node name if (!$hname) { # if it didn't resolve, keep what it had $resolved_name = $node_name; } # it did resolve else { $resolved_name = $hname; } # return the resolved name return($resolved_name); } # end of resolve_node #--------------------------------------------------------------------# # get_locator_node : Returns the resource name and locator from a # # resource name/locator combination. Ex. ConditionName:nodeA # # will return ConditionName and nodeA. # # # # Parameters: # # resource_name_in The resource name / locator combination. # # # # Returns: # # resource_name resource name. # # locator locator, if there is one. # # # # Global Variables: # #--------------------------------------------------------------------# sub get_locator_node { my $resource_name_in = shift(@_); # resource/locator combo my $resource_name = ""; # resource name for output my $temp_resource = ""; # temporary place for names my $locator = ""; # locator name for output my $hname = ""; # used by gethost my $haliases = ""; # used by gethost my $haddrtype = ""; # used by gethost my $hlength = 0; # used by gethost my @haddrs = (); # used by gethost # split the resource/locator based on colons @temp_resource = split /:/,$resource_name_in; # if there were some colons, take the last splitee as the locator if ($#temp_resource > 0) { $locator = $temp_resource[$#temp_resource]; # set the resource name from input but remove locator $resource_name = $resource_name_in; $resource_name =~s/:$locator$//; } # else there's no colons, it's all resource name else { $locator = ""; $resource_name = $resource_name_in; } return($resource_name, $locator); } # end of get_locator_node #--------------------------------------------------------------------# # process_monitor_status: returns the MonitorStatus portion of the # # MonitorStatus attribute SD and its description. # # The MonitorStatus attribute is in form: # # [monitorstatus,{errornodes},{errorcodes}] # # # # Parameters: # # monitor_status_sd The MonitorStatus attribute value. # # monitor_desc_text The hash of values for the descriptions. # # # # Returns: # # monitor_status The MonitorStatus code of the SD. # # monitor_desc The description for monitor_status. # # # # Global Variables: # #--------------------------------------------------------------------# sub process_monitor_status { my $monitor_status_sd = shift(@_); # MonitorStatus SD my %monitor_desc_text = @_; # hash of text descriptions my $monitor_status = 0; # MonitorStatus code my $monitor_desc = ""; # MonitorStatus description my @monitor_temp = (); # temporary my $monitor_temp2 = ""; my $found = $FALSE; # keep track of when text found # split on commas @monitor_temp = split /,/,$monitor_status_sd; # take first element $monitor_temp2 = $monitor_temp[0]; # split on [ @monitor_temp = split /\[/,$monitor_temp2; # take second element as status $monitor_status = $monitor_temp[1]; # see if monitor status to find exists if (defined $monitor_desc_text{$monitor_status}) { $found = $TRUE; } # translate monitor status if ($found) { $monitor_desc = $monitor_desc_text{$monitor_status}; } else { $monitor_desc = $monitor_desc_text{"?"}; } # add quotes $monitor_desc = "\"".$monitor_desc."\""; return($monitor_status, $monitor_desc); } # end of process_monitor_status #--------------------------------------------------------------------# # process_active_status: returns the translated text representing # # the description for the Active flag for an association resource. # # # # Parameters: # # active_status The active flag value. # # active_desc_text The hash of values for the descriptions. # # # # Returns: # # active_desc The description for active_status. # # # # Global Variables: # #--------------------------------------------------------------------# sub process_active_status { my $active_status = shift(@_); # active status code my %active_desc_text = @_; # hash of text descriptions my $active_desc = ""; # active status description my $found = $FALSE; # keep track of when text found # see if active status to find exists if (defined $active_desc_text{$active_status}) { $found = $TRUE; } # translate active status if ($found) { $active_desc = $active_desc_text{$active_status}; } else { $active_desc = $active_desc_text{"?"}; } # add quotes $active_desc = "\"".$active_desc."\""; return($active_desc); } # end of process_active_status #--------------------------------------------------------------------# # set_orig_rmc_scope : Uses the global varibales set by the ERRM # # command to set the CT_MANAGEMENT_SCOPE environment variable # # to what it was, or wasn't, back when the command started. # # # # Parameters: # # None. # # # # Returns: # # None. # # # # Global Variables: # # $main::Scope_orig_set was CT_MANAGEMENT_SCOPE originally set # # $main::Scope_orig_value CT_MANAGEMENT_SCOPE original value if set# #--------------------------------------------------------------------# sub set_orig_rmc_scope { # if CT_MANAGEMENT_SCOPE was originally set, return it to its original # value. (may already be that value but so what) if ($main::Scope_orig_set) { $ENV{CT_MANAGEMENT_SCOPE} = $main::Scope_orig_value; } # else it shouldn't exist. Make sure it doesn't else { if (defined $ENV{CT_MANAGEMENT_SCOPE}) { # get rid of it delete $ENV{CT_MANAGEMENT_SCOPE}; } } } # end of set_orig_rmc_scope #--------------------------------------------------------------------# # check_set_cluster_scope: Checks the scope environment variable # # CT_MANAGEMENT_SCOPE to see if it is set for a cluster operation. # # If it is not set, it is set to 4 for DM/SR/local for the next # # rmc session. If it is set, and it's set to local, then it is # # set to 4 for DM/SR/local for the next rmc session. It is # # unchanged if it is DM or SR scope. # # # # Parameters: # # None. # # # # Returns: # # None. # # # #--------------------------------------------------------------------# sub check_set_cluster_scope { # if CT_MANAGEMENT_SCOPE is not defined, set it to 4 for DM/SR/Local scope if (!defined $ENV{CT_MANAGEMENT_SCOPE}) { $ENV{CT_MANAGEMENT_SCOPE} = $RMC_DM_SR_LOCAL_SCOPE; } # if it's defined, it shouldn't be local. If it's local, set it # to 4 for DM/SR/Local scope else { if ($ENV{CT_MANAGEMENT_SCOPE} == $RMC_LOCAL_SCOPE || $ENV{CT_MANAGEMENT_SCOPE} == $RMC_LOCAL2_SCOPE) { $ENV{CT_MANAGEMENT_SCOPE} = $RMC_DM_SR_LOCAL_SCOPE; } } } # end of check_set_cluster_scope #--------------------------------------------------------------------# # getIMsg : calls $LSMSG to print out the message with the # # required parameters, like printIMsg, except the message is # # returned instead of printed. Used for NLS. # # # # Parameters: # # msg in Message mnemonic / message number in a sense. # # optargs in Extra arguments/parameters to send to LSMSG. # # # # Returns: # # msgtext out Array of messages. # # # # Global Variables: # # $main::Trace in Print extra info when trace is on. # # $main::PROGNAME in Calling program/command for error message. # # $main::LSMSG in Path & Command to display messages. # # $main::MSGCAT in The calling commands Message catalogue. # #--------------------------------------------------------------------# sub getIMsg { my ($msg, @optargs) = @_; my ($optarg, $optargs); my @msgtext = (); $main::Trace && print STDERR "$main::LSMSG $main::PROGNAME $main::MSGCAT $msg @optargs\n"; # Keep the args to LSMSG separate by separating with single quotes # but must replace internal single quotes with blanks or get an error. # Must escape internal double quotes for the system call. foreach $optarg (@optargs) { $optarg =~ s/'/ /g; $optarg =~ s/"/\\"/g; } $optargs = "'" . join("' '",@optargs) . "'"; if (scalar @optargs > 0) { @msgtext = `$main::LSMSG $main::PROGNAME $main::MSGCAT $msg $optargs`; } else { @msgtext = `$main::LSMSG $main::PROGNAME $main::MSGCAT $msg`; } return (@msgtext); } # end getIMsg #--------------------------------------------------------------------# # process_exit_code: returns 0, the signal exit code, or the process # # exit code from the called process. This is used to examine the # # exit codes from perl uses for called processes. # # The exit value of the subprocess is in the high byte (>>8) # # The low byte has the signal the process died from (if any)(& 127)# # To be complete, core dumps are indicated with (& 128) (not used) # # # # Parameters: # # exit_code The exit code to be examined. # # # # Returns: # # process_exit_code 0, signal, or process exit code. # # # # Global Variables: # #--------------------------------------------------------------------# sub process_exit_code { my $exit_code = shift(@_); # the exit code to check my $process_signal_exit_code = 0; # signal exit code, if any my $process_exit_code = 0; # what to return # if it's 0, wonderful. if ($exit_code == 0) { return (0);}; # check for signal process died from, if any $process_signal_exit_code = $exit_code & 127; # if there was a signal, return it if ($process_signal_exit_code > 0) { printCEMsg("EMsgERRMcliUnExpectRMCrc",$process_signal_exit_code); return ($process_signal_exit_code); } # otherwise return the process exit code $process_exit_code = $exit_code >> 8; return ($process_exit_code); } # end process_exit_code #--------------------------------------------------------------------# # process_api_error - Scans the input varaible for error messages # # found by the c-api command. The c-api command errors are # # found by searching each output line for "ERROR" at the # # beginning of the line. The error message printed is the last # # double colon delimited string. # # Resource not found errors (rc=6) are not printed. # # # # Parameters: # # $delimiter The delimiter used in the error string. # # $rc The return code from the c-api call. # # @command_output The output from the command. # # # # Returns: # # None. # # # # Global Variables: # #--------------------------------------------------------------------# sub process_api_error { my $delimiter = shift(@_); # output delimiter my $api_rc = shift(@_); # rc from c-api call my @command_output = @_; # command output to scan my $error_count = 0; # number of error messages # scan each line for ERROR foreach $line (@command_output) { # does it start with ERROR? if ($line =~ /^ERROR.*/) { # split it apart based on double colons # last one should be error message @error_parts = split /$delimiter/, $line; if ($error_parts[2] != $RMC_CLI_RSRC_NOT_FOUND) { # replace any escaped new lines with new lines $error_parts[$#error_parts] =~ s/\\n/\n/g; # get rid of any beginning/ending quote that comes from # having CT_CLI_QUOTE_STRING turned on (sometimes) if ( defined $ENV{CT_CLI_QUOTE_STRING} && $ENV{CT_CLI_QUOTE_STRING}==1) { $error_parts[$#error_parts] =~ s/^\"//; $error_parts[$#error_parts] =~ s/\"$//; #$error_parts[$#error_parts] =~ s/\\\"/\"/g; $error_parts[$#error_parts] = unescape_chars($error_parts[$#error_parts]); } # last one should be error message. print it to STDERR. print STDERR $error_parts[$#error_parts]; $error_count++; } else { # rc=resource not found, count that $error_count++; } } } # print unexpected error if api rc was not 0 and no messages were displayed if (($error_count == 0) && ($api_rc != 0)) { printCEMsg("EMsgERRMcliUnExpectRMCrc",$api_rc); } } # end of process_api_error #--------------------------------------------------------------------# # remove_api_error - Scans the input varaible for error messages # # found by the c-api command. The c-api command errors are # # found by searching each output line for "ERROR" at the # # beginning of the line. An array is returned that is the same as # # the input array except that the error messages are removed. # # # # Parameters: # # @command_output The output from the command. # # # # Returns: # # @errorless_output The original @command_output array contents # # with the errors removed. # # # # Global Variables: # #--------------------------------------------------------------------# sub remove_api_error { my @command_output = @_; # command output to scan my @errorless_output = (); # errors removed # scan each line for ERROR foreach $line (@command_output) { # does it start with ERROR? if (!($line =~ /^ERROR.*/)) { # put it in the errorless array push @errorless_output, $line; } } return (@errorless_output); } # end of remove_api_error #--------------------------------------------------------------------# # escape_selstr: # # Scans a to-be select string respecting multibyte encodings to # # add SQL escapes (#) escapes for %, #, and _ characters so they # # are not interpretted by SQL processing as special characters in # # an rmc select string. # # # # Paramaters: # # $string_in string to check for any needed SQL escapes. # # # # Returns: # # $string_out result. # # # #--------------------------------------------------------------------# sub escape_selstr { use POSIX; use POSIX qw(:stdlib_h); use POSIX qw(mblen); my $string_in = shift(@_); my $string_in2 = ""; my $string_out = ""; my $lenstring = 0; my $lenchar = 0; # get the length of the prospective select string $lenstring = length($string_in); # if there are no %,#,_, skip over checking char-by-char if ($string_in =~ /.*[%#_].*/) { for (my $i=0; $i<$lenstring; $i+=$lenchar) { # form the string of where we're at $string_in2 = substr($string_in,$i); # determine if this is a multibyte encoding (mblen>1) $lenchar = mblen ($string_in2, MB_CUR_MAX); # if it's length is less than 1, treat it as 1 character if (!$lenchar >= 1) { $lenchar = 1;} # if it's not multibyte and it's a backslash, escape it if ( ($lenchar == 1) && ($string_in2 =~ /^[%#_]/) ) { $string_out .= "#" . substr($string_in2,0,1); } # otherwise, just take it as it is else {$string_out .= substr($string_in2,0,$lenchar);} } } # it doesn't have any characters we're worried about so take it as is else {$string_out = $string_in;} return ($string_out); } # end escape_selstr #--------------------------------------------------------------------# # in_cluster : Returns true if in a cluster environment, false if # # not. # # # # Parameters: # # None. # # # # Returns: # # 1 (true) if in a cluster # # 0 (false) if not in a cluster # # # # Global Variables: # # $main::Trace in Print extra info when trace is on. # # $main::PROGNAME in Calling program/command for error message. # #--------------------------------------------------------------------# sub in_cluster { my @listout = (); my $trace_opt = ""; my $local_node = ""; my $rc = 0; my $scope_val = 0; my $incluster = $FALSE; # get the node name $local_node = &get_source_node; $main::Trace && print STDERR "$main::PROGNAME: calling lsrsrc-api\n"; $main::Trace && ($trace_opt = " -T "); # set local scope to find the node we need $ENV{CT_MANAGEMENT_SCOPE} = $RMC_LOCAL_SCOPE; # get the ActiveMgtScopes attribute @listout = `$CTBINDIR/lsrsrc-api -I $DELIMITERI -D $DELIMITERO -s IBM.Host${DELIMITERI}\"Name==\\\"$local_node\\\"\"${DELIMITERI}${DELIMITERI}${DELIMITERI}ActiveMgtScopes 2>&1`; $rc = $?; $rc = &process_exit_code($rc); $main::Trace && print STDERR "lsrsrc-api results:\n"; $main::Trace && print STDERR "@listout"; $main::Trace && print STDERR "$main::PROGNAME: lsrsrc-api returned $rc\n"; # if there was an error, continue on as if nothing happened # but assume that we're in a cluster so nodename is shown in output if ($rc != 0) { $incluster = $TRUE; } # else it worked ok else { # get the scope value $scope_val = $listout[0]; # scope >1 means there's a cluster if ($scope_val > 1) { $incluster = $TRUE; } else { $incluster = $FALSE;} } return ($incluster); } # end of in_cluster #--------------------------------------------------------------------# # End Exported Subroutines (with @EXPORT_OK, -> on demand). # #--------------------------------------------------------------------# #--------------------------------------------------------------------# # End File. # #--------------------------------------------------------------------#