def main(g_params):#{{{ submitjoblogfile = "%s/submitted_seq.log"%(path_log) runjoblogfile = "%s/runjob_log.log"%(path_log) finishedjoblogfile = "%s/finished_job.log"%(path_log) if not os.path.exists(path_cache): os.mkdir(path_cache) loop = 0 while 1: if os.path.exists("%s/CACHE_CLEANING_IN_PROGRESS"%(path_result)):#pause when cache cleaning is in progress continue # load the config file if exists configfile = "%s/config/config.json"%(basedir) config = {} if os.path.exists(configfile): text = myfunc.ReadFile(configfile) config = json.loads(text) if rootname_progname in config: g_params.update(config[rootname_progname]) if os.path.exists(black_iplist_file): g_params['blackiplist'] = myfunc.ReadIDList(black_iplist_file) os.environ['TZ'] = g_params['TZ'] time.tzset() avail_computenode = webcom.ReadComputeNode(computenodefile) # return value is a dict g_params['vip_user_list'] = myfunc.ReadIDList2(vip_email_file, col=0) num_avail_node = len(avail_computenode) webcom.loginfo("loop %d"%(loop), gen_logfile) isOldRstdirDeleted = False if loop % g_params['STATUS_UPDATE_FREQUENCY'][0] == g_params['STATUS_UPDATE_FREQUENCY'][1]: qdcom.RunStatistics_basic(webserver_root, gen_logfile, gen_errfile) isOldRstdirDeleted = webcom.DeleteOldResult(path_result, path_log, gen_logfile, MAX_KEEP_DAYS=g_params['MAX_KEEP_DAYS']) webcom.CleanServerFile(path_static, gen_logfile, gen_errfile) if 'DEBUG_ARCHIVE' in g_params and g_params['DEBUG_ARCHIVE']: webcom.loginfo("Run ArchiveLogFile, path_log=%s, threshold_logfilesize=%d"%(path_log, threshold_logfilesize), gen_logfile) webcom.ArchiveLogFile(path_log, threshold_logfilesize=threshold_logfilesize) qdcom.CreateRunJoblog(loop, isOldRstdirDeleted, g_params) # Get number of jobs submitted to the remote server based on the # runjoblogfile runjobidlist = myfunc.ReadIDList2(runjoblogfile,0) remotequeueDict = {} for node in avail_computenode: remotequeueDict[node] = [] for jobid in runjobidlist: rstdir = "%s/%s"%(path_result, jobid) remotequeue_idx_file = "%s/remotequeue_seqindex.txt"%(rstdir) if os.path.exists(remotequeue_idx_file): content = myfunc.ReadFile(remotequeue_idx_file) lines = content.split('\n') for line in lines: strs = line.split('\t') if len(strs)>=5: node = strs[1] remotejobid = strs[2] if node in remotequeueDict: remotequeueDict[node].append(remotejobid) cntSubmitJobDict = {} # format of cntSubmitJobDict {'node_ip': [INT, INT, STR]} for node in avail_computenode: queue_method = avail_computenode[node]['queue_method'] num_queue_job = len(remotequeueDict[node]) if num_queue_job >= 0: cntSubmitJobDict[node] = [num_queue_job, g_params['MAX_SUBMIT_JOB_PER_NODE'], queue_method] else: cntSubmitJobDict[node] = [g_params['MAX_SUBMIT_JOB_PER_NODE'], g_params['MAX_SUBMIT_JOB_PER_NODE'], queue_method] # entries in runjoblogfile includes jobs in queue or running hdl = myfunc.ReadLineByBlock(runjoblogfile) if not hdl.failure: lines = hdl.readlines() while lines != None: for line in lines: strs = line.split("\t") if len(strs) >= 11: jobid = strs[0] email = strs[4] try: numseq = int(strs[5]) except: numseq = 1 try: numseq_this_user = int(strs[10]) except: numseq_this_user = 1 rstdir = "%s/%s"%(path_result, jobid) finishtagfile = "%s/%s"%(rstdir, "runjob.finish") status = strs[1] webcom.loginfo("CompNodeStatus: %s"%(str(cntSubmitJobDict)), gen_logfile) runjob_lockfile = "%s/%s/%s.lock"%(path_result, jobid, "runjob.lock") if os.path.exists(runjob_lockfile): msg = "runjob_lockfile %s exists, ignore the job %s" %(runjob_lockfile, jobid) webcom.loginfo(msg, gen_logfile) continue #if IsHaveAvailNode(cntSubmitJobDict): if not g_params['DEBUG_NO_SUBMIT']: qdcom.SubmitJob(jobid, cntSubmitJobDict, numseq_this_user, g_params) qdcom.GetResult(jobid, g_params) # the start tagfile is written when got the first result qdcom.CheckIfJobFinished(jobid, numseq, email, g_params) lines = hdl.readlines() hdl.close() myfunc.WriteFile("sleep for %d seconds\n"%(g_params['SLEEP_INTERVAL']), gen_logfile, "a", True) time.sleep(g_params['SLEEP_INTERVAL']) loop += 1 return 0
def main(g_params): #{{{ argv = sys.argv numArgv = len(argv) if numArgv < 2: PrintHelp() return 1 rmsg = "" outpath = "" jobid = "" datapath = "" numseq = -1 numseq_this_user = -1 email = "" host_ip = "" base_www_url = "" i = 1 isNonOptionArg = False while i < numArgv: if isNonOptionArg == True: webcom.loginfo("Error! Wrong argument: %s" % (argv[i]), gen_errfile) return 1 isNonOptionArg = False i += 1 elif argv[i] == "--": isNonOptionArg = True i += 1 elif argv[i][0] == "-": if argv[i] in ["-h", "--help"]: PrintHelp() return 1 elif argv[i] in ["-outpath", "--outpath"]: (outpath, i) = myfunc.my_getopt_str(argv, i) elif argv[i] in ["-email", "--email"]: (email, i) = myfunc.my_getopt_str(argv, i) elif argv[i] in ["-host", "--host"]: (host_ip, i) = myfunc.my_getopt_str(argv, i) elif argv[i] in ["-nseq", "--nseq"]: (numseq, i) = myfunc.my_getopt_int(argv, i) elif argv[i] in ["-nseq-this-user", "--nseq-this-user"]: (numseq_this_user, i) = myfunc.my_getopt_int(argv, i) elif argv[i] in ["-baseurl", "--baseurl"]: (base_www_url, i) = myfunc.my_getopt_str(argv, i) elif argv[i] in ["-jobid", "--jobid"]: (jobid, i) = myfunc.my_getopt_str(argv, i) elif argv[i] in ["-datapath", "--datapath"]: (datapath, i) = myfunc.my_getopt_str(argv, i) elif argv[i] in ["-force", "--force"]: g_params['isForceRun'] = True i += 1 elif argv[i] in ["-only-get-cache", "--only-get-cache"]: g_params['isOnlyGetCache'] = True i += 1 elif argv[i] in ["-q", "--q"]: g_params['isQuiet'] = True i += 1 else: webcom.loginfo("Error! Wrong argument: %s" % (argv[i]), gen_errfile) return 1 else: webcom.loginfo("Error! Wrong argument: %s" % (argv[i]), gen_errfile) return 1 if outpath == "": webcom.loginfo("outpath not set. exit", gen_errfile) return 1 elif not os.path.exists(outpath): cmd = ["mkdir", "-p", outpath] try: rmsg = subprocess.check_output(cmd, stderr=subprocess.STDOUT) except subprocess.CalledProcessError as e: print(e) print(rmsg) return 1 if jobid == "": webcom.loginfo("%s: jobid not set. exit" % (sys.argv[0]), gen_errfile) return 1 if datapath == "": webcom.loginfo("%s: datapath not set. exit" % (sys.argv[0]), gen_errfile) return 1 elif not os.path.exists(datapath): webcom.loginfo("%s: datapath does not exist. exit" % (sys.argv[0]), gen_errfile) return 1 elif not os.path.exists("%s/query.fa" % (datapath)): webcom.loginfo( "%s: file %s/query.fa does not exist. exit" % (sys.argv[0], datapath), gen_errfile) return 1 g_params['debugfile'] = "%s/debug.log" % (outpath) webcom.loginfo("Go to SubmitJobToQueue()", g_params['debugfile']) return SubmitJobToQueue(jobid, datapath, outpath, numseq, numseq_this_user, email, host_ip, base_www_url)
def SubmitJobToQueue( jobid, datapath, outpath, numseq, numseq_this_user, email, #{{{ host_ip, base_www_url): myfunc.WriteFile("Entering SubmitJobToQueue()\n", g_params['debugfile'], "a", True) fafile = "%s/query.fa" % (datapath) if numseq == -1: numseq = myfunc.CountFastaSeq(fafile) if numseq_this_user == -1: numseq_this_user = numseq query_parafile = "%s/query.para.txt" % (outpath) query_para = {} content = myfunc.ReadFile(query_parafile) para_str = content if content != "": query_para = json.loads(content) try: name_software = query_para['name_software'] except KeyError: name_software = "prodres" runjob = "%s %s/run_job.py" % (python_exec, rundir) scriptfile = "%s/runjob,%s,%s,%s,%s,%d.sh" % ( outpath, name_software, jobid, host_ip, email, numseq) code_str_list = [] code_str_list.append("#!/bin/bash") code_str_list.append("source %s/bin/activate" % (virt_env_path)) cmdline = "%s %s -outpath %s -tmpdir %s -jobid %s " % ( runjob, fafile, outpath, datapath, jobid) if email != "": cmdline += "-email \"%s\" " % (email) if base_www_url != "": cmdline += "-baseurl \"%s\" " % (base_www_url) if g_params['isForceRun']: cmdline += "-force " if g_params['isOnlyGetCache']: cmdline += "-only-get-cache " code_str_list.append(cmdline) code = "\n".join(code_str_list) msg = "Writting scriptfile %s" % (scriptfile) webcom.loginfo(msg, g_params['debugfile']) myfunc.WriteFile(code, scriptfile, mode="w", isFlush=True) os.chmod(scriptfile, 0o755) webcom.loginfo("Getting priority", g_params['debugfile']) priority = myfunc.GetSuqPriority(numseq_this_user) if email in vip_user_list: priority = 999999999.0 webcom.loginfo("priority=%d" % (priority), g_params['debugfile']) st1 = webcom.SubmitSlurmJob(datapath, outpath, scriptfile, g_params['debugfile']) return st1
def RunJob(infile, outpath, tmpdir, email, jobid, g_params): #{{{ all_begin_time = time.time() rootname = os.path.basename(os.path.splitext(infile)[0]) starttagfile = "%s/runjob.start" % (outpath) runjob_errfile = "%s/runjob.err" % (outpath) runjob_logfile = "%s/runjob.log" % (outpath) app_logfile = "%s/app.log" % (outpath) finishtagfile = "%s/runjob.finish" % (outpath) failedtagfile = "%s/runjob.failed" % (outpath) query_parafile = "%s/query.para.txt" % (outpath) query_para = "" content = myfunc.ReadFile(query_parafile) if content != "": query_para = json.loads(content) rmsg = "" resultpathname = jobid outpath_result = "%s/%s" % (outpath, resultpathname) tmp_outpath_result = "%s/%s" % (tmpdir, resultpathname) tarball = "%s.tar.gz" % (resultpathname) zipfile = "%s.zip" % (resultpathname) tarball_fullpath = "%s.tar.gz" % (outpath_result) zipfile_fullpath = "%s.zip" % (outpath_result) resultfile_text = "%s/%s" % (outpath_result, "query.result.txt") mapfile = "%s/seqid_index_map.txt" % (outpath_result) finished_seq_file = "%s/finished_seqs.txt" % (outpath_result) for folder in [outpath_result, tmp_outpath_result]: try: os.makedirs(folder) except OSError: msg = "Failed to create folder %s" % (folder) myfunc.WriteFile(msg + "\n", gen_errfile, "a") return 1 try: open(finished_seq_file, 'w').close() except: pass #first getting result from caches # ================================== maplist = [] maplist_simple = [] toRunDict = {} hdl = myfunc.ReadFastaByBlock(infile, method_seqid=0, method_seq=0) if hdl.failure: isOK = False else: webcom.WriteDateTimeTagFile(starttagfile, runjob_logfile, runjob_errfile) recordList = hdl.readseq() cnt = 0 origpath = os.getcwd() while recordList != None: for rd in recordList: isSkip = False # temp outpath for the sequence is always seq_0, and I feed # only one seq a time to the workflow tmp_outpath_this_seq = "%s/%s" % (tmp_outpath_result, "seq_%d" % 0) outpath_this_seq = "%s/%s" % (outpath_result, "seq_%d" % cnt) subfoldername_this_seq = "seq_%d" % (cnt) if os.path.exists(tmp_outpath_this_seq): try: shutil.rmtree(tmp_outpath_this_seq) except OSError: pass maplist.append( "%s\t%d\t%s\t%s" % ("seq_%d" % cnt, len(rd.seq), rd.description, rd.seq)) maplist_simple.append( "%s\t%d\t%s" % ("seq_%d" % cnt, len(rd.seq), rd.description)) if not g_params['isForceRun']: md5_key = hashlib.md5( (rd.seq + str(query_para)).encode('utf-8')).hexdigest() subfoldername = md5_key[:2] cachedir = "%s/%s/%s" % (path_cache, subfoldername, md5_key) zipfile_cache = cachedir + ".zip" if os.path.exists(cachedir) or os.path.exists( zipfile_cache): if os.path.exists(cachedir): try: shutil.copytree(cachedir, outpath_this_seq) except Exception as e: msg = "Failed to copytree %s -> %s" % ( cachedir, outpath_this_seq) date_str = time.strftime(FORMAT_DATETIME) myfunc.WriteFile( "[%s] %s with errmsg=%s\n" % (date_str, msg, str(e)), runjob_errfile, "a") elif os.path.exists(zipfile_cache): cmd = [ "unzip", zipfile_cache, "-d", outpath_result ] webcom.RunCmd(cmd, runjob_logfile, runjob_errfile) shutil.move("%s/%s" % (outpath_result, md5_key), outpath_this_seq) if os.path.exists(outpath_this_seq): info_finish = webcom.GetInfoFinish_PRODRES( outpath_this_seq, cnt, len(rd.seq), rd.description, source_result="cached", runtime=0.0) myfunc.WriteFile("\t".join(info_finish) + "\n", finished_seq_file, "a", isFlush=True) isSkip = True if not isSkip: # first try to delete the outfolder if exists if os.path.exists(outpath_this_seq): try: shutil.rmtree(outpath_this_seq) except OSError: pass origIndex = cnt numTM = 0 toRunDict[origIndex] = [rd.seq, numTM, rd.description ] #init value for numTM is 0 cnt += 1 recordList = hdl.readseq() hdl.close() myfunc.WriteFile("\n".join(maplist_simple) + "\n", mapfile) if not g_params['isOnlyGetCache']: torun_all_seqfile = "%s/%s" % (tmp_outpath_result, "query.torun.fa") dumplist = [] for key in toRunDict: top = toRunDict[key][0] dumplist.append(">%s\n%s" % (str(key), top)) myfunc.WriteFile("\n".join(dumplist) + "\n", torun_all_seqfile, "w") del dumplist sortedlist = sorted(list(toRunDict.items()), key=lambda x: x[1][1], reverse=True) #format of sortedlist [(origIndex: [seq, numTM, description]), ...] # submit sequences one by one to the workflow according to orders in # sortedlist for item in sortedlist: origIndex = item[0] seq = item[1][0] description = item[1][2] subfoldername_this_seq = "seq_%d" % (origIndex) outpath_this_seq = "%s/%s" % (outpath_result, subfoldername_this_seq) tmp_outpath_this_seq = "%s/%s" % (tmp_outpath_result, "seq_%d" % (0)) if os.path.exists(tmp_outpath_this_seq): try: shutil.rmtree(tmp_outpath_this_seq) except OSError: pass seqfile_this_seq = "%s/%s" % (tmp_outpath_result, "query_%d.fa" % (origIndex)) seqcontent = ">query_%d\n%s\n" % (origIndex, seq) myfunc.WriteFile(seqcontent, seqfile_this_seq, "w") if not os.path.exists(seqfile_this_seq): msg = "failed to generate seq index %d" % (origIndex) date_str = time.strftime(g_params['FORMAT_DATETIME']) myfunc.WriteFile("[%s] %s\n" % (date_str, msg), runjob_errfile, "a", True) continue cmd = [ "python", runscript, "--input", seqfile_this_seq, "--output", tmp_outpath_this_seq, "--pfam-dir", path_pfamdatabase, "--pfamscan-script", path_pfamscanscript, "--fallback-db-fasta", blastdb ] if 'second_method' in query_para and query_para[ 'second_method'] != "": cmd += ['--second-search', query_para['second_method']] if 'pfamscan_evalue' in query_para and query_para[ 'pfamscan_evalue'] != "": cmd += ['--pfamscan_e-val', query_para['pfamscan_evalue']] elif 'pfamscan_bitscore' in query_para and query_para[ 'pfamscan_bitscore'] != "": cmd += ['--pfamscan_bitscore', query_para['pfamscan_bitscore']] if 'pfamscan_clanoverlap' in query_para: if query_para['pfamscan_clanoverlap'] == False: cmd += ['--pfamscan_clan-overlap', 'no'] else: cmd += ['--pfamscan_clan-overlap', 'yes'] if 'jackhmmer_iteration' in query_para and query_para[ 'jackhmmer_iteration'] != "": cmd += [ '--jackhmmer_max_iter', query_para['jackhmmer_iteration'] ] if 'jackhmmer_threshold_type' in query_para and query_para[ 'jackhmmer_threshold_type'] != "": cmd += [ '--jackhmmer-threshold-type', query_para['jackhmmer_threshold_type'] ] if 'jackhmmer_evalue' in query_para and query_para[ 'jackhmmer_evalue'] != "": cmd += ['--jackhmmer_e-val', query_para['jackhmmer_evalue']] elif 'jackhmmer_bitscore' in query_para and query_para[ 'jackhmmer_bitscore'] != "": cmd += [ '--jackhmmer_bit-score', query_para['jackhmmer_bitscore'] ] if 'psiblast_iteration' in query_para and query_para[ 'psiblast_iteration'] != "": cmd += ['--psiblast_iter', query_para['psiblast_iteration']] if 'psiblast_outfmt' in query_para and query_para[ 'psiblast_outfmt'] != "": cmd += ['--psiblast_outfmt', query_para['psiblast_outfmt']] (t_success, runtime_in_sec) = webcom.RunCmd(cmd, runjob_logfile, runjob_errfile, True) aaseqfile = "%s/seq.fa" % (tmp_outpath_this_seq + os.sep + "query_0") if not os.path.exists(aaseqfile): seqcontent = ">%s\n%s\n" % (description, seq) myfunc.WriteFile(seqcontent, aaseqfile, "w") if os.path.exists(tmp_outpath_this_seq): cmd = [ "mv", "-f", tmp_outpath_this_seq + os.sep + "query_0", outpath_this_seq ] isCmdSuccess = False (isCmdSuccess, t_runtime) = webcom.RunCmd(cmd, runjob_logfile, runjob_errfile, True) if not 'isKeepTempFile' in query_para or query_para[ 'isKeepTempFile'] == False: try: temp_result_folder = "%s/temp" % (outpath_this_seq) shutil.rmtree(temp_result_folder) except: msg = "Failed to delete the folder %s" % ( temp_result_folder) date_str = time.strftime(g_params['FORMAT_DATETIME']) myfunc.WriteFile("[%s] %s\n" % (date_str, msg), runjob_errfile, "a", True) flist = [ "%s/outputs/%s" % (outpath_this_seq, "Alignment.txt"), "%s/outputs/%s" % (outpath_this_seq, "tableOut.txt"), "%s/outputs/%s" % (outpath_this_seq, "fullOut.txt") ] for f in flist: if os.path.exists(f): try: os.remove(f) except: msg = "Failed to delete the file %s" % (f) date_str = time.strftime( g_params['FORMAT_DATETIME']) myfunc.WriteFile("[%s] %s\n" % (date_str, msg), runjob_errfile, "a", True) if isCmdSuccess: timefile = "%s/time.txt" % (outpath_this_seq) runtime = webcom.ReadRuntimeFromFile(timefile, default_runtime=0.0) info_finish = webcom.GetInfoFinish_PRODRES( outpath_this_seq, origIndex, len(seq), description, source_result="newrun", runtime=runtime) myfunc.WriteFile("\t".join(info_finish) + "\n", finished_seq_file, "a", isFlush=True) # now write the text output for this seq info_this_seq = "%s\t%d\t%s\t%s" % ( "seq_%d" % origIndex, len(seq), description, seq) resultfile_text_this_seq = "%s/%s" % (outpath_this_seq, "query.result.txt") #webcom.WriteSubconsTextResultFile(resultfile_text_this_seq, # outpath_result, [info_this_seq], runtime_in_sec, g_params['base_www_url']) # create or update the md5 cache # create cache only on the front-end if webcom.IsFrontEndNode(g_params['base_www_url']): md5_key = hashlib.md5( (seq + str(query_para)).encode('utf-8')).hexdigest() subfoldername = md5_key[:2] md5_subfolder = "%s/%s" % (path_cache, subfoldername) cachedir = "%s/%s/%s" % (path_cache, subfoldername, md5_key) # copy the zipped folder to the cache path origpath = os.getcwd() os.chdir(outpath_result) shutil.copytree("seq_%d" % (origIndex), md5_key) cmd = ["zip", "-rq", "%s.zip" % (md5_key), md5_key] webcom.RunCmd(cmd, runjob_logfile, runjob_logfile) if not os.path.exists(md5_subfolder): os.makedirs(md5_subfolder) shutil.move("%s.zip" % (md5_key), "%s.zip" % (cachedir)) shutil.rmtree( md5_key ) # delete the temp folder named as md5 hash os.chdir(origpath) # Add the finished date to the database date_str = time.strftime(FORMAT_DATETIME) webcom.InsertFinishDateToDB(date_str, md5_key, seq, finished_date_db) all_end_time = time.time() all_runtime_in_sec = all_end_time - all_begin_time if not g_params['isOnlyGetCache'] or len(toRunDict) == 0: # now write the text output to a single file statfile = "%s/%s" % (outpath_result, "stat.txt") #webcom.WriteSubconsTextResultFile(resultfile_text, outpath_result, maplist, # all_runtime_in_sec, g_params['base_www_url'], statfile=statfile) # now making zip instead (for windows users) # note that zip rq will zip the real data for symbolic links os.chdir(outpath) # cmd = ["tar", "-czf", tarball, resultpathname] cmd = ["zip", "-rq", zipfile, resultpathname] webcom.RunCmd(cmd, runjob_logfile, runjob_errfile) # write finish tag file if os.path.exists(finished_seq_file): webcom.WriteDateTimeTagFile(finishtagfile, runjob_logfile, runjob_errfile) isSuccess = False if (os.path.exists(finishtagfile) and os.path.exists(zipfile_fullpath)): isSuccess = True else: isSuccess = False webcom.WriteDateTimeTagFile(failedtagfile, runjob_logfile, runjob_errfile) # send the result to email # do not sendmail at the cloud VM if webcom.IsFrontEndNode(g_params['base_www_url'] ) and myfunc.IsValidEmailAddress(email): if isSuccess: finish_status = "success" else: finish_status = "failed" webcom.SendEmail_on_finish( jobid, g_params['base_www_url'], finish_status, name_server="PRODRES", from_email="*****@*****.**", to_email=email, contact_email=contact_email, logfile=runjob_logfile, errfile=runjob_errfile) if os.path.exists(runjob_errfile) and os.path.getsize(runjob_errfile) > 1: return 1 else: try: shutil.rmtree(tmpdir) msg = "rmtree(%s)" % (tmpdir) webcom.loginfo("rmtree(%s)" % (tmpdir), runjob_logfile) except Exception as e: msg = "Failed to rmtree(%s)" % (tmpdir) webcom.loginfo( "Failed to rmtree(%s) with error message: %s" % (tmpdir, str(e)), runjob_errfile) return 0