def testrefresh(self):
     adm_queue = 'mobyle'
     self.assertEqual(self.adm.getQueue(), None)
     adm = Admin(Admin.FILENAME)
     adm.setQueue(adm_queue)
     adm.commit()
     self.assertEqual(self.adm.getQueue(), None)
     self.adm.refresh()
     self.assertEqual(self.adm.getQueue(), adm_queue)
Example #2
0
    def run(self, commandLine , dirPath , serviceName , jobKey , jobState , queue , xmlEnv ):
        """
        Run the commandLine 
        redirect the standard error and output on service.name.out and service.name.err, then restore the sys.stderr and sys.stdout
        @return: the L{Mobyle.Status.Status} of this job and a message
        @rtype: Status  object
        """
        jobKey = self.getKey()
        fout = open( serviceName + ".out" , 'w' )
        ferr = open( serviceName + ".err" , 'w' )

        try:
            ## execute the commandline through your favorite execution system
            pass
        except OSError, err:
            msg= "System execution failed: " + str(err)
            self._logError( dirPath , serviceName ,jobKey,
                            userMsg = "Mobyle internal server error" ,
                            logMsg = None )
                
            _log.critical( "%s/%s : %s" %( self.serviceName ,
                                                jobKey ,
                                                msg
                                                )
                                )

            raise MobyleError , msg 
                
            adm = Admin( dirPath )
            adm.setExecutionAlias( self.execution_config_alias )  ## store the alias of execution config used for this job 
            adm.setNumber( jobKey ) ## store the key to query/retrieve this job on this system execution
            adm.commit()

            ## link the .admin file in ADMINDIR which looklike to a "process table"
            linkName = ( "%s/%s.%s" %(self. _cfg.admindir() ,
                                      serviceName ,
                                      jobKey
                                    )
                         )
            
            try:
                os.symlink(
                    os.path.join( self.dirPath , '.admin') ,
                    linkName
                    )
            except OSError , err:
                msg = "can't create symbolic link %s in ADMINDIR: %s" %( linkName , err )
                self._logError( dirPath , serviceName ,jobKey,
                                userMsg = "Mobyle internal server error" ,
                                logMsg = None )
                
                _log.critical( "%s/%s : %s" %( serviceName ,
                                               jobKey ,
                                               msg
                                            )
                                 )
                raise MobyleError , msg
 def testcommit(self):
     ## Commit should update file
     bef = os.stat(Admin.FILENAME)
     adm = Admin(Admin.FILENAME)
     adm.commit()
     aft = os.stat(Admin.FILENAME)
     self.assertTrue(bef.st_ino != aft.st_ino and bef.st_mtime <= aft.st_mtime)
     ## Cannot create/rename temporary file
     mod = os.stat(".").st_mode
     os.chmod(".", mod & ~stat.S_IWUSR)
     self.assertRaises(MobyleError, adm.commit)
     os.chmod(".", mod)
     ## Nothing to save (fails silently)
     adm.me.clear()
     adm.commit()
