#) # # osds_acfsroot.pm # # Copyright (c) 2007, 2016, 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_RH machine_is_SLES osds_symvers_exists osds_configure_acfs_remote $MEDIA_FOUND $ORACLE_HOME $USM_DFLT_DRV_LOC $USM_DFLT_CMD_LOC $USM_TUNE_OS_DIR $USM_TUNE_ORA_DIR ); use osds_acfslib; use acfslib; 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 ($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); # We do not install/uninstall the commands destined for ORACLE_HOME - that # is now done by the mapfiles during Oracle install/uninstall. We use # _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) = "libacfs12.so"; # Default ACFS library install directory my ($LIBACFS_DIR) = "/opt/oracle/extapi/64/acfs/orcl/1/"; my (@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", ); my (@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/acfsccm", "$OH_BIN_DIR/advmccb", "$OH_BIN_DIR/acfsrm", ); my (@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/acfshanfs.pl", "$OH_LIB_DIR/osds_acfshanfs.pm", ); my (@USM_PUB_COMPONENTS) = ( "$USM_PUB_DST_DIR/acfslib.h", ); my (@MESG_COMPONENTS) = ( "$MESG_DST_DIR/acfsus.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_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 our ($DOM) = -1; # dom mode for ACFSR our $asm_storage_mode = 0; # ASM Storage Mode # osds_symvers_exists # # /sbin/weak-modules depends on /boot being accessible and the # symvers- file being present. sub osds_symvers_exists { my ($kver) = @_; if (machine_is_RH()) { my ($symvers_file) = "symvers-" . $kver . ".gz"; 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); return 0; } } 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'; # /sbin/weak-modules depends on /boot being accessible and the # symvers- file being present. if (!osds_symvers_exists($kver)) { # error messages generated by osds_symvers_exists(). return 0; } # 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. my ($no_init) = ""; $no_init = `/sbin/weak-modules -h | grep ^'--no-initrd\\|--no-initramfs'`; chomp($no_init); # 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 $output = `ls $base_directory/$DRIVER_COMPONENTS[OKS_IDX] | /sbin/weak-modules --verbose --dry-run $no_init --add-modules 2>&1 | grep -v debug | grep -w "with kernel $kver" | grep $compatible | grep -v ksplice`; if ($output eq "") { 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[OFS_IDX], $DRIVER_COMPONENTS[AVD_IDX]) { # Checking for ACFS/ADVM Driver $output = `ls $base_directory/$module | /sbin/weak-modules --verbose --dry-run $no_init --add-modules 2>&1 | grep -v debug | grep -w "with kernel $kver" | grep "compatible" | grep -v ksplice`; # 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 ($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) { lib_verbose_print(9460, "Missing symbols: '%s'", join ' ', @confirmed_missing_symbols); return 0; } } } 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, $test_mode, $test_os, $test_unamer, $test_patchlevel, $test_arch) = @_; my ($vendor); my ($type); my (@test_params); my ($test_release); my ($lxcversion); 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"))) { 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 $lxcversion = lib_is_local_container(); if ( $lxcversion ne USM_SUPPORTED ) { lib_error_print(9430, "ADVM/ACFS is not supported on this OS configuration: '%s'", "Linux Container"); return USM_NOT_SUPPORTED; } # /sbin/weak-modules depends on /boot being accessible and the # symvers- 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; $USM_DFLT_DRV_LOC = get_install_home_from_base($base, $type, $ARCH, $KVER, @test_params); if (defined($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 ($target) = "$SBIN_DIR/$component"; my ($source); $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) ) { $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 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); $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 =~ /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); } } # 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); lib_verbose_print_noalert (9504, "Copying file '%s' to the path '%s'", $source, $target); ($uid, $gid) = (stat($target))[UID,GID]; if ( ! acfslib::lib_are_same_file($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); } $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_acfsroot::DOM >= 0) { my $result; my $filename = "/etc/modprobe.d/oracleadvm.conf"; my $asm_acfsr_mode = $osds_acfsroot::DOM; if ( -e "/tmp/oracleadvm.conf" ) { lib_trace("9999", "Using /tmp/oracleadvm.conf"); system("mv /tmp/oracleadvm.conf $filename"); } my $asm_acfsr_mode_line = "options oracleadvm 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; open ($fh,">$filename") || return USM_FAIL; for (@lines) { s/$asm_acfsr_mode_line\d/$asm_acfsr_mode_line$asm_acfsr_mode/g; print $fh $_; } close $fh; } else { # write mode to file and check for operation failure # create file and check for operation failure lib_trace("9999", "No oracleadvm.conf 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 = "644"; $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/modprobe.d/oracleadvm.conf"; $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) = @_; 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 $USM_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 ("/", $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; } @install_loc_array = split(/,/, $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"; if ($component =~ /$LIBACFS/) { # Special case libacfs as it lives apart from the other commands. $source = "$USM_LIB_SRC_DIR/$file"; } elsif ($component =~ /msb$/) { # 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 ($no_initrd) = ""; my ($print_header) = 1; $no_initrd = `/sbin/weak-modules -h | grep ^'--no-initrd\\|--no-initramfs'`; chomp($no_initrd); my ($cmd) = "echo \"$driver_list\" | /sbin/weak-modules $no_initrd" . " --add-modules $KVER 2>&1 |"; open (MOD, $cmd); while () { 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 { # 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 (!$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; } } } # Guarantee that we're not in one of the usm directories about to be nuked. chdir "/"; # Remove /etc/modprobe.d/oracleadvm.conf if( -e "/etc/modprobe.d/oracleadvm.conf" ) { my $result; if (defined($ENV{'ADE_VIEW_ROOT'})) { $result = system("mv /etc/modprobe.d/oracleadvm.conf /tmp/"); } else { $result = system("rm -f /etc/modprobe.d/oracleadvm.conf"); } if ($result != 0) { lib_error_print(5027, "cannot remove file: %s", "/etc/modprobe.d/oracleadvm.conf"); } } # 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) open (CHECK, "find /lib/modules 2> /dev/null |"); while () { 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 the base directories but only if empty my (undef, $lib, $modules, $kver) = split (/\//, $driver); my $subdir = "/$lib/$modules/$kver"; finddepth(sub{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()); } # 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 () { 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", "$OH_BIN_DIR/acfsload", "$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", ); my ($prog); my ($line); my (@buffer); foreach $prog (@progs) { my ($read_index, $write_index); $read_index = 0; lib_trace( 9999, "Fixing $prog wrapper script."); if (open(READ, "<$prog")) { while ($line = ) { 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"; } $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, $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 @test_args; if (defined($test_mode)) { if ($test_mode == 1) { # Will probably send uname -r instead of kernel version @test_args = @_[4..8]; # 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") { open (LS, "ls -v $base/$type/$ARCH |"); while ($subdir = ) { chomp($subdir); @subdir_bydot = split(/\./, $subdir); $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"; } # We'll check if the drivers are kABI-compatible compatible if (!defined($test_mode)) { # 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 if ( !($base =~ $kverstr)) }# 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 = ) { 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 = ) { 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); } } open (LS, "ls $base/$type/$ARCH/SP$SPnumber |"); while ($subdir = ) { @subdir_bydash = split(/\-/, $subdir); chomp($subdir); @subdir_bydot = split(/\./, $subdir); $subdirstr = "$subdir_bydot[0]".".". "$subdir_bydot[1]".".". "$subdir_bydot[2]"; #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; } 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. # $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); $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. # $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 =cut This function starts the iscsid service if we detect an ACFS Remote installation in Domain Services Mode. For now, only el7uek 3.8 is supported. =cut sub osds_configure_acfs_remote { lib_trace( 9999, "Configuring ACFS Remote."); my $result = 0; my $return_code = 0; $asm_storage_mode = acfslib::getParam("ASM_CONFIG"); if ($asm_storage_mode ne '') { if ($asm_storage_mode eq 'near') { $asm_storage_mode = 0; } else { $asm_storage_mode = 1; } # Set the ACFS Remote storage mode tunable (AcfsRemoteStorageMode). $result = system("$ACFSUTIL tune " . " AcfsRemoteStorageMode=$asm_storage_mode" . "2>1 1>/dev/null"); if($result != 0) { lib_error_print(3099, "error updating driver tunables"); $return_code = $result; } } my $kernel = $UNAME_R; my $cluster_class = acfslib::getParam("CLUSTER_CLASS");; if ( $cluster_class ne '') { lib_trace( 9999, "Cluster class is $cluster_class"); if ($cluster_class eq 'DOMAINSERVICES' || (defined ($ENV{'ADE_VIEW_ROOT'}) && $cluster_class eq 'SHMI')) { # TODO create a get_dc_supported_transport function for # when we support more variations. if ($cluster_class eq 'SHMI' || (($kernel =~ /3.8/) && ($kernel =~ /el7uek/))) { lib_trace( 9999, "ACFS Remote is supported in this kernel." . " Setting up iscsid."); # Insert transport configuration here. `/sbin/service iscsid start`; `/sbin/service iscsid status`; } else { lib_trace( 9999, "ACFS Remote is not supported in this " . "kernel. Skipping iscsid setup."); } } else { lib_trace( 9999, "Skipping iscsid setup."); } if ($cluster_class eq 'MEMBER') { my $udev_rules = '/etc/udev/rules.d/65-usm-acfsr-member.rules'; my $udev_script = '/lib/udev/acfsr_member'; # write udev rules open (OUT_FILE, ">$udev_rules") || die ("ERROR: Cannot create file '$udev_rules': $!\n"); print OUT_FILE "KERNEL==\"sd*\", " . "SUBSYSTEMS==\"scsi\", " . "PROGRAM=\"acfsr_member %b %p\", " . "SYMLINK+=\"acfsr/%c{1}/%c{2}\""; close OUT_FILE; # write udev script open (OUT_FILE, ">$udev_script") || die ("ERROR: Cannot create file '$udev_script': $!\n"); print OUT_FILE "#!/usr/bin/perl\n"; print OUT_FILE "\n"; print OUT_FILE "use strict;\n"; print OUT_FILE "\n"; print OUT_FILE "my \$BUS = \$ARGV[0];\n"; print OUT_FILE "my \$SYSFSPATH = \"/sys\$ARGV[1]\";\n"; print OUT_FILE "my \$dh;\n"; print OUT_FILE "my \@session;\n"; print OUT_FILE "my \$trString;\n"; print OUT_FILE "my \$seqnum;\n"; print OUT_FILE "my \$port;\n"; print OUT_FILE "\n"; print OUT_FILE "\n"; print OUT_FILE "# BUS should look like 4:0:0:0\n"; print OUT_FILE "\$BUS =~ m/(\\d+):*/;\n"; print OUT_FILE "my \$HOST = \$1; # Should return the first number in BUS\n"; print OUT_FILE "\n"; print OUT_FILE "\n"; print OUT_FILE "\n"; print OUT_FILE "my \$HOSTDIR = \"/sys/class/iscsi_host/host\$HOST/device\";\n"; print OUT_FILE "if ( -d \$HOSTDIR )\n"; print OUT_FILE "{\n"; print OUT_FILE " # ISCSI\n"; print OUT_FILE " \$trString = \"ISCSI\";\n"; print OUT_FILE "\n"; print OUT_FILE " opendir(\$dh, \$HOSTDIR);\n"; print OUT_FILE " \@session = grep { /session*/ } readdir(\$dh);\n"; print OUT_FILE " closedir(\$dh);\n"; print OUT_FILE "\n"; print OUT_FILE " exit 1 if (\@session != 1);\n"; print OUT_FILE "\n"; print OUT_FILE " my \$file = \"/sys/class/iscsi_host/host\$HOST/device/\$session[0]/iscsi_session/\$session[0]/targetname\";\n"; print OUT_FILE "\n"; print OUT_FILE " open FILE, \"<\$file\" || exit 1; \n"; print OUT_FILE " my \$target_name = do { local \$/; };\n"; print OUT_FILE " close FILE;\n"; print OUT_FILE "\n"; print OUT_FILE " exit 1 if (\$target_name !~ /oracle:acfsr:/);\n"; print OUT_FILE "\n"; print OUT_FILE " my (\@tgt_array) = split (\":\", \$target_name);\n"; print OUT_FILE "\n"; print OUT_FILE "# iqn.2015-12.com.oracle:acfsr:xxxxxx::\n"; print OUT_FILE " exit 1 if (\@tgt_array != 5);\n"; print OUT_FILE "\n"; print OUT_FILE " \$seqnum = \$tgt_array[3];\n"; print OUT_FILE " \$port = \$tgt_array[4];\n"; print OUT_FILE "}\n"; print OUT_FILE "else\n"; print OUT_FILE "{\n"; print OUT_FILE " exit 1;\n"; print OUT_FILE "}\n"; print OUT_FILE "\n"; print OUT_FILE "# if seqnum is non-numeric, then punt\n"; print OUT_FILE "if (\$seqnum =~ /[^0-9]/) {\n"; print OUT_FILE " exit 1;\n"; print OUT_FILE "}\n"; print OUT_FILE "\n"; print OUT_FILE "\$trString = \$trString . \".\" . \$seqnum;\n"; print OUT_FILE "\n"; print OUT_FILE "# Update the request queue parameters for the SCSI device\n"; print OUT_FILE "if ( -w \"\$SYSFSPATH/queue/nr_requests\")\n"; print OUT_FILE "{\n"; print OUT_FILE " system(\"echo 512 >\$SYSFSPATH/queue/nr_requests\");\n"; print OUT_FILE "}\n"; print OUT_FILE "if ( -w \"\$SYSFSPATH/queue/max_sectors_kb\")\n"; print OUT_FILE "{\n"; print OUT_FILE " system(\"echo 1024 >\$SYSFSPATH/queue/max_sectors_kb\");\n"; print OUT_FILE "}\n"; print OUT_FILE "\n"; print OUT_FILE "print \"\$trString \$port\";\n"; close OUT_FILE; } } else { lib_trace( 9999, "CLUSTER_CLASS is NULL."); } } 1;