#!/usr/local/bin/perl
# 
# $Header: has/install/crsconfig/oraacfs.pm /st_has_11.2.0/13 2013/06/10 08:16:40 loguzman Exp $
#
# oraacfs.pm
# 
# Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
#
#    NAME
#      oraacfs.pm - Library module for ACFS root install functions.
#
#    DESCRIPTION
#      oraacfs.pm - Contains initial installation and deinstallation
#                   routines for ACFS.
#
#    NOTES
#
#    MODIFIED   (MM/DD/YY)
#    loguzman    06/06/13 - When checking if registry resource is online
#                           do not trace "already running" messages.
#    loguzman    05/22/13 - If we try to start ora.registry.acfs and it is
#                           already started do not stop starting it on all
#                           the other nodes. 
#    loguzman    05/07/13 - Check ora.registry.acfs resource is online on 
#                           each given node.
#    agraves     03/28/13 - Update check for ASM_STORAGE_USED to better handle
#                           an upgrade case, where the registry isn't already
#                           started, and ensure it gets started.
#    loguzman    01/24/13 - Add diskgroup(s) as  STOP_DEPENDENCIES in 
#                           registry.acfs. 
#    gsanders    11/09/11 - Backport gsanders_hasmain13263435 from main
#    agraves     10/21/11 - Fix bug 12812838 and 12636331, the registry being
#                           in the wrong state after an upgrade.
#    agraves     07/25/11 - Change FAILED return code when acfsroot to SUCCESS
#                           for NOT_SUPPORTED.
#    xyuan       07/11/11 - Fix bug 12701521
#    anjiwaji    06/24/11 - Backport anjiwaji_bug-12644077_main from main
#    josmith     05/18/11 - Don't modify replication types if no replication
#                           resources were found
#    josmith     04/20/11 - Add ACFS replication upgrade functions
#    agraves     03/07/11 - Initial Creation
# 

=head1 NAME

  oraacfs.pm  Oracle clusterware ACFS component configuration/startup package

=head1 DESCRIPTION

   This package contains functions required for initial configuration
   and startup of the ACFS component of Oracle clusterware

=cut

package oraacfs;
use strict;
use English;
use File::Temp qw/ tempfile /;
use File::Spec::Functions;
use File::Find ();

use crsconfig_lib;

use strict;

use Exporter;
use vars qw(@ISA @EXPORT @EXPORT_OK);
@ISA = qw(Exporter);

my @exp_func  = qw(add_acfs_registry start_acfs_registry 
                   upgrade_acfs_registry installUSMDriver
                   isACFSSupported acfsrepl_updateResources 
                   acfsrepl_lastNode);

# This should export ACFS SUPPORTED constants.
#my @exp_const = qw(CSS_EXCL_SUCCESS CSS_EXCL_FAIL
#                   CSS_EXCL_FAIL_CLUSTER_ACTIVE);

push @EXPORT, @exp_func; #, @exp_const;


# OSD API definitions
# TODO: We'll need this for acfs if there are OSD sections.
#use s_oraacfs;



=head2 add_acfs_registry

   Creates or updates ACFS Registry resource

=head3 Parameters

   None

=head3 Returns

  TRUE  - ACFS Registry configuration was     created or updated
  FALSE - ACFS Registry configuration was not created or updated

=head3 Notes


=cut

