# $Header: has/install/crsconfig/crspatch.pm /st_has_11.2.0/9 2013/06/04 19:58:38 gadiga Exp $
#
# crspatch.pm
#
# Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
#

=head1 NAME

  crspatch.pm  Oracle clusterware Patching Module/Package

=head1 DESCRIPTION

   This package contains functions required for  patching
   Oracle clusterware Software

=cut

#    MODIFIED   (MM/DD/YY)
#    gadiga      05/23/13 - patch TFA
#    rtamezd     02/23/12 - XbranchMerge rtamezd_bug-13652088 from
#                           st_has_11.2.0.3.0gipsu
#    rtamezd     02/07/12 - Fix bug 13652088
#    xesquive    08/16/11 - Add two function set_bold and reset_bold, refer to
#                           bug-12765467
#    xyuan       07/11/11 - Fix bug 12701521
#    sidshank    06/09/11 - Adding norestart option to crspatch
#    xyuan       06/01/11 - Add add_localOlr_OlrConfig_OcrConfig to 
#                           Instantiatepatchfiles (fix bug 12587677)
#    shullur     05/11/11 - For handling CHM out-of-place patching.Bug 11852891.
#    ksviswan    05/16/11 - Fix Bugs 12553820,12550187
#    ksviswan    04/13/11 - XbranchMerge ksviswan_opauto_segregate from main
#    ksviswan    03/08/11 - opatch auto segregation
#    ksviswan    09/23/10 - Part fix for bug 10119895
#    ksviswan    09/21/10 - Merge fix for bugs 9482228,9750739
#    dpham       06/30/10 - Add arguement to create_dirs() and set_file_perms() 
#                           functions (9850696)
#    ksviswan    08/24/09 - Fix Bug 8797450
#    dpham       07/29/09 - XbranchMerge dpham_bug-8727340 from
#                           st_has_11.2.0.1.0
#    ksviswan    07/24/09 - Install ACFS after patching
#    dpham       07/15/09 - XbranchMerge dpham_bug-8664938 from main
#    dpham       07/09/09 - wait for crs to start
#    ksviswan    04/20/09 - Creation



package crspatch;
use strict;
use English;
use File::Spec::Functions;

use crsconfig_lib;
use oraacfs;
use constant CRSPATCH_SUCCESS             => 1;
use constant CRSPATCH_FAIL                => 0;

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


my @exp_func  = qw(Stopdbhomeres Startdbhomeres  patchcrssetup 
                   patchsihasetup findHomes findHomeType getcrshome isSIHA getcrsversion 
                   isServerready checkClusterstat checkdbhomestat getoracleowner
                   isClusterwareup CRSPatch CRSPatchhome HAPatch ispathShared error trace 
                   system_cmd_capture run_as_user2 unlockCRSHomeforpatch 
                   read_file unlockHAHomeforpatch Instantiatepatchfiles StartCRS StartHA);

my @exp_const = qw(CRSPATCH_SUCCESS CRSPATCH_FAIL);


push @EXPORT, @exp_func, @exp_const;

=head1 EXPORTED FUNCTIONS


=head2 Stopdbhomeres

   Stop all the database home resources that are managed by Grid Infrastructure.

=head3 Parameters

   1. Database home path
   2. Type of Database home. Is it a RAC database home or an Oracle Restart managed database home
   3. Owner of the database home

=head3 Returns

   CRSPATCH_SUCCESS  - Successfully stopped all database home resources
   CRSPATCH_FAIL     - Failed to stop all database home resources

=cut


