# # $Header: has/install/crsconfig/orachm.pm /st_has_12.2.0.1.0/1 2016/11/03 22:32:59 shullur Exp $ # # orachm.pm # # Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. # # NAME # orachm.pm - File for CHM subroutines for rootscripts # # DESCRIPTION # This file contains the subroutines for managing install, upgrade, # downgrade and deconfiguration. # # NOTES # # # MODIFIED (MM/DD/YY) # shullur 11/01/16 - Backport shullur_bug-24567625 from main # shullur 09/13/16 - For running diagsnap in dev env # shullur 02/02/15 - For fixing diagsnap issue. Bug 22312380. # shullur 07/22/15 - For fixing bug 21484101. # shullur 07/07/15 - For fixing bug 21380750 # shullur 06/12/15 - For migrating CHM modules # shullur 06/12/15 - Creation # package oraClusterwareComp::orachm; use parent 'oraClusterwareComp'; use strict; use English; use Carp; use File::Copy; use File::Path; use File::Find; use File::Temp qw/ tempfile /; use File::Basename; use File::Spec::Functions; use Cwd; use crsutils; use s_crsutils; use s_orachm; sub new { my $class = shift; # Pass the component name into the constructor my $componentName = @_; my $self = $class->SUPER::new(@_); $self->_initialize(); return $self; } # Initialize CHM sub _initialize { my $self = shift; my $compName = $self->compName; trace("Perform initialization tasks before configuring $compName"); } # # Interface to be implemented # # Is CHM supported based on the platform sub isSupported { return s_isCHMSupported(); } # Check the CHM bdbd location sub chm_check_bdbloc() { trace("check $_[1], $_[2]"); return s_chm_check_bdbloc($_[1], $_[2]); } sub dependsOn { return TRUE; } # Has the component already been configured sub isConfigured { return TRUE; } sub configureCurrentNode { create_CHM_config(); } # # Methods for upgrade # sub preUpgradeCheck { #TODO return SUCCESS; } sub upgradeCheckFirstNode { #TODO return SUCCESS; } sub upgradeCheckNonFirstNode { #TODO return SUCCESS; } sub upgradeCurrentNode { create_CHM_config(); } sub downgradeCurrentNode { CHMDowngrade(); } sub create_pinproc_list { my $pinproc; if ($CFG->platform_family eq "unix") { if (is_dev_env()) { $pinproc = "osysmond,ologgerd,ocssd,cssdmonitor,cssdagent,mdb_pmon_-MGMTDB"; } else { $pinproc = "osysmond.bin,ologgerd,ocssd.bin,cssdmonitor,cssdagent,mdb_pmon_-MGMTDB"; } } if ($^O eq "linux") { if (is_dev_env()) { $pinproc= "osysmond,ologgerd,ocssd,cssdmonitor,cssdagent,mdb_pmon_-MGMTDB,kswapd0"; } else { $pinproc= "osysmond.bin,ologgerd,ocssd.bin,cssdmonitor,cssdagent,mdb_pmon_-MGMTDB,kswapd0"; } } if ($^O eq "solaris") { if (is_dev_env()) { $pinproc= "osysmond,ologgerd,ocssd,cssdmonitor,cssdagent,mdb_pmon_-MGMTDB,pageout,sched"; } else { $pinproc= "osysmond.bin,ologgerd,ocssd.bin,cssdmonitor,cssdagent,mdb_pmon_-MGMTDB,pageout,sched"; } } if ($CFG->platform_family eq "windows") { $pinproc= "osysmond.exe,ologgerd.exe,ocssd.exe,cssdmonitor.exe,cssdagent.exe,mdb_pmon_-MGMTDB"; } trace("Pin process list is $pinproc"); return $pinproc; } sub chm_config_generate { my $mynameEntry = $_[0]; my $hlist = ""; my $nodelist = ""; my $master = ""; my $replica = ""; my $masterpub = ""; my $bdbloc = $_[1]; my $usernm = $_[2]; my $pinproc= create_pinproc_list(); my $clustnm = $CFG->params('CLUSTER_NAME'); my $chmhome = $CFG->ORA_CRS_HOME; my $host = $CFG->HOST; my $configfile; (undef, $configfile) = tempfile(); $hlist=$_[3]; $hlist =~ s/ //g; $nodelist=$_[3]; chomp($nodelist); my @hosts = split(/[,]+/, $nodelist); $master = $hosts[0]; if ($CFG->platform_family eq "windows") { $usernm = ""; } trace ("myname entry is $mynameEntry"); trace ("host name from cfg is $host"); # no replica if less than 2 nodes if (scalar(@hosts) >= 2) { $replica = $hosts[1]; } if ($mynameEntry eq $master) { $masterpub = $CFG->HOST; } my $orafile = catfile ($chmhome, "crf", "admin", "crf$host.ora"); if (!-e $orafile) { open CONFIG_FILE,'>',$configfile or die $!; print CONFIG_FILE "BDBLOC=$bdbloc\n" ; trace ("Cluster Health Monitor repository location updated with $bdbloc"); print CONFIG_FILE "PINNEDPROCS=$pinproc\n" ; trace ("Cluster Health Monitor pin process list updated with $pinproc"); } else { copy_file($orafile, $configfile); trace ("Copied existing orafile"); open CONFIG_FILE,'>>',$configfile or die $!; if (getCHMAttrib("BDBLOC", $configfile) eq "") { print CONFIG_FILE "BDBLOC=$bdbloc\n" ; trace("Cluster Health Monitor repository location copied if not present"); } if (getCHMAttrib("PINNEDPROCS", $configfile) eq "") { print CONFIG_FILE "PINNEDPROCS=$pinproc\n" ; trace ("Cluster Health Monitor pin process list updated with $pinproc"); } } if (getCHMAttrib("HOSTS", $configfile) eq "") { print CONFIG_FILE "HOSTS=$hlist\n" ; } if (getCHMAttrib("MASTER", $configfile) eq "") { print CONFIG_FILE "MASTER=$master\n" ; } if (getCHMAttrib("MYNAME", $configfile) eq "") { print CONFIG_FILE "MYNAME=$mynameEntry\n" ; } if (getCHMAttrib("MASTERPUB", $configfile) eq "") { print CONFIG_FILE "MASTERPUB=$masterpub\n" ; } if (getCHMAttrib("CLUSTERNAME", $configfile) eq "") { print CONFIG_FILE "CLUSTERNAME=$clustnm\n" ; } if (getCHMAttrib("USERNAME", $configfile) eq "") { print CONFIG_FILE "USERNAME=$usernm\n"; } if (getCHMAttrib("CRFHOME", $configfile) eq "") { print CONFIG_FILE "CRFHOME=$chmhome\n" ; } close CONFIG_FILE ; return $configfile; } sub removeCHMDB { my $bdbloc = getCHMAttrib("BDBLOC"); if ($bdbloc eq "default") { $bdbloc = catfile($CFG->ORA_CRS_HOME, "crf", "db", $CFG->HOST); } if (-d $bdbloc) { # delete old bdb files. trace("Deleting CHM repository at files at: ", $bdbloc); chm_delete_bdb($bdbloc); } else { trace("CHM repository path not found"); } } # This subroutine takes argument as attribute of ora file and returns # the corresponding value of that attribute in the ora file. # Eg: If ora file has a line with "BDBSIZE = 25632", # this subroutine returns 25632. sub getCHMAttrib { my $arg = $_[0]; my $orafile = $_[1]; my $loc; my $home = s_get_olr_file ("crs_home"); my $host = tolower_host(); if ($arg ne "") { # Read the ora file to get the BDB path if ($orafile eq "") { $orafile = catfile ($home, "crf", "admin", "crf$host.ora"); } if (!-f $orafile) { trace("Info: No ora file present at ", $orafile); return ""; } my @filecontent = read_file ($orafile); foreach my $line (@filecontent) { # skip blanks and comments if ($line !~ /^#|^\s*$/) { if ($line =~ /$arg=(.*)/) { if ($1 ne "") { $loc = $1; last; } } } } return $loc; } return ""; } ####--------------------------------------------------------- #### Move directory from one local location to another # # Moves directory from one local location to another # ARGS : 2 # ARG1 : Source directory path # ARG2 : Destination directory path # @returns SUCCESS or FAILED # sub movedir { my $srcdir = $_[0]; my $destdir = $_[1]; trace("movedir src $_[0] dst $_[1]"); if (! -d $destdir) { mkdir($destdir); } if (!opendir(DIR, $srcdir)) { trace("Cannot open $srcdir"); print_error(518, $srcdir); return FAILED; } my @files = grep {!/^\.+$/ } readdir(DIR); foreach my $file (@files) { my $old = "$srcdir/$file"; if (-f $old) { if (!move($old, $destdir)) { trace("Could not move $old into $destdir.\n"); print_error(519, $old, $destdir); return FAILED; } } if (-d $old) { return movedir($old, $destdir); } } close(DIR); return SUCCESS; } sub create_CHM_config { if (!s_isCHMSupported()) { trace("CHM is not supported on this platform"); return; } # Create CHM/OS config my $bdbloc = "default"; my $chmconfig = catfile($CFG->ORA_CRS_HOME, 'crf', 'admin', 'crf' . $CFG->HOST . '.ora'); my $tmpchmconfig = chm_config_generate($CFG->HOST, $bdbloc, $CFG->params('ORACLE_OWNER'), $CFG->params('NODE_NAME_LIST')); trace ("Creating CHM/OS config file $chmconfig"); # Delete older existing CHM/OS repository for Upgrade but # for new installation delete the newer location. # If not removed, leads to CHM/OS repository corruption. if ($CFG->UPGRADE) { my $old_crshome = $CFG->OLD_CRS_HOME; my $oldchmconfig = catfile($old_crshome, 'crf', 'admin', 'crf' . $CFG->HOST . '.ora'); $bdbloc = getCHMAttrib("BDBLOC", $oldchmconfig); if ($bdbloc eq "default") { $bdbloc = catfile($old_crshome, 'crf', 'db', $CFG->HOST); } } trace("argument value is $_[1]"); if ($_[1] eq "") { my $new_crs_running = FALSE; # Check if New Grid Infrastructure is running if ($CFG->isRerun) { trace("Trying to check if new CRS stack is partially up"); $new_crs_running = check_NewCrsStack(); } # Dont delete the bdb if the new stack is running. if (!$new_crs_running) { trace ("Deleting older CHM/OS repository at $bdbloc"); if ($bdbloc eq "default") { $bdbloc = catfile($CFG->ORA_CRS_HOME, "crf", "db", $CFG->HOST); } chm_delete_bdb($bdbloc); my $diagfile = crs_exec_path('diagsnap.pl'); my $perl = $^X; my $diagsetup = crs_exec_path('diagsnap_setup.pl'); if (!-e $diagfile) { trace("creating diagsnap.pl"); system_cmd_capture($perl, $diagsetup); } } } elsif ($_[1] eq "test") { my $perl = $^X; my $diagsetup = catfile($CFG->ORA_CRS_HOME, "has", "src", "utl", "clsdiaglsnr", "diagsnap_setup.pl"); my $diagfile = catfile($CFG->ORA_CRS_HOME, "has", "bin", "diagsnap.pl"); trace("diagsetup file $diagsetup"); if (!-e $diagfile) { trace("creating diagsnap.pl"); system_cmd_capture($perl, $diagsetup, "test"); } } copy_file($tmpchmconfig, $chmconfig); unlink $tmpchmconfig; # delete older CHM/OS installation chm_do_delete(); } # delete a node from the CRF install sub chm_do_delete { # shutdown the sysmond, ologgerd, oproxyd if they are running my ($cmd, $instdir, $defpath, $rootpath, $configfile, $line, $bdbloc, $admindir, $admin, $runpth); trace("Check and delete older CHM/OS installation"); if ($CFG->platform_family eq "windows") { $instdir = "C:\\Program Files\\oracrf"; $defpath = "$ENV{SYSTEMROOT}"."\\system32\\"; $rootpath = "$ENV{SYSTEMROOT}"; } else { $instdir = "/usr/lib/oracrf"; $defpath = "/usr/bin/"; $rootpath = "/"; } my $instfile = catfile($instdir, "install", "installed"); if (! -f $instfile) { trace("INFO: The OS Tool is not installed at $instdir."); } else { trace("Older CHM/OS installation detected ... Stopping and removing it..."); $cmd = "oclumon"." ". "stop"." ". "all"; my $chmhome = $instdir; $admindir = catfile("$instdir", "crf"); if ( -d $admindir) { $configfile = catfile($instdir, "crf", "admin", "crf" . $CFG->HOST . ".ora"); $runpth = catfile($chmhome, "crf", "admin", "run"); $admin = 'crf'; } else { $configfile = catfile($instdir, "admin", "crf" . $CFG->HOST . ".ora"); $runpth = catfile($chmhome, "admin", "run"); $admin = 'admin'; } system("$cmd"); sleep(5); # read config file to find older BDB loc $bdbloc = getCHMAttrib("BDBLOC", $configfile); if ($bdbloc eq "default") { $bdbloc = catfile($instdir, "crf", "db", "$CFG->HOST"); } my $pidf=catfile($runpth, "crfmond", "s" . $CFG->HOST . ".pid"); if (-f $pidf) { open(PID_FILE, $pidf); while () { chm_kill_for_sure($_); } close(PID_FILE); unlink($pidf); } my $dir = catfile("$runpth", "crfmond"); rmdir("$dir"); # ologgerd now $pidf=catfile($runpth, "crflogd", "l" . $CFG->HOST . ".pid"); if (-f $pidf) { open(PID_FILE, $pidf); while () { chm_kill_for_sure($_); } close(PID_FILE); unlink($pidf); } $dir = catfile($runpth, "crflogd"); rmdir("$dir"); # proxy next $pidf=catfile($runpth, "crfproxy", "p" . $CFG->HOST . ".pid"); if (-f $pidf) { open(PID_FILE, $pidf); while () { chm_kill_for_sure($_); # give some time to oproxy to react. sleep 2; } close(PID_FILE); unlink($pidf); } $dir = catfile($runpth, "crfproxy"); rmdir("$dir"); # ask chmcheck to shutdown cleanly $pidf=catfile($chmhome, "log", $CFG->HOST, "crfcheck", "crfcheck.lck"); if (-f $pidf) { open(PID_FILE, $pidf); while () { kill 15, $_; } close(PID_FILE); } my $rootpath; s_chm_remove_itab(); # remove the tree trace("Removing install dirs from $instdir ...\n"); my $filed; my $file; foreach $filed ('bin', 'lib', $admin, 'jlib', 'mesg', 'log', 'install', 'jdk', 'db') { $file = catfile($instdir, "$filed"); rmtree("$file", 0, 0); } # delete old bdb files. trace("Deleting older CHM/OS BDB files at: ", $bdbloc); chm_delete_bdb($bdbloc); unlink("$defpath"."crfgui"); unlink("$defpath"."oclumon"); unlink("$defpath"."ologdbg"); # change dir to a safer place chdir $rootpath; trace("Removing CRFHOME path $instdir...\n"); rmdir $instdir; trace("Old CHM/OS install removal operation completed.\n"); } } sub chm_kill_for_sure { kill(15, $_[0]); # if that didn't work, use force if (kill(0, $_[0])) { kill(9, $_[0]); } } # delete the bdb files in bdbloc. sub chm_delete_bdb { my $bdbloc = $_[0]; my $cwd = cwd(); trace("delete bdb $_[0]"); if ($bdbloc ne "" and -d $bdbloc) { # remove files which we created. chdir $bdbloc or print_error(355, $bdbloc); opendir(DIR, "$bdbloc") || print_error(356, $bdbloc); trace("Removing contents of BDB Directory $bdbloc\n"); my $crfbdbfile; my @ldbfiles = grep(/\.ldb$/,readdir(DIR)); foreach $crfbdbfile (@ldbfiles) { unlink ($crfbdbfile); } # database files rewinddir (DIR); my @bdbfiles = grep(/\.bdb$/,readdir(DIR)); foreach $crfbdbfile (@bdbfiles) { unlink ($crfbdbfile); } # env files rewinddir (DIR); my @dbfiles = grep(/__db.*$/,readdir(DIR)); foreach $crfbdbfile (@dbfiles) { unlink ($crfbdbfile); } # archive log rewinddir (DIR); my @bdblogfiles = grep(/log.*$/,readdir(DIR)); foreach $crfbdbfile (@bdblogfiles) { unlink ($crfbdbfile); } closedir (DIR); # change back to current working directory. if ($cwd) { chdir $cwd or print_error(355, $cwd); trace("Changed to older working directory $cwd\n"); } else { trace("Couldn't find older working directory\n"); } } } sub CHMDowngrade { my $oldcrfhome = $CFG->OLD_CRS_HOME; my $crfhome = $CFG->ORA_CRS_HOME; my $host = $CFG->HOST; my $oldorafile = catfile("$oldcrfhome", "crf", "admin", "crf$host.ora"); my $oldcfgfile = catfile("$oldcrfhome", "crf", "admin", "crf$host.cfg"); my $orafile = catfile("$crfhome", "crf", "admin", "crf$host.orabkp"); my $cfgfile = catfile("$crfhome", "crf", "admin", "crf$host.cfgbkp"); my $bdbloc; my $oldbdbdirbkp; if (s_isCHMSupported()) { if (!-e $orafile) { trace("Failed to find Cluster Health Monitor internally-generated file $orafile during downgrade."); } if (!copy_file($orafile, $oldorafile)) { trace("Failed to copy Cluster Health Monitor internally-generated file $orafile to $oldorafile during downgrade."); } if (!copy_file($cfgfile, $oldcfgfile)) { trace("Failed to copy Cluster Health Monitor internally-generated file $cfgfile to $oldcfgfile during downgrade."); } } else { trace("CHM not supported on this platform"); return; } $bdbloc = getCHMAttrib("BDBLOC", $orafile); if ($bdbloc eq "default") { $bdbloc = catfile("$crfhome", "crf", "db", $host); } # Check if the older bdb location exists if (-d $bdbloc) { my $bdbdirbkp = "$orafile"."bkp"; # Check if there is old bdb files if yes move to old location. if (-d $bdbdirbkp) { my $bdbdirbkp = "$orafile"."bkp"; # Check if there is old bdb files if yes move to old location. if (-d $bdbdirbkp) { if(!movedir($bdbdirbkp, $bdbloc)) { trace("Couldn't move back the old bdb directory\n"); } } } else { trace ("Not able to find older bdb location at $bdbloc"); } } else { trace ("Not able to find older bdb location at $bdbloc"); } } sub perform_CHM_upgrade { my $crfhome = $_[1]; my $patching = 1; my $oldcrfhome; my $oldorafile; my $oldcfgfile; my $bdblocbkp; my $oldorafilebkp; my $oldcfgfilebkp; my $neworafile; my $newcfgfile; my $oldbdbloc; my $oldbdbsize; my $HOST = tolower_host(); if (!s_isCHMSupported()) { trace("CHM is not supported on this platform"); return TRUE; } if ($crfhome eq "") { $crfhome = $CFG->ORA_CRS_HOME; $patching = 0; #It says it is rolling upgrade } #Find old home $oldcrfhome = s_get_olr_file ("crs_home"); if ($oldcrfhome eq $crfhome) { trace("11.2 Cluster Health Monitor upgrade actions are already performed"); return TRUE; } trace("The old crf home = $oldcrfhome"); #Get the bdb location from the old environment $oldbdbloc = getCHMAttrib("BDBLOC"); if ($oldbdbloc eq "default") { $oldbdbloc = catfile ($oldcrfhome, "crf", "db", "${HOST}"); } $oldbdbsize = getCHMAttrib("BDBSIZE"); # Get the old ora file and cfg file full path $oldorafile = catfile ($oldcrfhome, "crf", "admin", "crf${HOST}.ora"); if (!-e $oldorafile) { trace("Info: No old Cluster Health Monitor configuration file present at ", $oldorafile); return TRUE; } $oldcfgfile = catfile ($oldcrfhome, "crf", "admin", "crf${HOST}.cfg"); if (!-e $oldcfgfile) { trace("Info: No old Cluster Health Monitor configuration (cfg) file present at ", $oldcfgfile); return TRUE; } # Check if the new admin directory path exists. my $newadmindir = catdir ($crfhome, "crf", "admin"); if (!-d $newadmindir) { trace("Info: New admin directory doesn't exist at", $newadmindir); die(dieformat(406, $newadmindir)); } # Get the new ora file and cfg file full path $neworafile = catfile ($crfhome, "crf", "admin", "crf${HOST}.ora"); $oldorafilebkp = "$neworafile"."bkp"; $newcfgfile = catfile ($crfhome, "crf", "admin", "crf${HOST}.cfg"); $oldcfgfilebkp = "$newcfgfile"."bkp"; # Check if it is a rolling upgrade or patching if (((isRolling()) && (!$CFG->SIHA)) || $patching == 1) { # Create backup of the old configuration file to hande in case of failure. if (!copy_file($oldcfgfile, $oldcfgfilebkp)) { trace("Info: Failed to copy from $oldcfgfile to $oldcfgfilebkp"); } s_set_perms("0644", $oldcfgfilebkp); #copy the old configuration file. if (!copy_file($oldcfgfile, $newcfgfile)) { trace("Info: Failed to copy from $oldcfgfile to $newcfgfile"); } s_set_perms("0644", $newcfgfile); # Create a bakup of ora file to revert back in case of failure. if (!copy_file($oldorafile, $oldorafilebkp)) { trace("Info: Failed to copy from $oldorafile to $oldorafilebkp"); } s_set_perms("0644", $oldorafilebkp); # Just retain BDB Location and BDB Size from the old ora file. open (FP, ">$neworafile") || die(dieformat(408, $neworafile)); if (index($oldbdbloc, $oldcrfhome) == -1) { print FP "BDBLOC=$oldbdbloc\n"; } elsif ($patching == 1) { #Create a backup of oldbdb directory to handle in case of failure. $bdblocbkp = catdir("$crfhome", "crf", "db", "$HOST"); if (!movedir($oldbdbloc, $bdblocbkp)) { trace("Couldn't create a backup of oldbdb directory.\n"); } } # Don't move the bdb files in case of patching. if ($patching == 0) { my $hostbk = "$HOST"."bkp"; #Create a backup of oldbdb directory to handle in case of failure. $bdblocbkp = catdir("$crfhome", "crf", "db", "$hostbk"); if(!movedir($oldbdbloc, $bdblocbkp)) { trace("Couldn't create a backup of oldbdb directory.\n"); } } print FP "BDBSIZE=$oldbdbsize\n"; close (FP); } return TRUE; } # Wrapper for checking the version in case if we want to change it back to # bdb we need to change wrapper. sub isReposBDB { return isVersionGTE1201(); } 1;