#!/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 = "@(#)79 1.35 src/rsct/rm/ConfigRM/cli/bin/addrpnode.perl, configrmcli, rsct_rady, rady2035a 11/12/15 16:40:31" ###################################################################### # # # Module: addrpnode # # # # Purpose: # # addrpnode - adds a node to an RSCT peer domain. # # # # Syntax: # # addrpnode [-h] [-c] [-M] [-TV] Node_name[@Host_name] # # [Node_name[@Host_name] ...] # # # # addrpnode [-h] [-c] [-M] -f File | -F File [-TV] # # # # Flags: # # -h Help. Writes the command's usage statement to standard # # output. # # -c Continue on error. When adding multiple nodes to the # # peer domain, do not stop when an error occurs but # # continue processing the addrpnode command as long as at # # least one node can be added to the peer domain. # # -f File The file containing the nodes names to be added to 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. # # -F File Same as -f. # # -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 SecurityMode: Security mode of the node that needs to be # # added. # # If "-M" is given, node will be added to domain if node # # has NIST compliant keys and domain is in NIST mode. # # if Domain is not in NIST node addition will fail.# # If this option is not specified and domain is in # # NIST mode, node will be added to domain if # # Node is already in NIST mode # # otherwise node addition will fail # # # # # # Operands: # # Node_name[@Host_name] # # The node to be added to the peer domain definition. # # The node name (the Host_name, if there is any # # corresponding input) is the long or short version # # of the DNS hostname. It must be resolvable to an IP # # address. The node name can be specified as operands # # or in a file using the -f option, but not both. # # The "@Host_name" input is applicable for non-CAA # # domain not applicable for CAA. # # Node_name will be populated in nodename attribute. # # Host_name will be populated in hostname attribute, # # if any, otherwise populated initially with # # Node_name. # # # # Description: # # The addrpnode command adds the specified nodes to the online # # peer domain of where the command is run. The command must be # # run on a node that is online to the peer domain in which the new # # nodes are to be added. The added nodes are not brought online # # in the peer domain. Use the startrpnode command to bring the # # added nodes online. # # # # A node can be defined in multiple peer domains but only be # # online in one. # # # # 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 add the nodes nodeB and nodeC to the peer domain ApplDomain# # where nodeA is already defined and online to ApplDomain, run # # the following command on nodeA: # # addrpnode nodeB nodeC # # # # 2. To add the nodes nodeB and nodeC with hostnames HostB and HostC# # respectively in non-CAA domain, run the following command: # # addrpnode nodeB@HostB nodeC@HostC # # # # Man Page: # # For the most current detailed description of this command see # # the addrpnode man page in /opt/rsct/man. # # # #--------------------------------------------------------------------# # Inputs: # # /opt/rsct/msgmaps/configrmcli.addrpnode.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 add a node that's already in the cluster.# # 011218 JAC 78807: Don't resolve node names or check if in cluster# # 020131 JAC 79963: switch to use mkrsrc-api instead of mkrsrc. # # 020207 JAC 80121: Make printing of c-api results a trace msg. # # 020415 JAC 82055: Add -c for continue-on-error and get rid of # # looping to call mkrsrc-api (RM accepts >1). # # 020417 JAC 81859: Add -f file flag to read node names/nums. # # 020422 JAC 82248: Rename addclnode to addrpnode. # # 020424 JAC 82385: Add quotes around string passed to mkrsrc-api. # # 020428 JAC 82316: Call process_exit_code to check $rc. # # 020502 JAC 82564: Set peer domain scope before calling mkrsrc-api# # 021111 JAC 88901: Fix for node_names empty for last verbose msg. # # 030324 JAC 93122: Don't specify default command arguments. # # 030723 JAC 97439: Continue processing if unresolved nodes exist # # or nodes already in peer domain. # # 040319 JAC 105987: Add -F flag to do the same as -f. # # 040406 JAC 106712: Update usage for file options. # # 050406 JAC 119510: Add rc when calling process_api_error. # # 050506 JAC 119921: Fix verbose message when node list not known. # # 071105 JAC 146610: Add tiebreaker support. # ###################################################################### #--------------------------------------------------------------------# # General Program Flow/Logic: # # # # 1. Parse command line flags and operands. # # 2. Print usage if -h specified. # # 3. find the name of the node you're on and make sure it is online # # to the cluster. It's an error if it isn't. # # 4. Resolve the target node names. # # 5. Make sure the target node isn't already in the cluster. # # 6. Call RMC command mkrsrc. Also pass along -VT if necessary. # # 7. 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 get_opstate_by_name check_for_nodes process_api_error process_exit_code get_nodes_nums_from_file form_quorum_attribute resolve_node_names); use CRM_cli_include qw($TRUE $FALSE $RMC_OPSTATE_ONLINE $RSNODE $RSNETI $RMC_CLI_USER_ERROR $PEER_DOMAIN_SCOPE $CTBINDIR $CTDIR); #--------------------------------------------------------------------# # Global Variables # #--------------------------------------------------------------------# $Trace = $FALSE; # default - trace off $Verbose = $FALSE; # default - verbose turned off $Opt_Continue = $FALSE; # default - no continue on error $Opt_File_Input = $FALSE; # default - no file $Opt_SecurityMode = $FALSE; # default - no SecurityMode specified $PROGNAME = "addrpnode"; # 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 in cluster my @node_names_v = (); # nodes in cluster for -V my %node_opstates = (); # nodes in cluster my @node_info = (); # nodes in cluster my $resolved_node_names = ""; # resolved nodelist my $unresolved_node_names = ""; # unresolved nodelist my @node_names_to_add = (); # node names to add to cluster my $in_list = ""; # reference to array my $not_in_list = ""; # reference to array my $one_node = ""; # one from nodelist my $first_node = ""; # first one in the list my @cmd_out = (); # for mkrsrc output my @nnodes = (); # number of nodes my @node_quorum_flags = (); # array reference for Quorum specification my @node_tiebreaker_flags = (); # array reference for Tiebreaker specification my @node_gsgl_flags = (); # array reference for PreferredGSGL specification my $comma = ""; # used to build a list my $node_name_list = ""; # list of node names my $file_name = ""; # input file name my $node_names_file = ""; # array reference my $node_nums_file = ""; # array reference my $node_quorum_flags_file = ""; # array reference for Quorum specification my $node_tiebreaker_flags_file = ""; # array reference for Tiebreaker specification my $node_gsgl_flags_file = ""; # array reference for PreferredGSGL specification my @node_numbers = (); # nodes in cluster my $node_num_list = ""; # for rmc command my $one_num = ""; # one from node num list my $one_flag = ""; # one from IsQuorumNode/IsPrefferedGSGL list my $first_num = ""; # first one in the list my $first_quorum_flag = ""; # first one in the list my $first_gsgl_flag = ""; # first one in the list my $node_opts_list = ""; # for rmc command my $node_quorum_arg = ""; # reference to quorum arg array my @nodenames_list = (); # Node names (List of hostname, if any, otherwise nodename) list my @nodenames = (); # Input nodenames list my @hostnames = (); # Input hostnames list my $tmp_node_name = ""; my $tmp_host_name = ""; my $first_host_name = ""; my $host_names_list = ""; # Host name list my @copy_of_node_names = (); # copy of @node_names my $passopts = ""; # TV options to pass to RMC CLI my $other_opts = ""; # parameters to pass to RMC CLI my $delimiter = "#:#"; my $IPv6Support = 0; my $verify_secmode = 0; # if -M is specified, verify_secmode will be set to TRUE #--------------------------------------------------------------------# # Main Code # #--------------------------------------------------------------------# my $rc = 0; my $config_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, $verify_secmode, @node_names) = &parse_cmd_line; ($rc == 0) || error_exit($rc); if ($Verbose) { printIMsg("IMsgaddrpnodeStarted"); } if ($Trace) { $passopts = $passopts." -T"; } if ($Verbose) { $passopts = $passopts." -V"; } # 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); } # get the node names and numbers from a file, if specified if ($Opt_File_Input) { # extract the node names from the file ($node_names_file, $node_nums_file, $node_quorum_flags_file, $node_gsgl_flags_file, $node_tiebreaker_flags_file) = get_nodes_nums_from_file($file_name); # copy to other array @node_names = @$node_names_file; @node_numbers = @$node_nums_file; @node_quorum_flags = @$node_quorum_flags_file; @node_gsgl_flags = @$node_gsgl_flags_file; @node_tiebreaker_flags = @$node_tiebreaker_flags_file; } if ($Verbose) { printIMsg("IMsgaddrpnodeNodeList"); foreach $one_node (@node_names) { print(" ", $one_node); } print("\n"); } # consolidate quorum and tiebreaker arrays $node_quorum_arg = form_quorum_attribute(\@node_quorum_flags, \@node_tiebreaker_flags); # Hostname change support. # User has the flexibility to provide node name and corresponding hostname, like nodename[@hostname] # Hostname would be considered for resolving nodename otherwise node name will be used. $comma = ""; foreach $one_node (@node_names) { $tmp_node_name = ""; $tmp_host_name = ""; ($tmp_node_name, $tmp_host_name) = split /@/, $one_node; push (@nodenames, $tmp_node_name); if ($tmp_host_name eq "") { # Consider nodename as there is no Hostname push (@nodenames_list, $tmp_node_name); } else { # Consider hostname as there is input for corresponding nodename push (@nodenames_list, $tmp_host_name); push (@hostnames, $tmp_host_name); } $comma = ","; } # resolve node names and hostnames that are to be added to the cluster ($resolved_node_names, $unresolved_node_names) = resolve_node_names(@nodenames_list); # write an error message for each unresolved node name found # continue processing but set rc foreach $one_node (@$unresolved_node_names) { printEMsg("EMsgaddrpnodeUnresolvedNode",$one_node); $config_rc = CRM_CLI_USER_ERROR; } # remove unresolved node names from node name list # &reset_node_names(\@node_names, \@node_numbers, $unresolved_node_names); &reset_node_opts(\@nodenames_list, \@node_numbers, $node_quorum_arg, \@node_gsgl_flags, $unresolved_node_names); # make sure target nodes are not already in the cluster ($in_list,$not_in_list) = check_for_nodes(\@nodenames_list,\%node_opstates); # for nodes in the list (and already in cluster), print error message foreach $one_node (@$in_list) { printEMsg("EMsgaddrpnodeAlreadyAdded",$one_node); $config_rc = CRM_CLI_USER_ERROR; } # remove nodes that are already in cluster from node name list # &reset_node_names(\@node_names, \@node_numbers, $in_list); &reset_node_opts(\@nodenames_list, \@node_numbers, $node_quorum_arg, \@node_gsgl_flags, $in_list); # get ready to pass stuff to configrm # first, make sure there are nodes to process, in case of # previous errors. Exit if there are no nodes to process. if ($#nodenames_list < 0) { if ($Verbose) { printIMsg("IMsgaddrpnodeEnded"); } exit($config_rc); } # determine whether IPv6 addresses are permitted as node names $IPv6Supported = `$CTBINDIR/lsrsrc-api -c "${RSNETI}::IPv6Support" 2>&1`; chomp $IPv6Supported; if ("" eq $IPv6Supported) { # something went wrong getting $IPv6Supported - default to being restrictive $IPv6Supported = 0; } # make a list of the remaining node names to pass to rmc foreach $one_node (@nodenames, @hostnames) { if ((! $IPv6Supported) && ($one_node =~ /:/)) { printEMsg("EMsgaddrpnodeIPv6AddressNotPermitted",$one_node); exit CRM_CLI_USER_ERROR; } } # get the first node name. it's used in Name attribute $first_node = shift @nodenames; # HostName of first NodeName if available # Note: HostName field should not be passed unless it is provided ($tmp_node_name, $tmp_host_name) = split /@/, $node_names[0]; if ($tmp_host_name ne "") { $first_host_name = "${delimiter}HostName${delimiter}${tmp_host_name}"; } @copy_of_node_names = @node_names; shift @copy_of_node_names; $comma = ""; foreach $one_node (@copy_of_node_names) { ($tmp_node_name, $tmp_host_name) = split /@/, $one_node; $node_name_list = $node_name_list.$comma.$tmp_node_name; if ($tmp_host_name ne "") { $host_names_list = $host_names_list.$comma.$tmp_host_name; } else { $host_names_list = $host_names_list.$comma.""; } $comma = ","; } # setup the nodelist $other_opts = $other_opts."${delimiter}${delimiter}NodeNames${delimiter}"."{$node_name_list}"; # get the first num. it's used in NodeList attribute if ($#node_numbers >=0) { $first_num = shift @node_numbers;} # if there are node numbers, save the first for mkrsrc call if ($first_num ne "") {$first_num = "${delimiter}NodeList${delimiter}{$first_num}";} # make a list of the remaining node numbers to pass to rmc $comma = ""; foreach $one_num (@node_numbers) { $node_num_list = $node_num_list.$comma.$one_num; $comma = ","; } # setup node number list $other_opts = $other_opts."${delimiter}NodeNumbers${delimiter}"."{$node_num_list}"; # set the first Quorum value. It's used in IsQuorumNode attribute if ( $#$node_quorum_arg >= 0 ) { $first_quorum_flag = shift( @$node_quorum_arg ); } # if there are Quorum specifications, save the first for mkrsrc call if ( $first_quorum_flag ne "" ) { $first_quorum_flag = "${delimiter}IsQuorumNode${delimiter}${first_quorum_flag}"; } # setup node Quorum list if ( $#$node_quorum_arg >= 0 ) { $comma = ""; $node_opts_list = ""; foreach $one_flag (@$node_quorum_arg) { $node_opts_list = $node_opts_list.$comma.$one_flag; $comma = ","; } $other_opts = $other_opts."${delimiter}IsQuorumNodeArray${delimiter}{$node_opts_list}"; } # set the first Preferred Group leader value. It's used in IsPreferredGSGL attribute if ( $#node_gsgl_flags >= 0 ) { $first_gsgl_flag = shift( @node_gsgl_flags ); } # if there are Preferred Group leader specifications, save the first for mkrsrc call if ( $first_gsgl_flag ne "" ) { $first_gsgl_flag = "${delimiter}IsPreferredGSGL${delimiter}${first_gsgl_flag}"; } # setup node Preferred Group leader list if ( $#node_gsgl_flags >= 0 ) { $comma = ""; $node_opts_list = ""; foreach $one_flag (@node_gsgl_flags) { $node_opts_list = $node_opts_list.$comma.$one_flag; $comma = ","; } $other_opts = $other_opts."${delimiter}IsPreferredGSGLArray${delimiter}{$node_opts_list}"; } # continue on error specified? if ($Opt_Continue) { $other_opts = $other_opts."${delimiter}ContinueIfError${delimiter}1"; } #93122 - comment out specifying the default command argument #else { # $other_opts = $other_opts."${delimiter}ContinueIfError${delimiter}0"; #} # setup hostnames list if any if ($host_names_list ne "") { $other_opts = $other_opts."${delimiter}HostNames${delimiter}"."{$host_names_list}"; } $persistent_attrs = "${delimiter}Name${delimiter}${first_node}${first_num}${first_quorum_flag}${first_gsgl_flag}${first_host_name}"; #SecurityMode option is specified if( $Opt_SecurityMode) { $other_opts = $other_opts."${delimiter}VerifySecurityMode${delimiter}$verify_secmode"; } # call mkrsrc to add the nodes to the cluster if ($Trace) { print STDERR "$PROGNAME: calling mkrsrc-api\n";} #`$CTBINDIR/mkrsrc $passopts $RSNODE Name="$one_node"`; #@cmd_out=`$CTBINDIR/mkrsrc-api ${RSNODE}${delimiter}Name${delimiter}${one_node} 2>&1`; #@cmd_out=`$CTBINDIR/mkrsrc-api "${RSNODE}${delimiter}Name${delimiter}${first_node}${first_num}${other_opts}" 2>&1`; @cmd_out=`$CTBINDIR/mkrsrc-api -D"$delimiter" -I"$delimiter" "${RSNODE}${persistent_attrs}${other_opts}" 2>&1`; # capture the return code from mkrsrc $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($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 mkrsrc 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; } if ($Verbose) { printIMsg("IMsgaddrpnodeEnded"); } # exit with appropriate return code 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. # # @node_names Nodes to add to the cluster # # # # Global Variables Modified: # # $Verbose output True (-V) turn Verbose mode on. # # $Trace output True (-T) turn Trace mode on. # # $Opt_File_Input output True (-f|-F) file name specified # # $Opt_Continue output True (-c) Continue on error # # $Opt_SecurityMode output True (-M) Security Mode specified # #--------------------------------------------------------------------# sub parse_cmd_line { my(@original_argv) = @ARGV; my @node_names = (); # node names my %opts = (); my $file_name = ""; my $verify_secmode = 0; # Process the command line... if (!&getopts('hcf:F:VTM', \%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{c}) { # -c for continue on error $Opt_Continue = $TRUE; # -c flag specified } # Get the arguments... # Operands: one or more node names if ($#ARGV >= 0) { # cluster name and maybe more @node_names = @ARGV; # get node names } # make sure -f or -F for file used if there are no node names if (($#node_names < 0) && !(defined $opts{f}||defined $opts{F})) { printCEMsg("EMsgConfigRMcliInvalidNumberOfOperands"); &print_usage; return CRM_CLI_BAD_OPERAND; } if (defined $opts{f}) { # -f for file # make sure both -f and -F not used together if (defined $opts{F}) { printCEMsg("EMsgConfigRMcliImproperUsageCombination","-f","-F"); &print_usage; return CRM_CLI_BAD_FLAG; } $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{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}) { $verify_secmode = $TRUE; $Opt_SecurityMode = $TRUE; } return(0, $file_name, $verify_secmode, @node_names ); # success } # end parse_cmd_line #--------------------------------------------------------------------# # print_usage : print the usage statement (syntax) to stdout. # #--------------------------------------------------------------------# sub print_usage { &printIMsg("IMsgaddrpnodeUsageF"); } # end print_usage #--------------------------------------------------------------------# # reset_node_names : Removes from the node name list the node names # # provided in the list of nodes to remove. If the node number # # list exists, update it as well. # # # # Parameters: # # $node_names in/out Reference to an array of node names. # # $node_nums in/out Reference to an array of node numbers. # # $remove_nodes input Reference to an array of node names that # # need to be removed. # # # # Global Variables: # #--------------------------------------------------------------------# sub reset_node_names { my $node_names = ""; # ref to array of node names my $node_nums = ""; # ref to array of node nums my $remove_nodes = ""; # ref to nodes to remove my @node_names_new = (); # temp new name list my @node_nums_new = (); # temp new num list my $num_update_req = $FALSE; # update num array my $i = 0; # loop counter my $j = 0; # loop counter my $remove_cnt = 0; # loop counter my $remove = $FALSE; # search switch # get inputs $node_names = shift @_; $node_nums = shift @_; $remove_nodes = shift @_; # simply exit if there's no nodes to remove or no node names # to begin with if ( ($#$node_names < 0) || ($#$remove_nodes < 0) ) { return; } # determine (once) if node number array is present if ( $#$node_nums >=0 ) { $num_update_req = $TRUE; } # loop through node name list seeing if it needs to be # removed (or really not included in the new list) for ($i=0; (($i<=$#$node_names) && ($remove_cnt<=$#$remove_nodes)); $i++) { # set remove flag to false to say keep this node name $remove = $FALSE; # see if this node is a node in the remove list for ($j=0; (($j<=$#$remove_nodes) && (!$remove)); $j++) { # check if this is a node to dump if ($$remove_nodes[$j] eq $$node_names[$i]) { # set boolean switch $remove = $TRUE; $remove_cnt++; } } # if it's not to be removed, add to new list if (!$remove) { push @node_names_new, $$node_names[$i]; # update the node number list if necessary if ($num_update_req) { push @node_nums_new, $$node_nums[$i]; } } } # transfer rest of list if ($i<=$#$node_names) { for ($j=$i; $j<=$#$node_names; $j++) { push @node_names_new, $$node_names[$j]; # update the node number list if necessary if ($num_update_req) { push @node_nums_new, $$node_nums[$j]; } } } # copy new lists to old @$node_names = @node_names_new; @$node_nums = @node_nums_new; return; } # end of reset_node_names #--------------------------------------------------------------------# # reset_node_opts : Removes from the node name list the node names # # provided in the list of nodes to remove. If the other node # # option lists exists, update it as well. # # # # Parameters: # # $node_names in/out Reference to an array of node names. # # $node_nums in/out Reference to an array of node numbers. # # $node_quorum_flags in/out Reference to an array of IsQuroum. # # $node_gsgl_flags in/out Reference to an array of IsPreferedGSGL.# # ... in/out ... # # $remove_nodes input Reference to an array of node names that # # need to be removed. # # # # Global Variables: # #--------------------------------------------------------------------# sub reset_node_opts { my $node_names = ""; # ref to array of node names my @node_opts = (); # ref to array of node number, IsPreferredGSGL, IsQuroumNode my $remove_nodes = ""; # ref to nodes to remove my @node_names_new = (); # temp new name list my @node_opts_new = (); # temp new num list my $i = 0; # loop counter my $j = 0; # loop counter my $n = 0; # loop counter my $remove_cnt = 0; # loop counter my $remove = $FALSE; # search switch my $opts_req = 0; # other options update my @opts_update_reqs = (); # other options update list my $temp_src_ref = ""; # temp ref to a array my $temp_dst_ref = ""; # temp ref to a array # get inputs $node_names = shift @_; $remove_nodes = pop @_; @node_opts = @_; # simply exit if there's no nodes to remove or no node names # to begin with if ( ($#$node_names < 0) || ($#$remove_nodes < 0) ) { return; } #determine if there are none-empty option arrays #option arrays include node number list,Quorum flag list, PreferredGSGL flag list if ( $#node_opts >= 0 ) { $opts_req = 1; # Initialize new array corresponding to the option array # Set if the option array is empty foreach $i (@node_opts) { my @temp_array = (); push ( @node_opts_new, \@temp_array ); if ( $#$i >= 0 ) { push ( @opts_update_reqs, 1 ); } else { push ( @opts_update_reqs, 0 ); } } # end of "foreach $i" } # end of "if ( $#node_opts >= 0 )" # loop through node name list seeing if it needs to be # removed (or really not included in the new list) for ($i=0; (($i<=$#$node_names) && ($remove_cnt<=$#$remove_nodes)); $i++) { # set remove flag to false to say keep this node name $remove = $FALSE; # see if this node is a node in the remove list for ($j=0; (($j<=$#$remove_nodes) && (!$remove)); $j++) { # check if this is a node to dump if ($$remove_nodes[$j] eq $$node_names[$i]) { # set boolean switch $remove = $TRUE; $remove_cnt++; } } # end of "for $j" # if it's not to be removed, add to new list if ( !$remove ) { push @node_names_new, $$node_names[$i]; if ( !$opts_req ) { next; } # update other lists if necessary for( $n = 0; $n <= $#node_opts; $n++ ) { if ( $opts_update_reqs[$n] ) { $temp_src_ref = $node_opts[$n]; $temp_dst_ref = $node_opts_new[$n]; push @$temp_dst_ref, $$temp_src_ref[$i]; } } # end of "for $n < $#node_opts". } # end of "if ( !$remove )" } # end of " for $i" # transfer rest of list if ( $i <= $#$node_names ) { for ( $j = $i; $j <= $#$node_names; $j++) { push @node_names_new, $$node_names[$j]; if ( !$opts_req ) { next; } # update other lists if necessary for( $n = 0; $n <= $#node_opts; $n++ ) { if ( $opts_update_reqs[$n] ) { my $temp_src_ref = $node_opts[$n]; my $temp_dst_ref = $node_opts_new[$n]; push @$temp_dst_ref, $$temp_src_ref[$j]; } } # end of " for $n < $#node_opts" } # end of " for $j<=$#$node_names " } # end of "if ( $i <= $#$node_names )" # copy new lists to old @$node_names = @node_names_new; if ( $opts_req ) { for( $n = 0; $n <= $#node_opts; $n++ ) { if ( $opts_update_reqs[$n] ) { my $temp_src_ref = $node_opts[$n]; my $temp_dst_ref = $node_opts_new[$n]; @$temp_src_ref = @$temp_dst_ref; } } # end of " for $n < $#node_opts" } # end of "if ( $opts_req )" return; } # end of reset_node_opts