#!/usr/local/bin/perl
# 
# $Header: defaultimage_stage.pl 02-aug-2007.00:07:03 rshetty Exp $
#
# defaultimage_stage.pl
# 
# Copyright (c) 2005, 2007, Oracle. All rights reserved.  
#
#    NAME
#      defaultimage_stage.pl - <one-line expansion of the name>
#
#    DESCRIPTION
#      Stage Directives for Default Image
#      This script will create a final kickstart file by combining all 
#      the smaller kickstart files
#
#    NOTES
#      <other useful comments, qualifications, etc.>
#
#    MODIFIED   (MM/DD/YY)
#    rshetty     07/31/07 - removing copying of bootFiles
#    saurgarg    06/25/07 - Modifying the bootloader entry insertion from ref
#                           kickstart. need to have partition as mbr always
#    rshetty     06/18/07 - changing permissions of boot directory
#    sacgoel     11/13/06 - exit with exit status if creation of boot file
#                           fails
#    rattipal    10/03/06 - Network config
#    rshetty     09/27/06 - inckuding changes for complete boot automation
#    rattipal    09/11/06 - Backport ssdas_suse_fix from main
#    pshroff     03/10/06 - Backport rattipal_lastest_directives from main 
#    rattipal    12/12/05 - Backport pshroff_bootfile_auto from main 
#    ssdas       08/16/06 - 
#    rshetty     08/09/06 - taking only last 8 characters of for creation of
#                           boot file name
#    rattipal    04/05/06 - http url support 
#    pshroff     11/30/05 - to support bootfile automation 
#    pshroff     09/13/05 - chmod force option 
#    prayarot    08/23/05 - forcefully copy kickstart file 
#    pshroff     07/31/05 - adding error handling exitstatus code 
#    pshroff     07/28/05 - modifying part info 
#    pshroff     07/24/05 - added partitioning and firewall info
#    pshroff     07/21/05 - added xconfig info
#    pshroff     06/30/05 - pshroff_map_shiphome
#    pshroff     06/22/05 - changing temp kickstart filename to ks.cfg only
#    rbhanush    06/21/05 - giving write permissions to final kickstart file 
#    rbhanush    05/31/05 - Combining post script file
#    rbhanush    05/24/05 - rbhanush_update_props
#    rbhanush    05/19/05 - Creation
# 

use File::Find;
use Cwd;

require "$ENV{EMDROOT}/sysman/admin/scripts/provisioning/provisionCommon.pl";

my $rel_image_kickstart_path;
my $image_kickstart_path;
my $SAMPLE_BOOT_FILE = "$ENV{EMDROOT}/sysman/admin/scripts/provisioning/SAMPLE-PXE-BOOTFILE";

my $KICKSTART_URL = "KICKSTART_URL"; 
my $PXECONFIGDIR  = "pxelinux.cfg";
my $STAGE_BASE_URL_PROP = "NAME_StageBaseUrl";    
main();

sub main()
{
    $pathSeperator="/";

    
    my $currentfolder_cmd="pwd";
    chomp($currentfolder_cmd);
    my $imageFolder=`$currentfolder_cmd`;
    chomp $imageFolder;
    
    print "Current image folder is: $imageFolder\n";
    
    my $rel_imageFolder=$imageFolder;
    my $stage_top_dir=get_oraProperty("NAME_StageSharedMountPoint");
    $rel_imageFolder=~ s/$stage_top_dir//;
    
    #image kickstart name
    $ipPrefix=get_oraProperty("NAME_IpPrefix"); 
    $kickstart="-ks.cfg";
    
    # Finding imageHw name
    my $current_path=`pwd`;
    chomp($current_path);
    my $parent_path="..";
    chdir $parent_path;
    my $top_image_path=`pwd`;
    chomp($top_image_path);
    chdir $current_path;
    my $image_hw_name=$current_path;
	my $image_hw_path = $current_path;
    my $temp_top_image_path=$top_image_path.$pathSeparator;
    $image_hw_name=~ s/$temp_top_image_path//;
    
    #reference kickstart file name
    $ref_kickstart_name="ref-anaconda-ks.cfg";
    # kickstart file name will be the imageHw name appended with "-ks.cfg" suffix
    $image_kickstart_path="$imageFolder$pathSeperator$image_hw_name$kickstart";
    $ref_kickstart_file="$imageFolder$pathSeperator$ref_kickstart_name";
    
    #Getting entries from the reference kickstart file
    #following entries are added here:
    #mouse, keybord, lang, langsupport, bootloader, clearpart, xconfig
    createAndAppendToKickstart("#Following entries from reference kickstart file\n");
    print "Reference kickstart file location: $ref_kickstart_file\n";
    createDefaultEntries($ref_kickstart_file);
    
    #Adding default entries
    #Following entries are added here:
    #reboot, install, nfs
    appendToKickstart("#Adding default hardcoded values\n");
    appendToKickstart("reboot\n");
    appendToKickstart("install\n");
    
    #Combine smaller kickstart files
    appendToKickstart("\n#Combining entries from smaller kickstart files\n");
    find(\&create_kickstart, $imageFolder);
    
    #Add package section to the image kickstart file
    #Package section file "package-ks.cfg" is generated by linux os component 
    find(\&addPackageSection, $imageFolder);
    
    #Add post section to the image kickstart file
    #post section file "post-ks.cfg" is generated by linux os component 
    find(\&addPostSection, $imageFolder);
    
# After creating the kickstart file, it is moved to toplevel OS directory
    my $top_os_path=$stage_top_dir."/OS";
    system("mv -f $image_kickstart_path $top_os_path");
    $image_kickstart_path = $top_os_path.$pathSeparator.$image_hw_name.$kickstart;
    $rel_image_kickstart_path="/OS".$pathSeparator.$image_hw_name.$kickstart;     
    #now at this point, kickstart file is ready, modify boot server , update bootfile 
    # and use the kickstart file in ks-url
    my $bootFileDirPath = getBootFileDirPath($imageFolder);
    modifyBootServer($bootFileDirPath, $image_hw_path);
    
    
} #main end

