#!/usr/perl5/bin/perl
#
# Copyright 2001-2002 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#
# ident	"@(#)step6.pl	1.48	03/01/07 SMI"
#
# Installation page 6

require 5.005;
use strict;
use lib '/opt/SUNWscvw/lib/perl';
use Cluster::Cgi;
use Cluster::Install;
use Sun::Solaris::Utils qw(gettext);

# Set constants
use constant TRUE          => 0;
use constant FALSE         => 1;

# Set autoflush
$| = 1;

# Set pfexec path
my $PFEXEC = "/usr/bin/pfexec";

# Remove the BASEDIR environment variables
delete @ENV{'BASEDIR', 'CLIENT_BASEDIR'};

# Create the html query object
my $q = new Cluster::Cgi;

# Create a install object
my $install = new Cluster::Install;

# Set the javascript to launch the sccheck log viewer window
my $WIDTH = 650;
my $HEIGHT = 650;
my $log_link_jscript = 
	"var logWindow\n" .
	"function Log(nodename) {\n" .
	"  winprops='width=$WIDTH,height=$HEIGHT,scrollbars,resizable," .
	"toolbar'\n  logWindow = window.open(\"/cgi-bin/installation/" .
	"showlog.pl?node=\" + nodename + \"&file=sccheck/sccheck-results.\"" .
	"+ nodename + \".txt\", 'LogWindow', winprops)\n" .
	"  return false\n" .
	"}";

# Start the html document
$install->header($q, gettext("Sun Cluster Installation &gt; " .
			     "Installation in Progress"),
		 undef, $log_link_jscript);

print $q->p({class => "action-window-normal-text"});

# Print info
print gettext("The cluster is now being installed and configured.  " .
  "This process may take up to 90 minutes depending on the options you " .
  "have selected. When the installation has finished, this window will " .
  "automatically reload with the SunPlex Manager monitoring and " .
  "configuration GUI.");

print $q->p({class => "action-window-normal-text"});
print $q->img({	SRC => "/images/warning_16.gif",
		WIDTH => 16,
		HEIGHT => 16,
		ALT => "Warning"});
print " ";
print gettext("Do not close this browser window or modify the URL while " .
    "the installation is in progress.");
print $q->table({ CLASS => "action-table",
		  WIDTH => "97%",
		  BORDER => 0,
		  CELLSPACING => 0,
		  CELLPADDING => 0,
		  ALIGN => "center",
	  });
print $q->start_Tr({HEIGHT => 10});
print $q->start_td({COLSPAN => 2});
print $q->img({SRC => "/images/dot.gif", ALT => "", HEIGHT => 10});
print $q->end_td(), $q->end_Tr(), "\n";

print $q->start_Tr({HEIGHT => 1});
print $q->start_td({COLSPAN => 2, CLASS => "action-line-row"});
print $q->img({SRC => "/images/dot.gif", ALT => "", HEIGHT => 1});
print $q->end_td(), $q->end_Tr(), $q->end_table(), "\n";

# Setup the needed variables
my $cluster_name = $q->param('cluster_name');
my $cluster_size = $q->param('cluster_size');
my $cdrom_path = $q->param('cdrom_path');
my $ds_cdrom_path = $q->param('ds_cdrom_path');
my $solaris_cdrom_path = $q->param('solaris_cdrom_path');
my $install_nfs = $q->param('install_nfs');
my $nfs_address = $q->param('nfs_address');
my $patch_path = $q->param('patch_path');
my $install_apache = $q->param('install_apache');
my $apache_address = $q->param('apache_address');
my $run_sccheck = $q->param('run_sccheck');
my $retry_patches = $q->param('retry_patches');
my $uncompressed_patch_path = $install->get_uncompresspatchdir();

# Get the list of nodes we're installing
my @nodelist = $install->get_nodelist($q);
my $clustersize = $#nodelist + 1;

# Create a nodelist string
my $nodestring = join ',', @nodelist;

# Get the log directory to use
my $logdir = $install->get_logdir();

# After going through the sccheck stuff, write the nodelist and
# clustersize to all of the nodes. Also, write state files to make
# sure that the correct rc scripts get run after installation.
foreach my $node ($install->get_nodelist($q)) {
    my $nodefile = "$logdir/nodelist";
    my $sizefile = "$logdir/clustersize";
    my $quorumfile = "$logdir/setup_quorum_flag";
    $install->appendfile_remote($node, $sizefile, $clustersize);
    $install->appendfile_remote($node, $nodefile, $nodestring);
    $install->appendfile_remote($node, $quorumfile, "1");
}

