#!/usr/bin/perl
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
#  
#  
# Licensed Materials - Property of IBM 
#  
# (C) COPYRIGHT International Business Machines Corp. 2002,2007 
# All Rights Reserved 
#  
# US Government Users Restricted Rights - Use, duplication or 
# disclosure restricted by GSA ADP Schedule Contract with IBM Corp. 
#  
# IBM_PROLOG_END_TAG 
$::DEBUG = 1;
#####################################################################
#                                                                   #
# Command: csmprereboot                                             #
#                                                                   #
#-------------------------------------------------------------------#
#                                                                   #
# Description: This command is executed just before the first       #
#              reboot of a node after the operating system has been #
#              installed. It is called from the osprereboot script. #
#                                                                   #
#                                                                   #
# Command Syntax:  csmprereboot -m install_server                   #
#                               -p directory to mount               #
#                               -n node_hostname                    #
#                                                                   #
#                                                                   #
# Exit codes:                                                       #
#     0 - All was successful.                                       #
#     1 - An error occured.                                         #
#                                                                   #
#                                                                   #
#####################################################################
# @(#)41   1.46.1.3   src/csm/install/csmprereboot.perl, setup, csm_rfish, rfishs001b 12/30/05 20:54:43

use strict;

BEGIN
{
	use File::Basename;    # - this gives us the path of the command
	($::Bin) = dirname($0);    # - for this command we assume the modules and
	                           #   message maps are in the same place
}
use lib "$::Bin";
use Getopt::Std;

#	Note:	this script is meant to be standalone
#		it should not require other modules or message files.

#-------------------------------------------------------------------#
#   MAIN Main main section of code
#-------------------------------------------------------------------#
#-------------------------------------------------------------------#
# Global Variables                                                  #
#-------------------------------------------------------------------#
$::progname        = "csmprereboot";
$::install_mounted = 0;             # /csminstall/csm directory mounted
$::csm_server      = "";            # the long hostname of the install server
$::mnt_dir         = "";            # directory to mount from the install server
$::akb_nodename    = "";            # the long hostname of this node as known by
                                    #    the install server
$::foundmsname     = 0;             # indicate that we have the inst server
$::foundmntdir     = 0;             # we have the dir to mount
$::foundakbname    = 0;             # indicate that we have the hostname as
                                    #    known by the install server
$::mounted         = 0;
$::mounted_linux   = 0;
$::FLAG            = 0;
$::CSMCLIENTMNTDIR = "/var/opt/csm/mnt";
$::CSMINSTDIR      = "/csminstall/csm";        # this may be replaced in getargs
$::CSMLINUXDIR     = "/csminstall/Linux";
$::CSM_MOUNT       = "$::CSMCLIENTMNTDIR/csm";
$::CSM_MOUNT_LINUX = "$::CSMCLIENTMNTDIR/Linux";
$::OPTCSMINSTALL   = "/opt/csm/install";
$::PREINSTALLDIR   = "$::CSM_MOUNT/scripts/installprereboot";
$::CSMCFGDIR       = "$::CSM_MOUNT/config";
$::CAT             = "/bin/cat";
$::MKDIR           = "/bin/mkdir";
$::COPY            = "/bin/cp";
$::MKITAB          = "/usr/sbin/mkitab";
$::LSITAB          = "/usr/sbin/lsitab";
$::NOK             = 1;
$::OK              = 0;
$::GREP            = "/bin/grep";
$::CSMLOG          = "/var/log/csm";
$::INSTALL_LOG     = "/var/log/csm/install.log";
$::GLOBAL_EXIT     = 0;
$::logging         = 0;

$::command_line;

@::prescriptlist = ();    #  list of user-provided scripts to run

# get the platform and architecture
$::PLTFRM = `uname`;
chomp $::PLTFRM;

$::arch = `uname -m`;
chomp($::arch);

if ($::PLTFRM eq "AIX")
{
	$::MOUNT  = "/usr/sbin/mount";
	$::UMOUNT = "/usr/sbin/umount";
}
else
{
	$::MOUNT  = "/bin/mount";
	$::UMOUNT = "/bin/umount";
}

