5 from argparse
import ArgumentParser
6 from argparse
import HelpFormatter
7 from shutil
import copyfile, rmtree, move
10 from colors
import bcolors
16 with open(config)
as f:
18 line = line.replace(
" ",
"").strip()
21 if line[0] !=
'#' and line.split(
"=")[0] == parameter:
22 par = line.split(
"=")[1]
25 if parameter==
"ntuplesList" and "tools:" in p[1]:
26 ntp_path = os.getenv(
'CMSSW_BASE')
27 ntp_path +=
"/src/Analysis/Tools/data/ntuples/" 28 p[1] = p[1].replace(
"tools:",ntp_path)
35 with open(config,
"r") as f: 39 line = line.replace(
" ",
"").strip()
42 if line[0] !=
'#' and line.split(
"=")[0] == parameter:
47 with open(config,
"w")
as f:
48 f.write(parameter+
" = \n")
55 with open(config,
"r") as f: 57 with open(config, "w")
as f:
59 l = line.replace(
" ",
"").strip()
63 if l[0] !=
'#' and l.split(
'=')[0] == parameter:
64 if l.split(
'=')[1] ==
"" :
66 newpar =
" = " + newpar
69 f.write(re.sub(par, newpar, line))
74 with open(config,
"r") as f: 76 with open(config, "w")
as f:
78 l = line.replace(
" ",
"").strip()
82 if l[0] !=
'#' and l.split(
'=')[0] == parameter:
88 with open(config,
"r") as f: 90 with open(config, "w")
as f:
92 f.write(re.sub(name, os.path.basename(name), line))
96 libpath = os.environ[
'LD_LIBRARY_PATH']
98 Requirements = ( OpSysAndVer == "CentOS7" ) 100 executable = $(jobdir)/job.sh 101 log = $(jobdir)/xjob_$(Cluster)_$(Process).log 102 output = $(jobdir)/xjob_$(Cluster)_$(Process).out 103 error = $(jobdir)/xjob_$(Cluster)_$(Process).err 104 environment = "LD_LIBRARY_PATH_STORED=$ENV(LD_LIBRARY_PATH)" 106 queue jobdir matching dirs job_* 108 with open(f
'{maindir}/jobs.submit',
'w')
as condor_file:
109 print(condor_submit,file=condor_file)
112 libpath = os.environ[
'LD_LIBRARY_PATH']
114 Requirements = ( OpSysAndVer == "CentOS7" ) 117 log = xjob_$(Cluster)_$(Process).log 118 output = xjob_$(Cluster)_$(Process).out 119 error = xjob_$(Cluster)_$(Process).err 120 environment = "LD_LIBRARY_PATH_STORED=$ENV(LD_LIBRARY_PATH)" 124 with open(f
'{jobdir}/job.submit',
'w')
as condor_file:
125 print(condor_submit,file=condor_file)
129 if [[ ! -e "{}" ]]; then 132 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH_STORED 134 """.format(cfg,jobid,exe,cfg)
135 js_name = f
'{exedir}/job.sh' 136 with open(js_name,
'w')
as job_script:
137 print(js,file=job_script)
138 os.chmod(js_name, 0o744)
143 ntuples = args.ntuples
148 events_max = args.events_max
152 isMC = configMC[1] ==
'true' 155 print(
'TEST MODE:', test,
'jobs')
160 if not os.path.isfile(config):
161 print (
"Configuration file does not exist")
166 ntuples = configNtuples[1]
168 print (
"*error* You must define the parameter ntuplesList in your configuration.")
180 if not os.path.isfile(ntuples):
181 print (
"Ntuples list file does not exist")
184 if (
not 'tools:' in json)
and (
not os.path.isfile(json)):
185 print (
"Json file does not exist")
189 maindir =
"Condor_"+os.path.basename(args.exe)
191 maindir = maindir+
"_"+ os.path.splitext(os.path.basename(config))[0]
193 maindir +=
'_'+args.label
195 if os.path.exists(cwd+
"/"+maindir):
197 print (bcolors.FAIL,
'>>>>>>', maindir,
"already exists. Rename or remove it and then resubmit",bcolors.ENDC)
201 os.mkdir(maindir+
'/finished_jobs')
206 tmpdir =
".tmp_" + str(pid)
208 copyfile(ntuples, tmpdir+
"/"+os.path.basename(ntuples))
210 copyfile(config, tmpdir+
"/"+os.path.basename(config))
215 if (
not 'tools:' in json):
227 splitcmd =
"split.csh" +
" " + str(args.nfiles) +
" " + os.path.basename(ntuples)
229 os.remove(os.path.basename(ntuples))
230 files = glob.glob(
'.*_x????.txt')
236 for i,f
in enumerate(files):
238 if i >=
int(test)
and int(test)>=0:
241 jobnum = os.path.splitext(f)[0][-4:]
242 jobid =
"job_"+jobnum
243 exedir = maindir+
"/"+jobid
246 move(tmpdir+
"/"+f,exedir+
"/"+os.path.basename(ntuples))
248 if not 'tools:' in json:
249 copyfile(json, exedir+
"/"+os.path.basename(json))
251 copyfile(tmpdir+
"/"+os.path.basename(config),exedir+
"/"+os.path.basename(config))
252 condorcmd =
"condor_scripts.csh" +
" " + jobid +
" " + args.exe +
" " + os.path.basename(config)
256 condorcmd =
"condor_scripts.csh" +
" " + jobid +
" " + args.exe
259 jobf = open(f
'{exedir}/seed.txt',
'w+')
260 jobf.write(str(
int(jobnum)+1))
263 print (
"Creating ",jobid,
"...")
274 os.chdir(cwd+
'/'+maindir)
275 os.system(
'condor_submit jobs.submit')
282 exedir = maindir+
"/job_0000" 284 if os.path.isfile(args.exe):
285 copyfile(args.exe, exedir+
"/"+os.path.basename(args.exe))
287 jobf = open(
'./seed.txt',
'w+')
290 condorcmd =
"condor_scripts.csh job_0000" +
" " + os.path.basename(args.exe)
293 os.system(
'condor_submit job.submit')
299 os.remove(tmpdir+
"/"+os.path.basename(config))
305 files = os.listdir(jobdir)
306 log = [ jobdir+
'/'+x
for x
in files
if x.endswith(
'.log') ]
308 return max(log, key=os.path.getctime)
316 files = os.listdir(jobdir)
317 errs = [ jobdir+
'/'+x
for x
in files
if x.endswith(
'.err') ]
319 err = max(errs, key=os.path.getctime)
326 return (os.path.getsize(err) > 0)
333 job_status[
'submission'] =
False 334 job_status[
'termination'] =
False 335 job_status[
'execution'] =
False 336 job_status[
'abortion'] =
False 337 job_status[
'error'] =
True 338 job_status[
'jobid'] =
' ' 342 logname = os.path.basename(log)
343 job_status[
'jobid'] = logname.split(
'.')[0].split(
'_')[1] +
'.' + logname.split(
'.')[0].split(
'_')[2]
346 if re.search(
'Job submitted from host',l):
347 job_status[
'submission'] =
True 348 if re.search(
'Job executing on host',l):
349 job_status[
'execution'] =
True 350 if re.search(
'Job terminated.',l):
351 job_status[
'termination'] =
True 352 if re.search(
'Job was evicted',l)
or re.search(
'Job was aborted',l):
353 job_status[
'abortion'] =
True 354 if re.search(
'return value 0',l):
355 job_status[
'error'] =
False 362 def status(submission_dir, failed_only=False):
365 finished_dir = submission_dir+
'/finished_jobs' 366 jobs_dir = os.listdir(submission_dir)
367 jobs_dir = [ x
for x
in jobs_dir
if 'job_' in x ]
370 header =
' *** STATUS OF JOBS ***' 372 header =
' *** FAILED JOBS ***' 374 print(
'\n '+submission_dir)
376 dash=
' ----------------------------------------------------------------------------------------------------------' 378 print(
' job finished running submitted aborted error condor_id (latest)')
381 j = submission_dir+
'/'+jj
390 if js[
'termination']:
395 if js[
'error']
and not js[
'abortion']:
397 if not js[
'abortion']
and not js[
'error']:
399 if os.path.isfile(j+
'/finished.txt'):
403 finished =
'\u26A0\uFE0F ' 405 elif js[
'execution']
and not js[
'abortion']:
407 elif js[
'submission']
and not js[
'abortion']:
412 if not ( js[
'submission']
or js[
'termination']
or js[
'execution']
or js[
'abortion'] ):
413 submitted =
'\u26A0\uFE0F ' 414 if js[
'abortion']
or ( js[
'termination']
and js[
'error']):
416 if failed_only
and (
not (js[
'abortion']
or ( js[
'termination']
and js[
'error']))):
418 print(
' '+jj+
' '+finished+
' '+running+
' '+submitted+
' '+aborted+
' '+error+
' '+jobid)
419 if len(jobs_dir) == 0:
420 print(
' No jobs to be checked!')
423 print(
'\n N.B.: Good *finished* jobs will no longer appear in future "--status" calls')
429 failed_jobs =
status(submission_dir,
True)
432 jobs_dir = os.listdir(submission_dir)
433 jobs_dir = [ x
for x
in jobs_dir
if 'job_' in x ]
437 print(
' *** Resubmit failed jobs ***')
445 j = submission_dir+
'/'+jj
447 if js[
'abortion']
or ( js[
'termination']
and js[
'error'] ):
449 os.system(
'condor_submit job.submit')
461 failed_jobs =
status(submission_dir,
True)
466 os.chdir(submission_dir)
468 print(
' *** Resubmit jobs (EXPERT) ***')
475 os.system(
'condor_submit jobs.submit')
485 while answer
not in [
"y",
"n",
""]:
486 answer =
input(
" Please confirm this action (Y/[N])? ").lower()
487 return (answer ==
"y" or answer !=
"")
493 parser = ArgumentParser(prog=
'naf_submit.py', formatter_class=
lambda prog: HelpFormatter(prog,indent_increment=6,max_help_position=80,width=280), description=
'Prepare, submit and check jobs to NAF HTCondor batch system',add_help=
True)
494 parser_submission = parser.add_argument_group(
'submission',
'prepare and submit jobs')
496 parser_submission.add_argument(
"--exe" ,
"-e" , dest=
"exe" , help=
"Executable (REQUIRED)")
497 parser_submission.add_argument(
"--config" ,
"-c" , dest=
"config" , help=
"Configuration file (REQUIRED)")
498 parser_submission.add_argument(
"--ntuples",
"-n" , dest=
"ntuples" , help=
"List of ntuples file")
499 parser_submission.add_argument(
"--nfiles" ,
"-x" , dest=
"nfiles" , type=int, default=1, help=
"Number of ntuple files per job")
500 parser_submission.add_argument(
"--json" ,
"-j" , dest=
"json" , help=
"JSON file with certified data")
501 parser_submission.add_argument(
"--label" ,
"-l" , dest=
"label" , help=
"user label for the submission")
502 parser_submission.add_argument(
"--events" , dest=
"events_max" , default=
"-1" , help=
"override eventsMax in the config file (default = -1)")
503 parser_submission.add_argument(
"--test" , dest=
"njobs" , help=
"*** expert only ***:produce njobs, no automatic submission")
506 parser_status = parser.add_argument_group(
'status',
'show and modify status')
507 parser_status.add_argument(
"--dir" , dest=
"dir" , help=
"an existing condor directory (REQUIRED)")
508 parser_status.add_argument(
"--status" , dest=
"status" , action=
"store_true", help=
"-> returns the status of the jobs in --dir")
509 parser_status.add_argument(
"--resubmit" , dest=
"resubmit" , action=
"store_true", help=
"-> resubmits aborted and finished-with-error jobs in --dir")
510 parser_status.add_argument(
"--expert" , dest=
"expert" , action=
"store_true", help=
" -> *** expert mode ***")
511 args = parser.parse_args()
513 dash =
' ----------------------------------------------------------------------------------------------------------' 516 if not os.path.exists(args.dir):
517 print(
"Directory", args.dir,
"does not exist")
521 elif args.resubmit
and not args.expert:
523 elif args.resubmit
and args.expert:
528 if not args.exe
and not args.config:
def replaceConfigParameter(config, parameter, newpar)
def status(submission_dir, failed_only=False)
def basenameConfigParameter(config, name)
def createCondorDirsSubmit(maindir)
def getConfigParameter(config, parameter)
def createJobScript(exedir, jobid, exe, cfg)
def createCondorSubmit(jobdir)
def resubmit(submission_dir)
def removeConfigParameter(config, parameter)
def createConfigParameter(config, parameter)
def get_job_status(jobdir)
def resubmit_expert(submission_dir)