MINI MINI MANI MO
#)
#
# osds_acfsroot.pm
#
# Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
#
#
# NAME
# osds_acfsroot.pm - Linux OSD component of acfsroot.
#
# DESCRIPTION
# Purpose
# Install/uninstall USM 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_acfsroot;
require Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw(
osds_fix_wrapper_scripts
osds_get_kernel_version
osds_initialize
osds_install_from_distribution_files
osds_is_kabi_compatible
osds_search_for_distribution_files
osds_load_and_verify_usm_state
osds_usm_uninstall
osds_patch_verify
get_install_home_from_base
machine_is_supported_linux
machine_is_supported
machine_is_RH
machine_is_SLES
osds_symvers_exists
$MEDIA_FOUND
$ORACLE_HOME
$USM_DFLT_DRV_LOC
$USM_DFLT_CMD_LOC
$USM_TUNE_OS_DIR
$USM_TUNE_ORA_DIR
@OH_BIN_COMPONENTS
@OH_LIB_COMPONENTS
@SBIN_COMPONENTS
@USM_PUB_COMPONENTS
@MESG_COMPONENTS
);
use osds_acfslib;
use acfslib;
our ($ORACLE_HOME) = $ENV{ORACLE_HOME};
# This file is used by other commands, like acfsdriverstate. These commands can
# be run by a user, using a perl location in the db home. When this is done,
# ORACLE_HOME points to the dbhome, not crs home. However, to run other
# commands, we need access to the crs home - the acfs modules exist there.
# So, if ORACLE_HOME points to the db home (no usm/install dir), point it to the
# CRS_HOME. Both ORACLE_HOME and ORA_CRS_HOME are set in the wrapper scripts for
# the individual commands.
$ORACLE_HOME = $ENV{ORA_CRS_HOME} if (!(-e "$ORACLE_HOME/usm/install"));
my ($SHIPHOME_BASE_DIR) = "$ORACLE_HOME/usm/install";
our ($USM_DFLT_CMD_LOC) = "$SHIPHOME_BASE_DIR/cmds/bin"; # cmds media loc
our ($USM_DFLT_DRV_LOC); # location of the drivers media
my ($MINUS_L_DRIVER_LOC);
our ($MEDIA_FOUND) = ''; # path name to media
# used for version_check
use constant UID => 4;
use constant GID => 5;
use constant KABI_NOT_SUPPORTED => "KABI_NOT_SUPPORTED";
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";
our ($USM_TUNE_OS_DIR) = "/etc/sysconfig";
our ($USM_TUNE_ORA_DIR) = "$ORACLE_HOME/acfs/tunables";
# ACFS library name.
my ($LIBACFS) = "libacfs18.so";
# Default ACFS library install directory
my ($LIBACFS_DIR) = "/opt/oracle/extapi/64/acfs/orcl/1/";
# Bug 21518337
# tsc tkfvinfolink12 in which we extract the content of these elements.
our (@SBIN_COMPONENTS) = (
"advmutil", "advmutil.bin",
"fsck.acfs", "fsck.acfs.bin",
"mkfs.acfs", "mkfs.acfs.bin",
"mount.acfs", "mount.acfs.bin",
"acfsdbg", "acfsdbg.bin",
"acfsutil", "acfsutil.bin",
"umount.acfs", "umount.acfs.bin",
"acfssihamount",
);
our (@OH_BIN_COMPONENTS) = (
"$OH_BIN_DIR/acfsdriverstate", "$OH_BIN_DIR/acfsload",
"$OH_BIN_DIR/acfsregistrymount", "$OH_BIN_DIR/acfsroot",
"$OH_BIN_DIR/acfsrepl_apply", "$OH_BIN_DIR/acfsrepl_apply.bin",
"$OH_BIN_DIR/acfsrepl_monitor", "$OH_BIN_DIR/acfsreplcrs",
"$OH_BIN_DIR/acfsrepl_preapply", "$OH_BIN_DIR/acfsrepl_transport",
"$OH_BIN_DIR/acfsrepl_initializer", "$OH_BIN_DIR/acfssinglefsmount",
"$OH_BIN_DIR/acfsrepl_dupd", "$OH_BIN_DIR/acfsrepl_dupd.bin",
"$OH_BIN_DIR/acfshanfs", "$OH_BIN_DIR/acfsrm",
"$OH_BIN_DIR/acfsremote", "$OH_BIN_DIR/acfscm",
"$OH_BIN_DIR/acfsiob", "$OH_BIN_DIR/acfsrd",
);
our (@OH_LIB_COMPONENTS) = (
"$OH_LIB_DIR/acfsdriverstate.pl", "$OH_LIB_DIR/acfslib.pm",
"$OH_LIB_DIR/acfsload.pl", "$OH_LIB_DIR/acfsregistrymount.pl",
"$OH_LIB_DIR/acfstoolsdriver.sh", "$OH_LIB_DIR/osds_acfsdriverstate.pm",
"$OH_LIB_DIR/osds_acfslib.pm", "$OH_LIB_DIR/osds_acfsload.pm",
"$OH_LIB_DIR/acfsroot.pl", "$OH_LIB_DIR/acfssinglefsmount.pl",
"$OH_LIB_DIR/osds_acfsroot.pm", "$OH_LIB_DIR/acfsreplcrs.pl",
"$OH_LIB_DIR/osds_acfsregistrymount.pm",
"$OH_LIB_DIR/osds_acfssinglefsmount.pm",
"$OH_LIB_DIR/osds_unix_linux_acfslib.pm",
"$OH_LIB_DIR/$LIBACFS", "$OH_LIB_DIR/osds_acfsremote.pm",
"$OH_LIB_DIR/acfshanfs.pl", "$OH_LIB_DIR/acfsremote.pl",
"$OH_LIB_DIR/acfsr_member",
"$OH_LIB_DIR/65-usm-acfsr-member.rules",
);
our (@USM_PUB_COMPONENTS) = (
"$USM_PUB_DST_DIR/acfslib.h",
);
our (@MESG_COMPONENTS) = (
"$MESG_DST_DIR/acfsus.msb",
"$MESG_DST_DIR/acfsus.msg",
);
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_search_for_distribution_files() and
# consumed by osds_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 ($ASMADMIN); # ASM admin group name
my ($KVER); # kernel version being installed
# osds_symvers_exists
#
# /sbin/weak-modules depends on /boot being accessible and the
# symvers-<kernel_version> file being present.
sub osds_symvers_exists
{
my ($kver) = @_;
if ($osds_acfslib::configuration{symvers})
{
if ($osds_acfslib::configuration{symvers} eq "no")
{
return 0;
}
else
{
return 1;
}
}
if (!$kver)
{
$kver = $UNAME_R;
}
if (machine_is_RH())
{
my ($symvers_file) = "symvers-" . $kver . ".gz";
$osds_acfslib::configuration{symversfile} = $symvers_file;
if (! -r "/boot/$symvers_file")
{
lib_error_print(9213,
"Configuration file '%s' in the /boot directory does not exist or cannot be read.",
$symvers_file);
$osds_acfslib::configuration{symvers} = "no";
return 0;
}
}
$osds_acfslib::configuration{symvers} = "yes";
return 1;
}
# osds_is_kabi_compatible
#
# Predict the success to load ACFS Drivers on not supported kernels,
# without loading the drivers.
# Compare checksum symbols in the driver versus checksum symbols in the kernel.
# Checking for unknown symbols and disagree about version of symbols.
# Using weak-modules command
#
sub osds_is_kabi_compatible
{
my ($base_directory, $kver) = @_;
my $compatible = "is compatible";
my $not_compatible = "is not compatible";
my $weak_modules = "/sbin/weak-modules";
# if weak-modules does not exist or it is not executable,
# We can not check kabi compatibility
if (!-e $weak_modules ||
!-X $weak_modules)
{
lib_error_print(9551, "Command file '/sbin/weak-modules' does not exist " .
"or it is not an executable.");
return 0;
}
# We need to uncompress driver files first
lib_uncompress_all_driver_files($base_directory);
# In EL5 --no-initrd Do not generate an initrd.
# In EL6 --no-initramfs Do not generate an initramfs.
# Both cases, we don't want to generate.
#
# Output for weak-modules looks like:
# Module oracleoks.ko from kernel 2.6.18-164.0.0.0.1.el5 is compatible
# with kernel 2.6.18-238.0.0.0.1.el5
# or
# Module oracleoks.ko from kernel 2.6.18-164.0.0.0.1.el5 is not compatible
# with kernel 2.6.18-238.0.0.0.1.el5xen
# "from kernel" is the kernel used for compiling ACFS Drivers
# "with kernel" is the installed kernel
# We want to filter "with kernel"
#First, We check compatibility for OKS Driver.
my $command = "ls $base_directory/$DRIVER_COMPONENTS[OKS_IDX] | " .
"/sbin/weak-modules --verbose --dry-run $no_init --add-modules 2>&1 | " .
"grep -w 'with kernel $kver' | grep -v 'with kernel $kver.debug' | " .
"grep -v ksplice";
my $output = `$command`;
# We check return code for any error, check for empty output
# or check for compatible message
if (($? != 0) ||
(!$output) ||
(index($output, $compatible) == -1))
{
lib_error_print(9999, "Command Output: $output.");
#if weak-modules failed we send a message asking to run the command manually
#for checking issues
lib_error_print(9552,
"Command '/sbin/weak-modules' returned a potential " .
"compatibility issue. For more details execute the command '%s'.",
"$command");
$osds_acfslib::configuration{okskabi} = "no";
return 0;
}
# Second, if OKS Driver is compatible. We need to check compatibility
# for ACFS and ADVM Drivers. For these cases we can get "is not compatible".
# But it can be because ACFS and ADVM Drivers need the OKS symbols and these
# symbols are not loading in the Kernel Symbol Table.
# We need to filter out OKS Drivers and determine if the drivers are compatible or not.
# Getting OKS Symbols
my $oks_symbols = `/usr/bin/nm --defined-only $base_directory/$DRIVER_COMPONENTS[OKS_IDX]`;
foreach my $module ($DRIVER_COMPONENTS[AVD_IDX], $DRIVER_COMPONENTS[OFS_IDX])
{
# Checking for ACFS/ADVM Driver
$command = "ls $base_directory/$module | " .
"/sbin/weak-modules --verbose --dry-run $no_init --add-modules 2>&1 | " .
"grep -w 'with kernel $kver' | grep -v 'with kernel $kver.debug' | " .
"grep -v ksplice";
$output = `$command`;
# We need to check, whether ACFS/ADVM is compatible or not
# If ACFS/ADVM is compatible, we don't need to check for OKS Symbols
if ($? != 0 ||
!$output)
{
lib_error_print(9999, "Command Output: $output.");
#if weak-modules failed we send a message asking to run the command manually
#for checking issues
lib_error_print(9552,
"Command '/sbin/weak-modules' returned a potential " .
"compatibility issue. For more details execute the command '%s'.",
"$command");
if ($module eq "oracleadvm.ko")
{
$osds_acfslib::configuration{advmkabi} = "no";
}
else
{
$osds_acfslib::configuration{acfskabi} = "no";
}
return 0;
}
elsif ($output =~ $not_compatible) {
#We need to split for getting the missing symbols
my ($header, $symbols) = split(/\:/, $output);
#remove leading spaces
$symbols =~ s/^\s+//;
#remove trailing spaces
$symbols =~ s/\s+$//;
#Splitting ACFS/ADVM missing symbols
my @missing_symbols = split(/\s+/, $symbols);
#Have an array to store confirmed missing symbols
my @confirmed_missing_symbols= ();
foreach my $wrong_symbol (@missing_symbols)
{
#We try to find the symbol in OKS Symbols
if (!($oks_symbols =~ $wrong_symbol))
{
push @confirmed_missing_symbols, $wrong_symbol;
}
}
if (@confirmed_missing_symbols)
{
if ($module eq "oracleadvm.ko")
{
$osds_acfslib::configuration{advmkabi} = "no";
}
else
{
$osds_acfslib::configuration{acfskabi} = "no";
}
lib_error_print(9460, "Missing symbols: '%s'", join ' ', @confirmed_missing_symbols);
#if weak-modules failed we send a message asking to run the command manually
#for checking issues
lib_error_print(9552,
"Command '/sbin/weak-modules' returned a potential " .
"compatibility issue. For more details execute the command '%s'.",
"$command");
return 0;
}
}
}
$osds_acfslib::configuration{driverskabi} = "yes";
return 1;
}
# osds_initialize
#
# Perform OSD initialization.
# Set USM_DFLT_DRV_LOC - the location of the USM installation driver media.
# We deduce the location of the other components from there.
#
sub osds_initialize
{
my ($install_kver, $sub_command, $install_location, $option_l_used,
$test_mode, $test_os, $test_unamer, $test_patchlevel, $test_arch) = @_;
my ($vendor);
my ($type);
my (@test_params);
my ($test_release);
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;
}
if ($test_mode)
{
if ($test_os eq "EL5")
{
$test_release = "redhat-release-5";
}
elsif($test_os eq "EL6")
{
$test_release = "redhat-release-6";
}
elsif($test_os eq "EL7")
{
$test_release = "redhat-release-7";
}
elsif($test_os eq "RHEL6")
{
$test_release = "redhat-release-server-6";
}
elsif($test_os eq "RHEL7")
{
$test_release = "redhat-release-server-7";
}
elsif($test_os eq "SLES10")
{
$test_release = "sles-release-10";
}
elsif($test_os eq "SLES11")
{
$test_release = "sles-release-11";
}
elsif($test_os eq "SLES12")
{
$test_release = "sles-release-12";
}
push(@test_params, $test_mode);
push(@test_params, $test_release);
push(@test_params, $test_unamer);
push(@test_params, $test_patchlevel);
push(@test_params, $test_arch);
$KVER = $test_unamer;
}
# we have already verified that we have a valid Linux type
$type = lib_osds_get_os_type(@test_params);
$vendor = lib_osds_get_linux_vendor(@test_params);
# For "acfsdriverstate supported" command, we don't need to know
# asmadmin name, and we can get some errors running the command
# We skip this part for supported
if ($sub_command ne "supported")
{
# Get the name of the ASM adminisrator
$ASMADMIN = lib_get_asm_admin_name();
}
if (!((defined($ORACLE_HOME)) &&
(-e "$ORACLE_HOME/lib/acfsroot.pl") &&
(-e "$SHIPHOME_BASE_DIR")))
{
lib_error_print(9389,
"ORACLE_HOME is not set to the location of the Grid Infrastructure home.");
return USM_TRANSIENT_FAIL;
}
# ADVM/ACFS is not supported in a LXC environment
# LXC is sharing the Kernel with the Host OS
# Inserting new modules is not allowed
if (lib_is_local_container())
{
return USM_NOT_SUPPORTED;
}
# /sbin/weak-modules depends on /boot being accessible and the
# symvers-<kernel_version> file being present.
if (!$test_mode && !osds_symvers_exists($KVER))
{
my ($symvers_file) = "symvers-" . $KVER . ".gz";
if (! -e "/boot/$symvers_file")
{
lib_error_print(9305,
"ADVM/ACFS installation cannot proceed:");
lib_error_print(9158,
"Configuration file '%s' in the /boot directory does not exist.",
$symvers_file);
return USM_TRANSIENT_FAIL;
}
}
# default media location - over-ride with the -l option
my ($base) = $SHIPHOME_BASE_DIR;
my ($run_install_dir_verification) = 0;
#Alternative location
if ($option_l_used)
{
$base = $install_location;
$USM_DFLT_DRV_LOC = get_install_home_from_base($base, $type, $ARCH, $KVER,
$run_install_dir_verification, @test_params);
}
else
{
$run_install_dir_verification = 1;
$USM_DFLT_DRV_LOC = get_install_home_from_base($base, $type, $ARCH, $KVER,
$run_install_dir_verification, @test_params);
}
if (!$USM_DFLT_DRV_LOC || ($USM_DFLT_DRV_LOC eq KABI_NOT_SUPPORTED)) {
return USM_NOT_SUPPORTED;
}
return USM_SUCCESS;
}
# osds_get_kernel_version
#
sub osds_get_kernel_version
{
if (machine_is_supported_linux())
{
return $KVER;
}
lib_error_print(9319,"Unknown OS kernel version '%s' detected.",$KVER);
return USM_FAIL;
} # end osds_get_kernel_version
# osds_install_from_distribution_files
#
# Install the USM components from the specified distribution files
# The files have already been validated by the time we get here
# by osds_search_for_distribution_files(). Also, any previous USM installation
# will have been removed.
#
use File::Path;
sub osds_install_from_distribution_files
{
my ($component); # curent component being installed
my ($command); # current command being executed by system()
my ($ret) = 0; # 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 (9503, "ADVM and ACFS driver media location is '%s'",
$OIP_PATH);
foreach $component (@DRIVER_COMPONENTS)
{
my ($source) = "$OIP_PATH/$component";
my ($target) = "$DRIVER_DIR/$component";
if ($component eq "oracleadvm.ko")
{
$source = "$GPL_PATH/$component";
}
lib_verbose_print_noalert (9504, "Copying file '%s' to the path '%s'",
$source,
$target);
$command = "cp $source $target";
if ( ! acfslib::lib_are_same_file($source, $target) )
{
$ret = system ($command);
$return_code = USM_FAIL if $ret;
}
else
{
acfslib::lib_inform_print(9506,
"The files '%s' and '%s' are the same, not copying.",
$source, $target);
}
}
foreach $component (@SBIN_COMPONENTS)
{
my (@array) = split /\//, $component;
my ($file) = $array[-1];
my ($source) = "$CMDS_SRC_DIR/$component";
my ($target) = "$SBIN_DIR/$file";
$source = "$CMDS_SRC_DIR/$component";
lib_verbose_print_noalert (9504, "Copying file '%s' to the path '%s'",
$source,
$target);
if ( ! acfslib::lib_are_same_file($source, $target) )
{
if($component =~ /acfssihamount/)
{
# Check if this is SIHA
if(lib_osds_is_siha())
{
$target = "/etc/init.d/$file";
$ret = system ("cp $source $target");
$ret += system ("/sbin/chkconfig --add $file");
$ret += system ("/sbin/chkconfig --level 5 $file on");
}
else
{
# Skip if it isn't.
next;
}
}
else
{
$ret = system ("cp $source $target");
}
lib_verbose_print_noalert (9504, "Copying file '%s' to the path '%s'",
$source,
$target);
$return_code = USM_FAIL if $ret;
}
else
{
acfslib::lib_inform_print(9506,
"The files '%s' and '%s' are the same, not copying.",
$source, $target);
}
# if I cam write the file, I can change the mode - no need to check return
system("chmod 0755 $target");
}
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);
$ret = 0;
if ($component =~ /$LIBACFS/)
{
# Special case libusmacfs as it lives apart from the other commands.
$source = "$USM_LIB_SRC_DIR/$file";
}
else
{
$source = "$CMDS_SRC_DIR/$file";
}
$have_orig = 0;
if (-e $target)
{
$have_orig = 1;
# get the owner/group of the original file
($uid, $gid) = (stat($target))[UID,GID];
}
if ( ! acfslib::lib_are_same_file($source, $target) )
{
lib_verbose_print_noalert (9504, "Copying file '%s' to the path '%s'",
$source, $target);
unlink ("${target}/${LIBACFS}") if ($component =~ /$LIBACFS/ &&
-e "${target}/${LIBACFS}");
$ret = system ("cp $source $target");
$return_code = USM_FAIL if $ret;
}
else
{
acfslib::lib_inform_print(9506,
"The files '%s' and '%s' are the same, not copying.",
$source, $target);
}
# For lib directory, we only have two files with mode 0755. If we need to
# add more files to lib with different mode. Maybe we need to think
# in change this validation.
if (($target =~ /\/bin\//) ||
($component =~ /acfstoolsdriver.sh/) ||
($component =~ /acfsr_member/) ||
($component =~ /acfsreplcrs.pl/))
{
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";
if ( ! acfslib::lib_are_same_file($source, $target) )
{
lib_verbose_print_noalert (9504, "Copying file '%s' to the path '%s'",
$source, $target);
$ret = system ("cp $source $target");
$return_code = USM_FAIL if $ret;
}
else
{
acfslib::lib_inform_print(9506,
"The files '%s' and '%s' are the same, not copying.",
$source, $target);
}
}
foreach $component (@USM_PUB_COMPONENTS)
{
my (@array) = split /\//, $component;
my ($file) = $array[-1];
my ($target) = $component;
my ($source) = "$USM_PUB_SRC_DIR/$file";
if ( ! acfslib::lib_are_same_file($source, $target) )
{
lib_verbose_print_noalert (9504, "Copying file '%s' to the path '%s'",
$source, $target);
$ret = system ("cp $source $target");
$return_code = USM_FAIL if $ret;
}
else
{
acfslib::lib_inform_print(9506,
"The files '%s' and '%s' are the same, not copying.",
$source, $target);
}
}
#If we are using '-l' location, maybe the default location doesn't exist
if (! -d $USM_DFLT_DRV_LOC)
{
mkpath($USM_DFLT_DRV_LOC, 0, 0644);
}
# Copy the drivers and system commands to the install area so that
# subsequent "acfsroot 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 "acfsroot install".
foreach $component (@DRIVER_COMPONENTS)
{
my (@array) = split /\//, $component;
my ($file) = $array[-1];
my ($source) = "$MINUS_L_DRIVER_LOC/$component";
my ($target) = "$USM_DFLT_DRV_LOC/$file";
if ( ! acfslib::lib_are_same_file($source, $target) )
{
lib_verbose_print_noalert (9504, "Copying file '%s' to the path '%s'",
$source, $target);
$ret = system ("cp $source $target");
$return_code = USM_FAIL if $ret;
}
else
{
acfslib::lib_inform_print(9506,
"The files '%s' and '%s' are the same, not copying.",
$source, $target);
}
}
foreach $component (@SBIN_COMPONENTS)
{
my ($cmd_install_area) = "$ORACLE_HOME/usm/install/cmds/bin";
my (@array) = split /\//, $component;
my ($file) = $array[-1];
my ($source) = "$CMDS_SRC_DIR/$component";
my ($target) = "$cmd_install_area/$file";
my ($uid, $gid);
($uid, $gid) = (stat($target))[UID,GID];
if ( ! acfslib::lib_are_same_file($source, $target) )
{
if($component =~ /acfssihamount/)
{
# Check if this is SIHA
if(lib_osds_is_siha())
{
$target = "/etc/init.d/$file";
$ret = system ("cp $source $target");
$ret += system ("/sbin/chkconfig --add $file");
$ret += system ("/sbin/chkconfig --level 5 $file on");
}
else
{
# Skip if it isn't.
next;
}
}
else
{
$ret = system ("cp $source $target");
}
lib_verbose_print_noalert (9504, "Copying file '%s' to the path '%s'",
$source,
$target);
$return_code = USM_FAIL if $ret;
}
else
{
acfslib::lib_inform_print(9506,
"The files '%s' and '%s' are the same, not copying.",
$source, $target);
}
$ret = chmod 0755, $target;
if ($ret != 1)
{
# Warn only
lib_inform_print(9347, "Unable to set permission bits (%s) on: '%s'.",
0755, $target);
}
$ret = chown $uid, $gid, $target;
if ($ret != 1)
{
# Warn only
lib_inform_print(9426,
"Unable to set the file attributes for file %s.", $target);
}
}
}
# Copy ACFS library to the vendor specific location
$ret = osds_install_acfslib();
if($ret != USM_SUCCESS)
{
$return_code = USM_FAIL;
}
# check if the -m flag was set
if( $osds_acfslib::DOM >= 0)
{
my $result;
my $filename = "/etc/sysconfig/advmtunables";
my $asm_acfsr_mode = $osds_acfslib::DOM;
my $asm_acfsr_mode_line = "asm_acfsr_mode=";
if ( -e $filename )
{
lib_trace("9999", "Setting asm_acfsr_mode=$asm_acfsr_mode");
my $fh;
open ($fh,"<$filename") || return USM_FAIL;
my @lines = <$fh>;
close $fh;
my $overwrite = 0;
open ($fh,">$filename") || return USM_FAIL;
for (@lines)
{
my $line = $_;
if($line =~ /^$asm_acfsr_mode_line\d$/)
{
$overwrite = 1;
$line = "$asm_acfsr_mode_line$asm_acfsr_mode\n";
}
print $fh $line;
}
close $fh;
# The file will technically always exist. The tunable, however,
# may not be written in it. There's a chance the above loop never
# wrote the asm_acfsr_mode tunable.
if($overwrite eq 0)
{
open ($fh,">>$filename") || return USM_FAIL;
print $fh "$asm_acfsr_mode_line$asm_acfsr_mode\n";
close $fh;
}
}
else
{
# write mode to file and check for operation failure
# create file and check for operation failure
lib_trace("9999", "No advmtunables file found. Creating new one.");
$result = system("> $filename");
if($result != 0)
{
lib_error_print(5017,"cannot create file: %s",$filename);
}
# set permissions and check for operation failure
my $permissions = "660";
$result = system("chmod $permissions $filename");
if($result != 0)
{
lib_error_print(9347, "Unable to set permission bits (%s) on: '%s'",
$permissions, $filename);
}
lib_trace("9999", "Setting asm_acfsr_mode=$asm_acfsr_mode");
my $writeCmd = "echo \"$asm_acfsr_mode_line$asm_acfsr_mode\"";
$writeCmd = $writeCmd . " > /etc/sysconfig/advmtunables";
$result = system($writeCmd);
if($result != 0)
{
lib_error_print(3098,
"error writing to configuration file %s",
$filename);
$return_code = $result;
}
}
}
return $return_code;
} # end osds_install_from_distribution_files
# osds_search_for_distribution_files
#
# Search the media location(s) specified by the user for valid components
#
sub osds_search_for_distribution_files
{
my ($kernel_install_files_loc) = shift;
# -l option specified (we know that the path is fully qualified).
$minus_l_specified = shift;
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 ($minus_l_specified)
{
# $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 ("/", $USM_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;
#We need to update USM_DFLT_DRV_LOC, now is pointing to '-l' location.
$USM_DFLT_DRV_LOC = "$SHIPHOME_BASE_DIR/$driver_relative_path";
}
@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
# The GPL / no GPL decision will be made later
# search for GPL components
if (-e "$cur_loc/$DRIVER_COMPONENTS[AVD_IDX]")
{
$GPL_PATH = $cur_loc;
$components_found .= $DRIVER_COMPONENTS[AVD_IDX];
# if (! ($MEDIA_FOUND =~ m/GPL/))
# {
# # $MEDIA_FOUND is used by the check_version sub-command
# $MEDIA_FOUND .= "GPL components: $GPL_PATH\n";
# }
}
# search for OIP components
foreach $component ($DRIVER_COMPONENTS[OKS_IDX],
$DRIVER_COMPONENTS[OFS_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(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 (@DRIVER_COMPONENTS)
{
if (!($components_found =~ m/$component/))
{
lib_error_print(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_usm_driver_dir($OIP_PATH);
foreach $component (@SBIN_COMPONENTS)
{
if (! -e "$CMDS_SRC_DIR/$component")
{
lib_error_print(9320, "Missing file: '%s'.", "$CMDS_SRC_DIR/$component");
$ret_code = USM_FAIL;
}
}
foreach $component (@OH_COMPONENTS, @MESG_COMPONENTS, @USM_PUB_COMPONENTS)
{
my ($source);
if ($minus_l_specified)
{
my (@array) = split /\//, $component;
my ($file) = $array[-1];
$source = "$CMDS_SRC_DIR/$file";
my ($end) = 'bg'; #End of message file(msb or msg).
if ($component =~ /$LIBACFS/)
{
# Special case libacfs as it lives apart from the other commands.
$source = "$USM_LIB_SRC_DIR/$file";
}
elsif ($component =~ /ms[$end]$/)
{
# Special case msg files as it lives apart from the other commands.
$source = "$MESG_SRC_DIR/$file";
}
elsif ($component =~ /lib.h$/)
{
# Special case header files as it lives apart from the other commands.
$source = "$USM_PUB_DST_DIR/$file";
}
}
else
{
$source = $component;
}
if (! -e $source)
{
lib_error_print(9320, "Missing file: '%s'.", $source);
$ret_code = USM_FAIL;
}
}
return $ret_code;
} # end osds_search_for_distribution_files
# osds_load_and_verify_usm_state
#
# We unconditionally create the USM 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_usm_state
{
my ($no_load) = @_;
my ($driver); # currently loaded driver
my ($return_val);
my ($udev_perm_file);
lib_inform_print (9321, "Creating udev for ADVM/ACFS.");
lib_osds_create_udev($ASMADMIN);
# Make sure that all drivers are in place and can be loaded
my ($component);
my ($fail) = USM_SUCCESS;
my ($result);
foreach $component (@DRIVER_COMPONENTS)
{
if (! -e "$DRIVER_DIR/$component")
{
lib_error_print(9320, "Missing file: '%s'.", "$DRIVER_DIR/$component");
$fail = USM_FAIL;
}
}
if ($fail != USM_SUCCESS)
{
return $fail;
}
# create the driver dependencies
lib_inform_print(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 (@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 (9999, "$_");
}
close (MOD);
}
}
if ($no_load)
{
# 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.
lib_inform_print(9324, "Alternate drivers installed.");
lib_inform_print(9325, " OS kernel version = %s.", $UNAME_R);
lib_inform_print(9326, " installed driver version = %s.", $KVER);
}
else
{
if (defined($ENV{ACFSPATCH_SYNC}))
{
# if ACFSPATCH_SYNC is defined, run sync o.s.
system("sync;sync;sync");
}
# Load the USM drivers
$return_val = lib_load_usm_drivers();
if ($return_val != USM_SUCCESS)
{
# load_usm_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(9327, "Verifying ADVM/ACFS devices.");
$return_val = lib_verify_usm_devices();
if ($return_val != USM_SUCCESS)
{
# osds_verify_usm_devices() will print the specific error(s), if any;
return $return_val;
}
}
# see comments at the head of the routine
lib_trace( 9999, "Resolve ORA_CRS_HOME in the command wrapper scripts.");
osds_fix_wrapper_scripts();
# We leave the drivers running because if ASM is started early, because OH
# or the voting disk reside on ACFS, the drivers must be running as they
# won't have been started by ora.drivers.acfs (CRS is not yet running).
return USM_SUCCESS;
} # end osds_load_and_verify_usm_state
# osds_usm_uninstall
#
# remove the USM components.
#
#
use File::Basename;
use File::Find;
sub osds_usm_uninstall
{
my (undef, $preserve) = @_;
my ($return_code) = USM_SUCCESS; # Assume success
my ($ret);
my ($component);
my ($usm_perm_file);
if(lib_osds_is_siha())
{
# Remove the acfssihamount service
$ret = system("/sbin/service stop acfssihamount");
$ret += system("/sbin/chkconfig --del acfssihamount");
unlink ("/etc/init.d/acfssihamount");
}
if (!$preserve)
{
# 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(9348, "Unable to remove '%s'.", $advm_tunables);
$return_code = USM_TRANSIENT_FAIL;
}
}
if (-e $acfs_tunables)
{
if (! unlink $acfs_tunables)
{
lib_inform_print(9348, "Unable to remove '%s'.", $acfs_tunables);
$return_code = USM_TRANSIENT_FAIL;
}
}
}
# SLES udev rules work the same as RH5
if (machine_is_RH() || machine_is_SLES())
{
$usm_perm_file = lib_osds_get_usm_udev_rules_file();
# remove the udev USM premissions file
if (-e $usm_perm_file)
{
if (! unlink $usm_perm_file)
{
lib_inform_print(9348, "Unable to remove '%s'.", $usm_perm_file);
$return_code = USM_TRANSIENT_FAIL;
}
}
}
if( -e $osds_acfslib::udev_script_location)
{
if(! unlink ($osds_acfslib::udev_script_location))
{
lib_inform_print(9348, "Unable to remove '%s'.",
$osds_acfslib::udev_script_location);
}
}
if( -e $osds_acfslib::udev_rules_location)
{
if(! unlink ($osds_acfslib::udev_rules_location))
{
lib_inform_print(9348, "Unable to remove '%s'.",
$osds_acfslib::udev_rules_location);
}
}
# Guarantee that we're not in one of the usm directories about to be nuked.
chdir "/";
# Remove USM drivers from and any *empty* sub-directories we would have
# created at install time (e.g., /lib/modules/2.6.18-8.el5/extra/usm)
# Attempt to use /bin/find first
my $find_command = "";
if( -e "/bin/find")
{
$find_command = "/bin/find";
}
elsif( -e "/usr/bin/find")
{
# no? try /usr/bin/find
$find_command = "/usr/bin/find";
}
else
{
# no luck, use 'which'
$find_command = `which find 2>/dev/null`;
if( $find_command eq "")
{
# Should not happen, too bad
lib_error_print( 9999, "'find' command not found");
$return_code = USM_TRANSIENT_FAIL;
return $return_code;
}
}
# found, chomp, look for files and store output
chomp( $find_command);
$find_command .= " /lib/modules 2> /dev/null |";
open (CHECK, $find_command);
while (<CHECK>)
{
my ($driver) = split;
if (($driver =~ m/\/usm\/oracleoks.ko/) ||
($driver =~ m/\/usm\/oracleacfs.ko/) ||
($driver =~ m/\/usm\/oracleadvm.ko/))
{
# Remove the driver
if (! unlink $driver)
{
lib_inform_print(9348, "Unable to remove '%s'.", $driver);
$return_code = USM_TRANSIENT_FAIL;
}
# Remove any directories we created - such as the base dirs (if empty).
# <Base>/weak-updates and <Base>/extra should persist if we did not
# create them (that is, they are owned by an rpm).
my (undef, $lib, $modules, $kver) = split (/\//, $driver);
my ($subdir) = "/$lib/$modules/$kver";
my ($rpm_cmd) = "";
my ($extra_weakupdates) = "";
# Bug 27016503
# We will remove only dirs not owned by any rpm
#
# 1. remove /usm/ from /lib/modules/<kernel>/extra/usm/ if not owned by
# any rpm
# remove /usm/ from /lib/modules/<kernel>//weak-updates/usm/ if not
# owned by any rpm
#
# 2. remove /extra/ from /lib/modules/<kernel>/extra/ if not owned by
# any rpm
# remove /weak-updates/ from /lib/modules/<kernel>/weak-updates/ if
# not owned by any rpm
eval {
finddepth(
sub {
# Revmoving only /usm/ dir where ACFS modules exists
# Stop the finddepth loop with 'die' once we are in the /usm/ dir
# otherwise all the path will be removed.
#
# $subdir:
# must be the complete path for ACFS modules:
# /lib/modules/3.10.0-693.el7.x86_64/
# /lib/modules/3.10.0-693.1.1.el7.x86_64/
#
# $extra_weakupdates:
# must be the last directory like /usm/
if( ($_ =~ s/usm$//g) )
{
$extra_weakupdates = $File::Find::name;
die "";
}
}, $subdir);
};
# Remove /usm/ only if not owned by any rpm, otherwise leave and move.
# $rpm_cmd should have this form:
# file /lib/modules/<kernel>/extra/usm is not owned by any package
# file /lib/modules/<kernel>/weak-updates/usm is not owned by any package
$rpm_cmd = `/bin/rpm -qf $extra_weakupdates`;
if ($rpm_cmd =~ s/file//g)
{
rmdir($extra_weakupdates);
}
# Remove if exists /lib/modules/<kernel>/extra/
# we want to remove dirs not owned by any rpm, $rpm_cmd should have this
# form:
# file /lib/modules/<kernel>/extra/usm is not owned by any package
# file /lib/modules/<kernel>/weak-updates/usm is not owned by any package
$rpm_cmd = `/bin/rpm -qf $subdir`;
if ($rpm_cmd =~ s/file//g)
{
# Move outside current directory
chdir "/";
# Removing /extra/ or /weak-updates/ directory not owned by any rpm
finddepth(sub{rmdir}, $subdir);
# Removing parent dir only if empty, otherwise leave and move
if (! osds_check_dir_empty($subdir))
{
rmdir($subdir);
}
}
}
}
close(CHECK);
system("depmod > /dev/null");
foreach $component (@SBIN_COMPONENTS)
{
my ($command) = "$SBIN_DIR/$component";
# This could be a newly added command so if it doesn't exist on the
# current system, we ignore it. Ideally, you want to uninstall with the
# old acfsroot and re-install with the new. In practice, this often
# doesn't happen.
if ((-e $command) && (! unlink $command))
{
lib_inform_print(9348, "Unable to remove '%s'.", $command);
$return_code = USM_TRANSIENT_FAIL;
}
}
# Remove ACFS library from the vendor specific location
$ret = osds_uninstall_acfslib();
if($ret != USM_SUCCESS)
{
$return_code = USM_TRANSIENT_FAIL;
}
return $return_code;
} # end osds_usm_uninstall
###############################
# internal "static" functions #
###############################
# returns true of the machine is a RHEL system
#
sub machine_is_RH
{
my ($type) = lib_osds_get_os_type(@_);
if ($type =~ /EL5/ ||
$type =~ /EL6/ ||
$type =~ /EL7/)
{
return 1;
}
return 0;
}
sub machine_is_SLES
{
my ($type) = lib_osds_get_os_type(@_);
if ($type =~ /SLES/)
{
return 1;
}
return 0;
}
sub machine_is_supported_linux
{
return (machine_is_SLES() || machine_is_RH());
}
# machine_is_supported
#
# Returns if the machine is RH
sub machine_is_supported
{
my ($type) = lib_osds_get_os_type();
if ($type !~ /EL6/ && $type !~ /EL7/)
{
return 0;
}
return (machine_is_RH());
}
# get_usm_driver_dir
#
# return the directory where the USM drivers will be installed.
#
sub get_usm_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 oks driver - any USM driver would do.
open MODINFO , "modinfo $path/$DRIVER_COMPONENTS[OKS_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(9343, "Unable to retrieve OS kernel version from " .
"module %s.", "$path/$DRIVER_COMPONENTS[OKS_IDX]");
$driver_build_version = $UNAME_R;
}
return "/lib/modules/$driver_build_version/extra/usm";
}
} #end get_usm_driver_dir
# osds_fix_wrapper_scripts
#
# We need to resolve %ORA_CRS_HOME% in the command wrapper scripts.
#
sub osds_fix_wrapper_scripts
{
lib_trace( 9176, "Entering '%s'", "fix wrp scripts");
my (@progs) = (
"$SBIN_DIR/advmutil", "$SBIN_DIR/fsck.acfs",
"$SBIN_DIR/mkfs.acfs", "$SBIN_DIR/mount.acfs",
"$SBIN_DIR/umount.acfs", "$SBIN_DIR/acfsdbg ",
"$SBIN_DIR/acfsutil", "/etc/init.d/acfssihamount",
"$OH_BIN_DIR/acfsregistrymount", "$OH_BIN_DIR/acfsdriverstate",
"$OH_BIN_DIR/acfssinglefsmount", "$OH_BIN_DIR/acfsrepl_apply",
"$OH_BIN_DIR/acfsreplcrs", "$OH_BIN_DIR/acfsrepl_dupd",
"$OH_BIN_DIR/acfshanfs", "$OH_BIN_DIR/acfsload",
);
my ($prog);
my ($line);
my (@buffer);
my ($oracle_base) = acfslib::getParam("ORACLE_BASE");
foreach $prog (@progs)
{
my ($read_index, $write_index);
$read_index = 0;
lib_trace( 9999, "Fixing $prog wrapper script.");
if (open(READ, "<$prog"))
{
while ($line = <READ>)
{
if ($line =~ m/^ORA_CRS_HOME/)
{
chomp($line);
lib_trace( 9999, "Old line: $line");
$line = "ORA_CRS_HOME=$ORACLE_HOME";
lib_trace( 9999, "New line: $line");
$line .= "\n";
}
if ($line =~ m/^ORACLE_BASE/)
{
chomp($line);
lib_trace( 9999, "Old line: $line");
$line = "ORACLE_BASE=$oracle_base";
lib_trace( 9999, "New line: $line");
$line .= "\n";
}
$buffer[$read_index++] = $line;
}
close (READ);
$write_index = 0;
if (open(WRITE, ">$prog"))
{
while($write_index < $read_index)
{
print WRITE "$buffer[$write_index++]";
}
close (WRITE);
}
else
{
lib_trace( 9999, "Could not open file '$prog' for writing.");
}
}
else
{
lib_trace( 9999, "Could not open file '$prog' for reading.");
}
}
lib_trace( 9177, "Return from '%s'", "fix wrp scripts");
}
# end osds_fix_wrapper_scripts
# get_install_home_from_base
#
# Get the kernel version to use for the install. The heuristic is:
# If we have drivers for kernel version 1, 5, and 9, and our kernel
# version is 7, choose version 5 - the closest without going beyond.
# Higher driver versions may have symbols not in the current kernel.
#
sub get_install_home_from_base
{
my ($base, $type, $ARCH, $KVER, $runverification, $test_mode) = @_;
my ($subdir);
my ($lastdir) = "0";
my (@var);
my ($variation);
my ($minor);
my (@kver_bydash) = split(/\-/, $KVER);
my (@kver_bydot) = split(/\./, $KVER);
my @subdir_bydash;
my @subdir_bydot;
my @lastdir_bydash;
my @subkver_bydash;
my $subdirstr;
my $major;
my $midver;
my $valid_variation;
my $kverstr = $KVER;
my $km;
my $km_complete;
my $i = 0;
my @dir_list;
my @test_args;
my @kms = (
"oracleadvm.ko",
"oracleacfs.ko",
"oracleoks.ko"
);
my @el7_paths = ( "3.10.0-123", "3.10.0-229", "3.10.0-327",
"3.10.0-514", "3.10.0-693", "3.10.0-862");
my @el7uek_paths = ( "3.8.13-35", "4.1.12", "4.1.12-94.8.2", "4.1.12-103",
"4.1.12-112", "4.1.12-112.16.4" );
my @el6_paths = ( "2.6.32-71", "2.6.32-220", "2.6.32-279", "2.6.32-573",
"2.6.32-696");
my @el6uek_paths = ( "2.6.39-100", "2.6.39-200", "2.6.39-300", "2.6.39-400",
"3.8.13-13", "4.1.12", "4.1.12-94.8.2", "4.1.12-112", "4.1.12-112.16.4" );
my @sles12sp0 = ( "3.12.28-4" );
my @sles12sp1 = ( "3.12.49-11" );
my @sles12sp2 = ( "4.4.21-69" );
my @sles12sp3 = ( "4.4.73-5", "4.4.120-94.17" );
if (!$base || !(-d $base))
{
lib_error_print( 9544, "Invalid files or directories found: '%s'", $base);
}
if( !defined( $runverification))
{
$runverification = 0;
}
if (defined($test_mode))
{
if ($test_mode == 1)
{ # Will probably send uname -r instead of kernel version
@test_args = @_[5..9];
# We can't use KVER for 2.6.18, we look for el5 at the end.
@kver_bydash = split(/\-/, $test_args[2]);
@kver_bydot = split(/\./, $test_args[2]);
#$test_args[2] = $KVER;
}
}
if ( machine_is_RH(@test_args) )
{
$base .= "/Oracle";
#We check if this is a uek kernel
if ($KVER =~ /uek/) {
$type .= "UEK";
}
if (-d "$base/$type/$ARCH")
{
if( $type eq "EL6"){
@dir_list = @el6_paths;
}elsif( $type eq "EL6UEK"){
@dir_list = @el6uek_paths;
}elsif( $type eq "EL7"){
@dir_list = @el7_paths;
}elsif( $type eq "EL7UEK"){
@dir_list = @el7uek_paths;
}
$i = 0;
open (LS, "ls -v $base/$type/$ARCH |");
while ($subdir = <LS>)
{
chomp($subdir);
@subdir_bydot = split(/\./, $subdir);
if( $runverification != 0)
{
if ( ($subdir ne $dir_list[$i]) &&
($dir_list[$i] eq "4.1.12-112") )
{
# Skipping 4.1.12-112 directory.
$i++;
}
#Check if directories found matches with valid directories list
if( $subdir ne $dir_list[$i])
{
lib_error_print( 9544,
"Invalid files or directories found: '%s'",
$subdir);
return;
}
$i++;
}
$subdirstr = $subdir;
if ($subdirstr eq $kverstr)
{
$lastdir = $subdir;
last;
}
@subdir_bydash = split(/\-/, $subdir);
#Compare dir names, which are kernel versions, and kver numerically
if ((osds_unix_linux_acfslib::lib_osds_krncmp($subdirstr, $kverstr) <= 0) &&
(osds_unix_linux_acfslib::lib_osds_krncmp($subdir, $lastdir) >=0))
{
$lastdir = $subdir;
}
}
close(LS);
}
if ($lastdir eq "0")
{
# no error because the user may have supplied -l (location)
# which over-rides.
return;
}
# Set the global kernel version
($variation) = $kver_bydot[$#kver_bydot]; # el5 or el5PAE, etc.
chomp($variation);
#Sometimes you got the arch instead the type in the latest position.
#Sample: 2.6.32-71.el6.x86_64
if ($variation eq $ARCH) {
($variation) = $kver_bydot[$#kver_bydot - 1]; # el5 or el5PAE, etc.
chomp($variation);
}
#Try to find variation by matching any of el,uek,xmp,xen
#If we have 2.6.32-71.el6.x86_64, we pop x86_64 and then match el6.
#TODO[AG] - Consider replacing the above gymnastics with this simple
#piece of code to get the variation
my @kcp = @kver_bydot;
while($kcp[$#kcp] !~ /el/ &&
$kcp[$#kcp] !~ /uek/ &&
$kcp[$#kcp] !~ /smp/ &&
$kcp[$#kcp] !~ /xen/ &&
$#kcp > 3) {
pop @kcp;
}
if($#kcp > 3){
#We don't want to take major, minor, mid versions [3]
$variation = $kcp[$#kcp];
}
($major) = $kver_bydot[0];
($midver) = $kver_bydot[1];
($minor) = $kver_bydot[2];
# We currently build kernels for variations ending in "el5", "el5PAE",
# "el5xen", and "el6". We also build 2.6.32-100.
# If the variation/minor here is none of the above, we need to
# either build additional drivers or massage the variation here. In either
# case, it's an internal error that should have been caught before we got
# here and so we just bail. We don't want to fail the entire oracle install
# and so return USM_NOT_SUPPORTED so that OUI can complete sans USM.
$valid_variation = 0;
if($major eq "2")
{
if($midver eq "6")
{
if(($minor eq "32-100") || ($minor eq "32-71") ||
($variation eq 'el5') || ($variation eq 'el5PAE') ||
($variation eq 'el5xen') || ($variation eq 'el6') ||
($minor eq "32-200") || ($minor eq "32-300") ||
($minor eq "32-400") ||
($minor eq "39-100") || ($minor eq "39-200") ||
($minor eq "39-300") || ($minor eq "39-400")
)
{
$valid_variation = 1;
}
}
}
elsif ($major eq "3")
{
if($midver eq "8")
{
#We have support for 3.8.13 for el6uek and el7uek
if(($minor =~ /^13/) ||
($variation eq "el6uek") ||
($variation eq "el7uek"))
{
$valid_variation = 1;
}
}
elsif ($midver eq "10")
{
#We have support for 3.10 for el7
if($variation eq "el7")
{
$valid_variation = 1;
}
}
}
elsif ($major eq "4")
{
if($midver eq "1")
{
#We have support for 4.1.12 for el6uek and el7uek
if(($minor =~ /^12/) ||
($variation eq "el6uek") ||
($variation eq "el7uek"))
{
$valid_variation = 1;
}
}
}
# Do we got a valid_variation?
if( $valid_variation == 0)
{
my $print = $variation; #Do we print the minor or the variation?
# For non-rhel kernels, the variation is useless.
if ($variation =~ /uek/ )
{
$print = $minor;
}
if ($acfslib::USM_CURRENT_PROD eq "prod_afd")
{
lib_error_print(9384,
"Invalid operating system kernel variation '%s'.", $print);
lib_error_print(9508, "AFD installation aborted (component %s).",
$COMMAND);
}
else
{
lib_error_print(9384, "Invalid OS kernel variation '%s'.", $print);
lib_error_print(9508, "ACFS installation aborted (component %s).",
$COMMAND);
}
exit USM_NOT_SUPPORTED unless defined($test_mode);
}
# Now create a base directory to look for the adequate modules
if($major eq "4")
{
if($midver eq "1")
{
# If we are here, we have a 4.1 kernel as supported.
# We don't need to check for minor version
# osds_is_kabi_compatible function will check for
# any different minor version
$base .= "/$type/$ARCH/$lastdir/$lastdir";
}
} #end if($major eq "4")
elsif($major eq "3")
{
if($midver eq "8" ||
$midver eq "10")
{
# If we are here, we have a 3.8 or 3.10 kernel as supported.
# We don't need to check for minor version
# osds_is_kabi_compatible function will check for
# any different minor version
$base .= "/$type/$ARCH/$lastdir/$lastdir";
}
} #end if($major eq "3")
elsif($major eq "2")
{
if($midver eq "6")
{
if (
($minor eq "32-100") || ($minor eq "32-200") ||
($minor eq "32-300") || ($minor eq "32-400") ||
($minor eq "39-100") || ($minor eq "39-200") ||
($minor eq "39-300") || ($minor eq "39-400")
)
{
# "32-100" has no variation (el5PAE, for example).
$base .= "/$type/$ARCH/$lastdir/$lastdir";
if (!($variation =~ /uek/)) # Unless it's RedHat
{
$base .= ".$variation";
}
}
else
{
$base .= "/$type/$ARCH/$lastdir/$lastdir.$variation";
}
} #if($midver eq "6")
} #end elsif($major eq "2")
if ($ARCH eq "x86_64")
{
$base .= "-x86_64/bin";
}
else
{
$base .= "-i686/bin";
}
}# end if (machine_is_RH())
elsif ( machine_is_SLES(@test_args) )
{
my ($line);
my ($SPnumber) = 0;
$base .= "/Novell";
#We add the PATCH LEVEL
if ($test_mode)
{
$SPnumber = $test_args[3];
}
else
{
if (-e "/etc/SuSE-release")
{
open (RELEASE, "/etc/SuSE-release");
while ($line = <RELEASE>)
{
if ($line =~ /PATCHLEVEL/)
{
# format: "PATCHLEVEL = 3"
my ($patchlevel, $equals, $number) = split(/ /, $line);
chomp ($number);
$SPnumber = $number;
last;
}
}
close (RELEASE);
}
elsif (-e "/etc/os-release")
{
open (RELEASE, "/etc/os-release");
while ($line = <RELEASE>)
{
if ($line =~ /VERSION_ID/)
{
# format: VERSION_ID="12"
my ($version_id, $number) = split(/=/, $line);
chomp ($number);
$number =~ s/\"//g;
my ($nversion, $patchnumber) = split(/\./, $number);
if (defined($patchnumber))
{
$SPnumber = $number;
}
last;
}
}
close (RELEASE);
}
}
if( $SPnumber eq "0"){
@dir_list = @sles12sp0;
}elsif( $SPnumber eq "1"){
@dir_list = @sles12sp1;
}elsif( $SPnumber eq "2"){
@dir_list = @sles12sp2;
}elsif( $SPnumber eq "3"){
@dir_list = @sles12sp3;
}
open (LS, "ls -v $base/$type/$ARCH/SP$SPnumber |");
$i = 0;
while ($subdir = <LS>)
{
@subdir_bydash = split(/\-/, $subdir);
chomp($subdir);
@subdir_bydot = split(/\./, $subdir);
$subdirstr = "$subdir_bydot[0]".".".
"$subdir_bydot[1]".".".
"$subdir_bydot[2]";
if( $runverification != 0)
{
#Check if directories found matches with valid directories list
if( $subdir ne $dir_list[$i])
{
lib_error_print( 9544,
"Invalid files or directories found: '%s'",
$subdir);
return;
}
$i++;
}
#Compare dir names, which are kernel versions, and kver numerically
if ((osds_unix_linux_acfslib::lib_osds_krncmp($subdirstr, $kverstr) <= 0) &&
(osds_unix_linux_acfslib::lib_osds_krncmp($subdir, $lastdir) >=0))
{
$lastdir = $subdir;
}
}
close(LS);
if ($lastdir eq "0")
{
# no error because the user may have supplied '-l' (location)
# which over-rides.
return;
}
($variation) = $kver_bydash[$#kver_bydash];
# smp, xen, or default
if ($variation =~ /smp/)
{
$base .= "/$type/$ARCH/SP$SPnumber/$lastdir/smp/bin";
}
elsif ($variation =~ /xen/)
{
$base .= "/$type/$ARCH/SP$SPnumber/$lastdir/xen/bin";
}
else
{
$base .= "/$type/$ARCH/SP$SPnumber/$lastdir/default/bin";
}
}
elsif (defined($test_mode))
{
# Make sure base is illegal since we measure success just by checking
# if the install directory exists.
undef $base;
}
# In this point, we have the base directory, the complete path with the
# drivers to install. We'll do a couple of extra validations.
if (!$base ||
!(-d $base))
{
lib_error_print( 9544, "Invalid files or directories found: '%s'", $base);
exit USM_NOT_SUPPORTED;
}
$osds_acfslib::configuration{path} = $base;
# First, Match kernel version in the driver using vermagic modinfo vs the
# path, we don't want that the customer copy drivers for other path version.
# Second check if drivers are kABI-Compatible, avoiding mismatch between
# Kernel Symbols vs Drivers Symbols.
# Check for ORA_ACFSROOT_TEST Variable.
my $do_check = 1;
if (defined($ENV{ADE_VIEW_ROOT}) &&
defined($ENV{_ORA_ACFSROOT_TEST}))
{
if (($ENV{_ORA_ACFSROOT_TEST}) == 8)
{
# Don't run
$do_check = 0;
}
}
if ($do_check && !defined($test_mode))
{
lib_uncompress_all_driver_files($base);
my $km_verify = "";
my $cmd = "";
foreach $km (@kms)
{
$km_complete = $base . "/" . $km;
$cmd = "/sbin/modinfo $km_complete|egrep 'vermagic.*$lastdir'|wc -l";
$km_verify = `$cmd`;
chomp( $km_verify);
if ($lastdir eq "4.1.12-112")
{
#Validation is not working in this case
$km_verify = "1";
}
if( $km_verify ne "1")
{
lib_error_print( 9545,
"Verification error: kernel module '%(1)s' is incompatible with " .
"the installed kernel version '%(3)s'. It is compatible with " .
"kernel version '%(2)s'.",
$km_complete, $lastdir, $UNAME_R);
return;
}
}
}
# We'll check if the drivers are kABI-compatible
if (!defined($test_mode) &&
machine_is_RH(@test_args))
{ # Will fail in $test_mode most of the time
if (!osds_is_kabi_compatible($base, $UNAME_R))
{
$base = KABI_NOT_SUPPORTED;
if ($acfslib::USM_CURRENT_PROD eq "prod_afd")
{
acfslib::lib_error_print_noalert(620,
"AFD is not supported on this operating system version: '%s'",
$KVER);
}
else
{
acfslib::lib_error_print_noalert(9459,
"ADVM/ACFS is not supported on this OS version: '%s'",
$KVER);
}
}
} #end KABI Validation
return $base;
} # end get_install_home_from_base
sub osds_patch_verify
{
my ($component); # curent component being verified
my ($return_code) = USM_SUCCESS;
foreach $component (@DRIVER_COMPONENTS)
{
my ($source) = "$OIP_PATH/$component";
my ($target) = "$DRIVER_DIR/$component";
if ($component eq "oracleadvm.ko")
{
$source = "$GPL_PATH/$component";
}
if(md5compare($source,$target) == USM_FAIL)
{
lib_inform_print (9999, "$source");
lib_inform_print (9999,"\tFAIL");
$return_code = USM_FAIL;
}
else
{
lib_verbose_print (9999, "$source");
lib_verbose_print (9999, "\tPASS");
}
}
foreach $component (@SBIN_COMPONENTS)
{
my ($target) = "$SBIN_DIR/$component";
my ($source) = "$CMDS_SRC_DIR/$component";
if(md5compare($source,$target) == USM_FAIL)
{
lib_inform_print (9999, "$source");
lib_inform_print (9999,"\tFAIL");
$return_code = USM_FAIL;
}
else
{
lib_verbose_print (9999, "$source");
lib_verbose_print (9999, "\tPASS");
}
}
return $return_code;
}
# osds_install_acfslib
#
# Installs the ACFS shared libary into a vendor specific location.
# This allows DB homes to use ACFS functions without needing to know
# the location of the current GI home.
# Called during 'acfsroot install'.
sub osds_install_acfslib
{
my ($source);
my ($uid);
my ($gid);
my ($libpath);
my ($ret);
my ($target) = $ENV{_vendor_lib_loc};
my ($return_code) = USM_SUCCESS;
my ($asmadmin) = lib_get_asm_admin_name();
my ($user) = acfslib::getParam("ORACLE_OWNER");
if(!defined($target))
{
# Target should be of the type
# /opt/oracle/extapi/[32,64]/{API}/{VENDOR}/{VERSION}/lib<apiname>.<ext>
#
$target = $LIBACFS_DIR;
}
# libacfsXX.so goes to /opt/oracle/extapi/64/acfs/orcl/...
$source = "$ORACLE_HOME/lib/$LIBACFS";
$libpath = $target.$LIBACFS;
# Get Owner and group of source
# get the owner/group of the original file
($uid, $gid) = (stat($source))[UID,GID];
if($user)
{
$uid = getpwnam($user);
}
$gid = getgrnam($asmadmin);
if(!(-e $target))
{
`mkdir -m 755 -p $target`;
if ($?)
{
lib_error_print(9345, "Unable to create directory: '%s'.", $target);
return USM_FAIL;
}
}
lib_verbose_print_noalert (9504, "Copying file '%s' to the path '%s'",
$source, $target);
unlink ("${target}/${LIBACFS}") if (-e "${target}/${LIBACFS}");
$ret = system ("cp -f $source $target");
$return_code = USM_FAIL if $ret;
if($return_code == USM_SUCCESS)
{
system("chmod 755 $libpath");
$ret = chown $uid, $gid, $libpath;
if($ret != 1)
{
lib_error_print(9426,"unable to set the file attributes for file '%s'",
$libpath);
return USM_FAIL;
}
}
return $return_code;
} # end osds_install_acfslib
# osds_uninstall_acfslib
#
# Removes the ACFS library from the vendor specific location.
# Called during 'acfsroot uninstall'
sub osds_uninstall_acfslib
{
my ($return_code) = USM_SUCCESS;
my ($libpath);
my ($target) = $ENV{_vendor_lib_loc};
if(!defined($target))
{
# Target should be of the type
# /opt/oracle/extapi/[32,64]/{API}/{VENDOR}/{VERSION}/lib<apiname>.<ext>
#
$target = $LIBACFS_DIR;
}
$libpath = $target.$LIBACFS;
if(-e $libpath)
{
if (! unlink $libpath)
{
lib_inform_print(9348, "Unable to remove '%s'.", $libpath);
$return_code = USM_FAIL;
}
}
return $return_code;
} # end osds_uninstall_acfslib
# osds_check_dir_empty
#
# Check if passed directory is empty
# Called during 'acfsroot uninstall'
#
# Recive:
# dir name to check
#
# Return:
# 0: if empty
# 1: if non empty
sub osds_check_dir_empty
{
my ($dir) = $_[0];
opendir(DIR, $dir) || return 1;
my (@dir_cont) = readdir(DIR);
close(DIR);
if( grep(/\w/, @dir_cont) )
{
# dir non empty
return 1;
}
else
{
# dir empty
return 0;
}
} # end osds_check_dir_empty
1;
OHA YOOOO