#This subroutine copies the boot files(vmlinuz and initrd.img)
#and returns the boot directory path for the particular repository
 
sub getBootFileDirPath()
{
	my ($imageFolder) = @_;
    
	my $rpm_repository_url_info_file = "rpm_repository.info";
        my $bootFilesTopDir = "bootFiles";
	
	my $bootServerPath=get_oraProperty("NAME_BootServerPath");
	my $bootFileTopDirPath = $bootServerPath."/".$bootFilesTopDir;
	
	my $previous_dir = getcwd;
	chdir $imageFolder;

	my $rpmUrl = `head $rpm_repository_url_info_file -n 1`;
	chomp($rpmUrl);

	my $repositoryHash = `echo $rpmUrl|md5sum`;
	chomp($repositoryHash);
	$repositoryHash =~ s/\s*\-//;
	
	my $bootFileDirPath = $bootFileTopDirPath."/".$repositoryHash;
	my $bootFileDirRelativePath = $bootFilesTopDir."/".$repositoryHash;

	print "Boot File Directory Path is $bootFileDirPath\n";

	chdir($previous_dir);
	return $bootFileDirRelativePath;

}

# modify boot server, copy sample-boot file and then 
# modify the URL to point to proper kickstart file
# available on stage server
sub modifyBootServer()
{ 

    my ($bootFileDirPath,$image_hw_path) = @_;
    my $pxeDirName = $PXECONFIGDIR;
    #chmod 755 to final kickstart on stage server
    my $chmod_ks="chmod -f 755 $image_kickstart_path";
    syscmd($chmod_ks,"","true");
    $exitstatus = $? >> 8;
    
    if ($exitstatus != 0)
    {
        print "\nFailed to Change te Permission of the kickstart File \n";
        exit $exitstatus;
    }
    
    my $boot_filename = getBootFilename(); 
    
    #copying final kickstart file to boot server
    my $bootServerPath=get_oraProperty("NAME_BootServerPath");  
    
    #my $boot_filepath = "$bootServerPath$pathSeperator$PXECONFIGDIR$pathSeperator$boot_filename";
	syscmd("mkdir -p $image_hw_path$pathSeperator$pxeDirName","","true");
    my $boot_filepath = "$image_hw_path$pathSeperator$pxeDirName$pathSeperator$boot_filename";
    print "\nhex converted ip-prefix path is $boot_filepath \n";
    
    # change ks url  in boot file
    changeKickstartUrl($boot_filepath, $bootFileDirPath);
    
}