# Check if SDS is already installed
my $sds_installed=0;
foreach my $node (@nodelist) {
    if ($install->get_install_state($node, "DONE_SDS") eq 'YES') {
        $install->syslog("SDS has already been installed on $node.");
        $sds_installed++;
    }
}

# Install SDS
if ($q->param('install_sds') eq 'yes' && ($sds_installed == $clustersize)) {
    # Skip the SDS installation as it already has been done.
    # Print message for the user
    print $q->p({CLASS => "action-window-normal-text"});

    if ($install->is_solaris8() == TRUE) {
	    print gettext("Skipping installation of Solstice DiskSuite...\n");
    } else {
	    print gettext("Skipping configuration of Solaris Volume Manager...\n");
    }
} elsif ($q->param('install_sds') eq 'yes' && ($sds_installed!=$clustersize)) {

    # Common vars
    my ($ret, $error);
    $error = 0;

    # Print message for the user
    print $q->p({CLASS => "action-window-normal-text"});

    if ($install->is_solaris8() == TRUE) {
	    print gettext("Installing Solstice DiskSuite...");
    } else {
	    print gettext("Configuring Solaris Volume Manager...");
    }

    # 1. Call cgi-bin/installation/sds/installation in parallel on all nodes
    foreach my $node ($install->get_nodelist($q)) {

	    # Setup state files
	    my $devicefile = "$logdir/setup_devices_flag";
	    my $sdsfile = "$logdir/setup_sds_flag";
	    $install->appendfile_remote($node, $devicefile, "1");
	    $install->appendfile_remote($node, $sdsfile, "1");

	    my $installation = "/cgi-bin/installation/sds/installation.pl";
	    
	    if ($install->is_solaris8() == TRUE) {
		    $installation .= "?solaris_cdrom_path=$solaris_cdrom_path";
	    }

	    $install->syslog("Installing Solstice DiskSuite on $node");
	    
	    $install->get_http($node,
			       $install->get_http_port(),
			       $installation);
    }

    # 2. Wait for the SDS installation to finish on all nodes
    my $sds_complete = 0;

    while ($sds_complete == 0) {
	$sds_complete = 1;

	foreach my $node (@nodelist) {
	    if ($install->get_install_state($node, "DONE_SDS") ne 'YES') {
		$install->syslog("Solstice DiskSuite has NOT finished on $node");
		$sds_complete = 0;
		last;
	    } else {
		$install->syslog("Solstice DiskSuite has finished on $node");
	    }
	}

	print ".";
	sleep(5);
    }
 
    # 3. Create SDS/SVM configuration files
    $error += $install->process_appendfile_dat($q);
    
    # 4. Save the vfstab entry in a datafile on all nodes
    foreach my $node ($install->get_nodelist($q)) {
            $install->append_vfstab_entry($node);
    }
    
    # Final reporting of status
    if ($error != 0) {
	    $install->syslog("config_sds FAILED with return value $error");
    }

    print gettext("&nbsp;&nbsp;DONE");
} # End sds install

