#! /usr/bin/env perl
##**************************************************************
##
## Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
## University of Wisconsin-Madison, WI.
## 
## Licensed under the Apache License, Version 2.0 (the "License"); you
## may not use this file except in compliance with the License.  You may
## obtain a copy of the License at
## 
##    http://www.apache.org/licenses/LICENSE-2.0
## 
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
##**************************************************************

use warnings;
use strict;

# Update the module include path
BEGIN
{
    my $Dir = $0;
    if ( $Dir =~ /(.*)\/.*/ )
    {
	push @INC, "$1";
    }
}
use HawkeyePublish;
use HawkeyeLib;
use File::Temp qw/ :mktemp /;

# Prototypes
sub Init( );
sub RunIt ( );

# Setup the hawkeye stuff
my $Hawkeye;

# Config info
my %Config = (
	      Description	=> "",
	      NumContacts	=> 0,
	      CondorHost	=> "",
	      Probe		=> "GridProbe.pl",
	      TmpDir		=> "",
	      GlobusDir		=> "",
	      LogFile		=> "",
	      CondorPath	=> "",
	      NoExecute		=> 0,
	      RemoveScript	=> 1,
	      CleanLog		=> 0,
	      TestInFile	=> "",
	     );

# Do it
Init();
RunIt();


# #############################
# Initialize
# #############################
sub Init (){
    HawkeyeLib::DoConfig( );

    # Process command line..
    foreach my $Arg ( @ARGV )
    {
	if ( $Arg =~ /^-n$/ )
	{
	    $Config{NoExecute} = 1;
	}
	elsif ( $Arg =~ /^-k$/ )
	{
	    $Config{RemoveScript} = 0;
	}
	elsif ( $Arg =~ /^-c$/ )
	{
	    $Config{CleanLog} = 1;
	}
	elsif ( $Arg =~ /^-t=(.+)$/ )
	{
	    $Config{TestInFile} = $1;
	}
	else
	{
	    print STDERR "$0 Warning: Ignoring unknown argment \"$Arg\"\n";
	    print STDERR "usage: $0 name [-n] [-k] [-c]\n";
	    print STDERR "\t-n\tNo execute\n";
	    print STDERR "\t-k\tKeep script after execution\n";
	    print STDERR "\t-c\tClean log\n";
	}
    }

    # Setup Hawkeye output
    $Hawkeye = HawkeyePublish->new;
    $Hawkeye->Quiet( 1 );
    $Hawkeye->AutoIndexSet( 0 );

    # Try getting a list of contacts...
    my $NumContacts = 0;
    my $ContactList = HawkeyeLib::ReadConfig(  "_Contacts", "" );
    if ( ( ! defined $ContactList ) || ( $ContactList eq "" )  )
    {
	print STDERR "No valid Globus contact string found!!\n";
	exit 1;
    }
    # Walk through the list of contact logical names
    foreach my $Name ( split(/,/, $ContactList ) )
    {
	my $String =
	    HawkeyeLib::ReadConfig( "_" . $Name . "_Contact", "" );
	if ( ( ! defined $String ) || ( $String eq "" )  )
	{
	    print STDERR "Warning: No contact for $Name; ignoring\n";
	    next;
	}
	$Config{ContactStrings}{$Name} = $String;
	$NumContacts++;
    }

    # Any contacts?
    if ( 0 == $NumContacts )
    {
	print STDERR "No valid Globus contact string found!!\n";
	exit 1;
    }

    # Condor config var
    my $Condor = HawkeyeLib::ReadConfig( "_condor_config", "" );
    if ( ( defined $Condor ) && ( $Condor ne "" )  )
    {
	$Condor =~ s/\s//g;
	$ENV{CONDOR_CONFIG} = $Condor;
    }
    my $CondorPath = HawkeyeLib::ReadConfig( "_condor_path", "" );
    if ( ( defined $CondorPath ) && ( $CondorPath ne "" )  )
    {
	$CondorPath =~ s/\s//g;
	$Config{CondorPath} = $CondorPath;
    }

    # Globus location
    my $Globus = HawkeyeLib::ReadConfig( "_globus_location", "" );
    if ( ( defined $Globus ) && ( $Globus ne "" )  )
    {
	$Globus =~ s/\s//g;
	$ENV{GLOBUS_LOCATION} = $Globus;
    }
    if ( ( ! defined $ENV{GLOBUS_LOCATION} ) ||
	 ( $ENV{GLOBUS_LOCATION} eq "" ) )
    {
	print STDERR "No GLOBUS_LOCATION\n";
	exit 1;
    }

    # Grid cert
    my $X509 = HawkeyeLib::ReadConfig( "_X509_CERT_DIR", "" );
    if ( ( defined $X509 ) && ( $X509 ne "" )  )
    {
	$X509 =~ s/\s//g;
	$ENV{X509_CERT_DIR} = $X509;
    }

    # Get the Globus path info..
    my $Path;
    $Path = HawkeyeLib::ReadConfig( "_Path", "" );
    if ( ( defined $Path ) && ( $Path ne "" )  )
    {
	$Path = $Path . ":" if ( ! $Path =~ /:$/ );
	$Path =~ s/\s//g;
	$ENV{PATH} = $Path . $ENV{PATH};
	print STDERR "Path now $ENV{PATH}\n";
    }

    # A textual description of what we're monitoring..
    $Config{Description} = HawkeyeLib::ReadConfig( "_description", "" );

    # Condor host for condor_status
    $Config{CondorHost} = HawkeyeLib::ReadConfig( "_condor_host", "" );

    # Temp directory to use for submissions..
    $Config{TmpDir} = HawkeyeLib::ReadConfig( "_TmpDir", "" );

    # Other probe arguments (usually --skip-*)
    $Config{ProbeArgs} = HawkeyeLib::ReadConfig( "_ProbeArgs", "" );

    # The probe itself...
    $Config{Probe} = HawkeyeLib::ReadConfig( "_Probe", "" );

    # The user's globus directory
    $Config{GlobusDir} = HawkeyeLib::ReadConfig( "_GlobusDir", "" );

    # Logging
    $Config{LogFile} = HawkeyeLib::ReadConfig( "_LogFile", "" );
    if ( $Config{LogFile} ne "" )
    {
	print STDERR "Logging to $Config{LogFile}\n";
    }
}

