MINI MINI MANI MO
#
#
# olfsroot.pl
#
# Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
#
# NAME
# olfsroot.pl - <one-line expansion of the name>
#
# DESCRIPTION
# <short description of component this file declares/defines>
#
# NOTES
# <other useful comments, qualifications, etc.>
#
#
my ($KVER);
my ($ARCH) = `uname -i`; # Machine architecture - i386
chomp($ARCH);
my ($UNAME_R) = `uname -r`;
chomp($UNAME_R);
our ($ORACLE_HOME) = $ENV{ORACLE_HOME};
my ($SHIPHOME_BASE_DIR) = "$ORACLE_HOME/usm/install";
our ($OLFS_DFLT_CMD_LOC) = "$SHIPHOME_BASE_DIR/cmds/bin";
our ($OLFS_DFLT_DRV_LOC);
my ($SBIN_DIR) = "/sbin";
my ($DRIVER_DIR);
my ($COMMAND) = "No Command Specified";
my ($OLFS_PATCH_PREFIX) = ".olfs_patch_";
my ($OLFS_PATCH_PREFIX_LEN) = length($OLFS_PATCH_PREFIX);
my ($OLFS_HIDE_PREFIX) = ".olfs_hide_";
use constant USM_SUCCESS => 0;
use constant USM_FAIL => 1;
use strict;
use Getopt::Std;
use Cwd 'abs_path';
use File::Basename;
use English;
use Config;
use File::Path;
main();
sub get_olfs_driver_dir
{
my ($driver_build_version); # version that the driver was linked for.
$driver_build_version = $UNAME_R;
return "/lib/modules/$driver_build_version/extra/oracle";
}
sub olfsroot_exit
{
my ($ret) = @_;
exit $ret;
}
sub main
{
my ($sub_command); # start or stop
my ($return_code); # as the name implies
# user options
my (%opt); # user options hash - used by getopts()
# -h : help
# user flags. See description above or usage message output
my (%flags) = ( load => 'h',
unload => 'h',
repltree => 'h',
beginphase => 'h',
endphase => 'h',
delpatchfiles => 'h',
);
# process the command line for acfsutil cmdlog
# We could just use "acfsutil cmdlog -s @ARGV"
# but that wouldn't give us the absolute command path name;
my ($opt, $opts);
$opts = "";
foreach $opt (@ARGV)
{
$opts = abs_path($0) if $opts eq ""; # command name
$opts .= " $opt";
}
# supplied by the front end driver and 'guaranteed' to be there.
# command is what the user actually typed in (sans directories).
$COMMAND = shift(@ARGV);
# supplied by user
$sub_command = shift(@ARGV);
print "sub command is $sub_command\n";
# must be supplied by the user.
if (defined($sub_command))
{
if (!(($sub_command eq 'load') ||
($sub_command eq 'unload') ||
($sub_command eq 'repltree') ||
($sub_command eq 'beginphase') ||
($sub_command eq 'endphase') ||
($sub_command eq 'delpatchfiles')))
{
# illegal sub-command
print "invalid command\n";
usage("invalid", 0);
olfsroot_exit(USM_FAIL);
}
}
else
{
# no sub-command
print "No sub command found\n";
usage("invalid", 0);
olfsroot_exit(USM_FAIL);
}
# parse user options
%opt=();
getopts($flags{$sub_command}, \%opt) or usage($sub_command, 1);
if ($opt{'h'})
{
# print help information
usage($sub_command, 0);
olfsroot_exit(USM_SUCCESS);
}
##### command parsing complete #####
if ($sub_command eq 'load')
{
$return_code = load();
}
else
{
if ($sub_command eq 'unload')
{
$return_code = unload();
}
else
{
if ($sub_command eq 'repltree')
{
my ($src, $dest);
$src = shift(@ARGV);
$dest = shift(@ARGV);
repltree($src, $dest);
$return_code = USM_SUCCESS;
}
else
{
if (($sub_command eq 'beginphase') || ($sub_command eq 'endphase'))
{
my ($oh, $cmd);
$oh = shift(@ARGV);
if ($sub_command eq 'beginphase')
{
$cmd = $ORACLE_HOME . "/bin/olfsctl phase $oh 1";
}
else
{
$cmd = $ORACLE_HOME . "/bin/olfsctl phase $oh 0";
}
if (system($cmd) == 0)
{
$return_code = USM_SUCCESS;
}
else
{
$return_code = USM_FAIL;
}
}
else
{
if ($sub_command eq 'delpatchfiles')
{
my ($agi_path);
$agi_path = shift(@ARGV);
delete_patch_files($agi_path);
$return_code = USM_SUCCESS;
}
}
}
}
}
olfsroot_exit($return_code);
} # end main
sub load()
{
my $command;
my $ret;
my $return_code = USM_SUCCESS;
$DRIVER_DIR = get_olfs_driver_dir();
$command = "/sbin/insmod $DRIVER_DIR/oracleolfs.ko";
$ret = system ($command);
$return_code = USM_FAIL if $ret;
return ($return_code);
}
sub unload()
{
my $command;
my $ret;
my $return_code = USM_SUCCESS;
$command = "/sbin/rmmod oracleolfs.ko";
$ret = system ($command);
$return_code = USM_FAIL if $ret;
return ($return_code);
}
sub repltree {
my $mysrc = $_[0];
die "Incorrect source directory path ($mysrc) provided"
unless -d $mysrc;
my $mydest = $_[1];
if (-d $mydest)
{
create_dir($mysrc, $mydest, 1);
}
else
{
if (-f $mydest)
{
die "Destination ($mydest) not a directory\n"
}
else
{
create_dir($mysrc, $mydest, 0);
}
}
}
# In addition to deleting the patch hidden files and corresponding generated
# files, libasmclntsh18.so also needs to be deleted from AGI, as it contains
# the patching information, but is not re-generated during clone phase. So,
# there is no hidden patch file for it and the corresponding file in AGI does
# not get deleted automatically. Due to this, the patched file in AUI remains
# hidden by the corresponding AGI file. Hence, it must deleted manually.
#
# The object file containing the patch information is 'skgfpmi.o', which is
# archived into 'libasmclntsh18.a'. So, this archive file also needs to deleted
# because it does NOT get re-generated during the clone phase.
#
# Bug-26441818: comps.xml file contains the patch information, which is read by
# Opatch to list the patches installed in the home. During initial provisioning,
# it is promoted to AGI outside of the clone operation.
#
# So, when patching is done on an OLFS-based home for the first time, it is not
# updated during the clone phase and AGI still contains the older comps.xml
# file. As clone does not update this, so we do not create a hidden patch file
# for it.
#
# Before clone is run on patched home, RHP needs to run 'delpatchfiles' command
# to delete the files from AGI created during previous clone run, so that the
# home picks up new files from patched AUI. Since, comps.xml does not have a
# corresponding hidden file, it does not get deleted by 'delpatchfiles' command.
# Hence, even though the software running on a patched OLFS home contains the
# patches, but when queried upon, it does not list them.
#
# When patch rollback is executed on a patched OLFS home, Opatch tries to list
# the patches installed on the home, but it does not list any patches as
# comps.xml file is old. So, the command fails saying that there is nothing to
# rollback.
#
# Also, applying a patch over the already patched OLFS home would also fail as
# this also checks for existence of already installed patch.
#
# So, this file has to be deleted manually from AGI as a part of 'delpatchfiles'
# command before execution of clone. This ensures that when Opatch queries to
# list the patches, it uses the latest comps.xml file from patched AUI.
#
# Also, applying a patch over the already patched LPM home would fail as this
# too checks for existence of already installed patch.
sub delete_patch_files {
my $ag_path = $_[0];
del_patch_files($ag_path);
my $file = $ag_path . "/lib/libasmclntsh18.so";
unlink $file;
$file = $ag_path . "/lib/libasmclntsh18.a";
unlink $file;
$file = $ag_path . "/inventory/ContentsXML/comps.xml";
unlink $file;
}
# This function deletes the files and their corresponding hidden files created
# during the clone phase.
sub del_patch_files {
my $agi_dir = $_[0];
opendir(my $DIR, $agi_dir);
while (my $dirent = readdir $DIR) {
next if $dirent eq '.' or $dirent eq '..';
my $agi_path = $agi_dir . '/' . $dirent;
if (-f $agi_path)
{
if (index($dirent, $OLFS_PATCH_PREFIX) != -1)
{
my $fname = substr($dirent, $OLFS_PATCH_PREFIX_LEN);
my $fpath = $agi_dir . '/' . $fname;
my $hidden_fpath = $agi_dir . '/' . $OLFS_HIDE_PREFIX . $fname;
#print "File path to delete is: $fpath\n";
#print "Hidden File path to delete is: $agi_path\n";
#print "Hidden File path to delete is: $hidden_fpath\n";
unlink $fpath;
unlink $agi_path;
unlink $hidden_fpath;
}
}
elsif (-d $agi_path)
{
my $agi_path = $agi_dir . '/' . $dirent;
del_patch_files($agi_path);
}
}
closedir $DIR;
}
sub create_dir {
my $src = $_[0];
my $dest = $_[1];
my $call_num = $_[2];
if ($call_num == 0)
{
mkdir $dest;
#print "Creating new directory $dest\n";
}
opendir(my $DIR, $src);
while (my $dirent = readdir $DIR) {
next if $dirent eq '.' or $dirent eq '..';
my $new_src = $src . '/' . $dirent;
my $new_dest = $dest . '/' . $dirent;
next unless -d $new_src;
if (-l $new_src)
{
#print "Symlink found $new_src and dest is $new_dest\n";
my $new_link = readlink($new_src);
#print "Symlink path $new_link\n";
symlink($new_link, $new_dest);
}
elsif (-d $new_dest)
{
create_dir($new_src, $new_dest, 1);
}
else
{
if (-f $new_dest)
{
die "Destination ($new_dest) not a directory\n"
}
create_dir($new_src, $new_dest, 0);
}
}
closedir $DIR;
}
sub usage
{
my ($sub_command, $abort) = @_;
if ($sub_command eq "load")
{
print "olfscmd load: Load OLFS kernel driver.\n";
print "Usage: olfscmd load\n";
}
if ($sub_command eq "unload")
{
print "olfscmd load: Unload OLFS kernel driver.\n";
print "Usage: olfscmd unload\n";
}
if ($sub_command eq "repltree")
{
print "olfscmd repltree: replicate directory structure from src to dest\n";
print "Usage: olfscmd repltree <srcdir> <destdir>\n";
}
if ($sub_command eq "beginphase")
{
print "olfscmd beginphase: start the object regeneration phase\n";
print "Usage: olfscmd beginphase <ohpath>";
}
if ($sub_command eq "endphase")
{
print "olfscmd endphase: end the object regeneration phase\n";
print "Usage: olfscmd endphase <ohpath>";
}
if ($sub_command eq "delpatchfiles")
{
print "olfscmd delpatchfiles: delete hidden patch files created during object regeneration phase\n";
print "Usage: olfscmd delpatchfiles <agpath>";
}
if ($sub_command eq "invalid")
{
print "olfscmd: Invalid command.\n";
print "Usage: olfscmd {load | unload | repltree <srcdir> <destdir>} [-h]\n";
}
if ($abort)
{
olfsroot_exit(USM_FAIL);
}
}
OHA YOOOO