sub Stopdbhomeres
{
   my $home = $_[0];
   my $sihadb = $_[1];
   my $ohown = $_[2];
   my $srvctlbin    = catfile ($home, "bin", "srvctl");
   my $nodename = $CFG->HOST; 
   my $success = CRSPATCH_SUCCESS;
   my $cmd;
   my @output;
   my $status;

   my $stfile = catfile ($home, "srvm", "admin", "stophome.txt");
   $ENV{ORACLE_HOME} = $home;

   #Bug 10226636
   if (-e $stfile) {
      unlink $stfile;
   }
   
   if ( ! $sihadb) {
      $cmd = "$srvctlbin stop home -o $home -s $stfile -n $nodename";
   } else {
      $cmd = "$srvctlbin stop home -o $home -s $stfile";
   }

   $status = run_as_user2($ohown, \@output, $cmd );

   trace("$cmd output is @output");

   if ($status != 0) {
     error("Failed to stop resources from  database home $home");
     $success = CRSPATCH_FAIL;
   } else {
     trace("Stopped resources from datbase home $home");
  }
  return $success;
}

=head2 Statusdbhomeres

   Reports the Status of all database home resources that are managed by Grid Infrastructure.

=head3 Parameters

   1. Database home path
   2. Type of Database home. Is it a RAC database home or an Oracle Restart managed database home
   3. Node Name for which the status is required

=head3 Returns

   1. exit status of srvctl status home command
   2. output of srvctl status home. 

=cut
sub Statusdbhomeres
{
   my $home = $_[0];
   my $sihadb = $_[1];
   my $nodename = $_[2];
   my $ohown = $_[3];
   my $srvctlbin    = catfile ($home, "bin", "srvctl");
   my $success;
   my $cmd;
   my @output;
   my $status;

   my $stfile = catfile ($home, "srvm", "admin", "stathome.txt");
   $ENV{ORACLE_HOME} = $home;

   #Bug 10226636
   if (-e $stfile) {
      unlink $stfile;
   }

   if ( ! $sihadb) {
      $cmd = "$srvctlbin status home -o $home -s $stfile -n $nodename";
   } else {
      $cmd = "$srvctlbin status home -o $home -s $stfile";
   }

   $status = run_as_user2($ohown, \@output, $cmd );

   trace("$cmd output is @output");
  
   unlink ($stfile);
   return ($status, @output);
}



sub Instantiatepatchfiles
{
   #TODO - Should we just rely on crsconfig_params or
   #should we derive the critical values.
   instantiate_scripts ();

   add_localOlr_OlrConfig_OcrConfig();

   my @crsconfig_dirs = read_file (catfile ($ORA_CRS_HOME, 'crs', 'utl', 
                                            'crsconfig_dirs'));
   create_dirs (\@crsconfig_dirs);

   copy_wrapper_scripts ();

   my @crsconfig_fileperms = read_file (catfile ($ORA_CRS_HOME, 'crs', 'utl', 
                                                  "crsconfig_fileperms"));
   set_file_perms (\@crsconfig_fileperms);

   #set the ownership/permission of olr
   if (isSIHA()) {
     s_set_ownergroup ($CFG->params('ORACLE_OWNER'),
                     $CFG->params('ORA_DBA_GROUP'), $CFG->OLR_LOCATION);
   } else {
     s_set_ownergroup ($CFG->SUPERUSER,
                     $CFG->params('ORA_DBA_GROUP'), $CFG->OLR_LOCATION);
   }
   s_set_perms ("0600", $CFG->OLR_LOCATION);

   #copy init.ohad,ohasd to init/rc dirs
   s_register_service('ohasd');
}

sub StartCRS
{
   my $rc;
   my $CRSCTL = crs_exec_path('crsctl');
   trace("Starting Oracle Clusterware");
   $rc = system ("$CRSCTL start crs"); 

   if (!wait_for_stack_start(36)) { exit 1; }
}

sub StartHA
{
   my $rc;
   my $CRSCTL = crs_exec_path('crsctl');
   trace("Starting Oracle Restart");
   $rc = system ("$CRSCTL start has");

    # Check if the service/daemon has started
    trace ("Checking ohasd");
    my $ohasd_running = check_service ("ohasd", 24);

    if ($ohasd_running) {
      trace ("ohasd started successfully");
    } else {
      error ("Timed out waiting for ohasd to start.");
      exit 1;
    }
}


