#!/usr/local/bin/perl
# 
# $Header: crs_status_cluster.pl 26-feb-2007.15:10:53 ajdsouza Exp $
#
# crs_status_cluster.pl
# 
# Copyright (c) 2005, 2007, Oracle. All rights reserved.  
#
#    NAME
#      crs_status_cluster.pl - <one-line expansion of the name>
#
#    DESCRIPTION
#      <short description of component this file declares/defines>
#
#    NOTES
#      <other useful comments, qualifications, etc.>
#
#    MODIFIED   (MM/DD/YY)
#    ajdsouza    01/23/07 - fix bug 5732015,5732112,
#                            5527466,5494189
#    xuliu       10/21/05 - bug 4667678 
#    ysun        07/15/05 - ysun_bug-4458582
#    ysun        07/15/05 - Creation
# 

use strict;
use warnings;

use File::Spec::Functions;
use File::Basename;
use File::Path;
use Data::Dumper;
use locale;
use siha::Common;

require "emd_common.pl";
require "semd_common.pl";

my $cmd;

my ($rootDir, $crsVersionCategory) = @ARGV; # CRSHome
$cmd = 'olsnodes';
$rootDir =~ s/^\s+|\s+$//g if $rootDir;

if ( $crsVersionCategory 
      and $crsVersionCategory =~ /10gR1|pre10g|DefaultRange/i )
{
  print "em_result=1||\n";
  exit 0;
}

unless ( $rootDir )
{
 $rootDir = $ENV{CRS_HOME};
 $cmd = 'olsnodes';
}

unless ( $rootDir )
{
 $rootDir = $ENV{ORACLE_HOME};
 $cmd = 'olsnodes';
}

unless ( $rootDir )
{
 $rootDir = $ENV{EMDROOT};
 $cmd = 'lsnodes';
}

siha::Common::exit_fail("crs_status_cluster.pl:Failed to get rootdir for cluster binaries olsnodes and cluvfy")
 unless $rootDir and $rootDir !~ /#CRS_HOME#/;

EMD_PERL_DEBUG("crs_status_cluster.pl:**crs home is: $rootDir");

# bug 4667678
my $oldOH = $ENV{ORACLE_HOME};
$ENV{ORACLE_HOME} = $rootDir;

my $tmppath = catfile($rootDir,'bin');
$ENV{PATH}="$tmppath:$ENV{PATH}";

# default settings
my $crsIsUp = 1;
my $failedCount = 0;
my $successCount = 0;
my $errCount=0;
my $o;
my $nodes;
my @nlist;
my @fnlist;

#get the list of nodes using olsnodes
my %command_args = (exit_failure_list => [()]);

$nodes = siha::Common::runsystemcommand("$cmd 2>&1",'',%command_args);

siha::Common::exit_fail("crs_status_cluster.pl:Failed executing command **$cmd")
 if $command_args{command_return_status};

chomp($nodes) if $nodes;
$nodes=~ s/^\s+|\s+$//g if $nodes;
$nodes =~ s/\n/,/g if $nodes;
$nodes =~ s/,\s+,/,,/g if $nodes;
$nodes =~ s/,+/,/g if $nodes;
$nodes=~ s/^,|,$//g if $nodes;