# reads the sample boot file, modifies kickstart URL Info and 
# adds each line into boot file, specified by input param.
sub changeKickstartUrl()
{
    my ($boot_file, $bootFileDirPath) = @_;
    my $VMLINUZ = "vmlinuz";
    my $INITRD_IMG = "initrd.img";
    
    my $boot_url = getBootUrl(); 
    
    open IN_BOOT_FILEHANDLE, "$SAMPLE_BOOT_FILE" or die "Can't open sample boot file $SAMPLE_BOOT_FILE $!";
    open OUT_BOOT_FILEHANDLE, ">$boot_file" or die "Can't create boot file $boot_file $!";
    
    while ($entry = <IN_BOOT_FILEHANDLE> )
    {
        chomp $entry; 
	
        if ($entry =~ $KICKSTART_URL)
        {
            $entry = findAndReplace($entry, $KICKSTART_URL, $boot_url); 
        } 

	if ($entry =~ $VMLINUZ)
	{
	    $entry = findAndReplace($entry, $VMLINUZ, $bootFileDirPath."/".$VMLINUZ);		
	}	

	if ($entry =~ $INITRD_IMG)
	{
	    $entry = findAndReplace($entry, $INITRD_IMG, $bootFileDirPath."/".$INITRD_IMG);		
	}	

        print OUT_BOOT_FILEHANDLE "$entry\n";
    }
    
    close IN_BOOT_FILEHANDLE;
    close OUT_BOOT_FILEHANDLE;
    
    my $chmod_ks="chmod -f 777 $boot_file";
    system($chmod_ks);
    $exitstatus = $? >> 8;
    
    if ($exitstatus != 0)
    {
        print "\n Failed to Change the Permission of the boot File: Please check \n";
    }
    
    return;
}

sub getBootFilename()
{
    my $ip_prefix = get_oraProperty("NAME_IpPrefix");  
    
    my $gethostipcmd = "gethostip $ip_prefix";
    
    my $hexValue = `$gethostipcmd`;
    chomp $hexValue;
    
    @hex_info = split /\s+/ ,$hexValue ;
    
    my $len = $#hex_info;
    
    for($count=1;$count<=$len;$count++)
    {
        $hex_entry=$hex_info[$count];    
    }

    my $len = length($hex_entry);
    if ($len > 8)
    {
     $hex_entry = substr ($hex_entry,$len-8,8);
    }

    return trimZeroes($hex_entry);
}


sub getBootUrl()
{
    # Constants;
    my $COLON = ":";
    my $DOUBLE_SLASH = "//";
    
    # Local Variables
    my $m_baseUrl;
    my $m_host_name;
    my @m_urlInfo;
    my $m_len;
    my $m_count;
    my $m_urlEntry;
    my $m_url;
    
    
    $m_baseUrl = get_oraProperty($STAGE_BASE_URL_PROP); 
    if($m_baseUrl=~ /^file:/ || $m_baseUrl=~ /^FILE:/)
    {
	my $m_host_dir;
	$m_host_dir="";
	@m_urlInfo = split /\/+/ ,$m_baseUrl ;
	$m_len = $#m_urlInfo;
	for($m_count=1;$m_count<=$m_len;$m_count++)
	{
	    $m_urlEntry=$m_urlInfo[$m_count];
	    if($m_count ==1)
	    {
		$m_host_name = $m_urlInfo[$m_count];
	    }
			if($m_count >1)
			{
			    $m_host_dir = $m_host_dir."/".$m_urlInfo[$m_count];
			}
	}
	
	
        $m_url = "nfs".$COLON.$m_host_name.$COLON.$m_host_dir.$rel_image_kickstart_path;
    }
    else
    {
        $m_url = $m_baseUrl.$rel_image_kickstart_path;
    }
    
    print "kickstart url is $m_url\n";
    
    return $m_url;
}





#adds package file package-ks.cfg to image's kickstart file
sub addPackageSection()
{ 
    my ($package_file_path, $append_cmd);
    
    if($_=~"package-ks.cfg")
    {
        $package_file_path="$File::Find::dir/$_";
        print "Appending package section file $package_file_path to final kicktstart file\n";
        $append_cmd="cat $package_file_path >> $image_kickstart_path";
        system($append_cmd);
        my $exitstatus = $? >> 8;
        
        if ($exitstatus != 0)
        {
            print "\nFailed to Copy package section into the kickstart File \n";
            exit $exitstatus;
        }   
    }
}

#adds post file post-ks.cfg to image's kickstart file
sub addPostSection()
{
    my ($post_file_path, $append_cmd);
    if($_=~"post-ks.cfg")
    {
        $post_file_path="$File::Find::dir/$_";
        print "Appending post section file $post_file_path to final kicktstart file\n";
        $append_cmd="cat $post_file_path >> $image_kickstart_path";
        system($append_cmd);
        my $exitstatus = $? >> 8;
        
        if ($exitstatus != 0)
        {
            print "\nFailed to Copy post section into the kickstart File \n";
            exit $exitstatus;
        }
    }
}

sub create_kickstart()
{
    if(/kickstart$/)
    {
        $small_kickstart_path="$File::Find::dir/$_" ;
        print "Appending smaller kickstart $small_kickstart_path to final kickstart file \n";
        open READ,"$small_kickstart_path" or die "Can not read $small_kickstart_path : $!";
        while(<READ>)       
        {
            appendToKickstart("$_");
        }
        
        close READ;
    }
}