my ($cmd, $rc);

#
#  check the command line
#
print "Running csmprereboot script\n" if $::DEBUG;
&parse_args;

#
# start logging
#
print "$0: start logging\n" if $::DEBUG;

&append_logging($::INSTALL_LOG);
$::logging++;

#
# mount /csminstall/csm and /csminstall/Linux if not already mounted
#
$::CSMINSTDIR = $::mnt_dir . "/csm";

if (&mount_csminstall($::CSMINSTDIR, $::CSM_MOUNT) != 0)
{
	$::GLOBAL_EXIT = 1;
	exit;
}
else
{
	if ($::FLAG)
	{
		$::mounted++;
	}
}

$::CSMLINUXDIR = $::mnt_dir . "/Linux";
if ($::PLTFRM eq "Linux")
{
	if (&mount_csminstall($::CSMLINUXDIR, $::CSM_MOUNT_LINUX) != 0)
	{
		$::GLOBAL_EXIT = 1;
		exit;
	}
	else
	{
		if ($::FLAG)
		{
			$::mounted_linux++;
		}
	}
}

#
# get info from the config_info file
#
if (&get_config_info != 0)
{
	print
	  "$::progname: 2653-104 Could not get node attribute values from config_info file.\n";
	print $::LOG_FILE_HANDLE
	  "$::progname: 2653-104 Could not get node attribute values from config_info file.\n";
	$::GLOBAL_EXIT = 1;
	exit;
}

##		Run customer provided scripts

#	Set some environment variables for the cust scripts to use

#   The name of this node as it is known by the CSM
#   management server

$ENV{'CSMNODENAME'} = "$::akb_nodename";

#	The mount point for CSM on the node is equivalent
#	to /csminstall on the management server

$ENV{'CSMMOUNTPOINT'} = "/var/opt/csm/mnt";

#	The data directory where additional user provided scripts
#	and data files will be located.

$ENV{'SCRIPTDATAPATH'} = "/var/opt/csm/mnt/csm/scripts/data";

##	Run each user script

foreach my $name (@::prescriptlist)
{

	#	cd to the directory of the customer's script in case they
	#	use a relative path to get to the data directory.

	my $cmd = "cd $::PREINSTALLDIR; ./$name";
	print $::LOG_FILE_HANDLE
	  "$::progname: 2653-144 Beginning Customer Script: $cmd. Reported $rc.\n";

	&stop_logging(1);

	my $output = `$cmd 2>&1`;
	chomp($output);
	$rc = $? >> 8;

	&append_logging($::INSTALL_LOG, 1);

	if ($rc != 0)
	{
		print
		  "$::progname: 2653-144 Error running command $cmd. Reported $rc.\n";
		print $::LOG_FILE_HANDLE
		  "$::progname: 2653-144 Error running command $cmd. Reported $rc.\n";
	}
	else
	{
		print $::LOG_FILE_HANDLE
		  "$::progname: 2653-144 Completed Customer Script $cmd. Reported $rc.\n";
	}
}

##		Finish up and exit

END
{

	#
	# unmount /csminstall/csm  and /csminstall/Linux - if we mounted it
	#
	if ($::mounted)
	{
		if (&unmount_csminstall($::CSM_MOUNT) != 0)
		{
			$::GLOBAL_EXIT = 1;
			exit;
		}
	}
	if ($::mounted_linux)
	{
		if (&unmount_csminstall($::CSM_MOUNT_LINUX) != 0)
		{
			$::GLOBAL_EXIT = 1;
			exit;
		}
	}

	if ($::logging)
	{
		&stop_logging();
	}

	#Determine exit code
	if ($::GLOBAL_EXIT > $?)
	{
		$? = $::GLOBAL_EXIT;
	}
}

exit;    # end of Main

