#!/usr/local/bin/perl # # $Header: has/install/crsconfig/crska.pm /main/12 2016/04/18 01:27:21 bbeelamk Exp $ # # crska.pm # # Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. # # NAME # crska.pm - Library module for Kernel Accelarator root install functions. # # DESCRIPTION # crska.pm - Contains initial installation and deinstallation # routines for OKA (Kernel Accelarator). # # NOTES # # MODIFIED (MM/DD/YY) # bbeelamk 04/13/16 - Fix bug 23095140 # muhe 03/09/16 - Fix bug 22894801: Cache and reuse the result of # 'okadriverstate supported' # diguma 06/04/15 - bug21202075: need to fix the check for allowing KA # installation # emarron 05/28/15 - Print checkpoints only when enabled in removeOKARoot # emarron 03/20/15 - Bring perform_installKADriver from crsinstall.pm # emarron 02/26/15 - Add isOKAInstalled function # xyuan 09/02/14 - rsc modeling # emarron 06/30/14 - Disable by default, enable only on Exadata # hmbui 02/06/14 - Add proper handling for KA Driver install/upgrade/ # deconfig/downgrade. # xyuan 08/22/13 - Remove compilation warnings # ssprasad 06/29/12 - 'okaroot install' failures are ignored for root # scripts. Also, remove temporary disabled OKA code. # ssprasad 06/26/12 - Temporarily disable OKA # ssprasad 05/08/12 - Initial Creation # =head1 NAME crska.pm RAC Kernel Accelarator component configuration/startup package =head1 DESCRIPTION This package contains functions required for initial configuration and startup of the KA drivers. =cut package crska; use strict; use English; use File::Temp qw/ tempfile /; use File::Spec::Functions; use File::Find (); use Term::ANSIColor; use crsutils; # Centralizing future name changes use constant OKA_RESOURCE_NAME => 'ora.drivers.oka'; use constant OKA_RESOURCE_TYPE => 'ora.oka.type'; use Exporter; use vars qw(@ISA @EXPORT @EXPORT_OK); @ISA = qw(Exporter); my @exp_func = qw(perform_installKADriver installOKADriver disableOKADriver deleteOKADriver removeOKARoot actionOKADriversResource isOKASupported isOKAInstalled); push @EXPORT, @exp_func; =head2 perform_installKADriver Calls installOKADriver but first check supported and manage checkpoints =head3 Parameters None =head3 Returns TRUE - Configuration successful FALSE - Configuration failed =head3 Notes =cut sub perform_installKADriver { my $has = "crs"; # We print checkpoint since even usupported platforms should consider # completion of the function as a success. if (!isCkptexist("ROOTCRS_OKAINST")) { trace("Writing checkpoint for OKA driver install"); writeCkpt("ROOTCRS_OKAINST", CKPTSTART); $CFG->wipCkptName("ROOTCRS_OKAINST"); } # # Unconditionally perform_installKADriver() is called # by the caller. Hence, we need to check if OKA # is supported before proceeding. # if (!isOKASupported()) { # If OKA not supported, # then assume everything is okay. trace("OKA is not supported on this platform."); writeCkpt("ROOTCRS_OKAINST", CKPTSUC); $CFG->wipCkptName("ROOTCRS_STACK"); return; } if (!isCkptSuccess("ROOTCRS_OKAINST")){ $CFG->wipCkptName("ROOTCRS_OKAINST"); # install okaroot kernel my $ret = installOKADriver($has); if (FAILED == $ret) { # This is some failure that doesn't relate to driver load\unload. # For instance, this could be an issue generating symbols. print_error(2007); writeCkpt("ROOTCRS_OKAINST", CKPTFAIL); exit 1; } elsif (REBOOT == $ret) { # We couldn't unload the old drivers or load the new ones. # CRS is now disabled, so the user can reboot and try again. trace("OKA drivers unable to be installed."); set_bold(); print_error(400); reset_bold(); writeCkpt("ROOTCRS_OKAINST", CKPTFAIL); exit 1; } elsif (WARNING == $ret) { # # In case of driver install/load failure, # we just proceed without enabling the # OKA resource. # # Warning ! trace("OKA install failed. Continuing with rest of the installation."); writeCkpt("ROOTCRS_OKAINST", CKPTSUC); $CFG->wipCkptName("ROOTCRS_STACK"); } else { # It worked! trace("OKA drivers installation completed"); writeCkpt("ROOTCRS_OKAINST", CKPTSUC); $CFG->wipCkptName("ROOTCRS_STACK"); } } } =head2 installOKADriver Installs OKA - kernel and user components via okaroot. =head3 Parameters None =head3 Returns TRUE - Configuration successful FALSE - Configuration failed =head3 Notes =cut sub installOKADriver { my $okaroot; my $ret = SUCCESS; my $crsctl = crs_exec_path('crsctl'); my ($has) = @_; # if we are running in development mode, then limit support to only when # the appropriate env variables are set trace("installOKAdriver"); if (is_dev_env()) { my $okaInstall = uc($ENV{'ORA_ENABLE_OKA_INSTALL'}); # if this ENV is not set then we give up early if ( $okaInstall ne "TRUE" ) { trace("OKA disabled because of ENV in test mode"); return $ret; } } if ($CFG->platform_family eq 'windows') { $okaroot = catfile ($CFG->ORA_CRS_HOME, 'bin', 'okaroot.bat'); } else { $okaroot = catfile ($CFG->ORA_CRS_HOME, 'bin', 'okaroot'); } if (-e $okaroot) { my $cmd = "$okaroot install"; trace("Executing '$cmd'"); my @output = system_cmd_capture($cmd); my $rc = shift @output; if ($rc == 0) { my $enable = "$crsctl enable $has"; my @output = system_cmd_capture($enable); my $rc = shift @output; trace ("$cmd ... success"); if ($rc != 0) { trace("$enable .... unable to enable CRS."); print_error(2000); $ret = FAILED; } else { trace("$enable .... success."); } # Now that it is up and running we stop it and deactivate it $cmd = "$okaroot stop"; trace("Executing '$cmd'"); @output = system_cmd_capture($cmd); $rc = shift @output; trace( "$cmd ... rc: $rc" ); $cmd = "$okaroot deactivate"; trace("Executing '$cmd'"); @output = system_cmd_capture($cmd); $rc = shift @output; trace( "$cmd ... rc: $rc" ); } elsif ($rc != 2) { # # 629 covers unload failures. # 650 covers install and load failures. # (driver currently running, driver in use can't copy file etc.) # When we get above mentioned errors, we expect a # reboot will fix them. # # But, for now, we consider all non-success 'rc' to be same. # For any 'okaroot install' failure, we don't block # root scripts from proceeding. We return WARNING # and log a message in trace file. # # If OKA install/load fails, customer needs to manually # invoke the respective commands to enable KA. # We return WARNING to let root script proceed. # trace("OKA is supported on this platform, but install failed($rc)."); $ret = WARNING; } } else { trace("$okaroot not found"); if (isOKASupported()) { # if okaroot not found and OKA supported, we have a problem # some required files are not here. trace("OKA is supported on this platform, but install files are missing."); $ret = FAILED; } else { # If okaroot not found and OKA not supported, # then assume everything is okay. trace("OKA is not supported on this platform."); $ret = SUCCESS; } } trace("OKA driver install status is $ret"); return $ret; } sub removeOKARoot #------------------------------------------------------------------------------- # Function: remove OKA drivers #------------------------------------------------------------------------------- { my $chkpoints = $_; my $okaroot; my $has = "crs"; my $crsctl = catfile ($CFG->ORA_CRS_HOME, "bin", "crsctl"); if ($CFG->platform_family eq 'windows') { $okaroot = catfile ($CFG->ORA_CRS_HOME, 'bin', 'okaroot.bat'); } else { $okaroot = catfile ($CFG->ORA_CRS_HOME, 'bin', 'okaroot'); } if (! (-e $okaroot)) { trace ("OKA is not configured"); return; } if ( $chkpoints == USECHKPOINTS ) { if (!isCkptexist("ROOTCRS_OKAUNINST")) { trace("Writing checkpoint for OKA driver uninstall"); writeCkpt("ROOTCRS_OKAUNINST", CKPTSTART); $CFG->wipCkptName("ROOTCRS_OKAUNINST"); } } if (($chkpoints == NOTUSECHKPOINTS) || (!isCkptSuccess("ROOTCRS_OKAUNINST"))) { $CFG->wipCkptName("ROOTCRS_OKAUNINST"); my @cmd = ($okaroot, 'uninstall'); trace ("Executing @cmd"); my @output = system_cmd_capture(@cmd); my $rc = shift @output; if ( $rc == 0 ) { trace ("@cmd ... success"); trace("OKA drivers uninstall completed"); # Only try a re-enable if we had previously failed. # AND we are in the DOWNGRADE process # This is because we only require a reboot in the downgrade process. # See below. So we disable crs before reboot and enable it here. if ( (($chkpoints == NOTUSECHKPOINTS) || (getCkptStatus("ROOTCRS_OKAUNINST") == CKPTFAIL)) && ($CFG->DOWNGRADE) ) { my $enable = "$crsctl enable $has"; @output = system_cmd_capture($enable); $rc = shift @output; trace ("@cmd ... success"); if ($rc != 0) { trace("$enable .... unable to enable CRS."); print_error(2002); print_lines(@output); trace("$enable failed with status $rc"); exit 1; } else { trace("$enable .... success."); } } if ( $chkpoints == USECHKPOINTS ) { writeCkpt("ROOTCRS_OKAUNINST", CKPTSUC); } } elsif ( $rc != 2 ) { if ((scalar(grep(/9118/, @output))) || (scalar(grep(/9119/, @output))) || (scalar(grep(/9348/, @output))) > 0) { # We couldn't unload the old drivers or load the new ones. trace("OKA drivers unable to be uninstalled."); if ($CFG->DOWNGRADE) { print color 'bold'; print_error(2003); print color 'reset'; my $disable = "$crsctl disable $has"; trace("$disable ... disabling CRS in preparation for reboot."); @output = system_cmd_capture($disable); $rc = shift @output; if ($rc != 0) { trace("$disable ... unable to disable CRS for reboot."); # Don't fail here - the user should correct # the disable, by running it by hand, and reboot. print_error(2004); } else { trace("$disable ... CRS disabled, ready for reboot."); # At this point, CRS is disabled. The user will need # to reboot, rerun the operation. This will rely on # OPatch and OUI to print the appropriate error message. } } if ( $chkpoints == USECHKPOINTS ) { writeCkpt("ROOTCRS_OKAUNINST", CKPTFAIL); exit 1; } } } else { trace ("@cmd ... failed"); if ( $chkpoints == USECHKPOINTS ) { writeCkpt("ROOTCRS_OKAUNINST", CKPTFAIL); } exit 1; } } } sub isOKAResourceExisting { my $res = OKA_RESOURCE_NAME; my $crsctl = catfile ($CFG->ORA_CRS_HOME, "bin", "crsctl"); # Detect if the KA driver resource exists my @out = system_cmd_capture($crsctl, "stat", "res", $res, "-init"); my $foundError = grep (/CRS-2613/i, @out); my $resourceExists = !(scalar($foundError) > 0); trace("OKA resource exists: $resourceExists"); return $resourceExists; } =head2 actionOKADriversResource - Create/Upgrade/Start/Stop/Delete the OKA Drivers Resource, also Add/Delete start/stop dependency from a resource to the OKA Drivers Resource. =head3 Parameters $action - "add"/"upgrade"/"start"/"stop"/"delete"/"adddependency"/"deletedependency" actions for the drivers resource =head3 Returns TRUE - If the action was successfully performed. FALSE - Otherwise. =head3 Notes =cut sub actionOKADriversResource { my ($action, $dependency, $dependencyType, $dependencySource) = @_; my $crsctl = catfile ($CFG->ORA_CRS_HOME, "bin", "crsctl"); my $result = FAILED; if (isOKASupported()) { trace("Performing KA resource action: $action"); my $res = OKA_RESOURCE_NAME; my $resType = OKA_RESOURCE_TYPE; my $user = $CFG->params('ORACLE_OWNER');; my $grp = $CFG->params('ORA_DBA_GROUP'); my $owner = $CFG->SUPERUSER; my @oka_attr = ("ACL='owner:$owner:rw-,pgrp:$grp:rw-," . "other::r--,user:$user:rwx'"); if(!isOKAResourceExisting()) { # If an upgrade is attempted, and the resource doesn't exist, we need # to add it if(($action eq "add") || ($action eq "upgrade")) { $result = crsctlResource("add", $res, $resType, \@oka_attr); } } else { if($action eq "start" || $action eq "stop" || $action eq "delete") { my $statusOnline = FALSE; my $statusOffline = FALSE; if($action eq "start" || $action eq "stop") { # Get the status again just to be sure my @out = system_cmd_capture($crsctl, "stat", "res", $res, "-init"); $statusOnline = grep (/TARGET=ONLINE/i, @out); $statusOffline = grep (/TARGET=OFFLINE/i, @out); if(((scalar($statusOnline) > 0) && ($action eq "stop")) || ((scalar($statusOffline) > 0) && ($action eq "start"))) { $result = crsctlResource($action, $res); } } elsif($action eq "delete") { $result = crsctlResource($action, $res); } } elsif($action eq "adddependency" || $action eq "deletedependency") { my $depAttr; if($action eq "adddependency") { $depAttr = "+$dependency($res)"; } if($action eq "deletedependency") { $depAttr = "-$dependency($res)"; } if($dependencyType eq "start") { $depAttr = "START_DEPENDENCIES=\'$depAttr\'"; } elsif($dependencyType eq "stop") { $depAttr = "STOP_DEPENDENCIES=\'$depAttr\'"; } trace("Adding dependency: $depAttr"); $result = crsctlResource("modify", $dependencySource, $resType, $depAttr); } else { trace("Unexpected action: $action attempted on resource: $res"); $result = FAILED; } } trace("Action performed: $action on $res, status = $result"); } else { # If OKA not supported, # then assume everything is okay. trace("OKA is not supported on this platform."); $result = SUCCESS; } return $result; } =head2 isOKASupported Determines if this platform is an OKA supported platform by calling 'okadriverstate supported'. =head3 Parameters None =head3 Returns TRUE - OKA Supported FALSE - OKA Not Supported =head3 Notes =cut sub isOKASupported { my $OKA_supported = FALSE; my $okadriverstate; if (defined $CFG->OKASupported) { $OKA_supported = $CFG->OKASupported; trace ("isOKASupported: $OKA_supported"); return $OKA_supported; } if ($CFG->platform_family eq 'windows') { $okadriverstate = catfile($CFG->ORA_CRS_HOME, 'bin', 'okadriverstate.bat'); } else { $okadriverstate = catfile($CFG->ORA_CRS_HOME, 'bin', 'okadriverstate'); } # check if OKA is supported if (! (-e $okadriverstate)) { trace ("$okadriverstate not found"); goto CACHE_OKASUPPORTED; } my @cmd = ($okadriverstate, "supported"); my @out = system_cmd_capture(@cmd); my $rc = shift @out; if (($rc == 0 || (defined ($ENV{'ORA_OKA_INSTALL_FORCE'}) && $ENV{'ORA_OKA_INSTALL_FORCE'} eq "true")) && (!is_dev_env() || ($ENV{'ORA_ENABLE_OKA_INSTALL'} eq "true"))) { $OKA_supported = TRUE; trace ("OKA is supported"); } else { $OKA_supported = FALSE; trace ("OKA is not supported"); } CACHE_OKASUPPORTED: $CFG->OKASupported($OKA_supported); return $OKA_supported; } =head2 isOKAInstalled Determines whether OKA is installed by calling 'okadriverstate installed'. =head3 Parameters Silent Option =head3 Returns TRUE - OKA Installed FALSE - OKA Not Installed =head3 Notes =cut sub isOKAInstalled { my $silent = shift; my $OKA_installed = FALSE; my $okadriverstate; if ($CFG->platform_family eq 'windows') { #TODO make sure this whole option make sense for us $okadriverstate = catfile($CFG->ORA_CRS_HOME, 'bin', 'okadriverstate.bat'); } else { $okadriverstate = catfile($CFG->ORA_CRS_HOME, 'bin', 'okadriverstate'); } # check if oka is installed if (! (-e $okadriverstate)) { trace ("$okadriverstate not found"); return FALSE; } my @cmd = ($okadriverstate, "installed"); if ($silent) { push @cmd, '-s'; } trace("Running @cmd"); my @out = system_cmd_capture(@cmd); my $rc = shift @out; if ($rc == 0) { $OKA_installed = TRUE; trace ("OKA is installed"); } else { $OKA_installed = FALSE; trace ("OKA is not installed"); } return $OKA_installed; }