# # $Header: usm/src/cmds/acfsroot/acfsroot.pl /st_usm_11.2/7 2011/07/22 13:35:27 averhuls Exp $ # # acfsroot.pl # # Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. # # NAME # acfsroot.pl # # DESCRIPTION # install/uninstall USM components from the distribution files # See section 4.2.1 of Design Note Supporting USM Installation # # NOTES # acfsroot install -h [-s|-v] -l # install USM kernel drivers and commands. # acfsroot uninstall -h [-s|-v] -p # uninstall USM kernel drivers and commands. # acfsroot version_check -h -l # check if USM components are available for installation. # acfsroot enable [-h|-s|-v ] # enable ADVM/ACFS CRS resources. # acfsroot disable [-h|-s|-v] # disable ADVM/ACFS CRS resources. # # INSTALL ACTIONS # - verify that the user has root privs. # - checks that the proper install files exists # - unloads currently loaded drivers (if any). # - removes currently installed USM install files (if any). # - installs from the selected distribution files # - Loads the drivers to make sure that they load properly. # - Performs any required OSD actions, if needed. # # User output should be done in this file when possible to ensure # cross platform similarity in command look and feel. However, it is # understood that some OSD actions are specific to one platform only, # in which case it makes sense to do the output there. # # MODIFIED (MM/DD/YY) # averhuls 07/21/11 - XbranchMerge averhuls_crs_modify_and_more from main # averhuls 07/21/11 - reregister->enable, unregister->disable. # modify 9427 message. # averhuls 06/30/11 - return USM_REBOOT_RECOMMENDED on unload failures. # gsanders 06/30/11 - Backport gsanders_bug-12692110 from main # agraves 04/15/11 - Backport agraves_bug-12348303 from main # agraves 03/29/11 - Backport agraves_bug-11833948 from main # anjiwaji 03/23/11 - Add a verbose flag to wrap messages in acfslib. # Also reorganize the usage messages. # averhuls 03/15/11 - Backport averhuls_bug-11849923 from main # averhuls 10/26/10 - Alternative path location must be absolute - check # for it. # averhuls 09/02/10 - Add the "preserve" option to uninstall to # allow the preservation of the tunable parameters. # certan 06/28/10 - Pass $install_files_loc to uninstall() and # osds_usm_uninstall() as distribution files may be # needed during uninstall process # jinjche 06/02/10 - Add reregister and unregister subcommands for # managing CRS ACFS resources # agraves 04/10/10 - Change message 9316 to include the media location. # averhuls 03/17/10 - Return USM_NOT_SUPPORTED if the platform does not # support USM. # anjiwaji 02/10/10 - Change install and uninstall to check if any # drivers are running. # certan 11/25/09 - During the install process, pass the location # of install files to lib_unload_usm_drivers so # that new utilities can be used if the old # utilities cannot be found # agraves 04/30/09 - Make messages be consistent with Bill Manry's # review. # averhuls 03/17/09 - Correctly detect NT absolute paths in # get_oracle_home(). # averhuls 03/16/09 - Fix wrapper scripts if USM is not supported on # a machine. # averhuls 02/19/09 - Remove lib_osds references - everything goes thru # lib. # averhuls 01/30/09 - rename usm_ to acfs. # averhuls 01/21/09 - For version_check, list where it is searching for # media. # averhuls 12/23/08 - Use message catalog. # averhuls 11/06/08 - Fix Windows shiphome problem where the # "lib" directory might be "LIB". # averhuls 11/03/08 - Use library functions from usm_lib.pm. # averhuls 10/20/08 - Remove "USM" from print statements. # averhuls 10/14/08 - Search for usm_driver_state.pl not usm_driver_state # because that is common to all platforms. # averhuls 08/26/08 - convert constants implemented as variables to real # constants # averhuls 07/25/08 - Fix uninitialized error if executed on Redhat4. # -s only prints error messages (bug 7279974). # averhuls 07/02/08 - remove the -u option. # averhuls 04/11/08 - fix minor problems found during beta. # averhuls 03/13/08 - Improve printing. change usm_log_error() calls # to usm_print(). Use usm_driver_state rather # than an internal OSD function to determine # if USM drivers are loaded. # averhuls 02/14/08 - minor cleanup. # averhuls 12/18/07 - Enhancement. if no install media found, list where # it was liiking for them # averhuls 11/12/07 - move root validation to osd code # averhuls 10/16/07 - Look for media in the default location unless -l is # specified. # averhuls 10/08/07 - Add switch to tell if a suitable RPM is available. # averhuls 06/29/07 - Creation # use strict; use Getopt::Std; use Cwd; use Cwd 'abs_path'; use File::Basename; use Switch; use English; use acfslib; use osds_acfsroot; sub main { my ($sub_command); # start or stop my ($preserve) = 0; # uninstall: preserve tunable files - default = no. my ($return_code); # as the name implies # user options my (%opt); # user options hash - used by getopts() my ($install_kernel_vers); # -k : install kernel version (other than current) my ($install_files_loc); # -l : location(s) of the distribution files # -s : silent operation - no console output # -v : verbose operation - additional output # -h : help # user flags. See description above or usage message output my (%flags) = ( install => 'hsvk:l:', uninstall => 'hsvp', enable => 'hsv', disable => 'hsv', version_check => 'hl:k:', ); # supplied by the front end driver and 'guaranteed' to be there. # command is what the user actually typed in (sans directories). $COMMAND = shift(@ARGV); # supplied by user $sub_command = shift(@ARGV); # determine $ORACLE_HOME for this system get_oracle_home(); # Enable command line access to library functions if (defined($sub_command) && ($sub_command eq 'lib_run_func')) { exit lib_run_func "@ARGV"; } if (!lib_usm_supported()) { # OSD specific message generated in lib_usm_supported(). if ($sub_command eq "install") { # Resolve ORACLE_HOME in the "wrapper scripts". osds_fix_wrapper_scripts(); exit USM_NOT_SUPPORTED; } elsif ($sub_command eq "enable") { # Enable requires a previous installation. exit USM_NOT_SUPPORTED; } else { # all other sub-commands fall through. } } # sub commands "install", "uninstall", "enable", "disable", or "version_check" # must be supplied by the user. if (defined($sub_command)) { if (!(($sub_command eq 'install') || ($sub_command eq 'uninstall') || ($sub_command eq 'enable') || ($sub_command eq 'disable') || ($sub_command eq 'version_check'))) { # illegal sub-command usage("invalid", 0); exit USM_FAIL; } } else { # no sub-command usage("invalid", 0); exit USM_FAIL; } # parse user options %opt=(); getopts($flags{$sub_command}, \%opt) or usage($sub_command, 1); if ($opt{'k'}) { $install_kernel_vers = $opt{'k'}; } if ($opt{'p'}) { $preserve = 1; } if ($opt{'l'}) { $install_files_loc = $opt{'l'}; if (! File::Spec->file_name_is_absolute($install_files_loc)) { lib_error_print(9388, "An absolute path name must be specified for the alternate location."); exit USM_FAIL; } } if ($opt{'h'}) { # print help information usage($sub_command, 0); exit USM_SUCCESS; } if ($opt{'s'} && $opt{'v'}) { lib_error_print(9160, "Can not use the silent and verbose options at the same time."); exit USM_FAIL; } if ($opt{'s'}) { # do not generate console output - default is not silent. $SILENT = 1; } if ($opt{'v'}) { # Generate additional console output - default is not verbose. $VERBOSE = 1; } ##### command parsing complete ##### # perform required OSD initialization, if any. $return_code = osds_initialize($install_kernel_vers, $sub_command); if ($return_code != USM_SUCCESS) { # error messages generated by osds_initialize(). exit USM_FAIL; } # use the default location for media unless the user specified otherwise if (!defined($install_files_loc)) { $install_files_loc = $USM_DFLT_MEDIA_LOC; } # version availability checks don't require privileged access if ($sub_command eq 'version_check') { # check the availability of USM components $return_code = version_check($install_kernel_vers, $install_files_loc); exit $return_code; } # verify root access if (!lib_am_root()) { lib_error_print(9130, "Root access required"); exit USM_FAIL; } if ($sub_command eq 'install') { # install the USM components $return_code = install($install_kernel_vers, $install_files_loc); } else { if ($sub_command eq 'uninstall') { # uninstall the USM components # pass $install_files_loc to uninstall() as distribution files may be # needed during uninstall process $return_code = uninstall($install_files_loc, $preserve); } else { if ($sub_command eq 'enable') { # enable the ACFS resources $return_code = enable(); } else { if ($sub_command eq 'disable') { # disable the ACFS resources $return_code = disable(); } } } } exit $return_code; } # end main sub install { my ($install_kernel_vers, $install_files_loc,) = @_; my ($no_load) = 0; # Do not load the newly installed bits. my ($preserve) = 1; # Any tunable files are preserved. my ($return_code); my ($kernel_version) = osds_get_kernel_version(); my ($reboot_recommended) = 0; if (defined($install_kernel_vers)) { # We're installing USM for another kernel version - do not attempt to # load the drivers. The presumed scenario is that the user wants to # install USM for an about to be upgraded kernel. This way, USM can # be up and running upon reboot. Dunno if anyone will ever use this. $kernel_version = $install_kernel_vers; $no_load = 1; } # First, find the distribution files from which to install # No point in going on if they can't be found. $return_code = osds_search_for_distribution_files($install_files_loc); if ($return_code == USM_SUCCESS) { lib_inform_print(9300, "ADVM/ACFS distribution files found."); } else { lib_error_print(9301, "ADVM/ACFS installation can not proceed:"); if (defined($install_files_loc)) { lib_error_print(9317, "No ADVM/ACFS distribution media detected at " . "location: '%s'", $install_files_loc); } else { lib_error_print(9303, "No installation files found for OS kernel version %s.", $kernel_version); } return USM_FAIL; } # Can't continue if the currently loaded drivers can't be unloaded $return_code = lib_unload_usm_drivers($install_files_loc); if ($return_code != USM_SUCCESS) { if ($return_code == USM_REBOOT_RECOMMENDED) { lib_error_print(9427, "Failed to unload ADVM/ACFS drivers. A system reboot is recommended."); $reboot_recommended = 1; } else { lib_error_print(9304, "Installation cannot proceed: Failed to unload ADVM/ACFS drivers."); return $return_code; } } # Search for a previous installation and remove it if found. if (lib_check_any_driver_installed()) { # Pass $install_files_loc to uninstall() as distribution files may be # needed during uninstall process if (uninstall($install_files_loc, $preserve) == USM_FAIL) { lib_error_print(9305, "ADVM/ACFS installation can not proceed:"); lib_error_print(9306, "Failed to uninstall previous installation."); return USM_FAIL; } } # We have distribution files and no USM components are currently # installed or loaded - we can proceed with the installation. lib_inform_print(9307, "Installing requested ADVM/ACFS software."); # osds_search_for_distribution files() has set which files need # to be installed. $return_code = osds_install_from_distribution_files($reboot_recommended); if ($return_code == USM_SUCCESS) { if ($no_load == 0) { lib_inform_print (9308, "Loading installed ADVM/ACFS drivers."); } # ensure that all utilities and drivers are where they are expected to be $return_code = osds_load_and_verify_usm_state($no_load); if ($return_code == USM_SUCCESS) { if ($reboot_recommended) { $return_code = USM_REBOOT_RECOMMENDED; } lib_inform_print(9309, "ADVM/ACFS installation correctness verified."); } else { lib_error_print(9310, "ADVM/ACFS installation failed."); lib_error_print(9311, "not all components were detected after the installation."); } } else { lib_error_print(9310, "ADVM/ACFS installation failed."); } return $return_code; } # end install # Enable ACFS drivers and registry resources sub enable { my $ret = USM_SUCCESS; my $ret1 = USM_SUCCESS; # We are guaranteed here that the ADVM/ACFS supports this OS. if ((lib_check_drivers_installed() == 0) || (lib_check_drivers_loaded() == 0)) { lib_error_print(9167, "ADVM/ACFS is not installed or loaded. Run 'acfsroot install'."); return USM_FAIL; } if (! -e "$ORACLE_HOME/bin/crsctl") { lib_error_print(5062, "cannot query CRS resource"); return USM_FAIL; } # For some reason, crsctl will sometimes return 0 even if # crs is down. I suppose this is because the command # executed successfully. open CRSCTL, "$ORACLE_HOME/bin/crsctl check crs |"; while () { if (/CRS-4639/) { lib_error_print(5062, "cannot query CRS resource"); close CRSCTL; return USM_FAIL; } } close CRSCTL; if ((usm_resource_exists("drivers") == USM_SUCCESS) && (usm_resource_exists("registry") == USM_SUCCESS)) { # Upgrade the resources. $ret1 = modify_usm_drivers_resource(); if ($ret1 != USM_SUCCESS) { $ret = USM_FAIL; } $ret1 = modify_usm_registry_resource(); if ($ret1 != USM_SUCCESS) { $ret = USM_FAIL; } } else { # Install and start the resources. $ret1 = add_usm_drivers_resource(); if ($ret1 != USM_SUCCESS) { $ret = USM_FAIL; } $ret1 = start_usm_drivers_resource(); if ($ret1 != USM_SUCCESS) { $ret = USM_FAIL; } $ret1 = add_acfs_registry(); if ($ret1 != USM_SUCCESS) { $ret = USM_FAIL; } $ret1 = start_acfs_registry(); if ($ret1 != USM_SUCCESS) { $ret = USM_FAIL; } } return $ret; } # Disable ACFS drivers and registry resources sub disable { my $ret = USM_SUCCESS; my $ret1 = stop_acfs_registry(); if ($ret1 != USM_SUCCESS) { $ret = USM_FAIL; } $ret1 = delete_acfs_registry(); if ($ret1 != USM_SUCCESS) { $ret = USM_FAIL; } $ret1 = delete_usm_drivers_resource(); if ($ret1 != USM_SUCCESS) { $ret = USM_FAIL; } return $ret; } sub uninstall { my ($install_files_loc, $preserve) = @_; my ($return_code); # Search for a previous installation if (lib_check_any_driver_installed()) { lib_inform_print(9312, "Existing ADVM/ACFS installation detected."); } else { lib_error_print(9313, "No ADVM/ACFS installation detected."); return USM_SUCCESS; } # Can't continue if the currently loaded drivers can't be unloaded $return_code = lib_unload_usm_drivers(); if ($return_code != USM_SUCCESS) { return $return_code; } lib_inform_print(9314, "Removing previous ADVM/ACFS installation."); # Pass $install_files_loc to osds_usm_uninstall() as distribution files may # be needed during uninstall process $return_code = osds_usm_uninstall($install_files_loc, $preserve); if ($return_code == USM_SUCCESS) { lib_inform_print(9315, "Previous ADVM/ACFS components successfully removed."); } return $return_code; } # end uninstall sub version_check { my ($install_kernel_vers, $install_files_loc) = @_; my ($return_code); my ($kernel_version) = osds_get_kernel_version(); $return_code = osds_search_for_distribution_files($install_files_loc); if ($return_code == 0) { lib_inform_print(9316, "Valid ADVM/ACFS distribution media detected at: '%s'", $install_files_loc); } else { lib_error_print(9317, "No ADVM/ACFS distribution media detected at " . "location: '%s'", $install_files_loc); } return $return_code; } # end check ################################################ # The following are static functions. ################################################ # There are 3 different ways of getting ORACLE_HOME: # 1) From the environment. This may be set by rootcrs or the user. # 2) From the current location of the command. # 3) From the crsconfig_params file. # deinstall tree - Oracle provides a package of software # that contains all the tools necessary to remove the # Oracle software - this is called the deinstall. # In the event that you remove the Grid Home from # your system, this is the standalone deinstall, # although it currently doesn't work. Our deinstall # is part of this throught the deinstall mapfiles. # There are 5 different uses of the env ORACLE_HOME: # 1) From the deinstall tree - if the Grid Home that is being removed # is gone, it will point to non-existent Grid Home. # 2) From the deinstall tree, pointing to the Grid Home to remove. # 3) From the rootcrs.pl during install. # 4) From the rootcrs.pl during deinstall, but not from the deinstall tree. # 5) And the final one, manually during our patching procedures. # In all cases, we don't fully trust the passed in ORACLE_HOME, as the # user may have incorrectly set it. We also don't really want to force # the user to set it, except in certain situations. # So, we rely on a heuristic, which should catch all cases: # 1) Find out where we are running from. In most cases, acfsroot.pl # will run from ORACLE_HOME/lib. (The only case this isn't true for # is an ACFS only patch or a command line manual install.) # 2) Find out what the passed in ORACLE_HOME is. # 3) See if either discovered or passed in ORACLE_HOME has a crsconfig_params # file. # 4) Get ORACLE_HOME from the params file. # 5) Use the param file ORACLE_HOME for comparison if it exists, or the env # if it doesn't. # 6) Convert both the passed in or params ORACLE_HOME (if it exists) and the # discovered "ORACLE_HOME" to an absolute path, which will # correctly dereference all symlinks in the path. Compare these # two values. If they match, then use the passed in\params ORACLE_HOME, # and assume that it is correct (most times it will be coming from # rootcrs). This will cover most normal installs, and will # catch symlinks. # 7) If they do not match, then use the discovered value. This is # because during deinstall, one of two things can happen: # a) We are running from the deinstall tree, and the ORACLE_HOME # that is passed in is not valid. We want to use our tools out # of the deinstall tree. # b) We are running from the deinstall tree, and the ORACLE_HOME # that is passed in is valid, but it doesn't matter to us, # we still use our tools out of the deinstall tree. # And during install, one of 3 things can happen: # a) We are running from rootcrs, and the value matches. # b) We are running from the command line during a manual patch\install # and the user has the incorrect ORACLE_HOME specified. In # this case, assume we are running from the GridHome. (However, # this case will be covered by getting it from the params file.) # Bug 11833948 was a bug where the OH was a symlink, yet we used the # real path of the directory. This resulted in not being able to contact # the ASM instance for some reason. Changing the OH to the symlinked # path made things work again. sub get_oracle_home { my ($dir) = dirname($0); # $0 is built in acfstoolsdriver.{sh,bat} my $discovered_ORACLE_HOME; # the ORACLE_HOME from bin location. my $param_ORACLE_HOME; # the ORACLE_HOME in the param file. my $env_ORACLE_HOME; # the ORACLE_HOME in the env. my $compare_ORACLE_HOME; # the final choice we are comparing against. my $paramfile = ""; # The location of the parameter file. if (defined($ENV{SRCHOME})) { # We're in a development environment, we'll use that $ORACLE_HOME. $ORACLE_HOME = $ENV{ORACLE_HOME}; return; } # We're in a production environment. # This file lives in $ORACLE_HOME/lib - drop the trailing /lib $dir =~ s/\/lib$//; # This is where we are running from. $discovered_ORACLE_HOME = $dir; # Remove any trailing '\n's. chomp($discovered_ORACLE_HOME); # Now the env location, for safety. if (defined($ENV{ORACLE_HOME})) { $env_ORACLE_HOME = $ENV{ORACLE_HOME}; chomp($env_ORACLE_HOME); } # Now we try to get the information from the params file, # just in case it matches somewhere else. # We use this param file in a few places now... should we # have a function to access it and get info? # Most times we are running out of the grid home, or a place with # a crsconfig_params. $paramfile = $discovered_ORACLE_HOME . "crs/install/crsconfig_params"; if ( ! -e $paramfile ) { # Try the location of the env ORACLE_HOME for kicks. $paramfile = $env_ORACLE_HOME . "/crs/install/crsconfig_params"; } # This will fail if $paramfile doesn't exist, leaving us with nothing. open PARAMS, $paramfile; while () { if (m/^ORACLE_HOME/) { my @LINE = split /=/; $param_ORACLE_HOME = $LINE[$#LINE]; # Remove any trailing '\n's chomp($param_ORACLE_HOME); last; } } close (PARAMS); # Now, compare the env and the param file. If they are different, use # the param file (assuming it is not null). # If they are the same, use the param file. # If we couldn't get to the param file, use the env location. if (defined($param_ORACLE_HOME) ) { $compare_ORACLE_HOME = $param_ORACLE_HOME; } else #param is not defined. { if (defined($env_ORACLE_HOME)) { $compare_ORACLE_HOME = $env_ORACLE_HOME; } } # Now, compare the abs_path of all dirs found and use the one we trust. if (abs_path($compare_ORACLE_HOME) eq abs_path($discovered_ORACLE_HOME)) { # This will take into account symlinks. $ENV{ORACLE_HOME} = $compare_ORACLE_HOME; } else { # They differed (after abs_path), so assume the user # had something wrong somewhere, and use what we know # to be true. # Or the user is running deinstall, where ORACLE_HOME can point # to some invalid location not consistent with where we are # running out of. # This is okay - the system location of our files won't # change, and that's where we want to remove things from. # OUI can handle cleaning up the ORACLE_HOME, wherever it is. $ENV{ORACLE_HOME} = $discovered_ORACLE_HOME; } $ORACLE_HOME = $ENV{ORACLE_HOME}; } sub usage { my ($sub_command, $abort) = @_; if ($sub_command eq "install") { lib_error_print(9161, " acfsroot install: Install ADVM/ACFS components."); lib_error_print(9331, " %s [-h] [-s | -v] [-l ] [-k ]", "Usage: acfsroot install"); lib_error_print(9132, " [-h] - print help/usage information"); lib_error_print(9131, " [-s] - silent mode" . " (error messages only)"); lib_error_print(9159, " [-v] - verbose mode"); lib_error_print(9332, " [-l ] - location of the" . " distribution files"); } elsif ($sub_command eq "uninstall") { lib_error_print(9162, " acfsroot uninstall: Uninstall ADVM/ACFS" . " components."); lib_error_print(9338, " Usage: acfsroot uninstall [-h] [-s | -v]"); lib_error_print(9132, " [-h] - print help/usage information"); lib_error_print(9131, " [-s] - silent mode" . " (error messages only)"); lib_error_print(9159, " [-v] - verbose mode"); lib_error_print(9387, " [-p] - preserve tunable parameters"); } elsif ($sub_command eq "version_check") { lib_error_print(9163, " acfsroot version_check: Check ADVM/ACFS version."); lib_error_print(9385, " Usage: acfsroot version_check [-h] [-l ]" . " [-k ]"); lib_error_print(9132, " [-h] - print help/usage information"); lib_error_print(9332, " [-l ] - location of the" . " distribution files"); lib_error_print(9333, " (if not the default" . " location)"); lib_error_print(9335, " [-k ] - install kernel version" . " number"); lib_error_print(9336, " (if not the current kernel" . " version)"); } elsif ($sub_command eq "enable") { lib_error_print(9164, " acfsroot enable: Enable ADVM/ACFS CRS resources."); lib_error_print(9166, " %s [-h] [-s | -v]", "Usage: acfsroot enable"); lib_error_print(9132, " [-h] - print help/usage information"); lib_error_print(9131, " [-s] - silent mode" . " (error messages only)"); lib_error_print(9159, " [-v] - verbose mode"); } elsif ($sub_command eq "disable") { lib_error_print(9165," acfsroot disable: Disable ADVM/ACFS CRS resources."); lib_error_print(9166, " %s [-h] [-s | -v]", "Usage: acfsroot disable"); lib_error_print(9132, " [-h] - print help/usage information"); lib_error_print(9131, " [-s] - silent mode" . " (error messages only)"); lib_error_print(9159, " [-v] - verbose mode"); } else { lib_error_print(9337, "Usage: acfsroot [arguments]"); lib_error_print(9386, " For more information, use acfsroot -h"); } if ($abort) { exit USM_FAIL; } } # end usage main();