=head2 Startdbhomeres

   Starts all the database home resources that are managed by Grid Infrastructure.

=head3 Parameters

   1. Database home path
   2. Type of Database home. Is it a RAC database home or an Oracle Restart managed database home
   3. Owner of the database home

=head3 Returns

   CRSPATCH_SUCCESS  - Successfully stopped all database home resources
   CRSPATCH_FAIL     - Failed to stop all database home resources

=cut

sub Startdbhomeres
{
   my $home = $_[0];
   my $sihadb = $_[1];
   my $ohown = $_[2];

   my $srvctlbin    = catfile ($home, "bin", "srvctl");
   my $nodename = $CFG->HOST; 
   my $success = CRSPATCH_SUCCESS;
   my $cmd;
   my @output;
   my $status;

   my $stfile = catfile ($home, "srvm", "admin", "stophome.txt");

   if ( ! $sihadb ) {
      $cmd = "$srvctlbin start home -o $home -s $stfile -n $nodename";
   } else {
       $cmd = "$srvctlbin start home -o $home -s $stfile";
   }

   $ENV{ORACLE_HOME} = $home;
   $status = run_as_user2($ohown, \@output, $cmd );

   trace("$cmd output is @output");

   if ($status != 0) {
     error("Failed to start resources from  database home $home");
     $success = CRSPATCH_FAIL;
   } else {
     trace("Started resources from datbase home $home");
  }

  unlink ($stfile);  
  return $success;
}

=head2 findHomes

   Gets all the database homes that are managed by Grid Infrastructure.

=head3 Parameters

   None.

=head3 Returns

   Returns the list of database homes managed by Grid Infrastructure.

=cut

sub findHomes
{
 
        my @tmps = ();
        my $db = "";
        my $oh = "";
        my @ohs = ();
        my @ocp_ohs = ();
        my @ocp_databases;
        my $ocp_dblist;
        my $ocp_ohlist;
        my @out;
        my $rc;
        my $cmd;
        my $path;
        my %ohdb = ();
        my %dboh = ();

        my $srvctl    = catfile ($ORA_CRS_HOME, "bin", "srvctl");

        trace( "Looking for configured databases on node $HOST" );
        @ocp_databases = `$srvctl config`;
        chomp @ocp_databases;
        $ocp_dblist = join " ", @ocp_databases;
        trace( "Databases configured on node $HOST are: $ocp_dblist" );
        trace( "Determining ORACLE_HOME paths for configured databases" );
        $ocp_ohlist = "";
        @ocp_ohs = ();
        foreach $db ( @ocp_databases )
        {
            #trace( "Looking at database $db" );

            $cmd = "$srvctl config database -d $db";
            @out = system_cmd_capture($cmd);
            $rc = shift @out;

            if ( $rc != 0 )
            {
               trace("try with srvctl config database -v");
               $cmd = "$srvctl config database -v";
               @out = system_cmd_capture($cmd);
               $rc = shift @out;
               if ($rc == 0) {
                  foreach my $str (@out)
                  {
                     my ($dbname, $dbhome, $dbver) = split(" ", $str);
                     trace("db name is $dbname");
                     trace("db home is $dbhome");
                     trace("db ver is $dbver");
                     chomp $dbname;
                     chomp $dbhome;
                     $dboh{$dbname} = trim($dbhome);
                     trace("Oracle home for database $dbname is $dboh{$dbname}");
                  }
               } else {
                   error("Not able to retreive database home information");
                   exit 1;
               }
               last;
           }
           else
           {
              @tmps = grep(/Oracle home:/, @out);
              trace("output is @tmps");
              my ($dummy, $ohpath) = split( /\:/, $tmps[0] );
              $dboh{$db} = trim($ohpath);
              trace("Oracle home for database $db is $dboh{$db}");
           }
        }

        #create hash oracle home to dbs
        foreach $db (keys%dboh)
        {
         if(defined($ohdb{$dboh{$db}})) {
         $ohdb{$dboh{$db}} = "$ohdb{$dboh{$db}}:$db";
         } else {
           $ohdb{$dboh{$db}} = "$db";
         }
        }

        #get unique oracle home list
        @ocp_ohs = keys%ohdb;

        foreach $oh (keys%ohdb)
        {
         trace( "Oracle Home $oh is configured with Database\(s\)\-\> $ohdb{$oh}");
        }

 trace("oracle home list is @ocp_ohs");
 return @ocp_ohs;
}

