#
# Copyright 2002-2003 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#
#ident	"@(#)Quorum.pm	1.27	03/03/10 SMI"
#
# Quorum Device class

package Cluster::Quorum;
use strict;
use POSIX;
use Cluster::Common;
use Cluster::Menu;
use Cluster::RBAC;
use Cluster::RunCommand;
use Sun::Solaris::Utils qw(gettext);
use vars qw(@ISA $VERSION);
$VERSION = '1.00';
@ISA = qw(Cluster::Common);

# Internationalization
# action=
;# gettext("Maintain")
;# gettext("Reset")
;# gettext("Remove")

##############################################################################
#
# Class constructor
#
##############################################################################

sub new {
    my $proto = shift;
    my $class = ref($proto) || $proto;
    my $self  = {};
    bless ($self, $class);
    return $self;
}

##############################################################################
#
# Class Variables
#
##############################################################################

# File names and location
my $PFEXEC = '/usr/bin/pfexec';		# Used in execute_cmd()
my $QUORUMIMAGE = '/images/quorum/quorum_16.gif';
my $NODEIMAGE = '/images/node_16.gif';
my $VIEW   = '/cgi-bin/quorum/quorum_view.pl';
my $CONFIG = '/cgi-bin/quorum/quorum_config.pl';
my $ADD    = '/cgi-bin/quorum/quorum_add.pl';
my $SCCONF = '/usr/cluster/bin/scconf';
my $SCSTAT = '/usr/cluster/bin/scstat';
my $DIDADM = '/usr/sbin/didadm';

# Instantiate cluster objects
my $rbac = new Cluster::RBAC;
my $runcommand   = new Cluster::RunCommand;

# Command output saved in memory 
my @DIDADML_OUT;
my @SCCONFP_OUT;
my @SCSTATQ_OUT;

my @QD_LIST;

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

my @status_icons = (
	["Online", "Online", "ok"], # gettext("Online")
	["Offline", "Offline", "critical"], # gettext("Offline")
	["Degraded", "Degraded", "critical"], # gettext("Degraded")
	["Wait", "Wait", "minor"] # gettext("Wait")
);

my @enabled_status_icons = (
	["yes", "Yes", "ok"], # gettext("Yes")
	["no", "No", "critical"] # gettext("No")
);

##############################################################################
#
# Class methods
#
##############################################################################

sub quorum_header($$$$) {
        my ($self, $q, $headername, $quorumdevice) = @_;

        # Start the action bar table
        $q->start_action_bar_table($headername);

        # Print the middle of the action table
        $q->mid_action_bar_table();

        # Create the actions menu links
        my @links = ();
	my @action_helpMarkers = ();

	# Add if the user has solaris.cluster.quorum.admin
	if ($rbac->check_auth($CL_AUTH_QUORUM_ADMIN)) {
		push (@links, gettext("Put in Maintenance State..."),
                    "$CONFIG\?step=1&func=Maintain&quorumdevice=$quorumdevice",
                    gettext("Reset Quorum Device..."),
                    "$CONFIG\?step=1&func=Reset&quorumdevice=$quorumdevice",
		      gettext("---------------------"), "$VIEW");
		push (@action_helpMarkers, "quorumpm-maint", "quorumpm-reset",
		      "separator");
	}

	# Add if the user has solaris.cluster.quorum.modify
	if ($rbac->check_auth($CL_AUTH_QUORUM_MODIFY)) {
		push (@links, gettext("Add Quorum Device..."), "$ADD?step=1",
                     gettext("---------------------"), "$VIEW",
		     gettext("Remove Quorum Device..."),
		     "$CONFIG\?step=1&func=Remove&quorumdevice=$quorumdevice");
		push (@action_helpMarkers, "quorumpm-add", "separator",
		      "quorumpm-remove");
	}

	# Print if the user has quorum modify or admin permissions
	if ($rbac->check_auth($CL_AUTH_QUORUM_MODIFY) ||
	    $rbac->check_auth($CL_AUTH_QUORUM_ADMIN)) {
		$q->load_action_helpMarkers(\@action_helpMarkers);
		$q->actions_menu(gettext("Action Menu"), \@links);
	}	

        # End the action bar table
        $q->end_action_bar_table();
}

