# # osds_acfslib.pm # # Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. # # # NAME # osds_acfslib.pm - Linux OSD library components. # # DESCRIPTION # Purpose # Linux OSD library functions for the install/runtime scripts. # # 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; use acfslib; use osds_unix_linux_acfslib; package osds_acfslib; require Exporter; our @ISA = qw(Exporter); our @EXPORT = qw( lib_osds_check_uninstall_required lib_osds_check_driver_inuse lib_osds_check_driver_installed lib_osds_check_driver_loaded lib_osds_check_loaded_drivers_mismatch lib_osds_create_udev lib_osds_exportfs lib_osds_get_current_installed_version lib_osds_get_os_type lib_osds_get_make_type lib_osds_get_usm_udev_rules_file lib_osds_load_driver lib_osds_remove_exports lib_osds_restore_exports lib_osds_unload_driver lib_osds_get_linux_vendor lib_osds_is_mounted lib_osds_validate_asmadmin_group lib_osds_is_local_container lib_osds_acfs_remote_supported lib_osds_acfs_remote_installed lib_osds_acfs_remote_loaded @DRIVER_COMPONENTS ); our (@DRIVER_COMPONENTS) = ( "oracleadvm.ko", "oracleoks.ko", "oracleacfs.ko", ); my ($CACHED_INSTALLED_DRIVERS); # saved find /lib/modules output my ($CACHED_LOADED_DRIVERS); # saved find lsmod output my ($EXPORTFS) = "/usr/sbin/exportfs"; my ($UNAME_R) = `uname -r`; chomp ($UNAME_R); my ($ARCH) = `uname -i`; chomp ($ARCH); # e.g., "x86-64" chomp ($UNAME_R); my ($CGROUP) = "/proc/1/cgroup"; # LXC information file # /sbin/fuser ... RH Enterprise Linux # /bin/fuser ... Suse # /usr/sbin/fuser ... AIX, HPUX, Solaris # /usr/sbin/lsof ... RH Enterprise Linux # /sbin/modprobe ... RH Enterprise Linux $ENV{PATH} = $ENV{PATH} . ":/sbin:/bin:/usr/sbin"; # lib_osds_check_driver_inuse # # use lsmod to see if a driver is in use. # sub lib_osds_check_driver_inuse { my ($driver) = @_; my ($ret_val) = 0; # strip ".ko" from driver name $driver =~ s/.ko//; # USM drivers must be loaded. # This should have happened in clsinitd when clusterware started. open (INUSE, "lsmod |"); while () { my ($name, $size, $use_count) = split; if ($name eq $driver) { $ret_val = $use_count; last; } } close (INUSE); return $ret_val; } # end lib_osds_check_driver_inuse use File::Basename; # lib_osds_check_driver_installed() # sub lib_osds_check_driver_installed { my ($driver) = @_; my ($usm_driver); # only do the find(1) once. if (!defined($CACHED_INSTALLED_DRIVERS)) { #Change directory to tmp if (defined($ENV{'TEMP'}) && (-d "$ENV{'TEMP'}")) { chdir $ENV{'TEMP'}; } elsif (defined($ENV{'TMP'}) && (-d "$ENV{'TMP'}")) { chdir $ENV{'TMP'}; } elsif (-d "/tmp/") { chdir "/tmp"; } # search /lib/modules for the installed drivers. $CACHED_INSTALLED_DRIVERS = ""; # conditional code for RAC KA product if ($acfslib::USM_CURRENT_PROD eq "prod_afd") { open (USM, "find /lib/modules/ | grep oracle |"); } elsif ($acfslib::USM_CURRENT_PROD eq "prod_oka") { open (USM, "find /lib/modules/ | grep oracka |"); } else { open (USM, "find /lib/modules/ | grep usm |"); } while ($usm_driver = ) { $usm_driver = basename($usm_driver); chomp($usm_driver); $CACHED_INSTALLED_DRIVERS .= "$usm_driver "; } close(USM); } if ($CACHED_INSTALLED_DRIVERS =~ m/$driver/) { return 1; } # fail return 0; } # end lib_osds_check_driver_installed # lib_osds_check_uninstall_required # sub lib_osds_check_uninstall_required { my ($previous_install_detected_msg) = @_; my ($return_code); $return_code = acfslib::lib_check_any_driver_installed(); if(($return_code) && ($previous_install_detected_msg)) { acfslib::lib_inform_print(9312, "Existing ADVM/ACFS installation detected."); } return $return_code; } # end lib_osds_check_uninstall_required # lib_osds_check_driver_loaded # # use lsmod to see if a driver is loaded. # sub lib_osds_check_driver_loaded { my ($driver) = @_; my ($ret_val) = 0; my ($usm_driver); my (@cached_loaded_drivers_array); my ($lxcversion); # strip ".ko" from driver name $driver =~ s/.ko//; # Linux Container configuration # Host and Container are sharing '/proc/modules' and hence 'lsmod' # shows that oracle modules are configured and loaded. # Because ACFS/ADVM drivers are not supported on Linux Containers, # return early $lxcversion = acfslib::lib_is_local_container(); if ( $lxcversion ne osds_unix_linux_acfslib::USM_SUPPORTED ) { return $ret_val; } # only do the lsmod(8) once. if (!defined($CACHED_LOADED_DRIVERS)) { $CACHED_LOADED_DRIVERS = ""; open (LOADED, "lsmod |"); while ($usm_driver = ) { my ($module, $size, $used, $by) = split(/\s+ /, $usm_driver); $CACHED_LOADED_DRIVERS .= "$module "; } close (LOADED); } @cached_loaded_drivers_array = split(/ /, $CACHED_LOADED_DRIVERS); foreach $usm_driver (@cached_loaded_drivers_array) { if ($usm_driver eq $driver) { $ret_val = 1; last; } } return $ret_val; } # end lib_osds_check_drivers_loaded # lib_osds_check_loaded_drivers_mismatch # # Determine whether or not the installed drivers match the drivers that # are loaded in the kernel. # Solaris only for now. sub lib_osds_check_loaded_drivers_mismatch { return 0; } # lib_osds_create_udev # # Create a USM udev file # sub lib_osds_create_udev { my ($asmadmin) = @_; my ($udev_perm_file); $udev_perm_file = lib_osds_get_usm_udev_rules_file(); # create the permissions file - replaces existing file (if any) open PERM, ">$udev_perm_file" or die "can't create file: $!"; print PERM "#\n"; print PERM "# ADVM devices\n"; print PERM "KERNEL==\"asm/*\", GROUP=\"$asmadmin\", MODE=\"0770\"\n"; print PERM "KERNEL==\"asm/.*\", GROUP=\"$asmadmin\", MODE=\"0770\"\n"; print PERM "#\n"; print PERM "# ACFS devices\n"; print PERM "KERNEL==\"ofsctl\", GROUP=\"$asmadmin\", MODE=\"0664\"\n"; close PERM; } # end lib_osds_create_udev # lib_osds_exportfs # # called after a file system is mounted. If the mount point is in # /etc/exports, we export the file system here. # sub lib_osds_exportfs { my ($mountpoint) = @_; # TBD: parse /etc/exports and if $mountpoint is listed, export # the file sustem. # # For now, we use brute force. Calling "exportfs -a" repeatedly is # harmless and quick. system("$EXPORTFS -a"); } # end lib_osds_exportfs # lib_osds_get_os_type # # Add to this routine as USM supports new Linux variants # my ($lib_osds_get_os_type_initialized) = 0; my ($saved_vers) = 0; sub lib_osds_get_os_type { # conditional code for RAC KA product if ($acfslib::USM_CURRENT_PROD eq "prod_oka") { return lib_osds_get_oka_os_type(@_); } # Check whether ACFS/AVD/AFD is supported return lib_osds_get_acfs_os_type(@_); } # This api is for ACFS/ADVM/AFD. sub lib_osds_get_acfs_os_type { my ($vers) = "unknown"; my ($kver) = $UNAME_R; my ($release); my ($supported) = 0; my ($test_mode, $test_release, $test_version, $test_patchlevel, $test_arch) = @_; # during "acfsroot install" we get called 12 times (really). if ($lib_osds_get_os_type_initialized) { return $saved_vers; } # Check to see if we support this Linux release # see - http://www.oracle.com/us/technologies/027626.pdf and # see - http://www.oracle.com/us/technologies/linux6cert-400781.pdf if (-e "/etc/oracle-release") { open (RPM_QF, "rpm -qf /etc/oracle-release 2>&1 |"); $release = ; close (RPM_QF); } elsif (-e "/etc/redhat-release") { open (RPM_QF, "rpm -qf /etc/redhat-release 2>&1 |"); $release = ; close (RPM_QF); } elsif (-e "/etc/SuSE-release") { open (RPM_QF, "rpm -qf /etc/SuSE-release 2>&1 |"); $release = ; close (RPM_QF); } # Big distributions using systemd have to use os-release file. # EL7/RHEL7 and SLES12 include this file and they can # deprecate their own release files # http://comments.gmane.org/gmane.comp.sysutils.systemd.devel/4401 # http://www.freedesktop.org/software/systemd/man/os-release.html elsif (-e "/etc/os-release") { open (RPM_QF, "rpm -qf /etc/os-release 2>&1 |"); $release = ; close (RPM_QF); } if ($test_mode) { $release = $test_release; $kver = $test_version; $ARCH = $test_arch; } # Testing for "oraclelinux_release", etc prevents us from dropping # into the code below from other RH based distros like CentOS, for example. if ((defined($release)) && # Redhat or OEL if defined (($release =~ /^redhat-release/) || # straight RH ($release =~ /^enterprise-release/) || # Oracle Enterprise Linux ($release =~ /^oraclelinux-release/))) # Oracle Linux { my ($major, $minor, $patch, $vendor, $variation) = split /\./, $kver; my ($micro_number, $patch_level) = split /-/, $patch; # e.g., 100 and 32 if ($vendor =~ /\D/) { $vendor = 0; } if ($kver =~ /debug?/) { # we do not build drivers for debug kernels. $vers = $kver; $supported = 0; } elsif ($ARCH =~ /i[3-6]86/) { $vers = "i386"; # 32 bit kernels not supported $supported = 0; } elsif ($release =~ /AXS/) # Asianux Not supported { $vers = "ASIANUX"; $supported = 0; } elsif ($release =~ /release-4/) # RH/EL 4 Not Supported { $vers = "Linux 2.4"; $supported = 0; } elsif ($release =~ /release-5/) # RH/OEL 5 Partially Supported { # We assume unsupported unless we specifically indicate otherwise. $vers = $kver; $supported = 0; # Support for EL5 is removed in 12.2, support for 2.6.18 and # the rest of EL5 is going away. if ($kver =~ /2.6.18/) { $supported = 0; $vers = "EL5"; } elsif ($kver =~ /uek/) { if ($kver =~ /2.6.32-100/) { $vers = "EL5"; $supported = 0; } elsif ($kver =~ /2.6.32-200/) { $vers = "EL5"; $supported = 0; } elsif ($kver =~ /2.6.32-300/) { $vers = "EL5"; $supported = 0; } elsif ($kver =~ /2.6.32-400/) { $vers = "EL5"; $supported = 0; } elsif ($kver =~ /2.6.39-100/) { $vers = "EL5"; $supported = 0; } elsif ($kver =~ /2.6.39-200/) { $vers = "EL5"; $supported = 0; } elsif ($kver =~ /2.6.39-300/) { $vers = "EL5"; $supported = 0; } elsif ($kver =~ /2.6.39-400/) { $vers = "EL5"; $supported = 0; } } } elsif (($release =~ /release-6/) || # OEL 6 Partially Supported ($release =~ /server-6/)) # RHEL 6 Partially Supported { # We assume unsupported unless we specifically indicate otherwise. $vers = $kver; $supported = 0; #Oracle Linux 6 ships with two sets of kernel packages: # Unbreakable Enterprise Kernel (Ex: kernel-uek-2.6.32-100.28.5.el6), # which is available only on the x86_64 (64-bit) platform # # Red Hat compatible kernel (Ex: kernel-2.6.32-71.el6). #So, We can find uek or rhel compatible kernels. if ($kver =~ /uek/) { if ($kver =~ /2.6.39-100/) { $vers = "EL6"; $supported = 1; } elsif ($kver =~ /2.6.39-200/) { $vers = "EL6"; $supported = 1; } elsif ($kver =~ /2.6.39-300/) { $vers = "EL6"; $supported = 1; } elsif ($kver =~ /2.6.39-400/) { if ($vendor >= 278 && $vendor < 281) { $vers = "EL6"; $supported = 0; } else { $vers = "EL6"; $supported = 1; } } elsif ($kver =~ /3.8.13/) { if (($patch_level == 118) && ($vendor >= 5 && $vendor < 8)) { $vers = "EL6"; $supported = 0; } else { $vers = "EL6"; $supported = 1; } } elsif ($kver =~ /4.1.12/) { $vers = "EL6"; $supported = 1; } } else #For RHEL Kernels. We only support GA, U1 and U2. { #For compatible RHEL6 Kernels, We check the number release #We support 6.0, 6.1, 6.2 and 6.3 my $LSB_RELEASE; if(-e "/usr/bin/lsb_release") { $LSB_RELEASE = `/usr/bin/lsb_release -sr`; } if ($test_mode) { $LSB_RELEASE = "6.0"; #By default } #### Split $LSB_RELEASE my ($major_lsb, $minor_lsb); if(defined($LSB_RELEASE)){ ($major_lsb, $minor_lsb) = split /\./, $LSB_RELEASE; } #### $major_lsb has to be equal to 6 and $minor_lsb between 0 and 3 if ((defined($major_lsb) && defined($minor_lsb)) && ($major_lsb == 6 && ($minor_lsb >= 0 and $minor_lsb <= 3)) && ($kver =~ /2.6.32/)) { #RHEL6 GA - Start in 71 #RHEL6 U1 - Start in 131 #RHEL6 U2 - Start in 220 #RHEL6 U3 - Start in 279 #We check Build Number -XXX my ($krelease, $kremainder) = split /-/, $kver; my ($kvariation) = split /\./, $kremainder; if ($kvariation != 100 && $kvariation >= 71 && $kvariation < 131) { $vers = "EL6"; $supported = 1; } elsif ($kvariation >= 131 && $kvariation < 220) { $vers = "EL6"; $supported = 1; } elsif ($kvariation >= 220 && $kvariation < 279) { $vers = "EL6"; $supported = 1; } elsif ($kvariation >= 279) { $vers = "EL6"; $supported = 1; } } else { # For RHEL6. We are supporting all the number releases. # But we are not sure, if we can load or not the drivers. # Installation process has to do a validation to predict success # loading the drivers $vers = "EL6"; $supported = 1; } } } # release-6 elsif (($release =~ /release-7/) || # OEL 7 Supported ($release =~ /server-7/)) # RHEL 7 Supported { # We assume unsupported unless we specifically indicate otherwise. $vers = $kver; $supported = 0; #Oracle Linux 7 ships with two sets of kernel packages: # Unbreakable Enterprise Kernel # (Ex: kernel-uek-3.8.13-35.el7uek.x86_64). # # Red Hat compatible kernel (Ex: kernel-3.10.0-123.el7.x86_64). # #So, We can find uek or rhel compatible kernels. if ($kver =~ /uek/) { if ($kver =~ /3.8.13/) { if ($patch_level >= 35) { if (($patch_level == 118) && ($vendor >= 5 && $vendor < 8)) { $vers = "EL7"; $supported = 0; } else { $vers = "EL7"; $supported = 1; } } } elsif ($kver =~ /4.1.12/) { if ($patch_level >= 32) { $vers = "EL7"; $supported = 1; } } } else #For RHEL Kernels. { #For compatible RHEL7 Kernels, We check the number release #We support 7.0 my $LSB_RELEASE; if(-e "/usr/bin/lsb_release") { $LSB_RELEASE = `/usr/bin/lsb_release -sr`; } if ($test_mode) { $LSB_RELEASE = "7.0"; #By default } #### Split $LSB_RELEASE my ($major_lsb, $minor_lsb); if(defined($LSB_RELEASE)){ ($major_lsb, $minor_lsb) = split /\./, $LSB_RELEASE; } #### $major_lsb has to be equal to 7 and $minor_lsb between 0 and 1 if ((defined($major_lsb) && defined($minor_lsb)) && ($major_lsb == 7 && ($minor_lsb >= 0 and $minor_lsb <= 3)) && ($kver =~ /3.10.0/)) { #We check Build Number -XXX my ($krelease, $kremainder) = split /-/, $kver; my ($kvariation) = split /\./, $kremainder; if (($kvariation >= 123) && ($kvariation < 210)) { $vers = "EL7"; $supported = 1; } elsif (($kvariation >= 210) && ($kvariation < 514)) { $vers = "EL7"; $supported = 1; } elsif ($kvariation >= 514) { $vers = "EL7"; $supported = 1; } } elsif (($major == 3) && ($minor == 10)) { # For RHEL7. We are supporting all the number releases. # But we are not sure, if we can load or not the drivers. # Installation process has to do a validation to predict success # loading the drivers $vers = "EL7"; $supported = 1; } } } # release-7 } # RH/OEL elsif (defined($release) && $release =~ /^sles-release/) { my ($major, $minor, $patch, $vendor, $variation) = split /\./, $kver; my ($micro_number, $patch_level) = split /-/, $patch; # e.g., 100 and 32 my ($line); my ($SPnumber) = 0; if ($test_mode) { $SPnumber = $test_patchlevel; } 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 = $patchnumber; } last; } } close (RELEASE); } } # We assume unsupported unless we specifically indicate otherwise. $vers = "$kver SP$SPnumber"; $supported = 0; if ($kver =~ /debug?/) { # we do not build drivers for debug kernels. $vers = $kver; $supported = 0; } elsif ($ARCH eq "i386") { $supported = 0; $vers = "i386"; } elsif ($release =~ /^sles-release-11/) { if (($kver =~ /2.6.32/) && ($SPnumber == 1)) { $supported = 0; $vers = "SLES11"; } elsif (($kver =~ /^3.0/) && ($SPnumber == 2)) { $supported = 0; $vers = "SLES11"; } elsif (($kver =~ /^3.0/) && ($SPnumber == 3)) { # For SP3, We don't support all the 3.0.*Kernels # SuSe just releases the 3 following kernels: # SP3-July-2013 3.0.76-0.11.1 # July-11-2013 3.0.82-0.7.9 # Sept-21-2013 3.0.93-0.8.2 # So, We support greater than 3.0.76-0 if ($micro_number >= 76) { $supported = 0; $vers = "SLES11"; } } elsif (($kver =~ /^3.0/) && ($SPnumber == 4)) { # For SP4. SuSe release Kernel 3.0.101-63.1 if ($micro_number >= 101) { $supported = 0; $vers = "SLES11"; } } } elsif ($release =~ /^sles-release-12/) { if (($kver =~ /^3.12/) && ($SPnumber == 0)) { # SLES 12 was released with the kernel version # 3.12.28-4.6. if ($micro_number >= 28) { $supported = 1; $vers = "SLES12"; } } elsif (($kver =~ /^3.12/) && ($SPnumber == 1)) { # SLES 12 SP1 was released with the kernel version # 3.12.49-11.1 if ($micro_number >= 49) { $supported = 1; $vers = "SLES12"; } } } } else { # Not Redhat, OEL, SUSE, etc. $vers = $release; $supported = 0; } if ( ($supported) && (not defined($ENV{_ORA_USM_NOT_SUPPORTED})) ) { # Required by usm_root - $vers MUST be a sub-directory in the install path # e.g., install/Oracle/EL5/i386/2.6.18-8/2.6.18-8.el5PAE-i686/bin # ^^^ $saved_vers = $vers; return $vers; } if ( defined($ENV{_ORA_USM_NOT_SUPPORTED})) { $vers .= " (via ENV VARIABLE)"; } if (! $test_mode) { $lib_osds_get_os_type_initialized = 1; if ($acfslib::USM_CURRENT_PROD eq "prod_afd") { afdlib::lib_error_print_noalert(620, "AFD is not supported on this operating system version: '%s'", $vers); } else { acfslib::lib_error_print_noalert(9459, "ADVM/ACFS is not supported on this OS version: '%s'", $vers); } } if ($acfslib::USM_CURRENT_PROD eq "prod_afd") { $saved_vers = "AFD is not supported on $vers"; return "AFD is not supported on $vers"; } $saved_vers = "ADVM/ACFS is not supported on $vers"; return "ADVM/ACFS is not supported on $vers"; } # end get_os_type # RAC KA install - related sub lib_osds_get_oka_os_type { my ($vers) = "unknown"; my ($kver) = $UNAME_R; my ($release); my ($supported) = 0; my ($test_mode, $test_release, $test_version, $test_patchlevel) = @_; # during "okaroot install" we get called 12 times (really). if ($lib_osds_get_os_type_initialized) { return $saved_vers; } # Check to see if we support this Linux release # see - http://www.oracle.com/us/technologies/027626.pdf if (-e "/etc/oracle-release") { open (RPM_QF, "rpm -qf /etc/oracle-release 2>&1 |"); $release = ; close (RPM_QF); } elsif (-e "/etc/redhat-release") { open (RPM_QF, "rpm -qf /etc/redhat-release 2>&1 |"); $release = ; close (RPM_QF); } elsif (-e "/etc/SuSE-release") { open (RPM_QF, "rpm -qf /etc/SuSE-release 2>&1 |"); $release = ; close (RPM_QF); } elsif (-e "/etc/os-release") { open (RPM_QF, "rpm -qf /etc/os-release 2>&1 |"); $release = ; close (RPM_QF); } if ($test_mode) { $release = $test_release; $kver = $test_version; } if(!defined($release)) { $vers = $kver; $supported = 0; } # Testing for "oraclelinux_release", etc prevents us from dropping # into the code below from other RH based distros like CentOS, for example. elsif (($release =~ /^redhat-release/) || # straight RH ($release =~ /^enterprise-release/) || # Oracle Enterprise Linux ($release =~ /^oraclelinux-release/)) # Oracle Linux { my ($major, $minor, $patch, $subpatch1, $subpatch2) = split /\./, $kver; my ($micro_number, $patch_level) = split /-/, $patch; # e.g., 100 and 32 $vers = $kver; # We default to $kvers if ($kver =~ /debug?/) { # we do not build drivers for debug kernels. $vers = $kver; $supported = 0; } elsif ($ARCH eq "i386") { $vers = "i386"; # 32 bit kernels not supported $supported = 0; } elsif ($release =~ /AXS/) # Asianux Not supported { $vers = "ASIANUX"; $supported = 0; } elsif ($release =~ /release-4/) # RH/EL 4 Not Supported { $vers = "Linux 2.4"; $supported = 0; } elsif ($release =~ /release-5/) # RH/OEL 5 Partially Supported { if ($kver =~ /2.6.18/) { $supported = 0; $vers = "EL5"; } elsif ($kver =~ /uek/) { if ($kver =~ /2.6.32/) { $vers = "EL5"; $supported = 0; } elsif ($kver =~ /2.6.39/) { $vers = "EL5"; # we support starting with 2.6.39_400.205 since in this version # rds netfilter support was added Bug 17082619 if ((acfslib::lib_is_number($patch_level) && $patch_level == 400) && (acfslib::lib_is_number($subpatch1) && $subpatch1 >= 205)) { $supported = 0; } if (acfslib::lib_is_number($patch_level) && $patch_level > 400) { $supported = 0; } } } } elsif ($release =~ /release-6/) # RH/OEL 6 Partially Supported { if ($kver =~ /uek/) { if ($kver =~ /2.6.32/) { $vers = "EL6"; $supported = 0; } elsif ($kver =~ /2.6.39/) { $vers = "EL6"; # we support starting with 2.6.39_400.205 since in this version # rds netfilter support was added Bug 17082619 if ((acfslib::lib_is_number($patch_level) && $patch_level == 400) && (acfslib::lib_is_number($subpatch1) && $subpatch1 >= 205)) { $supported = 1; } if (acfslib::lib_is_number($patch_level) && $patch_level > 400) { $supported = 1; } } elsif ($kver =~ /4.1.12/) { $vers = "EL6"; $supported = 1; } } } # release-6 } # RH/OEL elsif ($release =~ /^sles-release/) { my ($line); my ($SPnumber); if ($test_mode) { $SPnumber = $test_patchlevel; } else { open (RELEASE, "/etc/SuSE-release"); while ($line = ) { if ($line =~ /PATCHLEVEL/) { # format: "PATCHLEVEL = 3" my ($patchlevel, $equals, $number) = split(/ /, $line); chomp ($number); $SPnumber = $number; } } close (RELEASE); } # We assume unsupported unless we specifically indicate otherwise. $vers = "$kver SP$SPnumber"; $supported = 0; if ($kver =~ /debug?/) { # we do not build drivers for debug kernels. $vers = $kver; $supported = 0; } elsif ($ARCH eq "i386") { $supported = 0; $vers = "i386"; } elsif ($release =~ /^sles-release-11/) { if (($kver =~ /2.6.32/) && ($SPnumber == 1)) { $supported = 0; $vers = "SLES11"; } elsif (($kver =~ /^3.0/) && ($SPnumber == 2)) { $supported = 0; $vers = "SLES11"; } } } else { # Not Redhat, OEL, SUSE, etc. $vers = $release; $supported = 0; } if ($supported) { # Required by okaroot - $vers MUST be a sub-directory in the install path # e.g., install/Oracle/EL5/i386/2.6.18-8/2.6.18-8.el5PAE-i686/bin # ^^^ $saved_vers = $vers; return $vers; } if (! $test_mode) { $lib_osds_get_os_type_initialized = 1; okalib::lib_error_print(620, "OKA is not supported on this operating system version: '%s'", $vers); } $saved_vers = "OKA is not supported on $vers"; return "OKA is not supported on $vers"; } # end lib_osds_get_oka_os_type # lib_osds_get_make_type # # THIS IS CALLED ONLY BY THE MAKEFILES # # Add to this routine as USM supports new Linux variants # This routine determines what platforms ACFS will build on. # This is not the same as the platforms we run on, and is # provided for the convenience of our makefiles so that they # know how to setup various variables. This was easier than # implementing this logic in the make script itself. # # Note that this is almost a copy of the lib_osds_get_os_type # function, with some vers and supported changes - as # not all supported platforms for building are supported for # running on. # sub lib_osds_get_make_type { my ($vers) = "unknown"; my ($kver) = $UNAME_R; my ($release); my ($supported) = 0; # Check to see if we support this Linux release # see - http://www.oracle.com/us/technologies/027626.pdf if (-e "/etc/oracle-release") { open (RPM_QF, "rpm -qf /etc/oracle-release 2>&1 |"); $release = ; close (RPM_QF); } elsif (-e "/etc/redhat-release") { open (RPM_QF, "rpm -qf /etc/redhat-release 2>&1 |"); $release = ; close (RPM_QF); } elsif (-e "/etc/SuSE-release") { open (RPM_QF, "rpm -qf /etc/SuSE-release 2>&1 |"); $release = ; close (RPM_QF); } # Big distributions using systemd have to use os-release file. # EL7/RHEL7 and SLES12 include this file and they can # deprecate their own release files # http://comments.gmane.org/gmane.comp.sysutils.systemd.devel/4401 # http://www.freedesktop.org/software/systemd/man/os-release.html elsif (-e "/etc/os-release") { open (RPM_QF, "rpm -qf /etc/os-release 2>&1 |"); $release = ; close (RPM_QF); } # Testing for "oraclelinux_release", etc prevents us from dropping # into the code below from other RH based distros like CentOS, for example. if ((defined($release)) && # Redhat or OEL if defined (($release =~ /^redhat-release/) || # straight RH ($release =~ /^enterprise-release/) || # Oracle Enterprise Linux ($release =~ /^oraclelinux-release/))) # Oracle Linux { my ($major, $minor, $patch, $vendor, $variation) = split /\./, $kver; my ($micro_number, $patch_level) = split /-/, $patch; # e.g., 100 and 32 if ($vendor =~ /\D/) { $vendor = 0; } if ($release =~ /AXS/) # Asianux Not supported { $vers = "ASIANUX"; $supported = 0; } elsif ($release =~ /release-4/) # RH/EL 4 Supported { # Uses the same build infrastructure as EL5. $vers = "EL5"; $supported = 0; } elsif ($release =~ /release-5/) # RH/OEL 5 Supported { # We support only 2.6.18, 2.6.32, and 2.6.39 if (($kver =~ /2.6.18/) || ($kver =~ /2.6.32/) || ($kver =~ /2.6.39/)) { if ($kver =~ /2.6.32-100/) { $vers = "EL5UEK32_100"; $supported = 0; } elsif ($kver =~ /2.6.32-200/) { $vers = "EL5UEK32_200"; $supported = 0; } elsif ($kver =~ /2.6.32-300/) { $vers = "EL5UEK32_300"; $supported = 0; } elsif ($kver =~ /2.6.32-400/) { $vers = "EL5UEK32_400"; $supported = 0; } elsif ($kver =~ /2.6.39-100/) { $vers = "EL5UEK39_100"; $supported = 0; } elsif ($kver =~ /2.6.39-200/) { $vers = "EL5UEK39_200"; $supported = 0; } elsif ($kver =~ /2.6.39-300/) { $vers = "EL5UEK39_300"; $supported = 0; } elsif ($kver =~ /2.6.39-400/) { $vers = "EL5UEK39_400"; $supported = 0; } else { my @end; my @numbers_before_first_period; # Need to check for RH5U4 or later # kver = 2.6.18-9.el5 @end=split '-', $kver; # @end = 2.6.18, 9.el5 @numbers_before_first_period=split '\.', $end[1]; # @numbers_before_first_period = 9, el5 if ($numbers_before_first_period[0] >= 164) { if ($kver =~ /xen/ ) { $vers = "EL5XEN164"; } else { $vers = "EL5164"; } } else { $vers = "EL5"; } $supported = 0; } } else { # Unsupported RH/OEL 5 kernel $vers = $kver; $supported = 0; } } elsif ($release =~ /release-6/) # RH/OEL 6 Partially Supported { # ensure 64 bit system if ($ARCH eq "x86_64") { # First, we check support for 2.6.32 and 2.6.39 if (($kver =~ /2.6.32/) || ($kver =~ /2.6.39/)) { if ( $kver =~ /uek/ ) { if ($kver =~ /39-100/) { $vers = "EL6UEK39_100"; $supported = 1; } elsif ($kver =~ /39-200/) { $vers = "EL6UEK39_200"; $supported = 1; } elsif ($kver =~ /39-300/) { $vers = "EL6UEK39_300"; $supported = 1; } elsif ($kver =~ /39-400/) { if ($vendor >= 278 && $vendor < 281) { $vers = "EL6UEK39_400_16K"; $supported = 0; } else { $vers = "EL6UEK39_400"; $supported = 1; } } } else { # This is a pretty simplistic way of looking at things. # Basically, patch levels aren't fixed, so anything # from 71 to 220 is ga build, etc. # We'll take this view for now, and if things get bad later, # beef it up. # Defaulting to latest RH kernel build (u3) for now. if ($micro_number == 32) { if ($patch_level >= 71 && $patch_level < 220) { $vers = "EL6"; $supported = 1; } elsif ($patch_level >= 220 && $patch_level < 279) { $vers = "EL6U2"; $supported = 1; } elsif ($patch_level >= 279 && $patch_level < 573) { $vers = "EL6U3"; $supported = 1; } else { $vers = "EL6U7_16K"; $supported = 1; } } } } #now check for kernel series 3.x.x elsif($kver =~ /3.8.13/) { if (($patch_level == 118) && ($vendor >= 5 && $vendor < 8)) { $vers = "EL6UEK3813_16K"; $supported = 0; } else { $vers = "EL6UEK3813"; $supported = 1; } } elsif($kver =~ /4.1.12/) { $vers = "EL6UEK4"; $supported = 1; } else { $vers = $kver; $supported = 0; } } else { # 32-bit EL6 is not supported $vers = $kver; $supported = 0; } } elsif ($release =~ /release-7/) { # ensure 64 bit system if ($ARCH eq "x86_64") { #Check for kernel series 3.x.x if($kver =~ /3.8.13/) { if (($patch_level == 118) && ($vendor >= 5 && $vendor < 8)) { $vers = "EL7UEK3813_16K"; $supported = 0; } else { $vers = "EL7UEK3813"; $supported = 1; } } elsif ($kver =~ /3.10.0/) { if (($patch =~ /0-229/) || #U1 ($patch =~ /0-327/)) #U2 { $vers = "EL7U1"; $supported = 1; } elsif ($patch =~ /0-514/) #U3 { $vers = "EL7U3"; $supported = 1; } else { $vers = "EL7"; $supported = 1; } } elsif($kver =~ /4.1.12/) { $vers = "EL7UEK4"; $supported = 1; } } else { # Any other architecture EL7 is not supported $vers = $kver; $supported = 0; } } else { # Unsupported RH/OEL release $vers = $release; $supported = 0; } } elsif (defined($release) && $release =~ /^sles-release/) { if ($release =~ /^sles-release-11/) { # ensure 64 bit system if ($ARCH eq "x86_64") { if ($kver =~ /2.6.32/) { $supported = 0; $vers = "SLES11SP1"; } elsif ($kver =~ /^3.0.13-0.27/) { $supported = 0; $vers = "SLES11SP2"; } elsif ($kver =~ /^3.0.76-0.11/) { $supported = 0; $vers = "SLES11SP3"; } elsif ($kver =~ /^3.0.101-63/) { $supported = 0; $vers = "SLES11SP4"; } else { # Don't report supported for other variants $vers = $kver; $supported = 0; } } else { # not 64 bit $supported = 0; $vers = "SLES11 ($ARCH)"; } } elsif ($release =~ /^sles-release-12/) { # ensure 64 bit system if ($ARCH eq "x86_64") { if ($kver =~ /^3.12.28/) { # SLES 12 was released with the kernel version # 3.12.28-4.6. $supported = 1; $vers = "SLES12"; } elsif ($kver =~ /^3.12.49/) { # SLES 12 SP1 was released with the kernel version # 3.12.49-11.1 $supported = 1; $vers = "SLES12SP1"; } else { # Don't report supported for other variants $vers = $kver; $supported = 0; } } else { # not 64 bit $supported = 0; $vers = "SLES12 ($ARCH)"; } } else { # non supported SUSE release $supported = 0; $vers = $release; } } else { # Not Redhat, OEL, SUSE, etc. $vers = $release; $supported = 0; } if ($supported) { # $vers MUST be a sub-directory in the install path # e.g., install/Oracle/EL5/i386/2.6.18-8/2.6.18-8.el5PAE-i686/bin # ^^^ # required by usm_root. return $vers; } acfslib::lib_error_print_noalert(9459, "ADVM/ACFS is not supported on this OS version: '%s'", $vers); return "ADVM/ACFS is not supported on $vers"; } # end get_make_type # lib_osds_get_linux_vendor # # Get the vendor string for this Linux version: # e.g. usm/install/$vendor/EL5/... # ^^^ this directory name sub lib_osds_get_linux_vendor { my ($vers); # conditional code for KA product if ($acfslib::USM_CURRENT_PROD eq "prod_oka") { $vers = lib_osds_get_oka_os_type(); } # Check if ADVM/ACFS/AFD is supported else { $vers = lib_osds_get_os_type(@_); } if ($vers =~ /^el/i) { return "Oracle"; } elsif ($vers =~ /^sles/i) { return "Novell"; } return $vers; } # lib_osds_get_usm_udev_rules_file # # get USM udev rules directory and file used by both install/uninstall # sub lib_osds_get_usm_udev_rules_file { return get_udev_common("/etc/udev/rules.d", "udev_rules", "55-usm.rules"); } # lib_osds_load_driver() # # use modprobe to load the specified driver # sub lib_osds_load_driver { my ($driver, $COMMAND) = @_; my ($result) = 0; my ($vendor) = lib_osds_get_linux_vendor(); if ($vendor eq "Novell") { # if this is a different kernel than the last that we ran on, we need # to make symlinks to the drivers in the correct lib/modules directory. $result = lib_osds_sles_mklinks(); if ($result) { return $result; } } else # RH or OEL { my ($dversion) = lib_osds_get_current_installed_version(); if ( (($COMMAND eq "acfsload") && (defined($dversion))) || (($COMMAND eq "okaload") && (defined($dversion))) || (($COMMAND eq "afdload") && (defined($dversion))) ) { # version = 2.6.18-128.el5xen (example) # release = 2.6.18 (example) # variation = 128 (example) my ($kversion) = $UNAME_R; my ($drelease, $dremainder) = split /-/, $dversion; my ($krelease, $kremainder) = split /-/, $kversion; my ($kvariation) = split /\./, $kremainder; my ($dvariation) = split /\./, $dremainder; my (@kcp) = split(/\./, $kversion); while($kcp[$#kcp] !~ /el/ && $kcp[$#kcp] !~ /uek/ && $kcp[$#kcp] !~ /smp/ && $kcp[$#kcp] !~ /xen/ && $#kcp > 3) { pop @kcp; } my ($kosvariation) = ""; if ($#kcp >= 3) { $kosvariation = $kcp[$#kcp]; } chomp($kosvariation); my (@dcp) = split(/\./, $dversion); while($dcp[$#dcp] !~ /el/ && $dcp[$#dcp] !~ /uek/ && $dcp[$#dcp] !~ /smp/ && $dcp[$#dcp] !~ /xen/ && $#dcp > 3) { pop @dcp; } my ($dosvariation) = ""; if ($#dcp >= 3) { $dosvariation = $dcp[$#dcp]; } else { # Driver for el5uek has a value of 2.6.32-100.28.8. # So, you never found the el5uek value. # If this is the case, we hard coded the value just for # this case if ($dversion eq "2.6.32-100.28.8") { $dosvariation = "el5uek"; } } chomp($dosvariation); # We add a validation for checking if the # O.S. is the same comparing el5, el5xen, el5uek # It should be the same for kernel and driver # Some examples: # Upgrading the OS from ol5 to el6, and you have installed # el5 drivers # ol5 driver: 2.6.39-400.3.0.el5uek # ol6 kernel: 2.6.39-400.17.1.el6uek.x86_64 # $drelease(2.6.39) eq to $krelease(2.6.39) but # $dosvariation(el5uek) ne to $kosvariation(el6uek) # # Same OS changing kernel: # ol5 Driver: 2.6.18-164.0.0.0.1.el5 # ol5 Kernel: 2.6.18-308.4.1.0.1.el5xen # $drelease(2.6.18) eq to $krelease(2.6.18) but # $dosvariation(el5) ne to $kosvariation(el5xen) # # Upgrading the kernel version # ol6 Driver: 2.6.39-300.21.1.el6uek.x86_64 # ol6 Kernel: 2.6.39-400.17.1.el6uek.x86_64 # $drelease(2.6.39) eq to $krelease(2.6.39) and # $dosvariation(el6uek) eq to $kosvariation(el6uek) # In this case, both statements are false and the else # condition will do the validation, # $kversion =~ /uek/ but # $dvariation(300) ne $kvariation(400) if (($drelease ne $krelease) || ($dosvariation ne $kosvariation)) { if ($COMMAND eq "acfsload") { # the kernel and the drivers are not both 2.6.18, for example. acfslib::lib_inform_print(9226, "ADVM/ACFS drivers not correct for this OS - cannot load."); acfslib::lib_inform_print(9399, "Calling 'acfsroot install' to install compatible ADVM/ACFS drivers."); system("$ENV{ORACLE_HOME}/bin/acfsroot install"); exit $?; } elsif($COMMAND eq "afdload") { # the kernel and the drivers are not both 2.6.18, for example. acfslib::lib_inform_print(9226, "AFD drivers not correct for this OS - cannot load."); acfslib::lib_inform_print(9399, "Calling 'afdroot install' to install compatible AFD drivers."); system("$ENV{ORACLE_HOME}/bin/afdroot install"); exit $?; } else { # the kernel and the drivers are not both 2.6.18, for example. acfslib::lib_inform_print(9226, "OKA drivers not correct for this OS - cannot load."); acfslib::lib_inform_print(9399, "Calling 'okaroot install' to install compatible OKA drivers."); system("$ENV{ORACLE_HOME}/bin/okaroot install"); exit $?; } } # Release could be 2.6.18, 2.6.32, 2.6.39, 3.8.13 or 3.10.0. # dvariation should be equal to kvariation for uek in # releases 2.6.32 and 2.6.39. # And $dvariation >= $kvariation for RHEL and 3.x Releases elsif ((($kversion =~ /uek/) && ($kversion =~ /^2\./) && ($dvariation ne $kvariation)) || ($dvariation > $kvariation)) { #If $drelease is equal to 2.6.32, We have two options uek or el6 kernel #If it's a uek kernel $dvariation has to be equal to $kvariation # Both drivers and kernel are 2.6.32 but one is 2.6.32-100 and the # other is 2.6.32-200, for example. #If it's a el6 kernel $dvariation has to be less or equal to $kvariation # This will need work if we have something like 200 and 238 that # are compatible. if ($COMMAND eq "acfsload") { acfslib::lib_inform_print(9226, "ADVM/ACFS drivers not correct for this OS - cannot load."); acfslib::lib_inform_print(9399, "Calling 'acfsroot install' to install compatible ADVM/ACFS drivers."); system("$ENV{ORACLE_HOME}/bin/acfsroot install"); exit $?; } elsif ($COMMAND eq "afdload") { # the kernel and the drivers are not both 2.6.18, for example. acfslib::lib_inform_print(9226, "AFD drivers not correct for this OS - cannot load."); acfslib::lib_inform_print(9399, "Calling 'afdroot install' to install compatible AFD drivers."); system("$ENV{ORACLE_HOME}/bin/afdroot install"); exit $?; } else { # the kernel and the drivers are not both 2.6.18, for example. acfslib::lib_inform_print(9226, "OKA drivers not correct for this OS - cannot load."); acfslib::lib_inform_print(9399, "Calling 'okaroot install' to install compatible OKA drivers."); system("$ENV{ORACLE_HOME}/bin/okaroot install"); exit $?; } } else { # DEBUG # print "continue to load using the existing installation\n"; } } } # strip ".ko" from driver name my ($driver_less_ko) = $driver; $driver_less_ko =~ s/.ko//; $result = system("modprobe $driver_less_ko"); if ($result) { return osds_unix_linux_acfslib::USM_FAIL; } if ($driver_less_ko eq 'oracleacfs') { my $result = 0; my $return_code = 0; my $storage_mode = acfslib::getParam("ASM_CONFIG"); if ($storage_mode ne '') { if ($storage_mode eq 'near') { $storage_mode = 0; } else { $storage_mode = 1; } # Set the ACFS Remote storage mode tunable (AcfsRemoteStorageMode). $result = system("$acfslib::ACFSUTIL tune " . "AcfsRemoteStorageMode=$storage_mode " . "1>/dev/null"); # Only hide 'success' if($result != 0) { acfslib::lib_error_print(3099, "error updating driver tunables"); return osds_unix_linux_acfslib::USM_FAIL; } } } return osds_unix_linux_acfslib::USM_SUCCESS; } # end lib_osds_load_driver # lib_osds_remove_exports # # Called before unmounting a file system to remove any NFS exports. # Returns a list of removed exports. The list is triply subscripted, the # first being the mountpoint, the second the client, the third, options. # If the unmount fails, the removed exports are restored from this list. # # Note that an exportfs output entry may be more than one line # # Note that you can have the following exports # /test # /test/123 # /test123 # If the mountpoint to be unexported is "/test", we remove # "/test" and "/test/123", but not "/test123". # sub lib_osds_remove_exports { my ($mountpoint) = @_; # mount point to remove export. my ($mountpoint_slash); # mount point, "/" terminated my ($line); # a line of output from "exportfs". my ($exportfs_mountpoint); # mountpoint from exportfs output. my ($exportfs_client); # client from exportfs output. my ($exportfs_options); # options from exportfs output. my (@export_list); # returned list of items we unexported. my ($index) = 0; # index into the export_list. open EXPORT, "$EXPORTFS -v |" or warn ("failed to read exportfs list: $!"), return @export_list; while ($line = ) { # replace tabs with spaces, lose the $line =~ s/\t/ /g; chomp($line); # an exportfs entry may be more than one line if ($line =~ /^\//) { my (@array) = split /\s+/, $line; my ($last_element) = $#array; if ($last_element == 0) { # There is more than one line for the entry. # This is the first line and has only the mountpoint. $exportfs_mountpoint = $line; next; } # The line contains both mount point and client. chomp ($array[0]); chomp ($array[1]); $exportfs_mountpoint = $array[0]; $exportfs_client = $array[1]; } else { # this is the second part of the entry - the line has only the client $line =~ s/ //g; $exportfs_client = $line; } # This is so we can differentiate between # "/test", "/test/123", and "/test123". $mountpoint_slash = $mountpoint . "/"; if (($exportfs_mountpoint eq $mountpoint) || ($exportfs_mountpoint =~ $mountpoint_slash)) { # We have a match! Unexport the entry and record it in export_list. # Separate the options from $exportfs_client. # Format: .(ro,wdelay,....,anongid=65534) my (@array) = split /\(/,$exportfs_client; $exportfs_client = $array[0]; $exportfs_options = $array[1]; $exportfs_options =~ s/\)//; # exportfs prints "" if the /etc/exports client field is "*". if ($exportfs_client =~ "^") { $exportfs_client =~ s//\\*/; } $export_list[$index][0] = $exportfs_mountpoint; $export_list[$index][1] = $exportfs_client; $export_list[$index][2] = $exportfs_options; $index++; system("$EXPORTFS -u $exportfs_client:$exportfs_mountpoint"); } } close (EXPORT); return @export_list; } # end lib_osds_remove_exports # lib_osds_restore_exports # # This is called if an unmount fails. # If we removed any exports, before the failed unmount, restore them here. # sub lib_osds_restore_exports { my (@export_list) = @_; my ($index) = 0; while(defined($export_list[$index])) { my ($exportfs_mountpoint) = $export_list[$index][0]; my ($exportfs_client) = $export_list[$index][1]; my ($exportfs_options) = $export_list[$index++][2]; system( "$EXPORTFS -o $exportfs_options $exportfs_client:$exportfs_mountpoint"); } } #end lib_osds_restore_exports # lib_osds_unload_driver() # # use modprobe to unload the specified driver # sub lib_osds_unload_driver { my ($driver) = @_; # strip ".ko" from driver name my ($driver_less_ko) = $driver; $driver_less_ko =~ s/.ko//; my @lsmod_result = ""; my $result = 0; # # In the (very rare) case where we are running the LRGs with the ODA # SHIM capabilities enabled, we need to shutdown the SHMU portion by # hand. To that end we will attempt to invoke the 'shim_unload' option # to advmutil. Note: if (a) advmutil does not "understand" 'shim_unload' # or (b) the SHIM stuff is not being used, then this command will fail # silently. If, on the other hand, we are indeed using the ADVM SHIM # stuff and this command fails, well then the driver unload will fail # and eventually the LRG will be killed... C'est la vie... # if ($driver_less_ko eq "oracleadvm") { system("advmutil shml_shutdown 1>/dev/null 2>/dev/null"); } # If module is not listed try to unload the next one if (! system("lsmod | grep $driver_less_ko > /dev/null 2>&1")) { $result = system("modprobe -r $driver_less_ko"); if ($result != 0) { # Command modprobe could not unload the driver. # We will try with rmmod $result = system("rmmod $driver_less_ko"); } } # remove driver from the cache if ($result == 0) { $CACHED_LOADED_DRIVERS =~ s/$driver_less_ko//g; } return $result; } # end lib_osds_unload_driver # lib_osds_sles_mklinks # # acfsroot for Suse placed the drivers in the /lib/modules directory for # which the driver was created - e.g., /lib/modules/2.6.16.60-0.54.5-smp # If that's what the user is running, all is good. For other kernels, we need # the drivers under /lib/modules/`uname -r` - in effect, /sbin/weak-modules, # which does not exist in SuSe. We'd like to do this in acfsroot but # there's a problem if the user upgrades the kernel and does not re-install # USM. The subsequent acfsload would fail because modprobe would not find # the drivers. This routine is called from the driver load routine and checks # to see if there are proper links under /lib/modules/`uname -r`, if required, # and creates them if not. # sub lib_osds_sles_mklinks { my ($src_dir); my ($dst_dir) = "/lib/modules/$UNAME_R/extra/usm"; my ($component); my ($return_val) = 0; my ($checkdriver) = "$dst_dir/$DRIVER_COMPONENTS[0]"; my ($findmodule) = "oracleoks"; if ($acfslib::USM_CURRENT_PROD eq "prod_afd") { $dst_dir = "/lib/modules/$UNAME_R/extra/oracle"; $checkdriver = "$dst_dir/oracleafd.ko"; $findmodule = "oracleafd"; } if (! -d $dst_dir) { # create the destination directory if needed. `mkdir -p $dst_dir`; if ($?) { acfslib::lib_error_print(9345, "Unable to create directory: '%s'.", $dst_dir); return 1; } } else { # check to name sure that a driver is there # (assume that the rest will be there too. if (-e "$checkdriver") { # This is the typical case and we leave without having serious work to do. return 0; } } # The USM driver that is *not* a symlink is our source base. This is where # "acfsroot install" placed the drivers. my ($file); my ($basedir); open FIND, "find /lib/modules | grep $findmodule |"; while ($file = ) { chomp($file); if (! -l $file ) { # file is not a symlink my (undef, $lib, $modules, $version) = split /\//, $file; $basedir = $version; last; } } close (FIND); if (!defined($basedir)) { # "can not happen" since we checked for an existing install # well before we got here. acfslib::lib_error_print(9344, "Missing directory: '%s'.", ""); return 1; } # Now create the symlinks. $src_dir = "/lib/modules/$basedir/extra/usm";; if ($acfslib::USM_CURRENT_PROD eq "prod_afd") { $src_dir = "/lib/modules/$basedir/extra/oracle";; } # src_dir is where the acfsroot/afdroot placed the drivers. if ($src_dir ne $dst_dir) { if ($acfslib::USM_CURRENT_PROD eq "prod_afd") { $component = "oracleafd.ko"; `ln -sf "$src_dir/$component" "$dst_dir/$component"`; if ($?) { $return_val = 1; acfslib::lib_error_print (9350, "Failed to create a symbolic link from '%s' to '%s'.", "$src_dir/$component", "$dst_dir/$component"); } } else { foreach $component (@DRIVER_COMPONENTS) { `ln -sf "$src_dir/$component" "$dst_dir/$component"`; if ($?) { $return_val = 1; acfslib::lib_error_print (9350, "Failed to create a symbolic link from '%s' to '%s'.", "$src_dir/$component", "$dst_dir/$component"); } } } if ($return_val == 1) { return 1; } # Run depmod so that modprobe(8) can find the drivers. my ($cmd) = "/bin/bash -c \"/sbin/depmod $UNAME_R 2>&1\"|"; my ($print_header) = 1; open (MOD, $cmd); while () { if ($_ =~ /^WARNING:/ || $_ =~ /KsSetThreadPriority*.*$DRIVER_COMPONENTS[1]$/ || $_ =~ /KsRwLockReadTry*.*$DRIVER_COMPONENTS[1]$/ || $_ =~ /KsGetLogSize*.*$DRIVER_COMPONENTS[1]$/ || $_ =~ /acfs*.*$DRIVER_COMPONENTS[1]$/ || $_ =~ /advm*.*$DRIVER_COMPONENTS[1]$/ || $_ =~ /oks*.*$DRIVER_COMPONENTS[1]$/ || $_ =~ /afd*.*$findmodule$/ ) { next; } if ($print_header) { acfslib::lib_print_cmd_header($cmd); $print_header = 0; } acfslib::lib_inform_print (9999, "$_"); } close (MOD); } return 0; } # end lib_osds_sles_mklinks # lib_osds_is_mounted # # check to see if the specified mount point is active # sub lib_osds_is_mounted { my ($mount_point) = @_; # mount point to test my ($mounted) = 0; # assume not mounted my ($line); # Remove trailing slash, if any, so that grep will work. $mount_point =~ s/\/$//; # Bug 9589426 - ACFS DBHOME resource fails to start in Linux # Print an error if relative pathname is provided for a mountpoint # to reflect review comments instead of making it work. my $slash = '/'; my $idx = index($mount_point, $slash); if ( ! acfslib::lib_is_abs_path ( $mount_point ) ) { acfslib::lib_error_print(9366, "Relative path for mount point '%s' is not supported.", $mount_point); return $mounted; } # Use /proc/mounts on Linux. /etc/mtab can be stale (see man page). open (CHK_MOUNT, "grep \" $mount_point \" /proc/mounts |"); while ($line = ) { # Format hint where mount_point = "/mymount": # /dev/asm/crsdg1vol1-23 /mymount acfs rw,device,rootsuid 0 0 $mounted = 1 if ( $line =~ /^[\S]+ +$mount_point +/ ); last; } close (CHK_MOUNT); return $mounted; } # end lib_osds_is_mounted # lib_osds_get_current_installed_version # # Get the currently installed kernel build and USM driver versions # sub lib_osds_get_current_installed_version { my ($line); my ($driver); my (@array); my ($driver_version); # USM driver version (label date) my ($kernel_version); my ($release_version); # conditional code for RAC KA product if ($acfslib::USM_CURRENT_PROD eq "prod_oka") { open(DRIVER, "find /lib/modules/ | grep oracka |"); } elsif ($acfslib::USM_CURRENT_PROD eq "prod_afd") { open(DRIVER, "find /lib/modules/ | grep oracleafd |"); } else { open(DRIVER, "find /lib/modules/ | grep oks |"); } $driver = ; close(DRIVER); open (STRINGS, "strings $driver |"); while ($line = ) { if ($line =~ /vermagic/) { $kernel_version = $line; } # The usm_label_info[] global contains: # usm_ade_label_info_make_header.pl: USM BUILD LABEL: USM_MAIN_LINUX.X64_100506 if ($line =~ /USM BUILD LABEL: (\S+)/) { $driver_version = $1; } # got all of our info? if (defined($driver_version) && (defined($kernel_version))) { last; } } close(STRINGS); # Return an undefined variable if we don't have all of our info. # That signals failure to the caller. if (!defined($driver_version)) { return $driver_version; } if (!defined($kernel_version)) { return $kernel_version; } # vermagic=2.6.18-8.el5 SMP mod_unload 686 REGPARM 4KSTACKS gcc-4.1 @array = split(/ /, $kernel_version); $kernel_version = $array[0]; $kernel_version =~ s/vermagic=//; # vermagic=2.6.18-8.el5 SMP mod_unload 686 REGPARM 4KSTACKS gcc-4.1 @array = split(/ /, $kernel_version); $kernel_version = $array[0]; $kernel_version =~ s/vermagic=//; # We don't want to export to the user the label info so we strip # that from the driver_version, leaving only the date. # so, USM_MAIN_LINUX_090112 becomes 090112. @array = split (/_/, $driver_version); $driver_version = $array[3]; # Returning release version $release_version = $array[1]; # Check if the label is patched if ($release_version =~ /^((\d+\.){3}\d+)(\.\d*(.*))$/) { # It is, strip the patch number # 11.2.0.4.0ACFSPSU becomes 11.2.0.4 (ACFSPSU) # untouched otherwise $release_version = "$1 ($4)."; } return ($kernel_version, $driver_version, $release_version); } # end lib_osds_get_current_installed_version # lib_osds_validate_asmadmin_group # # Make sure that the $asmadmin group name actually exists. # sub lib_osds_validate_asmadmin_group { my ($asmadmin) = @_; my ($retcode) = osds_unix_linux_acfslib::USM_SUCCESS; my ($cmd) = "/usr/bin/getent group $asmadmin"; my ($val); acfslib::lib_trace(9176, "Entering '%s'", "va admin group"); $val = system("$cmd > /dev/null"); if ($val) { # Despite the minimal Linux getent(1) man page, the exit codes are # identical to Solaris. acfslib::lib_trace(9179, "Command executed: '%s', output = '%s'", $cmd, (($val & 0xff00) >> 8)); $retcode = osds_unix_linux_acfslib::USM_FAIL; } acfslib::lib_trace(9178, "Return code = %s", $retcode); acfslib::lib_trace(9177, "Return from '%s'", "va admin group"); return $retcode; } #end lib_osds_validate_asmadmin_group ####### internal only functions ######### # get_udev_common # # common code for get_usm_RH5_udev_rules_file() and # get_usm_RH5_udev_permissions_file() sub get_udev_common { my ($default_dir, $config_param, $file_name) = @_; my ($line); # line from the udev.conf file # We get the rules directory from the udev.conf file # and then append the file name. my ($udev_perm_dir) = $default_dir; # default directory name # open file for read open (CONF, ") { my ($line_org) = $line; # strip off the parameter name, if it exists, leaving only the set value $line =~ s/^$config_param=//; # did we find the right line in the file? # we know it's the right line if the substitution worked. if ($line ne $line_org) { # remove the double quotes $line =~ s/"//g; # remove the carriage return chomp($line); $udev_perm_dir = $line; last; } } close CONF; # avoid "//" - just to make it pretty as it works fine as is $udev_perm_dir =~ s/\/$//; return ($udev_perm_dir . "/" . $file_name); } # end get_udev_common # lib_osds_is_local_container # LXC: Linux Container # Check if this is a LXC environment # i.e. /proc/1/cgroup # ::/// # sub lib_osds_is_local_container { # Assume is not a LXC environment my $lxccontainerflag = osds_unix_linux_acfslib::USM_SUPPORTED; if (defined($ENV{'LXC_FRM_TST'})) { # Simulating a LXC environment, where ACFS/ADVM is not supported $lxccontainerflag = osds_unix_linux_acfslib::USM_NOT_SUPPORTED; } else { if (-e "$CGROUP") { chomp(my @container = `cat $CGROUP`); # Control group info foreach my $cgroupvector (@container) { if ($cgroupvector =~ /lxc/) { # Inside a LXC environment, where ACFS/ADVM is not supported $lxccontainerflag = osds_unix_linux_acfslib::USM_NOT_SUPPORTED; last; } } } } return $lxccontainerflag; }# end lib_osds_is_local_container # This function will modify the values of the acfslib::acfsr hash. # The first value is 'True' when ACFS Remote is supported, 'False' otherwise. # In order to determine if it is supported we # - Retrieve the passed argument. It will either be "DOMAINSERVICES" # or "MEMBER". # - Depending on cluster class, determine if the current OS is supported. # If it is supported, other values will be pushed into the array # Is ISCSI supported? 'True' or 'False'. sub lib_osds_acfs_remote_supported { my $cluster_class = shift; if($cluster_class eq 'MEMBER') { $acfslib::acfsr{'ACFS Remote'} = 'True'; } elsif($cluster_class eq 'DOMAINSERVICES') { my $kernel_name = `uname -s`; my $kernel_release = $UNAME_R; chomp($kernel_name); if($kernel_name eq 'Linux' && $kernel_release =~ /^3\.8.*el7uek.*/) { $acfslib::acfsr{'ACFS Remote'} = 'True'; } } # Check ISCSI support # Allan said this is always supported. $acfslib::acfsr{'iSCSI'} = 'True'; =head2 For now, don't check this # Check if this is an ODA if(acfslib::isODA()) { # Xen Blkfrnt/blkback support $acfslib::acfsr{'xen blkfrnt/blkback'} = 'True'; } =cut } # This function will modify the values of the acfslib::acfsr hash. # The first value is 'True' when ACFS Remote is installed, 'False' otherwise. # In order to determine if it is installed we need to look for # /etc/modprobe.d/oracleadvm.conf (Linux location, this may vary in other OS) # If found, read it and look for asm_acfsr_mode option # As of 2/3/16 modes are: # DOMAINSERVICES = 1 # MEMBER = 2 # SHMI = 3 (ADE-only) # The list can be found in acfsroot.pl. # Perhaps I should move that list somewhere else? # Any of those modes mean 'installed'. Any other value (or a lack of one) # means not installed. # If it is supported, other values will be pushed into the array # Is ISCSI setup? 'True' or 'False'. sub lib_osds_acfs_remote_installed { my $cluster_class = shift; my $mode = '0'; my $conf_location = "/etc/modprobe.d/oracleadvm.conf"; my $fh; my $line; if(-f $conf_location) { open ($fh,"<$conf_location") or die "$!"; while($line = <$fh>) { if($line =~ /asm_acfsr_mode=(\d)/) { $mode = $1; } } close $fh; } if($cluster_class eq 'MEMBER' && $mode eq '2') { $acfslib::acfsr{'ACFS Remote'} = 'True'; } elsif($cluster_class eq 'DOMAINSERVICES' && $mode eq '1') { $acfslib::acfsr{'ACFS Remote'} = 'True'; } # Determine is iscsi is installed. my $iscsi_inst = `/sbin/service iscsid status`; # Could be running or stopped, so check if it's not there. # This check might break if we run in a shell in another language if($iscsi_inst =~ /unrecognized service/) { $acfslib::acfsr{'iSCSI'} = 'False'; } else { $acfslib::acfsr{'iSCSI'} = 'True'; } =head2 # We would check for xen blkfrnt/blkback support via isODA. # For now, we aren't going to check/show that. if(acfslib::isODA()) { # Xen Blkfrnt/blkback support $acfslib::acfsr{''} = 'True'; } else { $acfslib::acfsr{''} = 'True'; } =cut } # This function will modify the values of the acfslib::acfsr hash. # The first value is 'True' when ACFS Remote is loaded, 'False' otherwise. # Is ISCSI setup and running? 'True' or 'False'. sub lib_osds_acfs_remote_loaded { my $cluster_class = shift; my $mode = 0; my $conf_location = "/etc/modprobe.d/oracleadvm.conf"; my $fh; my $line; if(-e $conf_location) { open ($fh,"<$conf_location") or die "$!"; while($line = <$fh>) { if($line =~ /asm_acfsr_mode=(\d)/) { $mode = $1; } } close $fh; } if($cluster_class eq 'MEMBER' && $mode eq 2) { $acfslib::acfsr{'ACFS Remote'} = 'True'; } elsif($cluster_class eq 'DOMAINSERVICES' && $mode eq 1) { $acfslib::acfsr{'ACFS Remote'} = 'True'; } else { $acfslib::acfsr{'ACFS Remote'} = 'False'; } # Determine is iscsi is installed. my $iscsi_inst = `/sbin/service iscsid status`; # This check might break if we run in a shell in another language if($iscsi_inst =~ /running/) { $acfslib::acfsr{'iSCSI'} = 'True'; } else { $acfslib::acfsr{'iSCSI'} = 'False'; } =head For now, don't check this. if(acfslib::isODA()) { # Xen Blkfrnt/blkback support $acfslib::acfsr{''} = 'True'; } else { $acfslib::acfsr{''} = 'True'; } =cut }