# #############################
# Do the real work here...
# #############################
sub RunIt ( )
{
    my %Fields;
    my %GlobalFields;

    # ###############################################
    # Create the script to actually run the probe
    my ($Fh, $File) = mkstemp( "/tmp/tmpfileXXXXX" );
    local(*FH) = $Fh;
    my $ProbeCmd;
    $ProbeCmd = "$Config{Probe} --non-stop ";

    # Add contacts
    foreach my $Contact ( keys %{$Config{ContactStrings}} )
    {
	my $ContactString = $Config{ContactStrings}{$Contact};
	$ProbeCmd .= " --contact \"$ContactString\"";
    }

    # Other random args
    $ProbeCmd .= " --tmpdir \"$Config{TmpDir}\"" if ( $Config{TmpDir} ne "" );
    $ProbeCmd .= " --globusdir \"$Config{GlobusDir}\""
	if ( $Config{GlobusDir} ne "" );
    $ProbeCmd .= " --condor \"$Config{CondorHost}\""
	if ( $Config{CondorHost} ne "" );
    $ProbeCmd .= " $Config{ProbeArgs} ";

    # Build the temp file (that we'll execute below)
    print FH "GLOBUS_LOCATION=$ENV{GLOBUS_LOCATION}\n";
    print FH "export GLOBUS_LOCATION\n";
    print FH "source $ENV{GLOBUS_LOCATION}/etc/globus-user-env.sh\n";
    print FH "PATH=$Config{CondorPath}:\$PATH; export PATH\n"
	if ( $Config{CondorPath} ne "" );
    print FH "echo \$PATH\n";
    print FH "$ProbeCmd\n";
    close( FH );

    # Check for NoExecute option (for testing!!)
    if ( $Config{NoExecute} )
    {
	print STDERR "Script name '$File'\n";
	system( "cat $File" );
	exit 0;
    }

    # Log file handling
    my $Log = 0;
    if ( $Config{LogFile} ne "" )
    {
	unlink( $Config{LogFile} ) if ( $Config{CleanLog} );
	if ( ! open( LOG, ">>$Config{LogFile}" ) )
	{
	    print STDERR "Can't log to $Config{LogFile}\n";
	}
	else
	{
	    $Log = 1;
	    my $oldfh = select( LOG ); $| = 1; select $oldfh;
	    if ( open( TMP, $File ) )
	    {
		print LOG "============================================\n";
		$_ = `/bin/date`; chomp; print LOG "Started at $_\n";
		print LOG "-- Begin $File --\n";
		while( <TMP> )
		{
		    print LOG;
		}
		close( TMP );
		print LOG "-- End $File --\n";
	    }
	    print LOG "Path now $ENV{PATH}\n";
	}
    }

    # Run the script, and wade through its (wordy) output
    my $OpenFailed = 0;
    if ( $Config{TestInFile} ne "" )
    {
	if ( ! open( PROBE, $Config{TestInFile} )  )
	{
	    print STDERR "Failed to open debug input '$Config{TestInFile}'\n";
	    $OpenFailed = 1;
	}
	print STDERR "Reading log from '$Config{TestInFile}'\n";
    }
    elsif ( ! open( PROBE, "/bin/sh $File|" ) )
    {
	print STDERR "Failed to run probe $File!\n";
	$OpenFailed = 1;
    }

    # If ok, then go ahead and read....
    if ( ! $OpenFailed )
    {
	while ( <PROBE> )
	{
	    print LOG if ( $Log );
	    chomp;
	    if ( /^\s+test suite (\w+): (\w+)\s*(.*)/ )
	    {
		my $Test = $1;
		my $Status = $2;
		my $Description = $3;
		$Fields{$Test} = $Test; # All we need is the test name

		$Hawkeye->Store( $Test, $Status );
		if ( ( defined $Description ) && ( $Description ne "" ) )
		{
		    $Description =~ s/^\"/\\\"/;
		    $Description =~ s/([^\\])\"/$1\\\"/g;
		    $Hawkeye->Store( $Test . "Text",
				     $Description );
		}
		else
		{
		    $Hawkeye->Store( $Test . "Text", "none" );
		}
		$Fields{$Test."Text"} = "";
	    }
	    elsif ( /^\s+test:\s*(\S+)\/\[(\S+)=\"(.*)\"\]:\s*(\S+)\s+(.*)/ )
	    {
		my $Test = $1;
		my $Type = $2;
		my $Value = $3;
		my $Status = $4;
		my $Text = $5;

		# All I know about are contacts..
		if ( $Type ne "contact" )
		{
		    print STDERR "Unknown test type \"$Type\"\n";
		    print STDERR "Ignoring '$_'\n";
		}
		# Find the matching contact string, get logical name
		my $Matched = 0;
		foreach my $Contact ( keys %{$Config{ContactStrings}} )
		{
		    my $ContactString = $Config{ContactStrings}{$Contact};
		    next if ( $ContactString ne $Value );
		    $Hawkeye->Store( $Test . "_" . $Contact, $Status );
		    $Text = "none" if ( $Text eq "" );
		    my $tmp = $Text;
		    $Text =~ s/^\"/\\\"/;
		    $Text =~ s/([^\\])\"/$1\\\"/g;
		    $Hawkeye->Store( $Test . "Text" . "_" . $Contact, $Text );
		    $GlobalFields{$Test} = $Test;
		    $Matched = 1;
		}
		print STDERR "Unknown contact string '$Value'; ignoring\n"
		    if ( ! $Matched );
	    }
	}
	close( PROBE );
    }

    # Kill the temp script we made...
    if( $Config{RemoveScript} )
    {
	unlink( $File );
    }

    # Close log
    if ( $Log )
    {
	$_ = `/bin/date`; chomp; print LOG "Finished at $_\n";
	print LOG "============================================\n";
	close( LOG );
    }

    # Store the contact info...
    foreach my $Contact ( keys %{$Config{ContactStrings}} )
    {
	# Store this contact & string...
	my $ContactString = $Config{ContactStrings}{$Contact};
	$Hawkeye->Store( "Contact_" . $Contact, $ContactString );
	$Hawkeye->StoreIndex( "Contact_" . $Contact );
    }
    $Hawkeye->Store( "Contacts", join(" ", keys %{$Config{ContactStrings}} ) );
    $Hawkeye->Store( "GlobalFields", join( " ", keys ( %GlobalFields ) ) );

    # Plug in the descriptive text (if provided)
    $Hawkeye->Store( "Description", $Config{Description} )
	if ( $Config{Description} ne "" );

    # Create fields
    $Hawkeye->Store( "FIELDS" , join( " ", keys(%Fields) )  );

    # Let 'er rip!
    $Hawkeye->Publish( );
}
