MINI MINI MANI MO
#
#
# osds_okaroot.pm
#
# Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
#
#
# NAME
# osds_okaroot.pm - Linux OSD component of okaroot.
#
# DESCRIPTION
# Purpose
# Install/uninstall OKA components.
#
# NOTES
# All user visible output should be done in the common code.
# this will ensure a consistent look and feel across all platforms.
#
#
use strict;
package osds_okaroot;
require Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw(
osds_fix_oka_wrapper_scripts
osds_oka_initialize
osds_oka_install_from_distribution_files
osds_oka_search_for_distribution_files
osds_load_and_verify_oka_state
osds_oka_uninstall
$MEDIA_FOUND
$ORACLE_HOME
$OKA_DFLT_DRV_LOC
);
use acfslib;
use osds_okalib;
use osds_unix_linux_okalib;
use okalib;
use osds_acfslib;
use osds_acfsroot;
our ($ORACLE_HOME) = $ENV{ORACLE_HOME};
my ($SHIPHOME_BASE_DIR) = "$ORACLE_HOME/usm/install";
our ($USM_DFLT_CMD_LOC) = "$SHIPHOME_BASE_DIR/cmds/bin"; # cmds media loc
our ($OKA_DFLT_DRV_LOC); # location of the drivers media
my ($MINUS_L_DRIVER_LOC);
our ($MEDIA_FOUND) = ''; # path name to media
# used for version_check
my ($ARCH) = `uname -i`; # Machine architecture - i386
chomp($ARCH);
my ($UNAME_R) = `uname -r`;
chomp($UNAME_R);
my ($no_init) = "";
$no_init = `/sbin/weak-modules -h | grep ^'--no-init'` if machine_is_RH();
chomp($no_init);
# We do not install/uninstall the commands destined for ORACLE_HOME - that
# is now done by the mapfiles during Oracle install/uninstall. We use
# <XXX>_COMPONENTS only to verify that the commands exist in their
# installed location.
# The exception are the commands destined to live in /sbin. Since OUI
# won't have permissions to copy these commands directly, we do it here.
my ($SBIN_DIR) = "/sbin";
my ($OH_BIN_DIR) = "$ORACLE_HOME/bin";
my ($OH_LIB_DIR) = "$ORACLE_HOME/lib";
my ($MESG_DST_DIR) = "$ORACLE_HOME/usm/mesg";
my ($USM_PUB_DST_DIR) = "$ORACLE_HOME/usm/public";
my ($CMDS_SRC_DIR) = "$SHIPHOME_BASE_DIR/cmds/bin";
my ($MESG_SRC_DIR) = "$SHIPHOME_BASE_DIR/../mesg";
my ($USM_LIB_SRC_DIR) = "$SHIPHOME_BASE_DIR/../lib";
my ($USM_PUB_SRC_DIR) = "$SHIPHOME_BASE_DIR/../public";
my (@OH_BIN_COMPONENTS) = (
"$OH_BIN_DIR/okaroot", "$OH_BIN_DIR/okaload",
"$OH_BIN_DIR/okadriverstate",
);
my (@OH_LIB_COMPONENTS) = (
"$OH_LIB_DIR/okatoolsdriver.sh", "$OH_LIB_DIR/okalib.pm",
"$OH_LIB_DIR/okaroot.pl", "$OH_LIB_DIR/osds_okaroot.pm",
"$OH_LIB_DIR/okaload.pl", "$OH_LIB_DIR/osds_okaload.pm",
"$OH_LIB_DIR/okadriverstate.pl", "$OH_LIB_DIR/osds_okadriverstate.pm",
"$OH_LIB_DIR/osds_okalib.pm", "$OH_LIB_DIR/osds_unix_linux_okalib.pm",
);
my (@MESG_COMPONENTS) = (
"$MESG_DST_DIR/okaus.msb",
);
my (@OH_COMPONENTS) = (@OH_BIN_COMPONENTS, @OH_LIB_COMPONENTS);
my ($DRIVER_DIR); # installed driver location
my ($minus_l_specified) = 0; # Alternate install location specified by user.
# set by osds_oka_search_for_distribution_files() and
# consumed by osds_oka_install_from_distribution_files()
my ($OIP_PATH, $GPL_PATH);
# make sure that /sbin is in the PATH - that's where modprobe lives
$ENV{PATH} .= ':/sbin';
my ($KVER); # kernel version being installed
# osds_oka_initialize
#
# Perform OSD initialization.
# Set OKA_DFLT_DRV_LOC - the location of the OKA installation driver media.
# We deduce the location of the other components from there.
#
sub osds_oka_initialize
{
my ($install_kver, $sub_command) = @_;
my ($vendor);
my ($type);
if (!defined($install_kver))
{
# use the current kernel version
$KVER = $UNAME_R;
}
else
{
# use the specified kernel version
# TODO we'll want to do some sanity checking here.
$KVER = $install_kver;
}
# we have already verified that we have a valid Linix type
$type = lib_osds_get_os_type();
$vendor = lib_osds_get_linux_vendor();
if (!((defined($ORACLE_HOME)) && (-e "$ORACLE_HOME/lib/okaroot.pl")))
{
lib_error_print_noalert(9389,
"ORACLE_HOME is not set to the location of the Grid Infrastructure home.");
return USM_TRANSIENT_FAIL;
}
# default media location - over-ride with the -l option
my ($base) = $SHIPHOME_BASE_DIR;
$OKA_DFLT_DRV_LOC = get_install_home_from_base($base, $type, $ARCH, $KVER);
# /sbin/weak-modules depends on /boot being accessible and the
# symvers-<kernel_version> file being present.
if (($sub_command eq "install") && machine_is_RH())
{
my ($symvers_file) = "symvers-" . $KVER . ".gz";
if (! -e "/boot/$symvers_file")
{
lib_error_print_noalert(625,
"OKA installation cannot proceed:");
lib_error_print_noalert(9158,
"Configuration file '%s' in the /boot directory does not exist.",
$symvers_file);
return USM_TRANSIENT_FAIL;
}
}
return USM_SUCCESS;
}
# osds_oka_install_from_distribution_files
#
# Install the OKA components from the specified distribution files
# The files have already been validated by the time we get here
# by osds_oka_search_for_distribution_files(). Also, any previous USM installation
# will have been removed.
#
use File::Path;
sub osds_oka_install_from_distribution_files
{
my ($component); # curent component being installed
my ($command); # current command being executed by system()
my ($ret); # return of individual copy commands
my ($return_code) = USM_SUCCESS;
# install drivers
# the drivers have been verified to exist so the copy will not fail
if (! -d $DRIVER_DIR)
{
mkpath($DRIVER_DIR, 0, 0755);
}
# Print the location of the driver files
lib_verbose_print (626, "OKA driver media location is '%s'",
$OIP_PATH);
foreach my $component (@OKA_DRIVER_COMPONENTS)
{
my ($source) = "$OIP_PATH/$component";
my ($target) = "$DRIVER_DIR/$component";
lib_verbose_print (9504, "Copying file '%s' to the path '%s'",
$source,
$target);
$command = "cp $source $target";
$ret = system ($command);
$return_code = USM_FAIL if $ret;
}
if ($minus_l_specified)
{
# Normally, the ORACLE_HOME/{bin,lib} components are installed via the
# mapfiles. But, when the user specifies an alternate location via the
# '-l' option on the command line, we need to install the alternate
# OH/{bin,lib} files also. The OH commands are, conveniently located
# with the sbin commands.
#
# If we are replacing existing files, we want to preserve the original
# file attributes.
foreach $component (@OH_COMPONENTS)
{
my (@array) = split /\//, $component;
my ($file) = $array[-1];
my ($target) = "$component";
my ($source);
my ($have_orig);
my ($uid, $gid);
$source = "$CMDS_SRC_DIR/$file";
$have_orig = 0;
if (-e $target)
{
use constant UID => 4;
use constant GID => 5;
$have_orig = 1;
# get the owner/group of the original file
($uid, $gid) = (stat($target))[UID,GID];
}
lib_verbose_print (9504, "Copying file '%s' to the path '%s'",
$source,
$target);
$ret = system ("cp $source $target");
$return_code = USM_FAIL if $ret;
if (($target =~ /\/bin\//) || ($component =~ /okatoolsdriver.sh/))
{
system("chmod 0755 $target");
}
else # lib
{
system("chmod 0644 $target");
}
if ($have_orig)
{
chown $uid, $gid, $target;
}
}
foreach $component (@MESG_COMPONENTS)
{
my (@array) = split /\//, $component;
my ($file) = $array[-1];
my ($target) = $component;
my ($source) = "$MESG_SRC_DIR/$file";
lib_verbose_print (9504, "Copying file '%s' to the path '%s'",
$source,
$target);
$ret = system ("cp $source $target");
$return_code = USM_FAIL if $ret;
}
# Copy the drivers and system commands to the install area so that
# subsequent "okaroot install"s will get the patched bits should
# the user forget to use the -l option. It also allows us to compare
# checksums on the drivers in the "install" area to the "installed"
# area at load time. This will catch situations where users installed
# new bits but did run "okaroot install".
my ($cmd_install_area) = "$ORACLE_HOME/usm/install/cmds/bin";
foreach $component (@OKA_DRIVER_COMPONENTS)
{
my (@array) = split /\//, $component;
my ($file) = $array[-1];
my ($source) = "$MINUS_L_DRIVER_LOC/$component";
my ($target) = "$OKA_DFLT_DRV_LOC/$file";
lib_verbose_print (9504, "Copying file '%s' to the path '%s'",
$source,
$target);
$ret = system ("cp $source $target");
$return_code = USM_FAIL if $ret;
}
}
return $return_code;
} # end osds_oka_install_from_distribution_files
# osds_oka_search_for_distribution_files
#
# Search the media location(s) specified by the user for valid components
#
sub osds_oka_search_for_distribution_files
{
my ($kernel_install_files_loc) = @_;
my (@install_loc_array);
my ($cur_loc); # current location (directory) being examined
my ($component); # current component (cmd/driver) being examined
my ($components_found) = "";# list of components detected
my ($components_missing) = 0; # set if one or more components are AWOL
my ($ret_code) = USM_SUCCESS;
# $kernel_install_files_loc is where the drivers and drivers related files
# live. - as of 11.2.0.3 and later, the commands are shipped in a separate
# directory.
if (!defined($kernel_install_files_loc))
{
return USM_FAIL;
}
# Look to see if an alternate location for the distribution was specified.
if ($kernel_install_files_loc ne $OKA_DFLT_DRV_LOC)
{
# -l option specified (we know that the path is fully qualified).
$minus_l_specified = 1;
# $kernel_install_files_loc is a misnomer for -l within this 'if clause',
# where it's really the the directory path up to and including "install" -
# but, what the heck. Once out of this clause, it really will mean the
# location of the kernel drivers.
# We use "install" as our starting point for finding our bits
# so it had better be there.
if (!($kernel_install_files_loc =~ /install$/))
{
# Error message generated by caller
return USM_TRANSIENT_FAIL;
}
# We have the "base" path, up to "install".
# It's time to find where the drivers are relative to that base.
my (@path_array) = split ("/", $OKA_DFLT_DRV_LOC);
my ($last_element) = $#path_array;
my ($driver_relative_path) = "";
my ($i);
for ($i = 1; $i <= $last_element; $i++)
{
# strip off all array elements of out default "base" location. What's
# left will be the parts of the driver relative path.
my ($element) = shift(@path_array);
if ($element eq "install")
{
last;
}
}
# Now assemble the driver relative path.
$last_element = $#path_array;
for ($i = 0; $i <= $last_element; $i++)
{
$driver_relative_path .= "$path_array[$i]/";
}
# We now know where the drivers and commands live in the '-l' location.
$CMDS_SRC_DIR = "$kernel_install_files_loc/cmds/bin";
$MESG_SRC_DIR = "$kernel_install_files_loc/../mesg";
$USM_LIB_SRC_DIR = "$kernel_install_files_loc/../lib";
$USM_PUB_SRC_DIR = "$kernel_install_files_loc/../public";
$MINUS_L_DRIVER_LOC = "$kernel_install_files_loc/$driver_relative_path";
$kernel_install_files_loc = $MINUS_L_DRIVER_LOC;
}
@install_loc_array = split(/,/, $kernel_install_files_loc);
# We need to uncompress driver files first
lib_uncompress_all_driver_files($kernel_install_files_loc);
foreach $cur_loc (@install_loc_array)
{
if (! -d $cur_loc)
{
# location (directory) does not exist
next;
}
# test that all of our expected components exist in the distribution
# search for OIP components
foreach $component ($OKA_DRIVER_COMPONENTS[OKA_IDX],
$OKA_DRIVER_COMPONENTS[OKG_IDX],
)
{
my ($target) = $cur_loc . "/" . $component;
if (-e $target)
{
$components_found .= " $component";
$OIP_PATH = $cur_loc;
# if (! ($MEDIA_FOUND =~ m/OIP/))
# {
# # $MEDIA_FOUND is used by the version_check sub-command
# $MEDIA_FOUND .= "OIP components: $OIP_PATH\n";
# }
}
else
{
lib_error_print_noalert(9320, "Missing file: '%s'.", $target);
$components_missing = 1;
}
}
}
if (defined($OIP_PATH))
{
$MEDIA_FOUND = "$OIP_PATH\n";
}
else
{
$MEDIA_FOUND = "";
}
# verify that we have all that we need
if ($components_missing)
{
return USM_FAIL;
}
foreach $component (@OKA_DRIVER_COMPONENTS)
{
if (!($components_found =~ m/$component/))
{
lib_error_print_noalert(9320, "Missing file: '%s'.", $component);
$ret_code = USM_FAIL;
}
}
if (!defined($OIP_PATH))
{
return USM_FAIL;
}
# We found drivers, now find where they will be installed.
$DRIVER_DIR = get_oka_driver_dir($OIP_PATH);
foreach $component (@OH_COMPONENTS, @MESG_COMPONENTS)
{
my ($source);
if ($minus_l_specified)
{
my (@array) = split /\//, $component;
my ($file) = $array[-1];
$source = "$CMDS_SRC_DIR/$file";
if ($component =~ /msb$/)
{
# Special case msg files as it lives apart from the other commands.
$source = "$MESG_SRC_DIR/$file";
}
}
else
{
$source = $component;
}
if (! -e $source)
{
lib_error_print_noalert(9320, "Missing file: '%s'.", $source);
$ret_code = USM_FAIL;
}
}
return $ret_code;
} # end osds_oka_search_for_distribution_files
# osds_load_and_verify_oka_state
#
# We unconditionally create the OKA udev permissions file
# If the install was for the current kernel version, we load the drivers
# and test to see that the expected /dev entries get created.
#
use File::Copy;
sub osds_load_and_verify_oka_state
{
my ($no_load) = @_;
my ($driver); # currently loaded driver
my ($return_val);
my ($udev_perm_file);
my ($okaadmin);
# extract the admin name for use
$okaadmin = lib_get_oka_admin_name();
lib_inform_print_noalert (9321, "Creating udev for OKA.");
lib_osds_oka_create_udev($okaadmin);
print ("creating oka node \n");
lib_osds_oka_create_node($okaadmin);
# Make sure that all drivers are in place and can be loaded
my ($component);
my ($fail) = USM_SUCCESS;
my ($result);
foreach $component (@OKA_DRIVER_COMPONENTS)
{
if (! -e "$DRIVER_DIR/$component")
{
lib_error_print_noalert(9320, "Missing file: '%s'.", "$DRIVER_DIR/$component");
$fail = USM_FAIL;
}
}
if ($fail != USM_SUCCESS)
{
return $fail;
}
# create the driver dependencies
lib_inform_print_noalert(9323,
"Creating module dependencies - this may take some time.");
if (machine_is_RH() || machine_is_SLES())
{
my ($moved_dep) = 0;
my ($driver_list);
foreach $component (@OKA_DRIVER_COMPONENTS)
{
$driver_list .= "$DRIVER_DIR/$component\n";
}
if (-e "/lib/modules/$KVER/modules.dep")
{
move("/lib/modules/$KVER/modules.dep", "/tmp/modules.dep");
$moved_dep = 1;
}
$return_val = system("depmod -v $KVER > /dev/null");
if (($return_val != 0) && $moved_dep)
{
# depmod failed - restore the original
move("/tmp/modules.dep", "/lib/modules/$KVER/modules.dep");
}
if (machine_is_RH())
{
my ($print_header) = 1;
my ($cmd) = "echo \"$driver_list\" | /sbin/weak-modules $no_init" .
" --add-modules $KVER 2>&1 |";
open (MOD, $cmd);
while (<MOD>)
{
if ($_ =~ /^WARNING:/)
{
next;
}
if ($print_header)
{
lib_print_cmd_header($cmd);
$print_header = 0;
}
lib_inform_print_noalert (9999, "$_");
}
close (MOD);
}
}
if ($no_load)
{
# We're installing OKA for another kernel version - do not attempt to
# load the drivers. The presumed scenario is that the user wants to
# install OKA for an about to be upgraded kernel. This way, OKA can
# be up and running upon reboot. Dunno if anyone will ever use this.
lib_inform_print_noalert(9324, "Alternate drivers installed.");
lib_inform_print_noalert(9325, " OS kernel version = %s.", $UNAME_R);
lib_inform_print_noalert(9326, " installed driver version = %s.", $KVER);
}
else
{
# Load the OKA drivers
$return_val = lib_load_oka_drivers();
if ($return_val != USM_SUCCESS)
{
# lib_load_oka_drivers() will print the specific error(s), if any;
return $return_val;
}
# Make sure that the proper /dev files get created by udevd
lib_inform_print_noalert(649, "Verifying OKA devices.");
$return_val = lib_verify_oka_devices();
if ($return_val != USM_SUCCESS)
{
# osds_verify_oka_devices() will print the specific error(s), if any;
return $return_val;
}
}
# Fix wrapper scripts to have proper ORACLE_HOME
osds_fix_oka_wrapper_scripts();
return USM_SUCCESS;
} # end osds_load_and_verify_oka_state
# osds_oka_uninstall
#
# remove the OKA components.
#
#
use File::Basename;
use File::Find;
sub osds_oka_uninstall
{
my (undef, $preserve) = @_;
my ($return_code) = USM_SUCCESS; # Assume success
my ($component);
my ($oka_perm_file);
if (!$preserve)
{
my $ret;
# TODO-SOMA - do some KA specific action !!
# Names MUST match the ASM_OSD_TUNABLE_FILE_NAME define in asmdefs.h
# and OFS_OSD_TUNABLE_FILE_NAME in ofslintunables.h
#my ($advm_tunables) = "/etc/sysconfig/advmtunables";
#my ($acfs_tunables) = "/etc/sysconfig/acfstunables";
#if (-e $advm_tunables)
#{
# if (! unlink $advm_tunables)
# {
# lib_inform_print_noalert(9348, "Unable to remove '%s'.", $advm_tunables);
# $ret = USM_TRANSIENT_FAIL;
# }
#}
#if (-e $acfs_tunables)
#{
# if (! unlink $acfs_tunables)
# {
# lib_inform_print_noalert(9348, "Unable to remove '%s'.", $acfs_tunables);
# $ret = USM_TRANSIENT_FAIL;
# }
#}
}
# SLES udev rules work the same as RH5
if (machine_is_RH() || machine_is_SLES())
{
$oka_perm_file = lib_osds_get_oka_RH5_udev_rules_file();
# remove the udev OKA premissions file
if (! unlink $oka_perm_file)
{
# this is just a comment for the time being as we can still process
# the rest of the work
lib_inform_print_noalert(9348, "Unable to remove '%s'.", $oka_perm_file);
#$return_code = USM_TRANSIENT_FAIL;
}
}
# Guarantee that we're not in one of the usm directories about to be nuked.
chdir "/";
# Remove OKA drivers from and any *empty* sub-directories we would have
# created at install time (e.g., /lib/modules/2.6.18-8.el5/extra/oracle)
open (CHECK, "find /lib/modules 2> /dev/null |");
while (<CHECK>)
{
my ($driver) = split;
if (($driver =~ m/\/oracle\/oracka.ko/) ||
($driver =~ m/\/oracle\/oracka_mod_kga.ko/))
{
# Remove the driver
if (! unlink $driver)
{
lib_inform_print_noalert(9348, "Unable to remove '%s'.", $driver);
$return_code = USM_TRANSIENT_FAIL;
}
# Remove the base directories but only if empty
# even if it is not empty, it is removing, so comment it out for now
#my (undef, $lib, $modules, $kver) = split (/\//, $driver);
#my $subdir = "/$lib/$modules/$kver";
#finddepth(sub{rmdir}, $subdir);
}
}
close(CHECK);
system("depmod > /dev/null");
system("rm -f /dev/oka");
return $return_code;
} # end osds_oka_uninstall
###############################
# internal "static" functions #
###############################
# get_oka_driver_dir
#
# return the directory where the OKA drivers will be installed.
#
sub get_oka_driver_dir
{
my ($path) = @_;
if (machine_is_RH() || machine_is_SLES())
{
my ($driver_build_version); # version that the driver was linked for.
my ($vermagic);
my (@tmp_array);
# pick the oka driver - any KA driver would do.
open MODINFO , "modinfo $path/$OKA_DRIVER_COMPONENTS[OKA_IDX] |";
while (<MODINFO>)
{
if ($_ =~ /^vermagic/)
{
$vermagic = $_;
}
}
close (MODINFO);
if (defined($vermagic))
{
# Get the version number from the modinfo vermagic line. It looks like:
# vermagic: 2.6.18-8.el5PAE SMP mod_unload 686 REGPARM 4KSTACKS gcc-4.1
$vermagic =~ s/vermagic://;
$vermagic =~ s/^\s+//g;
@tmp_array = split(/ /, $vermagic);
$driver_build_version = $tmp_array[0];
}
else
{
# Use the current kernel version if we can't get vermagic
lib_inform_print_noalert(9343, "Unable to retrieve OS kernel version from " .
"module %s.", "$path/$OKA_DRIVER_COMPONENTS[OKA_IDX]");
$driver_build_version = $UNAME_R;
}
return "/lib/modules/$driver_build_version/extra/oracle";
}
} #end get_oka_driver_dir
# osds_fix_oka_wrapper_scripts
#
# We need to resolve %ORA_CRS_HOME% in the command wrapper scripts.
#
sub osds_fix_oka_wrapper_scripts
{
my (@progs) = (
"$OH_BIN_DIR/okaload",
"$OH_BIN_DIR/okadriverstate",
"$OH_BIN_DIR/okacmd"
);
my ($prog);
my ($line);
my (@buffer);
foreach $prog (@progs)
{
my ($read_index, $write_index);
$read_index = 0;
open READ, "<$prog" or next;
while ($line = <READ>)
{
if ($line =~ m/^ORA_CRS_HOME/)
{
$line = "ORA_CRS_HOME=$ORACLE_HOME\n";
}
$buffer[$read_index++] = $line;
}
close (READ);
$write_index = 0;
open WRITE, ">$prog" or next;
while($write_index < $read_index)
{
print WRITE "$buffer[$write_index++]";
}
close (WRITE);
}
}
# end osds_fix_oka_wrapper_scripts
1;
OHA YOOOO