=head2 findHomeType

   Find the type of the Oracle Home.

=head3 Parameters

   Oracle Home Path

=head3 Returns

   Returns one of the following type.
   HA - Oracle Restart Home
   CRS - Oracle Grid Infrastructure home
   DB  - Oracle database Home.

=cut

sub findHomeType
{
   my $home = $_[0];
   my $crshome;
   my $type;
   my $local_only = s_get_config_key("ocr", "local_only");
   $crshome = getcrshome();

   if (($home eq $crshome) && ($local_only =~ m/true/i)) {
     $type = "HA";
   } elsif (($home eq $crshome) && ($local_only =~ m/false/i)) {
     $type = "CRS";
   } else {
     $type = "DB";
   }

   return $type;
}

=head2 getcrshome

   Gets the Grid Infrastructure Home path.

=head3 Parameters

   None.

=head3 Returns

   Returns the Oracle Grid Infrastructure Home Path

=cut


sub getcrshome
{
  my $crsHome;

  $crsHome = s_get_olr_file ("crs_home");
  
  if (! -e $crsHome) {
     error("Clusterware home location $crsHome does not exist");
     exit 1;
  }
  return $crsHome;
}

=head2 iscrshome

   Check if the home path is a valid crs home

=head3 Parameters

   Oracle Home Path

=head3 Returns

   None

=cut

sub iscrshome
{
  my $home = $_[0];
  
  if ((-f $OLRCONFIG) && ($home ne s_get_olr_file ("crs_home"))) {
       error("Incorrect clusterware home path provided for -och option");
       exit 1;
  }

}

=head2 isSIHA

   Check if an Oracle Restart home is configured

=head3 Parameters

   None

=head3 Returns

   None

=cut

sub isSIHA
{
   my $ret= CRSPATCH_FAIL;
   my $local_only = get_config_key("ocr", "local_only");
   if ($local_only =~ m/true/i) {
      $ret = CRSPATCH_SUCCESS;
   }
   return $ret;
}

sub get_config_key
{
   my $src = $_[0];
   my $key = $_[1];
   $src    =~ tr/a-z/A-Z/;
   my ($val, $cfgfile);

   if ($src eq 'OCR') {
      $cfgfile = $OCRCONFIG;
   }
   elsif ($src eq 'OLR') {
      $cfgfile = $OLRCONFIG;
   }

   open (CFGFL, "<$cfgfile") or return $val;
   while (<CFGFL>) {
      if (/^$key=(\S+)/) {
         $val = $1;
         last;
      }
   }

   close (CFGFL);
   return $val;
}

=head2 getcrsversion

   Gets the Active Version of Oracle Grid Infrastructure or Oracle Restart

=head3 Parameters

   None

=head3 Returns

   Version of the Grid Infrastructure or Oracle Restart

=cut

sub getcrsversion {
  my $crsctlbin = catfile ($ORA_CRS_HOME, 'bin', 'crsctl');
  my @cmd;
  if (isSIHA()) {
     @cmd       = ($crsctlbin, 'query', 'has', 'releaseversion');
  } else {
     @cmd       = ($crsctlbin, 'query', 'crs', 'activeversion');
  }
  my @out       = system_cmd_capture(@cmd);
  my $rc        = shift @out;
  my @versionarr = (0, 0, 0, 0, 0);
  my $verstring = $out[0];

  if ($rc == 0) {
     $verstring  =~ m/\[(\d*)\.(\d*)\.(\d*)\.(\d*)\.(\d*)\].*$/;
     @versionarr = ($1, $2, $3, $4, $5);
     trace("crs version is @versionarr");
  }
  else {
     error ("@cmd ... failed rc=$rc with message:\n @out \n");
  }

  return @versionarr;
}


