#!/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 = "@(#)74   1.13.1.8   src/rsct/rm/ER/cli/bin/mkcondresp.perl, errmcli, rsct_rady, rady2035a 11/12/15 16:39:48"
######################################################################
#                                                                    #
# Module: mkcondresp                                                 #
#                                                                    #
# Purpose:                                                           #
#   mkcondresp - link an existing condition to an existing response  # 
#                                                                    #
# Syntax:                                                            #
#   mkcondresp [-h] [-T] [-V] Condition[:Node_name] Response         #
#              [Response ...]                                        #
# Flags:                                                             #
#   -h      help - writes this command's usage statement to stdout   #
#   -T      Trace. IBM Support Center use only.                      #
#   -V      Verbose.                                                 #
#                                                                    #
# Operands:                                                          #
#   Condition   The name of the existing Condition to be linked to   #
#           the existing Response.  The Condition is always specified#
#           first.  Node_name specifies where the condition (and     #
#           responses) is defined.                                   #
#   Response [Response ...]                                          #
#           The names of one or more Responses to be linked to the   #
#           existing Condition.  Specifying more than one Response   #
#           links all specified responses to the specified Condition.#
#                                                                    #
# Description:                                                       #
#   The mkcondresp command creates a link between a condition and a  #
#   response. More than one response may be linked with a condition. #
#   You can start monitoring for this condition and its linked       #
#   response later by using the startcondresp command.               #
#                                                                    #
# 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. Link existing condition "JFS space used" to existing response #
#      "Broadcast event on-shift":                                   #
#      mkcondresp "JFS space used" "Broadcast event on-shift"        #
#   2. Link existing condition "JFS space used" to existing responses#
#      "Broadcast event on-shift" and "E-mail root anytime":         #
#      mkcondresp "JFS space used" "Broadcast event on-shift"  \     #
#                 "E-mail root anytime"                              #
#                                                                    #
# Man Page:                                                          #
#   For the most current detailed description of this command see    #
#   the mkcondresp man page in /opt/rsct/man.                   #
#                                                                    #
#--------------------------------------------------------------------#
# Inputs:                                                            #
#   /opt/rsct/msgmaps/errmcli.mkcondresp.map - message 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.                        #
#   001228 JAC 67470: Completed mkcondresp command.                  #
#   010103 JAC 70296: Make TRUE/FALSE come from utils.               #
#   010109 JAC 70406: Update syntax to remove -c and -r flags.       #
#   010123 JAC 70355: Updates for final messages ship.               #
#   010129 JAC 70951: Shift rc after RMC calls if error occurs.      #
#   010301 JAC 71185: Continue to make resources even if a           #
#                     condition or response is not found.            #
#   010303 JAC 71044: Comment out code to name the association.      #
#   010403 JAC 72894: Eliminate extra call to lsrsrc to get handle   #
#   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.   #
#   020306 JAC 80865: Fix for multiple associations using locator.   #
#   020416 JAC 81754: Fix exit code checking and use mkrsrc-api.     #
#   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.                             #
#   071026 JAC 146726: set delimiter for -api calls.                 #
######################################################################

#--------------------------------------------------------------------#
# 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 create condition-response assoc.  #
# 2. Print usage if -h specified                                     #
# 3. Make sure one and only one condition is specified and that it   #
#    exists.                                                         #
# 4. Make sure all responses that are specified exist.               #
# 5. Find the resource handles for the condition and responses.      #
# 6. Call RMC command mkrsrc to create an association resource for   # 
#    condition-response pair using the resource handles. Also pass   # 
#    along -VT if necessary.                                         #
# 7. 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_handle get_source_node
                    find_resource_name get_locator_node
                    find_association_handle
                    set_orig_rmc_scope check_set_cluster_scope
                    process_api_error process_exit_code
                    $TRUE $FALSE
                    $DELIMITERO $DELIMITERI
                    $CTDIR $CTBINDIR
                    $RMC_CLI_USER_ERROR $RMC_LOCAL_SCOPE
                    $MKRSRC $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

$PROGNAME = "mkcondresp";               # Program Name for messages
$LSMSG = "$CTBINDIR/ctdspmsg";          # list / display message rtn
$MSGCAT = "errmcli.cat";                # msg catalogue for this cmd
$ENV{'MSGMAPPATH'} = "$CTDIR/msgmaps";  # msg maps used by $LSMSG

