#!/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 = "@(#)89 1.29 src/rsct/rm/ConfigRM/cli/bin/startrpdomain.perl, configrmcli, rsct_rady, rady2035a 11/12/15 16:40:27" ###################################################################### # # # Module: startrpdomain # # # # Purpose: # # startrpdomain - brings an already defined RSCT peer domain # # online. # # # # Syntax: # # startrpdomain [-h] [-A|L] [-t Timeout] # # [-Q QuorumTypeName|QuorumTypeValue] # # [-m Fanout] [-w [-s Seconds]] # # [-TV] PeerDomain # # # # Flags: # # -h Help. Writes the command's usage statement to standard # # output. # # -A Use the configuration of all nodes. -A cannot be used # # with -L. If -A or -L is not specified, the configuration # # of a quorum of nodes is used. # # -L Use the configuration of the local node. -L cannot be # # used with -A. If -A or -L is not specified, the # # configuration of a quorum of nodes is used. # # -t Timeout Timeout interval. The number of seconds to wait for # # the peer domain configuration to be determined from the # # nodes in the peer domain. This value should be long # # enough for the configutation from at least a quorum of # # nodes to be determined. The default value is 20 seconds.# # -Q QuorumTypeName|QuorumTypeValue The Quorum Type to use. The # # quorum type can be specified as a name or a value. A # # valid quorum name can be found from the # # AvailableQuorumTypes class attribute on IBM.PeerDomain. # # -m Fanout Max number of threads to use in parallel operations # # for this start operation only. Overrides default for # # 'PeerDomain' stored as persistent attr in its # # IBM.PeerNode class. # # -w Wait. When -w is specified, the command will wait for # # the peer domain to be online 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 online. # # If the waiting exceeds the number of seconds, the # # command returns, but the online operation continues. The # # default is 300 seconds (5 minutes). Use 0 to specify # # that the command should not return until the peer # # domain is online (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 a previously defined peer domain to be # # brought online. # # # # Description: # # The startrpdomain command brings a defined peer domain online by # # starting the resources on each node belonging to the peer domain.# # # # The command must be run on a node that is defined to the peer # # domain. The command invites all the nodes (whose nominal state # # is online) defined to the peer domain to come online in the peer # # domain every time the command is run for the peer domain. The # # command can be executed more than once in the peer domain. If # # all the nodes defined in the peer domain are already online, no # # action is performed. # # # # A node can only be online to one peer domain at a time. The # # startrpdomain command cannot be run on a node for a peer domain # # when another peer domain is already online for that node. # # # # 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 online and nodeA is one # # of the nodes defined to this peer domain, run the following # # command on nodeA: # # startrpdomain ApplDomain # # # # Man Page: # # For the most current detailed description of this command see # # the startrpdomain man page in /opt/rsct/man. # # # #--------------------------------------------------------------------# # Inputs: # # /opt/rsct/msgmaps/configrmcli.startrpdomain.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: Don't check for cluster already online. # # 011015 JAC 77328: Add timeout and config cmd arguments. # # 020108 JAC 79352: Pass both cmd args when at least 1 is specified# # 020202 JAC 79963: weed out startrsrc error messages. # # 020207 JAC 80121: Make printing of c-api results a trace msg. # # 020421 JAC 82248: Rename startcluster to startrpdomain. # # 020428 JAC 82316: Call process_exit_code to check $rc. # # 020502 JAC 82564: Set local scope before calling startrsrc-api. # # 020530 JAC 82589: Use startrsrc-api instead of startrsrc. # # 020619 JAC 84268: Fix call to startrsrc-api to skip nodelist. # # 020724 JAC 85045: Change -a to -A for command consistency. # # 020822 JAC 86035: Add -L option. # # 020916 JAC 86909: Fix for setting OnlineCriteria option. # # 030324 JAC 93122: Don't specify default command arguments. # # 030421 JAC 93428: Rework 93122. Timeout passed as 0 by startrsrc.# # 040329 JAC 102042: Add -Q quorum flag. # # 040407 JAC 105863: Use escape_chars for "\" searches. # # 040602 JAC 109790: Don't pass Timeout if not specified. (0 ok) # # 040616 JAC 110694: Move where quorum type (-Q) is processed. # # 041118 JMS 104741: make ConfigRM RMC thread fanout configurable # # 050124 JMS 116382: -m instead of -n for fanout # # 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. # # 4. Make sure there are no other clusters online. # # 5. Call RMC command startrsrc. 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 get_source_node process_api_error process_exit_code check_quorum_type get_opstate_by_name get_opstate_by_name_rc get_domain_type); use CRM_cli_include qw($TRUE $FALSE $RSCLUSTER $RMC_CLI_USER_ERROR $RMC_OPSTATE_ONLINE $LOCAL_SCOPE $CTBINDIR $CTDIR); #--------------------------------------------------------------------# # Global Variables # #--------------------------------------------------------------------# $Trace = $FALSE; # default - trace off $Verbose = $FALSE; # default - verbose turned off $Opt_Timeout = $FALSE; # default - no timeout value $Opt_All_Criteria = $FALSE; # default - not all nodes $Opt_Local_Criteria = $FALSE; # default - not local node $Opt_QuorumType = $FALSE; # default - no quorum type $Opt_Fanout = $FALSE; # default - no fanout $Opt_Synchronous = $FALSE; # default - no waiting $PROGNAME = "startrpdomain"; # 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 start my $timeout = 0; # timeout value 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 $local_node = ""; # node you're on my $found = 0; # boolean value my $i = 0; # counter my @cmd_out = (); # output from startrsrc my $q_type = ""; # quorum type my $fanout = 0; # fanout 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, $timeout, $q_type, $fanout, $wait_timeout) = &parse_cmd_line; ($rc == 0) || error_exit($rc); if ($Verbose) { printIMsg("IMsgstartrpdomainStart",$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); # if either online criteria, timeout, or quorum is specified, # pass as command arguments to startrsrc if ($Opt_All_Criteria || $Opt_Local_Criteria || $Opt_Timeout || $Opt_QuorumType || $Opt_Fanout) { # skip over nodelist $other_opts = "::"; # set the OnlineCriteria option # (1=all nodes, 2=local node, otherwise default to quorum 0) if ($Opt_All_Criteria) { $other_opts = $other_opts . "::OnlineCriteria::1"; } if ($Opt_Local_Criteria) { $other_opts = $other_opts . "::OnlineCriteria::2"; } #93122 - comment out specifying the default command argument #else { $other_opts = $other_opts . "::OnlineCriteria::0"; } # set the Timeout option if ($Opt_Timeout) { # make sure timeout value is positive integer if ($timeout <= 0) { printEMsg("EMsgstartrpdomainInvTime",$timeout); exit(CRM_CLI_USER_ERROR); } $other_opts = $other_opts . "::Timeout::$timeout"; } #93122 - comment out specifying the default command argument #93248 - timeout needs to be specified or else startrsrc-api sets it to 0 #109790 - back to not including if not specified. 0 means 120 to RM #else { $other_opts = $other_opts . "::Timeout::120"; } # pass in quorum type, if specified if ($Opt_QuorumType) { # -Q used for quorum type $other_opts = $other_opts."::StartQuorumType::$q_type"; } # pass in fanout, if specified if ($Opt_Fanout) { # -n used for fanout $other_opts = $other_opts."::Fanout::$fanout"; } } # 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 start 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("EMsgstartrpdomainClusterNotFound",$cluster_name); exit(CRM_CLI_USER_ERROR); } # make sure there are no online clusters - besides this one # (ok to "restart". restart invites all nodes to come online foreach $one_cluster (@clusters) { if (($cluster_opstates{$one_cluster} == $RMC_OPSTATE_ONLINE) && ($cluster_name ne $one_cluster)) { # get the resolved name of the node you're on $local_node = get_source_node; # print error message if another cluster is online printEMsg("EMsgstartrpdomainAlreadyOnline",$cluster_name,$local_node,$one_cluster); exit(CRM_CLI_USER_ERROR); } } # Quit here for CAA domain type if(get_domain_type()) { #printCEMsg("EMsgConfigRMCmdNotSupported"); exit (CRM_CLI_SUCCESS); } # call startrsrc-api if ($Trace) { print STDERR "$PROGNAME: calling startrsrc-api\n";} #@cmd_out = `$CTBINDIR/startrsrc $passopts -s "Name==\\\"$cluster_name\\\"" $RSCLUSTER $other_opts 2>&1`; @cmd_out=`$CTBINDIR/startrsrc-api -s ${RSCLUSTER}::Name==\\\"${cluster_name}\\\"${other_opts} 2>&1`; # capture the return code from startrsrc-api $rc = $?; $rc = process_exit_code($rc); if ($Trace) { print STDERR "startrsrc-api results:\n"; print STDERR "@cmd_out";} if ($Trace) { print STDERR "$PROGNAME: startrsrc-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 startrsrc failed for something else, print RMC error message and exit if ($rc != 0) { # printCEMsg("EMsgConfigRMcliUnExpectRMCrc",$rc); exit(CRM_CLI_RMC_ERROR); } # if wait until started selected if ($Opt_Synchronous) { # use $i to check for timeout exceeded $i = 0; $TIMED_OUT = $FALSE; # check opstate until online or timeout exceeded while ( ($cluster_opstates{$cluster_name} != $RMC_OPSTATE_ONLINE) && (!$TIMED_OUT) ) { sleep($wait_poll_int); $i = $i + $wait_poll_int; ($state_rc, %cluster_opstates_new) = get_opstate_by_name_rc($RSCLUSTER); if ($state_rc == 0) { %cluster_opstates = %cluster_opstates_new; } if ( ($cluster_opstates{$cluster_name} != $RMC_OPSTATE_ONLINE) && ($i > $wait_timeout) && ($wait_timeout != 0) ){ printCEMsg("EMsgConfigRMcliWaitTimedOut"); $rc = CRM_CLI_ERROR; $TIMED_OUT = $TRUE; } } } if ($Verbose) { printIMsg("IMsgstartrpdomainEnd",$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 start. # # $timeout Timeout value. # # $q_type Quorum type. # # $fanout Fan out value. # # $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_Timeout output True (-t) timeout specified. # # $Opt_All_Criteria output True (-A) all nodes criteria spec. # # $Opt_Local_Criteria output True (-L) local node criteria spec. # # $Opt_QuorumType output True (-Q) Quorum type # # $Opt_Fanout output True (-m) Fanout. # # $Opt_Synchronous output True (-w) Wait. # #--------------------------------------------------------------------# sub parse_cmd_line { my(@original_argv) = @ARGV; my $cluster_name = ""; # cluster name my $timeout = 0; # timeout value my $q_type = ""; # quorum type my $fanout = 0; # fanout value my $wait_timeout = 300; # wait timeout value my %opts = (); # Process the command line... if (!&getopts('ht:ALQ:m:ws: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{t}) { # -t timeout value $timeout = $opts{t}; $Opt_Timeout = $TRUE; # -t flag specified } if (defined $opts{A}) { # -A online criteria all nodes $Opt_All_Criteria = $TRUE; # -A flag specified } if (defined $opts{L}) { # -L online criteria local node # error if -A is set if ($Opt_All_Criteria) { printCEMsg("EMsgConfigRMcliImproperUsageCombination","-A","-L"); &print_usage; return CRM_CLI_BAD_FLAG; } $Opt_Local_Criteria = $TRUE; # -L flag specified } if (defined $opts{Q}) { # -Q for quorum group name $q_type = $opts{Q}; # turn quorum type into a number $q_type = check_quorum_type($q_type); $Opt_QuorumType = $TRUE; # -Q flag specified } if (defined $opts{m}) { # -m for fanout $fanout = $opts{m}; $Opt_Fanout = $TRUE; # -m 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("EMsgstartrpdomainInvTimeoutSeconds","$opts{s}"); &print_usage; return CRM_CLI_BAD_FLAG; } } # Get the arguments... # Operands: cluster name 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, $timeout, $q_type, $fanout, $wait_timeout); } # end parse_cmd_line #--------------------------------------------------------------------# # print_usage : print the usage statement (syntax) to stdout. # #--------------------------------------------------------------------# sub print_usage { &printIMsg("IMsgstartrpdomainUsageW"); } # end print_usage