#!/usr/bin/perl # IBM_PROLOG_BEGIN_TAG # This is an automatically generated prolog. # # # # Licensed Materials - Property of IBM # # (C) COPYRIGHT International Business Machines Corp. 2001,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 = "@(#)87 1.32 src/rsct/rm/ConfigRM/cli/bin/stoprpnode.perl, configrmcli, rsct_rady, rady2035a 1/31/18 10:16:57" ###################################################################### # # # Module: stoprpnode # # # # Purpose: # # stoprpnode - brings a node offline to an RSCT peer domain. # # # # Syntax: # # stoprpnode [-h] [-f] [-w [-s Seconds]] [-TV] [-m 0|1] Node_name # # [Node_name ...] # # # # stoprpnode [-h] [-f] -F File [-w [-s Seconds]] [-TV] [-m 0|1] # # # # Flags: # # -h Help. Writes the command's usage statement to standard # # output. # # -f Force. Forces the subsystems to accept the stop request # # when it otherwise would not, as when resources are # # allocated, for example. # # -F File The file containing the nodes names to be taken offline # # in the peer domain. The node names are defined as # # Node_name operands or in a file, not both. When in a # # file, each line of the file is scanned for one node # # name. Comments may be placed on each line, but after # # the comment character "#". Lines that start (col 1) with # # "#" or are entirely blank are ignored. Use -F "-" to # # specify STDIN as the input file. # # -w Wait. When -w is specified, the command will wait for # # the all of the specified nodes to be offline before the # # command completes. Use the -s flag to specify how long # # the command waits. # # -s Seconds. Used with the -w flag to specify how long in seconds# # the command is to wait for all of the specified nodes to # # be offline. If the waiting exceeds the number of seconds,# # the command returns, but the offline operation continues.# # The default is 300 seconds (5 minutes). Use 0 to specify# # that the command should not return until all of the # # specified nodes are offline (no timeout on waiting). # # -T Trace. Writes the command's trace messages to standard # # error. For your software-service organization's use only.# # -V Verbose. Writes the command's verbose messages to # # standard output. # # -m Enable or disable application of global maintenance mode # # configuration, when stopping the specified node(s). # # If [-m 0] is specified, then maintenance mode will not # # be applied. If [-m 1] is specified, then maintenance # # mode will be applied. # # # # Operands: # # Node_name The name of the node to be brought offline to the # # peer domain. The node name is the peer domain node # # name of the node. The peer domain node names can be # # displayed using the lsrpnode command. # # # # Description: # # The stoprpnode command brings an online node offline to a peer # # domain. The peer domain is determined by the online peer domain # # of where the command is run. The command must be run from a # # node that is online to the desired peer domain. # # # # The -f force flag must be used to override a subsystem's # # rejection of the request to take a node offline. A subsystem # # may reject the request if a node resource is busy, for example. # # Specifying the -f force flag in this situation indicates to the # # sub systems that the node must be brought offline. # # # # If this command is used to bring more than one node offline by # # specifying more than one Node_name operand, and the node that # # this command is running on is in the list, it will be brought # # offline last. # # # # Exit Values: # # 0 CRM_CLI_SUCCESS Command completed successfully. # # 1 CRM_CLI_RMC_ERROR Command terminated due to an underlying # # RMC error. # # 2 CRM_CLI_ERROR Command terminated due to an underlying # # error in the command script. # # 3 CRM_CLI_BAD_FLAG Command terminated due to user # # specifying an invalid flag. # # 4 CRM_CLI_BAD_OPERAND Command terminated due to user # # specifying a bad operand. # # 5 CRM_CLI_USER_ERROR Command terminated due to a user error, # # for example specifying a name that # # already exists. # # # # Examples: # # 1. To bring the node nodeB, which is online to ApplDomain, # # offline, and nodeA is also online to ApplDomain, run the # # following command on nodeA: # # stoprpnode nodeB # # # # 2. To bring the node nodeB, which is online to ApplDomain, # # offline and force the offline request, and nodeA is also # # online to ApplDomain, run the following command on nodeA: # # stoprpnode -f nodeB # # # # Man Page: # # For the most current detailed description of this command see # # the stoprpnode man page in /opt/rsct/man. # # # #--------------------------------------------------------------------# # Inputs: # # /opt/rsct/msgmaps/configrmcli.stoprpnode.map - # # message mapping # # # # Outputs: # # stdout - none. # # stderr - any error message. # # # # External Ref: # # Commands: ctdspmsg # # Modules: CRM_cli_utils.pm, CRM_cli_rc.pm, # # CRM_cli_include.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: # # 010806 JAC 75435: Initial design & write. # # 010827 JAC 75436: Change some initial checking. # # 011219 JAC 78807: Don't resolve node names or check if in cluster# # 020202 JAC 79963: weed out stoprsrc error messages. # # 020207 JAC 80121: Make printing of c-api results a trace msg. # # 020325 JAC 80304: Put back some checking to stop source last. # # 020422 JAC 82248: Rename stopclnode to stoprpnode. # # 020428 JAC 82316: Call process_exit_code to check $rc. # # 020503 JAC 82564: Set peer domain scope before calling stoprsrc. # # 020530 JAC 82589: Use stoprsrc-api instead of stoprsrc. # # 020711 JAC 84621: Use NodeNameList instead of Name in stoprsrc. # # 030324 JAC 93122: Don't specify default command arguments. # # 040319 JAC 105987: Add -F flag for file input for node names. # # 040406 JAC 106712: Update usage for file options. # # 050218 JAC 111917: Use runact-api instead of stoprsrc. # # 050406 JAC 119510: Add rc when calling process_api_error. # # 050504 JAC 119931: Return $config_rc in stop_ functions. # # 050506 JAC 119921: Fix verbose message when node list not known. # # 051218 JAC 131665: Add -w/-s to make command synchronous. # # 100604 NG 165141: Add check for CAA domain type # ###################################################################### #--------------------------------------------------------------------# # General Program Flow/Logic: # # # # 1. Parse command line flags and operands. # # 2. Print usage if -h specified # # 3. Set the force option if specified. # # 4. Resolve the name of the node the command will run on and make # # sure that it's online in the cluster. # # 5. If no target is specified, make the node you're on the target. # # 6. Resolve the target node names and make sure they are in the # # cluster and online # # 7. If the node we're on is a target, make sure it's processed last.# # 8. Call RMC command startrsrc. Also pass along -VT if necessary. # # 9. Return back any errors. # # # #--------------------------------------------------------------------# #--------------------------------------------------------------------# # Included Libraries and Extensions # #--------------------------------------------------------------------# use lib "/opt/rsct/pm"; use locale; use Getopt::Std; use CT_cli_utils qw(printIMsg printEMsg); use CRM_cli_rc qw(CRM_CLI_SUCCESS CRM_CLI_RMC_ERROR CRM_CLI_ERROR CRM_CLI_BAD_FLAG CRM_CLI_BAD_OPERAND CRM_CLI_USER_ERROR); use CRM_cli_utils qw(error_exit printCIMsg printCEMsg check_node_state check_for_nodes get_source_node process_api_error process_exit_code get_nodes_nums_from_file get_opstate_by_name get_opstate_by_name_rc get_domain_type); use CRM_cli_include qw($TRUE $FALSE $RMC_CLI_USER_ERROR $RMC_OPSTATE_ONLINE $RSNODE $RMC_OPSTATE_OFFLINE $RMC_CLI_API_SCOPE_ERROR $PEER_DOMAIN_SCOPE $CTBINDIR $CTDIR $DELIMITER); #--------------------------------------------------------------------# # Global Variables # #--------------------------------------------------------------------# $Trace = $FALSE; # default - trace off $Verbose = $FALSE; # default - verbose turned off $Opt_Force = $FALSE; # default - no Force option $Opt_File_Input = $FALSE; # default - no file $ACTION_NOT_ALLOWED_RC = 32; # retruned by configrm $Opt_Synchronous = $FALSE; # default - no waiting $PROGNAME = "stoprpnode"; # Program Name for messages $LSMSG = "$CTBINDIR/ctdspmsg"; # list / display message rtn $MSGCAT = "configrmcli.cat"; # msg catalogue for this cmd $ENV{'MSGMAPPATH'} = "$CTDIR/msgmaps"; # msg maps used by $LSMSG #--------------------------------------------------------------------# # Variables # #--------------------------------------------------------------------# my @node_names = (); # nodes to be stopped my %node_opstates = (); # nodes in cluster my %node_opstates_new = (); # nodes in cluster refreshed my $resolved_node_names = ""; # resolved nodelist my $unresolved_node_names = ""; # unresolved nodelist my $source_node_name = ""; # cluster node name of source node my $add_source_node = $FALSE; # is source node in stop list my @online_node_names = (); # online nodes to stop my $one_node = ""; # one from nodelist my $source_online = $FALSE; # boolean my $node_online = $FALSE; # boolean my $node_offline = $FALSE; # boolean my $in_list = ""; # reference to array my $not_in_list = ""; # reference to array my @nnodes = (); # number of nodes my $file_name = ""; # file name for node names my $file_error = ""; # error with file my $node_names_file = ""; # reference to node names my $node_nums_file = ""; # reference to node numbers my @node_numbers = (); # nodes in cluster my $Use_stoprsrc = $FALSE; # is env var set to use old way my $force_element = ""; # force for runact my $wait_timeout = 300; # wait timeout value my $wait_poll_int = 30; # wait polling interval my $TIMED_OUT = $FALSE; # check timeout my $NODES_OFFLINE = $FALSE; # check nodes state my $maintenance_mode = ""; # maintenance mode for runact my $Use_DefaultMMode = $TRUE; # assume maintenance mode flag unspecified my $passopts = ""; # TV options to pass to RMC CLI my $other_opts = ""; # parameters to pass to RMC CLI my $delimiter = "#:#"; $DELIMITER = $delimiter; # override so utils don't choke on IPv6 "::" #--------------------------------------------------------------------# # Main Code # #--------------------------------------------------------------------# my $rc = 0; my $config_rc = 0; my $tmp_rc = 0; my $state_rc = 0; # set peer domain scope $ENV{CT_MANAGEMENT_SCOPE} = $PEER_DOMAIN_SCOPE; # parse the command line, exit if there are errors ($rc, $file_name, $wait_timeout, @node_names) = &parse_cmd_line; ($rc == 0) || error_exit($rc); if ($Verbose) { printIMsg("IMsgstoprpnodeStarted"); } if ($Trace) { $passopts = $passopts." -T"; } if ($Verbose) { $passopts = $passopts." -V"; } # if CT_CONFIGRMCLI_METHOD is set, use stoprsrc-api (old way) if (defined $ENV{CT_CONFIGRMCLI_METHOD}) { $Use_stoprsrc = $TRUE; } # set the wait polling interval in case it's used if (defined $ENV{CT_CONFIGRMCLI_POLL_INTERVAL}) { if ( ($ENV{CT_CONFIGRMCLI_POLL_INTERVAL} =~ /^[0-9]+$/) && ($ENV{CT_CONFIGRMCLI_POLL_INTERVAL} >=1) ) { $wait_poll_int = $ENV{CT_CONFIGRMCLI_POLL_INTERVAL}; } } # set the force option, if specified if ($Opt_Force) { $other_opts = "${delimiter}Force${delimiter}1"; $force_element = "${delimiter}ForcedFlag${delimiter}1"; } #93122 - comment out specifying the default command argument #else { $other_opts = "${delimiter}Force${delimiter}0"; } # set default value if ($Use_DefaultMMode) { $maintenance_mode = "${delimiter}MaintenanceModeFlag${delimiter}2"; } # get the nodes opstate info %node_opstates = get_opstate_by_name($RSNODE); # make sure there are nodes in the cluster @nnodes = keys %node_opstates; if ($#nnodes <0) { printCEMsg("EMsgConfigRMcliNoCluster"); exit (CRM_CLI_USER_ERROR); } # find the source name $source_node_name = get_source_node; # get the node names from a file, if specified if ($Opt_File_Input) { # extract the node names from the file ($node_names_file, $node_nums_file) = get_nodes_nums_from_file($file_name); # copy to other array @node_names = @$node_names_file; @node_numbers = @$node_nums_file; } if ($Verbose) { printIMsg("IMsgstoprpnodeNodeList"); foreach $one_node (@node_names) { print(" ", $one_node); } print("\n"); } # make sure the target nodes are in the cluster ($in_list, $not_in_list) = check_for_nodes(\@node_names, \%node_opstates); # for nodes not in the list (not in the cluster), print error message foreach $one_node (@$not_in_list) { printEMsg("EMsgstoprpnodeNotInCluster",$one_node); $config_rc = CRM_CLI_USER_ERROR; } # for nodes in the list (in the cluster), # make sure they're online and then add to list for stopping foreach $one_node (@$in_list) { $node_online = check_node_state($one_node,$RMC_OPSTATE_ONLINE, %node_opstates); if (!$node_online) { printEMsg("EMsgstoprpnodeAlreadyStopped",$one_node); $config_rc = CRM_CLI_USER_ERROR; } # it's online so add to list to stop else { # add it to the list unless it's the source node. # add that one last. if ($one_node eq $source_node_name) { $add_source_node = $TRUE; } else { push (@online_node_names, $one_node); } } } # add the source node last, if needed. if ($add_source_node) { push (@online_node_names, $source_node_name); } # 201252 -- support stoprpnode in CAA from RSCT 3.2.1.0 onwards #if(get_domain_type()) { # #printCEMsg("EMsgConfigRMCmdNotSupported"); # exit (CRM_CLI_SUCCESS); #} # decide whether old way or new way # if CT_CONFIGRMCLI_METHOD is set, do old way if ($Use_stoprsrc) { $tmp_rc = stop_by_stoprsrc($other_opts, \@online_node_names); } # else use new way else { $tmp_rc = stop_by_action($force_element, $maintenance_mode, $other_opts, \@online_node_names); } if ($tmp_rc != 0) { $config_rc = $tmp_rc}; # if wait until started selected if ($Opt_Synchronous) { # use $i to check for timeout exceeded $i = 0; $TIMED_OUT = $FALSE; $NODES_OFFLINE = $FALSE; # check opstate until all nodes offline or timeout exceeded while ( (!$NODES_OFFLINE) && (!$TIMED_OUT) ) { sleep($wait_poll_int); $i = $i + $wait_poll_int; # get new opstates ($state_rc, %node_opstates_new) = get_opstate_by_name_rc($RSNODE); if ($state_rc == 0) { %node_opstates = %node_opstates_new; } # see if everybody's online yet $NODES_OFFLINE = $TRUE; # $state_rc = $RMC_CLI_API_SCOPE_ERROR if this node goes offline # then we can figure all nodes are offline and be done if ( $state_rc != $RMC_CLI_API_SCOPE_ERROR ) { foreach $one_node (@online_node_names) { $node_offline = check_node_state($one_node,$RMC_OPSTATE_OFFLINE, %node_opstates); if (!$node_offline) { $NODES_OFFLINE = $FALSE; } } # check to see if we've timed out if ( (!$NODES_OFFLINE) && ($i > $wait_timeout) && ($wait_timeout != 0) ){ printCEMsg("EMsgConfigRMcliWaitTimedOut"); $config_rc = CRM_CLI_ERROR; $TIMED_OUT = $TRUE; } } } } if ($Verbose) { printIMsg("IMsgstoprpnodeEnded"); } if ($config_rc == 0) { exit($rc); } else { exit($config_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. # # CRM_CLI_BAD_FLAG Command line contained a bad flag. # # $wait_timeout Wait timeout value. # # @node_names Node names to be started. # # # # Global Variables Modified: # # $Verbose output True (-V) turn Verbose mode on. # # $Trace output True (-T) turn Trace mode on. # # $Opt_Force output True (-f) turn force option on. # # $Opt_File_Input output True (-F) file name specified # # $Opt_Synchronous output True (-w) Wait. # #--------------------------------------------------------------------# sub parse_cmd_line { my(@original_argv) = @ARGV; my @node_names = (); # nodes to be started my $file_name = ""; # file name my $wait_timeout = 300; # wait timeout value my %opts = (); # Process the command line... if (!&getopts('hfF:ws:m:VT', \%opts)) { # Gather options; # if errors &print_usage; # display proper usage return CRM_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; } if (defined $opts{f}) { # -f turn on force $Opt_Force = $TRUE; # -f flag specified } if (defined $opts{w}) { # -w for wait $Opt_Synchronous = $TRUE; # -w flag specified } if (defined $opts{s}) { # -s for wait timeout # error if -w is not if (!$Opt_Synchronous) { printCEMsg("EMsgConfigRMcliUnexpectFlag","-s","-w"); &print_usage; return CRM_CLI_BAD_FLAG; } #check the timeout value if ( ($opts{s} =~ /^[0-9]+$/) && ($opts{s} >=0)) { $wait_timeout = $opts{s}; } else { printEMsg("EMsgstoprpnodeInvTimeoutSeconds","$opts{s}"); &print_usage; return CRM_CLI_BAD_FLAG; } } # Get the arguments... # Operands: node names if ($#ARGV >= 0) { # node names @node_names = @ARGV; # get node names } # make sure -F for file used if there are no node names if (($#node_names < 0) && (!defined $opts{F})) { printCEMsg("EMsgConfigRMcliInvalidNumberOfOperands"); &print_usage; return CRM_CLI_BAD_OPERAND; } if (defined $opts{F}) { # -F for file $Opt_File_Input = $TRUE; $file_name = $opts{F}; # make sure file and cmd line not both used for node names if ($#node_names >= 0) { printCEMsg("EMsgConfigRMcliInvalidNumberOfOperands"); &print_usage; return CRM_CLI_BAD_OPERAND; } } if (defined $opts{m}) { $Use_DefaultMMode = $FALSE; my $flag_value = $opts{m}; $maintenance_mode = "${delimiter}MaintenanceModeFlag${delimiter}${flag_value}"; } return(0, $file_name, $wait_timeout, @node_names); # success } # end parse_cmd_line #--------------------------------------------------------------------# # print_usage : print the usage statement (syntax) to stdout. # #--------------------------------------------------------------------# sub print_usage { &printIMsg("IMsgstoprpnodeUsage"); } # end print_usage #--------------------------------------------------------------------# # stop_by_stoprsrc - Stop nodes by using stoprsrc-api. # # # # Return: # # $rc Return code from stoprsrc-api. # # # # Input: # # $options Options to use on stoprsrc-api. # # \@nodes_to_stop Reference to a list of nodes to stop. # # # #--------------------------------------------------------------------# sub stop_by_stoprsrc { my $rc = 0; # return code my $config_rc = 0; # return code for all my $options = shift(@_); # options my $nodes_to_stop = shift(@_); # nodes to remove (array ref) my $one_node = ""; # single node my @cmd_out = (); # stoprsrc command result # for each node to stop, call stoprsrc-api foreach $one_node (@$nodes_to_stop) { if ($Trace) { print STDERR "$PROGNAME: calling stoprsrc-api\n";} #@cmd_out = `$CTBINDIR/stoprsrc $passopts -s "Name==\\\"$one_node\\\"" $RSNODE $other_opts 2>&1`; #@cmd_out=`$CTBINDIR/stoprsrc-api -s ${RSNODE}::Name==\\\"${one_node}\\\"${other_opts} 2>&1`; @cmd_out=`$CTBINDIR/stoprsrc-api -I"$delimiter" -s "${RSNODE}${delimiter}NodeNameList|<{\\\"${one_node}\\\"}${options}" 2>&1`; # capture the return code from stoprsrc-api $rc = $?; $rc = process_exit_code($rc); if ($Trace) { print STDERR "stoprsrc-api results:\n"; print STDERR "@cmd_out"; print STDERR "$PROGNAME: stoprsrc-api returned $rc\n";} # show any errors if there was a bad rc if ($rc != 0) { process_api_error($delimiter,$rc,@cmd_out); } # save rc as ConfigRM CLI user error if it's an RMC CLI user error if ($rc == $RMC_CLI_USER_ERROR) { $config_rc = CRM_CLI_USER_ERROR; } # if stoprsrc failed, print RMC error message and save rc if (($rc != 0) && ($rc != $RMC_CLI_USER_ERROR)) { # printCEMsg("EMsgConfigRMcliUnExpectRMCrc",$rc); $config_rc = CRM_CLI_RMC_ERROR; } } return ($config_rc); } # end stop_by_stoprsrc #--------------------------------------------------------------------# # stop_by_action - Stop nodes by using runact-api. # # # # Return: # # $rc Return code from runact-api. # # # # Input: # # $options Options to use on runact-api. # # \@nodes_to_stop Reference to a list of nodes to stop. # # # #--------------------------------------------------------------------# sub stop_by_action { my $rc = 0; # return code my $config_rc = 0; # return code for all my $action_rc = 0; # return code from action my $options = shift(@_); # options my $maintenance_mode_opts = shift(@_); # maintenance mode options my $stoprsrc_opts = shift(@_); # options in case stoprsrc used my $nodes_to_stop = shift(@_); # nodes to stop (array ref) my $one_node = ""; # single node my $stop_nodes = ""; # list of nodes to stop my $comma_needed = $FALSE; # add comma to list? my @cmd_out = (); # runact output # build a string containing the options to be passed to the runact-api command my $runact_options = "${options}${maintenance_mode_opts}"; # build a string containing the list of node names to stop $stop_nodes = ""; $comma_needed = $FALSE; foreach $one_node (@$nodes_to_stop) { if ( $comma_needed ) { $stop_nodes .= "," . $one_node; } else { $stop_nodes .= $one_node; $comma_needed = $TRUE; } } # call runact-api to stop the nodes if there are nodes to stop if ($#$nodes_to_stop >= 0) { # Defect 161752 #@cmd_out=`$CTBINDIR/runact-api -D"$delimiter" -I"$delimiter" -c "${RSNODE}${delimiter}${delimiter}StopMultipleNodes${delimiter}NodeNames${delimiter}{${stop_nodes}}${runact_options}" 2>&1`; my $cmd = "$CTBINDIR/runact-api -D\"$delimiter\" -I\"$delimiter\" -c ${RSNODE}${delimiter}${delimiter}StopMultipleNodes${delimiter}NodeNames${delimiter}"."\"{${stop_nodes}}\"${runact_options}"; if ($Trace) { print STDERR "$PROGNAME: calling runact-api\n";} if ($Trace) { print STDERR "$PROGNAME: $cmd\n";} @cmd_out=`$cmd 2>&1`; # capture the return code from runact-api $rc = $?; $rc = process_exit_code($rc); if ($Trace) { print STDERR "runact-api results:\n"; print STDERR "@cmd_out"; print STDERR "$PROGNAME: runact-api returned $rc\n";} # show any errors if there was a bad rc if ($rc != 0) { $action_rc = process_api_error_stop_action($delimiter,$rc,@cmd_out); } # save rc as ConfigRM CLI user error if it's an RMC CLI user error if ($rc == $RMC_CLI_USER_ERROR) { $config_rc = CRM_CLI_USER_ERROR; } # if runact-api failed, print RMC error message and save rc if (($rc != 0) && ($rc != $RMC_CLI_USER_ERROR) && ($action_rc != $ACTION_NOT_ALLOWED_RC) ) { # printCEMsg("EMsgConfigRMcliUnExpectRMCrc",$rc); $config_rc = CRM_CLI_RMC_ERROR; } # if the action failed because the active version is not at the correct level # do the stop the old way if ($action_rc == $ACTION_NOT_ALLOWED_RC) { $config_rc = stop_by_stoprsrc($stoprsrc_opts, $nodes_to_stop); } } return ($config_rc); } # end stop_by_action #--------------------------------------------------------------------# # process_api_error_stop_action - 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. # # # # This version checks for api rc=32. This means the action can't # # run on this configuration and we need to go back and use # # stoprsrc-api. # # # # # # # # 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: # # 0 If everything went ok. # # 32 If action failed due to api rc=32. # # # # Global Variables: # #--------------------------------------------------------------------# sub process_api_error_stop_action { my $rc = 0; # returned rc 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 my $line = ""; # scan each line for ERROR foreach $line (@command_output) { # does it start with ERROR? if ($line =~ /^ERROR.*/) { # split it apart based on the delimiter # last one should be error message @error_parts = split /$delimiter/, $line; # check for scope error if ($error_parts[$#error_parts -1] == $RMC_SCOPE_ERROR) { printCEMsg("EMsgConfigRMcliNoCluster"); exit(CRM_CLI_USER_ERROR); } $error_count++; # check for action not allowed error if ($error_parts[$#error_parts -1] == $ACTION_NOT_ALLOWED_RC) { $rc = $ACTION_NOT_ALLOWED_RC; } # output the message (except for scope/action) else { # replace any escaped new lines with new lines $error_parts[$#error_parts] =~ s/\\n/\n/g; # last one should be error message. print it to STDERR. print STDERR $error_parts[$#error_parts]; } } } # print unexpected error if api rc was not 0 and no messages were displayed if (($error_count == 0) && ($api_rc != 0)) { printCEMsg("EMsgConfigRMcliUnexpectErrorRC",$api_rc); } return ($rc) } # end of process_api_error_stop_action