#!/usr/bin/perl -w
#*********************************************************************
#
# fai-progress -- monitor process that does progress and error
#                 display for FAI installations.
#
# (c) 2008-2010 by Cajus Pollmeier <pollmeier@gonicus.de>
#
#*********************************************************************

=head1 NAME

fai-progress - show an informative progress bar during FAI operations.

=head1 SYNOPSIS

/usr/lib/cdebconf/debconf fai-progress

=head1 DESCRIPTION

fai-progress is a script used to display an informative progress bar
during installations or softupdates using FAI and a standard cdebconf
method.

Use vga=788 as your kernel start parameter and you're getting the
GTK backend instead of textual NEWT. You can use dpatch to change
the graphical logo to your own one.

=over 10

=head1 ENVIRONMENT VARIABLES

=item B<FAI_LOG_PATH>        FAI logfile to monitor for changes

=item B<FAI_METHOD>          Either 'install' or 'update' - this only controls
                             the displayed information

=item B<GOSA_SI_SOCKET>      Path to a named pipe to write the current progress
                             information. It can be used for faimond related
                             processes to update the client installation progress
                             in percent.

=head1 USAGE

This example is from the confdir.default.source hook. It creates a new VT and starts the fai-progress process inside of this VT. It can be stopped by "echo fai-progress: hangup >> $FAI_LOG_PATH".

FAI_PROGRESS_VT=$(openvt -v 2>&1 -- sh -c "
        export TERM=linux ;
        export TERM_UTF8=yes ;
        export FAI_LOG_PATH=$LOGDIR/fai.log ;
        export DEBCONF_DEBUGFILE=$LOGDIR/debconf.log ;
        export DEBCONF_DEBUG=developer ;
        export LANG=UTF-8

        if [ -c /dev/fb0 ]; then
                export DEBIAN_FRONTEND=gtk ;
        else
                export DEBIAN_FRONTEND=newt ;
        fi ;

        setterm -blank 0 -powersave off -powerdown 0 ;
        echo -ne "\033%G" ;
        touch -f $FAI_LOG_PATH ;
        /usr/lib/cdebconf/debconf /usr/bin/fai-progress ;
        reset")

FAI_PROGRESS_VT=${FAI_PROGRESS_VT##* }
echo "${FAI_PROGRESS_VT##/dev/tty}" > $LOGDIR/fai-progress-vt

chvt ${FAI_PROGRESS_VT##/dev/tty}


=head1 PRESUMPTION

In order to display the installation progress correctly, you have to set the MAXPACKAGES FAI variable to a large value - i.e. 10000.

=back

=cut

use strict;
use warnings;
use POSIX;
use File::Tail;
use Debconf::Client::ConfModule ':all';
use GOto::Utils; 
use Locale::gettext;
use MIME::Base64;

# I18N setup
setlocale(LC_MESSAGES, "");
textdomain("fai-progress");

# Global variables
my $percent= 0;
my $last_percent= 0;
my $template= "fai-progress";
my $update= 0;
my $monitor_path= "/var/log/fai.log";
my $gosa_si_path= "/var/run/gosa-si/gosa-si-client.socket";

sub gosa_si_signal {
  my ($parm)= @_;
	if (-w $gosa_si_path){
		open( GOSA, ">>$gosa_si_path" );
		print GOSA "$parm\n";
		close(GOSA);
	}
}


#################################################################
##                     M A I N - R O U T I N E                 ##
#################################################################

# Evaluate environment variables
if (defined $ENV{'FAI_LOG_PATH'}){
  $monitor_path= $ENV{'FAI_LOG_PATH'};
}
if (defined $ENV{'GOSA_SI_SOCKET'}){
  $gosa_si_path= $ENV{'GOSA_SI_SOCKET'};
}
if (defined $ENV{'FAI_METHOD'} && $ENV{'FAI_METHOD'} eq 'update'){
  $update= 1;
}

# Sanity check
if ( ! -r $monitor_path ) {
	die ("fai-progress: fatal: cannot read '$monitor_path' - aborting");
}

# Setup tail
my $line;
my $file= File::Tail->new(name=>$monitor_path, interval=>0.2, maxinterval=>0.2, adjustafter=>100000);

# Expect Debconf version 2.0
version('2.0');

# Extract locale from the environment and set it to debconf
my $current_locale= $ENV{'LANG'};
$current_locale =~ s/^(..).*$/$1/;
set("debconf/language", "$current_locale");

if ($update){
  subst ("fai-progress/title", "i", gettext("FAI Update Progress"));
  subst ("fai-progress/info", "i", gettext("Progress of update"));
} else {
  subst ("fai-progress/title", "i", gettext("FAI Installation Progress"));
  subst ("fai-progress/info", "i", gettext("Progress of installation"));
}
settitle("fai-progress/title");
progress ("start", 0, 100, "fai-progress/info");
subst ("fai-progress/step", "i", gettext("Initializing FAI"));
progress("info", "fai-progress/step");
progress("set", $percent);

# Lets roll
my $res;
while (defined($line= $file->read)) {
	
	# Tail logfile line by line until we're ready
	$res= process_input($line);
	if ($res->{'status'} == -1){
		last;
	}

	# Completely bail out on errors
	if ($res->{'status'} != 0){
		progress("stop");

    # Errors detected here will not be 'cancel-able'
    while (1) {
      capb();
      if (defined $res->{'action'}){
        subst ("fai-progress/".$res->{'task'}, "i", $res->{'action'});
      }
      input("critical", "fai-progress/".$res->{'task'});
      go();
    }

		stop();
		exit 0;
	}

  # Handle different progress information
  if (defined $res->{'action'}){

    # Start hardware detection progress
    if (defined $res->{'task'} && $res->{'task'} eq "goto-hardware-detection-start"){
		  $percent= progress("get");
      $template= "goto-hardware";
      progress("stop");

      settitle("goto-hardware/title");
      progress ("start", 0, 100, "goto-hardware/info");
      subst ("goto-hardware/step", "i", gettext("Hardware detection started"));
      progress("info", "goto-hardware/step");
      progress("set", 0);
      next;
    }

    # Start activation progress
    if (defined $res->{'task'} && $res->{'task'} eq "goto-activation-start"){
		  $percent= progress("get");
      $template= "goto-activation";
      progress("stop");

      gosa_si_signal("GOTOACTIVATION");

      settitle("goto-activation/title");
      progress ("start", 0, 100, "goto-activation/info");
      subst ("goto-activation/step", "i", gettext("System is locked. Waiting for activation..."));
      progress("info", "goto-activation/step");
      progress("set", 0);
      next;
    }

    if (defined $res->{'task'} && ( $res->{'task'} eq "goto-hardware-detection-stop" || $res->{'task'} eq "goto-activation-stop" ) ){
      progress("stop");
      $template= "fai-progress";

      # Restore installation progress bar
      settitle("fai-progress/title");
      progress ("start", 0, 100, "fai-progress/info");
      progress("set", $percent);
    }

    # Updated progressbar(s)
    if (defined $res->{'percent'}){
      subst ("$template/step", "i", $res->{'action'});
      progress("info", "$template/step");
      progress("set", $res->{'percent'});
      if ($last_percent != $res->{'percent'}){
        $last_percent= $res->{'percent'};
        gosa_si_signal("PROGRESS ".$res->{'percent'});
      }
    }
  }

}

# Finish up
progress("stop");
stop();
print "faiprogress: got hangup - shutting down";

exit (0);


1;

__END__

# vim:ts=2:sw=2:expandtab:shiftwidth=2:syntax:paste