=head2 isServerready

   Check if the Grid Infrastructure is ready to start the database

=head3 Parameters

   None

=head3 Returns

   TRUE  - If the clusterware is ready
   FALSE - If the clusterware is not ready 

=cut

sub isServerready
{
  my $crsctl    = catfile ($ORA_CRS_HOME, "bin", "crsctl");
  my @output;
  my $rc;
  my $retries = 360;
  my $ready = FALSE;
  my $grep_val = "STATE=ONLINE";
  my @cmdout;

  while ( $retries) {
     @output = system_cmd_capture($crsctl, 'stat', 'resource', '-c' , $HOST);
     $rc     = shift @output;
    
     @cmdout = grep(/$grep_val/, @output);
     if (scalar(@cmdout) > 0) {
       $ready = TRUE;
       last;
     }

     trace ("Waiting for Server assignments");
     sleep (5);
     $retries--;
  }

  if ($ready) {
    trace ("Server assignments completed. Ready to start databases");
  } else {
    error ("Timed out waiting for server assignments");
  }

  return $ready;

}

=head2 checkClusterstat

   Check the status of clusterware stack on the remote nodes

=head3 Parameters

   None

=head3 Returns

   None

=cut

sub checkClusterstat
{
  my $crsctl    = catfile ($ORA_CRS_HOME, "bin", "crsctl");
  my @output;
  my $rc;
  my $grep_val = "4537|4529|4533";
  my @cmdout;
  my $nodelist = $CFG->params('NODE_NAME_LIST');
  my @nodes = split(/,/, $nodelist);
  my $node;
  my $count = 0;

  foreach $node (@nodes) {
     if ($node !~ /\b$HOST\b/i) {
        @output = system_cmd_capture($crsctl, 'check', 'cluster', '-n' , $node);
        $rc     = shift @output;

        @cmdout = grep(/$grep_val/, @output);
        if (scalar(@cmdout) > 0) {
        error("Clusterware stack up on node $node");
        $count++;
        }
     }
  }

  if ($count == 0) {
    trace ("Clusterware stack is not running on remote nodes");
  } else {
    error ("Clusterware stack is running on remote nodes");
    print "Refer to opatch auto help for patching shared homes and follow the steps\n";
    exit 1;
  }

}

=head2 checkdbhomestat

   Check the status of database home resources on the remote nodes

=head3 Parameters

   None

=head3 Returns

   None

=cut

sub checkdbhomestat
{
  my $home = $_[0];
  my $ohown = getoracleowner($home);
  my @cmdout;
  my $nodelist = $CFG->params('NODE_NAME_LIST');
  my @nodes = split(/,/, $nodelist);
  my $node;
  my $count = 0;
  my $rc;
  my $retstat;

  foreach $node (@nodes) {
     if ($node !~ /\b$HOST\b/i) {
        @cmdout = Statusdbhomeres($home, 0, $node,$ohown);
        my $retstat = shift @cmdout;

        trace("ret code for status db home on $node is $retstat");

        if (($retstat == 0) && (scalar(@cmdout) > 0)) {
           error("Database home resources for $home are running  on node $node");
           $count++;
        }
     }
  }

  if ($count == 0) {
    trace ("Database home resources for $home is not running on remote nodes");
  } else {
    error ("Database home resources for $home is running on remote nodes");
    print "Refer to opatch auto help for patching shared homes and follow the steps\n";
    exit 1;
  }

}

=head2 getoracleowner

   gets the  owner of the oracle home

=head3 Parameters

   Oracle Home Path