sub add_acfs_registry
{
   if (! isACFSSupported()) {
      return TRUE;
   }

   my $ORA_CRS_HOME = $CFG->ORA_CRS_HOME;
   my $owner        = $CFG->SUPERUSER;
   my $asmgrp       = $CFG->params('ORA_ASM_GROUP');
   my $crsctl       = catfile ($ORA_CRS_HOME, "bin", "crsctl");
   my $rc           = TRUE;

   if ($CFG->platform_family eq "windows") {
      if (is_dev_env()) {
         $owner = $CFG->params('ORACLE_OWNER');
      }
      else {
         $owner = '';
      }
   }

   # check if acfs registry type exists
   my @cmd    = ($crsctl, 'status', 'type', 'ora.registry.acfs.type');
   my @out    = system_cmd_capture(@cmd);
   my $checkrc     = shift @out;

   # if type doesn't exist, add it.
   # CRS-2560 = Resource type  xxx  does not exist
   if ((defined($out[0])) && ($out[0] =~ m/CRS-2560/)) {
       # add type ora.registry.acfs.type
       my @cmd = ($crsctl, 'add', 'type', 'ora.registry.acfs.type',
                  '-basetype', 'ora.local_resource.type',
                  '-file', "$ORA_CRS_HOME/crs/template/registry.acfs.type");
       trace ("Invoking: @cmd");
       my $status = system_cmd(@cmd);

       if (0 == $status) {
          trace ("add ora.registry.acfs.type ... success");
       }
       else {
          error ("add ora.registry.acfs.type ... failed");
          return FALSE;
       }
   }
   else
   {
       trace ("ora.registry.acfs.type already exists.... skipping type add");
   }


   # check if acfs registry exists
   my @cmd    = ($crsctl, 'status', 'resource', 'ora.registry.acfs');
   my @out    = system_cmd_capture(@cmd);
   my $checkrc     = shift @out;

   # if registry doesn't exist, add it.
   # CRS-2613 =  Could not find resource
   if (defined($out[0]) && ($out[0] =~ m/CRS-2613/ )) {
       # add resource ora.registry.acfs
       my @cmd = ($crsctl, "add", "resource", "ora.registry.acfs", "-attr",
                  "\"ACL='owner:$owner:rwx,pgrp:$asmgrp:rwx,other::r--'\"",
                  "-type", "ora.registry.acfs.type", "-f");
       if (! is_dev_env() && ($CFG->platform_family eq "windows")) {
          push @cmd, '-buildowner';
       }

       my $status = system_cmd(@cmd);
       if (0 == $status) {
          trace ("add resource ora.registry.acfs ... success");
       }
       else {
          error ("add resource ora.registry.acfs ... failed");
          return FALSE;
       }
  }
  else
  {
      trace ("ora.registry.acfs already exists ... skipping");
  }
  return $rc;
}


=head2 start_acfs_registry

   Starts the ACFS registry on specified nodes.

=head3 Parameters

   arg[0] - Nodes to start on.

=head3 Returns

  TRUE  - ACFS Registry is ONLINE
  FALSE - ACFS Registry is OFFLINE

=head3 Notes


=cut
sub start_acfs_registry
{
   if (! isACFSSupported())
   {
      return TRUE;
   }

   # Only start the ACFS registry if ASM is used as storage.
   # ACFS requires ASM volumes, which requires ASM.
   # This used to check for an upgrade (! UPGRADE), which 
   # would mean that the function would return true only if:
   #  it wasn't an upgrade (! UPGRADE) 
   #  and asm storage wasn't used (! ASM_STORAGE).
   # This left the following cases where the registry was started:
   #   * any install where ASM was used
   #   * any upgrade, even ones where ASM Storage wasn't used.
   # In order to fix this, we'll start the registry any time
   #  asm storage is used - this will handle all installs
   #  and all upgrades.
   # Note that, due to the hard start dependency on ASM, this will
   #  bring up the ASM resource.
   # When ASM storage is not used, the registry will not be started.
   # However, if the user starts ora.asm - it will pullup the registry,
   # because of the specification on the registry start pullup(ora.asm).
   # This states that when ora.asm is started, to start the registry as
   # well.
   #
   # The most significant change of behavior from previous check is
   # that not all upgrades will start the registry - only ones where
   # asm is used as the storage.  We'll rely on the dependency chain
   # to start the registry for other installs.
   if (! (($CFG->ASM_STORAGE_USED) || ($CFG->UPGRADE && isOCRonASM())))
   {
      return TRUE;
   }

   my $nodes_to_start_ref = shift;
   trace ("starting acfs_registry...");
   trace ("nodes_to_start=@$nodes_to_start_ref");

   my $crsctl = catfile ($CFG->ORA_CRS_HOME, "bin", "crsctl");
   my $rc     = TRUE;

   # start resource ora.acfs
   foreach my $node (@$nodes_to_start_ref) {
      my @cmd = ($crsctl, 'start', 'res', 'ora.registry.acfs', '-n', $node);
      my @out = system_cmd_capture_noprint(@cmd); 
      my $status = shift @out;

      if (0 == $status) 
      {
         trace ("@cmd ... success");
      }
      else 
      {
         if ($out[0] =~ m/already running/) 
         {
           #if resource is already started do not print an error.
           trace ("@cmd ... success");
           $rc = TRUE; 
         }
         else
         { 
           #print output command
           trace ("@cmd ... failed");
           if (scalar(@out) > 0) 
           {
             trace(join("\n>  ", ("Command output:",  @out)),
              "\n>End Command output");
           }
           $rc = FALSE;
         }
      }
   }

   return $rc;
}

