#!/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 = "@(#)18 1.22 src/rsct/rm/ConfigRM/cli/bin/lscomg.perl, configrmcli, rsct_rady, rady2035a 11/12/15 16:41:03" ###################################################################### # # # Module: lscomg # # # # Purpose: # # lscomg - lists information about the communication groups of a # # cluster. # # # # Syntax: # # lscomg [-h] [-l|-t|-d|-D Delimiter] [-x] [-TV] # # [Communication_group] # # # # Flags: # # -h Help. Writes the command's usage statement to standard # # output. # # -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. # # -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: # # Communication_group The name of the communication group to be # # listed. Communication_group may be a communication group # # name or a substring of a communication group name. When # # it is a substring, any defined communication group name # # that contains the substring will be listed. # # # # Description: # # The lscomg command lists information about the communication # # groups defined to the online cluster where the command runs. # # When a communication group is specified, the information is # # limitted to that communication group information only. # # # # # # 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: # # # # Man Page: # # For the most current detailed description of this command see # # the lscomg man page in /opt/rsct/man. # # # #--------------------------------------------------------------------# # Inputs: # # /opt/rsct/msgmaps/configrmcli.lscomg.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. # # 011130 JAC 77315: updates for final approved design. # # 020204 JAC 80023: update 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 79346: Add NodeNameList to -i output. # # 020207 JAC 80133: Issue not found message if a comg specified. # # 020214 JAC 80323: Remove braces around nodenamelist for -i. # # 020428 JAC 82316: Call process_exit_code to check $rc. # # 020503 JAC 82564: Set peer domain scope before calling lsrsrc-api# # 040407 JAC 105863: Use escape_chars for "\" searches. # # 040422 JAC 108194: Use escape_selstr for comg name and use LIKE # # in select string. # # 050406 JAC 119510: Add rc when calling process_api_error. # # 071210 JAC 147147: Use PeriodMillSec and add Grace. # ###################################################################### #--------------------------------------------------------------------# # 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_input_utils qw(escape_chars); use CT_cli_display_utils qw(set_display); use CRM_cli_rc qw(CRM_CLI_SUCCESS CRM_CLI_RMC_ERROR CRM_CLI_ERROR CRM_CLI_BAD_FLAG CRM_CLI_COMG_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 escape_selstr lookup_yesno lookup_mediatype); use CRM_cli_include qw($TRUE $FALSE $RSCOMG $RMC_CLI_USER_ERROR $DELIMITER $RSNETI $RSHBI $PEER_DOMAIN_SCOPE $RMC_CLI_RSRC_NOT_FOUND $CTBINDIR $CTDIR); my $delimiter = "#:#"; $DELIMITER = $delimiter; # override so utils don't choke on IPv6 "::" #--------------------------------------------------------------------# # Global Constants # #--------------------------------------------------------------------# # attribute names $Attr_name = "Name"; $Attr_sensitivity = "Sensitivity"; $Attr_period = "PeriodMilliSec"; $Attr_priority = "Priority"; $Attr_broadcast = "UseBroadcast"; $Attr_sourcerte = "UseSourceRouting"; #$Attr_configch = "ConfigChanged"; $Attr_NIMpname = "NIMPathName"; $Attr_NIMparms = "NIMParameters"; $Attr_grace = "PingGracePeriodMilliSec"; $Attr_MediaType = "MediaType"; $Attr_UseForNodeMbrship = "UseForNodeMembership"; $lsr_attr_names = $Attr_name; $lsr_attr_names .= "${delimiter}$Attr_sensitivity"; $lsr_attr_names .= "${delimiter}$Attr_period"; $lsr_attr_names .= "${delimiter}$Attr_priority"; $lsr_attr_names .= "${delimiter}$Attr_broadcast"; $lsr_attr_names .= "${delimiter}$Attr_sourcerte"; $lsr_attr_names .= "${delimiter}$Attr_NIMpname"; $lsr_attr_names .= "${delimiter}$Attr_NIMparms"; $lsr_attr_names .= "${delimiter}$Attr_grace"; $lsr_attr_names .= "${delimiter}$Attr_MediaType"; $lsr_attr_names .= "${delimiter}$Attr_UseForNodeMbrship"; # attribute names for -i flag (NetworkInterface) $Attr_name = "Name"; $Attr_nodename = "NodeNameList"; $Attr_ipaddr = "IPAddress"; $Attr_subnet = "Subnet"; $Attr_subnetmsk = "SubnetMask"; $lsr_attr_names2 = $Attr_name; $lsr_attr_names2 .= "${delimiter}$Attr_nodename"; $lsr_attr_names2 .= "${delimiter}$Attr_ipaddr"; $lsr_attr_names2 .= "${delimiter}$Attr_subnet"; $lsr_attr_names2 .= "${delimiter}$Attr_subnetmsk"; # attribute names for -i flag (HeartbeatInterface) $Attr_deviceinfo = "DeviceInfo"; $lsr_attr_names3 = $Attr_name; $lsr_attr_names3 .= "${delimiter}$Attr_nodename"; $lsr_attr_names3 .= "${delimiter}$Attr_deviceinfo"; $lsr_attr_names3 .= "${delimiter}$Attr_MediaType"; #--------------------------------------------------------------------# # 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_Display_i = $FALSE; # default - no -i $PROGNAME = "lscomg"; # 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 $comg_name = ""; # communication group to list my $comg_name_orig = ""; # communication group to list my $name_select = ""; # selection string for name my @lsr_out = (); # output from lsrsrc my @lof_comgs = (); # 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 $broadcst_index = 5; # output index for broadcast my $sourcert_index = 6; # output index for source rte my $nodename_index = 2; # output index for nodename my $period_index = 3; # output index for period my $grace_index = 9; # output index for grace my $mediatype_index = 10; # output index for MediaType my $mediatype_index_i = 4; # output index for MediaType for -i flag my $resource_class = ""; # class to list my @heading = (); # heading for listing data my $msg_ptr = "1X"; # keep track of which msg my @noyestext = (); # for translating no/yes my @gracetext = (); # for translating 0/-1 my @mediatypetext = (); # for translating MediaType my %media_types = (); # hash for MediaType descriptions 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, $comg_name) = &parse_cmd_line; ($rc == 0) || error_exit($rc); if ($Verbose) { printIMsg("IMsglscomgStart"); } if ($Trace) { $passopts = $passopts." -T"; } if ($Verbose) { $passopts = $passopts." -V"; } # Do some escaping on strings. Do the escape character first # for anything that's a string, escape any inner \ #$comg_name =~ s/\\/\\\\/g; # for anything that's a string, escape any inner double quotes #$comg_name =~ s/\"/\\\"/g; $comg_name_orig = $comg_name; $comg_name = escape_chars($comg_name); $comg_name = escape_selstr($comg_name); # if a comg name was entered, build a select clause if ($comg_name ne "") { # $name_select = "-s ${RSCOMG}${delimiter}\"Name ?= \\\"$comg_name\\\"\""; $name_select = "-s ${RSCOMG}${delimiter}\"Name LIKE \\\"%${comg_name}%\\\"\""; } # for no name, use o flag for list else { $name_select = "-o ${RSCOMG}"; } # if -i specified, switch some things if ($Opt_Display_i) { # Check MediaType @lsr_out = `$CTBINDIR/lsrsrc-api -I"$delimiter" -s ${RSCOMG}${delimiter}\"Name == \\\"$comg_name_orig\\\"\"${delimiter}MediaType 2>&1`; # capture the return code from lsrsrc-api $rc = $?; $rc = process_exit_code($rc); if ($Trace) { print STDERR "lsrsrc-api results:\n"; print "@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);} if ($rc == $RMC_CLI_RSRC_NOT_FOUND) { printEMsg("EMsglscomgComgNotFound",$comg_name_orig); exit(CRM_CLI_COMG_NOT_FOUND); } my $mediatype = $lsr_out[0]; chomp($mediatype); # change the attribute names and selection string if ($mediatype == 1) { $lsr_attr_names = $lsr_attr_names2; $name_select = "-s ${RSNETI}${delimiter}\"CommGroup == \\\"$comg_name_orig\\\"\""; $msg_ptr = 2; } else { $lsr_attr_names = $lsr_attr_names3; $name_select = "-s ${RSHBI}${delimiter}\"CommGroup == \\\"$comg_name_orig\\\"\""; $msg_ptr = 3; } } # call lsrsrc if ($Trace) { print STDERR "$PROGNAME: calling lsrsrc-api\n";} #@lsr_out = `$CTBINDIR/lsrsrc -x -D $DELIMITER $passopts $name_select $RSCOMG $lsr_attr_names`; #@lsr_out = `$CTBINDIR/lsrsrc -x -D $DELIMITER $passopts $name_select $resource_class $lsr_attr_names`; @lsr_out = `$CTBINDIR/lsrsrc-api -D"$DELIMITER" -I"$delimiter" ${name_select}${delimiter}${delimiter}${delimiter}${lsr_attr_names} 2>&1`; # capture the return code from lsrsrc-api $rc = $?; $rc = process_exit_code($rc); if ($Trace) { print STDERR "lsrsrc-api results:\n"; print "@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 comg name specified if ($rc == $RMC_CLI_RSRC_NOT_FOUND) { if ($comg_name eq "") { exit(0);} else { if ($Opt_Display_i) { if ($msg_ptr == 2) { printEMsg("EMsglscomgNetiNotFound",$comg_name_orig); } else { printEMsg("EMsglscomgHbiiNotFound",$comg_name_orig); } } else { printEMsg("EMsglscomgComgNotFound",$comg_name_orig);} exit(CRM_CLI_COMG_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); } # form 2D array to pass to display utils # get heading from message file @heading = getIMsg("IMsglscomgHeading$msg_ptr"); # form heading @attr_names = split(/::/,$heading[0]); $i = 1; foreach $attr_name (@attr_names) { $lof_comgs[0][$i] = $attr_name; $i++; } # get from message file what to use for no/yes @noyestext = getIMsg("IMsglscomgNoYes"); @noyestext = split(/::/,$noyestext[0]); # get from message file what to use for Grace @gracetext = getIMsg("IMsglscomgGraceValues"); @gracetext = split(/::/,$gracetext[0]); # get from message file what to use for MediaType @mediatypetext = getIMsg("IMsglscomgMediaType"); @mediatypetext = split(/::/,$mediatypetext[0]); # fill in the hash for opstates for ($mt_cnt=0;$mt_cnt<=$#mediatypetext;$mt_cnt=$mt_cnt+2) { $media_types{$mediatypetext[$mt_cnt]} = $mediatypetext[$mt_cnt+1]; } # 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_comgs[$i][0] = "\nnode $i:"; $lof_comgs[$i][0] = " "; $j = 1; foreach $attr_val (@attr_vals) { # translate source routing and broadcast when not -i if ( !$Opt_Display_i && ($j == $broadcst_index) || ($j == $sourcert_index)) { $attr_val = lookup_yesno($attr_val,@noyestext); } # format the period and grace period output when not -i if ( !$Opt_Display_i && ($j == $period_index) || ($j == $grace_index)) { $attr_val = &format_period($attr_val); # translate grace values, if necessary if ( $j == $grace_index ) { $attr_val = lookup_grace($attr_val,@gracetext); } } # translate MediaType if ($Opt_Display_i) { if (($msg_ptr == 3) && ($j == $mediatype_index_i)) { $attr_val = lookup_mediatype($attr_val,%media_types); } } else { if ($j == $mediatype_index) { $attr_val = lookup_mediatype($attr_val,%media_types); } } # get rid of braces in nodenamelist when -i used if ( $Opt_Display_i && ($j == $nodename_index)) { $attr_val =~ s/{//g; $attr_val =~ s/}//g; } # put output into the output array $lof_comgs[$i][$j] = $attr_val; $j++; } $i++; } # set how many rows of data there is $row_count = $#lof_comgs; $col_count = scalar(@{$lof_comgs[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_comgs, $Opt_Delm_Str); } if ($Verbose) { printIMsg("IMsglscomgEnd"); } 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_Display_i output True (-i) display interface resources# #--------------------------------------------------------------------# sub parse_cmd_line { my(@original_argv) = @ARGV; my $comg_name = ""; # comunication name my %opts = (); # Process the command line... if (!&getopts('hltdD:xiVT', \%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{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; } # Get the arguments... # Operands: comg name if ($#ARGV <= 0) { # comg name if ($#ARGV == 0) { $comg_name = shift @ARGV; # get comg name } } else { # cluster name not specified or too many printCEMsg("EMsgConfigRMcliInvalidNumberOfOperands"); &print_usage; return CRM_CLI_BAD_OPERAND; } if (defined $opts{i}) { # -i show interface resources $Opt_Display_i = $TRUE; if ($comg_name eq "") { # name required with -i printEMsg("EMsglscomgNameRequired","-i"); return CRM_CLI_USER_ERROR; } } return(0, $comg_name); # success } # end parse_cmd_line #--------------------------------------------------------------------# # print_usage : print the usage statement (syntax) to stdout. # #--------------------------------------------------------------------# sub print_usage { &printIMsg("IMsglscomgUsage"); } # end print_usage #--------------------------------------------------------------------# # format_period: format the period from milliseconds to seconds. # # # # Parameters: # # $in_value Milliseconds value. # # # # Returns: # # $out_value Formatted Seconds value. # # # # Global Variables: # #--------------------------------------------------------------------# sub format_period { my $in_value = shift(@_); my $out_value = $in_value; # format all values >0 if ($in_value > 0) { # convert from milliseconds to seconds $out_value = $in_value / 1000; # format to 3 decimal places $out_value = sprintf "%0.3f",$out_value; # get rid of trailing 0's $out_value =~ s/0+$//; # get rid of an ending decimal point $out_value =~ s/\.$//; } return ($out_value); } # format_period #--------------------------------------------------------------------# # lookup_grace : Translates the grace values to a text string, if # # one exists for the particular grace value. # # # # Parameters: # # $in_grace Grace value to check and make substitute. # # # # Returns: # # $out_grace The grace text to use for $in_grace, or just # # $in_grace if no substitution is done. # # # # Global Variables: # #--------------------------------------------------------------------# sub lookup_grace { my %grace_vals = (); # hash for grace descriptions my $use_quotes = $FALSE; # boolean flag my $one_descr = ""; # one from list of descriptions # get inputs my $in_grace = shift @_; %grace_vals = @_; #set default $out_grace my $out_grace = $in_grace; # figure out if quotes are needed around strings if ( (defined $ENV{CT_CLI_QUOTE_STRING}) && ($ENV{CT_CLI_QUOTE_STRING} == 1) ) { $use_quotes = $TRUE; } # see if grace value to find exists if (defined $grace_vals{$in_grace}) { $out_grace = $grace_vals{$in_grace}; # add quotes if necessary if ($use_quotes) { $out_grace = "\"".$out_grace."\""; } } return($out_grace); } # end of lookup_grace