#############################################################################
# NAME   :  orarun.pl
# Copyright (c) 2005, Oracle. All rights reserved.
#
# DESCRIPTION 
#  	Install directive for orarun component (a generic component) that 
# 	must be used before CRS is installed.This will populate the orarun response 
# 	file, and invoke the orarun.sh script to do the pre CRS setup.  
#
# NOTES
#      This directive expects the following property to be set while
#      creating orarun Component in the provisioning application UI.
#       1) NAME_CloneUser    : name for  the clone user account on  all hosts
#       2) NAME_ClonePassword : encrypted password for this account
#       3) NAME_MountInfo  (LIST) : List of mount locations. Each entry consists of  
#	the File system type, directory to mount, mount point, and options with % as separator  
#       Note that the first entry in this list will be used when setting SSH for nodes, it should be 
#	a NFS or OCFS mount (raw  will not  work)       
#       4) NAME_WorkDir   :A temporary work directory to be created during install
#       5) NAME_InventoryLoc  : Optional, if given, sets the permissions on ths directory
#       6) NAME_InstallGroup The group that  owns the inventory location directory
#       7) NAME_PrimaryGroup primary group of clone user account (required)
#       8) NAME_UserGroups:  Comma separated list of other groups the clone user is part of(optional )
#       9) NAME_UsrID: The id value to use for the user account on  all hosts 
#	10)NAME_OCFS_rpms : list of ocfs rpms required separated by spaces(*)
#	11)NAME_OCFSTOOL_rpms : list of ocfs tool rpms required separated by spaces(*)
# 	12)NAME_CVUQDISK_rpms : list of cvuqdisk rpms to be installed
#
#  	It also expects the NODELIST property  and NAME_DestHomeLocation property of the
# 	 CRS component to be filled.
# 	The CRS component is referenced as 'CRS_Component' hence the user must 
#       create this reference in the image. Modify the directive if this reference name is changed.
#
#	(*)The ocfs rpms are expected to be present in the stage server mount point 
# 	top level directory.
#
#	IMPORTANT: If NIS accounts are used, the user account creation step in this directive is
#	not required. Thus the 'NAME_ClonePassword' attribute need not be created for the generic 
#	component, and references to this attribute should be commented out in this script.
#	Likewise, SSH setup may already be present for NIS user accounts and need not be done here
#	
#      Refer to Provisioning Best practices doc for more details on components
#      and directives creation. 
#############################################################################
$ENV{PATH} = "/bin:/usr/bin:/usr/local/bin:/usr/sbin";
use strict;

require "$ENV{EMDROOT}/sysman/admin/scripts/provisioning/provisionCommon.pl";


my $g_priviplist="";
my $g_viplist="";
my $g_privnodeslist="";
my $g_sshdir="";
my $ocfs_used="false";
main();

