# # Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. # # NAME # crsdeconfig.pm # # DESCRIPTION # Root deconfig script for Oracle Clusterware. # # MODIFIED (MM/DD/YY) # yilhu 07/20/16 - Fix bug 23727991 # luoli 06/28/16 - Skip checkLeafNodes() in 12.2.0.1 # bbeelamk 06/07/16 - Fix bug 23533341 # luoli 05/24/16 - Fix bug 23328179 # xyuan 04/25/16 - Fixed few compilation warnings # bbeelamk 04/15/16 - Fix bug 23110594 # bbeelamk 04/05/16 - Fix perl warning # luoli 03/21/16 - Fix bug 22955254 # dpham 03/07/16 - Bug 22826122 # bbeelamk 03/02/16 - Fix srvctl error # luoli 03/01/16 - Fix bug 22825685 # luoli 02/17/16 - Fix bug 22700293 # xyuan 01/10/16 - Fix bug 20835274 # muhe 01/05/16 - Fix bug 22496053 # muhe 12/23/15 - Fix RTI 18860282 # muhe 12/14/15 - Fix bug 22359934 # luoli 11/23/15 - Fix bug 21971395 # muhe 10/21/15 - Fix bug 21886212 # muhe 10/20/15 - Fix bug 21980263 # bbeelamk 10/05/15 - Fix bug 21830931 # bbeelamk 09/22/15 - Fix bug 21879542 # bbeelamk 09/15/15 - Changing srvctl method # muhe 08/14/15 - Fix bug 21611452 # bbeelamk 08/07/15 - Fix bug 21218176 # muhe 07/13/15 - Fix bug 21434917 # bbeelamk 06/24/15 - Fix bug 21237070 # samjo 06/19/15 - Bug 21044453. Look at 'ASMCMD-9489' to detect no # Client Clusters configured # muhe 06/17/15 - Fix bug 21176323 # shullur 06/15/15 - For migrating CHM to new rootscript framework # luoli 06/15/15 - Change print_error to print_info when printing # success information # luoli 06/09/15 - Fix bug 21213444 # muhe 06/03/15 - Fix bug 21182047 # muhe 05/20/15 - Fix bug 20911755 # emarron 02/26/15 - change OKA check in RemoveDrivers function # madoming 02/19/15 - Changes for new framework # muhe 01/30/15 - Remove global checkpoint file only on lastnode # luoli 01/12/15 - Separate downgrade/deconfig flow # sbezawad 12/19/14 - Bug 20019354: Migrate OCR and OLR to new framework # luoli 12/21/14 - rsc modeling for downgrade/deconfig # xyuan 12/18/14 - wrt Application Cluster # samjo 12/12/14 - Bug 20201434. Add message at the end of deconfig # for ASM CC # luoli 12/17/14 - Fix bug 20187649 # muhe 12/11/14 - Fix bug 20187693 # muhe 12/09/14 - Fix bug 20099320 # jmarcias 12/04/14 - Fix bug 20099783 # luoli 11/25/14 - Fix bug 19955755 for windows # luoli 11/13/14 - Fix bug 19955755 # muhe 11/04/14 - Fix bug 18844632 # bbeelamk 11/03/14 - Fix bug 19849644 # muhe 10/30/14 - Fix bug 19916737 # bbeelamk 10/26/14 - Fix bug 19688282 # ssprasad 09/29/14 - #18953639: Cleanup AFD if installed # bbeelamk 09/15/14 - Fix bug 19612597 # gnagiah 09/15/14 - Bug 19617592. handle node num 0 in case of vendor # clusterware # jmarcias 08/27/14 - Fix bug 19450419 # bbeelamk 08/27/14 - To fix bug 19479935 # jmarcias 08/19/14 - Fix bug 19418824 # ssprasad 08/11/14 - Fix bug 18859665 # luoli 07/28/14 - Fix bug 18349475 # rdasari 07/25/14 - use crsctl stop has to stop SIHA stack # lcarvall 07/20/14 - Bug 13800615 - Use mnemonic string instead nuemerica values # luoli 07/10/14 - Fix bug 19155350 # luoli 07/09/14 - Fix bug 19170747 # jmarcias 07/09/14 - Fix Bug 19059392 # xyuan 06/27/14 - Fix bug 19076778 # luoli 06/11/14 - Fix bug 18955644 # rdasari 06/09/14 - fix bug 18937186 # xyuan 06/06/14 - Remove the saved pfile for mgmtdb # xyuan 06/03/14 - Fix bug 18893576 # rdasari 05/28/14 - fix bug 18837560 # muhe 05/18/14 - Fix bug 18751257 # luoli 05/15/14 - Fix bug 18722594 # luoli 05/14/14 - Fix bug 18819158 # luoli 05/08/14 - Fix bug 18716571 # muhe 05/07/14 - Fix bug 18614068 # xyuan 05/05/14 - Fix bug 18493777 # muhe 05/04/14 - Fix bug 18675566 # luoli 04/28/14 - Fix bug 18667810 # xyuan 04/28/14 - Fix bug 18351413 # muhe 04/10/14 - Fix bug 18517951 # luoli 04/09/14 - Fix bug 18531995 # bburton 04/04/14 - Fix bug 18410410 - setup TFA from old home after # downgrade # luoli 04/03/14 - Fix bug 18510735 # muhe 04/03/14 - Fix bug 16801852 # luoli 03/24/14 - Skip lastnodeCheck() during partial downgrade # muhe 03/24/14 - Fix bug 17596579 # luoli 03/14/14 - Fix bug 18364276 # xyuan 03/17/14 - Fix bug 18402594 # ssprasad 03/11/14 - Change s_rm_afd_conf to rm_afd_conf # muhe 03/10/14 - Fix bug 18373231 # xyuan 03/06/14 - Fix bug 17861637 # luoli 02/25/14 - Fix bug 17967087 # xyuan 02/25/14 - Fix bug 18292097 # muhe 02/20/14 - Fix bug 18227454 # ssprasad 02/18/14 - #17395511: AFD in CRS downgrade paths # xyuan 02/16/14 - Remove the mgmtdb unconditionally when downgrade # from 12102 # cnagur 02/09/14 - Fix for Bug 17977698 # hmbui 02/06/14 - Enabling KA Driver install/deconfig/upgrade/ # downgrade options. # rdasari 02/06/14 - fix RemoveNodeApps # ssprasad 02/03/14 - Remove afd.conf # shullur 01/26/14 - For fixing bug 17991840. # luoli 01/21/14 - Fix bug 16833539 # luoli 01/20/14 - Fix bug 18007811 # luoli 01/14/14 - Ocr backup and restore # xyuan 01/08/14 - Fix bug 17602658 # luoli 01/08/14 - Fix bug 18007811 # xyuan 01/07/14 - Fix bug 18003879 # madoming 01/06/14 - Fix bug 17908663 # samjo 12/09/13 - Bug 17778985. Reset ASM card # xyuan 12/23/13 - Fix bug 17787018 # xyuan 12/12/13 - Do not call asmca -downgrade for downgrades to # 12.1.0.1 # luoli 12/08/13 - Fix bug 17895028 # madoming 11/22/13 - Fix bug 17841639 # xyuan 11/11/13 - Fix bug 17672924 # luoli 10/29/13 - Fix bug 17342639 # madoming 10/28/13 - Add validation for current working directory # luoli 10/25/13 - Fix bug 17566469 # xyuan 10/21/13 - Fix bug 17587410 # xyuan 10/10/13 - Fix bug 17586765 # xyuan 10/08/13 - Fix bug 17500273 # xyuan 09/27/13 - Fix bug 17499662 - call asmca only on the last to # downgrade # cnagur 09/24/13 - Support for TFA # xyuan 08/25/13 - Fix bug 16877613 # xyuan 08/25/13 - Fix lrg#9646541 # xyuan 08/24/13 - Remove compilation warnings # xyuan 08/05/13 - Fix bug 17058867 # shmubeen 07/05/13 - remove ORA_ENABLE_AFD_INSTALL check # xyuan 07/04/13 - Fix bug 17027740 # shmubeen 06/09/13 - AFD install fix # xyuan 05/29/13 - Fix bug 14795873 # xyuan 04/25/13 - Fix bug 13036885 - Fix sub removeOCROnDG # ssathyan 04/12/13 - 16613507 # xyuan 04/09/13 - Restore the old ocr.loc during downgrade # sidshank 03/15/13 - unset ORACLE_HOME environment variable before # OCRDowngrade # sidshank 03/14/13 - XbranchMerge sidshank_bug-16382128_win from # st_has_12.1.0.1 # sidshank 02/24/13 - fix bug 16382128. # xyuan 02/18/13 - Fix bug 14380026 # sidshank 02/12/13 - remove checkpoint index file during deconfig. # xyuan 02/07/13 - Fix bug 15967856 # xyuan 02/06/13 - Fix bug 14602984 # sidshank 11/15/12 - fix bug 15843792 # ssprasad 11/13/12 - Disable OKA actions for 12.1 # xyuan 11/06/12 - Fix bug 14404372 # xyuan 10/11/12 - Fix bug 14501724 - remove all 12.1-related stuff # from /etc/oratab during downgrade # rdasari 10/10/12 - use force to stop excl mode stack # xyuan 10/10/12 - Fix bug 14634138 # rdasari 09/12/12 - disable remote asm during last node deconfig # xyuan 08/30/12 - Fix bug 14528838 # xyuan 08/30/12 - Fix bug 14528781 # xyuan 08/20/12 - Fix bug 14000167 # rdasari 08/16/12 - mention ocr backup location in mesg 414 # xyuan 08/02/12 - Fix bug 14404483 # rdasari 08/01/12 - stop oc4j before removing the resource # shmubeen 07/19/12 - add uninstall of afd # xyuan 07/01/12 - Fix bug 14241008 # shullur 06/21/12 - For ignoring downgrade path failures in case of ora # file # xyuan 06/16/12 - Fix bug 14183602 # shullur 06/15/12 - For checking if bdb location is default # rdasari 05/25/12 - remove KA # shullur 05/09/12 - For removing exit if no previous CHM data is not # found # rtamezd 05/11/12 - Fix bug 14061578 # sidshank 05/03/12 - remove s_redirect/restore output subroutines # rtamezd 03/20/12 - Fix bug 13867352 # rtamezd 03/12/12 - Fix bug 13700977 # anjiwaji 02/15/12 - Use chkpoints in removeACFSRoot if not in SIHA. # xyuan 02/01/12 - XbranchMerge rdasari_bug-12614809 from # st_has_11.2.0.3.0 # gsanders 01/30/12 - remove call to removeACFSRegistry() # rdasari 01/19/11 - remove OCR on DG in deconfigure_ASM if DG is reused # sidshank 01/18/12 - fix for bug 13537946 # xyuan 01/08/12 - Add 12c to 11.2 downgrade code # sidshank 12/15/11 - disabling call to remove_misc_dirs on windows # sidshank 11/09/11 - Fix for the bug 13352502 # shullur 11/04/11 - XbranchMerge shullur_bug_12639640 from # st_has_11.2.0 # shullur 11/04/11 - XbranchMerge shullur_bug_11852891 from # st_has_11.2.0 # xesquive 09/19/11 - forward fix from bug-12587677 to main # xyuan 07/27/11 - XbranchMerge xyuan_bug-12585291 from # st_has_11.2.0.3.0 # xyuan 07/27/11 - XbranchMerge xyuan_bug-12727247 from # xesquive 07/26/11 - Add functions set_bold and reset_bold instead of # print color # dpham 03/31/11 - Creation for 12c # package crsdeconfig; use strict; use English; use File::Copy; use File::Path; use File::Spec::Functions; use Cwd; # root scripts modules use crsutils; use crsgpnp; use oracss; use oraacfs; use crska; use oraafd; use s_crsutils; use crstfa; use oraasm; use oraohasd; use oraClusterwareComp; use oraolr; use oraocr; use s_oraolr; use s_oraocr; use orachm; my @ns_files = ("CSS","CRS","EVM","PROC","css","crs","evm","proc"); sub new { shift; crsutils->new(@_); $CFG->compACFS(oraClusterwareComp::oraacfs->new("ACFS")); ($CFG->compACFS)->checkPath(); rscPreChecks(); if($CFG->CLEANSOCKETS) { if ($CFG->platform_family eq "unix") { stopFullStack("force") || die(dieformat(349)); s_NSCleanUp(); set_bold(); print_info(513); reset_bold(); exit(0); } } # Set the node attribute for deconfig based on the determination # if the current node is the last node to deconfig or not ($CFG->LASTNODE) ? $CFG->nodeAttributeDeconfigure(LAST_NODE_TO_DECONFIGURE): $CFG->nodeAttributeDeconfigure(NONLAST_NODE_TO_DECONFIGURE); if ($CFG->SIHA) { HADeconfig(); } else { CRSDeconfig(); } } my @CRS_DECONFIG_STAGES = ( {"name" => "DeconfigValidate", "checkpoint" => "null", "sub" => \&crs_deconfig_validate}, # prechecksDeconfig, remove ckpts, {"name" => "DeconfigResources", "checkpoint" => "null", "sub" => \&crs_deconfig_resources}, # verify and remove resources {"name" => "DeconfigCleanup", "checkpoint" => "null", "sub" => \&crs_deconfig_cleanup}, ); my @HA_DECONFIG_STAGES = ( {"name" => "DeconfigResources", "checkpoint" => "null", "sub" => \&ha_deconfig_resources}, {"name" => "DeconfigCleanup", "checkpoint" => "null", "sub" => \&ha_deconfig_cleanup}, ); sub CRSDeconfig { my $count = 0; trace ("Deconfiguring Oracle Clusterware on this node"); foreach my $stage (@CRS_DECONFIG_STAGES) { my $name = $stage->{"name"}; my $checkpoint = $stage->{"checkpoint"}; my $func = $stage->{"sub"}; trace("Executing the [$name] step with checkpoint [$checkpoint] ..."); &$func(); $count++; } if ($count == scalar(@CRS_DECONFIG_STAGES)) { trace ("Successfully deconfigured Oracle Clusterware stack on this node"); set_bold(); ($CFG->DECONFIG_WARNING eq "true") ? print_error(557) : print_error(336); if (($CFG->LASTNODE)) { print_info(559, $CFG->ORA_CRS_HOME); my $cluster_class = getClusterClass(); if (isFarASM() || (lc($cluster_class) eq lc(CLUSTER_CLASS_MEMBER))) { print_info(590, $CFG->params('CLUSTER_NAME')); } } reset_bold(); # Any invocation of Oracle executable could generate new files under # ORACLE_BASE/diag, hence deinstallCleanup() must be the last step if # deinstall asks the root deconfiguration. deinstallCleanup(); exit(0); } else { trace ("Failed to deconfigure Oracle Clusterware stack on this node"); set_bold(); print_error(588); reset_bold(); exit(1); } } sub crs_deconfig_validate { $CFG->compOLR(oraClusterwareComp::oraolr->new("OLR")); $CFG->compOCR(oraClusterwareComp::oraocr->new("OCR")); $CFG->compCHM(oraClusterwareComp::orachm->new("CHM")); prechecksDeconfig(); TraceOptions(); # Validate system command ValidateCRSCTL(); } sub crs_deconfig_resources { my $status = VerifyResources(); if ($status eq FAILED) { die(dieformat(311)); } # Only remove resources which were created during # Oracle Clusterware configuration RemoveResources(); my $success = TRUE; trace ("Deconfiguring Oracle ASM or shared filesystem storage ..."); trace("Stopping Oracle Clusterware ..."); $success = stopFullStack("force"); if ($CFG->LASTNODE) { # OHASD should not be up before CSS exclusive startup if (! $success) { die(dieformat(191)); } if (isOCRonASM()) { if (! deconfigure_ASM()) { if (! ($CFG->FORCE)) { die(dieformat(558)); } else { print_info(558); print_info(651); } } } # If cluster still has NFS voting files, delete them my @votedisk_list = extractVotedisks(); s_ResetVotedisks(@votedisk_list); # stop CSS running in exclusive mode, which is started in # deconfigure_ASM & extractVotedisks $success = FALSE if (! stopFullStack("force")); } $CFG->DECONFIG_WARNING("true") if (! $success); sleep 10; # Allow CRS daemons to shutdown in 10sec if (! $success) { trace("Failed to stop the current stack, but it's still feasible to " . "shut it down after deconfiguration or downgrade"); print_error(463); } # reset OCR my $oraocr = $CFG->compOCR; $oraocr->s_ResetOCR(); } sub crs_deconfig_cleanup { my $orachm = $CFG->compCHM; RemoveDrivers(USECHKPOINTS); # Remove CHM repository $orachm->removeCHMDB(); # Uninstall TFA remove_tfa(); s_RemoveInitResources(); DeleteSCR(); s_NSCleanUp(); if ($CFG->platform_family eq 'windows') { s_houseCleaning(); } if ($CFG->platform_family ne 'windows') { remove_misc_dirs(); } remove_gpnp_profiles_wallets_files(); s_CleanTempFiles(); remove_checkpoints(); remove_checkpoint_index(); if ($CFG->LASTNODE) { remove_global_checkpoints(); remove_global_checkpoint_index(); remove_config_params_file(); } # reset the permissions only when deconfig is called from deinstall or # the -deinstall option is specified during de-configuration if (($CFG->defined_param('HOME_TYPE')) || ($CFG->DEINSTALL)) { trace ("Opening permissions on Oracle clusterware home"); s_reset_crshome($CFG->params('ORACLE_OWNER'), $CFG->params('ORA_DBA_GROUP'), 755, $CFG->params('ORACLE_HOME')); trace("Reset Parent dir permissions for Oracle clusterware home"); s_resetParentDirOwner($CFG->ORA_CRS_HOME); } if ($CFG->platform_family eq "unix") { s_removeCvuRpm(); } } sub ValidateSRVCTL { trace ("Validate srvctl command"); my $srvctl = crs_exec_path('srvctl'); my $srvctl_exists = ValidateCommand ($srvctl); if (! $srvctl_exists) { if ($CFG->FORCE) { return SUCCESS; } else { print_error(36, $srvctl); print_error(37); trace ("Use -force option to force deconfiguration"); return FAILED; } } return SUCCESS; } sub ValidateCRSCTL { trace ("Validate crsctl command"); my $crsctl = crs_exec_path('crsctl'); if (! ValidateCommand($crsctl)) { if ($CFG->FORCE) { return SUCCESS; } else { print_error(36, $crsctl); print_error(37); trace ("Use -force option to force deconfiguration"); return FAILED; } } return SUCCESS; } sub ValidateCommand #------------------------------------------------------------------------------- # Function: Validate system command to ensure command exists and # exececutable. # Args : 1 #------------------------------------------------------------------------------- { my $cmd = $_[0]; trace("Validating $cmd"); if (-x $cmd) { return (TRUE); } else { return (FALSE); } } sub removeListeners { trace ("Remove listener resource..."); my $run_as_owner = FALSE; # Verify listener resources when deconfiguring last node in the cluster # Listener resource are local resources my @out; my $rc = srvctl_capture($run_as_owner, \@out, "config listener"); if (($rc == 0) || ($rc == 2)){ print_info(332); #stop the listener resource my $cmd = "stop listener"; if ($CFG->FORCE) { $cmd = "stop listener -f"; } my $status = srvctl($run_as_owner, $cmd); if ($status == FALSE) { if ($CFG->FORCE) { print_error(424); } else { print_error(423); return FAILED; } } #remove the listener resource $cmd = "remove listener -a"; if ($CFG->FORCE) { $cmd = "remove listener -a -f"; } $status = srvctl($run_as_owner, $cmd); if ($status == FALSE) { if ($CFG->FORCE) { print_error(334); } else { print_error(333); return FAILED; } } } return SUCCESS; } sub VerifyASMProxy { return SUCCESS; } sub VerifyDatabases { return SUCCESS; } sub VerifyResources #------------------------------------------------------------------------------- # Function: Verify resources (db, lsnr, asm) # Args : 0 #------------------------------------------------------------------------------- { trace ("Verifying the existence of CRS resources used by Oracle RAC databases"); my $node_name = $CFG->HOST; # Check if CRS is running trace ("Check if CRS is running"); my $crs_running = check_service ("crs", 2); if (! $crs_running) { if ($CFG->FORCE) { return SUCCESS; } else { print_error(38); trace("Restart the clusterware stack and retry"); return FAILED; } } # Validate system command ValidateSRVCTL || return FAILED; if ($CFG->LASTNODE) { removeListeners () || return FAILED; VerifyASMProxy () || return FAILED; } VerifyDatabases () || return FAILED; } sub VerifyHAResources #------------------------------------------------------------------------------- # Function: Verify resources (db, lsnr, asm) # Args : 0 #------------------------------------------------------------------------------- { trace ("Verifying the existence of SIHA resources used by Oracle databases"); my $node_name = $CFG->HOST; # Check if SIHA is running trace ("check_service SIHA"); my $siha_running = check_service ("ohasd", 2); if (! $siha_running) { if ($CFG->FORCE) { return SUCCESS; } else { print_error(39); trace("Restart the SIHA stack (use crsctl start has) and retry"); return FAILED; } } # Validate system command ValidateSRVCTL () || return FAILED; removeListeners () || return FAILED; VerifyDatabases () || return FAILED; } sub RemoveResources #--------------------------------------------------------------------- # Function: Remove nodeapps # Args : 0 #--------------------------------------------------------------------- { trace ("Remove Resources"); # Validate system command ValidateSRVCTL || return FAILED; if ($CFG->LASTNODE) { RemoveCVU(); if (! isAppCluster()) { RemoveScan(); } else { remove_appvips(); remove_network(); } } if (! isAppCluster()) { RemoveNodeApps(); } } sub remove_network { trace("Removing the public network in an application cluster ..."); my $run_as_owner = FALSE; my $cmd = "config network -netnum 1"; if (! srvctl($run_as_owner, $cmd)) { trace("No public network was found configured in the cluster"); return SUCCESS; } my $force; if ($CFG->FORCE) { $force = '-force'; } $cmd = "remove network -netnum 1 $force"; if (! srvctl($run_as_owner, $cmd)) { die(dieformat(587)); } return SUCCESS; } sub remove_appvips { my @appvips = (); my $CRSCTL = crs_exec_path('crsctl'); my @cmd = ($CRSCTL, 'stat', 'res', '-w', '"(TYPE = app.appvipx.type) OR (TYPE = app.appviptypex2.type)"'); my @out = system_cmd_capture(@cmd); my $rc = shift(@out); if (0 == $rc) { # List all application VIPs including the one created during install # and ones created by customers post install trace("Retrieving all application VIPs ..."); foreach my $line (@out) { if ($line =~ /NAME=/) { my @vipname = split(/=/, $line); my @vipname2 = split(/\(/, $vipname[1]); #remove rg name push(@appvips, trim($vipname2[0])); } } } else { # Fall back to at least remove the application VIP created during # install if ($CFG->params('APPLICATION_VIP')) { my $cluster_name = $CFG->params('CLUSTER_NAME'); my $vipname = "$cluster_name"."-vip"; push(@appvips, $vipname); } } trace("Listing all application VIPs: [@appvips]"); foreach my $appvip (@appvips) { removeAppVIP($appvip); } } sub removeAppVIP { my $vipname = $_[0]; my $force; if ($CFG->FORCE) { $force = '-force'; } my $CRSCTL = crs_exec_path('crsctl'); my @out = system_cmd_capture($CRSCTL, 'status', 'res', $vipname, '-f'); # check for resource group # stop the resource group if exists my @attr = grep(/^RESOURCE_GROUP=/, @out); my ($rgAttr, $resourceGroup) = split(/=/, $attr[0]); if ($resourceGroup) { trace("stop resource group=$resourceGroup"); system_cmd_capture($CRSCTL, 'stop', 'rg', $resourceGroup, '-f'); } trace("Attempt to stop the application VIP '$vipname'"); stop_resource($vipname, ($CFG->FORCE) ? "-f" : ""); trace("Trying to remove the application VIP ..."); my $appvipcfg = catfile($CFG->ORA_CRS_HOME, "bin", "appvipcfg"); my $cmd = "$appvipcfg delete -vipname=$vipname $force"; @out = system_cmd_capture($cmd); my $rc = shift(@out); if (0 == $rc) { trace("Successfully removed the application VIP"); } elsif ($CFG->FORCE) { print_error(586, $vipname); } else { die(dieformat(586, $vipname)); } return SUCCESS; } sub RemoveNodeApps #--------------------------------------------------------------------- # Function: Remove nodeapps # Args : 0 #--------------------------------------------------------------------- { trace ("Removing nodeapps..."); # check if nodeapps is configured my $run_as_owner = FALSE; my $rc = srvctl($run_as_owner, "config nodeapps"); if ($rc == FALSE) { return SUCCESS; } my $node = $CFG->HOST; my ($cmd, $force); if ($CFG->FORCE) { $force = '-f'; } # stop nodeapps $cmd = "stop nodeapps -n $node $force"; $rc = srvctl($run_as_owner, $cmd); if ($rc == FALSE) { trace ("srvctl $cmd ... failed"); } # remove nodeapps if lastnode, otherwise remove VIP if ($CFG->LASTNODE) { $cmd = "remove nodeapps -y $force"; $rc = srvctl($run_as_owner, $cmd); if ($rc == FALSE) { trace ("srvctl $cmd ... failed"); } } else { # vip does not exist on leaf nodes if (isHubNode()) { $cmd = "remove vip -i $node -y $force"; $rc = srvctl($run_as_owner, $cmd); if ($rc == FALSE) { trace ("srvctl $cmd ... failed"); } } } } sub RemoveCVU { trace("Removing CVU ..."); my $ret = TRUE; my $force; if ($CFG->FORCE) { $force = '-f'; } my $run_as_owner = TRUE; my $status = srvctl($run_as_owner, "stop cvu $force"); if ($status) { trace("Stop CVU ... success"); } else { $ret = FALSE; } $status = srvctl($run_as_owner, "remove cvu $force"); if ($status) { trace("Remove CVU ... success"); } else { $ret = FALSE; } return $ret; } sub RemoveScan #------------------------------------------------------------------------------- # Function: Remove scan and scan listener # Args : 0 #------------------------------------------------------------------------------- { trace("Removing scan...."); my $run_as_owner = TRUE; my ($cmd, $force, $rc); if ($CFG->FORCE) { $force = '-f'; } # stop/remove scan listener $cmd = "stop scan_listener $force"; $rc = srvctl($run_as_owner, $cmd); if ($rc == FALSE) { trace ("srvctl $cmd ... failed"); } $cmd = "remove scan_listener -y $force"; $rc = srvctl($run_as_owner, $cmd); if ($rc == FALSE) { trace ("srvctl $cmd ... failed"); } # stop/remove scan vip $cmd = "stop scan $force"; $run_as_owner = FALSE; $rc = srvctl($run_as_owner, $cmd); if ($rc == FALSE) { trace ("srvctl $cmd ... failed"); } # remove scan vip $cmd = "remove scan -y $force"; $rc = srvctl($run_as_owner, $cmd); if ($rc == FALSE) { trace ("srvctl $cmd ... failed"); } } sub RemoveHAResources #--------------------------------------------------------------------- # Function: Remove HA application resources # Args : 0 #--------------------------------------------------------------------- { trace ("Remove High Availability resources..."); my ($rc, $status); my $run_as_owner = FALSE; # Validate system command ValidateSRVCTL () || return FAILED; # remove ONS $rc = srvctl ($run_as_owner, "config ons"); if ($rc == TRUE) { # stop ons my $cmd = "stop ons"; if ($CFG->FORCE) { $cmd = "stop ons -f"; } $status = srvctl($run_as_owner, $cmd); if ($status == FALSE) { trace ("srvctl $cmd ... failed"); } # remove ons $cmd = "remove ons"; if ($CFG->FORCE) { $cmd = "remove ons -f"; } $status = srvctl($run_as_owner, $cmd); if ($status == FALSE) { trace ("srvctl $cmd ... failed"); } } } sub RemoveDrivers { my $chkpoints = $_[0]; ($CFG->compACFS)->deconfigureCurrentNode(); if (isOKAInstalled()) { crska::removeOKARoot($chkpoints); trace("OKA driver removed."); } # AFD can be installed after GI install. # Remove AFD if installed. if (isAFDInstalled()) { rm_afd_conf(); s_rm_afdinit_rclevel(); s_rm_afdinit_init(); oraafd::removeAFDRoot($chkpoints); } } sub DeleteSCR #------------------------------------------------------------------------------- # Function: Remove SCR dir/registry # Args : none #------------------------------------------------------------------------------- { if ($CFG->platform_family eq 'windows') { s_removeSCR(); } else { if (-d $CFG->params('SCRBASE')) { trace ("Cleaning up SCR settings in " . $CFG->params('SCRBASE')); rmtree ($CFG->params('SCRBASE')); } if (-d $CFG->params('OPROCDDIR')) { trace ("Cleaning oprocd directory, and log files"); rmtree ($CFG->params('OPROCDDIR')); } } } sub deinstallCleanup { if ($CFG->defined_param('HOME_TYPE')) { trace("Performing clean-up as part of deinstall ..."); my $crsdata_dir = catdir($CFG->params('ORACLE_BASE'), "crsdata"); my $diag_dir = catdir($CFG->params('ORACLE_BASE'), "diag"); removeSpecDir($diag_dir); # the crsdata directory needs to be removed last since it is used by # the other remove operations removeSpecDir($crsdata_dir); } } sub remove_misc_dirs { # Following directories and files are removed # only if root script is invoked from deinstall tool my $diagdir = catdir ($CFG->params('ORACLE_BASE'), 'oradiag_root'); my $mapdir = catdir ($CFG->params('OCRCONFIGDIR'), 'maps'); my $asmgidfile = catfile($CFG->params('OCRCONFIGDIR'), 'setasmgid'); if ($CFG->defined_param('HOME_TYPE')) { # remove oracle_base/oradiag_root,/etc/oracle/maps,/etc/oracle/setasmgid # & oracle_base/crsdata if (-e $diagdir) { trace ("Remove $diagdir"); rmtree ($diagdir); } if (-e $mapdir) { trace ("Remove $mapdir"); rmtree ($mapdir); } if (-e $asmgidfile) { trace("Remove $asmgidfile"); s_remove_file("$asmgidfile"); } } else { trace ("Root script is not invoked as part of deinstall. $diagdir, " . "$mapdir, and $asmgidfile are not removed"); } } sub removeSpecDir { my $specDir = $_[0]; my $rmlist; my $errors; trace("The dir to remove is '$specDir'"); if ((! $CFG->SIHA) && (isPathShared($specDir))) { trace("Attempt to remove the shared path '$specDir'"); if (($CFG->LASTNODE) && (-e $specDir)) { trace("Remove $specDir"); rmtree($specDir, {result => \$rmlist, error => \$errors}); } } else { trace("Attempt to remove the node specific dir '$specDir'"); if (-e $specDir) { trace("Remove $specDir"); rmtree($specDir, {result => \$rmlist, error => \$errors}); } } # The error variable is a reference to an array of hash references. foreach my $hashRef (@$errors) { my ($file, $message) = %$hashRef; print_error(647, $file, $message); } } sub HADeconfig { my $count = 0; trace ("Deconfiguring Oracle Restart on this node"); foreach my $stage (@HA_DECONFIG_STAGES) { my $name = $stage->{"name"}; my $checkpoint = $stage->{"checkpoint"}; my $func = $stage->{"sub"}; trace("Executing the [$name] step with checkpoint [$checkpoint] ..."); &$func(); $count++; } if ($count == scalar(@HA_DECONFIG_STAGES)) { set_bold(); print_info(337); reset_bold(); deinstallCleanup(); exit(0); } else { trace ("Failed to deconfigure Oracle Restart on this node"); set_bold(); print_error(589); reset_bold(); exit(1); } } sub ha_deconfig_resources { TraceOptions (); remove_checkpoints(); if (! $CFG->DOWNGRADE) { remove_checkpoint_index(); my $status = VerifyHAResources (); if ($status eq FAILED) { die(dieformat(312)); } # Only remove resources which were created during # Oracle Restart configuration RemoveHAResources (); } $CFG->compOLR(oraClusterwareComp::oraolr->new("OLR")); $CFG->compOCR(oraClusterwareComp::oraocr->new("OCR")); my $oraocr = $CFG->compOCR; stopFullStack_SIHA("force") || die(dieformat(348)); RemoveDrivers(NOTUSECHKPOINTS); s_RemoveInitResources(); $oraocr->s_ResetOCR(); } sub ha_deconfig_cleanup { DeleteSCR(); if ($CFG->platform_family eq "unix") { s_NSCleanUp(); } if ($CFG->platform_family eq 'windows') { s_houseCleaning(); } if (($CFG->defined_param('HOME_TYPE')) && ($CFG->platform_family eq 'unix')) { my $file = catfile($CFG->params('OCRCONFIGDIR'), 'setasmgid'); if (-f $file) { trace("Remove $file"); s_remove_file("$file"); } my $mapdir = catdir($CFG->params('OCRCONFIGDIR'), 'maps'); if (-e $mapdir) { trace ("Remove dir $mapdir"); rmtree ($mapdir); } } s_CleanTempFiles(); if ($CFG->defined_param('HOME_TYPE')) { trace ("Opening permissions on Oracle Restart home"); s_reset_crshome($CFG->params('ORACLE_OWNER'), $CFG->params('ORA_DBA_GROUP'), 755, $CFG->params('ORACLE_HOME')); } } sub deconfigure_ASM { trace ("De-configuring ASM..."); my $owner = $CFG->params('ORACLE_OWNER'); my $rc = FALSE; my $oraocr = $CFG->compOCR; my $status; # start stack up to CRSD if (! startExclCRS()) { if ($CFG->FORCE) { trace("Failed to start the stack in exclusive mode," ." but force option is passed"); print_error(260); $CFG->DECONFIG_ERROR(TRUE); return FALSE; } else { die(dieformat(260)); } } # Check if current cluster is client then do not execute ASM deconfiguration my $asm_mode; verify_gpnp_dirs($CFG->ORA_CRS_HOME, $CFG->params('GPNPGCONFIGDIR'), $CFG->params('GPNPCONFIGDIR'), $CFG->HOST, $CFG->params('ORACLE_OWNER'), $CFG->params('ORA_DBA_GROUP')); trace("Try to read ASM mode from the global stage profile"); ($rc, $asm_mode) = gpnp_get_asm_mode(get_peer_profile_file(FALSE)); if (0 != $rc) { trace("Try to read ASM mode from the node-specific profile"); ($rc, $asm_mode) = gpnp_get_asm_mode(get_peer_profile_file(TRUE)); } if (0 != $rc) { trace("Unable to get ASM mode from Oracle Clusterware GPnP profile"); $CFG->DECONFIG_ERROR(TRUE); return FALSE; } trace("ASM mode = $asm_mode"); # abort the deconfig if there is a member cluster using the diskgroup # memeber clusters can be created only on a Domain Services Cluster. # Member clusters can be Windows, but not DSC. if (isDSCConfigured()) { trace("Check for Member clusters"); clientClusterCheck($asm_mode); } stop_crsd_and_check($CFG->ORA_CRS_HOME); if (ASM_MODE_CLIENT eq $asm_mode ) { if (! removeAllVotingDisks($asm_mode)) { trace("Unable to delete voting files in exclusive mode"); $CFG->DECONFIG_ERROR(TRUE); return FALSE; } trace("Skip calling ASMCA and only remove the OCR and OCR backup on DG"); removeClusterFilesOnDG($asm_mode); $oraocr->removeOCROnDG($asm_mode); $rc = ($CFG->DECONFIG_ERROR) ? FALSE : TRUE; return $rc; } # ASM_DROP_DISKGROUPS is valid only if the root script is invoked # from the deinstall tool, and we pass -reuseDiskgroup to asmca if # ASM_DROP_DISKGROUPS is set to false. # # $CFG->KEEPDG can be set along with -deconfig my $keepDG = FALSE; if ((($CFG->defined_param('ASM_DROP_DISKGROUPS')) && ('false' eq $CFG->params('ASM_DROP_DISKGROUPS'))) || $CFG->KEEPDG) { $keepDG = TRUE; removeClusterFilesOnDG($asm_mode); $oraocr->removeOCROnDG($asm_mode); } bounce_ohasd(); trace("Disable ASM to avoid race issue between ASM agent and ASMCA."); my $node = $CFG->HOST; my $resName = 'ora.asm'; my $CRSCTL = crs_exec_path('crsctl'); my $attr = "\"ENABLED\@SERVERNAME($node)=0\""; my @cmd = ($CRSCTL, 'modify', 'resource', $resName, '-attr', $attr, '-init'); my @out = system_cmd_capture(@cmd); my $crsctl_rc = shift @out; if (0 != $crsctl_rc) { print_lines(@out); trace(join(' ', @cmd) . " failed with status $crsctl_rc"); if ($CFG->FORCE) { print_error(180, join(' ', @cmd)); $CFG->DECONFIG_ERROR(TRUE); } else { die(dieformat(180, join(' ', @cmd))); } } else { trace("Successfully disabled ASM resource."); } # call asmca -deleteLocalASM to delete diskgroup # Do not change the order of these parameters as asmca requires the # parameters to be in a specific order or it will fail my @runasmca = (catfile ($CFG->ORA_CRS_HOME, "bin", "asmca"), '-silent', '-deleteLocalASM'); my $dgList; if ($CFG->defined_param('HOME_TYPE')) # deconfig is called from deinstall { trace("Starting CSS exclusive"); my $css_rc = CSS_start_exclusive(); if ($css_rc != CSS_EXCL_SUCCESS) { trace ("CSS failed to enter exclusive mode to de-configure ASM"); $CFG->DECONFIG_ERROR(TRUE); return FALSE; } $dgList = $CFG->params('OCR_VD_DISKGROUPS'); } else { my @diskgroups = getOCRVotingDiskgroups(); $dgList = join(",", @diskgroups); my $backupDG = $CFG->params('CDATA_BACKUP_DISK_GROUP'); if ($backupDG) { trace("Backup disk group to be dropped: $backupDG"); $dgList = $dgList.",$backupDG"; } } trace("Dropping the diskgroups: $dgList ..."); if ($dgList =~ /\$/) { # if diskgroup contains '$', put single-quotes around it quoteDiskGroup($dgList); push @runasmca, '-diskGroups', "'$dgList'"; } else { push @runasmca, '-diskGroups', $dgList; } if (($CFG->defined_param('ASM_DISKSTRING')) && ($CFG->params('ASM_DISKSTRING'))) { my $disktring = $CFG->params('ASM_DISKSTRING'); push @runasmca, '-diskString', "'$disktring'"; } if (! removeAllVotingDisks($asm_mode)) { trace("Unable to delete voting files in exclusive mode"); $CFG->DECONFIG_ERROR(TRUE); return FALSE; } trace("keep DG = $keepDG"); if ($keepDG) { trace("Re-use existing diskgroups"); push @runasmca, '-reuseDiskgroup'; } #Adding additional arbitrary parameter to ASMCA. push @runasmca, $CFG->params('ASMCA_ARGS'); $ENV{'PARAM_FILE_NAME'} = $CFG->paramfile; my $ASMCA_log = catdir($CFG->params('ORACLE_BASE'), 'cfgtoollogs', 'asmca'); $status = run_as_user($owner, @runasmca); if ($status == 0) { # set remote asm to disabled in the gpnp profile $rc = disableRemoteASM(); if (SUCCESS != $rc) { trace("disable remote asm failed with error $rc"); print_error(170, $rc); $CFG->DECONFIG_ERROR(TRUE); return $rc; } trace ("disable remote asm success"); trace ("see asmca logs at $ASMCA_log for details"); } else { trace("de-configuration of ASM ... failed with error $status"); trace("see asmca logs at $ASMCA_log for details"); print_error(170, $status); $CFG->DECONFIG_ERROR(TRUE); } $CFG->compASM(oraClusterwareComp::oraasm->new("ASM")); # Deconfigure the local system files for audit log redirection # for ASM, IOS and APX instances my $oraasm = $CFG->compASM; if ($CFG->LASTNODE) { $oraasm->deconfigureLastNode(); } else { $oraasm->deconfigureNonLastNode(); } if($CFG->DECONFIG_ERROR) { trace("de-configuration of ASM ... failed"); return FALSE; } else { trace ("de-configuration of ASM ... success"); return TRUE; } } sub getOcrBackupWithKey { my $keyname = $_[0]; $keyname = "SYSTEM.rootcrs.".$keyname; my $crsHome = getCrsHome(); my $OCRDUMPBIN = catfile ($crsHome, 'bin', 'ocrdump'); trace("Get ocr backup file name with ocrdump"); if ($CFG->platform_family eq "windows") { open (OCRDUMP, "$OCRDUMPBIN -stdout -noheader -keyname $keyname |"); } else { open (OCRDUMP, "$OCRDUMPBIN -stdout -noheader -keyname '$keyname' |"); } my @output = ; close (OCRDUMP); trace("ocrdump output: @output"); if (scalar(grep (/$keyname/, @output)) > 0) { trace("The key pair with key name: $keyname exists in OCR."); my @txt = grep (/ORATEXT/, @output); my ($key, $value) = split (/:/, $txt[0]); $value = trim($value); trace("Ocrbackup info: $value"); return $value; } else { # ocrdump doesn't work or the ocr backup info is null in the first place return ""; } } sub prechecksDeconfig { trace("Perform prechecks for deconfiguration"); if ($CFG->LASTNODE && !$CFG->FORCE) { my $localNode = tolower_host(); trace("Checking whether current node $localNode has been deconfigured."); my $crsctl = catfile($CFG->ORA_CRS_HOME, 'bin', 'crsctl'); my $cmd = "$crsctl check crs"; my @output = system_cmd_capture($cmd); my $rc = shift @output; if (scalar(grep(/4047/, @output)) > 0) { trace("This node $localNode has been deconfigured."); set_bold(); print_info(561,$localNode); reset_bold(); exit(0); } } # following check make sure leaf node will not be left as the last node to # deconfig # In 12.2.0.1 user should make sure not leaving the LEAF node to be # deconfigured last. # checkLeafNodes() will be re-enable in 12.2.0.2 by the fix of bug 23713986 # checkLeafNodes(); } # ------------------------------------------------------------------------------ # Function: Removes various files and directories that belong to this cluster # from the DG. # Currently it removes the OCR backup and the Mgmtdb files. # ------------------------------------------------------------------------------ sub removeClusterFilesOnDG { my $asm_mode = $_[0]; my @diskgroups; my $ocrBackupDir; my $mgmtdbDir; my $clustername = $CFG->params('CLUSTER_NAME'); my $rc; ($rc, @diskgroups) = kfodListDiskgroups(); if ($rc != 0) { ($CFG->FORCE) ? $CFG->DECONFIG_ERROR(TRUE) : die(dieformat(655)); } if (scalar(@diskgroups) <= 0) { trace("No vote disk or OCR diskgroup found."); trace("There is no OCR backup file need to be removed from disk group."); return; } # Remove the OCR backup files on all disk groups setOraHomeSID($asm_mode); my $asmcmd = catfile($CFG->ORA_CRS_HOME, "bin", "asmcmd"); foreach my $diskgroup (@diskgroups) { $ocrBackupDir = "+"."$diskgroup"."/$clustername/OCRBACKUP/"; trace("Directory where OCR backup need to be removed: $ocrBackupDir"); removeFileOnDG($asm_mode, $ocrBackupDir, TRUE); $mgmtdbDir = "+"."$diskgroup"."/$clustername/_mgmtdb/"; trace("Directory where mgmtdb needs to be removed: $mgmtdbDir"); removeFileOnDG($asm_mode, $mgmtdbDir, TRUE); } } sub getOCRVotingDiskgroups { my @diskgroups; my @vfDiskgroups; my $oraocr = $CFG->compOCR; @diskgroups = $oraocr->discoverOCRDiskgroups(); @vfDiskgroups = extractDiskgroups(); if (scalar(@vfDiskgroups) <= 0) { trace("No diskgroups with voting disks found"); } else { my $vfDG = $vfDiskgroups[0]; trace("The diskgroup to store voting files: $vfDG"); if (scalar(grep(/^$vfDG$/, @diskgroups)) <= 0) { trace("The different DG to store voting files"); push(@diskgroups, $vfDG); } } trace("All diskgroups used by Clusterware: @diskgroups"); return @diskgroups; } # Function: check if there is any ASM, GIMR and RHP client cluster using the diskgroup sub clientClusterCheck { my $asm_mode = $_[0]; # The check for client clusters is done by the deinstall tool for deinstall. return SUCCESS if($CFG->defined_param('HOME_TYPE')); my @capout; setOraHomeSID($asm_mode); my $crsHome = $CFG->ORA_CRS_HOME; trace("CRS HOME: $crsHome"); my $asmcmd = catfile($crsHome, "bin", "asmcmd"); my @cmd = ($asmcmd, "lscc", "--suppressheader", "-l"); my $rc = run_as_user2($CFG->params('ORACLE_OWNER'), \@capout, @cmd); trace("rc: $rc"); trace("Output: @capout"); if ($rc != 0) { trace("Failed to check whether there is any ASM, GIMR and/or RHP client cluster using ". "the diskgroup"); if ($CFG->DECONFIG && $CFG->FORCE) { print_error(180, join(' ', @cmd)); $CFG->DECONFIG_ERROR(TRUE); return FAILED; } else { die(dieformat(180, join(' ', @cmd))); } } # 'asmcmd lscc' will return 'ASMCMD-9489' if no client clusters configured elsif(scalar(grep(/ASMCMD-9489/, @capout)) > 0) { trace("ASM, GIMR and RHP client clusters are not using the diskgroup"); return SUCCESS; } else { # 'asmcmd lscc' will display all client clusters after the # change to a single credentials file. # parse the client cluster name from the outputs # example of output: # ASMCMD [+] >lscc --suppressheader -l # clientcluster1 12.2.0.0.0 c79b52d26a37efdfff7d5df32413bae6 ASM,GIMR,RHP # Test-CC23AFDEF 12.2.0.0.0 abe0068a87a6ef35ff710cf8e8355d36 ASM foreach my $line (@capout) { $line = trim($line); my @word = split(/\s+/, $line); trace("The Client cluster $word[0] is using service(s) $word[3] on ". "the diskgroup configured on this server cluster"); print_error(562, $word[0], $word[3]); } if ($CFG->DECONFIG && $CFG->FORCE) { $CFG->DECONFIG_ERROR(TRUE); return FAILED; } else { trace("Abort the deconfig"); exit 1; } } } 1;