#!/usr/local/bin/perl
# 
# $Header: dgObserverStatus.pl 16-aug-2006.07:31:17 sjconnol Exp $
#
# dgObserverStatus.pl
# 
# Copyright (c) 2005, 2006, Oracle. All rights reserved.  
#
#    NAME
#      dgObserverStatus.pl - Script to get the status of DG Fast-start failover observer
#
#    DESCRIPTION
#      This script gets the status for the Data Guard Fast-start failover observer.
#	The status could be one of the following
#	1) Fast-start failover disabled (When FSFO is not enabled)
#	2) Normal (When FSFO is enabled and observer is up)
#	3) Error ORA-16820 (When FSFO is enabled and observer is down)
#
#    NOTES
#      Applicable only for 10gR2 upwards
#
#    MODIFIED   (MM/DD/YY)
#    sjconnol    08/16/06 - 11g changes
#    ngade       04/06/06 - display current observer 
#    kramarat    07/24/05 - kramarat_dgob
#    kramarat    07/21/05 - Creation
# 

use strict;
use Sys::Hostname;
require "$ENV{EMDROOT}/sysman/admin/scripts/db/dg/dgutil.pl";


# RaiseError
$SIG{__DIE__} = \&handleError;
# PrintError
$SIG{__WARN__} = \&handleWarning;

# Trace the target name.
EMD_PERL_DEBUG("Database target=$ENV{EM_TARGET_NAME}");

# Supports 10gR2.
my $db_version = $ENV{VersionCategory};
verify_dbversion_102($db_version);

# Connect to the instance.
my %stdinArgs = get_stdinvars();
my $username = $stdinArgs{EM_TARGET_USERNAME};
my $password = $stdinArgs{EM_TARGET_PASSWORD};
my $role = $ENV{EM_TARGET_ROLE};
my $mode = 0;
if($role =~ /SYSDBA/i)
{
  $mode = 2;
}
elsif($role =~ /SYSOPER/i)
{
  $mode = 4;
}

my $address = $ENV{EM_TARGET_ADDRESS};
my $lda = DBI->connect('dbi:Oracle:', "$username@".$address, "$password", {ora_session_mode => $mode, PrintError => 0, RaiseError => 1});

# Register this test once we're connected.
register_metric_call($lda);

# Make a few more checks before continuing.
verifyPrimary($lda);
my $broker = verifyBroker($lda); 

if ($broker)
{
  doEval($lda);
}

$lda->disconnect;

exit 0;

sub verifyFSFO
{
  my ($lda) = @_;
  
  my $sql = "select FS_FAILOVER_STATUS from v\$database";
  my $dbcur = $lda->prepare($sql);
  $dbcur->execute;
  my @row = $dbcur->fetchrow_array();
  my $fsfo_status = $row[0];
  
  if($fsfo_status =~ /DISABLED/i)
  {
     return 0;
  }
  else
  {
     return 1;
  }
}

sub getObserverHost
{
  my ($lda) = @_;

  my $sql = "select FS_FAILOVER_OBSERVER_HOST from v\$database";
  my $dbcur = $lda->prepare($sql);
  $dbcur->execute;
  my @row = $dbcur->fetchrow_array();
  my $fsfo_host = $row[0];
  return $fsfo_host;
}

