#!/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 = "@(#)80 1.30 src/rsct/rm/ConfigRM/cli/bin/lsrpnode.perl, configrmcli, rsct_rady, rady2035a 11/12/15 16:41:04" ###################################################################### # # # Module: lsrpnode # # # # Purpose: # # lsrpnode - lists information about the nodes defined in an # # RSCT peer domain. # # # # Syntax: # # lsrpnode [-h] [-o|-O|-L] [-l|-t|-d|-D Delimiter] [-x] [-i] # # [-P] [-Q] [-B] [-TV] [Node] # # lsrpnode [-h] [-l|-t|-d|-D Delimiter] [-x] [-p PeerDomain] # # [-TV] # # # # Flags: # # -h Help. Writes the command's usage statement to standard # # output. # # -i Include the node number and node ID in the output. # # This information is helpful for debugging purposes. # # -Q Indicates if the node participates in quorum decisions. # # "yes" is displayed if the node participates in quorum # # decisions. "no" is displayed if the node does not # # participate in quorum decisions. # # -B Indicates if the node has access to the peer domain's # # tiebreaker mechanism. "yes" is displayed if the node # # does has access to the peer domain's tiebreaker # # mechanism. "no" is displayed if the node does not have # # access to the peer domain's tiebreaker mechanism. # # -P Indicates if the node is a group services group leader # # candidate."yes" is displayed if the node can be a group # # services group leader."no" is displayed if the node # # cannot be a group service group leader. # # -o Online nodes. List only information about the online # # nodes in the peer domain. # # -O Offline nodes. List only information about nodes that # # are offline (not online) in the peer domain. # # -L Local node. List the information about the local node. # # -l Long formatted output. The information is displayed on # # separate lines. # # -t Tabular formatted output. The information is displayed # # in separate columns. # # -d Delimiter-formatted output. The default delimiter is a # # colon (:). Use the -D flag if you wish to change the # # default delimiter. # # -D Delimiter Delimiter-formatted output that uses the specified# # delimiter. Use this flag to specify something other # # than the default colon (:). An example is when the data # # to be displayed contains colons. Use this flag to # # specify a delimiter of one or more characters. # # -x Exlude header. Suppress header printing. # # -p PeerDomain. Lists the node names in the specified peer # # domain. This option does not require the peer domain to # # be online. # # -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: # # Node The name of the node to be listed. Node may be a node # # name or a substring of a node name. When it is a # # substring, any defined node name that contains the # # substring will be listed. # # # # Description: # # The lsrpnode command lists information about the nodes that are # # in the online peer domain. The flags and operands can be used to # # specify what is listed. When a node name is specified, the # # listed information is limitted to that node information only. # # The -o or -O flag also limits the listed information. The -o # # flag lists only the online node's information. The -O flag # # lists information for nodes that are not online. # # # # # # 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. # # 6 CRM_CLI_NOT_FOUND Node not defined in peer domain. # # # # Examples: # # # # Man Page: # # For the most current detailed description of this command see # # the lsrpnode man page in /opt/rsct/man. # # # #--------------------------------------------------------------------# # Inputs: # # /opt/rsct/msgmaps/configrmcli.lsrpnode.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. # # 011008 JAC 75442: Final version. # # 020201 JAC 79963: switch to use lsrsrc-api instead of lsrsrc. # # 020206 JAC 80077: Add NLS support for heading and xlate values. # # 020207 JAC 80121: Make printing of c-api results a trace msg. # # 020207 JAC 80133: Issue not found message if a node specified. # # 020227 JAC 80700: Get -a and -n flags to work. # # 020412 JAC 81856: Add -L flag to list local node. # # 020417 JAC 81859: Fix usage message. # # 020422 JAC 82248: Rename lsclnode to lsrpnode. # # 020425 JAC 82405: Add -p flag to list domains from the registry. # # 020428 JAC 82316: Call process_exit_code to check $rc. # # 020502 JAC 82649: Fix -p not found error to use $rc, not msg no. # # 020503 JAC 82564: Set peer domain scope before calling lsrsrc-api# # 020724 JAC 85045: Change -a|-n to -o|-O for cmd consistency. # # 021015 JAC 88041: Use lssrtbl-api instead of lssrtbl for -p. # # 021024 JAC 88405: Fix 88041 for missing line 1 perl directive. # # 030108 JAC 90576: Use new lssrctbl-api syntax. # # 030203 JAC 89737: Continue to display data if there's an error. # # 030909 JAC 98648: Print "no nodes" msg for no resources found. # # 040407 JAC 105863: Use escape_chars for "\" searches. # # 040422 JAC 108194: Use escape_selstr for node name and use LIKE # # in select string. # # 040726 JAC 109612: Add -i flag to show node names and node IDs. # # 050406 JAC 119510: Add rc when calling process_api_error. # # 071031 JAC 146610: Add -B Tiebreaker support. # ###################################################################### #--------------------------------------------------------------------# # General Program Flow/Logic: # # # # 1. Setup attributes to list with the command. # # 2. Parse command line flags and operands. # # 3. Print usage if -h specified # # 4. Setup a selection string if a node name operand was specified. # # 5. List the node information used the RMC lsrsrc command. # # Also pass along -VT if necessary. # # 6. Return back any errors from lsrsrc. # # 7. Format the output into a 2D array so a utility can be used. # # 8. Set the type of output to display (long, table, ...). # # 9. Call the set_display utility to display the output. # # # #--------------------------------------------------------------------# #--------------------------------------------------------------------# # Included Libraries and Extensions # #--------------------------------------------------------------------# use lib "/opt/rsct/pm"; use locale; use Getopt::Std; use CT_cli_utils qw(printIMsg printEMsg); use CT_cli_display_utils qw(set_display); 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_NOT_FOUND CRM_CLI_BAD_OPERAND CRM_CLI_USER_ERROR); use CRM_cli_utils qw(error_exit printCIMsg printCEMsg getIMsg process_api_error process_exit_code remove_api_error get_source_node escape_selstr lookup_opstate lookup_yesno); use CRM_cli_include qw($TRUE $FALSE $RSNODE $RMC_CLI_USER_ERROR $RMC_OPSTATE_ONLINE $RMC_CLI_RSRC_NOT_FOUND $DELIMITER $PEER_DOMAIN_SCOPE $CTBINDIR $CTDIR); #--------------------------------------------------------------------# # Global Constants # #--------------------------------------------------------------------# #$attrs = "Name OpState ConfigChanged NodeList RSCTVersion ClassVersions"; # attribute names $Attr_name = "Name"; $Attr_rsctversion = "RSCTVersion"; $Attr_nodelist = "NodeList"; #$Attr_classvers = "ClassVersions"; $Attr_opstate = "OpState"; #$Attr_configch = "ConfigChanged"; $Attr_nodeIDs = "NodeIDs"; $Attr_isquorum = "IsQuorumNode"; $Attr_isprefGSGL = "IsPreferredGSGL"; $lsr_attr_names = $Attr_name; $lsr_attr_names .= "::$Attr_opstate"; $lsr_attr_names .= "::$Attr_rsctversion"; # override DELIMITER so IPv6 address node names display properly $DELIMITER = "#:#"; #--------------------------------------------------------------------# # Global Variables # #--------------------------------------------------------------------# $Trace = $FALSE; # default - trace off $Verbose = $FALSE; # default - verbose turned off $Opt_Delm_Format = $FALSE; # default - no delimited output # -d, -D flags $Opt_Delm_Str = ":"; # default - delimiter character # can be overridden with -D flag $Opt_Long_Format = $FALSE; # default - long formatted output $Opt_Table_Format = $TRUE; # default - tabular format $Opt_No_HDR = $FALSE; # default - do not supress heading # output, -x flag $Opt_Only_Online = $FALSE; # default - do not list only # the online cluster $Opt_Only_NotOnline = $FALSE; # default - do not list only the # clusters that are not online $Opt_Local = $FALSE; # default - list all nodes in cluster $Opt_Cluster = $FALSE; # default - list peer nodes $Opt_ShowNodeNums = $FALSE; # default - no node nums/IDs $Opt_ShowQuorum = $FALSE; # default - no quorum $Opt_ShowTieBreaker = $FALSE; # default - no tiebreaker $Opt_ShowPrefGSGL = $FALSE; # default - no group service group leader perferred $PROGNAME = "lsrpnode"; # 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_name = ""; # node to list my $node_name_orig = ""; # node to list my $name_select = ""; # selection string for name my @lsr_out = (); # output from lsrsrc my @lsr_out2 = (); # copy of output from lsrsrc my @lof_nodes = (); # 2D array to be displayed my $attr_name = ""; # an attribute name my @attr_names = (); # all attribute names my $attr_val = ""; # an attribute value my @attr_vals = (); # all attribute values my $line = ""; # one line of output my $i = 0; # array index my $j = 0; # array index my $row_count = 0; # number of display rows my $col_count = 0; # number of display columns my $display_type = ""; # type of display call my $opstate_index = 2; # output index for opstate my $nodeID_index = 0; # output index for nodeID my $name_index = 1; # output index for name my $quorum_index = 0; # output index for IsQuorumNode my $tiebreaker_index = 0; # output index for IsQuorumNode my $prefGSGL_index = 0; # output index for IsPreferredGSGL my @heading = (); # heading for listed data my @opstatetext = (); # for translating opstate my @noyestext = (); # for translating no/yes my %op_states = (); # hash for opstate descriptions my $local_node = ""; # node you're on (-L) my $cluster_name = ""; # for -p to list nodes from reg. my @reg_names = (); # node names from registry my $passopts = ""; # TV options to pass to RMC CLI my $other_opts = ""; # parameters to pass to RMC CLI #--------------------------------------------------------------------# # 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, $node_name, $cluster_name) = &parse_cmd_line; ($rc == 0) || error_exit($rc); if ($Verbose) { printIMsg("IMsglsrpnodeStart"); } if ($Trace) { $passopts = $passopts." -T"; } if ($Verbose) { $passopts = $passopts." -V"; } # if -i was specified, add two more attributes to get if ($Opt_ShowNodeNums) { $lsr_attr_names .= "::$Attr_nodelist"; $lsr_attr_names .= "::$Attr_nodeIDs"; } # if -Q was specified, add IsQuorumNode attribute to get if($Opt_ShowQuorum) { $lsr_attr_names .= "::$Attr_isquorum"; } #if -P was specified, add IsPreferredGSGL attribute to get if($Opt_ShowPrefGSGL) { $lsr_attr_names .= "::$Attr_isprefGSGL"; } # if -B was specified, add IsQuorumNode attribute to get # if -Q didn't already get it if($Opt_ShowTieBreaker) { if(!$Opt_ShowQuorum) { $lsr_attr_names .= "::$Attr_isquorum"; } } # process the -p flag separately if ($Opt_Cluster) { # get node names in registry for this cluster @reg_names = &list_cluster_nodes($cluster_name); # form 2D array to pass to display utils # get heading from message file @heading = getIMsg("IMsglsrpnodeHeadingName"); # form heading @attr_names = split(/::/,$heading[0]); $i = 1; foreach $attr_name (@attr_names) { $lof_nodes[0][$i] = $attr_name; $i++; } # form each line of output $i = 1; foreach $line (@reg_names) { chomp($line); # parse the output @attr_vals = split(/$DELIMITER/, $line); # put into array $lof_nodes[$i][0] = " "; $j = 1; foreach $attr_val (@attr_vals) { # get rid of quotes $attr_val =~ s/^\"//; $attr_val =~ s/\"$//; # put output into the output array $lof_nodes[$i][$j] = $attr_val; $j++; } $i++; } } # process everything else but -p flag else { # Do some escaping on strings. Do the escape character first # for anything that's a string, escape any inner \ #$node_name =~ s/\\/\\\\/g; # for anything that's a string, escape any inner double quotes #$node_name =~ s/\"/\\\"/g; $node_name_orig = $node_name; $node_name = escape_chars($node_name); $node_name = escape_selstr($node_name); # if a node name was entered, build a select clause if ($node_name ne "") { # $name_select = "-s ${RSNODE}::\"Name ?= \\\"$node_name\\\"\""; $name_select = "-s ${RSNODE}::\"Name LIKE \\\"%${node_name}%\\\"\""; } # for no name, use o flag for list else { $name_select = "-o ${RSNODE}"; } # call lsrsrc if ($Trace) { print STDERR "$PROGNAME: calling lsrsrc-api\n";} #@lsr_out = `$CTBINDIR/lsrsrc -x -D $DELIMITER $passopts $name_select $RSNODE $lsr_attr_names`; @lsr_out = `$CTBINDIR/lsrsrc-api -D "$DELIMITER" ${name_select}::::::${lsr_attr_names} 2>&1`; # capture the return code from lsrsrc $rc = $?; $rc = process_exit_code($rc); if ($Trace) { print STDERR "lsrsrc-api results:\n"; print STDERR "@lsr_out";} if ($Trace) { print STDERR "$PROGNAME: lsrsrc-api returned $rc\n";} # show any errors if there was a bad rc if (($rc != 0) && ($rc != $RMC_CLI_RSRC_NOT_FOUND)) { process_api_error($DELIMITER,$rc,@lsr_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);} # return OK if resource not found error, unless a node was specified if ($rc == $RMC_CLI_RSRC_NOT_FOUND) { # if ($node_name eq "") { exit(0);} if ($node_name eq "") { printCEMsg("EMsgConfigRMcliNoCluster"); exit(CRM_CLI_USER_ERROR); } else { printEMsg("EMsglsrpnodeNodeNotFound",$node_name_orig); exit(CRM_CLI_NOT_FOUND); } } # if lsrsrc failed for something else, print RMC error message and exit if ($rc != 0) { # printCEMsg("EMsgConfigRMcliUnExpectRMCrc",$rc); # exit(CRM_CLI_RMC_ERROR); @lsr_out = remove_api_error(@lsr_out); $config_rc = $rc; } # limit the output if -o, -O, or -L was specified if ($Opt_Only_Online || $Opt_Only_NotOnline || $Opt_Local) { @lsr_out2 = @lsr_out; @lsr_out = (); # find the local node name for -L $local_node = get_source_node; # look at each line to see if -o, -O, or -L applies foreach $line (@lsr_out2) { chomp($line); # parse the output @attr_vals = split(/$DELIMITER/, $line); if ($Opt_Only_Online && ($attr_vals[$opstate_index-1] == $RMC_OPSTATE_ONLINE)) { push (@lsr_out,$line); } if ($Opt_Only_NotOnline && ($attr_vals[$opstate_index-1] != $RMC_OPSTATE_ONLINE)) { push (@lsr_out,$line); } if ($Opt_Local && ($attr_vals[$name_index-1] eq $local_node)) { push (@lsr_out,$line); } } } # if -Q for quorum and -B for tiebreaker are both specified, # copy the quorum column of data to create a tiebreaker column if ($Opt_ShowQuorum && $Opt_ShowTieBreaker) { # look at each line to break up the attribute values $i = 0; foreach $line (@lsr_out) { chomp($line); # parse the output @attr_vals = split(/$DELIMITER/, $line); # if -P was specified, PreferredGSGL is last column and QuorumNode is last-1 # if -P was not specified, QuorumNode is last column if ($Opt_ShowPrefGSGL) { $lsr_out[$i] .= $DELIMITER . $attr_vals[$#attr_vals-1]; } else { $lsr_out[$i] .= $DELIMITER . $attr_vals[$#attr_vals]; } $i++ } } # form 2D array to pass to display utils # get the appropriate heading from the message file if ($Opt_ShowNodeNums) { $nodeID_index = 5; # indicate the position for offset nodeID @heading = getIMsg("IMsglsrpnodeHeadingIFlag"); } else { @heading = getIMsg("IMsglsrpnodeHeading"); } # form heading, $i is the index of attr @attr_names = split(/::/,$heading[0]); $i = 1; foreach $attr_name (@attr_names) { $lof_nodes[0][$i] = $attr_name; $i++; } # form heading for IsQuorumNode - Quorum if ( $Opt_ShowQuorum ) { @heading = getIMsg("IMsglsrpnodeHeadingQ"); $lof_nodes[0][$i] = $heading[0]; $quorum_index = $i; $i++; } # form heading for IspreferredGSGL if ( $Opt_ShowPrefGSGL ) { @heading = getIMsg("IMsglsrpnodeHeadingP"); $lof_nodes[0][$i] = $heading[0]; $prefGSGL_index =$i; $i++; } # form heading for IsQuorumNode - Tiebreaker if ( $Opt_ShowTieBreaker ) { @heading = getIMsg("IMsglsrpnodeHeadingB"); $lof_nodes[0][$i] = $heading[0]; $tiebreaker_index = $i; $i++; } # get from message file what to use for opstates @opstatetext = getIMsg("IMsglsrpnodeOpState"); @opstatetext = split(/::/,$opstatetext[0]); # fill in the hash for opstates for ($op_cnt=0;$op_cnt<=$#opstatetext;$op_cnt=$op_cnt+2) { $op_states{$opstatetext[$op_cnt]} = $opstatetext[$op_cnt+1]; } # get from message file what to use for yes/no @noyestext = getIMsg("IMsglsrpnodeNoYes"); @noyestext = split(/::/, $noyestext[0]); # form each line of output $i = 1; foreach $line (@lsr_out) { chomp($line); # parse the output @attr_vals = split(/$DELIMITER/, $line); # put into array # $lof_nodes[$i][0] = "\nnode $i:"; $lof_nodes[$i][0] = " "; $j = 1; foreach $attr_val (@attr_vals) { # translate opstate if ($j == $opstate_index) { $attr_val = lookup_opstate($attr_val,%op_states); } elsif ($j == $nodeID_index) { $attr_val =~ s/^{//; $attr_val =~ s/}$//; $attr_val = &xlate_dec2hex_hardway($attr_val); } # translate yes/no for IsQuorumNode - Quorum elsif ($j == $quorum_index) { $attr_val = &lookupQuorum_yesno($attr_val,@noyestext); } # translate yes/no for IsPreferredGSGL elsif ($j == $prefGSGL_index) { $attr_val = lookup_yesno($attr_val,@noyestext); } # translate yes/no for IsQuorumNode - Tiebreaker elsif ($j == $tiebreaker_index) { $attr_val = &lookupTieBreaker_yesno($attr_val,@noyestext); } # put output into the output array $lof_nodes[$i][$j] = $attr_val; $j++; } $i++; } } # end else (process everything but -p) # set how many rows of data there is $row_count = $#lof_nodes; $col_count = scalar(@{$lof_nodes[0]}); # set formatting string needed by set_display ($Opt_Long_Format) && ($display_type = "long"); ($Opt_Table_Format) && ($display_type = "column"); ($Opt_Delm_Format) && ($display_type = "delim"); # print out results, if any if ($row_count > 0) { $rc = set_display($display_type, $Opt_No_HDR, $row_count, $col_count, \@lof_nodes, $Opt_Delm_Str); } if ($Verbose) { printIMsg("IMsglsrpnodeEnd"); } 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_name Name of node to list. # # # # Global Variables Modified: # # $Verbose output True (-V) turn Verbose mode on. # # $Trace output True (-T) turn Trace mode on. # # $Opt_Delm_Format output True (-d,-D) delimited output # # $Opt_Delm_Str output char (-D) delimiter character # # $Opt_Long_Format output True (-l) long formatted output # # $Opt_Table_Format output True (-t) tabular formatted output # # $Opt_No_HDR output True (-x) supress heading # # $Opt_Only_Online output True (-o) list only online cluster # # $Opt_Only_NotOnline output True (-O) list clusters not online # # $Opt_Local output True (-L) list local node only # # $Opt_Cluster output True (-p) list cluster from registry # # $Opt_ShowNodeNums output True (-i) show node nums and IDs # # $Opt_ShowQuorum output True (-P) show attr IsQurorumNode # # $Opt_ShowTieBreaker output True (-B) show attr IsQurorumNode # # $Opt_ShowPrefGSGL output True (-Q) show attr IsPreferredGSGL # #--------------------------------------------------------------------# sub parse_cmd_line { my(@original_argv) = @ARGV; my $node_name = ""; # node name my $cluster_name = ""; # cluster name for -p my %opts = (); # Process the command line... if (!&getopts('hioOLltdD:xp:QBPVT', \%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{o}) { # -o for online cluster only $Opt_Only_Online = $TRUE; } if (defined $opts{O}) { # -O for not online clusters # only if ($Opt_Only_Online) { # -o already specified printCEMsg("EMsgConfigRMcliImproperUsageCombination","-o","-O"); &print_usage; exit(CRM_CLI_BAD_FLAG); } $Opt_Only_NotOnline = $TRUE; } if (defined $opts{L}) { # -L for list local only if ($Opt_Only_Online) { # -o already specified printCEMsg("EMsgConfigRMcliImproperUsageCombination","-o","-L"); &print_usage; exit(CRM_CLI_BAD_FLAG); } if ($Opt_Only_NotOnline) { # -O already specified printCEMsg("EMsgConfigRMcliImproperUsageCombination","-O","-L"); &print_usage; exit(CRM_CLI_BAD_FLAG); } $Opt_Local = $TRUE; } if (defined $opts{D}) { # -D delimited output with specified $Opt_Delm_Format = $TRUE; # delimiter $Opt_Delm_Str = $opts{D}; $Opt_Long_Format = $FALSE; } if (defined $opts{d}) { # -d delimited output $Opt_Delm_Format = $TRUE; $Opt_Delm_Str = ":"; $Opt_Long_Format = $FALSE; } if (defined $opts{t}) { # -t table formatted output $Opt_Table_Format = $TRUE; $Opt_Long_Format = $FALSE; $Opt_Delm_Format = $FALSE; } if (defined $opts{l}) { # -l long formatted output $Opt_Long_Format = $TRUE; $Opt_Table_Format = $FALSE; $Opt_Delm_Format = $FALSE; } if (defined $opts{x}) { # -x supress headings $Opt_No_HDR = $TRUE; } if (defined $opts{i}) { # -i show nodenum and nodeid $Opt_ShowNodeNums = $TRUE; } if (defined $opts{Q}) { # -Q show IsQuorumNode $Opt_ShowQuorum = $TRUE; } if (defined $opts{B}) { # -B show IsQuorumNode $Opt_ShowTieBreaker = $TRUE; } if (defined $opts{P}) { # -P show IsPreferredGSGL $Opt_ShowPrefGSGL = $TRUE; } # Get the arguments... # Operands: node name if ($#ARGV <= 0) { # node name if ($#ARGV == 0) { $node_name = shift @ARGV; # get node name } } else { # cluster name not specified or too many printCEMsg("EMsgConfigRMcliInvalidNumberOfOperands"); &print_usage; return CRM_CLI_BAD_OPERAND; } if (defined $opts{p}) { # -p show cluster from registry if ($Opt_Only_NotOnline) { # -O already specified printCEMsg("EMsgConfigRMcliImproperUsageCombination","-O","-p"); &print_usage; exit(CRM_CLI_BAD_FLAG); } if ($Opt_Only_Online) { # -o already specified printCEMsg("EMsgConfigRMcliImproperUsageCombination","-o","-p"); &print_usage; exit(CRM_CLI_BAD_FLAG); } if ($Opt_Local) { # -L already specified printCEMsg("EMsgConfigRMcliImproperUsageCombination","-L","-p"); &print_usage; exit(CRM_CLI_BAD_FLAG); } if ($Opt_ShowNodeNums) { # -i already specified printCEMsg("EMsgConfigRMcliImproperUsageCombination","-i","-p"); &print_usage; exit(CRM_CLI_BAD_FLAG); } if ($Opt_ShowQuorum) { # -Q already specified printCEMsg("EMsgConfigRMcliImproperUsageCombination","-Q","-p"); &print_usage; exit(CRM_CLI_BAD_FLAG); } if ($Opt_ShowTieBreaker) { # -B already specified printCEMsg("EMsgConfigRMcliImproperUsageCombination","-B","-p"); &print_usage; exit(CRM_CLI_BAD_FLAG); } if ($Opt_ShowPrefGSGL) { # -P already specified printCEMsg("EMsgConfigRMcliImproperUsageCombination","-P","-p"); &print_usage; exit(CRM_CLI_BAD_FLAG); } if ($node_name ne "") { # node name specified printCEMsg("EMsgConfigRMcliInvalidNumberOfOperands"); &print_usage; exit(CRM_CLI_BAD_OPERAND); } $Opt_Cluster = $TRUE; $cluster_name = $opts{p}; } return(0, $node_name, $cluster_name); # success } # end parse_cmd_line #--------------------------------------------------------------------# # print_usage : print the usage statement (syntax) to stdout. # #--------------------------------------------------------------------# sub print_usage { #&printIMsg("IMsglsrpnodeUsageI"); &printIMsg("IMsglsrpnodeUsageIQPB"); } # end print_usage #--------------------------------------------------------------------# # list_cluster_nodes : Returns an array of cluster node name for the # # cluster name specified. The information is taken from the system# # registry. # # # # Parameters: # # $cluster_name The name of the cluster for which the cluster # # node names are to be found. # # # # Returns: # # @node_names Array of cluster node names for the cluster. # # # #--------------------------------------------------------------------# sub list_cluster_nodes { my $cluster_name = shift(@_); # cluster name to look up my $trace_opt = ""; # don't trace lssrtbl my @listout2 = (); # lsrsrc-api output my @listout = (); # sorted lsrsrc-api output $main::Trace && print STDERR "$main::PROGNAME: calling lssrtbl-api\n"; $main::Trace && ($trace_opt = " -T "); # export the appropriate environment variable $ENV{CT_SR_FS_HOME} = "/var/ct/$cluster_name/registry/local_tree"; # list the nodes for the cluster from the registry @listout2 = `$CTBINDIR/lssrtbl-api $trace_opt -D $DELIMITER -s /IBM/PeerNode/Resources::::Name 2>&1`; $rc = $?; $rc = process_exit_code($rc); $main::Trace && print STDERR "$main::PROGNAME: lssrtbl-api returned $rc\n"; # see if no cluster was found if ($rc == $RMC_CLI_USER_ERROR) { # print not found error printEMsg("EMsglsrpnodeClusterNotFound",$cluster_name); exit(CRM_CLI_USER_ERROR); } # if list command failed, print RMC error message and exit if ($rc != 0) { # print the error process_api_error($DELIMITER,$rc,@listout2); exit(CRM_CLI_RMC_ERROR); } # sort the cluster node names returned @listout = sort @listout2; # return the cluster node names return(@listout); } # end of list_cluster_nodes #--------------------------------------------------------------------# # xlate_dec2hex_hardway : Returns a hex string from a decimal value # # that is stored in a string. The builtin "hex" function was not # # used because it doesn't work if the hex value is longer than 8 # # places. Also, not all supported perl releases support 64 bit # # integers. So do it the hard way.... # # # # Parameters: # # $decimal_str The decimal value to convert to hex. # # # # Returns: # # $hex_val The hexidecimal value that represents the # # decimal value. # # # #--------------------------------------------------------------------# sub xlate_dec2hex_hardway { use POSIX; my $decimal_val = shift(@_); # get the value to convert my $hex_val = ""; # the final haex value my @remainders = (); # the list of remainders my $i = 0; # remainder counter my $j = 0; # place in $decimal_val my $done = $FALSE; # is the dividing done? my $dec_len = 0; # length of $decimal_val my $tmp = ""; # what is currently being divided my $tmp2 = ""; # builds quotient my $tmp_q = 0; # intermediate quotient my $tmp_r = 0; # intermediate remainder # the idea is to simulate long division # divide by 16 one place at a time, left to right # this while loop continues until no more divisions by 16 are possible while (!$done) { $j = 0; $dec_len = length $decimal_val; # this while loop does the long division, left to right while ($j < $dec_len) { # get the next digit to the right $tmp .= substr($decimal_val,$j,1); $tmp_q = floor ($tmp / 16); $tmp_r = $tmp % 16; # Use the remainder in the next division unless it couldn't be divided # at all, then you need to keep it for the next time around if ($tmp_q != 0) {$tmp = $tmp_r;} # tmp2 builds the quotient (to use for next time around outer loop) $tmp2 .= $tmp_q; $j++; } # save the remainder for the entire division by 16. it's part of the final answer. $remainders[$i] = $tmp_r; $i++; # if there's nothing left to divide, stop if ($tmp2 == 0) { $done = $TRUE;} # build next value to divide by 16 else { $tmp2 =~ s/^0*//; $decimal_val = $tmp2; $tmp2 = ""; $tmp = ""; } } # end while not done # form the hex value from the remainders for ($i=$#remainders; $i >= 0; $i--) { if ($remainders[$i] >= 10) { # $remainders[$i] = chr($remainders[$i] + 87); $remainders[$i] = chr( ord("a") + ($remainders[$i] - 10) ); } $hex_val .= $remainders[$i]; } return($hex_val); } # end of xlate_dec2hex_hardway #--------------------------------------------------------------------# # lookupQuorum_yesno : Translates the quorum value into "no" or "yes"# # # # Parameters: # # $trans_value Value to translate. # # @trans_array Values used to translate # # # # Returns: # # $descr "yes" if quorum, "no" if not. # # # # Global Variables: # #--------------------------------------------------------------------# sub lookupQuorum_yesno { my $trans_value = 0; # value to translate my $descr = "?"; # default - don't know my $use_quotes = $FALSE; # boolean flag my @trans_array =(); # array with the values # get inputs $trans_value = shift @_; @trans_array = @_; # figure out if quotes are needed around strings if ( (defined $ENV{CT_CLI_QUOTE_STRING}) && ($ENV{CT_CLI_QUOTE_STRING} == 1) ) { $use_quotes = $TRUE; } # translate the value # 1 or 3 is a yes if (($trans_value == 1) || ($trans_value == 3)) { $descr = $trans_array[1]; } else { # set to no $descr = $trans_array[0]; } # add quotes if necessary if ($use_quotes) { $descr = "\"".$descr."\""; } return($descr); } # end of lookupQuorum_yesno #--------------------------------------------------------------------# # lookupTieBreaker_yesno : Translates the tiebreaker value into "no" # # or "yes" # # # # Parameters: # # $trans_value Value to translate. # # @trans_array Values used to translate # # # # Returns: # # $descr "yes" if tiebreaker, "no" if not. # # # # Global Variables: # #--------------------------------------------------------------------# sub lookupTieBreaker_yesno { my $trans_value = 0; # value to translate my $descr = "?"; # default - don't know my $use_quotes = $FALSE; # boolean flag my @trans_array =(); # array with the values # get inputs $trans_value = shift @_; @trans_array = @_; # figure out if quotes are needed around strings if ( (defined $ENV{CT_CLI_QUOTE_STRING}) && ($ENV{CT_CLI_QUOTE_STRING} == 1) ) { $use_quotes = $TRUE; } # translate the value # 1 or 2 is a yes if (($trans_value == 1) || ($trans_value == 2)) { $descr = $trans_array[1]; } else { # set to no $descr = $trans_array[0]; } # add quotes if necessary if ($use_quotes) { $descr = "\"".$descr."\""; } return($descr); } # end of lookupTieBreaker_yesno