#Read entries from reference kickstart file and add to the image kickstart file.
#following entries are added here:
#mouse, keybord, lang, langsupport, bootloader, clearpart, xconfig
sub createDefaultEntries()
{
    my ($ref_kickstart_file)=@_;
    
    #Open reference kickstart file and add entries to the image kickstart file
    open REF_KICKSTART, "$ref_kickstart_file" or die "\nCan not read reference kickstart file: $ref_kickstart_file $!";
    while(<REF_KICKSTART>)
    {
        chomp;
        push(@reference_entries, $_);
    }
    close REF_KICKSTART;
    
    @mouse=grep /^mouse /, @reference_entries;
    $mouse_entry=@mouse[0];
    #$mouse_entry=stripComments($mouse_entry);
    appendToKickstart("$mouse_entry\n");
    
    @keyboard=grep /^keyboard /, @reference_entries;
    $keyboard_entry=@keyboard[0];
    #$keyboard_entry=stripComments($keyboard_entry);
    appendToKickstart("$keyboard_entry\n");
    
    @lang=grep /lang /, @reference_entries;
    $lang_entry=@lang[0];
    #$lang_entry=stripComments($lang_entry);
    appendToKickstart("$lang_entry\n");
    
    @langsupport=grep /langsupport /, @reference_entries;
    $langsupport_entry=@langsupport[0];
    #$langsupport_entry=stripComments($langsupport_entry);
    appendToKickstart("$langsupport_entry\n");
    
    @bootloader=grep /^bootloader /, @reference_entries;
    $bootloader_entry=@bootloader[0];

    #convert from partition/none to mbr for default case
    my $from_regex = "--location[ ]*=[ ]*(([n][o][n][e])|([p][a][r][t][i][t][i][o][n]))";
    my $to_regex = "--location=mbr";

    $bootloader_entry =~ s/$from_regex/$to_regex/g;

    #$bootloader_entry=stripComments($bootloader_entry);
    appendToKickstart("$bootloader_entry\n");
    
    #Default Partitioning Info
    @clearpart=grep /^clearpart /, @reference_entries;
    $clearpart_entry=@clearpart[0];
    if ($clearpart_entry eq '')
    {
        $clearpart_entry="clearpart --all --initlabel";
    }
    appendToKickstart("$clearpart_entry\n");
    
    my $root_part="part / --fstype ext3 --size 5120 --grow\n";
    appendToKickstart($root_part);
    my $swap_part="part swap --size 1024\n";
    appendToKickstart($swap_part);
    #Default Partitioning Info ends
    
    #Network information
    my $deviceName = get_oraProperty("NAME_NetworkProfile.NAME_NetworkConfig[0].NAME_DeviceName");
    if ( $deviceName eq "")
    {
    my $network_part="network --bootproto=dhcp --device=eth0\n";
    appendToKickstart($network_part);
    }
    #firewall info
    @firewall=grep /^firewall /, @reference_entries;
    $firewall_entry=@firewall[0];
    if ($firewall_entry eq '')
    {
        $firewall_entry="firewall --disabled\n";
    }
    appendToKickstart("$firewall_entry\n");
    
    #xconfig info
    @xconfig=grep /^xconfig /, @reference_entries;
    $xconfig_entry=@xconfig[0];
    if ($xconfig_entry eq '')
    {
        $xconfig_entry="skipx";
    }
    appendToKickstart("$xconfig_entry\n");
    
    close OUT;
}

sub appendToKickstart()
{
    my ($entry)=@_;
    open OUT, ">>$image_kickstart_path" or die "Can't open kickstart file $image_kickstart_path $!" ;
    print OUT $entry;
    close OUT;
}

sub createAndAppendToKickstart()
{
    my ($entry)=@_;
    open OUT, ">$image_kickstart_path" or die "Can't open kickstart file $image_kickstart_path $!" ;
    print OUT $entry;
    close OUT;
}

=head
syntax execute ($command,$errorMessage,$isexit)

This functions executes the system command $command and print $errorMessage on failure and exits if $isExit is true
=cut
sub syscmd ()
{
	 my $command = shift;
	 my $errorMessage = shift;
  	 my $isExit = shift;  # by deafult is true

     print ("Executing command: $command\n");
	 system($command);
	 my $exitStatus = $? >> 8;
	 if ($exitStatus != 0)
	 {
		  print ("Status: Failed\n");
		  print ("Error Status: $exitStatus\n");
		  if ($errorMessage) {print ("Error Message: $errorMessage\n");}

		  if ($isExit ne "false") {
    		  exit ($exitStatus);
		  }	
	 }
	 else {
		print ("Status:Succeded\n");
	 }
	 return ($exitStatus);
}
