#! /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.
##
##**************************************************************


BEGIN {$^W = 1;}
use strict;

	# Seconds between updates.
my $SLEEP_TIME = 30;
my $DEBUG_LEVEL;
my $LOG_DIR;

chomp( $DEBUG_LEVEL = int ( `condor_config_val GLITE_CONDORC_DEBUG_LEVEL` ) );
if ( $? != 0 ) {
	$DEBUG_LEVEL = 10;
}

chomp( $LOG_DIR = `condor_config_val GLITE_CONDORC_LOG_DIR` );
if ( $? != 0 || ! -d $LOG_DIR ) {
	$LOG_DIR = "/tmp";
}

# We need to use our host cert to authenticate with the remote collectors
$ENV{"X509_USER_CERT"} = $ENV{"GLITE_HOST_CERT"};
$ENV{"X509_USER_KEY"} = $ENV{"GLITE_HOST_KEY"};

exit main();

sub main {
	while(1) {
		debug_print(10, "#################\n");
		my(@ads) = get_machine_ads();
		if(@ads == 0) {
			debug_print(3, "No machines to advertise\n");
		}
		publish_ads(@ads);
		@ads = rewrite_machine_ads(@ads);
		publish_ads(@ads);
		if(getppid() == 1) {
	        debug_print(10, "My parent disappeared.  Assuming he exitted.  Quitting\n");
   	    	exit(1);
		}
		sleep($SLEEP_TIME);
	}
}

sub get_hostnames {
	local *IN;
	my @all_hostnames;
	my @uniq_hostnames;
	# TODO The location of ismdump.fl can be overridden in
	#   $GLITE_LOCATION/etc/glite_wms.conf
	if ( ! open(IN, "<$ENV{GLITE_LOCATION_VAR}/workload_manager/ismdump.fl") ) {
		debug_print( 1, "Failed to open $ENV{GLITE_LOCATION_VAR}/workload_manager/ismdump.fl\n" );
		return;
	}
	while ( <IN> ) {
		if ( s|^\s*CEid *= *\"([^\s:\/]+).*voblah.*\";\s*$|$1| ) {
			print "Found match: $_\n";
			push @all_hostnames, $_;
		}
	}
	close ( IN );
	@all_hostnames = sort @all_hostnames;
	for ( @all_hostnames ) {
		if ( $_ ne $uniq_hostnames[-1] ) {
			push @uniq_hostnames, $_;
		}
	}
	return @uniq_hostnames;
}

sub get_machine_ads {
	local *IN;
	my @ads;
	my @hosts = get_hostnames();
	if ( @hosts == 0 ) {
		return;
	}
	for ( @hosts ) {
		# This will grab all of the ads from the remote collectors, not
		# just those for our VO. The jobs' requirements better contain a
		# clause asking for the right VO.
		if ( !open( IN, "condor_status -pool $_ -schedd -l |" ) ) {
			debug_print( 1, "unable to open condor_status\n" );
			return;
		}
		local $/ = "\n\n";
		my(@host_ads) = <IN>;
		foreach my $ad (@host_ads) {
			if($ad =~ /^\s*$/) {
				next;
			}
			my(%keyvals) = ($ad =~ /(.+?) = (.+)/g);
			push @ads, \%keyvals;
		}
	}
	close( IN );
	return @ads;
}

sub rewrite_machine_ads {
	my (@ads) = @_;
	foreach my $ad (@ads) {
		debug_print(3, "Rewriting $ad->{Name}\n");
		$ad->{StartdIpAddr} = $ad->{ScheddIpAddr};
		$ad->{MyType} = '"Machine"';
		$ad->{TargetType} = '"Job"';
		$ad->{CondorCAd} = 1;
		$ad->{UpdateSequenceNumber} = time();
		$ad->{OpSys} = '"CondorC"';
		$ad->{Arch} = '"CondorC"';
		$ad->{Activity} = '"Idle"';
		$ad->{State} = '"Unclaimed"';
		$ad->{WantAdRevaluate} = 'True';
		if(not exists $ad->{Requirements} and not exists $ad->{REQUIREMENTS}) {
			debug_print(4, "    Setting requirements true\n");
			$ad->{Requirements} = 'TRUE';
		}
		if(exists $ad->{REQUIREMENTS}) {
			$ad->{START} = $ad->{REQUIREMENTS};
		} else {
			$ad->{START} = $ad->{Requirements};
		}
		#$ad->{Rank} = '0.000000';
		#$ad->{CurrentRank} = '0.000000';
		#$ad->{WantAdRevalute} = 'True';
		#$ad->{CurMatches} = '0';
		#$ad->{MaxMatches} = '2';
		#$ad->{Requirements} = 'CurMatches < MaxMatches';
			#Arch OpSys 
		my(@DELETES) = qw(
			UpdatesHistory UpdatesLost UpdatesSequenced UpdatesTotal
			ScheddIpAddr LastHeardFrom
			);
		foreach my $delete (@DELETES) {
			delete $ad->{$delete};
		}
	}
	return @ads;
}

sub publish_ads {
	my (@ads) = @_;
	local *OUT;
	my $tempfile = "/$LOG_DIR/condorcad.tmp.$$.$>";
	my $ad_type;
	foreach my $ad (@ads) {
		my(%ad) = %{$ad};

		if( ! open OUT, ">$tempfile" ) {
			debug_print( 1, "Publish failed, unable to write to $tempfile.\n" );
			return;
		}

		# Yes, there are other types of ads, but we don't care about them
		# here.
		if ( $ad{MyType} =~ /^\"?Scheduler\"?$/ ) {
			$ad_type = "UPDATE_SCHEDD_AD";
		} else {
			$ad_type = "UPDATE_STARTD_AD";
		}

		my $name = $ad{Name};
		print OUT "MyType = $ad{MyType}\n";
		delete $ad{MyType};
		print OUT "TargetType = $ad{TargetType}\n";
		delete $ad{TargetType};
		foreach my $key (sort keys %ad) {
			print OUT "$key = $ad{$key}\n";
		}

		close OUT;
		system("cat $tempfile\n");
		my $ret = system("condor_advertise", $ad_type, $tempfile);
		debug_print(1,"Advertising $name\n");
		if($ret != 0) {
			debug_print( 1, "condor_advertise failed!\n" );
		}
		unlink($tempfile);
	}
}

sub debug_print {
	my($level) = shift;
	if($level > $DEBUG_LEVEL) { return; }
	print tersedate();
	print " ";
	print @_;
}

sub tersedate {
	 my ($sec,$min,$hour,$mday,$mon,$year) = localtime(time);
	 return sprintf "%04d-%02d-%02d %02d:%02d:%02d",
	 	$year + 1900, $mon + 1, $mday, $hour, $min, $sec;
}