#--------------------------------------------------------------------#
# Variables                                                          #
#--------------------------------------------------------------------#
my $condition = "";                     # condition to use  -c
my @responses = ();                     # responses to use  -r
my $Cond_handle = "";                   # handle for condition
my @Resp_handle = ();                   # handle for response
my $response_handle = "";               # handle for response
my $Assoc_name = "";                    # association name
my $passopts = "";                      # options to pass to RMC
my $other_opts = "";                    # options to pass to RMC
my $node_select = "";                   # to specify a specific node
my $nhandle;                            # handle counter
my $i;                                  # counter
my $temp_name = "";                     # holds condition name
my $locator = "";                       # locator
my @cmd_out = ();                       # command output

#--------------------------------------------------------------------#
# 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 || $Verbose) { $passopts = $passopts." -"; }

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 the handle
($rc, $Cond_handle) = get_handle($condition, $RSCCOND, $locator);

# if RMC CLI user error, exit
if ($rc == $RMC_CLI_USER_ERROR) {
    exit(ERRM_CLI_USER_ERROR);
    }

if ($rc < 0) {                      # condition name not found
    printEMsg("EMsgmkcondrespConditionNotFound",$condition);
    exit(ERRM_CLI_USER_ERROR);
    }

# initialize response handle counter to 0
$nhandle = -1;

# for each response, see if an association already exists 
for ($i=0; $i<=$#responses; $i++) {

   # make sure this response already exists and get the handle
   ($rc, $response_handle) = get_handle($responses[$i], $RSCEVRS, $locator);

   # if RMC CLI user error, set ERRM CLI user error
   if ($rc == $RMC_CLI_USER_ERROR) {
       $errmcli_rc = ERRM_CLI_USER_ERROR;
       }
   else { 
      if ($rc < 0) {                  # response name not found
          printEMsg("EMsgmkcondrespResponseNotFound",$responses[$i]);
          $errmcli_rc = ERRM_CLI_USER_ERROR;
          }

      else {                          # response name exists

         # check to see if the condition - resource are already in Association
         $rc = find_association_handle($Cond_handle,$response_handle,$locator);
         if ($rc == 0) {             # already defined
             printEMsg("EMsgmkcondrespCondRespExists",$condition,$responses[$i]);
             $errmcli_rc = ERRM_CLI_USER_ERROR;
             }
          else {
             # if RMC CLI user error, set ERRM CLI user error
             if ($rc == $RMC_CLI_USER_ERROR) {
                $errmcli_rc = ERRM_CLI_USER_ERROR;
                }
             else {                  # save response handle to delete it
                $nhandle++;
                $Resp_handle[$nhandle] = $response_handle;
                }
             }
          }
       }
}
  
# make the association resource for each condition-response pair
for ($i=0; $i<=$#Resp_handle; $i++) {

   # 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 {
#     $node_select = " NodeNameList='{$locator}'";
      $node_select = "${DELIMITERI}NodeNameList${DELIMITERI}{$locator}";

      # use DM/SR/Local scope if scope not set
      check_set_cluster_scope;
   }

   if ($Verbose) { printIMsg("IMsgmkcondrespStart",$condition,$responses[$i]);}
   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[$i]' $node_select`;
   @cmd_out=`$CTBINDIR/mkrsrc-api -I $DELIMITERI -D $DELIMITERO ${RSCASSC}${DELIMITERI}ConditionHandle${DELIMITERI}${Cond_handle}${DELIMITERI}EventResponseHandle${DELIMITERI}${Resp_handle[$i]}${node_select} 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;
      }

   # if mkrsrc command failed, print RMC error message and exit
   else {
      if ($rc != 0) {
         printCEMsg("EMsgERRMcliUnExpectRMCrc",$rc);
         exit(ERRM_CLI_RMC_ERROR);
         }
      }
}       # end for loop creating associations

if ($Verbose) { printIMsg("IMsgmkcondrespEnd");}


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.      #
#   $condition_name          Name of the condition                   #
#   @responses               Names of one or more responses          #
#                                                                    #
# Global Variables Modified:                                         #
#   $Verbose           output   True (-V) turn Verbose mode on.      #
#   $Trace             output   True (-T) turn Trace mode on.        #
#--------------------------------------------------------------------#
sub parse_cmd_line 
{
my(@original_argv) = @ARGV;
my $condition_name = "";                # condition name    
my @responses = ();                     # response names
my %opts = ();
my $i;

# Process the command line...
if (!GetOptions(\%opts,
		'h' ,
		'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 >= 1) {                      # must have at least 2 
   
   # 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;
   }

return(0, $condition_name, @responses); # success
}   # end parse_cmd_line


#--------------------------------------------------------------------#
# print_usage : print the usage statement (syntax) to stdout.        #
#--------------------------------------------------------------------#
sub print_usage
{
&printIMsg("IMsgmkcondrespUsage51D");
}   # end print_usage