=head2 upgrade_acfs_registry


   Upgrades the ACFS Registry

=head3 Parameters

   None

=head3 Returns

  TRUE  - ACFS Registry successfully upgraded. (Note that one or more 
          attribute updates may fail, and success will still be 
          returned.)
  FALSE - ACFS Registry not successfully upgraded.

=head3 Notes


=cut
sub upgrade_acfs_registry
{
   # check if acfs resource exists
   my $owner        = $CFG->SUPERUSER;
   my $asmgrp       = $CFG->params('ORA_ASM_GROUP');
   my $crsctl = catfile ($CFG->ORA_CRS_HOME, "bin", "crsctl");
   my @cmd    = ($crsctl, 'status', 'resource', 'ora.registry.acfs');
   my @out    = system_cmd_capture(@cmd);
   my $rc     = shift @out;
   my @nodes = split (/,/, $CFG->params('NODE_NAME_LIST'));

   # if registry doesn't exist, add it.
   # CRS-2613 =  Could not find resource
   if (defined($out[0]) && ($out[0] !~ m/CRS-2613/ )) {
      add_acfs_registry();
      # Set attributes to 11.2.0.3 values.
      my @cmd = ($crsctl, 'modify', 'resource', 'ora.registry.acfs','-attr',
                 "\"ACL='owner:$owner:rwx,pgrp:$asmgrp:rwx,other::r--'\"");
      
      if (! is_dev_env() && ($CFG->platform_family eq "windows")) {
          push @cmd, '-buildowner';
      }
      my @out    = system_cmd_capture(@cmd);
      my $rc     = shift @out;
      if  ($rc != 0)
      {
          trace ("Setting registry.acfs ACL failed");
      }
      my @cmd = ($crsctl, 'modify', 'resource', 'ora.registry.acfs',
                 '-attr', '"SCRIPT_TIMEOUT=120"'); 
      my @out    = system_cmd_capture(@cmd);
      my $rc     = shift @out;
      if  ($rc != 0)
      {
          trace ("Setting registry.acfs SCRIPT_TIMEOUT failed");
      }
      @cmd = ($crsctl, 'modify', 'resource', 'ora.registry.acfs',
                 '-attr', '"START_TIMEOUT=180"'); 
      @out    = system_cmd_capture(@cmd);
      $rc     = shift @out;
      if  ($rc != 0)
      {
          trace ("Setting registry.acfs START_TIMEOUT failed");
      }
      @cmd = ($crsctl, 'modify', 'resource', 'ora.registry.acfs',
                 '-attr', '"STOP_TIMEOUT=900"'); 
      @out    = system_cmd_capture(@cmd);
      $rc     = shift @out;
      if  ($rc != 0)
      {
          trace ("Setting registry.acfs STOP_TIMEOUT failed");
      }
      @cmd = ($crsctl, 'modify', 'resource', 'ora.registry.acfs',
                 '-attr', '"CHECK_TIMEOUT=600"'); 
      @out    = system_cmd_capture(@cmd);
      $rc     = shift @out;
      if  ($rc != 0)
      {
          trace ("Setting registry.acfs CHECK_TIMEOUT failed");
      }
      #Add diskgroup stop dependency
      my $acfsutil;
      my @tokens;
      my @diskString;
      if ($CFG->platform_family eq 'windows') {
         $acfsutil = catfile ($CFG->ORA_CRS_HOME, 'bin', 'acfsutil');
      }
      else 
      {
         $acfsutil = "/sbin/acfsutil";
      }
      my $strcmd = "$acfsutil registry -l";
      if ($CFG->platform_family eq 'windows') 
      {
         $strcmd =~ s/\ -/\ \//g ;
      }
      open (OUT,"$strcmd | ") or trace("Failed: $strcmd");
      my %unique = ();
      #Get the diskgroup token
      foreach my $item ( <OUT> )
      {
          @tokens = split( " : ", $item );
          $tokens[9] =~ s/\s//g;
          $unique{$tokens[9]} ++;
      }
      if  (@tokens)
      {
          @diskString = keys %unique;
          chomp(@diskString);

          #Build the stop dependencies string
          my $stopDep = "hard(intermediate:ora.asm,";
          foreach my $disks (@diskString)
          {  
             $stopDep .= "shutdown:";
             $stopDep .= "ora.".$disks.".dg,";
          }
          chop($stopDep);
          $stopDep .= ")";
          $stopDep = "\"STOP_DEPENDENCIES='$stopDep'\"";
          @cmd = ($crsctl, 'modify', 'resource', 'ora.registry.acfs',
                     '-attr', $stopDep );

          #Check if we can modify stop_dependencies attribute
          @out = system_cmd_capture(@cmd);
          $rc  = shift @out;
          if  ($rc != 0)
          {
             trace ("Setting registry.acfs STOP_DEPENDENCIES failed\n");
          }
      }
   }
   else
   {
      trace ("Previous install does not have ora.registry.acfs, adding it....");
      if (isACFSSupported())
      {
        add_acfs_registry();
      }
   }

   # Only starts the registry if ASM storage is used, so safe to
   # call.
   start_acfs_registry(\@nodes);
}

