#!/usr/bin/perl # 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 # sccsid = "@(#)79 1.15.1.13 src/rsct/rm/ER/cli/bin/startcondresp.perl, errmcli, rsct_rady, rady2035a 11/12/15 16:39:07" ###################################################################### # # # Module: startcondresp # # # # Purpose: # # startcondresp - start monitoring a condition that has a response # # # # Syntax: # # startcondresp [-h] [-TV] Condition[:Node_name] [Response # # [Response ...]] # # # # startcondresp [-h] -U|-L [-TV] Condition[:Node_name] Response # # # # # # Flags: # # -h help - writes this command's usage statement to stdout # # -L Lock. Lock the link between a condition and response so # # that the monitoring state cannot be changed using the # # startcondresp or stopcondresp command or the link # # between the condition and response be removed using the # # rmcondresp command. # # -U Unlock. Unlock the link between a condition and response # # so that the monitoring state can be changed using the # # startcondresp or stopcondresp command or the link # # between the condition and response removed using the # # rmcondresp command. # # -T Trace. IBM Support Center use only. # # -V Verbose. # # # # Operands: # # Condition The condition that is linked to a response. The # # condition is always specified first. Node_name # # specifies where the condition is defined. # # Response The response that is linked to a condition. If more# # than one response is specified, all of the responses# # are linked to the same condition. # # # # Description: # # The startcondresp command starts the monitoring of a condition # # that has a linked response. After monitoring is started, when # # the condition occurs, the response is run. If no responses are # # specified, monitoring is started for all responses linked to the # # condition. This causes all of the linked responses to run when # # the condition occurs. If more than one response is specified, # # monitoring is started only for those linked responses. # # # # If one or more responses are specified and the responses are not # # linked with the condition, the startcondresp command links the # # specified responses to the condition, and monitoring is started. # # Use the mkcondresp command to link a response to a condition # # without starting monitoring. # # # # Exit Values: # # 0 ERRM_CLI_SUCCESS Command completed successfully. # # 1 ERRM_CLI_RMC_ERROR Command terminated due to an underlying # # RMC error. # # 2 ERRM_CLI_ERROR Command terminated due to an underlying # # error in the command script. # # 3 ERRM_CLI_BAD_FLAG Command terminated due to user # # specifying an invalid flag. # # 4 ERRM_CLI_BAD_OPERAND Command terminated due to user # # specifying a bad operand. # # 5 ERRM_CLI_USER_ERROR Command terminated due to a user error. # # For example specifying a name that # # already exists. # # # # Examples: # # 1. Start monitoring the condition "JFS space used" by using the # # response "Broadcast event on-shift", whether or not the # # response is linked with the condition: # # startcondresp "JFS space used" "Broadcast event on-shift" # # 2. Start monitoring the condition "JFS space used" by using all # # of its linked responses: # # startcondresp "JFS space used" # # 3. Start monitoring the condition "JFS space used" by using the # # response "Broadcast event on-shift" and "E-mail root anytime",# # whether or not they are linked with the condition: # # startcondresp "JFS space used" "Broadcast event on-shift" \ # # "E-mail root anytime" # # # # Man Page: # # For the most current detailed description of this command see # # the startcondresp man page in /opt/rsct/man. # # # #--------------------------------------------------------------------# # Inputs: # # /opt/rsct/msgmaps/errmcli.startcondresp.map - msg mapping # # # # Outputs: # # stdout - display information on the condition. # # stderr - any error message. # # # # External Ref: # # Commands: ctdspmsg # # Modules: ERRM_cli_utils.pm, ERRM_cli_rc.pm # # CT_cli_utils.pm # # Perl library routines: Getopt::Std # # # # Tab Settings: # # 4 and tabs should be expanded to spaces before saving this file. # # in vi: (:set ts=4 and :%!expand -4) # # # # Change Activity: # # 001106 JAC 67469: Initial design & write. # # 010115 JAC 67471: Completed startcondresp command. # # 010303 JAC 71044: Comment out code to name the association. # # 010306 JAC 72065: Continue to process responses even if a # # response is not found. # # 010330 JAC 71287: Update runact call due to syntax change # # 010403 JAC 72894: Eliminate extra call to lsrsrc to get handle # # 010412 JAC 73148: Enclose ActiveFlags in quotes on runact. # # 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. # # 011120 JAC 77597: Add distributed RMC changes # # 020128 JAC 79559: Change how destination/locator node is used. # # 020214 JAC 77600: Add node name to runact call if not local. # # 020416 JAC 81754: Fix exit code checking and use mkrsrc-api. # # 020425 JAC 82407: Fix for doing a mkrsrc when no assoc exists. # # 020529 JAC 82590: Use runact-api instead of runact. # # 020719 JAC 84931: Modify quoting in runact-api call. # # 020719 JAC 84425: Add $rc to process_api_error call. # # 020729 JAC 85061: Use 4 (DM/SR/local) for scope if locator used # # and scope not set. # # 030610 JAC 95615: Add support for locked attribute. # # 030620 JAC 96060: Add -U|-L for Locked attribute. # # 071026 JAC 146726: set delimiter for calling -api commands. # ###################################################################### #--------------------------------------------------------------------# # General Program Flow/Logic: # # # # 1. Parse command line flags and operands, determine which flavor # # of this command we are actually invoking. # # This command allows a user to start monitoring a condition- # # response association. # # 2. Print usage if -h specified. # # 3. Make sure one and only one condition is specified and it exists # # 4. Make sure any responses specified exist. # # 5. If there are no responses, find all associations for the # # condition and save the resource handles. # # 6. If there are responses, for each response, # # see if the condition - response association exists. If it does,# # save the resource handle. If it doesn't, make the association # # and save the resource handle. # # 7. Call RMC command runact using the action SetActiveFlags with # # the array of association handles and a matching array of 1's. # # Also pass along -VT if necessary. # # 8. Return back any errors. # # # #--------------------------------------------------------------------# #--------------------------------------------------------------------# # Included Libraries and Extensions # #--------------------------------------------------------------------# use lib "/opt/rsct/pm"; use locale; use Getopt::Long; use CT_cli_utils qw(printIMsg printEMsg); use ERRM_cli_rc qw(ERRM_CLI_SUCCESS ERRM_CLI_RMC_ERROR ERRM_CLI_ERROR ERRM_CLI_BAD_FLAG ERRM_CLI_BAD_OPERAND ERRM_CLI_USER_ERROR); use ERRM_cli_utils qw(error_exit printCIMsg printCEMsg get_source_node get_locator_node find_resource_name get_handle get_assoc_handles find_names_from_assoc change_locked_attr set_orig_rmc_scope check_set_cluster_scope process_api_error process_exit_code $CTDIR $CTBINDIR $STARTMON $DELIMITERI $DELIMITERO $LSNOTFND $MKRSRC $TRUE $FALSE $RMC_CLI_USER_ERROR $RMC_LOCAL_SCOPE $RUNACT $LSRSRC $RSCASSC $RSCCOND $RSCEVRS); #--------------------------------------------------------------------# # Global Variables # #--------------------------------------------------------------------# Getopt::Long::Configure ("bundling", "no_auto_abbrev", "no_ignore_case", "require_order", "prefix_pattern=(--|-)"); $Trace = $FALSE; # default - trace off $Verbose = $FALSE; # default - verbose turned off $Scope_orig_set = $FALSE; # default - no CT_MANAGEMENT_SCOPE $Scope_orig_value = 0; # default - scope value $Opt_Lock = $FALSE; # default - no set lock $Opt_Unlock = $FALSE; # default - no set unlock $PROGNAME = "startcondresp"; # Program Name for messages $MSGCAT = "errmcli.cat"; # msg catalogue for this cmd $LSMSG = "$CTBINDIR/ctdspmsg"; # list / display message rtn. $ENV{'MSGMAPPATH'} = "$CTDIR/msgmaps"; # msg maps used by $LSMSG #--------------------------------------------------------------------# # Variables # #--------------------------------------------------------------------# my $condition = ""; # condition to use my @responses = (); # responses to use my $Cond_handle = ""; # handle for condition my $Resp_handle = ""; # handle for response my $handle_ref = 0; # reference for handle array my $flag_ref = 0; # reference for flag array my $passopts = ""; # options to pass to RMC my $Assoc_name = ""; # temp - name for Assoc my $i = 0; # loop counter my $handle_comma = ""; # for building handle string my $flag_comma = ""; # for building flag string my $handle_str = ""; # string of handles to process my $flag_str = ""; # string of flag settings my $num_handles = -1; # number of handles to process my $temp_name = ""; # holds condition name my $locator = ""; # locator my $other_opts = ""; # command parameters my @cmd_out = (); # xxx-api command output my @action_resp = (); # action response my @locked_assocrh = (); # locked assoc handles my $line = ""; # action response line my $cond_names = ""; # name reference my $resp_names = ""; # name reference my $j = 0; # loop counter my $lock_val = 0; # Locked attr value #--------------------------------------------------------------------# # Main Code # #--------------------------------------------------------------------# my $rc = 0; my $errmcli_rc = 0; # save original rmc management scope value, in case it's changed later if (defined $ENV{CT_MANAGEMENT_SCOPE}) { $Scope_orig_set = $TRUE; $Scope_orig_value = $ENV{CT_MANAGEMENT_SCOPE}; } # parse the command line, exit if there are errors ($rc, $condition, @responses) = &parse_cmd_line; ($rc == 0) || error_exit($rc); if ($Trace) { $passopts = $passopts." -T"; } if ($Verbose) { $passopts = $passopts." -V"; } # extract the locator from condition, if it exists ($temp_name, $locator) = get_locator_node($condition); # put back condition name without locator if ($locator ne "") { $condition = $temp_name; } # make sure the condition already exists and get handle ($rc, $Cond_handle) = get_handle($condition, $RSCCOND, $locator); if ($rc != 0) { # condition name not found # if get_handle failed due to RMC CLI user error 73620 # set ERRM CLI user error and exit if ($rc == $RMC_CLI_USER_ERROR) { exit(ERRM_CLI_USER_ERROR); } printEMsg("EMsgstartcondrespConditionNotFound",$condition); exit(ERRM_CLI_USER_ERROR); } # if there are no responses, find all associations for the condition if ($#responses <0) { # no responses # get all associations for the condition handle, if any # get back references to array of handles, flags ($rc, $handle_ref, $flag_ref) = get_assoc_handles($Cond_handle,"",$locator); # if no associations are found for this condition, error and exit if ($rc != 0) { # if get_assoc_handles failed due to RMC CLI user error 73620 # set ERRM CLI user error and exit if ($rc == $RMC_CLI_USER_ERROR) { exit(ERRM_CLI_USER_ERROR); } printEMsg("EMsgstartcondrespCondNotInAssoc",$condition); exit(ERRM_CLI_USER_ERROR); } # if there are associations, save the handles else { if ($Verbose) { printIMsg("IMsgstartcondrespStartNoResp",$condition);} for ($i=0;$i<=$#$handle_ref;$i++) { $$handle_ref[$i] =~ s/^\"//; $$handle_ref[$i] =~ s/\"$//; $handle_str = $handle_str . $handle_comma . $$handle_ref[$i]; $handle_comma = ","; $num_handles++; } } } # end of if no responses # else there is a condition and one or more responses else { # loop for each response: get handle, find association for ($i=0;$i<=$#responses;$i++) { # make sure it exists and get handle ($rc, $Resp_handle) = get_handle($responses[$i], $RSCEVRS, $locator); if ($rc != 0) { # response does not exist # if get_handle failed due to RMC CLI user error 73620 # set ERRM CLI user error and go to next response if ($rc == $RMC_CLI_USER_ERROR) { $errmcli_rc = ERRM_CLI_USER_ERROR; } else { printEMsg("EMsgstartcondrespResponseNotFound",$responses[$i]); $errmcli_rc = ERRM_CLI_USER_ERROR; } $rc = 0; # reset rc } else { # response found # get the association handle for the condition-response # get back references to array of handles, flags ($rc, $handle_ref, $flag_ref) = get_assoc_handles($Cond_handle,$Resp_handle,$locator); # if get_assoc_handles failed due to RMC CLI user error 73620 # set ERRM CLI user error and go to next response if ($rc == $RMC_CLI_USER_ERROR) { $errmcli_rc = ERRM_CLI_USER_ERROR; next; } # if only changing Locked attribute, do it and leave if ($Opt_Lock || $Opt_Unlock) { # if the association is not found, print error message and leave if ($rc != 0) { printEMsg("EMsgstartcondrespCondRespNotFound",$condition,$responses[$i]); exit(ERRM_CLI_USER_ERROR); } else { # set lock value if ($Opt_Lock) { $lock_val = 1;} if ($Opt_Unlock) { $lock_val = 0;} # call function to change Locked attribute $rc = change_locked_attr($lock_val,$locator,$RSCASSC,$$handle_ref[0]); if ($Verbose) { printIMsg("IMsgstartcondrespEnd");} exit($rc); } } # if there's no association, create it if ($rc != 0) { # temporarily add a resource name #$Assoc_name = $condition . "->" . $responses[$i]; 71044 # set CT_MANAGEMENT_SCOPE to original setting, in case it was used set_orig_rmc_scope; # if the destination node was not specified, make a local association. # 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 { # $other_opts = " NodeNameList='{$locator}'"; $other_opts = "${DELIMITERI}NodeNameList${DELIMITERI}{$locator}"; # use DM/SR/Local scope if scope not set and there's a locator check_set_cluster_scope; } if ($Trace) { print STDERR "$PROGNAME: calling mkrsrc-api\n";} # call RMC mkrsrc to create the association #`$CTBINDIR/$MKRSRC $passopts $RSCASSC ConditionHandle='$Cond_handle' EventResponseHandle='$Resp_handle' $other_opts`; @cmd_out=`$CTBINDIR/mkrsrc-api -I $DELIMITERI -D $DELIMITERO ${RSCASSC}${DELIMITERI}ConditionHandle${DELIMITERI}${Cond_handle}${DELIMITERI}EventResponseHandle${DELIMITERI}${Resp_handle}${other_opts} 2>&1`; $rc = $?; $rc = &process_exit_code($rc); if ($Trace) { print STDERR "mkrsrc-api results:\n"; print STDERR "@cmd_out";} if ($Trace) { print STDERR "$PROGNAME: mkrsrc-api returned $rc\n";} # show any errors if there was a bad rc if ($rc != 0) { process_api_error($DELIMITERO,$rc,@cmd_out); } # if mkrsrc command failed due to RMC CLI user error 73620 # set ERRM CLI user error and go to next condition/response if ($rc == $RMC_CLI_USER_ERROR) { $errmcli_rc = ERRM_CLI_USER_ERROR; } else { # if mkrsrc command failed, print RMC error message and exit if ($rc != 0) { printCEMsg("EMsgERRMcliUnExpectRMCrc",$rc); exit(ERRM_CLI_RMC_ERROR); } # go back and get the association handle ($rc, $handle_ref, $flag_ref) = get_assoc_handles($Cond_handle,$Resp_handle,$locator); # if get_assoc_handles failed due to RMC CLI user error 73620 # set ERRM CLI user error and go to next response if ($rc == $RMC_CLI_USER_ERROR) { $errmcli_rc = ERRM_CLI_USER_ERROR; next; } if ($Verbose) { printIMsg("IMsgstartcondrespStart",$condition,$responses[$i]);} # save the association handle $$handle_ref[0] =~ s/^\"//; $$handle_ref[0] =~ s/\"$//; $handle_str = $handle_str . $handle_comma . $$handle_ref[0]; $handle_comma = ","; $num_handles++; } } # if there is an association, see if it's already active else { if ($$flag_ref[0] == $STARTMON) { # active flag is on printEMsg("EMsgstartcondrespAlreadyStarted",$condition,$responses[$i]); $errmcli_rc = ERRM_CLI_USER_ERROR; } # if it's not active, add the association handle to the handle array else { if ($Verbose) { printIMsg("IMsgstartcondrespStart",$condition,$responses[$i]);} $$handle_ref[0] =~ s/^\"//; $$handle_ref[0] =~ s/\"$//; $handle_str = $handle_str . $handle_comma . $$handle_ref[0]; $handle_comma = ","; $num_handles++; } } } } # end of for loop } # end of else there is a condition and response(s) # make a string of 1's to use in the runact command for on-flags for ($i=0;$i<=$num_handles;$i++) { $flag_str = $flag_str . $flag_comma . "$STARTMON"; $flag_comma = ","; } $rc = 0; # make sure there's something to activate if ($num_handles >=0) { # set CT_MANAGEMENT_SCOPE to original setting, in case it was used set_orig_rmc_scope; # if the destination node was not specified, make a local association. # Make sure rmc scope is set to local scope. if ($locator eq "") { $ENV{CT_MANAGEMENT_SCOPE} = $RMC_LOCAL_SCOPE; # $other_opts = ""; } # # a locator was specified, use it with the -n flag on runact # else { # $other_opts = " -n $locator "; # } else { # use DM/SR/Local scope if scope not set and there's a locator check_set_cluster_scope; } # call runact to start monitoring if ($Trace) { print STDERR "$PROGNAME: calling runact-api\n";} #`$CTBINDIR/$RUNACT $passopts -c $other_opts $RSCASSC SetActiveFlags ActiveFlags='{$flag_str}' AssoRHs='{$handle_str}'`; @cmd_out = `$CTBINDIR/runact-api -I $DELIMITERI -D $DELIMITERO -c "${RSCASSC}${DELIMITERI}${locator}${DELIMITERI}SetActiveFlags${DELIMITERI}ActiveFlags${DELIMITERI}{$flag_str}${DELIMITERI}AssoRHs${DELIMITERI}{$handle_str}" 2>&1`; $rc = $?; $rc = process_exit_code($rc); if ($Trace) { print STDERR "runact-api results:\n"; print STDERR "@cmd_out";} if ($Trace) { print STDERR "$PROGNAME: runact-api returned $rc\n";} # show any errors if there was a bad rc if ($rc != 0) { process_api_error($DELIMITERO,$rc,@cmd_out); } # if runact command failed due to RMC CLI user error 73620 # set ERRM CLI user error and go to next condition/response if ($rc == $RMC_CLI_USER_ERROR) { $errmcli_rc = ERRM_CLI_USER_ERROR; } else { # if runact command failed, print RMC error message and exit if ($rc != 0) { #printCEMsg("EMsgERRMcliUnExpectRMCrc",$rc); exit(ERRM_CLI_RMC_ERROR); } } # check for locked attribute if ($#cmd_out >= 0) { # see if locked rc is set (=2) foreach $line (@cmd_out) { @action_resp = split(/$DELIMITERO/, $line); if ($action_resp[2] == 2) { push @locked_assocrh, $action_resp[$#action_resp]; } } # get condition and response names for the associations ($rc, $cond_names, $resp_names) = find_names_from_assoc($locator, @locked_assocrh); # print error messages for locked resource for ($j=0; $j<=$#$cond_names;$j++) { printEMsg("EMsgstartcondrespAssocLocked",$$cond_names[$j],$$resp_names[$j]); $errmcli_rc = ERRM_CLI_USER_ERROR; } } } if ($Verbose) { printIMsg("IMsgstartcondrespEnd");} if ($errmcli_rc == 0) { exit($rc);} else { exit($errmcli_rc);} #--------------------------------------------------------------------# # End Main Code # #--------------------------------------------------------------------# #--------------------------------------------------------------------# # parse_cmd_line - Parse the command line for options and operands. # # Set appropriate global variables as outlined below, make sure we # # have a valid combination of arguments / options. # # # # Return: # # $rc 0 Command line parsed fine, no problem. # # ERRM_CLI_BAD_FLAG Command line contained a bad flag. # # $resource Name of resource to be removed. # # # # Global Variables Modified: # # $Verbose output True (-V) turn Verbose mode on. # # $Trace output True (-T) turn Trace mode on. # # $Opt_Lock output True (-U) lock specified # # $Opt_Unlock output True (-U) unlock specified # #--------------------------------------------------------------------# sub parse_cmd_line { my(@original_argv) = @ARGV; my $condition_name = ""; # condition name my @responses = (); # array of response names my $i = 0; # simple counter my $rc = 0; # return code my %opts = (); # Process the command line... if (!GetOptions(\%opts, 'h' , 'U' , 'L' , 'V' , 'T')) { # Gather options; # if errors &print_usage; # display proper usage return ERRM_CLI_BAD_FLAG; # return bad rc - bad flag } # process h flag if (defined $opts{h}) { # -h, help request &print_usage; # print usage statement exit(0); # all done with good return! } if (defined $opts{T}) { # -T turn trace on $Trace = $TRUE; } if (defined $opts{V}) { # -V turn verbose mode on $Verbose = $TRUE; } # Get the arguments... # Operands: Condition [Response [Response ...]] if ($#ARGV >= 0) { # must have at least 1 # first one is Condition name $condition_name = shift @ARGV; # the rest are responses @responses = @ARGV; } # end of processing valid operands else { # not enough operands printCEMsg("EMsgERRMcliInvalidNumberOfOperands"); &print_usage; return ERRM_CLI_BAD_OPERAND; } # check for lock/unlock flags if ((defined $opts{L}) || (defined $opts{U})) { # -U,-L for unlock,lock # set global flag if ( defined $opts{L} ) { $Opt_Lock = $TRUE; } if ( defined $opts{U} ) { $Opt_Unlock = $TRUE; } # these flags are not allowed together or with the other flags (qr) if ( $Opt_Lock && $Opt_Unlock ) { printCEMsg("EMsgERRMcliImproperUsageCombination","L","U"); &print_usage; return ERRM_CLI_BAD_FLAG; } # must have 1 condition and 1 response if ( ($condition_name eq "") || ($#responses != 0) ) { printCEMsg("EMsgERRMcliInvalidNumberOfOperands"); &print_usage; return ERRM_CLI_BAD_OPERAND; } } return(0, $condition_name, @responses); # success } # end parse_cmd_line #--------------------------------------------------------------------# # print_usage : print the usage statement (syntax) to stdout. # #--------------------------------------------------------------------# sub print_usage { &printIMsg("IMsgstartcondrespUsage52B"); } # end print_usage