#!/usr/bin/perl # IBM_PROLOG_BEGIN_TAG # This is an automatically generated prolog. # # # # Licensed Materials - Property of IBM # # (C) COPYRIGHT International Business Machines Corp. 2000,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 = "@(#)28 1.25 src/rsct/rm/SensorRM/cli/bin/lssensor.perl, sensorcli, rsct_rady, rady2035a 11/12/15 16:37:17" # Lists resources from the RMC IBM.Sensor class use strict; use locale; BEGIN { # this enables us to redirect where it looks for other RSCT files during development $::rsctroot = $ENV{'RSCT_ROOT'} || '/opt/rsct'; $::rsctpm = "$::rsctroot/pm"; $::rsctmsgmaps = "$::rsctroot/msgmaps"; } use lib $::rsctpm; use Getopt::Long; use CT_cli_utils qw(printIMsg printEMsg); use CT_cli_display_utils qw(set_display); use CT_cli_input_utils qw( check_input_file unescape_chars ); use MC_cli_utils qw( read_from_Stdin process_api_error remove_api_error ); $main::PROGNAME = 'lssensor'; $main::MSGCAT = 'sensorcli.cat'; $main::LSMSG = '/opt/rsct/bin/ctdspmsg'; # For the usage, see sensorcli.msg #sub usage { printIMsg('IMsgLssensorUsage2'); exit (scalar(@_) ? $_[0] : 1); } #sub usage { printIMsg('IMsgLssensorUsage3'); exit (scalar(@_) ? $_[0] : 1); } sub usage { printIMsg('IMsgLssensorUsage4'); exit (scalar(@_) ? $_[0] : 1); } Getopt::Long::Configure ("bundling", "no_auto_abbrev", "no_ignore_case", "require_order", "prefix_pattern=(--|-)"); # Parse the cmd line args and check them if(!GetOptions( 'h|help|version' , 'A' , 'a' , 'd' , 'l' , 'm' , 't' , 'v' , 'V' , 'x' , 'D=s' , 'n=s', 'N=s' )) { &usage; } if ($::opt_h) { &usage(0); } if ((scalar(@ARGV)>0 && $::opt_A) || (defined($::opt_n) && defined($::opt_N)) || ($::opt_a && defined($::opt_N)) || ($::opt_a && defined($::opt_n))) { &usage; } if ($::opt_V) { $::opt_v = 1; } # determine the class to use my $CLASSNAME = "IBM.Sensor"; if ($::opt_m) { $CLASSNAME = "IBM.MicroSensor"; } my $options = ''; my $selectstr = ''; my $attr = ''; my $format = "column"; my $delim= ""; my $No_HDR= 0; my $node_file_flag = 0; # node_file_flag =1 if -N was specified. my $node_file_name = ""; # node_file_name my $node_file_from_stdin = 0; # node_file_from_stdin = 1 if -N '-' my @dcount =(); my @output_wmsgs = (); my $name = ''; # set -api command delimiters my $DELIMITERI = "tvitvitvi"; my $DELIMITERO = "tvotvotvo"; if ($::opt_A) # show everything { $options = "-I $DELIMITERI -D $DELIMITERO -n -i"; $attr = "'*b0x0020'"; $format = "old_long"; } elsif (scalar(@ARGV) >= 1) # show all attributes of this sensor { $options = "-I $DELIMITERI -D $DELIMITERO -n"; $attr = "'*b0x0020'"; $name = join("','",@ARGV); $selectstr = q/Name IN ('/ . join("','",@ARGV) . q/')/; $format = "old_long"; } else # show all sensor names { $options = "-I $DELIMITERI -D $DELIMITERO -n -i"; $attr = 'Name'; if ($::opt_a || defined($::opt_n)||defined($::opt_N)) { $attr .= "${DELIMITERI}NodeNameList"; } } if ($::opt_l) { # if (!$No_HDR) # { $format= "long"; # } } elsif ($::opt_t) { $format = "column"; $delim= $DELIMITERO; } elsif($::opt_d) { $format = "delim"; $delim= ":"; } elsif ($::opt_D) { $format= "delim"; $delim= "$::opt_D"; } if ($::opt_x) { $No_HDR= 1; } if ($::opt_a || defined($::opt_n) || defined($::opt_N)) { if ($ENV{CT_MANAGEMENT_SCOPE}!=2 && $ENV{CT_MANAGEMENT_SCOPE}!=3) { $ENV{CT_MANAGEMENT_SCOPE}=4; } } if (defined($::opt_n)) { my @nodes = split(/[, ]+/,$::opt_n); if (length($selectstr)) { $selectstr .= ' && '; } $selectstr .= q/NodeNameList IN ('/ . join("','",@nodes) . q/')/; } if (defined($::opt_N)) { $node_file_name = $::opt_N; $node_file_flag = 1; if ( $node_file_name eq "-" ) { $node_file_from_stdin = 1; } else { if ( check_input_file($node_file_name) ) { exit(1); } } } if (length($selectstr)) { $selectstr = qq("$selectstr"); } # setup lsrsrc-api cmdline. my $cmd = ''; if ( $node_file_flag == 0 ) { $cmd = qq(/usr/bin/lsrsrc-api $options -s ${CLASSNAME}${DELIMITERI}${selectstr}${DELIMITERI}$attr 2>&1); } else { if ($node_file_from_stdin != 0) { $node_file_name = read_from_Stdin(); } $cmd = qq(/usr/bin/lsrsrc-api $options -w ${CLASSNAME}${DELIMITERI}${selectstr}${DELIMITERI}${node_file_name}${DELIMITERI}$attr 2>&1); } if ($::opt_v) { printIMsg('IMsgRmcCmd', $cmd); } my @output = `$cmd`; my $rc = $? >> 8; # remove temp node file if it is from STDIN if ($node_file_from_stdin != 0) { unlink($node_file_name); } #if ($rc) #{ # #if (!$::opt_v) { $output[0] =~ s/.*:\|:.*:\|:.*:\|:.*:\|:.*:\|://; } # #print @output; # #exit $rc; # process_api_error(':\|:', $rc, @output); # @output = remove_api_error(':\|:', @output); #} @output_wmsgs = @output; @output = remove_api_error($DELIMITERO, @output); my $lsrc = $rc; chop(@output); # add in any dynamic attrs that aren't monitored if ( ! ($attr =~ /^Name$/) ) { &reformatOutput; } # show any error messages from original output # suppress "dyn attr not monitored" msg, unless verbose $lsrc = &process_api_most_error($DELIMITERO, $lsrc, @output_wmsgs); if ( $#output <0 ) { exit ($lsrc); } # Display output if ($format eq "old_long") { &displayLong; } else { my $divider= `$main::LSMSG $main::PROGNAME $main::MSGCAT IMsgLssensorDivider`; my $line; my $i; my $j= 1; my @Lof_conds=(); # Create a Header $Lof_conds[0][0] = `$main::LSMSG $main::PROGNAME $main::MSGCAT IMsgLssensorOut`; if ($format eq "delim") { $Lof_conds[0][0]= $Lof_conds[0][0] . "\n"; } $line = $output[0]; my %attrnames = split(/$DELIMITERO/, $line); $j = 1; # $Lof_conds[0][$j]= "Name"; $Lof_conds[0][$j]= scalar(`$main::LSMSG $main::PROGNAME $main::MSGCAT IMsgLssensorNameHeading`); delete $attrnames{Name}; foreach my $attrname (sort keys %attrnames) { $j++; $Lof_conds[0][$j]= $attrname; } $j = 1; foreach $line (@output) { if ($j == 1) { $Lof_conds[$j][0] = "$divider $j:"; } else { $Lof_conds[$j][0] = "\n$divider $j:"; } my %attrs = split(/$DELIMITERO/, $line); # Convert the value of TimeCommandRun to a user friendly one if ( defined($attrs{TimeCommandRun}) && ($attrs{TimeCommandRun} ne "") ) { $attrs{TimeCommandRun}= localtime($attrs{TimeCommandRun}); } if ( defined($attrs{LastQueryTime}) && ($attrs{LastQueryTime} ne "") ) { $attrs{LastQueryTime}= localtime($attrs{LastQueryTime}); } # Make sure the hostname is displayed 1st if (defined($attrs{Name})) { $Lof_conds[$j][1]= $attrs{Name}; $i= 2; delete $attrs{Name}; # so we do not repeat it in the following loop } else { $i= 1; } foreach my $k (sort keys %attrs) { # Fill the Attributes values $Lof_conds[$j][$i]= $attrs{$k}; $i++; } $j++; } my $row_count = $#Lof_conds; my $col_count = scalar(@{$Lof_conds[0]}); $rc = set_display($format, $No_HDR, $row_count, $col_count, \@Lof_conds, $delim); } if ( $lsrc != 0) { exit ($lsrc); } sub displayLong { my $firsttime = 1; foreach my $l (@output) { if (!$firsttime) { print "-------------------\n"; } # separate this resource from the previous else { $firsttime = 0; } # takes the alternating attrs and values and puts them in the hash correctly my %attrs = split(/$DELIMITERO/, $l); # Make sure the hostname is displayed 1st if (defined($attrs{Name})) { print " Name = $attrs{Name}\n"; delete $attrs{Name}; # so we do not repeat it in the following loop } # Convert the value of TimeCommandRun to a user friendly one if ( defined($attrs{TimeCommandRun}) && ($attrs{TimeCommandRun} ne "") ) { $attrs{TimeCommandRun}= localtime($attrs{TimeCommandRun}); } if ( defined($attrs{LastQueryTime}) && ($attrs{LastQueryTime} ne "") ) { $attrs{LastQueryTime}= localtime($attrs{LastQueryTime}); } # Now display the rest of the attributes, sorted foreach my $k (sort keys %attrs) { print " $k = $attrs{$k}\n"; } } } sub reformatOutput # merge the output from lsrsrc-api and lsrsrcdef-api and reformat it # so it works with the existing display routines { my @junk = (); my @dynattr = (); # get a list of dynamic attributes my $cmd2 = ''; $cmd2 = qq(/usr/bin/lsrsrcdef-api -I $DELIMITERI -D $DELIMITERO -r ${CLASSNAME}${DELIMITERI}*d0x0020 2>&1); if ($::opt_v) { printIMsg('IMsgRmcCmd', $cmd2); } my @defoutput = `$cmd2`; my $rc2 = $? >> 8; process_api_error($DELIMITERO, $rc2, @defoutput); @defoutput = remove_api_error($DELIMITERO, @defoutput); # create array of dynamic attr names my $m=0; foreach my $l2 (@defoutput) { if ( !( $l2 =~ /CT_NONE/ ) ) { ($dynattr[$m], @junk) = split (/$DELIMITERO/, $l2); $m++; } } # loop through each resource my $i =0; for ($i=0; $i<=$#output; $i++) { @dcount[$i]=0; my %attrs = split(/$DELIMITERO/, $output[$i]); # check to see if all dynamic attrs are in @output line foreach my $dattr (@dynattr) { if ( ! defined ($attrs{$dattr}) ) { # add it to @output $output[$i] .= "$DELIMITERO${dattr}$DELIMITERO"; } else { # count that we got a dyn attr from lsrsrc-api @dcount[$i]++; } } } } sub process_api_most_error { my $delimiter = shift(@_); # output delimiter my $api_rc = shift(@_); # rc from c-api call my @command_output = @_; # command output to scan my $error_count = 0; # number of error messages my @error_parts = (); my $dyn_error_count = 0; # number of error messages my $RMC_DYNATTR_NOTMONITORED_RC = 262177; # RMC rc if dynamic attr not monitored # scan each line for ERROR foreach my $line (@command_output) { # does it start with ERROR? if ($line =~ /^ERROR.*/) { # split it apart based on double colons # last one should be error message @error_parts = split /$delimiter/, $line; # replace any escaped new lines with new lines $error_parts[$#error_parts] =~ s/\\n/\n/g; # get rid of any beginning/ending quote that comes from # having CT_CLI_QUOTE_STRING turned on (sometimes) if ( defined $ENV{CT_CLI_QUOTE_STRING} && $ENV{CT_CLI_QUOTE_STRING}==1) { $error_parts[$#error_parts] =~ s/^\"//; $error_parts[$#error_parts] =~ s/\"$//; #$error_parts[$#error_parts] =~ s/\\\"/\"/g; $error_parts[$#error_parts] = unescape_chars($error_parts[$#error_parts]); } if ( ($::opt_v) || ($error_parts[4] != $RMC_DYNATTR_NOTMONITORED_RC) ) { # last one should be error message. print it to STDERR. if($lsrc == 6) { if ($::opt_v) { print STDERR $error_parts[$#error_parts]; } printEMsg('EMsgResNotDefinedLs',$name); } else { print STDERR $error_parts[$#error_parts]; } } if ($error_parts[4] == $RMC_DYNATTR_NOTMONITORED_RC) { $dyn_error_count++; } else { $error_count++; } } } # set the return code based on how many non-"dyn attr not monitored" msgs there are if ($error_count > 0) { return ($api_rc); } else # if only non-"dyn attr not monitored" msgs, reset rc to 0 { return (0); } } # end of process_api_most_error