sub votes_table($$) {
	 my ($self, $q) = @_;

        # Set the headers for the node adapter table
        my @table_headers = (gettext("Node / Quorum Device"), "40%",
                                gettext("Current Votes"), "20%",
                                gettext("Possible Votes"), "20%",
				"&nbsp;", "14",
                                gettext("Status"), "20%");

	# Determine the number of columns from the headers
        my $numcols = ($#table_headers + 1) / 2;

	# Start the table
        $q->start_prop_table(gettext("Cluster Quorum Votes"), \@table_headers,
			$QUORUMIMAGE);	

	# Get the node votes list
	my @nodevoteslist = $self->get_nodevoteslist();

	# Get the quorum devices votes list
	my @qdlist = $self->get_quorumdevicelist();

	# Print nodes votes
	for (my $i = 0; $i <= $#nodevoteslist; $i++) {
		# Start a table row
		$q->start_prop_tr();

		# Print a table cell for the node name
		$q->start_prop_td();
		$q->start_table_text("table-label-text");
		print $nodevoteslist[$i]{'name'};
		$q->end_table_text();
		$q->end_prop_td();

		# Print a table cell for the present votes
		$q->start_prop_td({ align => "center" });
		$q->start_table_text("table-normal-text");
		print $nodevoteslist[$i]{'presentvotes'};
		$q->end_table_text();
		$q->end_prop_td();
		
		# Print a table cell for the possible votes
		$q->start_prop_td({ align => "center" });
		$q->start_table_text("table-normal-text");
		print $nodevoteslist[$i]{'possiblevotes'};
		$q->end_table_text();
		$q->end_prop_td();

		# Print a table cell for the status
		$q->start_prop_td();
		$q->table_status_text($nodevoteslist[$i]{'status'},
		    \@status_icons);
		$q->end_prop_td();

		$q->end_prop_tr();

		$q->line_row($numcols);
	}

	# Print quorum devices votes
	for (my $i = 0; $i <= $#qdlist; $i++) {
		my ($presentvotes, $status) =
			$self->get_quorumdevicevotes($qdlist[$i]{'name'});
		# Start a table row
		$q->start_prop_tr();

		# Print a table cell for the node name
		$q->start_prop_td();
		$q->table_link_text($qdlist[$i]{'name'},
			$qdlist[$i]{'name'},
			"$VIEW?quorumdevice=$qdlist[$i]{'name'}");
		$q->end_prop_td();

		# Print a table cell for the present votes
		$q->start_prop_td({ align => "center" });
		$q->start_table_text("table-normal-text");
		print $presentvotes; 
		$q->end_prop_td();
		
		# Print a table cell for the possible votes
		$q->start_prop_td({ align => "center" });
		$q->start_table_text("table-normal-text");
		print $qdlist[$i]{'possiblevotes'};
		$q->end_prop_td();

		# Print a table cell for the status
		$q->start_prop_td();
		$q->table_status_text($status,
		    \@status_icons);
		$q->end_prop_td();
		
		$q->end_prop_tr();

		$q->line_row($numcols);
	}

	# Get the votes summary
	my ($possible, $needed, $present) = $self->get_votessummary();

	# Print the votes summary
	$q->start_prop_tr();
	#$q->start_prop_td({ align => "center" });
	$q->start_prop_td();
	print $q->start_div({ CLASS => "table-summary-text" });
	print gettext("Total Votes:");
	print $q->end_div();
	$q->end_prop_td();

	$q->start_prop_td({ align => "center" });
	print $q->start_div({ CLASS => "table-strong-text" });
	print $present;
	print $q->end_div();
	$q->end_prop_td();

	$q->start_prop_td({ align => "center" });
	print $q->start_div({ CLASS => "table-strong-text" });
	print $possible;
	print $q->end_div();
	$q->end_prop_td();
	
	$q->start_prop_td();
	print $q->indent(1); 
	$q->end_prop_td();
		
	$q->start_prop_td();
	print $q->indent(1); 
	$q->end_prop_td();
		
	$q->end_prop_tr();
	$q->line_row($numcols);
	
	$q->start_prop_tr();
	$q->start_prop_td({ align => "center" });
	print $q->start_div({ CLASS => "table-summary-text" });
	print gettext("Votes Required:");
	print $q->end_div();
	$q->end_prop_td();

	$q->start_prop_td({ align => "center" });
	print $q->start_div({ CLASS => "table-strong-text" });
	print $needed;
	print $q->end_div();
	$q->end_prop_td();

	$q->start_prop_td({ align => "center" });
	print $q->start_div({ CLASS => "table-strong-text" });
	print $q->indent(1); 
	$q->end_prop_td();
		
	$q->start_prop_td();
	print $q->indent(1); 
	$q->end_prop_td();
		
	$q->start_prop_td();
	print $q->indent(1); 
	$q->end_prop_td();
	
	$q->end_prop_tr();
	
	# End the node status table
        $q->end_prop_table();
}

sub quorum_table($$$) {
	my ($self, $q, $qd) = @_;

	# Set the headers for the Quorum Device Properties table
        my @table_headers = (gettext("Property"), "40%",
				"&nbsp;", "14",
                                gettext("Value"), "60%");
	
	# Determine the number of columns from the headers
        my $numcols = ($#table_headers + 1) / 2;

	# Start the table
        $q->start_prop_table(sprintf(gettext("Quorum Device Properties - %s"),
	    $qd), \@table_headers, "$QUORUMIMAGE");	

	my @qdlist = $self->get_quorumdevicelist();
	my $i = $self->find_item_by_name(\@qdlist, $qd);
	if ($i == -1) {
		# Not Found
		# Start a table row and cell with the colspan of the table
                $q->start_prop_tr();
                $q->start_prop_td({ COLSPAN => 3 });

                # Print the message in table-label-text style
                $q->start_table_text('table-label-text');
	        print sprintf(gettext("Quorum Device %s is Not Configured on This Cluster"), $qd);
                $q->end_table_text();

                # End the cell and row
                $q->end_prop_td();
                $q->end_prop_tr();
		# End the table
	        $q->end_prop_table();
		return;
	}

	my ($presentvotes, $status) =
		$self->get_quorumdevicevotes($qdlist[$i]{'name'});	
	$q->start_prop_tr();
	$q->start_prop_td();
	$q->start_table_text('table-label-text');
	print gettext("Current Status:");
	$q->end_table_text();
	$q->end_prop_td();
	$q->start_prop_td();
	$q->table_status_text($status,
		    \@status_icons);
	$q->end_prop_td();
	$q->end_prop_tr();
	$q->line_row($numcols);

	$q->start_prop_tr();
	$q->start_prop_td();
	$q->start_table_text('table-label-text');
	print gettext("Quorum Device Name:");
	$q->end_table_text();
	$q->end_prop_td();
	$q->start_prop_td();
	$q->table_status_text($qdlist[$i]{"name"});
	$q->end_prop_td();
	$q->end_prop_tr();
	$q->line_row($numcols);

	$q->start_prop_tr();
	$q->start_prop_td();
	$q->start_table_text('table-label-text');
	print gettext("Possible Votes:");
	$q->end_table_text();
	$q->end_prop_td();
	$q->start_prop_td();
	$q->table_status_text($qdlist[$i]{"possiblevotes"});
	$q->end_prop_td();
	$q->end_prop_tr();
	$q->line_row($numcols);

	$q->start_prop_tr();
	$q->start_prop_td();
	$q->start_table_text('table-label-text');
	print gettext("Present Votes:");
	$q->end_table_text();
	$q->end_prop_td();
	$q->start_prop_td();
	$q->table_status_text($presentvotes);
	$q->end_prop_td();
	$q->end_prop_tr();
	$q->line_row($numcols);

	$q->start_prop_tr();
	$q->start_prop_td();
	$q->start_table_text('table-label-text');
	print gettext("Enabled:");
	$q->end_table_text();
	$q->end_prop_td();
	$q->start_prop_td();
	$q->table_status_text($qdlist[$i]{"enabled"},
	    \@enabled_status_icons);
	$q->end_prop_td();
	$q->end_prop_tr();
	$q->line_row($numcols);

	$q->start_prop_tr();
	$q->start_prop_td();
	$q->start_table_text('table-label-text');
	print gettext("Hosts (Enabled):");
	$q->end_table_text();
	$q->end_prop_td();
	$q->start_prop_td();
	$q->table_status_text($qdlist[$i]{"enablednodelist"});
	$q->end_prop_td();
	$q->end_prop_tr();
	$q->line_row($numcols);

	$q->start_prop_tr();
	$q->start_prop_td();
	$q->start_table_text('table-label-text');
	print gettext("Hosts (Disabled):");
	$q->end_table_text();
	$q->end_prop_td();
	$q->start_prop_td();
	$q->table_status_text($qdlist[$i]{"disablednodelist"});
	$q->end_prop_td();
	$q->end_prop_tr();

	# End the table
	$q->end_prop_table();
}
	
sub is_installmode
{
	my ($i, @parts, $line);
	$i = 0;
	for (my $j = 0; $j <= $#SCCONFP_OUT; $j++) {
		$line = $SCCONFP_OUT[$j];
		if ($line =~ /Cluster install mode:/) {
			@parts = split /(\:)/, $line;
			$parts[2] =~ s/\s+//g;
			if ($parts[2] eq "enabled") {
				return 1;
			} else {
				return 0;
			}
		}
	}
	return 0;
}

sub get_quorumdevicelist
{
	return @QD_LIST;
}

## Get quorum device list
sub _get_quorumdevicelist
{
	my (@qd_list, $i, @parts, $line);
	$i = 0;
	for (my $j = 0; $j <= $#SCCONFP_OUT; $j++) {
		$line = $SCCONFP_OUT[$j];
		if ($line =~ /Quorum device name:/) {
			@parts = split /(\S+)/, $line;
			$qd_list[$i]{'gname'} = $parts[7];
			$line = $SCCONFP_OUT[++$j];
			@parts = split /(\S+)/, $line;
			$qd_list[$i]{'possiblevotes'} = $parts[7];	
			$line = $SCCONFP_OUT[++$j];
			@parts = split /(\S+)/, $line;
			$qd_list[$i]{'enabled'} = $parts[7];
			$line = $SCCONFP_OUT[++$j];
			@parts = split /(\S+)/, $line;
			$qd_list[$i]{'name'} = $parts[7];
			$line = $SCCONFP_OUT[++$j];
			@parts = split /(\:)/, $line;
			# Get rid of the leading spaces
			$parts[2] =~ s/\s+//;
			if ($parts[2] eq "") {
				$qd_list[$i]{'enablednodelist'} = gettext("N/A");
			} else {
				$qd_list[$i]{'enablednodelist'} = $parts[2];
			}
			$line = $SCCONFP_OUT[++$j];
			@parts = split /(\:)/, $line;
			# Get rid of the leading spaces
			$parts[2] =~ s/\s+//;
			if ($parts[2] eq "" ) {
				$qd_list[$i]{'disablednodelist'} = gettext("N/A");
			} else {
				$qd_list[$i]{'disablednodelist'} = $parts[2];
			}
			$qd_list[$i]{'presentvotes'} = "0";
			$qd_list[$i]{'status'} = "Offline";
			$qd_list[$i]{'owner'} = gettext("N/A");

			$i++;
		}
	}
	return (@qd_list);
}

# Get the specified quorumdevice's dynamic vote info from scstat -q
sub get_quorumdevicevotes($$)
{
	my ($self, $quorumdevice) = @_;
	my ($presentvotes, $status, $line, @parts);
	# Initialize the vote info
	$presentvotes = "0";
	$status = "Offline";
	for (my $k = 0; $k <= $#SCSTATQ_OUT; $k++) {
		$line = $SCSTATQ_OUT[$k];
		if ($line =~ /Device votes:/) {
			@parts = split /(\S+)/, $line;
			if (!($parts[5] eq $quorumdevice)) {
				next;
			}
			$presentvotes = $parts[7];	
			$status = $parts[11];	
			last;
		}
	}
	return ($presentvotes, $status);
}

sub get_nodevoteslist
{
	my (@nv_list, $i, @parts, $line);
	$i = 0;
	# Potential status returns from scstat -q (scstat_cluster.c)
	;# gettext("Online")
	;# gettext("Offline")
	;# gettext("Faulted")
	;# gettext("Degraded")
	;# gettext("Wait")
	;# gettext("Not Monitored")
	;# gettext("Unknown")

	for (my $j = 0; $j <= $#SCSTATQ_OUT; $j++) {
		$line = $SCSTATQ_OUT[$j];
		if ($line =~ /Node votes:/) {
			@parts = split /(\S+)/, $line;
			$nv_list[$i]{'name'} = $parts[5];
			$nv_list[$i]{'presentvotes'} = $parts[7];
			$nv_list[$i]{'possiblevotes'} = $parts[9];
			$nv_list[$i]{'status'} = $parts[11];
			$i++;
		}
	}
	return (@nv_list);
}

sub get_votessummary
{
	my ($self, $q) = @_;
	my ($possible, $needed, $present, @parts, $line);
	foreach $line (@SCSTATQ_OUT) {
		if ($line =~ /Quorum votes possible:/) {
			@parts = split /(\S+)/, $line;
			$possible = $parts[7];
		}
		if ($line =~ /Quorum votes needed:/) {
			@parts = split /(\S+)/, $line;
			$needed = $parts[7];
		}
		if ($line =~ /Quorum votes present:/) {
			@parts = split /(\S+)/, $line;
			$present = $parts[7];
		}
	}

	return ($possible, $needed, $present);
}

sub config_remove($$$$)
{
	my ($self, $q, $step, $qd_name) = @_;

	if ($step == 1) {
		my @qd_list = $self->get_quorumdevicelist();
                if ($#qd_list < 0) {
			$q->print_title([gettext("Quorum"), $VIEW,
			gettext("Remove Quorum Device"),
			    "$CONFIG\?step=1&func=Remove&quorumdevice=$qd_name",
			gettext("Warning")]);
                        print "<form>";
                        $q->start_message_table("warning");
                        print $q->start_p({ class => "message-header-text" });
                        print gettext("No Quorum Device is Configured");
                        print $q->end_p();
                        $q->end_message_table();
                        $q->buttons_table(gettext("  Cancel  "), "self.location.href=\"$VIEW\"" );
                        print "</form>";
		} else {
			 $q->print_title([gettext("Quorum"), $VIEW,
			     gettext("Remove Quorum Device")]);
			# gather information
			print "<form name=inputs action=$CONFIG>";
                        print $q->input({ type => "hidden",
                                        name => "step",
                                        value => 2 });
                        print $q->input({ type => "hidden",
                                        name => "func",
                                        value => "Remove" });
                        print $q->start_table({ cellpadding => 5 });
                        print $q->start_Tr();
                        print $q->start_td();
                        print $q->start_div({ class => "action-window-label-text
" });
                        print gettext("Quorum Device:");
                        print $q->end_div();
                        print $q->end_td();
                        print $q->start_td();
			my $selectindex = 0;
			if (defined $qd_name) {
				$selectindex = $self->find_item_by_name(\@qd_list, $qd_name);
				if ($selectindex < 0) {
					$selectindex = 0;
				}
			}
			print "<select name=quorumdevice>";
			for (my $i = 0; $i <= $#qd_list; $i++) {
           		     print "<option value=$qd_list[$i]{'name'}>$qd_list[$i]{'name'}";	
			}
			print "</select>";
			print $q->start_script();
                        print "document.inputs.quorumdevice.selectedIndex=$selectindex";
                        print $q->end_script();
			print $q->end_td();
                        print $q->end_Tr();
			print $q->end_table();

			$q->start_message_table("warning");
                        print $q->start_p({ class => "message-description-text" });
                        print gettext("This action will permanently remove the quorum device. The device will no longer contribute to the quorum count.");
                        print $q->end_p();
                        $q->end_message_table();

                        $q->buttons_table(gettext(" Remove Quorum Device "),
					  "document.inputs.submit()",
					  gettext("  Cancel  "),
					  "self.location.href = \"$VIEW\"" );
			print "</form>";
		}
	} else {
		# generate the command
		my $cmd = "$SCCONF -r -q globaldev=$qd_name";

		# Executing the command
                $self->execute_cmd($q, $cmd, "Removed", $qd_name);
	}
}

sub config_changestate
{
	my ($self, $q, $step, $action, $qd_name) = @_;

	if ($step == 1) {
		my @qd_list = $self->get_quorumdevicelist();
                if ($#qd_list < 0) {
			$q->print_title([gettext("Quorum"), $VIEW,
			    sprintf(gettext("%s Quorum Device"),
				gettext($action)),
                        "$CONFIG\?step=1&func=$action&quorumdevice=$qd_name",
			    gettext("Warning")]);
                        print "<form>";
                        $q->start_message_table("warning");
                        print $q->start_p({ class => "message-header-text" });
                        print gettext("No Quorum Device is Configured");
                        print $q->end_p();
                        $q->end_message_table();
                        $q->buttons_table(gettext("  Cancel  "), "self.location.href=\"$VIEW\"" );
                        print "</form>";
		} else {
			if ($action eq "Maintain") {
				 $q->print_title([gettext("Quorum"), $VIEW,
		 gettext("Put Quorum Device in Maintenance State")]);
			} else {
				 $q->print_title([gettext("Quorum"), $VIEW,
		 sprintf(gettext("%s Quorum Device"), gettext($action))]);
			}

			# gather information
			print "<form name=inputs action=$CONFIG>";
                        print $q->input({ type => "hidden",
                                        name => "step",
                                        value => 2 });
                        print $q->input({ type => "hidden",
                                        name => "func",
                                        value => $action });
                        print $q->start_table({ cellpadding => 5 });
                        print $q->start_Tr();
                        print $q->start_td();
                        print $q->start_div({ class => "action-window-label-text" });
                        print gettext("Quorum Device:");
                        print $q->end_div();
                        print $q->end_td();
                        print $q->start_td();
			my $selectindex = 0;
			if (defined $qd_name) {
				$selectindex = $self->find_item_by_name(\@qd_list, $qd_name);
				if ($selectindex < 0) {
					$selectindex = 0;
				}
			}
			print "<select name=quorumdevice>";
			for (my $i = 0; $i <= $#qd_list; $i++) {
           		     print "<option value=$qd_list[$i]{'name'}>$qd_list[$i]{'name'}";	
			}
			print "</select>";
			print $q->start_script();
                        print "document.inputs.quorumdevice.selectedIndex=$selectindex";
                        print $q->end_script();
			print $q->end_td();
                        print $q->end_Tr();
			print $q->end_table();

			$q->start_message_table("warning");
                        print $q->start_p({ class => "message-description-text" });
			if ($action eq "Maintain") {
	                        print gettext("This action will set the device's quorum vote count to zero. The device will not contribute to the quorum count until it is reset.");
			} else {
	                        print gettext("This action will reset the vote count for the selected quorum device to its default value.");
			}
                        print $q->end_p();
                        $q->end_message_table();

                        $q->buttons_table(sprintf(gettext(" %s Quorum Device "),
			    gettext($action)),
			    "document.inputs.submit()",
			    gettext("  Cancel  "),
			    "self.location.href = \"$VIEW\"" );
			print "</form>";
		}
	} else {
		# generate the command
		my $cmd;
		if ($action eq "Maintain") {
			$cmd = "$SCCONF -c -q globaldev=$qd_name,maintstate";
		} else {
			$cmd = "$SCCONF -c -q globaldev=$qd_name,reset";
		}

		# Executing the command
		if ($action eq "Maintain") {
			$self->execute_cmd($q, $cmd, "in Maintenance State", 
					   $qd_name, "noreload");
		} else {
			$self->execute_cmd($q, $cmd, $action , $qd_name, "noreload");
		}
	}
}

# Get the available globaldevice from didadm -L output, excluding the one
# that is already being configured as quorumdevice
sub get_globaldev
{
	my (@gd_list, $i, @parts, $line, $name, $count);
	$count = 0;
	$name = "";
	$i = 0;
	my @qd_list = get_quorumdevicelist();
	foreach $line (@DIDADML_OUT) {
		@parts = split /(\S+)/, $line;
		if (!($parts[5] eq $name)) {
			if ($count > 1) {
				my $found = 0;
				for (my $j = 0; $j <= $#qd_list; $j++) {
					# check if it is already configured
					# as quorum device
					my $pattern = sprintf("%ss", $name);
					if ($qd_list[$j]{'name'} =~ $pattern) {
						$found = 1;
						last;
					}
				}
				if ($found == 0) { 
					$gd_list[$i++] = $name;
				}	
			}
			$name = $parts[5];
			$count = 1;
		} else {
			$count++;
		}
	}
	return (@gd_list);
}

# Get the local disk list that maps to the global device
sub get_localdisklist
{
	my ($self, $gd_name) = @_;
	my (@localdisk_list, $i, @parts, $line);
	foreach $line (@DIDADML_OUT) {
		@parts = split /(\S+)/, $line;
		if ($parts[5] eq $gd_name) {
			$localdisk_list[$i++] = $parts[3];
		} elsif ($#localdisk_list >= 0) {
			last;
		}
	}
	return (@localdisk_list);
}

sub add_quorumdevice($$$$)
{
	my ($self, $q, $step, $qd_name) = @_;
	
	if ($step == 1) {
		my @gd_list = $self->get_globaldev();	
		if ($#gd_list < 0) {
			$q->print_title([gettext("Quorum"), $VIEW,
				gettext("Add Quorum Device"), "$ADD?step=1",
				gettext("Warning")]);
			print "<form>";
			$q->start_message_table("warning");
			print $q->start_p({ class => "message-header-text" });
			print gettext("No Available Global Device to be Configured as Quorum Device.");
			print $q->end_p();
			$q->end_message_table();
			$q->buttons_table(gettext("  Cancel  "), "window.location.href=\"$VIEW\"" );
			print "</form>";
		} else {
			$q->print_title([gettext("Quorum"), $VIEW,
				gettext("Add Quorum Device")]);
			# gather information
			print "<form name=inputs action=$ADD>";
			print $q->input({ type => "hidden",
					name => "step",
					value => 2 });	
			print $q->start_table({ cellpadding => 5 });
			print $q->start_Tr();
			print $q->start_td();
			print $q->start_div({ class => "action-window-label-text" });
			print gettext("New Quorum Device:");
			print $q->end_div();
			print $q->end_td();
			print $q->start_td();
			my $j = 0;
			my (@gd_links, $selectindex);
			$selectindex = 0;
			for (my $i = 0; $i <= $#gd_list; $i++) {
				if ($gd_list[$i] eq $qd_name) {
					$selectindex = $i;
				}
				$gd_links[$j++] = $gd_list[$i];
				$gd_links[$j++] = "$ADD\?step=1&qd_name=$gd_list[$i]";
			} 
			$q->select_menu(\@gd_links, "gd_menu", $gd_links[1]);
			print $q->start_script();
			print "document.inputs.gd_menu.selectedIndex=$selectindex";
			print $q->end_script();
			print $q->end_td();
			print $q->end_Tr();
			print $q->start_Tr();
			print $q->start_td();
			print $q->end_td();
			print $q->start_td();
			print $q->start_p({ class => "message-header-text" });
			print sprintf(gettext("Global device %s is mapped to:"),
			    $gd_list[$selectindex]);
			print $q->end_p();
			my @localdisk_list = $self->get_localdisklist($gd_list[$selectindex]);
			for (my $i = 0; $i < $#localdisk_list + 1; $i++) {
				print $q->start_p({ class => "message-description-text" });
				print $localdisk_list[$i];
				print $q->end_p();
			}
			print $q->end_td();
			print $q->end_Tr();
			print $q->end_table();
			
			$q->buttons_table(gettext(" Add Quorum Device "),
				"self.location.href = \"$ADD\?step=2&qd_name=$gd_list[$selectindex]\"",
				gettext("  Cancel  "),
				"self.location.href = \"$VIEW\"" );

			print "</form>";
		}
	} else {
		# generate the command
		my $cmd = "$SCCONF -a -q globaldev=$qd_name";

		# Executing the command
		$self->execute_cmd($q, $cmd, "Added", $qd_name);
	}
}

sub execute_cmd($$$$$)
{
	my ($self, $q, $cmd, $action, $qd_name, $noreload) = @_;
	
	my $output = `$PFEXEC $cmd 2>&1`;
	my $ret = $?;
	my $title;
	my $success;
	my $errorTitle;
	my $error;
	SWITCH: {
		if ($action eq "in Maintenance State") {
			$title = gettext("Quorum Device in Maintenance State");
			$success = gettext("Quorum Device %1 Successfully in Maintenance State");
			$errorTitle = gettext("Quorum Device Not in Maintenance State Error");
			$error = gettext("Quorum Device %1 Not in Maintenance State");
			last SWITCH;
		}
		if ($action eq "Reset") {
			$title = gettext("Quorum Device Reset");
			$success = gettext("Quorum Device %1 Successfully Reset");
			$errorTitle = gettext("Quorum Device Not Reset Error");
			$error = gettext("Quorum Device %1 Not Reset");
			last SWITCH;
		}
		if ($action eq "Added") {
			$title = gettext("Quorum Device Added");
			$success = gettext("Quorum Device %1 Successfully Added");
			$errorTitle = gettext("Quorum Device Not Added Error");
			$error = gettext("Quorum Device %1 Not Added");
			last SWITCH;
		}
		if ($action eq "Removed") {
			$title = gettext("Quorum Device Removed");
			$success = gettext("Quorum Device %1 Successfully Removed");
			$errorTitle = gettext("Quorum Device Not Removed Error");
			$error = gettext("Quorum Device %1 Not Removed");
			last SWITCH;
		}
	}
	if ($ret == 0) {
		$q->print_title([gettext("Quorum"), $VIEW, $title]);
		print "<form>";
		$q->start_message_table("info");
		print $q->start_p({ class => "message-header-text" });
		print $q->sprintfn($success, $qd_name);
		print $q->end_p();
		print $q->start_p({ class => "message-description-text" });
		print gettext("The following command completed without error:");
		print $q->end_p();
		print $q->start_p({ class => "message-command-text" });
		print $cmd; 
		print $q->end_p();
		$q->end_message_table();
		$q->buttons_table(gettext(" View Quorum Device Information "),
				  "self.location.href= \"$VIEW\"" );
		print "</form>";
		if (!defined $noreload) {
			my $menu = new Cluster::Menu;
			$menu->reload_menu($q);
		}
	} else {
		$q->print_title([gettext("Quorum"), $VIEW, $errorTitle]);
		print "<form>";
		$q->start_message_table("error");
		print $q->start_p({ class => "message-header-text" });
		print $q->sprintfn($error, $qd_name);
		print $q->end_p();
		print $q->start_p({ class => "message-description-text" });
		print gettext("The command:");
		print $q->end_p();
		print $q->start_p({ class => "message-command-text" });
		print $cmd; 
		print $q->end_p();
		print $q->start_p({ class => "message-description-text" });
		print gettext("Failed with the following error:");
		print $q->end_p();
		print $q->start_p({ class => "message-command-text" });
		print $output;
		print $q->end_p();
		$q->end_message_table();
		$q->buttons_table(gettext("  < Back  "), "history.back()",
				  gettext("  Cancel  "), "self.location.href = \"$VIEW\"" );
		print "</form>";
	}
}

# Get the scconfp out into memory without checking whether it is up-to-date
# only used by jmenu.pl when only scconfpout is used.
sub get_scconfpout
{
	my ($self) = @_;
	my $update;
	($update, @SCCONFP_OUT) = $runcommand->scconfp_cache();
	if ($update == TRUE) {
		@QD_LIST = $self->_get_quorumdevicelist();
	}
}

# Get useful commands output into memory 
sub get_commandoutput
{
	my ($self) = @_;
	$self->get_scconfpout();
	
	my $update;
	($update, @DIDADML_OUT) = $runcommand->didadml_cache();
	@SCSTATQ_OUT = $runcommand->scstat("-q");
}

# Return true
1;
