#!../../perl/bin/perl
# 
# $Header: install/utl/clone/bin/clone.pl /st_install_11.2.0/3 2011/03/16 22:37:12 huliliu Exp $
#
# clone.pl
# 
# Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. 
#
#    NAME
#      clone.pl - 
#
#    DESCRIPTION
#     Script that performs the cloning operation on the current home. This script should
#     be called at the target of the cloning operation. 
#
#    NOTES
#      <other useful comments, qualifications, etc.>
#
#    MODIFIED   (MM/DD/YY)
#    huliliu   03/16/11 - XbranchMerge huliliu_bug-11781857 from main
#    huliliu   03/15/11 - add validation on -O'"CLUSTER_NODE={node1,node2}'"
#                         format, -bug 11781857
#    pvallam   12/27/10 - XbranchMerge pvallam_bug-10094341_11203 from
#                         st_install_11.2.0
#    pvallam   12/03/10 - adding support for skiprootpre property
#    scravind  08/20/10 - Doing the changes to prompt for rootpre on
#                         solarisamd64 Vendor cluster for the bug 10045398
#    scravind  08/20/10 - XbranchMerge scravind_bug-10045398 from
#                         st_install_11.2.0
#    scravind  03/29/10 - XbranchMerge scravind_bug-9499881 from
#                         st_install_11.2.0.1.0
#    svaggu    08/02/09 - Fix for Bug 8339964
#    wyou      02/25/09 - use the relative path for shebang instead of using
#                         instantiation
#    xiaofwan  02/18/09 - Fix bug 8259748 by enabling -defaultHomeName
#    wyou      01/13/09 - change the header into instantiation
#    xiaofwan  11/12/07 - Combine clone.pl with db.clone.pl
#    xiaofwan  04/24/07 - Fix bug 6005641 by accepting ORACLE_BASE as a
#                         mandatory parameter
#    poosrini  12/11/06 - Added -nowait to OUI cmd line
#    rlemos    06/10/05 - Fix issue with validation checks 
#    rlemos    05/04/05 - Updates to create the targets.xml.tmp file 
#    rlemos    03/22/05 - rlemos_checkin_cloning_scripts
#    rlemos    03/22/05 - Creation
#

use English qw(-no_match_vars);  

use File::Path;
use File::Spec::Functions;

my $root_directory = File::Spec->rel2abs(File::Basename::dirname ( $PROGRAM_NAME ));

my $ORACLE_HOME = "Not yet set!!";
my $ORACLE_HOME_NAME = "Not yet set!!";
my $ORACLE_BASE = "Not yet set!!";
my $OSDBA_GROUP = "Not yet set!!";
my $OSOPER_GROUP = "Not yet set!!";
my $OSASM_GROUP = "Not yet set!!";

my $SKIP_ROOTPRE_PROPERTY = "FALSE";
my $SKIP_ROOTPRE_PROPERTY_PASSED = "FALSE";

my %ARGS;

# Build the command line
my $OUI_COMMAND = "./runInstaller";

if (onWindows())
{
	$OUI_COMMAND = ".\\setup.exe";
}
my $CLONE_COMMAND_LINE = $OUI_COMMAND . " -clone -waitForCompletion ";

# Update path environment variable
if (!onWindows())
{
	update_path_environment_variable();
}

# parse the command line arguments
parse_arguments(@ARGV);

# validate the arguments passed
validate_arguments();

# rootpre check
rootpre_check();

# build the command line
build_clone_command();

$props_file = File::Spec->catfile($root_directory, updir(), "config", "cs.properties");
%PROPS = load_properties($props_file);
$CLONE_COMMAND_LINE_BUFFER = $PROPS{clone_command_line};
$CLONE_COMMAND_LINE = $CLONE_COMMAND_LINE.' '.$CLONE_COMMAND_LINE_BUFFER;

# Explicitly unsetting the following ENV variables
delete $ENV{'ORACLE_HOME'};
delete $ENV{'ORACLE_HOME_NAME'};
delete $ENV{'ORACLE_BASE'};
delete $ENV{'OSDBA_GROUP'};
delete $ENV{'OSOPER_GROUP'};
delete $ENV{'OSASM_GROUP'};