=head2 isACFSSupported

   Determines if this platform is an ACFS supported platform
   by calling 'acfsdriverstate supported'.

=head3 Parameters

   None

=head3 Returns

  TRUE  - ACFS Supported
  FALSE - ACFS Not Supported

=head3 Notes


=cut
sub isACFSSupported
{
   my $ACFS_supported = FALSE;
   my $acfsdriverstate;

   if ($CFG->platform_family eq 'windows') {
      $acfsdriverstate = catfile ($CFG->ORA_CRS_HOME, 'bin', 'acfsdriverstate.bat');
   }
   else {
      $acfsdriverstate = catfile ($CFG->ORA_CRS_HOME, 'bin', 'acfsdriverstate');
   }

   # check if acfs is supported
   if (! (-e $acfsdriverstate)) {
      trace ("$acfsdriverstate not found");
      return FALSE;
   }

   my @cmd = ($acfsdriverstate, "supported");
   my @out = system_cmd_capture(@cmd);
   my $rc  = shift @out;

   if ($rc == 0) {
      $ACFS_supported = TRUE;
      trace ("acfs is supported");
   }
   else {
      $ACFS_supported = FALSE;
      trace ("acfs is not supported");
   }

  return $ACFS_supported;
}

=head2 installUSMDriver

   Installs ACFS, ADVM, OKS - kernel and user components via acfsroot.

=head3 Parameters

   None

=head3 Returns

  TRUE  - Configuration successful
  FALSE - Configuration failed

=head3 Notes


=cut
sub installUSMDriver
{
   my $acfsroot;
   my $ret = SUCCESS;


   # if we are running in development mode, then limit support to only when
   # the appropriate env variables are set

   if (is_dev_env())
   {
      my $acfsInstall = uc($ENV{'USM_ENABLE_ACFS_INSTALL'});

      # if this ENV is not set then we give up early
      if ( $acfsInstall ne "TRUE" )
      {
         trace("ADVM/ACFS disabled because of ENV in test mode");
         return $ret;
      }
   }

   if ($CFG->platform_family eq 'windows') {
      $acfsroot = catfile ($CFG->ORA_CRS_HOME, 'bin', 'acfsroot.bat');
   }
   else {
      $acfsroot = catfile ($CFG->ORA_CRS_HOME, 'bin', 'acfsroot');
   }

   if (-e $acfsroot) {
      my $cmd = "$acfsroot install";

      trace("Executing '$cmd'");
      my @output = system_cmd_capture($cmd);
      my $rc = shift @output;

      if ($rc == 0) {
         trace ("$cmd ... success");
      }
      elsif ($rc != 2) {
         if (scalar(grep(/9427/, @output)) > 0)
         {
           $ret = WARNING;
           trace("$cmd ... success, but need a system reboot");
         }
         else
         {
           $ret = FAILED;
           trace ("$cmd ... failed");
         }
      }
   }
   else {
     trace("$acfsroot not found");
     if (isACFSSupported())
     {
       # if acfsroot not found and usm supported, we have a problem
       # some required files are not here.
       trace("ACFS is supported on this platform, but install files are missing.");
       $ret = FAILED;
     }
     else
     {  
       # If acfsroot not found and acfs not supported,
       # then assume everything is okay.
       trace("ACFS is not supported on this platform.");
       $ret = SUCCESS;
     }
   }

  trace("USM driver install status is $ret");
  return $ret;
}

