#!/usr/bin/perl -w
use strict ;

=head1 sched_commit_job

A complete network system schedule solution

=head2 DESCRIPTION

This program take a job file an check if we can detect error.

=head2 USAGE

    Usage : sched_commit_job [-c master.cfg] [-r comment] -j job
	--help        : print this help
	--config file : path to master config file (db information)
	--job job     : execute job
	--release-comment ''  : comment about this release

=head2 INSTALLATION

Complete installation details are in the README and README.conf files included
with the software. It works with library available on CPAN.

=head2 AUTHOR

(C) 2004-2005 Eric Bollengier

You may reach me through the contact info at eric@eb.homelinux.org

=head2 LICENSE

    sched_validate_job, part of the network scheduling system (Sched)
    Copyright (C) 2004-2005 Eric Bollengier
        All rights reserved.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

=cut


use Sched::Job ;

my $VERSION = '$Id: sched_job_commit,v 1.1 2005/04/05 19:59:33 mcgregor Exp $' ;

$ENV{PATH} = '/bin:/usr/bin' ;

################################################################
# traitement de la ligne de commande

sub HELP_MESSAGE
{
    print "Usage : $0 [-c master.cfg] [-r comment] -j job
    --help        : print this help
    --config file : path to master config file (db information)
    --job job     : execute job
    --release-comment ''  : comment about this release
" ;
    exit (1) ;
}


################################################################
################	Variables	        ################

my $file_job = '';		# fichier xml du job
my $file_conf = "$Sched::prefix_etc/master.cfg" ;
my $comment ;

use Getopt::Long ;

GetOptions("job=s"    => \$file_job,
	   "config=s" => \$file_conf,
	   "release-comment=s" => \$comment,
	   "help"     => \&HELP_MESSAGE) ;

if (!-r $file_job) {
    print "E : job file is not readable $!\n" ;
    HELP_MESSAGE() ;
}

Sched::init("utils", $file_conf) || die "E : error in $file_conf" ;
Sched::set_serial() ;

# pas de conversion des champs dates
$Sched::Var::do_strftime = 0 ;

# first validate it
my $job = new Sched::Job(serial => $Sched::serial, file => $file_job) 
    || die "E : Error while loading $file_job" ;

my $xml = $job->{xml} ;
Sched::NS::register_id('=xml-root=', $xml) ;

$job->validate() || die "E : $file_job is not valid" ;

if (!$xml->attribute('host')) {
    print STDERR "E : $file_job doesn't have host attribute\n" ;
    die "E : this is not an network job" ;
}

if (!$comment) {
    $comment = $job->attribute('comment') || 'No comment' ;
}

# open connection to database
use DBI ;
my $dbh ;

sub rollback_and_die
{
    my $msg =  shift ;
    $dbh->rollback() ;
    die $msg ;
}

my $db_dsn = $Sched::cfg->val("master", "dsn") 
    || die "E : error can't find [master]/dsn" ;

# postgresql
$dbh = DBI->connect("DBI:Pg:$db_dsn",'', '') 
    || die "E : error of database connection" ;

#
my $md5 = Sched::Job::get_md5($file_job) ;

# recuperation de la "version" (nb de job avec le meme id)
my $req = $dbh->prepare('SELECT count(*)+1 AS ver FROM job WHERE job.id = ?') ;
$req->execute($xml->attribute('id')) ;
my ($job_version) = $req->fetchrow_array ;

$dbh->begin_work() ;
$req = $dbh->prepare('
INSERT INTO job (id,md5,host,date,comment,xml) VALUES (?,?,?,now(),?,?)');

# on stock tout le fichier dans la base
open(FP, $file_job) ;
my $xml_text = join('', <FP>) ;
close(FP) ;


$req->execute($xml->attribute("id"), 
	      $md5, 
	      $xml->attribute("host"),
	      "v$job_version : $comment",
	      $xml_text) 
    || rollback_and_die("E : Job can't be registred") ;

undef $xml_text ;

my $job_env = $job->attribute('env') || '' ;

# pb de concurence
$req = $dbh->prepare("SELECT currval('job_job_no_seq')") ;
$req->execute() ;
my ($job_no) = $req->fetchrow_array ;

$req = $dbh->prepare('INSERT INTO task (job_no,id,host,xml) VALUES (?,?,?,?)') ;

sub register_cmd
{
    my $root = shift ;
    for my $t (@{ $root->getAllChildren('task') }) {
	if ($t->attribute('host')) {
	
	    my $cmd = Sched::Cmd::get_from_sid($t->attribute('sid')) ;

	    # on recupere les variables d'environnement du pere
	    # pour les mettre devant celle du task
	    if ($job_env) {
		my $cmd_env = $cmd->attribute('env') || '' ;

		my $env = join("\n", 
			       map { $_ if ($_ !~ /^\s*$/) } 
			       split(/\n/, "$job_env\n$cmd_env")) ;

		Sched::Var::add_var('ID', $cmd->attribute('id')) ;
		$env = Sched::Var::expand($env) ;
		Sched::Var::del_var('ID') ;
		
		$cmd->attribute('env', $env) ;
	    }

	    delete $t->{_attributes}->{sid} ;
	    $req->execute($job_no,
			  $t->attribute('id'),
			  $t->attribute('host'),
			  $cmd->to_xml()) 
      	|| rollback_and_die("E : can't insert cmd " . $t->attribute('id'));
	}
	register_cmd($t) ;
    }
}

register_cmd($xml) ;

$dbh->commit() ;

print "I : OK $job_no is registred\n" ;

exit 0 ;
# EOF