=head3 Returns

    Owner of the Oracle home.

=cut

sub getoracleowner
{
  my $oh = $_[0];
  my $getoh_ox = "$oh/bin/oracle";
  my ($name, $passwd, $uid, $gid, $quota, $comment, $gcos, $dir, $shell) = getpwuid( $< );
  my $getoh_u;
  if (  -f $getoh_ox )
  {
     my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size, $atime, $mtime, $ctime, $blksize, $blocks) = stat( $getoh_ox );
     ($name, $passwd, $uid, $gid, $quota, $comment, $gcos, $dir, $shell) = getpwuid( $uid );
     $getoh_u = $name;
     trace( "Oracle user for $oh is $getoh_u" );
  }
  else {
     error("unable to get oracle owner for $oh");
     exit 1;
  }
  return $getoh_u;
}

=head2 isClusterwareup

   Check the status of clusterware stack on the local node

=head3 Parameters

   None

=head3 Returns

   TRUE  - If the clusterware is running
   FALSE - If the clusterware is not running

=cut

sub isClusterwareup
{
   my $crs_running;
   if (! isSIHA())
   {
      $crs_running = check_service ("cluster", 2);
   } else {
      $crs_running = check_service ("ohasd", 2);
   }

   return $crs_running;
}

=head2 patchcrssetup

   Initial setup for patching Grid Infrastructure home

=head3 Parameters

   1. Location of  configuration parameter file (crsconfig_params)
   2. Location of platform definition file (s_crsconfig_defs)
   3. Location of Log file
   4. hostname
   5. superuser id

=head3 Returns

   None

=cut

sub patchcrssetup
{

  my ($paramfile, $defsfile, $logfile, $HOST, $SUPERUSER) = @_;
  my $cfg;

  trace("Starting Clusterware Patch Setup");

   $cfg =
      crsconfig_lib->new(paramfile           => $paramfile,
                     osdfile             => $defsfile,
                     crscfg_trace        => TRUE,
                     crscfg_trace_file   => $logfile,
                     HOST                => $HOST,
                     HAS_USER            => $SUPERUSER,
                     );
}

=head2 patchsihasetup

   Initial setup for patching Oracle Restart home

=head3 Parameters

   1. Location of  configuration parameter file (crsconfig_params)
   2. Location of platform definition file (s_crsconfig_defs)
   3. Location of Log file
   4. hostname
   5. superuser id

=head3 Returns

   None

=cut


sub patchsihasetup
{

  my ($paramfile, $defsfile, $logfile, $HOST, $SUPERUSER) = @_;
  my $cfg;
  my $sihainst = isSIHA();

  trace("Starting Oracle Restart Patch Setup");

   $cfg =
      crsconfig_lib->new(paramfile           => $paramfile,
                     osdfile             => $defsfile,
                     crscfg_trace        => TRUE,
                     crscfg_trace_file   => $logfile,
                     HOST                => $HOST,
                     IS_SIHA             => $sihainst,
                     );
}

=head2 ispathShared

   Finds if the given path is shared across cluster nodes

=head3 Parameters

   1. path for which sharedness check is needed.

=head3 Returns

   TRUE : if the path is shared
   FALSE: if the path is not shared. 

=cut

sub ispathShared
{
   my $path = $_[0];
   my @capout = ();
   my $rc;
   my $user = $CFG->params('ORACLE_OWNER');
   my $nodelist = $CFG->params('NODE_NAME_LIST');
   my $status;

   my @nodes = split(/,/, $nodelist);
   trace("The cluster nodes are @nodes");
   if (scalar(@nodes) == 1) {
      trace("Single node cluster");
      $status = FALSE;
      return $status;
   }
   my $CLUVFY = catfile( $ORA_CRS_HOME, 'bin', 'cluvfy');
   my @program = ($CLUVFY, 'comp ssa', '-t software', '-s' , $path , '-n', $nodelist, '-display_status');
   my $status;

   trace("checking if path $path is shared");
   # run as specific user, if requested
   $rc = run_as_user2($user, \@capout, @program);
   trace("return code for shared check is $rc");
   trace("output of sharedness check is @capout");

   if (scalar(grep(/EFAIL/, @capout)) > 0) {
     $status = ERROR;
   } elsif ((scalar(grep(/VFAIL/, @capout))) > 0){
     $status = FALSE;
   } else {
     trace("The path $path is shared ");
     $status = TRUE;
   }
   return $status;
}



