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)
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()
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 )
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)