sub main()
{
    
    
    print "\nInstalling Orarun component";
    my $exitstatus ;

    #get the path where the Orarun home is located on the target machine.
    my $currentfolder_cmd="pwd";
    my $currentfolder=`$currentfolder_cmd`;
    chomp $currentfolder;
    print "\nCurrent folder is: $currentfolder";
    
    
    #get the name of the tar file associated with the Orarun component.
    my $binaryFile = get_oraComponentFilename();

    # installFilePath variable stores the location of the Orarun tar file.
    print "\nComponent binary filename is $binaryFile";
    my $installFilePath="$currentfolder/$binaryFile";
    print "\nComponent binary filepath is $installFilePath";


    #constants

    # Not required if using NIS accounts, comment if so 
    my $CLONE_PASSWD = "NAME_ClonePassword";

    my $CLONE_USER   = "NAME_CloneUser";
    my $NODE_PROPERTY = "NAME_Image.CRS_Component.NAME_NodePropertyList[0]";
    my $HOMELOC_PROPERTY ="NAME_Image.CRS_Component.NAME_DestHomeLocation"; 
    my $CRSWRKDIR_PROPERTY ="NAME_Image.CRS_Component.NAME_DestWorkDir";
    my $MOUNT_INFO = "NAME_MountInfo[0]";
    my $WORKING_DIR = "NAME_WorkDir";
    my $INVENTORYLOC = "NAME_InventoryLoc";
    my $INSTALLGRP = "NAME_InstallGroup"; 
    my $PRIMGRP = "NAME_PrimaryGroup"; 
    my $USRGRPS = "NAME_UserGroups"; 
    my $USRID   = "NAME_UsrID"; 
    my $OCFS_FILES   = "NAME_OCFS_rpms";
    my $OCFS_TOOLFILES   = "NAME_OCFSTOOL_rpms";
    my $STAGE_MOUNT ="NAME_StageSharedMountPoint";
 
    # Get all the Orarun Component properties specified by user during creation time.

    # Not required if using NIS accounts, and can be commented out 
    my $clonePasswd = get_oraComponentProperty($CLONE_PASSWD);

    my $cloneUser = get_oraComponentProperty($CLONE_USER);
    my $workingDir = get_oraComponentProperty($WORKING_DIR);
    my $inventoryloc = get_oraComponentProperty($INVENTORYLOC);
    my $instGroup = get_oraComponentProperty($INSTALLGRP); 
    my $userGroups= get_oraComponentProperty($USRGRPS); 
    my $primGroup= get_oraComponentProperty($PRIMGRP); 
    my $OCFS_RPMS= get_oraComponentProperty($OCFS_FILES);
    my $OCFS_TOOLRPMS= get_oraComponentProperty($OCFS_TOOLFILES);
    my $usrID= get_oraComponentProperty($USRID); 

	
	#specific to OCFS and cvuqdisk
	my $base_url = get_oraProperty("NAME_StageBaseUrl");
        my $cvudisk_rpm = get_oraComponentProperty("NAME_CVUQDISK_rpms");

	my $usrID= get_oraComponentProperty($USRID);	
	my (@url_info, $len, $count, $url_entry, $dir, $nfs_host_name, $nfs_host_dir, $ocfsDir, $mount_ocfs);
	$nfs_host_dir="";
	my $mount_ocfs_onto = "/ocfs_rpms";
    @url_info = split /\/+/ ,$base_url ;
    $len = $#url_info;
    if($base_url=~ /^file:/  || $base_url =~/^FILE:/)
    {
		for($count=1;$count<=$len;$count++)
		{
			$url_entry=$url_info[$count];
			if($count ==1)
			{
				$nfs_host_name = $url_info[$count];
			}
			if($count >1)
			{
				$nfs_host_dir = $nfs_host_dir."/".$url_info[$count];
			}
		}
		#create the directory and mount the stage base url
		system("mkdir -m 777 $mount_ocfs_onto");
		system("mount $nfs_host_name:$nfs_host_dir $mount_ocfs_onto");
		$ocfsDir = $mount_ocfs_onto;
		$mount_ocfs="true";
	
		
	}
	else
	{
		$ocfsDir = $base_url;
	}

    if($cvudisk_rpm ne '')
    {
	#system("export CVUQDISK_GRP=".$instGroup);
	$ENV{CVUQDISK_GRP}="".$instGroup;
        my @list_cvuqdisk_rpms = split(/ /, $cvudisk_rpm);
	my $temp;
	foreach $temp (@list_cvuqdisk_rpms)
	{
		system("rpm","-Uvh", $ocfsDir."/".$cvudisk_rpm);	
	}
    }

    my  @nodeArray= ();
    #the complete string of all mount locations to be passed in  response file
    my $mountString="";     
    # NOTE:we  get this property from the CRS clone component
    my $homeLocation = get_oraProperty($HOMELOC_PROPERTY);
    my $crsWorkDir = get_oraProperty($CRSWRKDIR_PROPERTY);
    # NOTE:we should get this property from the CRS clone component
    my $nodeProperty = get_oraProperty($NODE_PROPERTY);
    print "\n read  node property:$nodeProperty";
    print "\n read  crs destworkdir property:$crsWorkDir";
    my $i = 0;
    #read all rows
    while ($nodeProperty)
    {
        push(@nodeArray,$nodeProperty);
	print "\nUser supplied node property:$nodeProperty";
        # go for next row ..
        $i = $i + 1;
        $NODE_PROPERTY= "NAME_Image.CRS_Component.NAME_NodePropertyList[$i]";
        $nodeProperty = get_oraProperty($NODE_PROPERTY);
        if ($nodeProperty eq "")
        {
            last;
        }
    }
    #read all mount locations, typically user will have three for voting disks  
    my $mountInfo = get_oraComponentProperty($MOUNT_INFO);
    my @mountArray= ();
    my $mountDirLoc="";
    @mountArray=split(/%/,$mountInfo);
    my $mountDir1=$mountArray[2];
    $i = 0;
    while ($mountInfo)
    {
        
       	@mountArray=split(/%/,$mountInfo);
       	$mountDirLoc=$mountArray[2];
	if($mountArray[0] eq "ocfs")
    	{
		$ocfs_used = "true";
    	}
	#create the mount location for bare metal box
        system("mkdir -p $mountDirLoc");
        system("chgrp $instGroup  $mountDirLoc");
        system("chmod 777  $mountDirLoc");
        $mountString=$mountString . $mountInfo . " ";
        # go for next row ..
        $i = $i + 1;
        $MOUNT_INFO = "NAME_MountInfo[$i]";
        $mountInfo = get_oraComponentProperty($MOUNT_INFO);
        if ($mountInfo eq "")
        {
            last;
        }
    }
    # Location of the orarun Response file.
    my $defaultResponseFile = $workingDir."/orarun.response";

    # Location of the enable file.
    my $enableFile = $workingDir."/orarun.enable";

    # Log file for the installation
    my $logFile = "/tmp/orarun-installer.out";

    # Location of the orarun script file.
    my $scriptFile = $workingDir."/orarun.sh";


    #location of EMDROOT
    my $emdDir=$ENV{EMDROOT};
    my $provScriptDir= $emdDir . "/sysman/admin/scripts/provisioning";

    # Check if the user has specified the required Component properties.
    # If not, exit displaying proper error message

    my $errorMsg = "";
    my $flag = 0;

    
    # Required to have the cloneUser all permissions
    system("chown -R $cloneUser $currentfolder/../..");
    system("chmod -R 777 $currentfolder/../..");

    # The check for password is not required if using NIS accounts, can be commented	
    if ($clonePasswd=~/null/ || $clonePasswd eq '')
    {
        $errorMsg = $errorMsg." $CLONE_PASSWD";
        $flag = 1;
    }

    if (!($cloneUser=~/null/ || $cloneUser eq '')) {
        print "\nUser supplied $CLONE_USER:$cloneUser";
    }
    else {
        $errorMsg = $errorMsg." $CLONE_USER";
        $flag = 1;
    }

    if ($primGroup=~/null/ || $primGroup eq '')
    {
        $errorMsg = $errorMsg." $PRIMGRP";
        $flag = 1;
    }
    
    
    if (!($workingDir=~/null/ || $workingDir eq '')) {
        print "\nUser supplied $WORKING_DIR:$workingDir";
        $workingDir = $workingDir."/";
    }
    else {
        $errorMsg = $errorMsg." $WORKING_DIR";
        $flag = 1;
    }
    if ($flag) {
        print "\nUser didnt specify $errorMsg. Specify this for the Orarun Component. Installation aborted. Exiting ... ";
        exit 1;
    }


    if (!($mountInfo=~/null/ || $mountInfo eq ''))
    {
        print "\nUser supplied MOUNT_INFO:$mountInfo";
    }
    # start nfs service
    # (uncomment in the unlikely case that the shared filesystems to be mounted are on one of the cluster hosts )
    #system("service portmap start");
    #system("service nfslock start");
    #system("service nfs start");

    #set domainname 
    my $domainStr=`dnsdomainname`;
    chomp $domainStr;
    system("domainname $domainStr");    
    
    
    #USER ACCOUNT CREATION: NOT NEEDED FOR NIS, PLEASE COMMENT /REMOVE 
    #add user and assign to primary group,  specify id 
#    my $idstr = " -u " . $usrID . " ";
    
#    my $usraddcmd="useradd -g " .  $primGroup .  " -p " . $clonePasswd . $idstr . $cloneUser;
#    print "\ncreate user:$usraddcmd";
#    system("$usraddcmd");
    
    #END USER ACCOUNT CREATION
    
    
    
    # create the text to go for user secondary groups in response file 
    $userGroups= $cloneUser.":".$userGroups;     

    #Adding entry to sudo file
    my $sudo_entry="\n".$cloneUser."\tALL=(ALL)\t ALL";
    my $sudoers_path="/etc/sudoers";
    open(INFO, ">>$sudoers_path");      # Open for appending
    print INFO $sudo_entry;

    
    #SSH KEY CREATION, NOT REQUIRED IF NIS USER HAS SSH SETUP ALREADY
    #PLEASE COMMENT THE LINE BELOW FOR THAT CASE
    #create ssh keys for the user and put them in the home/.ssh directory.
    sshSetup($cloneUser);
    
    
    
    
    #make clone home location dir 
    system("mkdir -p $homeLocation");
    system("chown $cloneUser  $homeLocation");
    system("chgrp $instGroup  $homeLocation");
   #make crs dest work dir
   print "\nmkdir -p $crsWorkDir\n";
   system("mkdir -p $crsWorkDir");
   print "\nchown $cloneUser  $crsWorkDir\n";
   system("chown $cloneUser  $crsWorkDir");
   print "\nchgrp $instGroup  $crsWorkDir\n";
   system("chgrp $instGroup  $crsWorkDir");

    # create the working directory as $cloneUser user.
    system("sudo -u $cloneUser mkdir -p $workingDir");
    $exitstatus = $? >> 8;
    if ($exitstatus != 0)
    {
        print "\nFailed while creating $workingDir directory.";
        exit $exitstatus;
    }

    chdir $workingDir;
    $exitstatus = $? >> 8;
    if ($exitstatus != 0)
    {
        print "\nFailed while changing the directory.";
        cleanup($workingDir,$cloneUser);
        exit $exitstatus;
    }

    # Untar the Orarun Shiphome as $cloneUser user.
    print "\nUntaring the Orarun Shiphome, This will take sometime. Please wait...\n";
    my $command = `sudo -u $cloneUser tar -zxvf $installFilePath`;
    $exitstatus = $? >> 8;
    if ($exitstatus != 0)
    {
        print "\nFailed while untaring the Orarun component\n";
        cleanup($workingDir,$cloneUser);
        exit $exitstatus;
    }
    
	
    # Modify the response file to include username,group, and vip,internal ip info
    readNodeProperties(@nodeArray);
    system("chmod 777 $defaultResponseFile");
    system("chmod 777 $enableFile");

    update_file($defaultResponseFile,"<%ORACLEUSER%>",$cloneUser,"ignorecase");
    update_file($defaultResponseFile,"<%VIRTUAL_IP_INFO%>",$g_viplist,"ignorecase");
    update_file($defaultResponseFile,"<%PRIVATE_NODE_INFO%>",$g_priviplist,"ignorecase");
    update_file($defaultResponseFile,"<%PRIVATE_NODES%>",$g_privnodeslist,"ignorecase");
    update_file($defaultResponseFile,"<%MOUNT_INFO%>",$mountString,"ignorecase");
    update_file($defaultResponseFile,"<%OCFS_RPM_BASE_LOC%>",$ocfsDir,"ignorecase");
    update_file($defaultResponseFile,"<%INVENTORY_LOCATION%>",$inventoryloc,"ignorecase");
    update_file($defaultResponseFile,"<%INSTALL_GRP%>",$instGroup,"ignorecase");
    update_file($defaultResponseFile,"<%USR_GRP%>",$userGroups,"ignorecase");
    update_file($defaultResponseFile,"<%OCFS_RPMS%>",$OCFS_RPMS,"ignorecase");
    update_file($defaultResponseFile,"<%OCFS_TOOL_RPMS%>",$OCFS_TOOLRPMS,"ignorecase");

  
    if($ocfs_used eq "true")
    {
	update_file($enableFile,"<%INSTALL_OCFS_MODULE%>","true","ignorecase");
    }
    else
    {
    	update_file($enableFile,"<%INSTALL_OCFS_MODULE%>","false","ignorecase");
    }

    system("chmod 777 $scriptFile");
    system("chmod 755 $defaultResponseFile");
    system("chmod 755 $enableFile");
    system("cat $defaultResponseFile >$logFile");
    system("cat $enableFile >$logFile");
    # Run orarun.sh as root user.
    my $runOrarun = $workingDir."orarun.sh  $defaultResponseFile $enableFile>> $logFile";

    print "\nExecuting orarun script This will take sometime. Please wait...";
    print "\n$runOrarun";

    $command = `$runOrarun`;
    $exitstatus = $? >> 8;
    print "\n Exit Code: $exitstatus";

    if ($exitstatus != 0 && $exitstatus !=1)
    {
        print "\nFailed while Executing runOrarun";
        print "\nSee log file:$logFile for details";
        cleanup($workingDir,$cloneUser);
        exit $exitstatus;
    }

    #IF USING NIS USER ACCOUNTS, PLEASE MODIFY CODE BELOW 
    #TO COPY SSH KEYS FROM THE CORRECT LOCATION
    #copy the SSH keys to the mount directory 
    my $hostnm=`hostname`;
    chomp $hostnm;
    system("sudo -u $cloneUser cp $g_sshdir/identity.pub  $mountDir1/$hostnm.identity");
    system("sudo -u $cloneUser cat $g_sshdir/known_hosts >> $mountDir1/$hostnm.hostkeys");
    
    
    cleanup($workingDir,$cloneUser);
	if($mount_ocfs eq "true")
	{
		system("umount $mount_ocfs_onto");
		system("rm -rf $mount_ocfs_onto");
	}
    print "\nSuccessfully Installed the Orarun Component";
    exit 0;
}


