#! /usr/bin/python

import os, sys, getopt

if not os.environ.has_key( 'MOBYLEHOME' ):
    sys.exit( "MOBYLEHOME must be defined in your environment." )

if ( os.path.join( os.environ[ 'MOBYLEHOME' ] ) ) not in sys.path:
    sys.path.append( os.environ[ 'MOBYLEHOME' ] )
if ( os.path.join( os.environ['MOBYLEHOME'] , 'Src' ) ) not in sys.path:    
    sys.path.append( os.path.join( os.environ['MOBYLEHOME'] , 'Src' ) )

import string
import types
import glob

from Mobyle import RunnerChild
from Mobyle.Utils import Admin
from Mobyle.MobyleError import MobyleError
import Local.Config.Config

def killJobs( keys ):
    """
    kill the job corresponding to the keys
    @param keys: the keys of the job to kill
    @type keys: list of strings
    """
    errors = []

    for key in keys:

        if len( key ) == 15  and key[0] in string.ascii_uppercase :
            try:
                int( key[1:] )
            except ValueError:
                errors.append( ( key , "invalid key" ) )
                continue
            else:
                if os.path.exists( Local.Config.Config.RESULTS_PATH ): 
                    results_path = os.path.realpath( Local.Config.Config.RESULTS_PATH )
                else:
                    msg = "RESULTS_PATH : " + str( Local.Config.Config.RESULTS_PATH ) + " no such directory."
                    raise Mobyle.MobyleError.ConfigError , msg
                
                search = "%s/ADMINDIR/*.%s" %( results_path , key )
                admins = glob.glob( search )
                
                if len( admins ) == 1 :
                    adminPath = admins[0]
                elif len( admins ) == 0:
                    errors.append( ( key , "no running job with key : " + key  ) )
                    continue
                else:
                    raise MobyleError , "there is more than 1 running job with the same key : " + key 
            try:
                adm = Admin( adminPath )
            except MobyleError , err :
                errors.append( ( key , "invalid key" ) )
                continue
        
            batch = adm.getBatch()
            jobNum = adm.getNumber()
            job = adm.getJobName() + "/" + key 
            
            if jobNum is None:
                # an error occured on this jobID but I continue to kill the other jobIDs
                errors.append( ( job , 'no jobNum for this job' ) )
                continue

            try:
                try:
                    killer = "RunnerChild.%s.kill( '%s' )" %( batch , jobNum )
                    eval( killer )
                except ( NameError , AttributeError ) , err:
                    errors.append( ( job , "unknown batch \""+ batch +"\" " ) )
                    continue
                except Exception , err :
                    errors.append( ( job , str( err )  ) )
                    continue
                    
            except MobyleError ,err :
                errors.append( ( job , str( err ) ) )

        else: # len(key) != 15
            errors.append( ( key , "invalid key" ) )
            continue

    if errors:
        msg = ''
        for job , msgErr in errors :
            msg = "%s Mkill( %s ) - %s\n" %( msg , job , msgErr )

        raise MobyleError , msg

if __name__ == '__main__':

    def usage():
        print """
        usage: mkill jobKeys  ... 
    
        option:
            -h or --help  ... Print this message and exit.
        """

    # ===== command line parser
    try:
        opts, args = getopt.gnu_getopt( sys.argv[1:], "h", ["help"] )
    
        for option , value in opts: 
    
            if option in ( "-h","--help" ):
                usage()
                sys.exit( 0 )
    
        if not args:
            usage()
            sys.exit( 1 )
            
    except getopt.GetoptError:
            print usage()
            sys.exit( 1 )
    
    # ===== killer
    try:
        killJobs( args )
    except MobyleError , err:
        print >> sys.stderr , err
        sys.exit( 2 )
