#!/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 = "@(#)80 1.15.1.14 src/rsct/rm/ER/cli/bin/stopcondresp.perl, errmcli, rsct_rady, rady2035a 11/12/15 16:39:05" ###################################################################### # # # Module: stopcondresp # # # # Purpose: # # stopcondresp - stop monitoring a condition that has a response # # # # Syntax: # # stopcondresp [-h] [-q] [-TV] Condition[:Node_name] [Response # # [Response ...]] # # # # stopcondresp [-h] -U|-L [-TV] Condition[:Node_name] Response # # # # Flags: # # -h help - writes this command's usage statement to stdout # # -q Does not return an error when either condition or # # response does not exist or when the condition linked # # to the response is not being monitored. # # -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 stopcondresp command stops monitoring of a condition that # # has a linked response. If no response is specified, all of the # # linked responses for the condition are stopped. If more than # # one response is specified, only those linked responses are # # stopped. When the condition occurs, the response is not run. # # If no responses are active for a condition, the condition is # # no longer monitored. # # # # 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. Stop monitoring the condition "JFS space used" with the # # response "Broadcast event on-shift": # # stopcondresp "JFS space used" "Broadcast event on-shift" # # 2. Stop monitoring the condition "JFS space used" for all of # # its linked responses: # # stopcondresp "JFS space used" # # # # Man Page: # # For the most current detailed description of this command see # # the stopcondresp man page in /opt/rsct/man. # # # #--------------------------------------------------------------------# # Inputs: # # /opt/rsct/msgmaps/errmcli.stopcondresp.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. # # 010119 JAC 67471: Completed stopcondresp command. # # 010306 JAC 72063: Message EMsgstopcondrespCondNotInAssoc is not # # in msgcat. Comment and use print for now. # # 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. # # 020606 JAC 83872: 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. # # 030630 JAC 96546: Define subroutine change_locked_attr. # # 071026 JAC 146726: set delimiter for calls to -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 stop 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. # # 7. Call RMC command runact using the action SetActiveFlags with # # the array of association handles and a matching array of 0'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 process_exit_code process_api_error check_set_cluster_scope $DELIMITERO $DELIMITERI $CTDIR $CTBINDIR $STOPMON $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 $Quiet_req = $FALSE; # is -q requested for quiet? $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 = "stopcondresp"; # 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 $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); } if ($Quiet_req) { # don't care about it exit(0); } printEMsg("EMsgstopcondrespConditionNotFound",$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); } if ($Quiet_req) { # don't care about it exit(0); } printEMsg("EMsgstopcondrespCondNotInAssoc",$condition); exit(ERRM_CLI_USER_ERROR); } # if there are associations, save the handles else { if ($Verbose) { printIMsg("IMsgstopcondrespStartNoResp",$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: # make sure it exists, 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 { if (!$Quiet_req) { printEMsg("EMsgstopcondrespResponseNotFound",$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 there's no association, skip over this response # but set return code if not in quiet mode if ($rc != 0) { if (!$Quiet_req) { printEMsg("EMsgstopcondrespCondRespNotFound",$condition,$responses[$i]); $errmcli_rc = ERRM_CLI_USER_ERROR; } } else { # association exists # if only changing Locked attribute, do it and leave if ($Opt_Lock || $Opt_Unlock) { # 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("IMsgstopcondrespEnd");} exit($rc); } # see if it's already deactived if ($$flag_ref[0] == $STOPMON) { # active flag is off if (!$Quiet_req) { printEMsg("EMsgstopcondrespAlreadyStopped",$condition,$responses[$i]); $errmcli_rc = ERRM_CLI_USER_ERROR; } } # if it's active, add the association handle to the handle array else { if ($Verbose) { printIMsg("IMsgstopcondrespStart",$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 else association exists } # end response exists } # end of for loop } # end of else there is a condition and response(s) # make a string of 0's to use in the runact command for off-flags for ($i=0;$i<=$num_handles;$i++) { $flag_str = $flag_str . $flag_comma . "$STOPMON"; $flag_comma = ","; } $rc = 0; # make sure there's something to stop 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 for NodeNameList # 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 stop 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("EMsgstopcondrespAssocLocked",$$cond_names[$j],$$resp_names[$j]); $errmcli_rc = ERRM_CLI_USER_ERROR; } } } if ($Verbose) { printIMsg("IMsgstopcondrespEnd");} 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. # # $Quiet_req output True (-q) quiet 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 = (); my $lock_flag = ""; # for invalid flag message my $lock_flag2 = ""; # for invalid flag messag # Process the command line... if (!GetOptions(\%opts, 'h' , 'q' , '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! } # process q flag if (defined $opts{q}) { # -q, quiet request $Quiet_req = $TRUE # set quiet flag } 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; $lock_flag = "L"; } if ( defined $opts{U} ) { $Opt_Unlock = $TRUE; $lock_flag = "U"; } # these flags are not allowed together or with the other flags (qr) if ( $Opt_Lock && $Opt_Unlock ) { $lock_flag = "L"; $lock_flag2 = "U"; } if (defined $opts{r}) { $lock_flag2 = "r";} if ( $lock_flag2 ne "" ) { printCEMsg("EMsgERRMcliImproperUsageCombination",$lock_flag,$lock_flag2); &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("IMsgstopcondrespUsage52B"); } # end print_usage