sub cleanup()
{
    my $workingDir = $_[0];
        my $installUser = $_[1];
    system("sudo -u $installUser rm -rf $workingDir");

    my $exitstatus = $? >> 8;
    if ($exitstatus != 0)
    {
        print "\nFailed while removing $workingDir dir";
        exit $exitstatus;
    }
}

sub readNodeProperties()
{
   my $hostname="";
   my $nodename="";
   my $tmpdir=""; 
   my $priv="";
   my $vip="";
   foreach (@_) {
	($hostname,$nodename,$tmpdir,$priv,$vip) = split(/;/);
   	 $g_viplist=$g_viplist . $vip . ":". $nodename . "_vip" . " ";
	 $g_priviplist=$g_priviplist. $priv . ":" . $nodename . "_priv" . " ";
	 $g_privnodeslist=$g_privnodeslist.$nodename."_priv"." ";
    } 
    print "viplist = $g_viplist \n";
    print "priviplist = $g_priviplist \n";
    print "privnodeslist = $g_privnodeslist \n";
}

#############################################################################
# NAME   : update_file
# PURPOSE: Upadates a file replacing all enteries of a search string with a replace string.
# INPUTS : Complete path of the file, the pattern to be searched for, the replace string.
# OUTPUTS:
# NOTES  : Contributed by Madhukar Akrapu
#
#############################################################################
sub update_file
{
   my $file_name="";
   my $search_string="";
   my $replace_string="";
   my $case_sensitive_switch="";
   my $backup_file="";
   my $line="";
   my @array= ();

   ($file_name, $search_string, $replace_string, $case_sensitive_switch)=@_;
   $backup_file = $file_name."\.backup";
   open (ORIG_FILE, $file_name);
   @array=<ORIG_FILE>;
   close (ORIG_FILE);
   open (ORIG_FILE_TMP, ">".$backup_file);
   foreach $line (@array)
   {
       if ($line =~ /$search_string/)
       {
           if ($case_sensitive_switch eq "ignorecase")
           {
               $line=~s/$search_string/$replace_string/gi;
           }
           else
           {
               $line=~s/$search_string/$replace_string/g;
           }
       }
       print ORIG_FILE_TMP $line;
   }
   close (ORIG_FILE_TMP);
   #unlinking the file as behavior of the rename call varies wildly depending on the system implementation
   unlink $file_name;
   rename($backup_file, $file_name);
}