#
#-------------------------------------------------------------------------#
# parse_args - Parse the command line for options and operands.           #
#--------------------------------------#----------------------------------#
sub parse_args
{

	my @command_line = ();
	@command_line   = @ARGV;
	$::command_line = $0 . " " . join(" ", @command_line);

	#
	# Process the command line...
	#
	if (!getopts('m:p:n:'))
	{    # Gather options
		exit 1;
	}

	if ($::opt_m ne "")
	{    # # name of server
		$::csm_server = $::opt_m;
		$::csm_server =~ s/^\s*//;    # delete leading white space
		$::csm_server =~ s/\s*$//;    # delete trailing spaces
		chomp $::csm_server;
		print "csmprereboot: Install server is $::csm_server\n" if $::DEBUG;
		$::foundmsname++;
	}
	if ($::opt_p ne "")
	{
		$::mnt_dir = $::opt_p;
		$::mnt_dir =~ s/^\s*//;
		$::mnt_dir =~ s/\s*$//;
		chomp $::mnt_dir;
		print "csmprereboot: Directory to mount is $::mnt_dir\n" if $::DEBUG;
		$::foundmntdir++;
	}
	if ($::opt_n ne "")
	{
		$::akb_nodename = $::opt_n;
		$::akb_nodename =~ s/^\s*//;
		$::akb_nodename =~ s/\s*$//;
		chomp $::akb_nodename;
		print "csmprereboot: Node name is $::akb_nodename\n" if $::DEBUG;
		$::foundakbname++;
	}
	return $::OK;
}

#-------------------------------------------------------------------------#
#   mount_csminstall - mount the /csminstall/csm and /csminstall/Linux    #
#		       directory                                          #
#                                                                         #
#   Return Codes: 0 - All was successful.                                 #
#                 1 - An error occured.                                   #
#--------------------------------------#----------------------------------#
sub mount_csminstall
{
	my ($src_dir, $dest_dir) = @_;
	my $cmd;
	my $rc;
	my $srcdir;
	my $output;

	$cmd = "$::MOUNT | $::GREP $dest_dir >/dev/null 2>&1";
	$rc  = system("$cmd");
	if ($rc >> 8)
	{
		print $::LOG_FILE_HANDLE
		  "$0: mounting $::csm_server:$src_dir to $dest_dir\n"
		  if $::DEBUG;

		$srcdir = "$::csm_server:$src_dir";
		chomp $srcdir;
		if (!-d $dest_dir)
		{

			# create a local directory
			$cmd = "$::MKDIR -m 755 -p $dest_dir";
			$rc  = system("$cmd");
			if ($rc >> 8)
			{
				print
				  "$::progname:  2653-158 Could not create \"$dest_dir\" directory.\n";
				print $::LOG_FILE_HANDLE
				  "$::progname: 2653-158 Could not create \"$dest_dir\" directory.\n";
				return $::NOK;
			}
		}

		#  Mount the /csminstall/csm filesystem
		$cmd = "$::MOUNT -o nolock $srcdir $dest_dir";
		$rc  = system("$cmd");
		if ($rc >> 8)
		{
			print "$::progname:  2653-032 Could not mount \"$srcdir\".\n";
			print $::LOG_FILE_HANDLE
			  "$::progname: 2653-032 Could not mount \"$srcdir\".\n";
			return $::NOK;
		}
		else
		{
			print $::LOG_FILE_HANDLE "\"$srcdir\" is mounted now.\n";
			print "$::progname: \"$srcdir\" is mounted now.\n";
			$::FLAG = 1;
		}
	}
	else
	{
		print "$::progname:  \"$dest_dir\" is already mounted.\n";
		print $::LOG_FILE_HANDLE
		  "$::progname: \"$dest_dir\" is already mounted.\n";
	}
	return $::OK;
}

#-------------------------------------------------------------------------#
#   get_config_info - Get required information out of the config_info     #
#                     file. This file contains attributes and values for  #
#                     the node we are running on.                         #
#                                                                         #
#   Return Codes: 0 - All was successful.                                 #
#                 1 - An error occured.                                   #
#--------------------------------------#----------------------------------#

