#!/usr/local/bin/perl
# 
# $Header: emagent/sysman/admin/scripts/crs_status.pl /st_emagent_10.2.0.4.3db11.2.0.2/1 2010/05/18 15:01:32 ajdsouza Exp $
#
# crs_status.pl
# 
# Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 
#
#    NAME
#      crs_status.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    08/25/09 - added EM_CRS_TEST_CRS_HOME env
#    ajdsouza    11/11/08 - add begin clock for view testing
#    ajdsouza    02/02/07 - fix bug 5732015,5732112,
#                            5527466,5494189
#    ysun        07/11/05 - Creation
# 
use strict;
use warnings;

use File::Spec::Functions;
use File::Basename;
use File::Path;
use Data::Dumper;
use locale;
eval "use has::Common; 1" or print "em_warning=Module has::Common:: is not found, Failed to get cluster node status \n" and exit 0;
require "emd_common.pl";
require "semd_common.pl";


my $oldOH;

BEGIN
{

 use POSIX qw(locale_h);

 my $clocale='C';

 for ( qw ( LC_ALL LC_COLLATE LC_CTYPE LC_TIME LC_NUMERIC LC_MESSAGES LC_MONETARY LANG LANGUAGE ) )
 {
   $ENV{$_}=$clocale;
 }

 # if SRVM_TRACE is set to TRUE them do not disable SRVM_TRACE for cluvfy
 if ( exists $ENV{SRVM_TRACE} and $ENV{SRVM_TRACE} and $ENV{SRVM_TRACE} =~ /TRUE/i )
 {
   $has::Commmon::has_metric_config{ENV_VARIABLE_SRVM_TRACE}='TRUE';
   # added the extra line to get around the perl error
   #  used only once: possible typo
   $has::Commmon::has_metric_config{ENV_VARIABLE_SRVM_TRACE}='TRUE';
 }

 # trace is disabled as srvctl writes trace to stdout, enabled slectively for cluvfy
 delete $ENV{SRVM_TRACE} if $ENV{SRVM_TRACE};

 setlocale(LC_ALL,$clocale) or warn "WARN:Failed to set locale to $clocale \n ";

 # save ORACLE_HOME and restore it back in END
 $oldOH = $ENV{ORACLE_HOME} if $ENV{ORACLE_HOME};

 # temporarly setting environment only in dev view env
 # this code is not avtive in production
 # !! DO NOT CHANGE THE CLUSTER NAME HERE WHEN YOU
 # CHECK IN AS THIS WILL BREAK REGRESSION
 #
 # IF YOU ARE CREATING A HAS VIEW CREATE IT 
 # WITH VIEW NAME <sa view_name>t
 # e.g. if sa view is sa3114 the has view should be sa3114t
 # the clustername is the has view should be newdb_cluster
 if ( $ENV{ADE_VIEW_ROOT} and not $ENV{HAS_USE_SHIPHOME} )
 {

  my $advrt;
  if ( $ENV{EM_CRS_TEST_CRS_HOME}  )
  {
    $advrt =  $ENV{EM_CRS_TEST_CRS_HOME};
  }
  else
  {
   $advrt =  $ENV{ADE_VIEW_ROOT};
   $advrt  =~ s/_ag$//;
   $advrt  = $advrt."t";
   $ENV{ORA_CRS_HOME}="$advrt/oracle";
  }

  if ( $ENV{EM_CRS_TEST_CLUSTER_NAME}  )
  {
    $ENV{CSS_CLUSTERNAME}=$ENV{EM_CRS_TEST_CLUSTER_NAME};
  }
  else
  {
    $ENV{CSS_CLUSTERNAME}='newdb_cluster';
  }
  $ENV{CRS_HOME}="$ENV{ORA_CRS_HOME}";
  $ENV{CV_HOME}="$ENV{CRS_HOME}";
  $ENV{OCR_ROOT}="$ENV{CRS_HOME}/has_work/data.ocr";
  $ENV{OCR_LOC}="$ENV{CRS_HOME}/has_work/ocr.loc";
  $ENV{OCR_DEVELOPER_ENV}='TRUE';
  $ENV{HAS_DEVELOPMENT_ENVIRONMENT}='TRUE';
  $ENV{CV_JDKHOME}="$ENV{CRS_HOME}/jdk15";
  $ENV{ORA_ENVIRON_OPTS}='true';

  my $libs = "$ENV{CRS_HOME}/lib:$ENV{CRS_HOME}/has/lib:$ENV{CRS_HOME}/opsm/lib";

  $ENV{LD_LIBRARY_PATH}="$libs:$ENV{LD_LIBRARY_PATH}" if $ENV{LD_LIBRARY_PATH};
  $ENV{LD_LIBRARY_PATH}="$libs" unless $ENV{LD_LIBRARY_PATH};

  $ENV{PATH}="$ENV{CRS_HOME}/bin:$ENV{CRS_HOME}/has/bin:$ENV{PATH}" if $ENV{PATH};
  $ENV{PATH}="$ENV{CRS_HOME}/bin:$ENV{CRS_HOME}/has/bin" unless $ENV{PATH};

 }

}

