# $Header: emcore/sysman/admin/scripts/osm/ecmCloneHome.pl /stpl_db_11.2.0.1.0_gen/1 2009/09/28 21:20:49 kbodkhe Exp $ # # Copyright (c) 2001, 2009, Oracle and/or its affiliates. All rights reserved. # # DESCRIPTION # perl routines used by CloneInstallation job # # NOTES # # # MODIFIED (MM/DD/YY) # kbodkhe 09/24/09 - Handling hybrid java invocations on Solaris x64 # amani 01/10/08 - Backport amani_coregen from main # kkhanuja 09/11/07 - # shnavane 05/18/07 - Fix bug #6024894 # shnavane 09/02/07 - Backport shnavane_bug-6024894 from main # amani 08/09/07 - Added overloaded method preparesourceHomeEx, for enabling to use # zip utility. HP POC requirement. # amani 08/08/06 - Backport amani_fix_5374094 from main # amani 07/13/06 - For bug fix 5374094 # amani 05/25/06 - Adding additional options for update # amani 05/25/06 - Adding additional options for update # amani 05/25/06 - Adding additional options for update # amani 05/25/06 - Adding additional options for update # amani 08/01/06 - Backport amani_bug-5075347 from main # amani 07/31/06 - Backport amani_bug-4870299 from main # amani 05/03/06 - For adding options to dcmJoincluster, changing code for addtoOUI # amani 04/24/06 - To add Prereq check for windows.Bug fix 5053879. # makarapu 02/28/06 - Exit code issue with addnode # audupi 01/18/06 - Backport audupi_bug-4870686 from main # audupi 12/27/05 - 4906869 - 10.1.3 Integration # audupi 12/14/05 - Backport audupi_bug-4870686 from main # audupi 12/13/05 - Adding sub-routine to register home with # OUIinventories.add # audupi 09/15/05 - 4609384 - Adding -nowait to clone parameters # anusharm 08/25/05 - making checkDestPrereqs compatible with 10.1GC # audupi 08/23/05 - 4568252 - Win CRS create cluster changes # anusharm 08/22/05 - unsetting EMSTATE for AS Cloning # anusharm 08/08/05 - win32 CRS parameters # audupi 08/03/05 - Removing braces for cluster-nodes for attachRACHome # anusharm 08/01/05 - clearing CONSOLE_CFG for ias clone # anusharm 07/15/05 - windows crs support # anusharm 07/15/05 - windows crs support # anusharm 07/12/05 - adding ORACLE_HOSTNAME for CRS # anusharm 06/14/05 - removing unnecessary params from prepareCRS # anusharm 05/31/05 - making prepare_clone.pl optional for prepareAS # anusharm 05/24/05 - correcting crs extend case # anusharm 04/28/05 - correcting prepareASHome params, adding prepareCRSHome # anusharm 04/14/05 - removing extra escape chars # gpalrech 04/06/05 - attachHome method for RAC # anusharm 04/04/05 - adding checkDestPrereqs to job # anusharm 03/28/05 - cleaning up rac job # anusharm 02/03/05 - cloning for crs # mgoodric 01/31/05 - fix ambiguous warn subroutine # anusharm 01/24/05 - clean up updateHome classpath # anusharm 12/28/04 - dcmJoinCluster, dcm whichCluster # anusharm 12/01/04 - adding local_node, calling clone.pl in # updateBuiltInClonable, calling prepare_clone.pl # for db homes, adding emCfg.jar to classpath # anusharm 11/10/04 - ignoring exit status 2 for linux while tar, # take care of homes with space while setting invptrloc # anusharm 09/28/04 - adding 10gr2 enhancements # mnosseir 09/16/04 - add getFreeSpace() and dirPermission() to remove # dependency on db_common.pl # mnosseir 09/16/04 - #(3872357) set oracle.install.oui_loc in # updateBuiltInClonable() # anusharm 09/01/04 - merging ple changes # djoly 08/18/04 - Break up cemd # skumar 08/13/04 - HP, AIX, Tru64, MAC OS X, HPI and L64 changes # anusharm 06/18/04 - bug 3427734 # anusharm 06/17/04 - bug 3235500 # djoly 05/14/04 - Update core reference # mnosseir 04/09/04 - #(3488792) typecast the return value of # getFreeSpace to int # mbhoopat 03/10/04 - linux port # nsharma 01/21/04 - change solaris to linux # jmansur 12/21/03 - bug 3238183 - testing shows oui bug prevents oui # using oui_loc when updateHome() is called, so # set LD_LIBRARY_PATH for that as before. # jmansur 12/17/03 - bug 3238183 - set oui_loc when check dest pre-reqs # (and when updateHome for platform-independence) # jmansur 01/12/04 - fix bug 3368647 - in updateBuiltInClonable(), if # status file is present, treat update as successful # jmansur 12/09/03 - bug 3307527 - handle Locale with no country piece # jmansur 12/05/03 - bug 3278299 - use csh for piped commands so overall # command fails if the 1st command in pipeline fails # jmansur 11/20/03 - bug 3271279 - fix copySourceHome so it doesn't try # to recursively copy a home to under itself # jmansur 11/14/03 - bug 3238101 - do preClone check in # updateBuiltInClonable(); if preClone check fails, # assume preClone not needed so job can continue # jmansur 11/13/03 - bug 3252975 - get zipped+expanded size of home's # ClonerStage(s) in checkSourcePrereqs() # jmansur 11/05/03 - bug 3238183 - handle space in new home's homeName, # so we can let oui tell us it's an invalid homeName # jmansur 10/22/03 - use /bin/find and /bin/ftp, so don't rely on path # - add other oui jars to classpath when updateHome() # - fix LD_LIBRARY_PATH when run oui's updateHome() # jmansur 09/25/03 - ClonerStage now (oui 2.3.0.9.0) returns an error # rather than a warning code if prereq-checks fail, # so go back to only warning for warning codes # jmansur 10/19/03 - add ftpGet - for bug 3200203 # jmansur 10/14/03 - use status-file when updateHome - for bug 3123996 # jmansur 10/14/03 - fix home-is-readable result; true/false, not 1/0 # jmansur 10/08/03 - check if home is readable in checkSourcePrereqs() # jmansur 10/02/03 - move more of prepareSource step from job to here # jmansur 09/23/03 - do case-blind search for excluded files on windows, # since windows has, e.g., .DBF, .log and .LOG files # jmansur 09/20/03 - use ' instead of ? as delimiter for search & subst, # since ?? only matches once between reset calls # jmansur 09/19/03 - handle embedded spaces in agent home location # jmansur 09/16/03 - handle embedded spaces in file paths; move more # perl here from job definition # jmansur 09/15/03 - jmansur_ecm-030912-clone-home-nt # jmansur 09/12/03 - creation # # use strict; use Config; use File::Basename; use File::Copy; use File::Path; use File::Spec; use Net::Domain qw(hostfqdn); use Sys::Hostname; require "emd_common.pl"; require "$ENV{EMDROOT}/sysman/admin/scripts/osm/ecmCommon.pl"; use vars qw($DF $DELIMITER); # # some platform-specific commands # my $FIND = '/usr/bin/find'; my $FTP = ''; my $TAR = ''; if (onWindows()) { $FTP = 'ftp'; } else { $FTP = '/usr/bin/ftp'; } if ($^O eq "darwin") { $TAR = '/usr/bin/gnutar'; } else { $TAR = '/bin/tar'; } my $CSH = '/bin/csh'; #### GLOBAL Platform-specific flags for all EM OSs #### if($^O =~ /solaris/i){ $DF = "/bin/df -k" } elsif($^O =~ /aix/i){ $DF = "/bin/df -Pk" } elsif($^O =~ /linux/i){ $DF = "/bin/df -k" } elsif($^O =~ /hpux/i){ $DF = "/usr/bin/bdf" } ## Operating system unknown (probably Unix) else{ $DF = "/bin/df -k" } ## The delimiter is used to separate paramters passed in perl routines from Java ## code. In most cases, it is used to separate file names. $DELIMITER = ":::"; # # check oui-style status returned from system(). oui-style status is: # 0 for success, 1 for ok with warnings, or -1 for failure # sub checkOuiStatus($$) { my ($systemStatus, # status from external call, e.g., from system() $operation # operation that failed, e.g., "update" ) = @_; my $warningText = "$operation completed successfully but there were some warnings"; my $exitStatus = $systemStatus / 256; if ($exitStatus == 1) { # use ecmCommon's warn subroutine main::warning($exitStatus, "$warningText"); } elsif ($exitStatus) { abort($operation, $exitStatus, "$systemStatus / 256"); } } # # check pre-requisite info at the clone dest # sub checkDestPrereqs() { (@ARGV) = @_; my $size = @ARGV; my $oms102 = "false"; #get type of OMS from number of arguments. if($size eq 5) { $oms102 = "true"; } if($oms102 eq "true") { my $homeLocation = $ARGV[0]; my $homeName = $ARGV[1]; my $scratchLocation = $ARGV[2]; my $homeArchSpaceReq = $ARGV[3]; my $homeSpaceReq = $ARGV[4]; #called only for pre-reqs step in the job checkDestPrereqsFor102($homeLocation, $homeName, $scratchLocation, $homeArchSpaceReq, $homeSpaceReq); } else { #for wizard validation, only for 10.1 GC my ($homeLocation, # dest home dir, e.g., /private/ora10gClone $homeName, # dest home name, e.g., ora10gClone $scratchLocation # scratch dir, e.g., /tmp/oemchd123 ) = @_; my $scratchIsRw; if (dirPermission($scratchLocation) eq "OK") { $scratchIsRw='true'; } else { $scratchIsRw='false'; } my $scratchFreeKB = int(getFreeSpace($scratchLocation)); my $homeFreeKB = int(getFreeSpace($homeLocation)); print("$scratchIsRw, $scratchFreeKB, $homeFreeKB"); # invoke code that uses oui then prints homeNameOK & ouiInvIsRw my $oracleHome = $ENV{ORACLE_HOME}; my $javaHome = $ENV{JAVA_HOME}; my $emdroot = $ENV{EMDROOT}; my $pathSep = "\":\""; if (onWindows()) { $pathSep = "\";\""; } my $d64_opt; if(is64BitHybridJava($ENV{EMDROOT})) { $d64_opt = "-d64"; } # same as emd.properties hostConfigClasspath my $classPath = "\"$oracleHome/oui/jlib/xmlparserv2.jar$pathSep$oracleHome/oui/jlib/OraInstaller.jar$pathSep$oracleHome/oui/jlib/srvm.jar$pathSep$oracleHome/oui/jlib/share.jar$pathSep$emdroot/sysman/jlib/emd_java.jar$pathSep$emdroot/sysman/jlib/emcoreAgent.jar$pathSep$emdroot/sysman/jlib/emagentSDK.jar$pathSep$emdroot/sysman/jlib/log4j-core.jar\""; chdir($javaHome) or abort("cd to '$javaHome'", $!, "$!"); system(getDirPath("bin", "java") . " $d64_opt -cp $classPath -Doracle.installer.oui_loc=\"$oracleHome/oui\" oracle.sysman.emd.ecm.clone.DestEnvironment -validate \"$homeName\" \"$homeLocation\""); exit ($? >> 8); } } sub checkDestPrereqsFor102() { my ($homeLocation, # dest home dir, e.g., /private/ora10gClone $homeName, # dest home name, e.g., ora10gClone $scratchLocation, # scratch dir, e.g., /tmp/oemchd123 $homeArchSpaceReq, # home archive space required $homeSpaceReq # home space required ) = @_; #For bug fix 5374094 $homeSpaceReq *= 2; $homeArchSpaceReq = $homeSpaceReq; print "Oracle Home Location:--$homeLocation--\n"; print "Oracle Home Name:--$homeName--\n"; print "Space required in working directory:$homeArchSpaceReq KB\n"; print "Space required for Oracle Home:$homeSpaceReq KB\n"; my $preReqFailures = ""; my $preReqWarnings = ""; my $scratchIsRw; if (dirPermission($scratchLocation) eq "OK") { $scratchIsRw='true'; } else { $scratchIsRw='false'; $preReqFailures = $preReqFailures."\nFailed >> Read/Write check failed for Working Directory:$scratchLocation\n"; } my $scratchFreeKB = int(getFreeSpace($scratchLocation)); if($scratchFreeKB eq "0") { $preReqWarnings = $preReqWarnings."\nWarning >> Could not find available space in the working directory.\n"; } elsif($scratchFreeKB < $homeArchSpaceReq) { $preReqFailures = $preReqFailures."\nFailed >> Not enough space in working directory($scratchFreeKB) for home archive($homeArchSpaceReq)\n"; } my $homeFreeKB = int(getFreeSpace($homeLocation)); if($homeFreeKB eq "0") { $preReqWarnings = $preReqWarnings."\nWarning >> Could not check available space in the volume.\n"; } elsif($homeFreeKB < $homeSpaceReq) { $preReqFailures = $preReqFailures."\nFailed >> Not enough space on the volume($homeFreeKB) selected for the Oracle Home($homeSpaceReq)\n"; } #On windows if the the drive is same, then the free space required must be greater than the (homeSpace+ArchSpace) if(onWindows()){ my $volOH = &getDriveName($homeLocation); my $volScratch = &getDriveName($scratchLocation); if($volOH eq $volScratch){ my $myTotReqdSpace = $homeSpaceReq + $homeArchSpaceReq; if($homeFreeKB < $myTotReqdSpace){ print "\n Space available for OracleHome:$homeFreeKB KB\n"; print "\n Space available for Working Directory:$scratchFreeKB KB\n"; $preReqFailures = $preReqFailures."\nFailed >> Total available space on the volume($homeFreeKB) for selected Oracle Home($homeSpaceReq) and Working Directory($homeArchSpaceReq) is not sufficient to support Clone operation\n"; } } } else { my $fileSyVal = &checkForSameFileSys($homeLocation,$scratchLocation ); if($fileSyVal eq "true") { my $totReqSpace = $homeSpaceReq + $homeArchSpaceReq; if($homeFreeKB < $totReqSpace){ print "\n Space available for OracleHome:$homeFreeKB KB\n"; print "\n Space available for Working Directory:$scratchFreeKB KB\n"; $preReqFailures = $preReqFailures."\nFailed >> Total available space on the system($homeFreeKB) for selected Oracle Home($homeSpaceReq) and Working Directory($homeArchSpaceReq) is not sufficient to support Clone operation\n"; } } } # invoke code that uses oui then prints homeNameOK & ouiInvIsRw my $oracleHome = $ENV{ORACLE_HOME}; my $javaHome = $ENV{JAVA_HOME}; my $emdroot = $ENV{EMDROOT}; my $pathSep = "\":\""; if (onWindows()) { $pathSep = "\";\""; } my $d64_opt; if(is64BitHybridJava($ENV{EMDROOT})) { $d64_opt = "-d64"; } # same as emd.properties hostConfigClasspath my $classPath = "\"$oracleHome/oui/jlib/xmlparserv2.jar$pathSep$oracleHome/oui/jlib/OraInstaller.jar$pathSep$oracleHome/jlib/emCfg.jar$pathSep$oracleHome/oui/jlib/srvm.jar$pathSep$oracleHome/oui/jlib/share.jar$pathSep$emdroot/sysman/jlib/emd_java.jar$pathSep$emdroot/sysman/jlib/emagentSDK.jar$pathSep$emdroot/sysman/jlib/emcoreAgent.jar$pathSep$emdroot/sysman/jlib/log4j-core.jar\""; chdir($javaHome) or abort("cd to '$javaHome'", $!, "$!"); my $cmd = getDirPath("bin", "java") . " $d64_opt -cp $classPath -Doracle.installer.oui_loc=\"$oracleHome/oui\" oracle.sysman.emd.ecm.clone.DestEnvironment -validate \"$homeName\" \"$homeLocation\""; open(READ, " $cmd |"); my @array=; close(READ); my $status = $?; if($status ne 0) { abort("checkDestPrereqs", $status >> 8, "could not execute destination validation"); } my $x = ""; my $homeOK = ""; my $locStatus = ""; my $ouiInvRw = ""; ($x, $homeOK, $locStatus, $ouiInvRw) = split(", ", $array[0], 4); if(uc($ouiInvRw) eq "FALSE") { $preReqFailures = $preReqFailures."\nFailed >> The central OUI inventory on this host is not read-writable or it is locked by another process. This directory must be read-writable before you submit the clone job.\n"; } if(uc($homeOK) eq "FALSE") { $preReqFailures = $preReqFailures."\nFailed >> Oracle Home Name is not valid.\n"; } if(($locStatus ne 1) && ($locStatus ne 2)) { if($locStatus eq -2)#is file { $preReqFailures = $preReqFailures."\nFailed >> Invalid Oracle Home Location. A file already exists by this name.\n"; } elsif($locStatus eq -3)#cannot create { $preReqFailures = $preReqFailures."\nFailed >> Invalid Oracle Home Location. Failed to create the new directory. The parent directory must be set as read-writable for the user specified in the Select Destination table for this host.\n"; } elsif($locStatus eq -4)#not empty { $preReqFailures = $preReqFailures."\nFailed >> Invalid Oracle Home Location. The existing directory is not empty.\n"; } elsif($locStatus eq -5)#not rw { $preReqFailures = $preReqFailures."\nFailed >> Invalid Oracle Home Location. Can not read-write into the existing directory. The directory location must be set as read-writable.\n"; } } #warnings if(length($preReqWarnings) ne 0) { print($preReqWarnings); } #failures if(length($preReqFailures) eq 0) { print("\n-----------------All pre-requisites succeeded-----------------\n"); exit; } else { #print("$preReqFailures\n"); abort("prerequisites", 1 , "$preReqFailures\n"); } } #given dirs, checks whether they belong to the same file system(unix type filesystem only) and returns true else returns false sub checkForSameFileSys($$) { my ($dir1, $dir2 ) = @_; #get the DF from global variable my $df = "$DF ."; my $row = -1; my $filesys1 = ""; my $filesys2 = ""; chdir($dir1); my @temp1 = `$df`; $_ = $temp1[$row]; my @tokens1 = split; $filesys1 = $tokens1[$#tokens1]; chdir($dir2); my @temp2 = `$df`; $_ = $temp2[$row]; my @tokens2 = split; $filesys2 =$tokens2[$#tokens2]; if($filesys1 eq $filesys2){ return "true"; } else { return "false"; } } # the vol, dir and file for the given path sub getDriveName($){ my ($myPath) = @_; my ($myVoluname,$myDirname,$myFilesname) = File::Spec->splitpath( $myPath ); return $myVoluname; } # # check pre-requisite info at the clone source host & home # sub checkSourcePrereqs($$) { my ($homeLocation, # source home dir, e.g., /private/ora10g $scratchLocation # scratch dir, e.g., /tmp/oemchs123 ) = @_; my $scratchIsRw; if (dirPermission($scratchLocation) eq "OK") { $scratchIsRw='true'; } else { $scratchIsRw='false'; } my $scratchFreeKB = int(getFreeSpace($scratchLocation)); my @clonerStages = getClonerStageList($homeLocation); my $clonerStageCount = @clonerStages; my $clonerStageKB = 0; # sum of zip + expanded size of home's ClonerStage(s) my $clonerStageCountSize = ""; if (0 != $clonerStageCount) { foreach my $cs (@clonerStages) { chomp($cs); # assume expanded size = 2 * zip size # TBD - should use ClonerStage's getSpaceRequired.pl $clonerStageKB += (-s $cs) * 3; } $clonerStageKB = int(($clonerStageKB + 512) / 1024); $clonerStageCountSize = $clonerStageCount . ":" . $clonerStageKB; } else { $clonerStageCountSize = $clonerStageCount; } # bug 3235500, removed install.platform from must-be-readable list. my $homeIsReadable = ((-r $homeLocation) && (-r ($homeLocation . '/inventory'))) ? 'true' : 'false'; print("$scratchIsRw, $scratchFreeKB, $clonerStageCountSize, $homeIsReadable"); # if OH/oraInst.loc exists, use that to fix inventory associated with this OH, bug 3427734 my $setInventory = ""; if( -e ($homeLocation . '/oraInst.loc') ) { my $inventoryLoc = getPropertyValue($homeLocation . '/oraInst.loc', "inventory_loc") ; if( ($inventoryLoc ne "") && ( -r $inventoryLoc )) { $setInventory = "-Doracle.installer.invPtrLoc=". "\"$homeLocation" . "/oraInst.loc\"" ; } } # invoke code that uses oui then prints homeKB & archiveKB, etc. my $oracleHome = $ENV{ORACLE_HOME}; my $javaHome = $ENV{JAVA_HOME}; my $emdroot = $ENV{EMDROOT}; my $pathSep = "\":\""; if (onWindows()) { $pathSep = "\";\""; } my $d64_opt; if(is64BitHybridJava($ENV{EMDROOT})) { $d64_opt = "-d64"; } # same as emd.properties hostConfigClasspath my $classPath = "\"$oracleHome/oui/jlib/xmlparserv2.jar$pathSep$oracleHome/oui/jlib/OraInstaller.jar$pathSep$oracleHome/jlib/emCfg.jar$pathSep$oracleHome/oui/jlib/srvm.jar$pathSep$oracleHome/oui/jlib/share.jar$pathSep$emdroot/sysman/jlib/emd_java.jar$pathSep$emdroot/sysman/jlib/emagentSDK.jar$pathSep$emdroot/sysman/jlib/emcoreAgent.jar$pathSep$emdroot/sysman/jlib/log4j-core.jar\""; chdir($javaHome) or abort("cd to '$javaHome'", $!, "$!"); system(getDirPath("bin", "java") . " $d64_opt $setInventory -cp $classPath -Doracle.installer.oui_loc=\"$oracleHome/oui\" oracle.sysman.emd.ecm.clone.SourceEnvironment -checkPrereqs \"$homeLocation\""); exit ($? >> 8); } # # do recursive copy of source home to dest home # sub copySourceHome($$$) { my ($sourceHomeLocation, # source home dir, e.g., /private/ora10g $destHomeLocation, # dest home dir, e.g., /private/ora10gClone $excludeListFile, # file listing files to exclude, e.g., /tmp/eList.txt ) = @_; # don't try to recursively copy home to under itself my $bsSource = getBackSlashedString($sourceHomeLocation) . "\\"; my $bsDest = getBackSlashedString($destHomeLocation) . "\\"; if (substr($bsDest, 0, length($bsSource)) eq $bsSource) { abort("recursive copy attempt of '$sourceHomeLocation' to under itself: '$destHomeLocation'", 1, "copy loop detected"); } chdir($sourceHomeLocation) or abort("cd to '$sourceHomeLocation'", $!, "$!"); if (onWindows()) { ##### TBD can't seem to make xcopy handle $excludeListFile with embedded ##### spaces so in that case, skip excluding files ##### double-quoting $excludeListFile fails the xcopy if ((`xcopy /?` =~ m'/EXCLUDE:') && !($excludeListFile =~ m' ')) #####if (`xcopy /?` =~ m'/EXCLUDE:') { $excludeListFile = getBackSlashedString($excludeListFile); echodo("xcopy /r /i /c /h /k /e /y /s /q /EXCLUDE:" . $excludeListFile . " \"$sourceHomeLocation\" \"$destHomeLocation\"") == 0 or abort("copySourceHome", $? >> 8, "$!"); } else { echodo("xcopy /r /i /c /h /k /e /s /q \"$sourceHomeLocation\" \"$destHomeLocation\"") == 0 or abort("copySourceHome", $? >> 8, "$!"); } } else { if ($^O eq "aix" or $^O eq "hpux" or $^O eq "dec_osf") { # no -X option echodo("$CSH -cf '$TAR cpfh - . | (cd \"$destHomeLocation\"; $TAR xpfh -)'"); } else { echodo("$CSH -cf '$TAR cpfXh - \"$excludeListFile\" . | (cd \"$destHomeLocation\"; $TAR xpfh -)'"); } # treat status 13 as non-error - assume "permission denied" and ignore - # assume all cases are like root-owned files that get re-created at dest # tbd - there may be other errors that we should swallow or warn about, # e.g., if a file changes size while we're tar'ing it my $status = $? >> 8; if ($^O eq "dec_osf") { # on Tru64, status 1 is warning - assume "permission denied" and ignore if ((0 != $status) && (1 != $status)) { abort("copySourceHome", $status, "$!"); } } elsif ($^O eq "linux") { # on linux, all errors are status 1 or 2 so we ignore them all if ((0 != $status) && (1 != $status) && (2 != $status)) { abort("copySourceHome", $status, "$!"); } } elsif ((0 != $status) && (13 != $status)) { abort("copySourceHome", $status, "$!"); } } } # # export home to a COMPRESSed tar file or a zip file # sub exportHome($$$$) { my ($homeLocation, # home location to export, e.g., /private/ora10gHome $archiveFilePath, # full path of archive, e.g., /tmp/homeArchive $excludeListFile, # file that lists excluded files, e.g., /tmp/eList.txt $sourceExcludes # comma/space-separated patterns, e.g., "*.dbf, *.log" ) = @_; if (onWindows()) { $excludeListFile = getBackSlashedString($excludeListFile); $archiveFilePath = getBackSlashedString($archiveFilePath); } my $operation = "-export"; # run the ecmHomePackager.pl in the Oracle home # NOTE: future - look for customHomePackager.pl & run that instead # since double-quoting the commands in the echodo's fails, get the perl dir # then chdir there in case path contains embedded blanks my ($perlName, $perlDir, $perlSuffix) = fileparse("$^X", ""); print("chdir($perlDir)\n"); chdir($perlDir) or abort("cd to '$perlDir'", $!, "$!"); echodo(getDirPath("$perlName") . " -w \"$ENV{EMDROOT}/sysman/admin/scripts/osm/ecmHomePackager.pl\" $operation \"$archiveFilePath\" \"$homeLocation\" \"$sourceExcludes\" \"$excludeListFile\""); exit ($? >> 8); } # # export home to a COMPRESSed tar file or a zip file # sub exportHomeEx($$$$$) { my ($homeLocation, # home location to export, e.g., /private/ora10gHome $archiveFilePath, # full path of archive, e.g., /tmp/homeArchive $excludeListFile, # file that lists excluded files, e.g., /tmp/eList.txt $sourceExcludes, # comma/space-separated patterns, e.g., "*.dbf, *.log" $useZIP # ) = @_; if (onWindows()) { $excludeListFile = getBackSlashedString($excludeListFile); $archiveFilePath = getBackSlashedString($archiveFilePath); } my $operation = "-export"; # run the ecmHomePackager.pl in the Oracle home # NOTE: future - look for customHomePackager.pl & run that instead # since double-quoting the commands in the echodo's fails, get the perl dir # then chdir there in case path contains embedded blanks my ($perlName, $perlDir, $perlSuffix) = fileparse("$^X", ""); print("chdir($perlDir)\n"); chdir($perlDir) or abort("cd to '$perlDir'", $!, "$!"); echodo(getDirPath("$perlName") . " -w \"$ENV{EMDROOT}/sysman/admin/scripts/osm/ecmHomePackager.pl\" $operation \"$archiveFilePath\" \"$homeLocation\" \"$sourceExcludes\" \"$excludeListFile\" \"$useZIP\""); exit ($? >> 8); } # # use ftp to pull source file from source host to dest file on current host # sub ftpGet($$$$$) { my ($sourceHost, # name host where source file resides $sourceFilePath, # path to file to get, e.g., /tmp/homeArchive $destFilePath, # path to file on current host, e.g., /tmp/homeArchive $sourceUsername, # username that can read source file $sourcePassword # password of user that can read source file ) = @_; my $systemCommand = "| $FTP -n $sourceHost"; print("\n$systemCommand\n"); $! = 0; open(FTPIN, "$systemCommand") || abort("fork", $!, "$!"); local $SIG{PIPE} = sub { abort("pipe", $!, "$!") }; print FTPIN "user $sourceUsername $sourcePassword\n"; print FTPIN "binary\n"; print FTPIN "get \"$sourceFilePath\" \"$destFilePath\"\n"; print FTPIN "close\n"; print FTPIN "bye\n"; my $status = close FTPIN; if (!$status) { if ($!) { abort("ftp process", $!, "$!"); } else { $status = $? >> 8; if ($status != 0) { abort("ftp", $? >> 8, "$? >> 8"); } } } if (! -e $destFilePath) { abort("ftp of '$sourceFilePath' to '$destFilePath'", $!, "$!"); } } # # returns a classPath containing the jars in jarDir. Elements of classPath # are double-quoted and seprated by a platform-specific separator. If # appendEmJars is not 'true', classPath is terminated with a separator. # sub getClassPathWithJars($$) { my ($jarDir, # dir containing jar files, e.g., /oracle/ora10g/oui/jlib $appendEmJars # 'true' asks that em jars (from under $ENV{"EMDROOT"}) # also be added to classPath ) = @_; my $emdroot = $ENV{EMDROOT}; my $pathSep = "\":\""; if (onWindows()) { $pathSep = "\";\""; } # add all of this dir's jars to classpath my $cp = '"'; if (!opendir(JAR_DIR, "$jarDir")) { abort("open of '$jarDir'", $!, "$!"); } while (my $jar = readdir(JAR_DIR)) { if ($jar =~ m'\.jar$') { $cp .= "$jarDir/$jar$pathSep"; } } closedir(JAR_DIR); # get rid of extra trailing double quote, if any if (onWindows()) { $cp =~ s';"$';'; # ' } else { $cp =~ s':"$':'; # ' } if ($appendEmJars eq "true") { $cp .= "\"$emdroot/sysman/jlib/emd_java.jar$pathSep$emdroot/sysman/jlib/emagentSDK.jar$pathSep$emdroot/sysman/jlib/emcoreAgent.jar$pathSep$emdroot/sysman/jlib/log4j-core.jar$pathSep"; } # get rid of extra trailing double quote(pathSep leaves extra quote) if (onWindows()) { $cp =~ s';"$';'; # ' } else { $cp =~ s':"$':'; # ' } return $cp; } # # get user-supplied computeAtClone variables & defaults needed for the clone # sub getCloneParams($$$$) { my ($homeLocation, # source home dir, e.g., /private/ora10g $localeLanguage, # locale.getLanguage() - language of param descriptions $localeCountry, # locale.getCountry() $localeVariant # locale.getVariant() ) = @_; my $oracleHome = $ENV{ORACLE_HOME}; my $javaHome = $ENV{JAVA_HOME}; my $emdroot = $ENV{EMDROOT}; my $pathSep = "\":\""; if (onWindows()) { $pathSep = "\";\""; } # if OH/oraInst.loc exists, use that to fix inventory associated with this OH, bug 3427734 my $setInventory = ""; if( -e ($homeLocation . '/oraInst.loc') ) { my $inventoryLoc = getPropertyValue($homeLocation . '/oraInst.loc', "inventory_loc") ; if( ($inventoryLoc ne "") && ( -r $inventoryLoc )) { $setInventory = "-Doracle.installer.invPtrLoc="."\"$homeLocation" . "/oraInst.loc\"" ; } } my $d64_opt; if(is64BitHybridJava($ENV{EMDROOT})) { $d64_opt = "-d64"; } # same as emd.properties hostConfigClasspath my $classPath = "\"$oracleHome/oui/jlib/xmlparserv2.jar$pathSep$oracleHome/oui/jlib/OraInstaller.jar$pathSep$oracleHome/jlib/emCfg.jar$pathSep$oracleHome/oui/jlib/srvm.jar$pathSep$oracleHome/oui/jlib/share.jar$pathSep$emdroot/sysman/jlib/emd_java.jar$pathSep$emdroot/sysman/jlib/emagentSDK.jar$pathSep$emdroot/sysman/jlib/emcoreAgent.jar$pathSep$emdroot/sysman/jlib/log4j-core.jar\""; chdir($javaHome) or abort("cd to '$javaHome'", $!, "$!"); system(getDirPath("bin", "java") . " $d64_opt $setInventory -cp $classPath -Doracle.installer.oui_loc=\"$oracleHome/oui\" oracle.sysman.emd.ecm.clone.SourceEnvironment -getCloneVariables \"$homeLocation\" \"$localeLanguage\" \"$localeCountry\" \"$localeVariant\""); exit ($? >> 8); } # # get list of ClonerStages in home # sub getClonerStageList($) { my ($homeLocation # home location to search, e.g., /private/ora10gHome ) = @_; my $csPattern = $homeLocation . '/sysman/clonerStage/ClonerStage*.zip'; my @csList = (); if (onWindows()) { $csPattern = getBackSlashedString($csPattern); @csList = `dir /b /s "$csPattern" 2> NUL`; } else { $csPattern =~ s' '\\ 'g; # ' @csList = glob($csPattern); } return @csList; } # # get directory path made up of caller supplied parts, prepended with . # sub getDirPath { my $slash = ''; if (onWindows()) { $slash = '\\'; } else { $slash = '/'; } my $fullPath= ".$slash" . join($slash, @_); return $fullPath; } # # get version of inputString with all forward slashes replaced by backslashes # sub getBackSlashedString($) { my ($inputString # string that may contain forward slashes ) = @_; my $backSlashedString = $inputString; $backSlashedString =~ s'/'\\'g; # ' closing quote fixes text highlighting return $backSlashedString; } # # get java home - use home's jre if found, else use JAVA_HOME from env # sub getJavaHome($) { my ($homeLocation # home location to search, e.g., /private/ora10gHome ) = @_; # find dest home's oui's jre & use its jre/bin/java to call oui updateHome() my $javaLocation = $ENV{JAVA_HOME}; my $ouiParamFile = $homeLocation . '/oui/oraparam.ini'; if (!open(OUI_PARAMS, $ouiParamFile)) { abort("open of '$ouiParamFile'", $!, "$!"); } while (my $line = ) { chomp $line; if ($line =~ m/(\S+)=(\S+)/) { #print("name, value = $1, $2\n"); if ($1 eq "JRE_LOCATION") { $javaLocation = $homeLocation . '/oui/bin/' . $2; #print("javaLocation=$javaLocation\n"); last; # TBD - or should we let bottom-most JRE_LOCATION win? } } } close(OUI_PARAMS); return $javaLocation; } # # get quoted version of command that can be passed to system() # # WARNING: each call overwrites the OEM_ECM_CH_COMMAND environment variable # sub getQuotedCommand($) { my ($command # the normal looking command, e.g, $^X (the perl exe) ) = @_; if (!($command =~ m' ')) { return $command; } my $quotedCommand = ''; if (onWindows()) { $ENV{'OEM_ECM_CH_COMMAND'} = "\"$command\""; print("\n\$ENV\{'OEM_ECM_CH_COMMAND'\}=\"$ENV{'OEM_ECM_CH_COMMAND'}\"\n"); $quotedCommand = '%OEM_ECM_CH_COMMAND%'; } else { $quotedCommand = "\"$command\""; } return $quotedCommand; } # # returns one if home needs preCloning (needs NOH components installed, etc.). # returns zero otherwise. # sub homeNeedsPreCloning($) { my ($homeLocation # home location to examine ) = @_; my $oracleHome = $ENV{ORACLE_HOME}; my $javaHome = $ENV{JAVA_HOME}; my $emdroot = $ENV{"EMDROOT"}; my $pathSep = "\":\""; if (onWindows()) { $pathSep = "\";\""; } my $d64_opt; if(is64BitHybridJava($ENV{EMDROOT})) { $d64_opt = "-d64"; } # same as emd.properties hostConfigClasspath my $classPath = "\"$oracleHome/oui/jlib/xmlparserv2.jar$pathSep$oracleHome/oui/jlib/OraInstaller.jar$pathSep$oracleHome/jlib/emCfg.jar$pathSep$oracleHome/oui/jlib/srvm.jar$pathSep$oracleHome/oui/jlib/share.jar$pathSep$emdroot/sysman/jlib/emd_java.jar$pathSep$emdroot/sysman/jlib/emagentSDK.jar$pathSep$emdroot/sysman/jlib/emcoreAgent.jar$pathSep$emdroot/sysman/jlib/log4j-core.jar\""; print("chdir($javaHome)\n"); chdir($javaHome) or abort("cd to '$javaHome'", $!, "$!"); my $systemCommand=getDirPath("bin", "java") . " $d64_opt -cp $classPath -Doracle.installer.oui_loc=\"$oracleHome/oui\" oracle.sysman.emd.ecm.clone.DestEnvironment -isPreCloneNeeded \"$homeLocation\" |"; print("\n$systemCommand\n"); $! = 0; if (!open(CHECKER, "$systemCommand")) { main::warning($!, "preClone check fork failed: $!"); return 0; } local $SIG{PIPE} = sub { main::warning($!, "preClone check pipe failed: $!"); return 0; }; while (my $line = ) { if (!close CHECKER) { main::warning($! ? $! : $?, $! ? "preClone check close failed: $!" : "preClone check exited with: $?"); return 0; } if ($line =~ /true/) { return 1; } else { return 0; } } main::warning($!, "preClone check failed for '$homeLocation': $!"); return 0; } # # import/create home from a COMPRESSed tar file or a zip file # sub importHome($$) { my ($homeLocation, # home location to populate, e.g., /private/ora10gClone $archiveFilePath # full path of archive, e.g., /tmp/homeArchive ) = @_; if (onWindows()) { $archiveFilePath = getBackSlashedString($archiveFilePath); } my $operation = "-import"; # run the ecmHomePackager.pl in the Oracle home # NOTE: future - look for customHomePackager.pl & run that instead my ($perlName, $perlDir, $perlSuffix) = fileparse("$^X", ""); print("chdir($perlDir)\n"); chdir($perlDir) or abort("cd to '$perlDir'", $!, "$!"); echodo(getDirPath("$perlName") . " -w \"$ENV{EMDROOT}/sysman/admin/scripts/osm/ecmHomePackager.pl\" $operation \"$archiveFilePath\" \"$homeLocation\""); exit ($? >> 8); } # # create a file containing a list of files that tar or xcopy should exclude # when copying a directory tree # sub listExcludedFiles($$$$) { my ($dirLocation, # dir location to examine, e.g., /private/ora10gHome $excludeListDir, # dir to hold file that will hold list, e.g., /tmp $excludeListFile, # file that will hold list, e.g., /tmp/eList.txt $sourceExcludes, # patterns, e.g., "*.dbf, *.log" ) = @_; my $oracleHome = $ENV{"ORACLE_HOME"}; my @excludePatterns = split(/[ ,]+/, $sourceExcludes); if (!open(EXCLUDE_LIST, "> $excludeListFile")) { abort("open of '$excludeListFile'", $!, "$!"); } close(EXCLUDE_LIST); my $size = @excludePatterns; if($size == 0) { return; } if (!onWindows()) { chdir($dirLocation) or abort("cd to '$dirLocation'", $!, "$!"); foreach my $pattern (@excludePatterns) { echodo("$FIND . -name \"$pattern\" >> \"$excludeListFile\"") == 0 or main::warning($!, "find for '$pattern': $!"); } } elsif (onWindows() && (`xcopy /?` =~ m'/EXCLUDE:')) { my $perlLoc = $oracleHome . '/perl'; chdir($perlLoc) or abort("cd to '$perlLoc'", $!, "$!"); chomp(my $find2Perl = `dir/b/s find2perl.bat`); chdir($dirLocation) or abort("cd to '$dirLocation'", $!, "$!"); my $findExcludesScript = $excludeListDir . '/findExcludes.pl'; $findExcludesScript = getBackSlashedString($findExcludesScript); $excludeListFile = getBackSlashedString($excludeListFile); foreach my $pattern (@excludePatterns) { unlink($findExcludesScript); #echodo(getQuotedCommand($find2Perl) . # " . -name \"$pattern\" -print | \"$^X\" >> \"$excludeListFile\"") == 0 echodo(getQuotedCommand($find2Perl) . " . -name \"$pattern\" -print > \"$findExcludesScript\"") == 0 or abort("'$find2Perl' for '$pattern'", $? >> 8, "$!"); echodo(getQuotedCommand($^X) . " \"$findExcludesScript\" >> \"$excludeListFile\"") == 0 or abort("'$findExcludesScript' for '$pattern'", $? >> 8, "$!"); my $ucPattern = uc($pattern); #echodo(getQuotedCommand($find2Perl) . # " . -name \"$ucPattern\" -print | \"$^X\" >> \"$excludeListFile\"") == 0 unlink($findExcludesScript); echodo(getQuotedCommand($find2Perl) . " . -name \"$ucPattern\" -print > \"$findExcludesScript\"") == 0 or abort("'$find2Perl' for '$ucPattern'", $? >> 8, "$!"); echodo(getQuotedCommand($^X) . " \"$findExcludesScript\" >> \"$excludeListFile\"") == 0 or abort("'$findExcludesScript' for '$ucPattern'", $? >> 8, "$!"); } rename("$excludeListFile", "$excludeListFile-ORIG"); open EXCLUDE_LIST_OLD, "$excludeListFile-ORIG"; open EXCLUDE_LIST_NEW, "> $excludeListFile"; while (my $line = ) { chomp $line; $line =~ s'^\./''; # ' $line = getBackSlashedString($line); print EXCLUDE_LIST_NEW "$line\n"; } close EXCLUDE_LIST_OLD; close EXCLUDE_LIST_NEW; } } # # # Make dir or fail if it already exists # sub makeNewDir($) { my ($dirName) = @_; my @createdDirs = (); $!=0; if (! -e $dirName) { #eval {@createdDirs = mkpath($dirName, 0, 0777)}; @createdDirs = mkpath($dirName, 1, 0777); if (! -e $dirName) { abort("mkdir of '$dirName'", $!, "$!"); } } else { abort("overwrite of '$dirName'", 1, "1"); } } # # pre-clone built-in-clonable (e.g., db 10g) homes. pre-cloning installs oui # non-oracle-home components used by the clone, if needed. # sub preCloneHome($$$) { my ($destHomeLocation, # dest home dir, e.g., /private/ora92Clone $destHomeName, # dest home name, e.g., ora92Clone $scratchLocation, # scratch dir, e.g., /tmp/oemchd123 ) = @_; my $clonerStageName = 'ClonerStage.zip'; my $scratchClonerStage = $scratchLocation . '/' . $clonerStageName; my $oracleHome = $ENV{"ORACLE_HOME"}; my $clonerStageTop = $scratchLocation . '/ClonerStage'; my @clonerStages = getClonerStageList($destHomeLocation); foreach my $cs (@clonerStages) { print("\n\n#####\n"); chomp($cs); print("copy($cs, $scratchClonerStage)\n"); copy($cs, $scratchClonerStage) == 1 or abort("copying '$cs", $!, "$!"); processClonerStage($destHomeLocation, $destHomeName, $scratchLocation, $clonerStageName); if(!onWindows()) { addToOUIInv($destHomeLocation); } chdir($scratchLocation) or abort("cd to '$scratchLocation'", $!, "$!"); removeDirTree($clonerStageTop); } } # # prepare source home - make scratch dir, list excluded files, export home # sub prepareSourceHomeEx($$$$$$$$) { my ($listExcludedFiles, # 'true' if must list files to exclude from copy $someDestsRemote, # 'true' if some clone destinations on other hosts $sourceExcludes, # patterns/files to exclude, e.g., '*.dbf, *.log' $scratchPath, # path of source scratch dir, e.g., /tmp/oemchs123 $homeLocation, # source home dir, e.g., /private/ora10g $excludeListFile, # file listing excluded files, e.g., /tmp/eList.txt $archiveFilePath, # full path of home archive, e.g., /tmp/homeArchive $useZIP # TRUE/FALSE, if true use zip archive ) = @_; #run prepare_clone.pl only if not ias if(($ENV{'HOME_TYPE'} ne "ias") && ($ENV{'HOME_TYPE'} ne "crs") && ( -e File::Spec -> catfile ( $homeLocation, "clone", "bin", "prepare_clone.pl"))) { print("chdir($homeLocation)\n"); chdir($homeLocation) or abort("cd to '$homeLocation'", $!, "$!"); echodo(getQuotedCommand($^X) . " " . getDirPath("clone", "bin", "prepare_clone.pl") . " ORACLE_HOME=\"$homeLocation\" 2>&1"); checkOuiStatus($?, "prepare_clone.pl"); } # if necessary, create temp working dir. Highly unlikely, # but if a dir named this already exists, fail job if (($listExcludedFiles eq "true") || ($someDestsRemote eq "true")) { makeNewDir($scratchPath); } # list excluded files if necessary if ($listExcludedFiles eq "true") { listExcludedFiles( $homeLocation, $scratchPath, $excludeListFile, $sourceExcludes); } # export home if necessary if ($someDestsRemote eq "true") { exportHomeEx( $homeLocation, $archiveFilePath, $excludeListFile, $sourceExcludes, $useZIP); } } # # prepare source home - make scratch dir, list excluded files, export home # sub prepareSourceHome($$$$$$$) { my ($listExcludedFiles, # 'true' if must list files to exclude from copy $someDestsRemote, # 'true' if some clone destinations on other hosts $sourceExcludes, # patterns/files to exclude, e.g., '*.dbf, *.log' $scratchPath, # path of source scratch dir, e.g., /tmp/oemchs123 $homeLocation, # source home dir, e.g., /private/ora10g $excludeListFile, # file listing excluded files, e.g., /tmp/eList.txt $archiveFilePath # full path of home archive, e.g., /tmp/homeArchive ) = @_; #run prepare_clone.pl only if not ias if(($ENV{'HOME_TYPE'} ne "ias") && ($ENV{'HOME_TYPE'} ne "crs") && ( -e File::Spec -> catfile ( $homeLocation, "clone", "bin", "prepare_clone.pl"))) { print("chdir($homeLocation)\n"); chdir($homeLocation) or abort("cd to '$homeLocation'", $!, "$!"); echodo(getQuotedCommand($^X) . " " . getDirPath("clone", "bin", "prepare_clone.pl") . " ORACLE_HOME=\"$homeLocation\" 2>&1"); checkOuiStatus($?, "prepare_clone.pl"); } # if necessary, create temp working dir. Highly unlikely, # but if a dir named this already exists, fail job if (($listExcludedFiles eq "true") || ($someDestsRemote eq "true")) { makeNewDir($scratchPath); } # list excluded files if necessary if ($listExcludedFiles eq "true") { listExcludedFiles( $homeLocation, $scratchPath, $excludeListFile, $sourceExcludes); } # export home if necessary if ($someDestsRemote eq "true") { exportHome( $homeLocation, $archiveFilePath, $excludeListFile, $sourceExcludes); } } # # prepare AS source home - prepare_clone.pl, prepareSourceHome # sub prepareASSourceHome($$$$$$$$$) { my ($listExcludedFiles, # 'true' if must list files to exclude from copy $someDestsRemote, # 'true' if some clone destinations on other hosts $sourceExcludes, # patterns/files to exclude, e.g., '*.dbf, *.log' $scratchPath, # path of source scratch dir, e.g., /tmp/oemchs123 $homeLocation, # source home dir, e.g., /private/ora10g $oidAdmin, # oid admin username(cn=orcladmin) $oidAdminPassword, # oid admin password $excludeListFile, # file listing excluded files, e.g., /tmp/eList.txt $archiveFilePath # full path of home archive, e.g., /tmp/homeArchive ) = @_; if( -e File::Spec -> catfile ( $homeLocation, "clone", "bin", "prepare_clone.pl")) { # run prepareClone.pl # since double-quoting the commands in the echodo's fails, get the unzip dir # then chdir there in case path contains embedded blanks print("chdir($homeLocation)\n"); chdir($homeLocation) or abort("cd to '$homeLocation'", $!, "$!"); my $optional = ($oidAdminPassword ne "") ? "-oid_obf_password $oidAdminPassword -oid_admin $oidAdmin" : ""; ##### TBD need to test with agent home location containing an embedded space echodo(getQuotedCommand($^X) . " " . getDirPath("clone", "bin", "prepare_clone.pl") . " ORACLE_HOME=\"$homeLocation\" $optional 2>&1"); checkOuiStatus($?, "preparing source AS Home"); } #set this so that prepare_clone not run again in prepareSourceHome $ENV{'HOME_TYPE'} = "ias"; #call generic prepareSourceHome prepareSourceHome($listExcludedFiles, $someDestsRemote, $sourceExcludes, $scratchPath, $homeLocation, $excludeListFile, $archiveFilePath); } # # prepare CRS source home - prepare_clone.pl, prepareSourceHome # sub prepareCRSSourceHomeEx($$$$$$$$) { my ($listExcludedFiles, # 'true' if must list files to exclude from copy $someDestsRemote, # 'true' if some clone destinations on other hosts $sourceExcludes, # patterns/files to exclude, e.g., '*.dbf, *.log' $scratchPath, # path of source scratch dir, e.g., /tmp/oemchs123 $homeLocation, # source home dir, e.g., /private/ora10g $excludeListFile, # file listing excluded files, e.g., /tmp/eList.txt $archiveFilePath, # full path of home archive, e.g., /tmp/homeArchive $useZIP # TRUE/FALSE ) = @_; # run prepareClone.pl # since double-quoting the commands in the echodo's fails, get the unzip dir # then chdir there in case path contains embedded blanks print("chdir($homeLocation)\n"); chdir($homeLocation) or abort("cd to '$homeLocation'", $!, "$!"); ##### TBD need to test with agent home location containing an embedded space if( -e File::Spec -> catfile ( $homeLocation, "clone", "bin", "prepare_clone.pl")) { echodo(getQuotedCommand($^X) . " " . getDirPath("clone", "bin", "prepare_clone.pl") . " ORACLE_HOME=\"$homeLocation\" 2>&1"); checkOuiStatus($?, "preparing source CRS Home"); } #set this so that prepare_clone not run again in prepareSourceHome $ENV{'HOME_TYPE'} = "crs"; #call generic prepareSourceHome prepareSourceHomeEx($listExcludedFiles, $someDestsRemote, $sourceExcludes, $scratchPath, $homeLocation, $excludeListFile, $archiveFilePath, $useZIP); } # # prepare CRS source home - prepare_clone.pl, prepareSourceHome # sub prepareCRSSourceHome($$$$$$$) { my ($listExcludedFiles, # 'true' if must list files to exclude from copy $someDestsRemote, # 'true' if some clone destinations on other hosts $sourceExcludes, # patterns/files to exclude, e.g., '*.dbf, *.log' $scratchPath, # path of source scratch dir, e.g., /tmp/oemchs123 $homeLocation, # source home dir, e.g., /private/ora10g $excludeListFile, # file listing excluded files, e.g., /tmp/eList.txt $archiveFilePath # full path of home archive, e.g., /tmp/homeArchive ) = @_; # run prepareClone.pl # since double-quoting the commands in the echodo's fails, get the unzip dir # then chdir there in case path contains embedded blanks print("chdir($homeLocation)\n"); chdir($homeLocation) or abort("cd to '$homeLocation'", $!, "$!"); ##### TBD need to test with agent home location containing an embedded space if( -e File::Spec -> catfile ( $homeLocation, "clone", "bin", "prepare_clone.pl")) { echodo(getQuotedCommand($^X) . " " . getDirPath("clone", "bin", "prepare_clone.pl") . " ORACLE_HOME=\"$homeLocation\" 2>&1"); checkOuiStatus($?, "preparing source CRS Home"); } #set this so that prepare_clone not run again in prepareSourceHome $ENV{'HOME_TYPE'} = "crs"; #call generic prepareSourceHome prepareSourceHome($listExcludedFiles, $someDestsRemote, $sourceExcludes, $scratchPath, $homeLocation, $excludeListFile, $archiveFilePath); } # # fix up 10.1.3.* AS homes # sub updateAS1013CloneHome($$$$$$) { my ($destHomeLocation, # dest home dir, e.g., /private/ora1012Clone $destHomeName, # dest home name, e.g., ora1012Clone $scratchLocation, # scratch dir, e.g., /tmp/oemchd123 $iasInstance, # instance name $oldOC4JAdminPassword, # old oc4j admin password $newOC4JAdminPassword # new oc4j admin password ) = @_; my $optional = ""; $optional = $optional.(($oldOC4JAdminPassword ne "") ? " -oc4jadmin_obf_old_password $oldOC4JAdminPassword " : ""); $optional = $optional.(($newOC4JAdminPassword ne "") ? " -oc4jadmin_obf_new_password $newOC4JAdminPassword " : ""); runUpdateASCloneHomeSteps($destHomeLocation, $destHomeName, $scratchLocation, $iasInstance, $optional); } # # fix up non-10.1.3.* AS homes e.g. Oracle AS 10.1.2 # sub updateASCloneHome($$$$$$$) { my ($destHomeLocation, # dest home dir, e.g., /private/ora1012Clone $destHomeName, # dest home name, e.g., ora1012Clone $scratchLocation, # scratch dir, e.g., /tmp/oemchd123 $iasInstance, # instance name $oldIASAdminPassword, # old ias admin password $newIASAdminPassword, # new ias admin password $oidAdminPassword, # oid admin password $dcmSchemaPassword, # dcm schema password used for DB-based management of clusters ) = @_; #-ias_admin_obf_old_pwd oldIASAdminPassword -ias_admin_obf_new_pwd newIASAdminPassword -oid_obf_password oidPassword -dcm_schema_obf_pwd dcmSchemaPassword my $optional = ""; $optional = ($oldIASAdminPassword ne " ") ? "-ias_admin_obf_old_pwd $oldIASAdminPassword " : ""; $optional = $optional. (($newIASAdminPassword ne " ") ? "-ias_admin_obf_new_pwd $newIASAdminPassword " : ""); $optional = $optional. (($oidAdminPassword ne "") ? "-oid_obf_password $oidAdminPassword " : ""); $optional = $optional. (($dcmSchemaPassword ne "") ? "-dcm_schema_obf_pwd $dcmSchemaPassword " : ""); runUpdateASCloneHomeSteps($destHomeLocation, $destHomeName, $scratchLocation, $iasInstance, $optional); } # # run steps to fix up all kinds of AS homes. # sub runUpdateASCloneHomeSteps($$$$$) { my ($destHomeLocation, # dest home dir, e.g., /private/ora1012Clone $destHomeName, # dest home name, e.g., ora1012Clone $scratchLocation, # scratch dir, e.g., /tmp/oemchd123 $iasInstance, # instance name $additionalParameters # additional parameters to be passed to clone command line. ) = @_; # clear CONSOLE_CFG for the benefit of iasconsole delete($ENV{'CONSOLE_CFG'}); delete($ENV{'EMSTATE'}); # since double-quoting the commands in the echodo's fails, get the unzip dir # then chdir there in case path contains embedded blanks print("chdir($destHomeLocation)\n"); chdir($destHomeLocation) or abort("cd to '$$destHomeLocation'", $!, "$!"); if(onWindows()) { echodo(getQuotedCommand($^X). " " .getDirPath("clone", "bin", "clone.pl") . " ORACLE_HOME=\"$destHomeLocation\" ORACLE_HOME_NAME=\"$destHomeName\" -instance $iasInstance $additionalParameters \"-O-noconsole \" 2>&1"); } else { echodo(getQuotedCommand($^X). " " .getDirPath("clone", "bin", "clone.pl") . " ORACLE_HOME=\"$destHomeLocation\" ORACLE_HOME_NAME=\"$destHomeName\" -instance $iasInstance $additionalParameters 2>&1"); } #echodo(getQuotedCommand($^X). " " .getDirPath("clone", "bin", "clone.pl") . " ORACLE_HOME=\"$destHomeLocation\" ORACLE_HOME_NAME=\"$destHomeName\" -instance $iasInstance $additionalParameters 2>&1"); checkOuiStatus($?, "clone.pl"); #Add the cloned home to OUIinventories if(!onWindows()) { addToOUIInv($destHomeLocation); } # remove dest temp files chdir($destHomeLocation); removeDirTree($scratchLocation); } # # fix up cloned RAC homes for DB 10g # sub updateRACCloneHome($$$$$$) { my ($destHomeLocation, # dest home dir, e.g., /private/ora1012Clone $destHomeName, # dest home name, e.g., ora1012Clone $scratchLocation, # scratch dir, e.g., /tmp/oemchd123 $clusterNodes, # all nodes of the RAC cluster $destParams, # user-supplied computeAtClone params & values $destParamsSecure # secure user-supplied computeAtClone params & values ) = @_; #print "ClusterNodes:\{$clusterNodes\}\n"; # add all the oui jars to classpath in case oui adds others in the future my $classPath = getClassPathWithJars("$destHomeLocation/oui/jlib", "true"); $classPath .= "\"$destHomeLocation/jlib/emCfg.jar\""; if (!onWindows()) { # NOTE: fix this for non-solaris platforms # TBD test embedded spaces in home location my $myplatform = "solaris"; if ($^O eq "linux") { $myplatform = "linux"; } $ENV{'LD_LIBRARY_PATH'} = "$destHomeLocation/oui/lib/$myplatform:" . "$ENV{'LD_LIBRARY_PATH'}"; #print("\$ENV{'LD_LIBRARY_PATH'}=$ENV{'LD_LIBRARY_PATH'}\n"); } # find dest home oui's jre and use its jre/bin/java to call oui updateHome() my $javaHome = getJavaHome($destHomeLocation); print("\nchdir($javaHome)\n"); chdir($javaHome) or abort("cd to '$javaHome'", $!, "$!"); my $d64_opt; if(is64BitHybridJava($ENV{EMDROOT})) { $d64_opt = "-d64"; } my $ouiLoc = "$destHomeLocation/oui"; my $statusFilePath = $scratchLocation . '/updateHomeCompleted.txt'; my $systemCommand="| " . getDirPath("bin", "java") . " $d64_opt -Doracle.installer.oui_loc=$ouiLoc -cp $classPath oracle.sysman.emd.ecm.clone.DestEnvironment -updateRacHome"; print("\n$systemCommand\n"); $! = 0; open(UPDATER, "$systemCommand") || abort("fork", $!, "$!"); local $SIG{PIPE} = sub { abort("pipe", $!, "$!") }; print UPDATER "$destHomeName\n"; print UPDATER "$destHomeLocation\n"; print UPDATER "\{$clusterNodes\}\n"; print UPDATER "$destParams\n"; print UPDATER "$destParamsSecure\n"; print UPDATER "$statusFilePath\n"; my $status = close UPDATER; my $updateStatus = $?; if (!$status) { if ($!) { #abort("updater process", $!, "$!"); main::warning($!, "error closing pipe to updater process: $!"); } } if (-e $statusFilePath) { # got through oui's updateHome(), check status from that checkOuiStatus($updateStatus, "update of rac home"); } else { abort("update of home", $updateStatus >> 8, "$updateStatus >> 8"); } #Add the cloned home to OUIinventories if(!onWindows()) { addToOUIInv($destHomeLocation); } # remove dest temp files removeDirTree($scratchLocation); } # # fix up cloned RAC homes for DB 10g, not used right now! # sub updateRACHome($$$$$$$) { my ($destHomeLocation, # dest home dir, e.g., /private/ora1012Clone $destHomeName, # dest home name, e.g., ora1012Clone $scratchLocation, # scratch dir, e.g., /tmp/oemchd123 $clusterNodes, # all nodes of the RAC cluster $localNode, # local node which OUI uses $destParams, # user-supplied computeAtClone params & values $destParamsSecure # secure user-supplied computeAtClone params & values ) = @_; my $clonepl = File::Spec -> catfile ( $destHomeLocation, "clone", "bin", "clone.pl" ); my $oui = ""; if (!onWindows()) { $oui = "runInstaller"; } else { $oui = "setup.exe"; } my $runInstaller = File::Spec -> catfile ( $destHomeLocation, "oui", "bin", "$oui" ); #print("\n destParams-->$destParams\n"); #print("\n destParamsSecure-->$destParamsSecure\n"); #for oracle base bug fix if (isEmpty($destParams)) { $destParams = ""; } if (isEmpty($destParamsSecure)) { $destParamsSecure = ""; } if( -e $clonepl ) { #call clone.pl my $dir = File::Spec -> catfile ( $destHomeLocation, "clone", "bin"); print("chdir($dir)\n"); chdir($dir) or abort("cd to '$$dir'", $!, "$!"); echodo(getQuotedCommand($^X) . " " . getDirPath("clone.pl") . " -waitForCompletion ORACLE_HOME=\"$destHomeLocation\" ORACLE_HOME_NAME=\"$destHomeName\" \"CLUSTER_NODES={$clusterNodes}\" LOCAL_NODE=$localNode $destParams $destParamsSecure 2>&1"); checkOuiStatus($?, "clone.pl"); } elsif ( -e $runInstaller ) { my $ouiParams = "-clone -silent -waitForCompletion -noConfig"; if (onWindows()) { $ouiParams = "$ouiParams -nowait"; } #call runInstaller my $dir = File::Spec -> catfile ( $destHomeLocation, "oui", "bin"); print("chdir($dir)\n"); chdir($dir) or abort("cd to '$$dir'", $!, "$!"); #need to remove back slashes if calling from runInstaller directly $clusterNodes =~ s/\\//g; echodo(getDirPath($oui) . " $ouiParams ORACLE_HOME=\"$destHomeLocation\" ORACLE_HOME_NAME=\"$destHomeName\" \"CLUSTER_NODES={$clusterNodes}\" LOCAL_NODE=$localNode $destParams $destParamsSecure 2>&1"); checkOuiStatus($?, "$oui clone mode"); } else { main::err(1, "$oui not found."); } # remove dest temp files chdir($destHomeLocation); removeDirTree($scratchLocation); } # # method to run attachHome for a RAC Home (gpalrech) # sub attachHomeRACHome($$$$$) { my ( $destHomeLocation, # dest home dir, e.g., /private/ora1012Clone $destHomeName, # dest home name, e.g., ora1012Clone $scratchLocation, # scratch dir, e.g., /tmp/oemchd123 $clusterNodes, # all nodes of the RAC cluster $localNode, # local node which OUI uses ) = @_; my $oui = ""; if (!onWindows()) { $oui = "runInstaller"; } else { $oui = "setup.exe"; } my $runInstaller = File::Spec -> catfile ( $destHomeLocation, "oui", "bin", "$oui" ); if ( -e $runInstaller ) { my $ouiParams = "-attachHome -silent -waitForCompletion"; if (onWindows()) { $ouiParams = "$ouiParams -nowait"; } #call runInstaller my $dir = File::Spec -> catfile ( $destHomeLocation, "oui", "bin"); print("chdir($dir)\n"); chdir($dir) or abort("cd to '$$dir'", $!, "$!"); #need to remove back slashes if calling from runInstaller directly $clusterNodes =~ s/\\//g; $clusterNodes =~ s/\"//g; echodo(getDirPath($oui) . " $ouiParams ORACLE_HOME=\"$destHomeLocation\" ORACLE_HOME_NAME=\"$destHomeName\" \"CLUSTER_NODES=$clusterNodes\" LOCAL_NODE=$localNode 2>&1"); checkOuiStatus($?, "$oui clone (attachHome) mode"); } else { main::err(1, "$oui not found."); } # remove dest temp files chdir($destHomeLocation); removeDirTree($scratchLocation); } sub getShortHostName() { my $host = hostname; my ($short, $remain) = split("\\.", $host, 2); return $short; } # # fix up cloned CRS homes for DB 10g # sub updateCRSHome($$$$$$$$$$$$$) { my ($destHomeLocation, # dest home dir, e.g., /private/ora1012Clone $destHomeName, # dest home name, e.g., ora1012Clone $scratchLocation, # scratch dir, e.g., /tmp/oemchd123 $extendMode, # create or extend mode $hostnames, # all hostnames of the CRS cluster $clusterNodes, # all nodes of the CRS cluster $tableList, # sl_tableList $clusterName, # name to register with em $ocrLoc, # OCR location $vdiskLoc, # Voting Disk location $localNode, # local node which OUI uses $destParams, # user-supplied computeAtClone params & values $destParamsSecure # secure user-supplied computeAtClone params & values ) = @_; my $shortHostname = getShortHostName(); my $createModeParams = ""; my $extendModeParams = ""; my $sourceTableList = ""; if($extendMode eq "false") #create mode { $createModeParams = "n_storageTypeVDSK=2 n_storagetypeOCR=2 oracle.crs:s_clustername=\"$clusterName\""; if(onWindows()) { #this param is only required for windows for all nodes except the first. my $hostname = hostfqdn(); if ($hostnames !~ /^$hostname$/ && $hostnames !~ /^$hostname,/) { #this node does not occur singly or before a comma. $createModeParams = "$createModeParams PERFORM_PARTITION_TASKS=FALSE"; } } else { #add ocr/vdisk location for non-windows. $createModeParams = "$createModeParams s_ocrpartitionlocation=\"$ocrLoc\" s_votingdisklocation=\"$vdiskLoc\""; } } elsif(($extendMode eq "true") && onWindows()) { #this param is only required for windows $extendModeParams = "PERFORM_PARTITION_TASKS=FALSE"; } if (isEmpty($destParams)) { $destParams = "ORACLE_BASE=".$destHomeLocation; } if (isEmpty($destParamsSecure)) { $destParamsSecure = ""; } my $cmdLine = " -waitForCompletion ORACLE_HOME=\"$destHomeLocation\" ORACLE_HOME_NAME=\"$destHomeName\" $createModeParams $extendModeParams \"sl_tableList={$tableList}\" ORACLE_HOSTNAME=$shortHostname $destParams $destParamsSecure -noConfig 2>&1"; my $clonepl = File::Spec -> catfile ( $destHomeLocation, "clone", "bin", "clone.pl" ); my $oui = ""; if (!onWindows()) { $oui = "runInstaller"; } else { $oui = "setup.exe"; } my $runInstaller = File::Spec -> catfile ( $destHomeLocation, "oui", "bin", "$oui" ); if( -e $clonepl ) { #call clone.pl my $dir = File::Spec -> catfile ( $destHomeLocation, "clone", "bin"); print("chdir($dir)\n"); chdir($dir) or abort("cd to '$$dir'", $!, "$!"); echodo(getQuotedCommand($^X) . " " . getDirPath("clone.pl") .$cmdLine ); checkOuiStatus($?, "clone.pl"); } elsif ( -e $runInstaller ) { if (onWindows()) { $cmdLine = " -nowait $cmdLine"; } #call runInstaller my $dir = File::Spec -> catfile ( $destHomeLocation, "oui", "bin"); print("chdir($dir)\n"); chdir($dir) or abort("cd to '$$dir'", $!, "$!"); echodo(getDirPath($oui) . " -clone -silent ". $cmdLine); checkOuiStatus($?, "$oui clone mode"); } else { main::err(1, "$oui not found."); } #Add the cloned home to OUIinventories if(!onWindows()) { addToOUIInv($destHomeLocation); } # remove dest temp files chdir($destHomeLocation); removeDirTree($scratchLocation); } # # updateNodeList on source RAC node to add new nodes to their node list # sub updateNodeList($$) { my ($homeLocation, # dest home dir, e.g., /private/ora1012Clone $nodes ) = @_; my $clonepl = File::Spec -> catfile ( $homeLocation, "clone", "bin", "clone.pl" ); my $oui = ""; if (!onWindows()) { $oui = "runInstaller"; } else { $oui = "setup.exe"; } #call runInstaller my $dir = File::Spec -> catfile ( $homeLocation, "oui", "bin"); print("chdir($dir)\n"); chdir($dir) or abort("cd to '$$dir'", $!, "$!"); #need to remove back slashes if calling from runInstaller directly my $ouiParams = "-updateNodeList -silent -waitForCompletion"; if (onWindows()) { $ouiParams = "$ouiParams -nowait"; } $nodes =~ s/\\//g; echodo(getDirPath("$oui") . " $ouiParams ORACLE_HOME=\"$homeLocation\" \"CLUSTER_NODES={$nodes}\" 2>&1"); checkOuiStatus($?, "$oui updateNodeList"); } sub addNode($$$$) { my ($homeLocation, $newNodes, $newPvtNodes, $newVips) = @_; my $addNode = ""; my $checkfile = ""; if (!onWindows()) { $checkfile = File::Spec -> catfile ( $homeLocation, "install", "rootaddnode.sh"); #Delete rootaddnode.sh if it exists unlink $checkfile || abort("Delete $checkfile", $!, "Unable to delete $checkfile file") ; $addNode = "addNode.sh"; } else { $checkfile = File::Spec -> catfile ( $homeLocation, "install", "crssetup.add.bat"); #Delete crssetup.add.bat if it exists unlink $checkfile || abort("Delete $checkfile", $!, "Unable to delete $checkfile file") ; $addNode = "addNode.bat -noRemoteActions -nowait"; } #call addNode my $dir = File::Spec -> catfile ( $homeLocation, "oui", "bin"); print("chdir($dir)\n"); chdir($dir) or abort("cd to '$$dir'", $!, "$!"); my $cmdLine = " -silent -noCopy \"CLUSTER_NEW_NODES={$newNodes}\" \"CLUSTER_NEW_PRIVATE_NODE_NAMES={$newPvtNodes}\" \"CLUSTER_NEW_VIRTUAL_HOSTNAMES={$newVips}\" "; echodo(getDirPath($addNode) . $cmdLine); #checkOuiStatus($?, "$addNode"); returning exit status 255 even on success, as of on 18-may-2005 #Non-existance of checkfile is an indication of failure. abort("$cmdLine", -1, "Add node operation failed.") if (!-e $checkfile); #if windows, then run crssetup.add.set(Windows equivalent of rootaddnode.sh) if (onWindows()) { $dir = File::Spec -> catfile ( $homeLocation, "install"); print("chdir($dir)\n"); chdir($dir) or abort("cd to '$$dir'", $!, "$!"); my $crssetup = "crssetup.add.bat"; echodo(getDirPath($crssetup)); } } #remmove this if not needed, was required to pass LOCAL_NODE to addnode.sh due to a bug which was fixed sub getLocalNode($) { my ($crsHome) = @_; my $localnode ; my $OLSNODES_CMD; if (onWindows()) { $OLSNODES_CMD = File::Spec->catfile($crsHome, "bin", "olsnodes.exe -l"); } else { $OLSNODES_CMD = File::Spec->catfile($crsHome, "bin", "olsnodes -l"); } my $pid = open (READ, " $OLSNODES_CMD |"); my @array = ; close READ; my $status = $?; if ($status != 0) { abort(); } $localnode = $array[0]; chomp($localnode); return $localnode; } # # expand ClonerStage residing at scratchLocation, then invoke its clone.pl # sub processClonerStage($$$$) { my ($destHomeLocation, # dest home dir, e.g., /private/ora92Clone $destHomeName, # dest home name, e.g., ora92Clone $scratchLocation, # scratch dir, e.g., /tmp/oemchd123 $clonerStageName # scratch ClonerStage name, e.g., ClonerStage.zip ) = @_; my $scratchClonerStage = $scratchLocation . '/' . $clonerStageName; my $oracleHome = $ENV{"ORACLE_HOME"}; my $clonerStageTop = $scratchLocation . '/ClonerStage'; # since double-quoting the commands in the echodo's fails, get the unzip dir # then chdir there in case path contains embedded blanks print("chdir($oracleHome)\n"); chdir($oracleHome) or abort("cd to '$oracleHome'", $!, "$!"); echodo(getDirPath("bin", "unzip") . " -o -q \"$scratchClonerStage\" -d \"$scratchLocation\"") == 0 or abort("expandClonerStage", $? >> 8, "$!"); chdir($clonerStageTop) or abort("cd to '$clonerStageTop'", $!, "$!"); ##### TBD need to test with agent home location containing an embedded space echodo(getQuotedCommand($^X) . " " . getDirPath("clone.pl") . " ORACLE_HOME=\"$destHomeLocation\" ORACLE_HOME_NAME=\"$destHomeName\" 2>&1"); checkOuiStatus($?, "ClonerStage clone.pl"); } # # remove a directory tree and display count of files deleted # sub removeDirTree($) { my ($dirPath, # directory path, e.g., /tmp/oemchd123 ) = @_; print("\nrmtree($dirPath, 0, 0)\n"); my $deletedCount = rmtree($dirPath, 0, 0); print("$deletedCount\n"); } # Check if the user has read/write permission for the specified directory # Return OK if the user has read/write permission, otherwise, return NOK. # dirPermission(dirName) sub dirPermission { my ($dirName) = @_; if(! -r "$dirName") { EMD_PERL_DEBUG("ecmCloneHome.dirPermission(): UID $> does not have read permission for $dirName"); return "NOK"; } if(! -w _) { EMD_PERL_DEBUG("ecmCloneHome.dirPermission(): UID $> does not have write permission for $dirName"); return "NOK"; } EMD_PERL_DEBUG("ecmCloneHome.dirPermission(): UID $> has read/write permission for $dirName"); return "OK"; } # Check if the user has read/write permission for the multiple directories. # Return an array containing OK and NOK. # Flag OK is returned if user has read/write permission, otherwise, NOK is returned. # dirsPermission(dirNameArray) sub dirsPermission { my ($dirNameArray) = @_; my @dirNames = split /$DELIMITER/, $dirNameArray; my $permissionStatus = ""; my $dirNames; foreach $dirNames (@dirNames) { if(! -r "$dirNames") { EMD_PERL_DEBUG("ecmCloneHome.dirsPermission(): UID $> does not have read permission for $dirNames"); $permissionStatus .= "NOK:"; } elsif(! -w "$dirNames") { EMD_PERL_DEBUG("ecmCloneHome.dirsPermission(): UID $> does not have write permission for $dirNames"); $permissionStatus .= "NOK:"; } else { EMD_PERL_DEBUG("ecmCloneHome.dirsPermission(): UID $> has read/write permission for $dirNames"); $permissionStatus .= "OK:"; } } return $permissionStatus; } # --------- OS platform-specific (for "getFreeSpace" only) ------------- # Run command $df, the free space information shows at $row (usually the last # row) and $column. If the unit is K-bytes, $divide = 1, if bytes, $divide = 1024. # paramForGetFreeSpace() sub paramForGetFreeSpace { my $df = ""; my $row = ""; my $column = ""; my $divide = ""; if($^O =~ /MSWin32/i) { EMD_PERL_DEBUG("ecmCloneHome.paramForGetFreeSpace(): OS platform: MSWin32"); $ENV{dircmd}=""; my $cmd = $ENV{ComSpec}." /c"; $df = "$cmd dir /ad /-c"; $row = -1; #For XP, 2000, 2003 etc. $column = 2; my $winVer= `ver`; if(($winVer =~ "NT")) { $column = 0; } $divide = 1024; } # This should cover all UNIX variants else #may be Unix { EMD_PERL_DEBUG("ecmCloneHome.paramForGetFreeSpace(): OS platform: UNIX"); $df = "$DF ."; $row = -1; $column = 3; $divide = 1; } return ($df, $row, $column, $divide); } # --------- OS platform-specific (END) ----------------------------------- # Check if a specified directory exists # Return OK if the directory exists, otherwise, return NOK. # dirExists(dirName) sub dirExists { my ($dirName) = @_; if(! -e "$dirName") { EMD_PERL_DEBUG("ecmCloneHome.dirExists(): Directory $dirName does not exist"); return "NOK"; } elsif(! -d "$dirName") { EMD_PERL_DEBUG("ecmCloneHome.dirExists(): $dirName is not a directory"); return "NOK"; } EMD_PERL_DEBUG("ecmCloneHome.dirExists(): Directory $dirName exists"); return "OK"; } # Find the nearest existing parent dir for a given dir. # Return dir found, otherwise, return "". # findNearestExistingParentDir(dirName) sub findNearestExistingParentDir { my ($dirName) = @_; EMD_PERL_DEBUG("ecmCloneHome.findNearestExistingParentDir(): Find nearest existing dir for $dirName"); my $dirExist = &dirExists($dirName); if($dirExist eq "OK") { EMD_PERL_DEBUG("ecmCloneHome.findNearestExistingParentDir(): Directory $dirName already exists"); return $dirName; } my($parent) = dirname($dirName); if($parent eq "/" || $parent =~ /:$/ || $parent eq "" || $parent eq ".") { return $parent; } while(! -e "$parent") { EMD_PERL_DEBUG("ecmCloneHome.findNearestExistingParentDir(): $parent does not exist"); $parent = dirname($parent); if($parent eq "/" || $parent =~ /:$/ || $parent eq "" || $parent eq ".") { return $parent; } } return $parent; } # This method is platform specific, will be dealt with later. # Get free space (KB) for a given directory # getFreeSpace(dirName) sub getFreeSpace { my ($dirName) = @_; EMD_PERL_DEBUG("ecmCloneHome.getFreeSpace(): Passed in dir: $dirName"); $dirName = &findNearestExistingParentDir($dirName); EMD_PERL_DEBUG("ecmCloneHome.getFreeSpace(): cd to the nearest existing parent dir: $dirName"); chdir($dirName) or (((EMD_PERL_ERROR("ecmCloneHome.getFreeSpace(): chdir $dirName failed")) && return "-1") || (return "-1")); my $freeKB = 0; (my $df, my $row, my $column, my $divide) = ¶mForGetFreeSpace(); EMD_PERL_DEBUG("ecmCloneHome.getFreeSpace(): df: $df, row: $row, column: $column, divide: $divide"); my @temp = `$df`; $_ = $temp[$row]; my @tokens = split; if(($^O !~ /MSWin32/i) && (@temp == 3)){ EMD_PERL_DEBUG("\tdf output on three lines\n"); $column = 2; } $freeKB = $tokens[$column]/$divide; if("$freeKB" eq "") { EMD_PERL_ERROR("ecmCloneHome.getFreeSpace(): Could not get free space: $!"); $freeKB = -1; } EMD_PERL_DEBUG("ecmCloneHome.getFreeSpace(): Free space (KB) in $dirName: $freeKB"); return $freeKB; } # # pre-clone and/or fix up an ad-hoc-clonable home, e.g., rdbms 9.2.0.4.0 home # # WARNING: deletes the $scratchLocation directory tree. # sub updateAdHocClonable($$$$) { my ($destHomeLocation, # dest home dir, e.g., /private/ora92Clone $destHomeName, # dest home name, e.g., ora92Clone $scratchLocation, # scratch dir, e.g., /tmp/oemchd123 $clonerStageName # scratch ClonerStage name, e.g., ClonerStage.zip ) = @_; my $scratchClonerStage = $scratchLocation . '/' . $clonerStageName; my $oracleHome = $ENV{"ORACLE_HOME"}; my $clonerStageTop = $scratchLocation . '/ClonerStage'; processClonerStage($destHomeLocation, $destHomeName, $scratchLocation, $clonerStageName); #Add the cloned home to OUIinventories if(!onWindows()) { addToOUIInv($destHomeLocation); } # remove dest temp files chdir($oracleHome); removeDirTree($scratchLocation); } # # fix up a built-in-clonable home, e.g., an rdbms 10g home # # WARNING: deletes the $scratchLocation directory tree. # sub updateBuiltInClonable($$$$$) { my ($destHomeLocation, # dest home dir, e.g., /private/ora92Clone $destHomeName, # dest home name, e.g., ora92Clone $scratchLocation, # scratch dir, e.g., /tmp/oemchd123 $clonerStageInHome, # 'true' if home has any ClonerStages $destParams, # user-supplied computeAtClone params & values $destParamsSecure # secure user-supplied computeAtClone params & values ) = @_; if (homeNeedsPreCloning($destHomeLocation)) { if ($clonerStageInHome ) { preCloneHome($destHomeLocation, $destHomeName, $scratchLocation); } else { main::warning(1, "pre-cloning required, but no ClonerStage in home"); } } my $clonepl = File::Spec -> catfile ( $destHomeLocation, "clone", "bin", "clone.pl"); my $oui = ""; if (!onWindows()) { $oui = "runInstaller"; } else { $oui = "setup.exe"; } my $runInstaller = File::Spec -> catfile ( $destHomeLocation, "oui", "bin", "$oui"); #print("\n destParams-->$destParams\n"); #print("\n destParamsSecure-->$destParamsSecure\n"); #print("\n clonepl-->$clonepl\n"); #print("\n runInstaller-->$runInstaller\n"); #for oracle base bug fix if (isEmpty($destParams)) { $destParams = ""; } if (isEmpty($destParamsSecure)) { $destParamsSecure = ""; } if( -e $clonepl ) { #call clone.pl my $dir = File::Spec -> catfile ( $destHomeLocation, "clone", "bin"); print("chdir($dir)\n"); chdir($dir) or abort("cd to '$$dir'", $!, "$!"); echodo(getQuotedCommand($^X) . " " . getDirPath("clone.pl") . " -waitForCompletion ORACLE_HOME=\"$destHomeLocation\" ORACLE_HOME_NAME=\"$destHomeName\" $destParams $destParamsSecure 2>&1"); checkOuiStatus($?, "clone.pl"); } elsif ( -e $runInstaller ) { my $ouiParams = "-clone -silent -waitForCompletion"; if (onWindows()) { $ouiParams = "$ouiParams -nowait"; } #call runInstaller my $dir = File::Spec -> catfile ( $destHomeLocation, "oui", "bin"); print("chdir($dir)\n"); chdir($dir) or abort("cd to '$$dir'", $!, "$!"); echodo(getDirPath($oui) . " $ouiParams ORACLE_HOME=\"$destHomeLocation\" ORACLE_HOME_NAME=\"$destHomeName\" $destParams $destParamsSecure 2>&1"); checkOuiStatus($?, "$oui clone mode"); } else { # add all the oui jars to classpath in case oui adds others in the future my $classPath = getClassPathWithJars("$destHomeLocation/oui/jlib", "true"); #print("\$classPath=$classPath\n"); $classPath .= "\"$destHomeLocation/jlib/emCfg.jar\""; if (!onWindows()) { # NOTE: fix this for non-solaris platforms # TBD test embedded spaces in home location my $myplatform = "solaris"; if ($^O eq "linux") { $myplatform = "linux"; $myplatform = "ia64linux" if ($Config{'archname'} =~ m/ia64-linux/); $myplatform = "linuxS390" if ($Config{'archname'} =~ m/s390x-linux/); } $myplatform = "decunix" if ($^O eq "dec_osf"); if ($^O eq "aix") { $ENV{'LIBPATH'} = "$destHomeLocation/oui/lib/aix:" . "$ENV{'LIBPATH'}"; } elsif ($^O eq "darwin") { $ENV{'DYLD_LIBRARY_PATH'} = "$destHomeLocation/oui/lib/mac_osx:" . "$ENV{'DYLD_LIBRARY_PATH'}"; } elsif ($^O eq "hpux") { $myplatform = "hpunix"; $myplatform = "ia64hpunix" if ($Config{'archname'} =~ m/IA64/); $ENV{'SHLIB_PATH'} = "$destHomeLocation/oui/lib/$myplatform:" . "$ENV{'SHLIB_PATH'}"; } else { $ENV{'LD_LIBRARY_PATH'} = "$destHomeLocation/oui/lib/$myplatform:" . "$ENV{'LD_LIBRARY_PATH'}"; #print("\$ENV{'LD_LIBRARY_PATH'}=$ENV{'LD_LIBRARY_PATH'}\n"); } } # find dest home oui's jre and use its jre/bin/java to call oui updateHome() my $javaHome = getJavaHome($destHomeLocation); print("\nchdir($javaHome)\n"); chdir($javaHome) or abort("cd to '$javaHome'", $!, "$!"); my $d64_opt; if(is64BitHybridJava($ENV{EMDROOT})) { $d64_opt = "-d64"; } my $statusFilePath = $scratchLocation . '/updateHomeCompleted.txt'; my $systemCommand="| " . getDirPath("bin", "java") . " $d64_opt -cp $classPath -Doracle.installer.oui_loc=\"$destHomeLocation/oui\" oracle.sysman.emd.ecm.clone.DestEnvironment -updateHome"; print("\n$systemCommand\n"); $! = 0; open(UPDATER, "$systemCommand") || abort("fork", $!, "$!"); local $SIG{PIPE} = sub { abort("pipe", $!, "$!") }; print UPDATER "$destHomeName\n"; print UPDATER "$destHomeLocation\n"; print UPDATER "$destParams\n"; print UPDATER "$destParamsSecure\n"; print UPDATER "$statusFilePath\n"; my $status = close UPDATER; my $updateStatus = $?; if (!$status) { if ($!) { #abort("updater process", $!, "$!"); main::warning($!, "error closing pipe to updater process: $!"); } } if (-e $statusFilePath) { # got through oui's updateHome(), check status from that checkOuiStatus($updateStatus, "update of home"); } else { abort("update of home", $updateStatus >> 8, "$updateStatus >> 8"); } } #Add the cloned home to OUIinventories if(!onWindows()) { addToOUIInv($destHomeLocation); } # remove dest temp files removeDirTree($scratchLocation); } # # Get the IAS properties from an AS installation # sub getIASProperties($) { my ($homeLocation) = @_; my $iasPropLoc = File::Spec -> catfile ( $homeLocation, "config", "ias.properties" ); my $properties = ""; open (IASPROP, $iasPropLoc) || die ("Could not open ias.properties"); { local $/; undef $/; $properties = ; } close(IASPROP); print $properties; print "ClusterName="; # if 10.1.3 home, no cluster information can be retrieved since there is no dcmctl. if ($properties =~ /Version=10\.1\.3/) { # check if clone bits are present in home and return. print "\nCloneBitsPresent="; if (-f (File::Spec -> catfile ($homeLocation, "clone", "bin", "clone.pl")) && (-f (File::Spec -> catfile ($homeLocation, "clone", "bin", "prepare_clone.pl")))) { print "true"; } else { print "false"; } return; } my $dcm = ""; if(onWindows()) { $dcm = "dcmctl.bat"; } else { $dcm = "dcmctl"; } system(File::Spec -> catfile ( $homeLocation, "dcm", "bin", "$dcm")." whichcluster"); if($?) { main::warning($! ? $! : $?, $! ? "dcm whichcluster failed: $!" : "dcm whichcluster exited with: $?"); } } # # Execute dcm joinCluster, called from clone job # sub dcmJoinCluster($$$) { my ($homeLocation, $joinCluster, $clusterName) = @_; my $dcm = ""; if($joinCluster eq "true") { if(onWindows()) { $dcm = "dcmctl.bat"; echodo(File::Spec -> catfile ( $homeLocation, "dcm", "bin", $dcm)." joinCluster -v -script $clusterName"); } else { $dcm = "dcmctl"; echodo(File::Spec -> catfile ( $homeLocation, "dcm", "bin", $dcm)." joinCluster $clusterName"); } #echodo(File::Spec -> catfile ( $homeLocation, "dcm", "bin", $dcm)." joinCluster $clusterName"); #return with exit status, so that step fails if command fails exit($? >> 8); } } sub registerCRSTarget($$) { my ($crsHome, $crsTargetName) = @_; my $emdroot = $ENV{EMDROOT}; my $emctlCmd = "emctl"; my $javaHome = getJavaHome($crsHome); print("\nchdir($javaHome)\n"); chdir($javaHome) or abort("cd to '$javaHome'", $!, "$!"); my $pathSep = "\":\""; if (onWindows()) { $pathSep = "\";\""; $emctlCmd = "emctl.bat"; } my $d64_opt; if(is64BitHybridJava($ENV{EMDROOT})) { $d64_opt = "-d64"; } my $classpath = "\"".File::Spec -> catfile ( $emdroot, "jlib", "emConfigInstall.jar").$pathSep.File::Spec -> catfile ( $emdroot, "sysman", "jlib", "emcoreAgent.jar")."\""; my $regCommand = getDirPath("bin", "java") . " $d64_opt -cp $classpath -DORACLE_HOME=\"$emdroot\" oracle.sysman.emd.ecm.clone.RegCRSCloneTgt AGENT_HOME=\"$emdroot\" CRS_TARGET_NAME=\"$crsTargetName\" CRS_HOME=\"$crsHome\""; echodo($regCommand) == 0 or abort("registerCRSTarget", $? >> 8, "$!"); chdir($emdroot) or abort("cd to '$emdroot'", $!, "$!"); echodo(getDirPath("bin", "$emctlCmd"). " reload"); } sub addToOUIInv($) { my ($oracleHome) = @_; my $oraInstLoc = File::Spec -> catfile ( $oracleHome, "oraInst.loc" ); my $ouiAdd = ""; if(-e $oraInstLoc) { $ouiAdd = File::Spec -> catfile ( $ENV{EMDROOT}, "sysman", "config", "OUIinventories.add" ); open(OUIINV, ">>".$ouiAdd) || abort("open of '$ouiAdd'", $!, "$!"); printf(OUIINV "\ninventory: %s\n", $oraInstLoc); close(OUIINV); } } #is64BitHybridJava returns the following # 1 in case ARU_ID has a platform which is 64 bit # and has a java which is hybrid # 0 in case ARU_ID is a 32/64 bit which does not have hybrid java # <0 in case oraclehomeproperties.xml file is not found. sub is64BitHybridJava() { my $oracleHome = shift; my $ohProp = "$oracleHome/inventory/ContentsXML/oraclehomeproperties.xml"; my $platID; if ( open(OHPROP, "<$ohProp") ) { my @arr = (); close OHPROP; my $line = join('',@arr); if ($line =~ m/(.*?\s*\\s*.*?)([^\s]+)(.*?\s*\<\/ARU_ID\>\s*.*?)$/s) { $platID = $2; } } else { return(0); } # 23 = SOLARIS_SPARC64 # 59 = HPUX_PARISC64 # 197 = HPUX_IA64 # 267 = SOLARIS x86-64 if(($platID == 23) || ($platID == 59) || ($platID == 197) || ($platID == 267)) { return 1; } else { return 0; } } sub updateNodeListDummy() { } 1;