sub get_config_info
{

	my ($attr, $value);
	my $cfg_file   = "$::CSMCFGDIR/$::akb_nodename.config_info";
	my $match_vers = 0;

	if (-f $cfg_file)
	{
		unless (open(CFGINFO, "<$cfg_file"))
		{
			print
			  "$::progname: 2653-142 Cannot open file \"$cfg_file\" for reading.\n";
			print $::LOG_FILE_HANDLE
			  "$::progname: 2653-142 Cannot open file \"$cfg_file\" for reading.\n";
			return $::NOK;
		}
		while (<CFGINFO>)
		{
			($attr, $value) = split('=');
			if (defined($attr) && defined($value))
			{
				if ($attr eq "PREINSTSCRIPTS")
				{
					@::prescriptlist = split(" ", $value);
				}
			}
		}

		close(CFGINFO);
	}
	else
	{
		print "$::progname: 2653-023 \"$cfg_file\" does not exist.\n";
		print $::LOG_FILE_HANDLE
		  "$::progname: 2653-023 \"$cfg_file\" does not exist.\n";
		return $::NOK;
	}
	return $::OK;
}

#-------------------------------------------------------------------------#
#   unmount_csminstall - unmount the /csminstall/csm and /csminstall/     #
#			 Linux directory                                  #
#                                                                         #
#   Return Codes: 0 - All was successful.                                 #
#                 1 - An error occured.                                   #
#--------------------------------------#----------------------------------#
sub unmount_csminstall
{
	my ($unmnt_dir, undef) = @_;
	my ($rc,        $cmd);

	print "$0: unmounting $unmnt_dir\n";
	$cmd = "$::UMOUNT $unmnt_dir";
	$rc  = system("$cmd");
	if ($rc >> 8)
	{
		print
		  "$::progname: 2653-037 The internal call to \"$::UMOUNT\" was not successful.\n";
		print $::LOG_FILE_HANDLE
		  "$::progname: 2653-037 The internal call to \"$::UMOUNT\" was not successful.\n";
		print "$::progname: 2653-033 Could not unmount \"$unmnt_dir\".\n";
		print $::LOG_FILE_HANDLE
		  "$::progname:  2653-033 Could not unmount \"$unmnt_dir\".\n";
		return $::NOK;
	}
	else
	{
		print $::LOG_FILE_HANDLE "$::progname: \"$unmnt_dir\" is unmounted.\n";
		print "\"$unmnt_dir\" is unmounted.\n";
	}
	return $::OK;
}

#-------------------------------------------------------------------------#
#                                                                         #
#   backup_logfile                                                        #
#                                                                         #
#        Backup the current logfile. Move logfile to logfile.1.           #
#        Shift all other logfiles (logfile.[1-3]) up one number.          #
#        The original logfile.4 is removed.                               #
#                                                                         #
#-------------------------------------------------------------------------#
sub backup_logfile
{
	my ($logfile) = @_;

	my ($logfile1) = $logfile . ".1";
	my ($logfile2) = $logfile . ".2";
	my ($logfile3) = $logfile . ".3";
	my ($logfile4) = $logfile . ".4";

	if (-f $logfile)
	{

		rename($logfile3, $logfile4) if (-f $logfile3);
		rename($logfile2, $logfile3) if (-f $logfile2);
		rename($logfile1, $logfile2) if (-f $logfile1);
		rename($logfile,  $logfile1) if (-f $logfile);
	}
	return $::OK;
}