# for the list of nodes execute cluvfy
if ( $nodes )
{

  @nlist = split(/,/, $nodes);

  EMD_PERL_DEBUG("crs_status_cluster.pl:**Node List: $nodes");
  
  %command_args = (exit_failure_list => [()]);
  
  # execute cluvfy new format with -display_status
  # ideally this should be a version check so cluvfy is executed only once
  $o = siha::Common::runsystemcommand(
                "cluvfy comp crs -display_status -n $nodes 2>&1",'',%command_args);

  $o =~ s/^\s+|\s+$// if $o;

  #execute cluvfy new format without -display_status if flag option is not
  # supported
  unless ( $o and  $o =~ /NODE_STATUS::/i )
  {
    %command_args = (exit_failure_list => [()]);
    $o = siha::Common::runsystemcommand(
                "cluvfy comp crs -n $nodes 2>&1",'',%command_args);
    $o =~ s/^\s+|\s+$// if $o;
  }

  chomp($o) if $o;

  siha::Common::exit_fail("crs_status_cluster.pl:Failed to get any results from cluvfy comp crs -n $nodes") 
   unless $o;

  # output with -display_status flag 
  # cluvfy comp crs -display_status -n staca31
  #NODE_STATUS::Node1:SUCC
  #NODE_STATUS::Node2:EFAIL
  #NODE_STATUS::Node3:VFAIL
  #NODE_STATUS::Node4:SUCC
  #OVERALL_STATUS::EFAIL

  # if cluvfy comp crs -n node1, node2 does not return a success 
  # for all nodes the exit status is failure
  for ( (1) )
  {

    # crs is up if cluvfy did not return a failure
    unless  ( $command_args{command_return_status} )
    {
      $crsIsUp = 1;
      $failedCount=0;
      last;
    }

    #------------------------------------------------------------------
    # check for failed nodes etc only if the cluvfy returned a failure
    #------------------------------------------------------------------
    #
    # for pre11g version we are trying to get the list of failed nodes
    # from the cli output using the following logic
    # cluvfy  comp crs -n <nodes>
    # a) fails on all nodes
    #   Verification of CRS integrity was unsuccessful on all the nodes.
    # b) partial failure , fails on some nodes
    #   Verification of CRS integrity was unsuccessful.
    #   checks did nto pass for the following node(s):
    #   node1,node2
    # c)all successful
    #   Verification of CRS integrity was successful
    #
    #  email sent by dipak.saggi confirming the messages
    #        "Verification of {0} was unsuccessful on all the nodes. "
    #       "Verification of {0} was unsuccessful. "
    #       "Checks did not pass for the following node(s):"
    #
    my $with_node_status_for_em = 'NODE_STATUS::|OVERALL_STATUS::';
    my $failed_on_some_nodes= 
     'Checks\s+did\s+not\s+pass\s+for\s+the\s+following\s+node\(s\):';
    my $failed_on_all_nodes =
     'unsuccessful\s+on\s+all\s+the\s+nodes';

    my $error_executing_cluvfy =
'ERROR:|CRS\s+is\s+not\s+installed\s+on\s+any\s+of\s+the\s+nodes|Verification\s+cannot\s+proceed|User\s+equivalence\s+is\s+not\s+set\s+for\s+nodes';

    # if cluvfy supports the displsy_status flag and gives NODE_STATUS
    if ( $o =~ /$with_node_status_for_em/ )
    {
       my @inp = split /\n/,$o;
       my @rows = grep /$with_node_status_for_em/, @inp;

       my $nodeVerificationFailed;

       for my $row ( @rows )
       {
          $row =~ s/^\s+|\s+$//;

          #success
          $successCount +=1 and next 
           if $row and $row =~ /NODE_STATUS::.+:SUCC$/;


          #if command returns overall success, then take the results of overall
          # and declare crs is up on all nodes
          if ( $row and $row =~ /OVERALL_STATUS::SUCC/ )
	  {
            $crsIsUp=1;
            $failedCount=0;
            $successCount = @nlist;
            last;
	  }

          # verification failed, increment failed count
          $failedCount +=1  and next if $row =~ /NODE_STATUS::.+:VFAIL/;

          # execution failure
          $errCount += 1 and next unless $row =~ /NODE_STATUS::.+:EFAIL/;

          my ($node) = ( $row =~ /NODE_STATUS::(.+):EFAIL/);

          siha::Common::warn_message
           ("crs_status_cluster.pl:Failed to get Status verification failed node name from $row\n")
            and next unless $node;

          $nodeVerificationFailed = "$nodeVerificationFailed,$node" 
           and next
           if $nodeVerificationFailed;

          $nodeVerificationFailed = "$node"
           unless $nodeVerificationFailed;
       }

       siha::Common::warn_message
         ("crs_status_cluster.pl:Status verification failed for node $nodeVerificationFailed\n")
          if $nodeVerificationFailed;

       # crs is down if all nodes failed or failed count is > nodes
       $crsIsUp = 0 if scalar(@nlist) == $failedCount;
       $crsIsUp = 0 unless $successCount;

    }
    elsif ($o =~ /$failed_on_some_nodes/i)
    {

       my $fo = $o;
       $fo =~ s/\n+/,/g;

       my ($ignore,$fnodes) =
         ( $fo =~ /.*($failed_on_some_nodes)(.*)$/i);

        $fnodes =~ s/,\s+,/,/g;
        $fnodes =~ s/,+/,/g;
        $fnodes =~ s/^\s+|\s+$//;
        $fnodes =~ s/^,+|,+$//;

        EMD_PERL_DEBUG(
         "crs_status_cluster.pl:**failed node list:($fnodes)");

        @fnlist = split(/,/, $fnodes);
        $failedCount = scalar(@fnlist);

        # if crs is up on atleast one node then crs is up
        if (  scalar(@nlist) == scalar (@fnlist) )
	{
         $crsIsUp = 0;
         last;
        }

        $crsIsUp = 1;
        last;

    }
    elsif ($o =~ /$failed_on_all_nodes/i )
    {
      $crsIsUp = 0;
      $failedCount=scalar(@nlist);
      last;
    }
    elsif ($o =~ /$error_executing_cluvfy/i )
    {
      $crsIsUp =2;
      $failedCount=scalar(@nlist);
      siha::Common::warn_message
        ("crs_status_cluster.pl:Failed to get Status for cluster, CRS verification failed for cluster $o\n");
      last;
    }
    else
    {
      $crsIsUp = 2;
      $failedCount=scalar(@nlist);
      siha::Common::warn_message
       ("crs_status_cluster.pl:Failed to get Status for cluster , CRS verification failed for cluster $o\n");
      last;
    }

  }

}
else
{
  # if olsnodes returns null then return an warning and 
  #mark cluster status as down
  siha::Common::warn_message
   ("crs_status_cluster.pl:$cmd returns No cluster node list\n");

  $crsIsUp = 2;
  $failedCount = 0;

  $o = "$cmd returns No cluster node list";
}

$o =~ s/\n/ /g;

print "em_result=", $crsIsUp, "|", $failedCount, "|", $o, "\n";

$ENV{ORACLE_HOME} = $oldOH;

exit 0;


END
{

  $ENV{ORACLE_HOME} = $oldOH if $oldOH;

  siha::Common::save_systemcmdoutput or
   warn "crs_status_cluster.pl:Failed to save the test results from crs_status_cluster.pl\n";

}