# Go to the OUI directory
chdir(File::Spec->catfile($ORACLE_HOME, "oui", "bin"));

print("$CLONE_COMMAND_LINE \n");

# Invoke OUI in clone mode
system($CLONE_COMMAND_LINE);

# Exit with the correct exit status
exit $?>>8;

#############################################################################
# NAME   : parse_arguments
# PURPOSE: Checks the command line arguments.
# INPUTS : The command line arguments
# OUTPUTS: NONE
# NOTES  : Updates global variables with command line arguments.
#
#############################################################################
sub parse_arguments
{
	(@ARGV)=@_;
	my %ARGS;
	$no_arguments = scalar ( @ARGV );
	for ( my $i = 0; $i < $no_arguments; $i++ )
	{
		# mandatory if we are connecting to an instance - if not passed use the old instance name
		if ($ARGV[$i] eq "-silent")
		{
			$SILENT_MODE = "true";
		}
		elsif ($ARGV[$i] eq "-debug")
		{
			$DEBUG_MODE = "true";
		}
		elsif ($ARGV[$i] eq "-help")
		{
			print_usage();
			exit;
		}
		# Read in values beginning with -O (pass to OUI clone cmd line) -P (preClone)
		elsif ($ARGV[$i] =~ /-O/)
		{
			$ARGV[$i]=~s/-O//;
			if ($ARGV[$i]=~ /CLUSTER_NODES=/)
			{
				# split the arg by '=' 
				($name, $value) = split(/=/, $ARGV[$i]);
                		# validate the {} at the right side of the args
                		if (($value =~ /^\{/) && ($value =~ /\}"$/))
				{
					$CLONE_COMMAND_LINE = $CLONE_COMMAND_LINE.' '.$ARGV[$i];
				}
				else
				{
                        		# error and exit
                        		print "CLUSTER_NODES must be specified within \{\}!\n";
                        		exit -1;
                		}
       			 }		
			else
			{	
				# for other -O parameters, no validation checking performed
				$CLONE_COMMAND_LINE = $CLONE_COMMAND_LINE.' '.$ARGV[$i];
			}
		}
		elsif ($ARGV[$i] =~ /OSDBA_GROUP=/)
		{
			($name, $value) = split (/=/, $ARGV[$i]);
			$ARGS{$name} = $value;
			$CLONE_COMMAND_LINE = $CLONE_COMMAND_LINE.' "oracle_install_OSDBA='.$value.'"';
		}
		elsif ($ARGV[$i] =~ /OSOPER_GROUP=/)
		{
			($name, $value) = split (/=/, $ARGV[$i]);
			$ARGS{$name} = $value;
			$CLONE_COMMAND_LINE = $CLONE_COMMAND_LINE.' "oracle_install_OSOPER='.$value.'"';
		}
		elsif ($ARGV[$i] =~ /OSASM_GROUP=/)
		{
			($name, $value) = split (/=/, $ARGV[$i]);
			$ARGS{$name} = $value;
			$CLONE_COMMAND_LINE = $CLONE_COMMAND_LINE.' "oracle_install_OSASM='.$value.'"';
		}
		elsif ($ARGV[$i] =~ /oracle.install.skipRootPre=/)
		{
			$SKIP_ROOTPRE_PROPERTY_PASSED="TRUE";
			($name, $value) = split (/=/, $ARGV[$i]);
			$ARGS{$name} = $value;
			if ( lc($value) eq 'true') 
			{
				$SKIP_ROOTPRE_PROPERTY="TRUE";
			}
		}
		elsif ($ARGV[$i] =~ /=/)
		{
			$CLONE_COMMAND_LINE = $CLONE_COMMAND_LINE.' "'.$ARGV[$i].'"';
			($name, $value) = split (/=/, $ARGV[$i]);
			$ARGS{$name} = $value;
		}
		else	# Hook for EM Cloning
		{
			$CLONE_COMMAND_LINE = $CLONE_COMMAND_LINE.' '.$ARGV[$i].' ';
		}
	}
	if (exists $ARGS{"ORACLE_HOME"})
	{
		$ORACLE_HOME = $ARGS{"ORACLE_HOME"};
	}
	if (exists $ARGS{"ORACLE_HOME_NAME"})
	{
		$ORACLE_HOME_NAME = $ARGS{"ORACLE_HOME_NAME"};
	}
	if (exists $ARGS{"ORACLE_BASE"})
	{
		$ORACLE_BASE = $ARGS{"ORACLE_BASE"};
	}
	if (exists $ARGS{"OSDBA_GROUP"})
	{
		$OSDBA_GROUP = $ARGS{"OSDBA_GROUP"};
	}
	if (exists $ARGS{"OSOPER_GROUP"})
	{
		$OSOPER_GROUP = $ARGS{"OSOPER_GROUP"};
	}
	if (exists $ARGS{"OSASM_GROUP"})
	{
		$OSASM_GROUP = $ARGS{"OSASM_GROUP"};
	}
}


#############################################################################
# NAME   : build_clone_command
# PURPOSE: builds the command line to be passed to OUI.
# INPUTS : NONE
# OUTPUTS: NONE
# NOTES  : 
#
#############################################################################
sub build_clone_command()
{
	if ($DEBUG_MODE eq "true")
	{
		$CLONE_COMMAND_LINE = $CLONE_COMMAND_LINE . " -debug";
	}
}

#############################################################################
# NAME   : validate_arguments
# PURPOSE: Validates the command line arguments.
# INPUTS : NONE
# OUTPUTS: NONE
# NOTES  : Exits if any of the mandatory arguments are not passed / are invalid
#
#############################################################################
sub validate_arguments
{
	my $error_occurred = "false";
	# Check if a valid ORACLE_HOME is specified
	if ($ORACLE_HOME eq "Not yet set!!") 
	{
		print ("ERROR: Oracle Home has not been specified. Aborting the clone operation.\n\n");
		$error_occurred = "true";
	}
	elsif (!-e File::Spec->catfile($ORACLE_HOME, "oui", "bin"))
	{
		print ("ERROR: Invalid Oracle Home specified. Aborting the clone operation.\n\n");
		$error_occurred = "true";
	}
	elsif ($ORACLE_HOME_NAME eq "Not yet set!!")
	{
                $CLONE_COMMAND_LINE = $CLONE_COMMAND_LINE . " -defaultHomeName";
	}
	elsif ($ORACLE_BASE eq "Not yet set!!")
	{
        print ("ERROR: Invalid Oracle Base specified. Aborting the clone operation.\n\n");
		$error_occurred = "true";
	}
	if ($error_occurred eq "true") 
	{
        	print_usage();
		exit -1;
	}
}

#############################################################################
# NAME   : print_usage
# PURPOSE: NONE
# INPUTS : NONE
# OUTPUTS: NONE
# NOTES  : Prints the usage for the current script.
#	   Spaces were used instead of tabs to maintain formatting.
#	   Please verify the formatting of the message if this method is being updated.
#
#############################################################################
sub print_usage
{
	$help_msg = "NAME\n";
	$help_msg = $help_msg."    clone.pl - Clones an Oracle home.\n\n";
	$help_msg = $help_msg."SYNOPSIS\n";
	if(onWindows()){
	   $help_msg = $help_msg."    perl clone.pl ORACLE_HOME=<OH>\n                  ORACLE_BASE=<OB>\n                  [ORACLE_HOME_NAME=<OH Name>]|-defaultHomeName\n                  -O<>\n                  -debug\n                  -help\n\n";
        }
	else{
	   $help_msg = $help_msg."    perl clone.pl ORACLE_HOME=<OH>\n                  ORACLE_BASE=<OB>\n                  [ORACLE_HOME_NAME=<OH Name>]|-defaultHomeName\n                  OSDBA_GROUP=<group-name>\n                  OSOPER_GROUP=<group-name>\n                  OSASM_GROUP=<group-name>\n                  -O<>\n                  -debug\n                  -help\n\n";
	}
	$help_msg = $help_msg."DESCRIPTION\n";
	$help_msg = $help_msg."    Invoked at the target to clone the Oracle home\n\n";
	$help_msg = $help_msg."    ORACLE_HOME=<OH>\n        This is the complete path to the Oracle Home being cloned. If an\n        invalid path is specified the script will exit. This is a manda-\n        tory parameter.\n\n";
	$help_msg = $help_msg."    ORACLE_BASE=<OB>\n        This is the complete path to the Oracle Base being cloned. If an\n        invalid path is specified the script will exit. This is a manda-\n        tory parameter.\n\n";
	$help_msg = $help_msg."    ORACLE_HOME_NAME=<OH Name>\n        The Oracle Home Name for the home being cloned. This is an opti-\n        onal parameter.'-defaultHomeName' flag can be passed instead of\n        ORACLE_HOME_NAME to assign the default Oracle Home Name for the home.\n\n";
	if(!onWindows()){
	   $help_msg = $help_msg."    OSDBA_GROUP=<group-name>\n        Operating System group to be used as OSDBA privileged group.\n        It is recommended to pass this parameter for Oracle Database and\n        Oracle Grid Infrastructure software cloning.\n\n";
	   $help_msg = $help_msg."    OSOPER_GROUP=<group-name>\n        Operating System group to be used as OSOPER privileged group.\n        It is recommended to pass this parameter for Oracle Database and\n        Oracle Grid Infrastructure software cloning.\n\n";
	   $help_msg = $help_msg."    OSASM_GROUP=<group-name>\n        Operating System group to be used as OSASM privileged group.\n        It is recommended to pass this parameter for Oracle Grid\n        Infrastructure software cloning.\n\n";
        }
	$help_msg = $help_msg."    -O<>\n       If the -O flag were used then anything following it is passed to\n       the OUI clone command line.\n\n";
	#$help_msg = $help_msg."    -P<>\n       If the -P flag were used then anything following it is passed to\n       the Preclone  clone command line.\n\n";
	$help_msg = $help_msg."    -debug\n       Runs the script in debug mode\n\n";
	$help_msg = $help_msg."    -help\n       Prints the usage for this script\n\n";

	# print the usage message
	print $help_msg;
}

#############################################################################
# NAME   : onWindows()
#
# PURPOSE: Return true if running under MS Windows
#############################################################################
sub onWindows
{
    return ($^O eq 'MSWin32');
}

#############################################################################
# NAME   : load_properties 
# PURPOSE: loads properties stored in the specified configuration file. 
# INPUTS : hash where the values are saved, and location of the config file.
# OUTPUTS: NONE
# NOTES  : 
#
#############################################################################
sub load_properties
{
	$props_file_loc = $_[0];
	#%PROPS = $_[1];
	my %PROPS ;
	#log_msg($DEBUG, "Loading properties from $props_file_loc");
	unless(-e $props_file_loc)
	{
		#log_msg ($ERROR, "Properties file $props_file_loc was not found. Failed loading correponding properties.");
		print "Properties file $props_file_loc was not found. Failed loading correponding properties.";
		return;
	}

	# load the file
	open(PROPS, $props_file_loc);

	while($line = <PROPS>)
	{
		# skip comment and empty lines
		if($line =~ /^#/ or $line eq "\n")
		{
			next;
		}
		($prop_name, $prop_val) = split("=", $line, 2);
		# Remove ^M characters
		$prop_name =~s/\^M//ig; 
		$prop_val =~s/\^M//ig;
		# Remove \n characters 
		$prop_name =~s/\\n//; 
		$prop_val =~s/\\n//; 
		# Trim spaces
		$prop_name =~s/^\s+//; 
		$prop_name =~s/\s+$//;
		$prop_val =~s/^\s+//; 
		$prop_val =~s/\s+$//;
		$PROPS{$prop_name} = $prop_val;
	}
	return %PROPS;
}

#############################################################################
# NAME   : rootpre_check
#
# PURPOSE: rootpre.sh need to be run on AIX to configure async I/O. Rootpre 
#	   needs to be run on solarisamd64 vendor clusters as well.
#############################################################################

sub rootpre_check
{

	$OS=$^O;
	if ( $OS eq "aix")
	{
		if ( -d "$ORACLE_HOME/inventory/Components21/oracle.rdbms" )
		{
			if  ($SKIP_ROOTPRE_PROPERTY eq "FALSE")
			{
				prompt_rootpre();         
			}
		}
	}

	if ($OS eq "solaris") 
	{
		$arch=`/usr/bin/isainfo -k`;
		chomp($arch);
		if ($arch eq "amd64"){
			if ( -e "$ORACLE_HOME/clone/rootpre.sh"){
				if ((-d "$ORACLE_HOME/inventory/Components21/oracle.crs") &&(isSunClusterRunning())){
					if  ($SKIP_ROOTPRE_PROPERTY eq "FALSE")
					{
						prompt_rootpre();
					}
				}
			}
		}
	}
}

#
# Check if SunCluster is running
#
sub isSunClusterRunning
{
  system("/bin/ps -e -u 0 | grep 'ucm[m]d' 1>/dev/null 2>/dev/null");
  if($? ne 0){
    return 0;
  }
  else{
    return 1;
  }
  
}

#############################################################################
# NAME   : prompt_rootpre
# PURPOSE: Output the rootpre prompt
# INPUTS : NONE
# OUTPUTS: NONE
#
#############################################################################
sub prompt_rootpre
{
	my $SHOW_ROOTPRE_PROMPT=FALSE;
	if ($SKIP_ROOTPRE_PROPERTY_PASSED eq "TRUE") {
		if ( $SKIP_ROOTPRE_PROPERTY eq "FALSE" ) {
			$SHOW_ROOTPRE_PROMPT=TRUE;
		}
	}
	else 
	{
		if(exists($ENV{"SKIP_ROOTPRE"})) {
			if ($ENV{'SKIP_ROOTPRE'} ne "TRUE") {
				print "SKIP_ROOTPRE not set to TRUE.\n";
		                exit 0;
			}
			else 
			{	
		                if ( $ENV{'SKIP_ROOTPRE'} eq "TRUE")
        		        {
                		        print "\n";
                        		print "****************************************************\n";
		                        print "SKIP_ROOTPRE environment variable is set to TRUE, \n";
        		                print "which means rootpre.sh was already run as root user.\n";
                		        print "****************************************************\n";
                        		print "\n";
                		}
			}
		} 
		else 
		{
			$SHOW_ROOTPRE_PROMPT=TRUE;
		}
	}		
	
	
	if ( $SHOW_ROOTPRE_PROMPT eq "TRUE" ){
		print "********************************************************************************\n";
		print "\n";
		print "Your platform requires the root user to perform certain pre-clone\n";
		print "OS preparation.  The root user should run the shell script 'rootpre.sh' before\n";
		print "you proceed with cloning.  rootpre.sh can be found at\n";
		print "$ORACLE_HOME/clone directory.";
		print "\n";
		print "Answer 'y' if the root user has run 'rootpre.sh' script.\n";
		print "\n";
		print "********************************************************************************\n";
		print "\n";
		print "Has 'rootpre.sh' been run by the root user? [y/n] (n)\n";
		chomp($response=<STDIN>);

		if ( $response eq "y" || $response eq "Y" )
		{
			print "";
		}
		else
		{
			print "Cloning stopped to run '$ORACLE_HOME/clone/rootpre.sh' by root.\n";
			exit 0;
		}
	}
}

#############################################################################
# NAME   : update_path_environment_variable
# PURPOSE: Updates the path environment variable
# INPUTS : NONE
# OUTPUTS: NONE
#
#############################################################################
sub update_path_environment_variable
{
	my $PATH=$ENV{'PATH'};
	if (! $PATH){
		$ENV{'PATH'} ='/usr/bin:/usr/ccs/bin';
	}
	else{
		$ENV{'PATH'}='/usr/bin:/usr/ccs/bin:'.$PATH;
	}
}
