#! /usr/bin/env python

#############################################################
#                                                           #
#   Author: Bertrand Neron                                  #
#   Organization:'Biological Software and Databases' Group, #
#                Institut Pasteur, Paris.                   #
#   Distributed under GPLv2 Licence. Please refer to the    #
#   COPYING.LIB document.                                   #
#                                                           #
#############################################################

import os, sys, getopt

MOBYLEHOME = None
if os.environ.has_key('MOBYLEHOME'):
    MOBYLEHOME = os.environ['MOBYLEHOME']
if not MOBYLEHOME:
    sys.exit('MOBYLEHOME must be defined in your environment')

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

from string import ascii_uppercase
import glob

from Mobyle.Utils import Admin , executionClassLoader , Status
from Mobyle.MobyleError import MobyleError
from Mobyle.JobState import JobState

from Mobyle.ConfigManager import 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 ascii_uppercase :
            try:
                int( key[1:] )
            except ValueError:
                errors.append( ( key , "invalid key" ) )
                continue
            else:
                config = Config()
                search = "%s/*.%s" %( config.admindir() , key )
                admins = glob.glob( search )
                
                if len( admins ) == 1 :
                    adminPath = os.path.realpath( 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
            
            jobID = adm.getJobID()
            jobState = JobState( uri=jobID )
            batch = adm.getBatch()
            jobNum = adm.getNumber()
            job = adm.getJobName() + "/" + key 
#            
            if jobID is None:
                # an error occured on this jobID but I continue to kill the other jobIDs
                errors.append( ( job , 'no jobID for this job' ) )
                continue

            try:
                
                try:
                    execKlass = executionClassLoader( jobID = jobID )
                    execKlass.kill( jobNum )
                    
                    killed = Status( code= 6 , message = "Your job has been cancelled" )               
                    adm.setStatus( killed ) 
                    adm.commit()
                    jobState.setStatus( killed )
                    jobState.commit()
                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 )