=head2 acfsrepl_updateResources

   Updates the replication resources to run at the upgraded version.
   Currently this upgrades from 11.2.0.2 on Linux. For this we do the
   following:
   - Stop all the replication resources.
   - Add the attributes PRIMARY_DEVICE and MOUNTPATH to the resources.

=head3 Parameters

   None

=head3 Returns

  None 

=head3 Notes
  
  Runs only on Linux

=cut
sub acfsrepl_updateResources
{
   my $crsctlbin = catfile ($CFG->ORA_CRS_HOME, "bin", "crsctl");
   my @repltypes = ('ora.acfsrepltransport.type', 'ora.acfsreplapply.type', 
                    'ora.acfsreplmain.type', 'ora.acfsreplinit.type');
   my @replres;
   my %repldevhash;
   my $type;
   my $cmd;
   my $status;

   if ($^O !~ /linux/i) 
   {
      # Replication is only supported starting with Linux 11.2.0.2
      return;
   }

   my @oldcrs_ver = @{$CFG->oldconfig('ORA_CRS_VERSION')};
   if (!($oldcrs_ver[0] eq '11' && $oldcrs_ver[1] eq '2' && 
       $oldcrs_ver[2] eq '0'  && $oldcrs_ver[3] eq '2') ) 
   {
     # We aren't running on 11.2.0.2
     return;
   }

   # Find all of the replication resources on this node and put them in an array.
   foreach $type (@repltypes)
   {
     # Add the resource to the list
     acfsrepl_findRes($type, \@replres, \%repldevhash); 
   }

   if(@replres == 0)
   {
     # Don't do anything if we don't have any resources
     return;
   }

   foreach $type (@repltypes)
   {
      # Add the PRIMARY_DEVICE attribute to the resource type
      $cmd = "$crsctlbin modify type $type -attr \"ATTRIBUTE=PRIMARY_DEVICE\",\"TYPE=string\",\"DEFAULT_VALUE=\",\"FLAGS=CONFIG\"";
      trace("Invoking \"$cmd\"");
      $status = system_cmd ("$cmd");
   }

   # Stop the resources
   trace("Stopping replication resources");
   foreach(0..$#replres)
   {
      trace("Stopping $replres[$_]");
      $cmd = "$crsctlbin stop resource $replres[$_]";
      trace("Invoking \"$cmd\"");
      $status = system_cmd ("$cmd");
   }

   # Update the resources
   foreach(0..$#replres)
   {
      my $res = $replres[$_];
      my $dev = $repldevhash{$res};
      
      trace("Updating resource $res");
      if($dev ne "")
      {
         # Add the PRIMARY_DEVICE attribute to the resource
         $cmd = "$crsctlbin modify resource $res -attr \"PRIMARY_DEVICE=$dev\"";
         trace ("Invoking \"$cmd\"");
         $status = system_cmd ("$cmd");
      }
   }
}

=head2 acfsrepl_findRes

   Finds all the replication resources of a given type.
   Adds the resources to an array
   Adds the resources primary device to a hash list.

=head3 Parameters

   type     - Resource type to search for.
   arrayref - Reference to array that holds the resource names found.
   hashref  - Reference to hash table that hold the primary devices found.

=head3 Returns

  None 

=head3 Notes

 - Only runs on Linux.
 
=cut
sub acfsrepl_findRes
{
  my $type     = shift;
  my $arrayref = shift;
  my $hashref  = shift;

  my $crsctlbin = catfile ($CFG->ORA_CRS_HOME, "bin", "crsctl");
  my $cmd = "$crsctlbin stat res -f -w \'TYPE = $type\'";
  my $devcmd = "/sbin/acfsutil info fs -o primaryvolume"; 

  my $line;
  my $res;

  open (OUT, "$cmd | ") or trace("Failed:$cmd($!)");
  while (<OUT>)
  {
    $line = $_;
    if($line =~ /^NAME=/)
    {
      $res = $';
      chomp($res);
      push(@$arrayref, $res);
    }
    if($line =~ /^MOUNTPOINT=/)
    {
      my $dev = `$devcmd $' 2>&1`;
      chomp($dev);
      ${$hashref}{ $res } = $dev;
    }
  }

}

=head2 acfsrepl_lastNode

   Does the replication upgrade processing on the last node.
   This is run AFTER the active version has been switched.
   Only runs on Linux upgrading from 11.2.0.2

=head3 Parameters

  Does the following:
  - Deletes the 'main' resource
  - Adds the new preapply and monitor types.
  - Gets all the replication resources and starts them

=head3 Returns

  None 

=head3 Notes

 - Only runs on Linux.
 
=cut

sub acfsrepl_lastNode
{
   my $crsctlbin        = catfile ($CFG->ORA_CRS_HOME, "bin", "crsctl");

   my $replpreapplytype = "ora.acfsreplpreapply.type";
   my $replmonitortype  = "ora.acfsreplmonitor.type";

   my @replres;
   my @repltypes = ('ora.acfsrepltransport.type', 'ora.acfsreplapply.type', 
                    'ora.acfsreplmain.type', 'ora.acfsreplinit.type');

   my %repldevhash;
   my $res;
   my $cmd;
   my $status;
   my $type;

   my $rc;
   my @lsnodes;
   my $node;
   
   if ($^O !~ /linux/i) 
   {
      # Replication is only support on Linux 11.2.0.2
      return;
   }

   my @oldcrs_ver = @{$CFG->oldconfig('ORA_CRS_VERSION')};
   if (!($oldcrs_ver[0] eq '11' && $oldcrs_ver[1] eq '2' && 
       $oldcrs_ver[2] eq '0'  && $oldcrs_ver[3] eq '2') ) 
   {
     # We aren't running on 11.2.0.2
     return;
   }

   # Get the node list in the cluster
   ($rc, @lsnodes) = get_olsnodes_info($CFG->OLD_CRS_HOME); 

   # Find all of the replication resources on this node and put them in an array.
   foreach $type (@repltypes)
   {
      # Add the resource to the list
      acfsrepl_findRes($type, \@replres, \%repldevhash);
   }

   if(@replres == 0)
   {
     # Don't do anything if we don't have any resources
     return;
   }

   # Add the new resource types. monitor and preapply.
   my $addmoncmd = "$crsctlbin add type $replmonitortype -basetype cluster_resource -attr \"ATTRIBUTE=MOUNTPOINT\",\"TYPE=string\",\"DEFAULT_VALUE=\",\"ATTRIBUTE=PRIMARY_DEVICE\",\"TYPE=string\", \"DEFAULT_VALUE=\",\"ATTRIBUTE=AGENT_FILENAME\",\"TYPE=string\",\"DEFAULT_VALUE=%CRS_HOME%/bin/oraagent%CRS_EXE_SUFFIX%\",\"ATTRIBUTE=AUTO_START\",\"TYPE=string\",\"DEFAULT_VALUE=never\",\"ATTRIBUTE=PLACEMENT\",\"TYPE=string\",\"DEFAULT_VALUE=restricted\",\"ATTRIBUTE=SERVER_POOLS\",\"TYPE=string\", \"DEFAULT_VALUE=*\",\"ATTRIBUTE=SITE\",\"TYPE=string\", \"DEFAULT_VALUE=\",\"ATTRIBUTE=START_TIMEOUT\",\"TYPE=int\", \"DEFAULT_VALUE=120\"";
   trace ("Invoking \"$addmoncmd\"");
   $status = system_cmd ("$addmoncmd");


   my $addpreappcmd = "$crsctlbin add type $replpreapplytype -basetype cluster_resource -attr \"ATTRIBUTE=MOUNTPOINT\",\"TYPE=string\",\"DEFAULT_VALUE=\",\"ATTRIBUTE=PRIMARY_DEVICE\",\"TYPE=string\", \"DEFAULT_VALUE=\",\"ATTRIBUTE=AGENT_FILENAME\",\"TYPE=string\",\"DEFAULT_VALUE=%CRS_HOME%/bin/oraagent%CRS_EXE_SUFFIX%\",\"ATTRIBUTE=AUTO_START\",\"TYPE=string\",\"DEFAULT_VALUE=never\",\"ATTRIBUTE=PLACEMENT\",\"TYPE=string\",\"DEFAULT_VALUE=restricted\",\"ATTRIBUTE=SERVER_POOLS\",\"TYPE=string\", \"DEFAULT_VALUE=*\",\"ATTRIBUTE=SITE\",\"TYPE=string\", \"DEFAULT_VALUE=\",\"ATTRIBUTE=START_TIMEOUT\",\"TYPE=int\", \"DEFAULT_VALUE=120\"";
   trace ("Invoking \"$addpreappcmd\"");
   $status = system_cmd ("$addpreappcmd");

   for(0..$#replres)
   {
      my $index = $_;
      $res = $replres[$index];

      if($res =~ /ora.repl.main./)
      {
         my $ressuffix = $';
         my $isStandby = 0;
         my $mntpt;
         my $pridev;
         $cmd = "$crsctlbin stat res $res -f";

         trace("Invoking \"$cmd\"");
         open (OUT, "$cmd | ") or die "Cannot run command:$cmd($!)\n";
         while (<OUT>)
         {
           if($_ =~ /^SITE=standby/)
           {
             $isStandby = 1;
           }
           if($_ =~ /^MOUNTPOINT=/)
           {
             $mntpt = $';
             chomp($mntpt);
           }
           if($_ =~ /PRIMARY_DEVICE=/)
           {
             $pridev = $';
             chomp($pridev);
           }
         }

         # Delete the main resource from the array.
         delete $replres[$index];

         # Add the new resources
         if($isStandby)
         {
           acfsrepl_addResource("ora.repl.preapply." . $ressuffix, $replpreapplytype, $mntpt, $pridev, $isStandby);
           push(@replres, "ora.repl.preapply." . $ressuffix);
         }
         acfsrepl_addResource("ora.repl.monitor." . $ressuffix,  $replmonitortype, $mntpt, $pridev, $isStandby);
         push(@replres, "ora.repl.monitor." . $ressuffix);

         # Delete the main resource
         $cmd = "$crsctlbin delete resource $res";
         trace("Invoking \"$cmd\"");
         $status = system_cmd ("$cmd");
    }

  }

  # Start all of the resources in the list
  foreach(0..$#replres)
  {
    my $res = $replres[$_];
    if(defined($res))
    {
      # Start the transport daemon on each node.
      if($res =~ /ora.repl.transport./)
      {
         foreach $node (@lsnodes)
         {
           $cmd = "$crsctlbin start resource $res -n $node";
           trace("Invoking \"$cmd\"");
           $status = system_cmd ("$cmd");
         }
      }
      else
      {
        $cmd = "$crsctlbin start resource $res";
        trace("Invoking \"$cmd\"");
        $status = system_cmd ("$cmd");
      }
    }
  }
 
}

sub acfsrepl_addResource
{
  my $resname   = shift;
  my $type      = shift;
  my $mntpt     = shift;
  my $pridev    = shift;
  my $isStandby = shift;
  my $site;
  my $cmd;
  my $status;
  my $crsctlbin = catfile ($CFG->ORA_CRS_HOME, "bin", "crsctl");

  if($isStandby == 1)
  {
    $site = "standby";
  }
  else
  {
    $site = "primary";
  }

  # Add the resource
  $cmd = "$crsctlbin add resource $resname -type $type -attr \"MOUNTPOINT=$mntpt\",\"PRIMARY_DEVICE=$pridev\",\"SITE=$site\"";
  trace("Invoking \"$cmd\"");
  $status = system_cmd ("$cmd");
}