#-------------------------------------------------------------------------#
#                                                                         #
#    start_logging                                                        #
#                                                                         #
#           Start logging messages to a logfile. Return the log file      #
#           handle so it can be used to close the file when done logging. #
#                                                                         #
#-------------------------------------------------------------------------#
sub start_logging
{
	my ($logfile) = @_;
	my ($cmd, $rc);

	&backup_logfile($logfile);

	# create the log directory if it's not already there
	if (!-d $::CSMLOG)
	{
		$cmd = "$::MKDIR -m 644 -p $::CSMLOG";
		$rc  = system("$cmd");
		if ($rc >> 8)
		{
			print
			  "$::progname: 2653-158 Could not create \"$::CSMLOG\" directory.\n";
			return ($::NOK);
		}
	}

	# open the log file
	unless (open(LOGFILE, ">$logfile"))
	{

		# Cannot open file
		print
		  "$::progname: 2653-141 Cannot open file \"$logfile\" for writing.\n";
		return $::NOK;
	}

	$::LOG_FILE_HANDLE = \*LOGFILE;

	# announce logging and print the date to the top of the logfile
	my $sdate = `/bin/date`;
	chomp $sdate;
	print "Output log is being written to \"$logfile\".\n";
	print $::LOG_FILE_HANDLE
	  "---------------------------------------------------------------------\n";
	print $::LOG_FILE_HANDLE "$::progname: Logging started $sdate.\n";
	print $::LOG_FILE_HANDLE
	  "---------------------------------------------------------------------\n";
	print $::LOG_FILE_HANDLE $::command_line . "\n";

	return ($::LOG_FILE_HANDLE);
}

#-------------------------------------------------------------------------#
#                                                                         #
#    append_logging                                                       #
#                                                                         #
#         Append logging messages to a logfile. Return the log file       #
#           handle so it can be used to close the file when done logging. #
#                                                                         #
#-------------------------------------------------------------------------#
sub append_logging
{
	my ($logfile, $stat) = @_;
	my ($cmd,     $rc);

	# create the log directory if it's not already there
	if (!-d $::CSMLOG)
	{
		$cmd = "$::MKDIR -m 644 -p $::CSMLOG";
		$rc  = system("$cmd");
		if ($rc >> 8)
		{
			print
			  "$::progname: 2653-158 Could not create \"$::CSMLOG\" directory.\n";
			return ($::NOK);
		}
	}

	#
	#  get log file ready
	#
	if (!-e $logfile)
	{    #  create the log file if not already there
		    # open the log file
		unless (open(LOGFILE, ">$logfile"))
		{

			# Cannot open file
			print
			  "$::progname: 2653-141 Cannot open file \"$logfile\" for writing.\n";
			return $::NOK;
		}
	}
	else
	{       # it's there so just append
		unless (open(LOGFILE, ">>$logfile"))
		{
			print "$::progname: 2653-036 Could not update  \"$logfile\".\n";
			return $::NOK;
		}
	}

	$::LOG_FILE_HANDLE = \*LOGFILE;

	if ((defined $stat) && ($stat == 1))
	{
		return ($::LOG_FILE_HANDLE);
	}

	# Print the date to the top of the logfile
	my $sdate = `/bin/date`;
	chomp $sdate;
	print "Output log is being written to \"$logfile\".\n";
	print $::LOG_FILE_HANDLE
	  "---------------------------------------------------------------------\n";
	print $::LOG_FILE_HANDLE "$::progname: Logging started $sdate.\n";
	print $::LOG_FILE_HANDLE
	  "---------------------------------------------------------------------\n";
	print $::LOG_FILE_HANDLE $::command_line . "\n";

	return ($::LOG_FILE_HANDLE);
}

#-------------------------------------------------------------------------#
#                                                                         #
#    stop_logging                                                         #
#                                                                         #
#                  Turn off message logging.  (Expects to have a file     #
#                   handle passed in. )                                   #
#                                                                         #
#-------------------------------------------------------------------------#
sub stop_logging
{

	# Print the date at the bottom of the logfile
	my ($stat) = @_;
	my $sdate = `/bin/date`;
	chomp $sdate;
	if ($stat != 1)
	{
		print $::LOG_FILE_HANDLE
		  "---------------------------------------------------------------------\n";
		print $::LOG_FILE_HANDLE "$::progname: Logging stopped $sdate.\n";
		print $::LOG_FILE_HANDLE
		  "---------------------------------------------------------------------\n";
	}

	close($::LOG_FILE_HANDLE);
	$::LOG_FILE_HANDLE = undef;

	return $::OK;
}
