#!/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 = "@(#)88 1.19 src/rsct/rm/ConfigRM/cli/bin/stoprpdomain.perl, configrmcli, rsct_rady, rady2035a 7/26/16 06:54:55" ###################################################################### # # # Module: stoprpdomain # # # # Purpose: # # stoprpdomain - brings an online RSCT peer domain offline. # # # # Syntax: # # stoprpdomain [-h] [-f] [-w [-s Seconds]] [-TV] PeerDomain # # # # 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. # # -w Wait. When -w is specified, the command will wait for # # the peer domain 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 the peer domain 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 the peer # # domain is 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. # # # # Operands: # # PeerDomain The name of the online peer domain to be brought # # offline. # # # # Description: # # The stoprpdomain command brings all the nodes which are currently# # online in the peer domain offline. The peer domain definition # # is not removed from the nodes. # # # # The command must be run on a node that is online in the peer # # domain. If the command is run on a node that is offline to the # # peer domain, no action is performed. # # # # The -f force flag must be used to override a subsystem's # # rejection of the request to take the peer domain offline. A # # subsystem may reject the request if a peer domain resource is # # busy, for example. Specifying the -f force flag in this # # situation indicates to the subsystems that the peer domain must # # be brought offline. # # # # 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 peer domain ApplDomain offline and nodeA is one # # of the nodes defined and online to this peer domain, run the # # following command on nodeA: # # stoprpdomain ApplDomain # # # # 2. To bring the peer domain ApplDomain offline, nodeA is one of # # the nodes defined and online to this peer domain, and the stop# # request is not to be rejected by any subsystem, run the # # following command on nodeA: # # stoprpdomain -f ApplDomain # # # # Man Page: # # For the most current detailed description of this command see # # the stoprpdomain man page in /opt/rsct/man. # # # #--------------------------------------------------------------------# # Inputs: # # /opt/rsct/msgmaps/configrmcli.stoprpdomain.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. # # 020202 JAC 79963: weed out stoprsrc error messages. # # 020207 JAC 80121: Make printing of c-api results a trace msg. # # 020421 JAC 82248: Rename stopcluster to stoprpdomain. # # 020428 JAC 82316: Call process_exit_code to check $rc. # # 020502 JAC 82564: Set local scope before calling stoprsrc-api. # # 020502 JAC 82564: Set local scope before calling stoprsrc-api. # # 020530 JAC 82589: Use stoprsrc-api instead of stoprsrc. # # 030324 JAC 93122: Don't specify default command arguments. # # 040407 JAC 105863: Use escape_chars for "\" searches. # # 050406 JAC 119510: Add rc when calling process_api_error. # # 051215 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. Make sure the cluster exists and is not already offline. # # 4. Check to see if the force flag was set. # # 5. Call RMC command stoprsrc. Also pass along -VT if necessary. # # 6. 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 CT_cli_input_utils qw(escape_chars); 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 process_api_error process_exit_code get_opstate_by_name get_opstate_by_name_rc get_domain_type); use CRM_cli_include qw($TRUE $FALSE $LOW_PORT $HIGH_PORT $RSCLUSTER $RMC_CLI_USER_ERROR $RMC_OPSTATE_ONLINE $RMC_OPSTATE_OFFLINE $LOCAL_SCOPE $CTBINDIR $CTDIR); #--------------------------------------------------------------------# # Global Variables # #--------------------------------------------------------------------# $Trace = $FALSE; # default - trace off $Verbose = $FALSE; # default - verbose turned off $Opt_Force = $FALSE; # default - no Force option $Opt_Synchronous = $FALSE; # default - no waiting $PROGNAME = "stoprpdomain"; # 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 $cluster_name = ""; # cluster to stop my %cluster_opstates = (); # cluster opstates my %cluster_opstates_new = (); # cluster opstates refreshed my @clusters = (); # clusters of the node my $one_cluster = ""; # one cluster name my $found = 0; # boolean value my $i = 0; # counter my @cmd_out = (); # stoprsrc command result my $wait_timeout = 300; # wait timeout value my $wait_poll_int = 30; # wait polling interval my $TIMED_OUT = $FALSE; # check timeout my $passopts = ""; # TV options to pass to RMC CLI my $other_opts = ""; # parameters to pass to RMC CLI #--------------------------------------------------------------------# # Main Code # #--------------------------------------------------------------------# my $rc = 0; my $state_rc = 0; # set local scope $ENV{CT_MANAGEMENT_SCOPE} = $LOCAL_SCOPE; # parse the command line, exit if there are errors ($rc, $cluster_name, $wait_timeout) = &parse_cmd_line; ($rc == 0) || error_exit($rc); if ($Verbose) { printIMsg("IMsgstoprpdomainStart",$cluster_name); } if ($Trace) { $passopts = $passopts." -T"; } if ($Verbose) { $passopts = $passopts." -V"; } # 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}; } } # Do some escaping on strings. Do the escape character first # for anything that's a string, escape any inner \ #$cluster_name =~ s/\\/\\\\/g; # for anything that's a string, escape any inner double quotes #$cluster_name =~ s/\"/\\\"/g; $cluster_name = escape_chars($cluster_name); # get the cluster opstate info %cluster_opstates = get_opstate_by_name($RSCLUSTER); # get a list of the cluster names for this node @clusters = keys %cluster_opstates; # make sure the cluster to stop exists $found = $FALSE; $i = 0; while (!$found && ($i <= $#clusters)){ if ($clusters[$i] eq $cluster_name) { $found = $TRUE;} $i++; } # print error message if the cluster name wasn't in the list if (!$found) { printEMsg("EMsgstoprpdomainClusterNotFound",$cluster_name); exit(CRM_CLI_USER_ERROR); } # check to see if it's already offline - which is ok if ($cluster_opstates{$cluster_name} != $RMC_OPSTATE_ONLINE) { printIMsg("IMsgstoprpdomainAlreadyOffline",$cluster_name); exit(0); } # set the force option, if specified if ($Opt_Force) { $other_opts = "::Force::1"; } #93122 - comment out specifying the default command argument #else { $other_opts = "::Force::0"; } # Quit here for CAA domain type if(get_domain_type()) { #printCEMsg("EMsgConfigRMCmdNotSupported"); exit (CRM_CLI_SUCCESS); } # call stoprsrc if ($Trace) { print STDERR "$PROGNAME: calling stoprsrc-api\n";} #@cmd_out = `$CTBINDIR/stoprsrc $passopts -s "Name==\\\"$cluster_name\\\"" $RSCLUSTER $other_opts 2>&1`; @cmd_out=`$CTBINDIR/stoprsrc-api -s ${RSCLUSTER}::Name==\\\"${cluster_name}\\\"${other_opts} 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";} if ($Trace) { print STDERR "$PROGNAME: stoprsrc-api returned $rc\n";} # show any errors if there was a bad rc if ($rc != 0) { process_api_error("::",$rc,@cmd_out); } # return ConfigRM CLI user error if it's an RMC CLI user error if ($rc == $RMC_CLI_USER_ERROR) { exit(CRM_CLI_USER_ERROR);} # if stoprsrc failed for something else, print RMC error message and exit if ($rc != 0) { # printCEMsg("EMsgConfigRMcliUnExpectRMCrc",$rc); exit(CRM_CLI_RMC_ERROR); } $SIG{ALRM} = sub { die "timeout" }; # if wait until stopped selected if ($Opt_Synchronous) { # use $i to check for timeout exceeded $i = 0; $TIMED_OUT = $FALSE; # check opstate until offline or timeout exceeded while ( ($cluster_opstates{$cluster_name} != $RMC_OPSTATE_OFFLINE) && (!$TIMED_OUT) ) { sleep($wait_poll_int); $i = $i + $wait_poll_int; eval{ alarm($wait_timeout); ($state_rc, %cluster_opstates_new) = get_opstate_by_name_rc($RSCLUSTER); alarm(0); }; if ($@) { $i=$i+$wait_timeout; } if ($state_rc == 0) { %cluster_opstates = %cluster_opstates_new; } if ( ($cluster_opstates{$cluster_name} != $RMC_OPSTATE_OFFLINE) && ($i > $wait_timeout) && ($wait_timeout != 0) ){ printCEMsg("EMsgConfigRMcliWaitTimedOut"); $rc = CRM_CLI_ERROR; $TIMED_OUT = $TRUE; } } } if ($Verbose) { printIMsg("IMsgstoprpdomainEnd",$cluster_name); } exit($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. # # $cluster_name Name of cluster to create. # # $wait_timeout Wait timeout value. # # # # Global Variables Modified: # # $Verbose output True (-V) turn Verbose mode on. # # $Trace output True (-T) turn Trace mode on. # # $Opt_Force output True (-f) Force option specified. # # $Opt_Synchronous output True (-w) Wait. # #--------------------------------------------------------------------# sub parse_cmd_line { my(@original_argv) = @ARGV; my $cluster_name = ""; # cluster name my $wait_timeout = 300; # wait timeout value my %opts = (); # Process the command line... if (!&getopts('hfws: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 force mode on $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("EMsgstoprpdomainInvTimeoutSeconds","$opts{s}"); &print_usage; return CRM_CLI_BAD_FLAG; } } # Get the arguments... # Operands: cluster followed optionally by node names if ($#ARGV == 0) { # cluster name $cluster_name = shift @ARGV; # get cluster name } else { # cluster name not specified or invalid operands printCEMsg("EMsgConfigRMcliInvalidNumberOfOperands"); &print_usage; return CRM_CLI_BAD_OPERAND; } return(0, $cluster_name, $wait_timeout); # success } # end parse_cmd_line #--------------------------------------------------------------------# # print_usage : print the usage statement (syntax) to stdout. # #--------------------------------------------------------------------# sub print_usage { &printIMsg("IMsgstoprpdomainUsageW"); } # end print_usage