my ($rootDir) = @ARGV; # CRSHome
$rootDir =~ s/^\s+|\s+$//g if $rootDir;
$rootDir = $ENV{CRS_HOME} unless $rootDir;
$rootDir = $ENV{ORACLE_HOME}  unless $rootDir;
$rootDir = $ENV{EMDROOT} unless $rootDir;

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

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

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

# default settings
my $crsIsUp = 1;
my $o;

for ( ( 1 ) )
{

  unless ( $rootDir and $rootDir !~ /#CRS_HOME#/ )
  {
    $crsIsUp = 0;
    $o = "Not a cluster host";
    last;
  }

  my %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
  if ( $has::Commmon::has_metric_config{ENV_VARIABLE_SRVM_TRACE} )
  {
    $ENV{SRVM_TRACE}='TRUE';
  }

  $o = has::Common::runsystemcommand(
                "cluvfy comp crs -display_status 2>&1","",\%command_args);

  delete $ENV{SRVM_TRACE} if $ENV{SRVM_TRACE};

  $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 => [()]);
    if ( $has::Commmon::has_metric_config{ENV_VARIABLE_SRVM_TRACE} )
    {
      $ENV{SRVM_TRACE}='TRUE';
    }
    $o = has::Common::runsystemcommand("cluvfy comp crs 2>&1","",\%command_args);

    delete $ENV{SRVM_TRACE} if $ENV{SRVM_TRACE};

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

  chomp($o) if $o;

  has::Common::exit_fail("crs_status.pl:Failed to get any results from cluvfy comp crs") 
   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;
      last;
    }

    #
    # 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::';

    my $failed_on_all_nodes =
     'unsuccessful\s+on\s+all\s+the\s+nodes|CRS\s+integrity\s+check\s+failed|Checks\s+did\s+not\s+pass\s+for\s+the\s+following\s+node\(s\)\s*:|Check\s+failed\s+on\s+nodes\s*:';

    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 $row = $rows[0] if @rows and $rows[0];

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

       #success
       if ( $row and $row =~ /NODE_STATUS::.+:SUCC$|OVERALL_STATUS::SUCC/ )
       {
        $crsIsUp=1;
        last;
       }

       # verification failed
       if ( $row and $row =~ /NODE_STATUS::.+:VFAIL|OVERALL_STATUS::VFAIL/ )
       {
         $crsIsUp=0;
         last;
       }

       # execution failure if not SUCC or VFAIL
       $crsIsUp=-1;
       has::Common::print_warn_message
        ("crs_status.pl:Failed to get CRS Status, CRS verification failed for node from $o\n");
       last;

    }
    elsif ($o =~ /$error_executing_cluvfy/i )
    {
      $crsIsUp =-1;
      has::Common::print_warn_message
        ("crs_status.pl:Failed to get CRS Status, CRS verification failed for node from $o\n");
      last;
    }
    elsif ($o =~ /$failed_on_all_nodes/i )
    {
      $crsIsUp = 0;
      last;
    }
    else
    {
      $crsIsUp = -1;
      has::Common::print_warn_message
       ("crs_status.pl:Failed to get CRS Status, CRS verification failed for node from $o\n");
      last;
    }

  }

}

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

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

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


exit 0;

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