# Install patches if we've defined a patch directory path
if (defined $patch_path && $patch_path ne '' &&
        $retry_patches ne "false" ) {
    print $q->p({CLASS => "action-window-normal-text"});
    print gettext("Adding patches...");

    my $patchadd_error_log="/var/cluster/spm/patchadd_error_log";
    # Call cgi-bin/installation/patchadd_local.pl on all nodes
    # and pass in the location of the uncompressed patches
    foreach my $node (@nodelist) {
	my $patchadd = "/cgi-bin/installation/patchadd_local.pl";
	$patchadd .= "?uncompressed_patch_path=$uncompressed_patch_path".
             "&patchadd_error_log=$patchadd_error_log";
	$install->syslog("Installing patches on $node");
	
	my @output = $install->get_http($node, $install->get_http_port(),
	      $patchadd);
	
	foreach my $line (@output) {
	    print $line;
	}
    }
    
    # Wait for the patch installation to finish on all nodes
    my $patch_complete = 0;
    my $patch_errors_nodes = 0;
    foreach my $node (@nodelist) {
        # redo comes here
        if ($install->get_install_state($node, "DONE_PATCHES") ne 'YES') {
            $install->syslog("PATCH ADDING has NOT finished on $node");
	    print ".";
            sleep(10);
            redo;
        } else {
            $install->syslog("PATCH ADDING has finished on $node");
            # Check each node's error log.  If there were errors when
            # adding patches, then halt the installation and prompt users
            # to either resolve any patch conflicts by hand, ignore the patch
	    # add errors, go back to the previous screen, or cancel.
            my @patch_errors = $install->check_patch_errors($node,
		$patchadd_error_log);
            if (@patch_errors) {
                # There were errors when adding certain patches!
                $patch_errors_nodes++;
                if ( $patch_errors_nodes == 1 ) {
		    $install->start_message_table($q, "/images/error_32.gif",
		        gettext("Error"), gettext("Patch Installation"),
		        gettext("The following errors occurred during patch " .
		            "installation:"));
		}
                foreach my $p_e ( @patch_errors ) {
                     # Print message for the user
                     print $q->p({CLASS => "message-command-text"}, $node,
			$p_e);
                     $install->syslog("$node $p_e");
                     $q->br();
                }
            }
        }
    }
    # End the message table if any patch errors were encountered.
    if ( $patch_errors_nodes != 0 ) {
        $install->end_message_table($q);
    }

    # Remove the state file in case that another attempt to add patches takes
    # place.
    foreach my $node (@nodelist) {
	# Remove the DONE_PATCHES state file.
        $install->remove_done_patches_state_file($node);
    }

    # Done with all the nodes
    # If there were any errors seen on any node, then print them to the user
    if ( $patch_errors_nodes > 0) {
	my $query_string = $q->get_cluster_query_string();
	my $retry_jscript = "self.location=\"step6.pl$query_string\"" .
		" + \"&run_sccheck=false\"";
	my $continue_jscript = $retry_jscript . 
		" + \"&retry_patches=false\"";
        # Prompt the user on their next course of action.
        print $q->p({class => "action-window-normal-text"});
        print gettext("The patches that did not encounter errors have been successfully added.  However, some patches experienced errors during patch addition.");
	print "<UL>";
	print "<LI> ".gettext("To complete patch installation, manually resolve the above patch installation errors, then click 'Retry Adding Patches'. ");
	print "<LI>".gettext("To ignore the above patch errors and proceed without the above patches, click 'Continue with Installation'.");
	print "<LI>".gettext("To return to the previous screen, click 'Back'.");
	print "<LI>".gettext("To cancel installation, click 'Cancel'.");
	print "</UL>";

        print $q->start_form({ action => '/cgi-bin/installation/step6.pl' });
        # Print the hidden cluster fields
        $q->print_hidden_cluster_fields();
        $install->start_button_table($q);
	print $q->button({ value   => gettext(" < Back  "),
			   onClick => "history.back()"
			   });
	print "&nbsp";
	print $q->button({ value => gettext("  Retry Adding Patches  "),
			   onClick => $retry_jscript
			   });
	print "&nbsp";
        print $q->button({ value   => gettext(" Continue with Installation "),
			   onClick => $continue_jscript
        		});
	print "&nbsp";
        $install->end_button_table($q, "cancel");
        print $q->end_form();
        # End the html document
        $install->footer($q);
        # end gracefully if errors were found
        exit(0);
    }
    # Print some blank lines.
    print gettext("&nbsp;&nbsp;DONE");
} # End patch install