Example #4
0
def emailResults(cfg, userEmail, registry, ID, job_path, serviceName, jobKey, FileName=None):
    """
    @param cfg: the configuration of Mobyle    
    @type cfg: Config instance
    @param userEmail: the user email address
    @type userEmail: EmailAddress instance
    @param registry: the registry of deployed services
    @type registry: Registry.registry object
    @param ID: the ID of the job
    @type ID: string
    @param job_path: the absolute path to the job 
    @type job_path: string
    @param serviceName: the name of the service
    @type serviceName: string
    @param jobKey: the key of the job
    @type jobKey: string
    @param FileName: the absolute path of zip file to attach to the email
    @type FileName: string or None
    """
    from Mobyle.Net import Email
    from Mobyle.MobyleError import EmailError, TooBigError
    import os

    dont_email_result, maxmailsize = cfg.mailResults()
    if dont_email_result:
        return
    else:
        if userEmail:
            mail = Email(userEmail)
            jobInPortalUrl = "%s/portal.py#jobs::%s" % (cfg.cgi_url(), registry.getJobPID(ID))

            if FileName is not None:
                zipSize = os.path.getsize(FileName)
                mailDict = {
                    "SENDER": cfg.sender(),
                    "HELP": cfg.mailHelp(),
                    "SERVER_NAME": cfg.portal_url(),
                    "JOB_URL": jobInPortalUrl,
                    "RESULTS_REMAIN": cfg.remainResults(),
                    "JOB_NAME": serviceName,
                    "JOB_KEY": jobKey,
                }
                if zipSize > maxmailsize - 2048:
                    # 2048 octet is an estimated size of email headers
                    try:
                        mail.send("RESULTS_TOOBIG", mailDict)
                        return
                    except EmailError, err:
                        msg = str(err)
                        adm = Admin(job_path)
                        adm.setMessage(msg)
                        adm.commit()
                        u_log.error("%s/%s : %s" % (serviceName, jobKey, msg))
                        return
                else:
                    try:
                        mail.send("RESULTS_FILES", mailDict, files=[FileName])
                        return
                    except TooBigError, err:
                        try:
                            mail.send("RESULTS_TOOBIG", mailDict)
                        except EmailError, err:
                            msg = str(err)
                            adm = Admin(job_path)
                            adm.setMessage(msg)
                            adm.commit()
                            u_log.error("%s/%s : %s" % (serviceName, jobKey, msg))

                        return
    def run( self , commandLine , dirPath , serviceName , jobState , xmlEnv = None):
        """
        @param execution_config: the configuration of the Execution 
        @type execution_config: ExecutionConfig instance
        @param commandLine: the command to be executed
        @type commandLine: String
        @param dirPath: the absolute path to directory where the job will be executed (normaly we are already in)
        @type dirPath: String
        @param serviceName: the name of the service
        @type serviceName: string
        @param jobState:
        @type jobState: a L{JobState} instance
        """
        self.jobState = jobState
        if dirPath[-1] == '/':
            dirPath = dirPath[:-1]
        jobKey = os.path.split( dirPath )[1]
        if os.getcwd() != os.path.abspath( dirPath ):
            msg = "the child process execute itself in a wrong directory"
            self._logError( dirPath , serviceName ,jobKey,
                            userMsg = "Mobyle internal server error" ,
                            logMsg = msg  )
            raise MobyleError , msg 
        
        protectedCommandLine = ''
        for c in commandLine:
            protectedCommandLine += '\\'+ c
            
        if xmlEnv is None:
            xmlEnv = {}
            
        dispatcher = self._cfg.getDispatcher()
        queue = dispatcher.getQueue( jobState )
        adm = Admin( dirPath )
        adm.setQueue( queue )
        adm.commit()
        
        new_path = ''
        binary_path = self._cfg.binary_path()
        if binary_path :
                new_path = ":".join( binary_path )        

        if xmlEnv.has_key( 'PATH' ) :      
                new_path = "%s:%s" %( xmlEnv[ 'PATH' ] , new_path )
        if new_path :
            xmlEnv[ 'PATH' ] = "%s:%s" %( new_path , os.environ[ 'PATH' ] ) 
        else:
            xmlEnv[ 'PATH' ] = os.environ[ 'PATH' ] 
        for var in os.environ.keys():
            if var != 'PATH':
                xmlEnv[ var ] = os.environ[ var ]
        self._returncode = None
        accounting = self._cfg.accounting()
        if accounting:
            beg_time = time.time()

        ###################################
        mobyleStatus = self._run( commandLine , dirPath , serviceName , jobKey , jobState , queue , xmlEnv )
        ###################################
        
        if accounting:
            end_time = time.time()
            elapsed_time = end_time - beg_time
            a_log = getLogger( 'Mobyle.account' )
            #%d trunc time to second
            #%f for millisecond
            a_log.info("%(serviceName)s/%(jobkey)s : %(exec_class)s/%(queue)s : %(beg_time)d-%(end_time)d %(ela_time)d : %(status)s" %{ 'serviceName':serviceName ,
                                                                                                                          'jobkey':jobKey,
                                                                                                                          'exec_class':self.execution_config.execution_class_name ,
                                                                                                                          'queue': queue,
                                                                                                                          'beg_time':beg_time ,
                                                                                                                          'end_time':end_time ,
                                                                                                                          'ela_time':elapsed_time ,
                                                                                                                          'status': mobyleStatus ,
                                                                                                                          }
                                                                                                              )
        self.status_manager.setStatus( dirPath , mobyleStatus )