sub Getcrsconfig
{

}

sub Getdbconfig
{

}

sub Stopcrshomeres
{

}

sub Stopcrs
{

}

sub Startcrshomeres
{

}


######################################################################
#                       M A I N                                      #
######################################################################

=head2 CRSPatch

   Performs post config steps for in place patching of  Grid Infrastructure home

=head3 Parameters

  A reference to a hash containing the prameter name and its value

=head3 Returns

   None

=cut

sub CRSPatch
{

   my $hash_arg = $_[0];

   my $nostrtflg = 0;

   if(defined($$hash_arg{"norestart"}))
   {
	$nostrtflg=$$hash_arg{"norestart"};
   }
   
   trace ("Patching Oracle Clusterware");
   trace ("norestart flag is set to $nostrtflg");

   #Instantiate the patched files.
   Instantiatepatchfiles ();
  
    # Patch TFA
    setup_tfa ();

   my $SUCC_REBOOT = crspatch_install_usm();

   if (! $nostrtflg) {
   	StartCRS();  
   }

   if (1 == $SUCC_REBOOT)
   {
     set_bold();
     print "A system reboot is recommended before using ACFS\n";
     reset_bold();
   }
}

=head2 CRSPatchhome

   Performs post config steps for out of place patching of  Grid Infrastructure home

=head3 Parameters

   None

=head3 Returns

   None

=cut

sub CRSPatchhome
{
   my $destcrshome = $_[0];
   my $actcrshome  = s_get_olr_file ("crs_home");

   stopClusterware($actcrshome, "crs");


   #update olr
   s_validate_olrconfig($CFG->OLR_LOCATION, $destcrshome);

   # Perform CHM patching
   if (!perform_CHM_upgrade($destcrshome)) {
     trace("Couldn't perform CHM patching");
   }

   CRSPatch ();

}

=head2 HAPatch

   Performs post config steps for in place patching of  Oracle Restart home

=head3 Parameters

    A reference to a hash containing the prameter name and its value 

=head3 Returns

   None

=cut

sub HAPatch
{

   my $hash_arg = $_[0];

   my $nostrtflg = 0;

   if(defined($$hash_arg{"norestart"}))
   {
        $nostrtflg=$$hash_arg{"norestart"};
   }

   trace ("Patching Oracle Restart");
   trace ("norestart flag is set to $nostrtflg");

   #Instantiate the patched files.
   Instantiatepatchfiles ();

   my $SUCC_REBOOT = crspatch_install_usm();   

   if (! $nostrtflg) {
   StartHA();
   }

   if (1 == $SUCC_REBOOT)
   {
     set_bold();
     print "A system reboot is recommended before using ACFS\n";
     reset_bold();
   }
}

=head2 crspatch_install_usm 

   Install USM drivers

=head3 Parameters

   None

=head3 Returns

   1: Need to reboot after installation
   0: No need to reboot after installation

=cut

sub crspatch_install_usm
{
  my $SUCC_REBOOT = 0;

  if (isACFSSupported()) 
  {
    my $ret = installUSMDriver();
    if (FAILED == $ret)
    {
      error ("ACFS driver install actions failed");
    }
    else
    {
      trace ("ACFS drivers installation completed");
      if (WARNING == $ret)
      {
        trace("Set reboot flag to 1");
        $SUCC_REBOOT = 1;
      }
    }
  }

  return $SUCC_REBOOT;
}

1;