# Ie we're installing HA NFS as a dataservice, then 
#	- Create an rc script that will install the NFS package on each
#		node.
#	- Check to make sure that we have a metaset 'mirror-1' created
#	- Find the node that is responsible for mirror-1 creation and
#		copy an rc script that will configure HA NFS using mirror-1.
#
# NOTE : It is possible that we are installing Solstice DiskSuite, but we
# do NOT find enough shared disks to make a mirrored metadevice.  If this is the
# case, then we cannot create a global filesystem which is a prerequisite 
# for HA NFS.
if ($install_nfs eq 'yes' || $install_apache eq 'yes') {

	# Setup the IPMP groups on each node
	print $q->p({CLASS => "action-window-normal-text"});
	print gettext("Configuring IP Network Multipathing (IPMP) groups...\n");
	
	for (my $i=0; $i<=$#nodelist; $i++) {
		my $node = $nodelist[$i];
		my $j = $i+1;
		my $setup_ipmp = "/cgi-bin/installation/setup_ipmp.pl" .
			"?testaddr=" . $q->param("node_$j.testaddr");
		my ($result) = $install->get_http($node,
						  $install->get_http_port(),
						  $setup_ipmp);
		chomp $result;
	}

	print gettext("&nbsp;&nbsp;DONE");

    # Choose which data services to install
    print $q->p({CLASS => "action-window-normal-text"});
    if ($install_apache eq 'yes') {
	if ($install_nfs eq 'yes') {
	    print gettext("Installing Apache and NFS...\n");
	} else {
	    print gettext("Installing Apache...\n");
	}
    } else {
	print gettext("Installing NFS...\n");
    }
    
    foreach my $node ($install->get_nodelist($q)) {
	my ($find_mirror_metaset, $result, $copy_nfs_scripts, 
		$nfs_installation);
	$find_mirror_metaset = "/cgi-bin/installation/nfs/find_mirror_metaset.pl";
	$nfs_installation = "/cgi-bin/installation/nfs/nfs_installation.pl" .
		"?cdrom_path=" . $q->param('cdrom_path') .
		"&ds_cdrom_path=" . $q->param('ds_cdrom_path') .
		"&solaris_cdrom_path=" . $q->param('solaris_cdrom_path'); 

	# Choose which data services to install
	if ($install_nfs eq 'yes') {
	    $nfs_installation .= "&install_nfs=yes";

	    # Write the logical hostname to all nodes
	    $install->appendfile_remote($node,
					"$logdir/logical_host",
					$nfs_address);
	}

	if ($install_apache eq 'yes') {
	    $nfs_installation .= "&install_apache=yes&apache_address=" . 
		$q->param("apache_address");

	    # Write the shared address to all nodes
	    $install->appendfile_remote($node,
					"$logdir/shared_address",
					$apache_address);
	}

	# Write the path of the data services cdrom
	if ($install_apache eq 'yes' || $install_nfs eq 'yes') {
		$install->appendfile_remote($node,
					    "$logdir/ds_cdrom_path",
					    $q->param('ds_cdrom_path'));
		$install->appendfile_remote($node,
					    "$logdir/setup_ds_packages_flag",
					    1);
	}

	# Write a rc script that will install the SUNWscnfs package on each
	# node of the cluster.
	($result) = $install->get_http($node,
				       $install->get_http_port(), 
				       $nfs_installation);
	chomp $result;
	if ($result eq "OK") {
		$install->syslog("Installing NFS packages on $node...");
	} else {
		print $q->start_b();
		print sprintf(gettext("Installation of NFS and/or Apache packages on %s failed!\n"), $node);
		print $q->br(), $q->end_b();
		$install->syslog("Installation of NFS and/or Apache packages on $node failed.");
	}

	# Only copy the rc script copy_nfs_scripts to the node that will
	# configure the HA NFS resource.
	($result) = $install->get_http($node, $install->get_http_port(), 
				$find_mirror_metaset);
	chomp $result;
	if ($result eq "FOUND") {
		$install->syslog("Configuring Apache/NFS on $node.");

		# Write the setup nfs flag to all nodes
		$install->appendfile_remote($node,
					    "$logdir/setup_nfs_flag",
					    "1");


		# Write the setup apache flag to all nodes
		$install->appendfile_remote($node,
					    "$logdir/setup_apache_flag",
					    "1");
	}
    }

    print gettext("&nbsp;&nbsp;DONE");
}

# Create loop variables
my $loopnode;
my $loopinstall;
my $nodenametocall;
my $command;

# Print message instructing the user to reload after the install
print $q->p({CLASS => "action-window-normal-text"});
print gettext("Configuring Sun Cluster and rebooting nodes...");

# SCINSTALL here!
for ($loopinstall = 1; $loopinstall <= $cluster_size; $loopinstall++) {
	$install->syslog("Installing and rebooting node $loopinstall");
	$nodenametocall = $q->param("node_$loopinstall.name");
	$command = $install->call_remote_scinstall($nodenametocall, 
						   $loopinstall, 
						   $q);
}

# Print the appet to wait and reload
print $q->applet({ codebase => "/",
		   code => "InstallStatus.class",
		   width => 1,
		   height => 1
		   });
print $q->end_applet();

# End the html document
$install->footer($q);