#THIS NEED NOT BE CALLED FOR NIS ACCOUNTS THAT HAVE SSH SET UP ALREADY 
#create ssh keys for user, create and populate known hosts file
sub sshSetup
{
    my $userAcc = $_[0];
    my $ip=`/sbin/ifconfig  | grep -i "eth0" -A 1 |grep "inet addr" | cut -d " " -f 12 |cut -d ":" -f 2`;
    chomp $ip;
    my $hostnm=`hostname -s`;
    chomp $hostnm;
    my $getHomeCmd="awk -F: '\$1 == \"$userAcc\"  {print \$6}'  /etc/passwd";
    my $userhome= `$getHomeCmd`;
    chomp $userhome;
    $g_sshdir= $userhome . "/.ssh";
    # create the .ssh directory as $cloneUser user then create keys inside.
    system("sudo -u $userAcc mkdir -p $g_sshdir");
    my $sshcmd="sudo -u $userAcc ssh-keygen -q -t rsa -f " . $g_sshdir . "/identity -N \"\"";
    system($sshcmd);
    $sshcmd="cat $g_sshdir/identity.pub >> $g_sshdir/authorized_keys";
    system($sshcmd);
    print "Creating known_hosts file on local host\n";
    system("sudo -u $userAcc touch $g_sshdir/known_hosts");
    print "\nChanging permissions on known_hosts to 644 on local host\n";
    system("chmod 644 $g_sshdir/known_hosts");
    system("echo -n \"$hostnm,$ip \" >> $g_sshdir/known_hosts");
    system("cat /etc/ssh/ssh_host_rsa_key.pub >> $g_sshdir/known_hosts");
}