sub doEval
{
  my ($lda) = @_;
  my $final_result;
  # verify if FSFO is enabled
  if(verifyFSFO($lda))
  {
    $final_result = observerRestartRequired($lda);
  }
  else
  {
    $final_result = "em_result=Fast-start failover disabled\n";
  }
  print $final_result;
}
# Get the status of DG FSFO observer
# Parameters
# lda - The login identifier (Login Data Area).
sub observerRestartRequired
{
  my ($lda) = @_;

  # Retrieve the configuration object content.
  my $indoc = "<DO_CONFIGURE_DRC><GET_DRC/></DO_CONFIGURE_DRC>";
  my $drc_obj = get_dg_document($lda, $indoc);

  # Retrieve the list of sites.
  my (%site_list);
  my ($site_id, $site_obj);
  my $drc_start_pos = -1;
  my $site_start_pos = -1;
  my $result;

  while (($site_id = get_dg_token($drc_obj, "site_id", $drc_start_pos)) ne "")
  {
    EMD_PERL_DEBUG("dgObserverStatus.observerRestartRequired: site_id=$site_id");
    # Retrieve the site object content.
    $indoc = "<DO_CONFIGURE_SITE><GET_SITE site_id=\"$site_id\"/></DO_CONFIGURE_SITE>";
    $site_obj = get_dg_document($lda, $indoc);
    $site_list{$site_id} = $site_obj;
  }

  foreach $site_id (keys(%site_list))
  {
    $site_obj = $site_list{$site_id};
    my($status) = DGgetDatabaseStatus($lda, $site_obj);
    my $dbres_id = get_dg_property($lda, $site_id, "DBRESOURCE_ID");

    if($status =~ /16820/)
    {
      EMD_PERL_DEBUG("dgObserverStatus.observerRestartRequired: found unobserved status; observer restart required");
      $result = "em_result=Error $status\n";
      return $result;
    }

    ## ORA-16824/16825 multiple FSFO errors; must get full status report
    if($status =~ /16824|16825/){
      EMD_PERL_DEBUG("dgObserverStatus.observerRestartRequired: found 16824/16825 status; getting StatusReport");
      my $dbres_id = get_dg_property($lda, $site_id, "DBRESOURCE_ID");
      my $statusrpt = get_dg_property($lda, $dbres_id, "StatusReport");
      my @dbres_status_tokens = split(/[><]+/, $statusrpt);
      my $dbres_status_token;
      foreach $dbres_status_token (@dbres_status_tokens)
      {
        if ($dbres_status_token =~ /ORA-16820/)
        {
          EMD_PERL_DEBUG("dgObserverStatus.observerRestartRequired: found unobserved status; observer restart required");
          $result = "em_result=Error $dbres_status_token\n";
          return $result;
        }
      }
    }
    EMD_PERL_DEBUG("dgObserverStatus.observerRestartRequired: status for site $site_id: $status");
  }

  EMD_PERL_DEBUG("dgObserverStatus.observerRestartRequired: no observer down status");
  my $fsfo_host = getObserverHost($lda);
  EMD_PERL_DEBUG("dgObserverStatus.observerRestartRequired: fsfo_host: ". $fsfo_host);
  $result = "em_result= Observer is running normally on $fsfo_host.\n";
  return $result;
}

sub DGgetDatabaseStatus
{
  my ($lda, $site_obj) = @_;
  my $site_start_pos = -1;

  # Parse out the site id.
  my $site_id = get_dg_token($site_obj, "site_id", $site_start_pos);
  EMD_PERL_DEBUG("dgObserverStatus.DGgetDatabaseStatus: site_id=$site_id");

  # Retrieve the site DBRESOURCE_ID property.
  my $dbres_id = get_dg_property($lda, $site_id, "DBRESOURCE_ID");
  EMD_PERL_DEBUG("dgObserverStatus.DGgetDatabaseStatus: dbres_id=$dbres_id");

  # Retrieve the db resource ENABLED property.
  my $dbres_enabled = get_dg_property($lda, $dbres_id, "ENABLED");
  EMD_PERL_DEBUG("dgObserverStatus.DGgetDatabaseStatus: dbres_enabled=$dbres_enabled");
  # The db resource must be enabled.
  if (!($dbres_enabled =~ /YES/i))
  {
    EMD_PERL_DEBUG("dgObserverStatus.DGgetDatabaseStatus: The db resource must be enabled.");
    return "";
  }
  # Retrieve the db resource INTENDED_STATE property.
  my $dbres_state = get_dg_property($lda, $dbres_id, "INTENDED_STATE");
  EMD_PERL_DEBUG("dgObserverStatus.DGgetDatabaseStatus: dbres_state=$dbres_state");
  # The db resource intended state must not be offline.
  if (($dbres_state =~ /OFFLINE/i))
  {
    EMD_PERL_DEBUG("dgObserverStatus.DGgetDatabaseStatus: The db resource must not be offline.");
    return "";
  }

  # Retrieve the db resource status.
  my $dbres_status = "";
  my $dbres_status_text = "";
  get_dg_dbres_status($lda, $dbres_id, $dbres_status, $dbres_status_text);

  EMD_PERL_DEBUG("dgObserverStatus.DGgetDatabaseStatus: Site $dbres_id : returning $dbres_status");
  return($dbres_status_text);
}

