# $Header: emcore/sysman/admin/scripts/osm/ecmCollectInventory.pl /stpl_db_11.2.0.1.0_gen/1 2009/09/26 01:07:43 chkaushi Exp $ # # Copyright (c) 2001, 2009, Oracle and/or its affiliates. All rights reserved. # # DESCRIPTION # collects snapshot - based on collectInventory.sh from vkhizder # # Script expects its parameters in the following order: # (* = "required parameter") # # *0: classpath - # has to include xmlparserv2.jar, emcoreAgent.jar, log4j-core.jar, and # OUI jars including OraInstaller.jar, share.jar, srvm.jar, etc. # # *1: perlBin - # perl executable location, e.g. "/private/oracle/mozart/perl/bin" # # *2: emdRoot - path of where emd is installed, e.g. "/private/oracle/mozart" # # *3: emHome - path to state home # # *4: targetName - e.g. "host.example.com" # # 5: loaderFile - file where to write out the collected snapshot, # e.g. "/private/inventory.xml". After file is written out, it # is rewritten into a file with the same name and added ".suc". # If not specified or empty, collected inventory is written # out to STDOUT # # 6: additionalInventoriesFile - filename with pointers to # additional OUI inventories (if not specified, no additional # inventories are scanned) # # 7: targetType - type of the target, # ("host" if not specified or empty) # # 8: displayTargetName - user friendly target name, # e.g. "Joe's host" (equal to targetName if not # specified or empty) # # 9: displayTargetType - user friendly target type, e.g. "Host" # (equal to targetType if not specified or empty) # # 10: snapshotType - type of the snapshot to be collected # ("host_configuration" if not specified or empty) # # 11: invPtrLoc - pointer to file containing path to default inventory # (allows tests to specify other than /var/opt/oracle/oraInst.loc) # # 12: workingDir - the directory where this script should run (useful # for tests that use inventory files containing relative paths) # # 13: ouiLoc - location of the oui directory (useful for testing so oui # can locate, e.g., the native library it uses) # # JRE_HOME has to be set correctly in the environment and has to # point to JDK1.3.1 home, e.g. /usr/local/packages/jdk1.3.1 # # In addition, it is assumed that environment variable # LD_LIBRARY_PATH or equivalent (depending on OS) has to include # a directory with liboraInstaller.so and liboraInstaller251.so or # equivalent libraries (depending on OS) # # MODIFIED (MM/DD/YY) # chkaushi 09/04/09 - XbranchMerge chkaushi_bug_8869446 from # st_emcore_10.2.0.1.0 # jashukla 06/03/08 - Bug 7144619 remove internal identifiers # jochen 11/20/07 - Return 0 for non-64bit platforms # hmodawel 10/08/07 - handle hybrid java invocations # mgoodric 01/31/05 - move functions to ecmCommon.pl # jmansur 12/01/04 - add ouiLoc argument # mgoodric 08/23/04 - fix IA64 and AIX java command # djoly 08/18/04 - Break up cemd # mgoodric 05/10/04 - Fix using /.. which doesn't work in vob split # mgoodric 02/10/04 - Fix null parameter passing on Windows (again) # mgoodric 11/07/03 - change to use JRE_HOME instead of JAVA_HOME # aaitghez 10/03/03 - review comments, update comments # aaitghez 10/03/03 - pass emhome dir to SnapshotFactory # mgoodric 08/15/03 - fix checking for loaderFileOrig parameter # mgoodric 08/10/03 - fix on demand refresh on NT # jmansur 08/04/03 - add mgoodric fix for empty arg on nt # vkhizder 02/26/03 - improving agent logging and error handling # vkhizder 10/01/02 - send only changed snapshots # vkhizder 07/01/02 - comment change # xxu 06/25/02 - remove /usr/local/bin/perl # vkhizder 06/11/02 - # jmansur 03/22/02 - add/use invPtrLoc and workingDir args for tests # vkhizder 03/07/02 - # vkhizder 02/25/02 - generalizing this script + various improvements # vkhizder 01/16/02 - removing error stream redirection to null # vkhizder 12/17/01 - redirecting std error to null device # jmansur 12/13/01 - update classes12.jar location for install env # jmansur 12/13/01 - use all caller-supplied arguments # jmansur 12/12/01 - update jar file locations so ok for ade and install # jmansur 12/11/01 - support optional writing of snapshot to loader file # jmansur 12/06/01 - creation # use strict; use File::Basename(); use File::Copy(); use File::Spec(); my $osmScriptDir = File::Basename::dirname($0); my $ecmCommon = File::Spec->catfile($osmScriptDir, 'ecmCommon.pl'); require "$ecmCommon"; my $scriptsDir = $osmScriptDir; $scriptsDir =~ s/.osm$//; my $emdCommon = File::Spec->catfile($scriptsDir, 'emd_common.pl'); require "$emdCommon"; ### Change this to 0 if you always want to send host configuration ### snapshots (even when they are the same as old snapshots) my $optimizeForUnchangedSnapshots = 1; # auto flush STDOUT and STDERROR setOutputAutoflush(); # debug and trace messages my $message_prefix = "ECM: host configuration collection: "; my $infoMsg = ''; my $warnMsg = ''; my $errMsg = ''; # Windows requires a double-quoted string for passing null parameters my $empty = ''; $empty = "\"\"" if (onWindows()); # ARGV index my $i = 0; # classpath including all necessary jar's as described in comment above my $classpath = $ARGV[$i++]; # e.g., /private/oracle/mozart/perl/bin my $perlBin = $ARGV[$i++]; # e.g., /private/oracle/mozart my $emdRoot = $ARGV[$i++]; my $emHome = $ARGV[$i++]; # e.g. host.example.com my $targetName = $ARGV[$i++]; # if target names were not required we could try some system-dependent # stuff... # # if (isEmpty($targetName)) # { # chomp($targetName = `hostname`); # } # emd-generated unique file name, optional, if missing or empty, # snapshot goes to stdout my $loaderFileOrig = $empty; if (defined($ARGV[$i]) && !($ARGV[$i] =~ m/OUIinventories\.add/)) { $loaderFileOrig = $ARGV[$i] if ($ARGV[$i] ne ''); $infoMsg = $message_prefix . "Filename: \"$ARGV[$i]\"."; EMD_PERL_DEBUG($infoMsg); } else { $i -= 1 if (onWindows()); $infoMsg = $message_prefix . "No filename provided."; EMD_PERL_DEBUG($infoMsg); } $i++; my $additionalInventoriesFile = $empty; if (defined($ARGV[$i]) && !isEmpty($ARGV[$i])) { $additionalInventoriesFile = $ARGV[$i]; # $infoMsg = $message_prefix . # "\$additionalInventoriesFile=>\"$additionalInventoriesFile\""; # EMD_PERL_DEBUG($infoMsg); } $i++; my $targetType; if (defined($ARGV[$i]) && !isEmpty($ARGV[$i])) { $targetType = $ARGV[$i]; } else { $targetType = 'host'; } $i++; my $displayTargetName; if (defined($ARGV[$i]) && !isEmpty($ARGV[$i])) { $displayTargetName = $ARGV[$i]; } else { $displayTargetName = $targetName; } $i++; my $displayTargetType; if (defined($ARGV[$i]) && !isEmpty($ARGV[$i])) { $displayTargetType = $ARGV[$i]; } else { $displayTargetType = $targetType; } $i++; my $snapshotType; if (defined($ARGV[$i]) && !isEmpty($ARGV[$i])) { $snapshotType = $ARGV[$i]; } else { $snapshotType = 'host_configuration'; } $i++; my $invPtrLoc; if (defined($ARGV[$i]) && !isEmpty($ARGV[$i])) { $invPtrLoc = $ARGV[$i]; } $i++; my $workingDir; if (defined($ARGV[$i]) && !isEmpty($ARGV[$i])) { $workingDir = $ARGV[$i]; chdir($workingDir); } $i++; my $ouiLoc; if (defined($ARGV[$i]) && !isEmpty($ARGV[$i])) { $ouiLoc = $ARGV[$i]; } # $i++; <---- if adding more arguments... # construct Java command my @systemCommand = getJavaCommand($classpath); if(is64BitHybridJava($emdRoot)) { @systemCommand = (@systemCommand, "-d64"); } if (!isEmpty($invPtrLoc)) { @systemCommand = (@systemCommand, "-Doracle.installer.invPtrLoc=$invPtrLoc"); } if (!isEmpty($ouiLoc)) { @systemCommand = (@systemCommand, "-Doracle.installer.oui_loc=$ouiLoc"); } @systemCommand = (@systemCommand, 'oracle.sysman.emd.ecm.track.SnapshotFactory'); @systemCommand = (@systemCommand, $snapshotType, $targetName, $targetType, $displayTargetName, $displayTargetType); @systemCommand = (@systemCommand, $scriptsDir, $perlBin, $emdRoot, $emHome, $additionalInventoriesFile, $loaderFileOrig); # $infoMsg = $message_prefix . "Executing: \"@systemCommand\""; # EMD_PERL_DEBUG($infoMsg); # print STDERR ("\n"); $! = 0; my $rv = system(@systemCommand); # execute the command if ($rv != 0) { $warnMsg = $message_prefix . "First snapshot collection attempt failed. Trying one more time... "; EMD_PERL_WARN($warnMsg); sleep 2; $! = 0; $rv = system(@systemCommand); } # OSD: Is exit value always returned value shifted by 8 bits? Appears to work on Solaris and WinNT # use integer; # so that if $rv is negative, the shift in the next line will retain negative sign (i.e. add 1's to the left) my $exit_value = $rv >> 8; # no integer; # should we set to no integer? why? # OSD: The following only distinguishes Solaris from Windows platforms. For HP, Linux, VMS, etc. this has to be modified.. # if (!onWindows()) # { # my $signal_num = $rv & 127; # does not work for negative (e.g. -1 when java command is not found) returns on Solaris # my $dumped_core = $rv & 128; # does not work for negative (e.g. -1 when java command is not found) returns on Solaris # } # $infoMsg = $message_prefix . # "Returned value: $rv; exit value = $exit_value; " . # "signal_num = $signal_num; dumped_core = $dumped_core; " . # "signum & ~0x80 = " . ($signal_num & ~0x80); # printf STDERR $infoMsg . "\n"; if ($rv == 0) { if ($loaderFileOrig ne $empty) { my $loaderFile = $loaderFileOrig . ".suc"; if ($optimizeForUnchangedSnapshots) { if (compareAndReplaceOldSnapshot($targetName, $targetType, $snapshotType, $loaderFileOrig) == 0) { $loaderFileOrig = $loaderFileOrig . ".almost_suc"; } } $! = 0; if (rename($loaderFileOrig, $loaderFile) == 1) { $infoMsg = $message_prefix . "Resulting file is \"$loaderFile\""; EMD_PERL_DEBUG($infoMsg); } else { my $error_code = $!; $errMsg = $message_prefix . "Could not rename file \"$loaderFileOrig\" to \"$loaderFile\": $error_code." ; EMD_PERL_ERROR($errMsg); print STDERR $errMsg; exit $error_code; } } $infoMsg = $message_prefix . "Configuration collection is successful."; EMD_PERL_DEBUG($infoMsg); } else { $errMsg = $message_prefix . "Collection failed"; if ($exit_value != 0) { $errMsg .= ": exit value: $exit_value"; } else { $errMsg .= " (potentially due to a signal)"; } $errMsg .= ("$^E" ne "" ? ": $^E" : "."); EMD_PERL_ERROR($errMsg); print STDERR $errMsg; exit $exit_value; } exit 0; # Compare old snapshot (if any) with just collected one. If they are the same, # generate small snapshot-update file with .almost_suc extension. Either way, # try to copy just collected file into the "old" one for future comparisons. # In case when the files match, move the just collected file instead of copying # into the old one (since we'll be sending ".almost_suc" file instead). # # Input: target name, target type, snapshot type, just collected filename # Return values: # < 0 => some error occurred; send the full file # 0 => files are the same except for the first line; new file with # name $newFile . ".almost_suc" was written out # 1 => files are different sub compareAndReplaceOldSnapshot { my ($targetName, $targetType, $snapshotType, $newFile) = @_; my $oldFilePath = File::Basename::dirname($newFile); my $oldFile = File::Spec->catfile($oldFilePath, ${targetName} . '_' . ${targetType} . '_' . ${snapshotType} . '_old'); my $returnValue = compareWithOldSnapshot($oldFile, $newFile); $! = 0; if ($returnValue == 0) # files are the same except for first line { # rename newFile into oldFile if (rename($newFile, $oldFile) == 1) { $infoMsg = $message_prefix . "Renamed new file \"$newFile\" into old file \"$oldFile\"."; EMD_PERL_DEBUG($infoMsg); } else { $errMsg = $message_prefix . "Could not rename newly collected file \"$newFile\" into \"$oldFile\": $!."; EMD_PERL_ERROR($errMsg); print STDERR $errMsg; # This means that the old file may not be trustworthy (since we cannot overwrite it). # Thus, send the snapshot! return -10; } } else { # copy newFile into oldFile if (File::Copy::copy($newFile, $oldFile) == 1) { $infoMsg = $message_prefix . "Config difference found: copied new " . "file \"$newFile\" into old file \"$oldFile\"."; EMD_PERL_DEBUG($infoMsg); } else { $errMsg = $message_prefix . "Config difference found: could not copy " . "newly collected file \"$newFile\" into \"$oldFile\": $!."; EMD_PERL_ERROR($errMsg); print STDERR $errMsg; # Should we indicate here somehow for the next collection that it should not trust the file? # Can try removing the file and/or creating a new one indicating the condition } } return $returnValue; } # Input: file name with old snapshot, file name with just collected snapshot # Return values: # < 0 => some error occurred # 0 => files are the same except for the first line; new file with # name $newFile . ".almost_suc" was written out # 1 => files are different sub compareWithOldSnapshot { my ($oldFile, $newFile) = @_; # try to find and open the old snapshot file unless (-f $oldFile && -T $oldFile) { $errMsg = $message_prefix . "Old file \"$oldFile\" is not found. "; EMD_PERL_DEBUG($errMsg); return -1; } unless (open(OLD, $oldFile)) { $errMsg = $message_prefix . "Do not have access to file \"$oldFile\". "; EMD_PERL_ERROR($errMsg); print STDERR $errMsg; return -2; } unless (open(NEW, $newFile)) { $errMsg = $message_prefix . "Do not have access to just created file \"$newFile\". "; EMD_PERL_ERROR($errMsg); print STDERR $errMsg; return -3; } my $firstOldLine = ; my $firstNewLine = ; my $oldLine; my $newLine; my @firstLines = ($firstNewLine); my $collectFirstLines = 1; while ($oldLine = ) { $newLine = ; if ($oldLine ne $newLine) { $infoMsg = $message_prefix . "Found difference in snapshot files: Old line: \"$oldLine\" "; EMD_PERL_DEBUG($infoMsg); $infoMsg = $message_prefix . "Found difference in snapshot files: New line: \"$newLine\" "; EMD_PERL_DEBUG($infoMsg); close(OLD) or return -4; close(NEW) or return -5; return 1; } if ($collectFirstLines) { $firstLines[scalar(@firstLines)] = $newLine; if ($newLine =~ /^\s*" . $newShortFile)) { $errMsg = $message_prefix . "Could not open \"${newShortFile}\" for writing. "; EMD_PERL_ERROR($errMsg); print STDERR $errMsg; return -8; } # write out almost_suc file my $status = 1; my $outLine; foreach $outLine (@firstLines) { if ((print NEW_SHORT $outLine) != 1) { $errMsg = $message_prefix . "Could not write out the following line: \"$outLine\" "; EMD_PERL_ERROR($errMsg); print STDERR $errMsg; return -9; } } if ((print NEW_SHORT " \n\n") == 1) { if (close(NEW_SHORT)) { return 0; } } # problem with writing into the almost_suc file or closing it return -9; } # 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; } }