Example #6
0
     msg= "SGE execution failed: "+ str(err)
     self._logError( dirPath , serviceName , jobKey ,
                    admMsg = msg ,
                     userMsg = "Mobyle internal server error" ,
                     logMsg = None )
     _log.critical( "%s/%s : %s" %( serviceName ,
                                    jobKey ,
                                    msg
                                    ) ,
                     exc_info = True
                   )
     raise MobyleError , msg
 adm = Admin( dirPath )
 adm.setExecutionAlias( self.execution_config_alias  )
 adm.setNumber( jobKey )
 adm.commit()
 linkName = ( "%s/%s.%s" %( self._cfg.admindir() ,
                            serviceName ,
                            jobKey
                            )
                            )
 try:
     os.symlink(
                os.path.join( dirPath , '.admin') ,
                linkName
                )
 except OSError , err:
     msg = "can't create symbolic link %s in ADMINDIR: %s" %( linkName , err )
     self._logError( dirPath , serviceName , jobKey ,
                     admMsg = msg ,
                     userMsg = "Mobyle internal server error" ,
def over_limit(job):
    """
    check if the user (same email) has a similar job (same command line or same workflow name) running
    @param job: the job to check before to submit it to Execution
    @type job: L{Job} instance
    @raise UserValueError: if the number of similar jobs exceed the Config.SIMULTANEOUS_JOBS
    """
    from hashlib import md5
    import glob
    from Mobyle.Admin import Admin
    from Mobyle.MobyleError import UserValueError, MobyleError

    max_same_jobs = job.cfg.max_similar_job_per_user()
    max_user_jobs = job.cfg.max_job_per_user()

    user_email = str(job.getEmail())
    newMd5 = md5()
    newMd5.update(job.getCommandLine())
    newDigest = newMd5.hexdigest()

    work_dir = job.getDir()
    thisJobAdm = Admin(work_dir)
    thisJobAdm.setMd5(newDigest)
    thisJobAdm.commit()

    if thisJobAdm.getWorkflowID():
        # this job is a subtask of a workflow
        # we allow a workflow to run several identical job in parallel
        return True
    mask = os.path.normpath("%s/*.*" % (job.cfg.admindir()))
    jobs = glob.glob(mask)

    same_jobs_nb = 0
    jobs_nb = 0
    msg = None
    for one_job in jobs:
        try:
            oldAdm = Admin(one_job)
        except MobyleError, err:
            if os.path.lexists(one_job):
                p_log.critical("%s/%s: invalid job in ADMINDIR : %s" % (job.getServiceName(), job.getKey(), err))
            continue
        if (oldAdm.getWorkflowID()):
            # this job is NOT a workflow but
            # this job is the "same" than a workflow subtasks
            # we allow a workflow to run several identical job in parallel
            continue
        old_email = oldAdm.getEmail()
        oldDigest = oldAdm.getMd5()
        if user_email == old_email:
            oldStatus = job.getStatus()
            if oldStatus.isEnded():
                p_log.debug("oldStatus.isEnded() = True")
                continue
            jobs_nb += 1
            if max_user_jobs and jobs_nb >= max_user_jobs:
                msg = "%d jobs (%s) have been already submitted (md5 = %s)" % (jobs_nb,
                                                                               os.path.basename(one_job),
                                                                               newDigest
                                                                               )
                userMsg = " %d job(s) have been already submitted, and are(is) not finished yet. Please wait for the end of these jobs before you resubmit." % (
                jobs_nb)
                p_log.warning(msg + " : run aborted ")
                raise UserValueError(parameter=None, msg=userMsg)
            if newDigest == oldDigest:
                same_jobs_nb += 1
                if max_same_jobs and same_jobs_nb >= max_same_jobs:
                    msg = "%d similar jobs (%s) have been already submitted (md5 = %s)" % (
                        same_jobs_nb,
                        os.path.basename(one_job),
                        newDigest
                    )
                    userMsg = " %d similar job(s) have been already submitted, and are(is) not finished yet. Please wait for the end of these jobs before you resubmit." % (
                    same_jobs_nb)
                    p_log.warning(msg + " : run aborted ")
                    raise UserValueError(parameter=None, msg=userMsg)