1 |
|
from JobType import JobType |
2 |
– |
from crab_logger import Logger |
2 |
|
from crab_exceptions import * |
3 |
|
from crab_util import * |
4 |
|
import common |
5 |
|
import Scram |
6 |
+ |
from Splitter import JobSplitter |
7 |
|
|
8 |
< |
import os, string, re, shutil, glob |
8 |
> |
from IMProv.IMProvNode import IMProvNode |
9 |
> |
import os, string, glob |
10 |
|
|
11 |
|
class Cmssw(JobType): |
12 |
< |
def __init__(self, cfg_params, ncjobs): |
12 |
> |
def __init__(self, cfg_params, ncjobs,skip_blocks, isNew): |
13 |
|
JobType.__init__(self, 'CMSSW') |
14 |
< |
common.logger.debug(3,'CMSSW::__init__') |
14 |
> |
common.logger.debug('CMSSW::__init__') |
15 |
> |
self.skip_blocks = skip_blocks |
16 |
> |
self.argsList = 1 |
17 |
|
|
15 |
– |
# Marco. |
18 |
|
self._params = {} |
19 |
|
self.cfg_params = cfg_params |
20 |
|
|
21 |
< |
try: |
22 |
< |
self.MaxTarBallSize = float(self.cfg_params['EDG.maxtarballsize']) |
23 |
< |
except KeyError: |
24 |
< |
self.MaxTarBallSize = 9.5 |
21 |
> |
### Temporary patch to automatically skip the ISB size check: |
22 |
> |
server=self.cfg_params.get('CRAB.server_name',None) |
23 |
> |
size = 9.5 |
24 |
> |
if server or common.scheduler.name().upper() in ['LSF','CAF']: size = 99999 |
25 |
> |
### D.S. |
26 |
> |
self.MaxTarBallSize = float(self.cfg_params.get('GRID.maxtarballsize',size)) |
27 |
|
|
28 |
|
# number of jobs requested to be created, limit obj splitting |
29 |
|
self.ncjobs = ncjobs |
30 |
|
|
27 |
– |
log = common.logger |
28 |
– |
|
31 |
|
self.scram = Scram.Scram(cfg_params) |
32 |
|
self.additional_inbox_files = [] |
33 |
|
self.scriptExe = '' |
34 |
|
self.executable = '' |
35 |
|
self.executable_arch = self.scram.getArch() |
36 |
< |
self.tgz_name = 'default.tgz' |
36 |
> |
self.tgz_name = 'default.tar.gz' |
37 |
> |
self.tar_name = 'default.tar' |
38 |
|
self.scriptName = 'CMSSW.sh' |
39 |
< |
self.pset = '' #scrip use case Da |
40 |
< |
self.datasetPath = '' #scrip use case Da |
39 |
> |
self.pset = '' |
40 |
> |
self.datasetPath = '' |
41 |
|
|
42 |
+ |
self.tgzNameWithPath = common.work_space.pathForTgz()+self.tgz_name |
43 |
|
# set FJR file name |
44 |
|
self.fjrFileName = 'crab_fjr.xml' |
45 |
|
|
46 |
|
self.version = self.scram.getSWVersion() |
47 |
< |
common.taskDB.setDict('codeVersion',self.version) |
44 |
< |
self.setParam_('application', self.version) |
45 |
< |
|
46 |
< |
### collect Data cards |
47 |
> |
common.logger.log(10-1,"CMSSW version is: "+str(self.version)) |
48 |
|
|
49 |
< |
## get DBS mode |
50 |
< |
try: |
51 |
< |
self.use_dbs_1 = int(self.cfg_params['CMSSW.use_dbs_1']) |
52 |
< |
except KeyError: |
52 |
< |
self.use_dbs_1 = 0 |
53 |
< |
|
49 |
> |
version_array = self.version.split('_') |
50 |
> |
self.CMSSW_major = 0 |
51 |
> |
self.CMSSW_minor = 0 |
52 |
> |
self.CMSSW_patch = 0 |
53 |
|
try: |
54 |
< |
tmp = cfg_params['CMSSW.datasetpath'] |
55 |
< |
log.debug(6, "CMSSW::CMSSW(): datasetPath = "+tmp) |
56 |
< |
if string.lower(tmp)=='none': |
57 |
< |
self.datasetPath = None |
58 |
< |
self.selectNoInput = 1 |
59 |
< |
else: |
60 |
< |
self.datasetPath = tmp |
61 |
< |
self.selectNoInput = 0 |
62 |
< |
except KeyError: |
64 |
< |
msg = "Error: datasetpath not defined " |
54 |
> |
self.CMSSW_major = int(version_array[1]) |
55 |
> |
self.CMSSW_minor = int(version_array[2]) |
56 |
> |
self.CMSSW_patch = int(version_array[3]) |
57 |
> |
except: |
58 |
> |
msg = "Cannot parse CMSSW version string: " + self.version + " for major and minor release number!" |
59 |
> |
raise CrabException(msg) |
60 |
> |
|
61 |
> |
if self.CMSSW_major < 1 or (self.CMSSW_major == 1 and self.CMSSW_minor < 5): |
62 |
> |
msg = "CRAB supports CMSSW >= 1_5_x only. Use an older CRAB version." |
63 |
|
raise CrabException(msg) |
64 |
+ |
""" |
65 |
+ |
As CMSSW versions are dropped we can drop more code: |
66 |
+ |
1.X dropped: drop support for running .cfg on WN |
67 |
+ |
2.0 dropped: drop all support for cfg here and in writeCfg |
68 |
+ |
2.0 dropped: Recheck the random number seed support |
69 |
+ |
""" |
70 |
+ |
|
71 |
+ |
### collect Data cards |
72 |
+ |
|
73 |
+ |
|
74 |
+ |
### Temporary: added to remove input file control in the case of PU |
75 |
+ |
self.dataset_pu = cfg_params.get('CMSSW.dataset_pu', None) |
76 |
+ |
|
77 |
+ |
tmp = cfg_params['CMSSW.datasetpath'] |
78 |
+ |
common.logger.log(10-1, "CMSSW::CMSSW(): datasetPath = "+tmp) |
79 |
|
|
80 |
< |
# ML monitoring |
81 |
< |
# split dataset path style: /PreProdR3Minbias/SIM/GEN-SIM |
82 |
< |
if not self.datasetPath: |
83 |
< |
self.setParam_('dataset', 'None') |
84 |
< |
self.setParam_('owner', 'None') |
80 |
> |
if tmp =='': |
81 |
> |
msg = "Error: datasetpath not defined " |
82 |
> |
raise CrabException(msg) |
83 |
> |
elif string.lower(tmp)=='none': |
84 |
> |
self.datasetPath = None |
85 |
> |
self.selectNoInput = 1 |
86 |
|
else: |
87 |
< |
try: |
88 |
< |
datasetpath_split = self.datasetPath.split("/") |
75 |
< |
# standard style |
76 |
< |
if self.use_dbs_1 == 1 : |
77 |
< |
self.setParam_('dataset', datasetpath_split[1]) |
78 |
< |
self.setParam_('owner', datasetpath_split[-1]) |
79 |
< |
else: |
80 |
< |
self.setParam_('dataset', datasetpath_split[1]) |
81 |
< |
self.setParam_('owner', datasetpath_split[2]) |
82 |
< |
except: |
83 |
< |
self.setParam_('dataset', self.datasetPath) |
84 |
< |
self.setParam_('owner', self.datasetPath) |
85 |
< |
|
86 |
< |
self.setTaskid_() |
87 |
< |
self.setParam_('taskId', self.cfg_params['taskId']) |
87 |
> |
self.datasetPath = tmp |
88 |
> |
self.selectNoInput = 0 |
89 |
|
|
90 |
|
self.dataTiers = [] |
91 |
|
|
92 |
+ |
self.debugWrap='' |
93 |
+ |
self.debug_wrapper = int(cfg_params.get('USER.debug_wrapper',0)) |
94 |
+ |
if self.debug_wrapper == 1: self.debugWrap='--debug' |
95 |
+ |
|
96 |
|
## now the application |
97 |
< |
try: |
98 |
< |
self.executable = cfg_params['CMSSW.executable'] |
99 |
< |
self.setParam_('exe', self.executable) |
100 |
< |
log.debug(6, "CMSSW::CMSSW(): executable = "+self.executable) |
96 |
< |
msg = "Default executable cmsRun overridden. Switch to " + self.executable |
97 |
< |
log.debug(3,msg) |
98 |
< |
except KeyError: |
99 |
< |
self.executable = 'cmsRun' |
100 |
< |
self.setParam_('exe', self.executable) |
101 |
< |
msg = "User executable not defined. Use cmsRun" |
102 |
< |
log.debug(3,msg) |
103 |
< |
pass |
97 |
> |
self.managedGenerators = ['madgraph', 'comphep', 'lhe'] |
98 |
> |
self.generator = cfg_params.get('CMSSW.generator','pythia').lower() |
99 |
> |
self.executable = cfg_params.get('CMSSW.executable','cmsRun') |
100 |
> |
common.logger.log(10-1, "CMSSW::CMSSW(): executable = "+self.executable) |
101 |
|
|
102 |
< |
try: |
106 |
< |
self.pset = cfg_params['CMSSW.pset'] |
107 |
< |
log.debug(6, "Cmssw::Cmssw(): PSet file = "+self.pset) |
108 |
< |
if self.pset.lower() != 'none' : |
109 |
< |
if (not os.path.exists(self.pset)): |
110 |
< |
raise CrabException("User defined PSet file "+self.pset+" does not exist") |
111 |
< |
else: |
112 |
< |
self.pset = None |
113 |
< |
except KeyError: |
102 |
> |
if not cfg_params.has_key('CMSSW.pset'): |
103 |
|
raise CrabException("PSet file missing. Cannot run cmsRun ") |
104 |
+ |
self.pset = cfg_params['CMSSW.pset'] |
105 |
+ |
common.logger.log(10-1, "Cmssw::Cmssw(): PSet file = "+self.pset) |
106 |
+ |
if self.pset.lower() != 'none' : |
107 |
+ |
if (not os.path.exists(self.pset)): |
108 |
+ |
raise CrabException("User defined PSet file "+self.pset+" does not exist") |
109 |
+ |
else: |
110 |
+ |
self.pset = None |
111 |
|
|
112 |
|
# output files |
113 |
|
## stuff which must be returned always via sandbox |
117 |
|
self.output_file_sandbox.append(self.fjrFileName) |
118 |
|
|
119 |
|
# other output files to be returned via sandbox or copied to SE |
120 |
< |
try: |
121 |
< |
self.output_file = [] |
122 |
< |
tmp = cfg_params['CMSSW.output_file'] |
123 |
< |
if tmp != '': |
124 |
< |
tmpOutFiles = string.split(cfg_params['CMSSW.output_file'],',') |
125 |
< |
log.debug(7, 'cmssw::cmssw(): output files '+str(tmpOutFiles)) |
126 |
< |
for tmp in tmpOutFiles: |
127 |
< |
tmp=string.strip(tmp) |
132 |
< |
self.output_file.append(tmp) |
133 |
< |
pass |
134 |
< |
else: |
135 |
< |
log.message("No output file defined: only stdout/err and the CRAB Framework Job Report will be available\n") |
136 |
< |
pass |
137 |
< |
pass |
138 |
< |
except KeyError: |
139 |
< |
log.message("No output file defined: only stdout/err and the CRAB Framework Job Report will be available\n") |
140 |
< |
pass |
120 |
> |
outfileflag = False |
121 |
> |
self.output_file = [] |
122 |
> |
tmp = cfg_params.get('CMSSW.output_file',None) |
123 |
> |
if tmp : |
124 |
> |
self.output_file = [x.strip() for x in tmp.split(',')] |
125 |
> |
outfileflag = True #output found |
126 |
> |
#else: |
127 |
> |
# log.message("No output file defined: only stdout/err and the CRAB Framework Job Report will be available\n") |
128 |
|
|
129 |
|
# script_exe file as additional file in inputSandbox |
130 |
< |
try: |
131 |
< |
self.scriptExe = cfg_params['USER.script_exe'] |
132 |
< |
if self.scriptExe != '': |
133 |
< |
if not os.path.isfile(self.scriptExe): |
134 |
< |
msg ="ERROR. file "+self.scriptExe+" not found" |
135 |
< |
raise CrabException(msg) |
136 |
< |
self.additional_inbox_files.append(string.strip(self.scriptExe)) |
137 |
< |
except KeyError: |
138 |
< |
self.scriptExe = '' |
130 |
> |
self.scriptExe = cfg_params.get('USER.script_exe',None) |
131 |
> |
if self.scriptExe : |
132 |
> |
if not os.path.isfile(self.scriptExe): |
133 |
> |
msg ="ERROR. file "+self.scriptExe+" not found" |
134 |
> |
raise CrabException(msg) |
135 |
> |
self.additional_inbox_files.append(string.strip(self.scriptExe)) |
136 |
> |
|
137 |
> |
self.AdditionalArgs = cfg_params.get('USER.script_arguments',None) |
138 |
> |
if self.AdditionalArgs : self.AdditionalArgs = string.replace(self.AdditionalArgs,',',' ') |
139 |
|
|
153 |
– |
#CarlosDaniele |
140 |
|
if self.datasetPath == None and self.pset == None and self.scriptExe == '' : |
141 |
< |
msg ="Error. script_exe not defined" |
142 |
< |
raise CrabException(msg) |
141 |
> |
msg ="Error. script_exe not defined" |
142 |
> |
raise CrabException(msg) |
143 |
> |
|
144 |
> |
# use parent files... |
145 |
> |
self.useParent = int(self.cfg_params.get('CMSSW.use_parent',0)) |
146 |
|
|
147 |
|
## additional input files |
148 |
< |
try: |
148 |
> |
if cfg_params.has_key('USER.additional_input_files'): |
149 |
|
tmpAddFiles = string.split(cfg_params['USER.additional_input_files'],',') |
150 |
|
for tmp in tmpAddFiles: |
151 |
|
tmp = string.strip(tmp) |
162 |
|
if not os.path.exists(file): |
163 |
|
raise CrabException("Additional input file not found: "+file) |
164 |
|
pass |
165 |
< |
fname = string.split(file, '/')[-1] |
177 |
< |
storedFile = common.work_space.pathForTgz()+'share/'+fname |
178 |
< |
shutil.copyfile(file, storedFile) |
179 |
< |
self.additional_inbox_files.append(string.strip(storedFile)) |
165 |
> |
self.additional_inbox_files.append(string.strip(file)) |
166 |
|
pass |
167 |
|
pass |
168 |
< |
common.logger.debug(5,"Additional input files: "+str(self.additional_inbox_files)) |
169 |
< |
except KeyError: |
184 |
< |
pass |
185 |
< |
|
186 |
< |
# files per job |
187 |
< |
try: |
188 |
< |
if (cfg_params['CMSSW.files_per_jobs']): |
189 |
< |
raise CrabException("files_per_jobs no longer supported. Quitting.") |
190 |
< |
except KeyError: |
191 |
< |
pass |
192 |
< |
|
193 |
< |
## Events per job |
194 |
< |
try: |
195 |
< |
self.eventsPerJob =int( cfg_params['CMSSW.events_per_job']) |
196 |
< |
self.selectEventsPerJob = 1 |
197 |
< |
except KeyError: |
198 |
< |
self.eventsPerJob = -1 |
199 |
< |
self.selectEventsPerJob = 0 |
200 |
< |
|
201 |
< |
## number of jobs |
202 |
< |
try: |
203 |
< |
self.theNumberOfJobs =int( cfg_params['CMSSW.number_of_jobs']) |
204 |
< |
self.selectNumberOfJobs = 1 |
205 |
< |
except KeyError: |
206 |
< |
self.theNumberOfJobs = 0 |
207 |
< |
self.selectNumberOfJobs = 0 |
208 |
< |
|
209 |
< |
try: |
210 |
< |
self.total_number_of_events = int(cfg_params['CMSSW.total_number_of_events']) |
211 |
< |
self.selectTotalNumberEvents = 1 |
212 |
< |
except KeyError: |
213 |
< |
self.total_number_of_events = 0 |
214 |
< |
self.selectTotalNumberEvents = 0 |
215 |
< |
|
216 |
< |
if self.pset != None: #CarlosDaniele |
217 |
< |
if ( (self.selectTotalNumberEvents + self.selectEventsPerJob + self.selectNumberOfJobs) != 2 ): |
218 |
< |
msg = 'Must define exactly two of total_number_of_events, events_per_job, or number_of_jobs.' |
219 |
< |
raise CrabException(msg) |
220 |
< |
else: |
221 |
< |
if (self.selectNumberOfJobs == 0): |
222 |
< |
msg = 'Must specify number_of_jobs.' |
223 |
< |
raise CrabException(msg) |
224 |
< |
|
225 |
< |
## source seed for pythia |
226 |
< |
try: |
227 |
< |
self.sourceSeed = int(cfg_params['CMSSW.pythia_seed']) |
228 |
< |
except KeyError: |
229 |
< |
self.sourceSeed = None |
230 |
< |
common.logger.debug(5,"No seed given") |
231 |
< |
|
232 |
< |
try: |
233 |
< |
self.sourceSeedVtx = int(cfg_params['CMSSW.vtx_seed']) |
234 |
< |
except KeyError: |
235 |
< |
self.sourceSeedVtx = None |
236 |
< |
common.logger.debug(5,"No vertex seed given") |
237 |
< |
|
238 |
< |
try: |
239 |
< |
self.sourceSeedG4 = int(cfg_params['CMSSW.g4_seed']) |
240 |
< |
except KeyError: |
241 |
< |
self.sourceSeedG4 = None |
242 |
< |
common.logger.debug(5,"No g4 sim hits seed given") |
243 |
< |
|
244 |
< |
try: |
245 |
< |
self.sourceSeedMix = int(cfg_params['CMSSW.mix_seed']) |
246 |
< |
except KeyError: |
247 |
< |
self.sourceSeedMix = None |
248 |
< |
common.logger.debug(5,"No mix seed given") |
168 |
> |
common.logger.debug("Additional input files: "+str(self.additional_inbox_files)) |
169 |
> |
pass |
170 |
|
|
250 |
– |
try: |
251 |
– |
self.firstRun = int(cfg_params['CMSSW.first_run']) |
252 |
– |
except KeyError: |
253 |
– |
self.firstRun = None |
254 |
– |
common.logger.debug(5,"No first run given") |
255 |
– |
if self.pset != None: #CarlosDaniele |
256 |
– |
import PsetManipulator |
257 |
– |
PsetEdit = PsetManipulator.PsetManipulator(self.pset) #Daniele Pset |
171 |
|
|
172 |
+ |
## New method of dealing with seeds |
173 |
+ |
self.incrementSeeds = [] |
174 |
+ |
self.preserveSeeds = [] |
175 |
+ |
if cfg_params.has_key('CMSSW.preserve_seeds'): |
176 |
+ |
tmpList = cfg_params['CMSSW.preserve_seeds'].split(',') |
177 |
+ |
for tmp in tmpList: |
178 |
+ |
tmp.strip() |
179 |
+ |
self.preserveSeeds.append(tmp) |
180 |
+ |
if cfg_params.has_key('CMSSW.increment_seeds'): |
181 |
+ |
tmpList = cfg_params['CMSSW.increment_seeds'].split(',') |
182 |
+ |
for tmp in tmpList: |
183 |
+ |
tmp.strip() |
184 |
+ |
self.incrementSeeds.append(tmp) |
185 |
+ |
|
186 |
+ |
self.firstRun = cfg_params.get('CMSSW.first_run',None) |
187 |
+ |
|
188 |
+ |
# Copy/return |
189 |
+ |
self.copy_data = int(cfg_params.get('USER.copy_data',0)) |
190 |
+ |
self.return_data = int(cfg_params.get('USER.return_data',0)) |
191 |
+ |
|
192 |
+ |
self.conf = {} |
193 |
+ |
self.conf['pubdata'] = None |
194 |
+ |
# number of jobs requested to be created, limit obj splitting DD |
195 |
|
#DBSDLS-start |
196 |
< |
## Initialize the variables that are extracted from DBS/DLS and needed in other places of the code |
196 |
> |
## Initialize the variables that are extracted from DBS/DLS and needed in other places of the code |
197 |
|
self.maxEvents=0 # max events available ( --> check the requested nb. of evts in Creator.py) |
198 |
|
self.DBSPaths={} # all dbs paths requested ( --> input to the site local discovery script) |
199 |
|
self.jobDestination=[] # Site destination(s) for each job (list of lists) |
202 |
|
blockSites = {} |
203 |
|
if self.datasetPath: |
204 |
|
blockSites = self.DataDiscoveryAndLocation(cfg_params) |
205 |
< |
#DBSDLS-end |
205 |
> |
#DBSDLS-end |
206 |
> |
self.conf['blockSites']=blockSites |
207 |
|
|
271 |
– |
self.tgzNameWithPath = self.getTarBall(self.executable) |
272 |
– |
|
208 |
|
## Select Splitting |
209 |
< |
if self.selectNoInput: |
210 |
< |
if self.pset == None: #CarlosDaniele |
211 |
< |
self.jobSplittingForScript() |
209 |
> |
splitByRun = int(cfg_params.get('CMSSW.split_by_run',0)) |
210 |
> |
|
211 |
> |
if self.selectNoInput: |
212 |
> |
if self.pset == None: |
213 |
> |
self.algo = 'ForScript' |
214 |
|
else: |
215 |
< |
self.jobSplittingNoInput() |
215 |
> |
self.algo = 'NoInput' |
216 |
> |
self.conf['managedGenerators']=self.managedGenerators |
217 |
> |
self.conf['generator']=self.generator |
218 |
> |
elif splitByRun ==1: |
219 |
> |
self.algo = 'RunBased' |
220 |
|
else: |
221 |
< |
self.jobSplittingByBlocks(blockSites) |
221 |
> |
self.algo = 'EventBased' |
222 |
> |
|
223 |
> |
# self.algo = 'LumiBased' |
224 |
> |
splitter = JobSplitter(self.cfg_params,self.conf) |
225 |
> |
self.dict = splitter.Algos()[self.algo]() |
226 |
> |
|
227 |
> |
self.argsFile= '%s/arguments.xml'%common.work_space.shareDir() |
228 |
> |
self.rootArgsFilename= 'arguments' |
229 |
> |
# modify Pset only the first time |
230 |
> |
if (isNew and self.pset != None): self.ModifyPset() |
231 |
> |
|
232 |
> |
## Prepare inputSandbox TarBall (only the first time) |
233 |
> |
self.tarNameWithPath = self.getTarBall(self.executable) |
234 |
> |
|
235 |
> |
|
236 |
> |
def ModifyPset(self): |
237 |
> |
import PsetManipulator as pp |
238 |
> |
PsetEdit = pp.PsetManipulator(self.pset) |
239 |
> |
try: |
240 |
> |
# Add FrameworkJobReport to parameter-set, set max events. |
241 |
> |
# Reset later for data jobs by writeCFG which does all modifications |
242 |
> |
PsetEdit.maxEvent(1) |
243 |
> |
PsetEdit.skipEvent(0) |
244 |
> |
PsetEdit.psetWriter(self.configFilename()) |
245 |
> |
## If present, add TFileService to output files |
246 |
> |
if not int(self.cfg_params.get('CMSSW.skip_TFileService_output',0)): |
247 |
> |
tfsOutput = PsetEdit.getTFileService() |
248 |
> |
if tfsOutput: |
249 |
> |
if tfsOutput in self.output_file: |
250 |
> |
common.logger.debug("Output from TFileService "+tfsOutput+" already in output files") |
251 |
> |
else: |
252 |
> |
outfileflag = True #output found |
253 |
> |
self.output_file.append(tfsOutput) |
254 |
> |
common.logger.info("Adding "+tfsOutput+" (from TFileService) to list of output files") |
255 |
> |
pass |
256 |
> |
pass |
257 |
> |
## If present and requested, add PoolOutputModule to output files |
258 |
> |
edmOutput = PsetEdit.getPoolOutputModule() |
259 |
> |
if int(self.cfg_params.get('CMSSW.get_edm_output',0)): |
260 |
> |
if edmOutput: |
261 |
> |
if edmOutput in self.output_file: |
262 |
> |
common.logger.debug("Output from PoolOutputModule "+edmOutput+" already in output files") |
263 |
> |
else: |
264 |
> |
self.output_file.append(edmOutput) |
265 |
> |
common.logger.info("Adding "+edmOutput+" (from PoolOutputModule) to list of output files") |
266 |
> |
pass |
267 |
> |
pass |
268 |
> |
# not required: check anyhow if present, to avoid accidental T2 overload |
269 |
> |
else: |
270 |
> |
if edmOutput and (edmOutput not in self.output_file): |
271 |
> |
msg = "ERROR: a PoolOutputModule is present in your ParameteSet %s \n"%self.pset |
272 |
> |
msg +=" but the file produced ( %s ) is not in the list of output files\n"%edmOutput |
273 |
> |
msg += "WARNING: please remove it. If you want to keep it, add the file to output_files or use CMSSW.get_edm_output\n" |
274 |
> |
if int(self.cfg_params.get('CMSSW.ignore_edm_output',0)): |
275 |
> |
msg +=" CMSSW.ignore_edm_output==True : Hope you know what you are doing...\n" |
276 |
> |
common.logger.info(msg) |
277 |
> |
else: |
278 |
> |
raise CrabException(msg) |
279 |
> |
pass |
280 |
> |
pass |
281 |
> |
|
282 |
> |
if (PsetEdit.getBadFilesSetting()): |
283 |
> |
msg = "WARNING: You have set skipBadFiles to True. This will continue processing on some errors and you may not be notified." |
284 |
> |
common.logger.info(msg) |
285 |
> |
|
286 |
> |
except CrabException, msg: |
287 |
> |
common.logger.info(str(msg)) |
288 |
> |
msg='Error while manipulating ParameterSet (see previous message, if any): exiting...' |
289 |
> |
raise CrabException(msg) |
290 |
|
|
282 |
– |
# modify Pset |
283 |
– |
if self.pset != None: #CarlosDaniele |
284 |
– |
try: |
285 |
– |
if (self.datasetPath): # standard job |
286 |
– |
# allow to processa a fraction of events in a file |
287 |
– |
PsetEdit.inputModule("INPUT") |
288 |
– |
PsetEdit.maxEvent("INPUTMAXEVENTS") |
289 |
– |
PsetEdit.skipEvent("INPUTSKIPEVENTS") |
290 |
– |
else: # pythia like job |
291 |
– |
PsetEdit.maxEvent(self.eventsPerJob) |
292 |
– |
if (self.firstRun): |
293 |
– |
PsetEdit.pythiaFirstRun("INPUTFIRSTRUN") #First Run |
294 |
– |
if (self.sourceSeed) : |
295 |
– |
PsetEdit.pythiaSeed("INPUT") |
296 |
– |
if (self.sourceSeedVtx) : |
297 |
– |
PsetEdit.vtxSeed("INPUTVTX") |
298 |
– |
if (self.sourceSeedG4) : |
299 |
– |
self.PsetEdit.g4Seed("INPUTG4") |
300 |
– |
if (self.sourceSeedMix) : |
301 |
– |
self.PsetEdit.mixSeed("INPUTMIX") |
302 |
– |
# add FrameworkJobReport to parameter-set |
303 |
– |
PsetEdit.addCrabFJR(self.fjrFileName) |
304 |
– |
PsetEdit.psetWriter(self.configFilename()) |
305 |
– |
except: |
306 |
– |
msg='Error while manipuliating ParameterSet: exiting...' |
307 |
– |
raise CrabException(msg) |
291 |
|
|
292 |
|
def DataDiscoveryAndLocation(self, cfg_params): |
293 |
|
|
294 |
|
import DataDiscovery |
312 |
– |
import DataDiscovery_DBS2 |
295 |
|
import DataLocation |
296 |
< |
common.logger.debug(10,"CMSSW::DataDiscoveryAndLocation()") |
296 |
> |
common.logger.log(10-1,"CMSSW::DataDiscoveryAndLocation()") |
297 |
|
|
298 |
|
datasetPath=self.datasetPath |
299 |
|
|
300 |
|
## Contact the DBS |
301 |
< |
common.logger.message("Contacting Data Discovery Services ...") |
301 |
> |
common.logger.info("Contacting Data Discovery Services ...") |
302 |
|
try: |
303 |
< |
|
322 |
< |
if self.use_dbs_1 == 1 : |
323 |
< |
self.pubdata=DataDiscovery.DataDiscovery(datasetPath, cfg_params) |
324 |
< |
else : |
325 |
< |
self.pubdata=DataDiscovery_DBS2.DataDiscovery_DBS2(datasetPath, cfg_params) |
303 |
> |
self.pubdata=DataDiscovery.DataDiscovery(datasetPath, cfg_params,self.skip_blocks) |
304 |
|
self.pubdata.fetchDBSInfo() |
305 |
|
|
306 |
|
except DataDiscovery.NotExistingDatasetError, ex : |
312 |
|
except DataDiscovery.DataDiscoveryError, ex: |
313 |
|
msg = 'ERROR ***: failed Data Discovery in DBS : %s'%ex.getErrorMessage() |
314 |
|
raise CrabException(msg) |
337 |
– |
except DataDiscovery_DBS2.NotExistingDatasetError_DBS2, ex : |
338 |
– |
msg = 'ERROR ***: failed Data Discovery in DBS : %s'%ex.getErrorMessage() |
339 |
– |
raise CrabException(msg) |
340 |
– |
except DataDiscovery_DBS2.NoDataTierinProvenanceError_DBS2, ex : |
341 |
– |
msg = 'ERROR ***: failed Data Discovery in DBS : %s'%ex.getErrorMessage() |
342 |
– |
raise CrabException(msg) |
343 |
– |
except DataDiscovery_DBS2.DataDiscoveryError_DBS2, ex: |
344 |
– |
msg = 'ERROR ***: failed Data Discovery in DBS : %s'%ex.getErrorMessage() |
345 |
– |
raise CrabException(msg) |
315 |
|
|
316 |
|
self.filesbyblock=self.pubdata.getFiles() |
317 |
< |
self.eventsbyblock=self.pubdata.getEventsPerBlock() |
318 |
< |
self.eventsbyfile=self.pubdata.getEventsPerFile() |
317 |
> |
#print self.filesbyblock |
318 |
> |
self.conf['pubdata']=self.pubdata |
319 |
|
|
320 |
|
## get max number of events |
321 |
< |
self.maxEvents=self.pubdata.getMaxEvents() ## self.maxEvents used in Creator.py |
321 |
> |
self.maxEvents=self.pubdata.getMaxEvents() |
322 |
|
|
323 |
|
## Contact the DLS and build a list of sites hosting the fileblocks |
324 |
|
try: |
325 |
|
dataloc=DataLocation.DataLocation(self.filesbyblock.keys(),cfg_params) |
326 |
|
dataloc.fetchDLSInfo() |
327 |
+ |
|
328 |
|
except DataLocation.DataLocationError , ex: |
329 |
|
msg = 'ERROR ***: failed Data Location in DLS \n %s '%ex.getErrorMessage() |
330 |
|
raise CrabException(msg) |
361 |
– |
|
331 |
|
|
332 |
< |
sites = dataloc.getSites() |
332 |
> |
|
333 |
> |
unsorted_sites = dataloc.getSites() |
334 |
> |
sites = self.filesbyblock.fromkeys(self.filesbyblock,'') |
335 |
> |
for lfn in self.filesbyblock.keys(): |
336 |
> |
if unsorted_sites.has_key(lfn): |
337 |
> |
sites[lfn]=unsorted_sites[lfn] |
338 |
> |
else: |
339 |
> |
sites[lfn]=[] |
340 |
> |
|
341 |
> |
if len(sites)==0: |
342 |
> |
msg = 'ERROR ***: no location for any of the blocks of this dataset: \n\t %s \n'%datasetPath |
343 |
> |
msg += "\tMaybe the dataset is located only at T1's (or at T0), where analysis jobs are not allowed\n" |
344 |
> |
msg += "\tPlease check DataDiscovery page https://cmsweb.cern.ch/dbs_discovery/\n" |
345 |
> |
raise CrabException(msg) |
346 |
> |
|
347 |
|
allSites = [] |
348 |
|
listSites = sites.values() |
349 |
|
for listSite in listSites: |
350 |
|
for oneSite in listSite: |
351 |
|
allSites.append(oneSite) |
352 |
< |
allSites = self.uniquelist(allSites) |
352 |
> |
[allSites.append(it) for it in allSites if not allSites.count(it)] |
353 |
> |
|
354 |
|
|
355 |
|
# screen output |
356 |
< |
common.logger.message("Requested dataset: " + datasetPath + " has " + str(self.maxEvents) + " events in " + str(len(self.filesbyblock.keys())) + " blocks.\n") |
356 |
> |
common.logger.info("Requested dataset: " + datasetPath + " has " + str(self.maxEvents) + " events in " + str(len(self.filesbyblock.keys())) + " blocks.\n") |
357 |
|
|
358 |
|
return sites |
375 |
– |
|
376 |
– |
def jobSplittingByBlocks(self, blockSites): |
377 |
– |
""" |
378 |
– |
Perform job splitting. Jobs run over an integer number of files |
379 |
– |
and no more than one block. |
380 |
– |
ARGUMENT: blockSites: dictionary with blocks as keys and list of host sites as values |
381 |
– |
REQUIRES: self.selectTotalNumberEvents, self.selectEventsPerJob, self.selectNumberofJobs, |
382 |
– |
self.total_number_of_events, self.eventsPerJob, self.theNumberOfJobs, |
383 |
– |
self.maxEvents, self.filesbyblock |
384 |
– |
SETS: self.jobDestination - Site destination(s) for each job (a list of lists) |
385 |
– |
self.total_number_of_jobs - Total # of jobs |
386 |
– |
self.list_of_args - File(s) job will run on (a list of lists) |
387 |
– |
""" |
388 |
– |
|
389 |
– |
# ---- Handle the possible job splitting configurations ---- # |
390 |
– |
if (self.selectTotalNumberEvents): |
391 |
– |
totalEventsRequested = self.total_number_of_events |
392 |
– |
if (self.selectEventsPerJob): |
393 |
– |
eventsPerJobRequested = self.eventsPerJob |
394 |
– |
if (self.selectNumberOfJobs): |
395 |
– |
totalEventsRequested = self.theNumberOfJobs * self.eventsPerJob |
396 |
– |
|
397 |
– |
# If user requested all the events in the dataset |
398 |
– |
if (totalEventsRequested == -1): |
399 |
– |
eventsRemaining=self.maxEvents |
400 |
– |
# If user requested more events than are in the dataset |
401 |
– |
elif (totalEventsRequested > self.maxEvents): |
402 |
– |
eventsRemaining = self.maxEvents |
403 |
– |
common.logger.message("Requested "+str(self.total_number_of_events)+ " events, but only "+str(self.maxEvents)+" events are available.") |
404 |
– |
# If user requested less events than are in the dataset |
405 |
– |
else: |
406 |
– |
eventsRemaining = totalEventsRequested |
359 |
|
|
408 |
– |
# If user requested more events per job than are in the dataset |
409 |
– |
if (self.selectEventsPerJob and eventsPerJobRequested > self.maxEvents): |
410 |
– |
eventsPerJobRequested = self.maxEvents |
411 |
– |
|
412 |
– |
# For user info at end |
413 |
– |
totalEventCount = 0 |
414 |
– |
|
415 |
– |
if (self.selectTotalNumberEvents and self.selectNumberOfJobs): |
416 |
– |
eventsPerJobRequested = int(eventsRemaining/self.theNumberOfJobs) |
417 |
– |
|
418 |
– |
if (self.selectNumberOfJobs): |
419 |
– |
common.logger.message("May not create the exact number_of_jobs requested.") |
420 |
– |
|
421 |
– |
if ( self.ncjobs == 'all' ) : |
422 |
– |
totalNumberOfJobs = 999999999 |
423 |
– |
else : |
424 |
– |
totalNumberOfJobs = self.ncjobs |
425 |
– |
|
426 |
– |
|
427 |
– |
blocks = blockSites.keys() |
428 |
– |
blockCount = 0 |
429 |
– |
# Backup variable in case self.maxEvents counted events in a non-included block |
430 |
– |
numBlocksInDataset = len(blocks) |
431 |
– |
|
432 |
– |
jobCount = 0 |
433 |
– |
list_of_lists = [] |
434 |
– |
|
435 |
– |
# list tracking which jobs are in which jobs belong to which block |
436 |
– |
jobsOfBlock = {} |
437 |
– |
|
438 |
– |
# ---- Iterate over the blocks in the dataset until ---- # |
439 |
– |
# ---- we've met the requested total # of events ---- # |
440 |
– |
while ( (eventsRemaining > 0) and (blockCount < numBlocksInDataset) and (jobCount < totalNumberOfJobs)): |
441 |
– |
block = blocks[blockCount] |
442 |
– |
blockCount += 1 |
443 |
– |
|
444 |
– |
if self.eventsbyblock.has_key(block) : |
445 |
– |
numEventsInBlock = self.eventsbyblock[block] |
446 |
– |
common.logger.debug(5,'Events in Block File '+str(numEventsInBlock)) |
447 |
– |
|
448 |
– |
files = self.filesbyblock[block] |
449 |
– |
numFilesInBlock = len(files) |
450 |
– |
if (numFilesInBlock <= 0): |
451 |
– |
continue |
452 |
– |
fileCount = 0 |
360 |
|
|
361 |
< |
# ---- New block => New job ---- # |
362 |
< |
parString = "\\{" |
363 |
< |
# counter for number of events in files currently worked on |
364 |
< |
filesEventCount = 0 |
365 |
< |
# flag if next while loop should touch new file |
459 |
< |
newFile = 1 |
460 |
< |
# job event counter |
461 |
< |
jobSkipEventCount = 0 |
462 |
< |
|
463 |
< |
# ---- Iterate over the files in the block until we've met the requested ---- # |
464 |
< |
# ---- total # of events or we've gone over all the files in this block ---- # |
465 |
< |
while ( (eventsRemaining > 0) and (fileCount < numFilesInBlock) and (jobCount < totalNumberOfJobs) ): |
466 |
< |
file = files[fileCount] |
467 |
< |
if newFile : |
468 |
< |
try: |
469 |
< |
numEventsInFile = self.eventsbyfile[file] |
470 |
< |
common.logger.debug(6, "File "+str(file)+" has "+str(numEventsInFile)+" events") |
471 |
< |
# increase filesEventCount |
472 |
< |
filesEventCount += numEventsInFile |
473 |
< |
# Add file to current job |
474 |
< |
parString += '\\\"' + file + '\\\"\,' |
475 |
< |
newFile = 0 |
476 |
< |
except KeyError: |
477 |
< |
common.logger.message("File "+str(file)+" has unknown number of events: skipping") |
478 |
< |
|
479 |
< |
|
480 |
< |
# if less events in file remain than eventsPerJobRequested |
481 |
< |
if ( filesEventCount - jobSkipEventCount < eventsPerJobRequested ) : |
482 |
< |
# if last file in block |
483 |
< |
if ( fileCount == numFilesInBlock-1 ) : |
484 |
< |
# end job using last file, use remaining events in block |
485 |
< |
# close job and touch new file |
486 |
< |
fullString = parString[:-2] |
487 |
< |
fullString += '\\}' |
488 |
< |
list_of_lists.append([fullString,str(-1),str(jobSkipEventCount)]) |
489 |
< |
common.logger.debug(3,"Job "+str(jobCount+1)+" can run over "+str(filesEventCount - jobSkipEventCount)+" events (last file in block).") |
490 |
< |
self.jobDestination.append(blockSites[block]) |
491 |
< |
common.logger.debug(5,"Job "+str(jobCount+1)+" Destination: "+str(self.jobDestination[jobCount])) |
492 |
< |
# fill jobs of block dictionary |
493 |
< |
if block in jobsOfBlock.keys() : |
494 |
< |
jobsOfBlock[block].append(jobCount+1) |
495 |
< |
else: |
496 |
< |
jobsOfBlock[block] = [jobCount+1] |
497 |
< |
# reset counter |
498 |
< |
jobCount = jobCount + 1 |
499 |
< |
totalEventCount = totalEventCount + filesEventCount - jobSkipEventCount |
500 |
< |
eventsRemaining = eventsRemaining - filesEventCount + jobSkipEventCount |
501 |
< |
jobSkipEventCount = 0 |
502 |
< |
# reset file |
503 |
< |
parString = "\\{" |
504 |
< |
filesEventCount = 0 |
505 |
< |
newFile = 1 |
506 |
< |
fileCount += 1 |
507 |
< |
else : |
508 |
< |
# go to next file |
509 |
< |
newFile = 1 |
510 |
< |
fileCount += 1 |
511 |
< |
# if events in file equal to eventsPerJobRequested |
512 |
< |
elif ( filesEventCount - jobSkipEventCount == eventsPerJobRequested ) : |
513 |
< |
# close job and touch new file |
514 |
< |
fullString = parString[:-2] |
515 |
< |
fullString += '\\}' |
516 |
< |
list_of_lists.append([fullString,str(eventsPerJobRequested),str(jobSkipEventCount)]) |
517 |
< |
common.logger.debug(3,"Job "+str(jobCount+1)+" can run over "+str(eventsPerJobRequested)+" events.") |
518 |
< |
self.jobDestination.append(blockSites[block]) |
519 |
< |
common.logger.debug(5,"Job "+str(jobCount+1)+" Destination: "+str(self.jobDestination[jobCount])) |
520 |
< |
if block in jobsOfBlock.keys() : |
521 |
< |
jobsOfBlock[block].append(jobCount+1) |
522 |
< |
else: |
523 |
< |
jobsOfBlock[block] = [jobCount+1] |
524 |
< |
# reset counter |
525 |
< |
jobCount = jobCount + 1 |
526 |
< |
totalEventCount = totalEventCount + eventsPerJobRequested |
527 |
< |
eventsRemaining = eventsRemaining - eventsPerJobRequested |
528 |
< |
jobSkipEventCount = 0 |
529 |
< |
# reset file |
530 |
< |
parString = "\\{" |
531 |
< |
filesEventCount = 0 |
532 |
< |
newFile = 1 |
533 |
< |
fileCount += 1 |
534 |
< |
|
535 |
< |
# if more events in file remain than eventsPerJobRequested |
536 |
< |
else : |
537 |
< |
# close job but don't touch new file |
538 |
< |
fullString = parString[:-2] |
539 |
< |
fullString += '\\}' |
540 |
< |
list_of_lists.append([fullString,str(eventsPerJobRequested),str(jobSkipEventCount)]) |
541 |
< |
common.logger.debug(3,"Job "+str(jobCount+1)+" can run over "+str(eventsPerJobRequested)+" events.") |
542 |
< |
self.jobDestination.append(blockSites[block]) |
543 |
< |
common.logger.debug(5,"Job "+str(jobCount+1)+" Destination: "+str(self.jobDestination[jobCount])) |
544 |
< |
if block in jobsOfBlock.keys() : |
545 |
< |
jobsOfBlock[block].append(jobCount+1) |
546 |
< |
else: |
547 |
< |
jobsOfBlock[block] = [jobCount+1] |
548 |
< |
# increase counter |
549 |
< |
jobCount = jobCount + 1 |
550 |
< |
totalEventCount = totalEventCount + eventsPerJobRequested |
551 |
< |
eventsRemaining = eventsRemaining - eventsPerJobRequested |
552 |
< |
# calculate skip events for last file |
553 |
< |
# use filesEventCount (contains several files), jobSkipEventCount and eventsPerJobRequest |
554 |
< |
jobSkipEventCount = eventsPerJobRequested - (filesEventCount - jobSkipEventCount - self.eventsbyfile[file]) |
555 |
< |
# remove all but the last file |
556 |
< |
filesEventCount = self.eventsbyfile[file] |
557 |
< |
parString = "\\{" |
558 |
< |
parString += '\\\"' + file + '\\\"\,' |
559 |
< |
pass # END if |
560 |
< |
pass # END while (iterate over files in the block) |
561 |
< |
pass # END while (iterate over blocks in the dataset) |
562 |
< |
self.ncjobs = self.total_number_of_jobs = jobCount |
563 |
< |
if (eventsRemaining > 0 and jobCount < totalNumberOfJobs ): |
564 |
< |
common.logger.message("Could not run on all requested events because some blocks not hosted at allowed sites.") |
565 |
< |
common.logger.message(str(jobCount)+" job(s) can run on "+str(totalEventCount)+" events.\n") |
566 |
< |
|
567 |
< |
# screen output |
568 |
< |
screenOutput = "List of jobs and available destination sites:\n\n" |
361 |
> |
def split(self, jobParams,firstJobID): |
362 |
> |
|
363 |
> |
jobParams = self.dict['args'] |
364 |
> |
njobs = self.dict['njobs'] |
365 |
> |
self.jobDestination = self.dict['jobDestination'] |
366 |
|
|
367 |
< |
blockCounter = 0 |
368 |
< |
for block in jobsOfBlock.keys(): |
572 |
< |
blockCounter += 1 |
573 |
< |
screenOutput += "Block %5i: jobs %20s: sites: %s\n" % (blockCounter,spanRanges(jobsOfBlock[block]),','.join(blockSites[block])) |
367 |
> |
if njobs==0: |
368 |
> |
raise CrabException("Ask to split "+str(njobs)+" jobs: aborting") |
369 |
|
|
370 |
< |
common.logger.message(screenOutput) |
370 |
> |
# create the empty structure |
371 |
> |
for i in range(njobs): |
372 |
> |
jobParams.append("") |
373 |
|
|
374 |
< |
self.list_of_args = list_of_lists |
374 |
> |
listID=[] |
375 |
> |
listField=[] |
376 |
> |
listDictions=[] |
377 |
> |
exist= os.path.exists(self.argsFile) |
378 |
> |
for id in range(njobs): |
379 |
> |
job = id + int(firstJobID) |
380 |
> |
listID.append(job+1) |
381 |
> |
job_ToSave ={} |
382 |
> |
concString = ' ' |
383 |
> |
argu='' |
384 |
> |
str_argu = str(job+1) |
385 |
> |
if len(jobParams[id]): |
386 |
> |
argu = {'JobID': job+1} |
387 |
> |
for i in range(len(jobParams[id])): |
388 |
> |
argu[self.dict['params'][i]]=jobParams[id][i] |
389 |
> |
# just for debug |
390 |
> |
str_argu += concString.join(jobParams[id]) |
391 |
> |
if argu != '': listDictions.append(argu) |
392 |
> |
job_ToSave['arguments']= str(job+1) |
393 |
> |
job_ToSave['dlsDestination']= self.jobDestination[id] |
394 |
> |
listField.append(job_ToSave) |
395 |
> |
from ProdCommon.SiteDB.CmsSiteMapper import CmsSEMap |
396 |
> |
cms_se = CmsSEMap() |
397 |
> |
msg="Job %s Arguments: %s\n"%(str(job+1),str_argu) |
398 |
> |
msg+="\t Destination: %s "%(str(self.jobDestination[id])) |
399 |
> |
SEDestination = [cms_se[dest] for dest in self.jobDestination[id]] |
400 |
> |
msg+="\t CMSDestination: %s "%(str(SEDestination)) |
401 |
> |
common.logger.log(10-1,msg) |
402 |
> |
# write xml |
403 |
> |
if len(listDictions): |
404 |
> |
if exist==False: self.CreateXML() |
405 |
> |
self.addEntry(listDictions) |
406 |
> |
self.addXMLfile() |
407 |
> |
common._db.updateJob_(listID,listField) |
408 |
> |
self.zipTarFile() |
409 |
|
return |
410 |
|
|
411 |
< |
def jobSplittingNoInput(self): |
581 |
< |
""" |
582 |
< |
Perform job splitting based on number of event per job |
583 |
< |
""" |
584 |
< |
common.logger.debug(5,'Splitting per events') |
585 |
< |
common.logger.message('Required '+str(self.eventsPerJob)+' events per job ') |
586 |
< |
common.logger.message('Required '+str(self.theNumberOfJobs)+' jobs in total ') |
587 |
< |
common.logger.message('Required '+str(self.total_number_of_events)+' events in total ') |
411 |
> |
def addXMLfile(self): |
412 |
|
|
413 |
< |
if (self.total_number_of_events < 0): |
414 |
< |
msg='Cannot split jobs per Events with "-1" as total number of events' |
413 |
> |
import tarfile |
414 |
> |
try: |
415 |
> |
tar = tarfile.open(self.tarNameWithPath, "a") |
416 |
> |
tar.add(self.argsFile, os.path.basename(self.argsFile)) |
417 |
> |
tar.close() |
418 |
> |
except IOError, exc: |
419 |
> |
msg = 'Could not add %s to %s \n'%(self.argsFile,self.tarNameWithPath) |
420 |
> |
msg += str(exc) |
421 |
> |
raise CrabException(msg) |
422 |
> |
except tarfile.TarError, exc: |
423 |
> |
msg = 'Could not add %s to %s \n'%(self.argsFile,self.tarNameWithPath) |
424 |
> |
msg += str(exc) |
425 |
|
raise CrabException(msg) |
426 |
|
|
427 |
< |
if (self.selectEventsPerJob): |
594 |
< |
if (self.selectTotalNumberEvents): |
595 |
< |
self.total_number_of_jobs = int(self.total_number_of_events/self.eventsPerJob) |
596 |
< |
elif(self.selectNumberOfJobs) : |
597 |
< |
self.total_number_of_jobs =self.theNumberOfJobs |
598 |
< |
self.total_number_of_events =int(self.theNumberOfJobs*self.eventsPerJob) |
599 |
< |
|
600 |
< |
elif (self.selectNumberOfJobs) : |
601 |
< |
self.total_number_of_jobs = self.theNumberOfJobs |
602 |
< |
self.eventsPerJob = int(self.total_number_of_events/self.total_number_of_jobs) |
603 |
< |
|
604 |
< |
common.logger.debug(5,'N jobs '+str(self.total_number_of_jobs)) |
605 |
< |
|
606 |
< |
# is there any remainder? |
607 |
< |
check = int(self.total_number_of_events) - (int(self.total_number_of_jobs)*self.eventsPerJob) |
608 |
< |
|
609 |
< |
common.logger.debug(5,'Check '+str(check)) |
610 |
< |
|
611 |
< |
common.logger.message(str(self.total_number_of_jobs)+' jobs can be created, each for '+str(self.eventsPerJob)+' for a total of '+str(self.total_number_of_jobs*self.eventsPerJob)+' events') |
612 |
< |
if check > 0: |
613 |
< |
common.logger.message('Warning: asked '+str(self.total_number_of_events)+' but can do only '+str(int(self.total_number_of_jobs)*self.eventsPerJob)) |
614 |
< |
|
615 |
< |
# argument is seed number.$i |
616 |
< |
self.list_of_args = [] |
617 |
< |
for i in range(self.total_number_of_jobs): |
618 |
< |
## Since there is no input, any site is good |
619 |
< |
# self.jobDestination.append(["Any"]) |
620 |
< |
self.jobDestination.append([""]) #must be empty to write correctly the xml |
621 |
< |
args=[] |
622 |
< |
if (self.firstRun): |
623 |
< |
## pythia first run |
624 |
< |
#self.list_of_args.append([(str(self.firstRun)+str(i))]) |
625 |
< |
args.append(str(self.firstRun)+str(i)) |
626 |
< |
else: |
627 |
< |
## no first run |
628 |
< |
#self.list_of_args.append([str(i)]) |
629 |
< |
args.append(str(i)) |
630 |
< |
if (self.sourceSeed): |
631 |
< |
args.append(str(self.sourceSeed)+str(i)) |
632 |
< |
if (self.sourceSeedVtx): |
633 |
< |
## + vtx random seed |
634 |
< |
args.append(str(self.sourceSeedVtx)+str(i)) |
635 |
< |
if (self.sourceSeedG4): |
636 |
< |
## + G4 random seed |
637 |
< |
args.append(str(self.sourceSeedG4)+str(i)) |
638 |
< |
if (self.sourceSeedMix): |
639 |
< |
## + Mix random seed |
640 |
< |
args.append(str(self.sourceSeedMix)+str(i)) |
641 |
< |
pass |
642 |
< |
pass |
643 |
< |
self.list_of_args.append(args) |
644 |
< |
pass |
645 |
< |
|
646 |
< |
# print self.list_of_args |
647 |
< |
|
648 |
< |
return |
649 |
< |
|
650 |
< |
|
651 |
< |
def jobSplittingForScript(self):#CarlosDaniele |
427 |
> |
def CreateXML(self): |
428 |
|
""" |
653 |
– |
Perform job splitting based on number of job |
429 |
|
""" |
430 |
< |
common.logger.debug(5,'Splitting per job') |
431 |
< |
common.logger.message('Required '+str(self.theNumberOfJobs)+' jobs in total ') |
657 |
< |
|
658 |
< |
self.total_number_of_jobs = self.theNumberOfJobs |
659 |
< |
|
660 |
< |
common.logger.debug(5,'N jobs '+str(self.total_number_of_jobs)) |
661 |
< |
|
662 |
< |
common.logger.message(str(self.total_number_of_jobs)+' jobs can be created') |
663 |
< |
|
664 |
< |
# argument is seed number.$i |
665 |
< |
self.list_of_args = [] |
666 |
< |
for i in range(self.total_number_of_jobs): |
667 |
< |
## Since there is no input, any site is good |
668 |
< |
# self.jobDestination.append(["Any"]) |
669 |
< |
self.jobDestination.append([""]) |
670 |
< |
## no random seed |
671 |
< |
self.list_of_args.append([str(i)]) |
430 |
> |
result = IMProvNode( self.rootArgsFilename ) |
431 |
> |
outfile = file( self.argsFile, 'w').write(str(result)) |
432 |
|
return |
433 |
|
|
434 |
< |
def split(self, jobParams): |
435 |
< |
|
436 |
< |
common.jobDB.load() |
677 |
< |
#### Fabio |
678 |
< |
njobs = self.total_number_of_jobs |
679 |
< |
arglist = self.list_of_args |
680 |
< |
# create the empty structure |
681 |
< |
for i in range(njobs): |
682 |
< |
jobParams.append("") |
683 |
< |
|
684 |
< |
for job in range(njobs): |
685 |
< |
jobParams[job] = arglist[job] |
686 |
< |
# print str(arglist[job]) |
687 |
< |
# print jobParams[job] |
688 |
< |
common.jobDB.setArguments(job, jobParams[job]) |
689 |
< |
common.logger.debug(5,"Job "+str(job)+" Destination: "+str(self.jobDestination[job])) |
690 |
< |
common.jobDB.setDestination(job, self.jobDestination[job]) |
434 |
> |
def addEntry(self, listDictions): |
435 |
> |
""" |
436 |
> |
_addEntry_ |
437 |
|
|
438 |
< |
common.jobDB.save() |
438 |
> |
add an entry to the xml file |
439 |
> |
""" |
440 |
> |
from IMProv.IMProvLoader import loadIMProvFile |
441 |
> |
## load xml |
442 |
> |
improvDoc = loadIMProvFile(self.argsFile) |
443 |
> |
entrname= 'Job' |
444 |
> |
for dictions in listDictions: |
445 |
> |
report = IMProvNode(entrname , None, **dictions) |
446 |
> |
improvDoc.addNode(report) |
447 |
> |
outfile = file( self.argsFile, 'w').write(str(improvDoc)) |
448 |
|
return |
449 |
< |
|
695 |
< |
def getJobTypeArguments(self, nj, sched): |
696 |
< |
result = '' |
697 |
< |
for i in common.jobDB.arguments(nj): |
698 |
< |
result=result+str(i)+" " |
699 |
< |
return result |
700 |
< |
|
449 |
> |
|
450 |
|
def numberOfJobs(self): |
451 |
< |
# Fabio |
703 |
< |
return self.total_number_of_jobs |
451 |
> |
return self.dict['njobs'] |
452 |
|
|
453 |
|
def getTarBall(self, exe): |
454 |
|
""" |
455 |
|
Return the TarBall with lib and exe |
456 |
|
""" |
457 |
< |
|
458 |
< |
# if it exist, just return it |
459 |
< |
# |
712 |
< |
# Marco. Let's start to use relative path for Boss XML files |
713 |
< |
# |
714 |
< |
self.tgzNameWithPath = common.work_space.pathForTgz()+'share/'+self.tgz_name |
715 |
< |
if os.path.exists(self.tgzNameWithPath): |
716 |
< |
return self.tgzNameWithPath |
457 |
> |
self.tarNameWithPath = common.work_space.pathForTgz()+self.tar_name |
458 |
> |
if os.path.exists(self.tarNameWithPath): |
459 |
> |
return self.tarNameWithPath |
460 |
|
|
461 |
|
# Prepare a tar gzipped file with user binaries. |
462 |
|
self.buildTar_(exe) |
463 |
|
|
464 |
< |
return string.strip(self.tgzNameWithPath) |
464 |
> |
return string.strip(self.tarNameWithPath) |
465 |
|
|
466 |
|
def buildTar_(self, executable): |
467 |
|
|
468 |
|
# First of all declare the user Scram area |
469 |
|
swArea = self.scram.getSWArea_() |
727 |
– |
#print "swArea = ", swArea |
728 |
– |
# swVersion = self.scram.getSWVersion() |
729 |
– |
# print "swVersion = ", swVersion |
470 |
|
swReleaseTop = self.scram.getReleaseTop_() |
471 |
< |
#print "swReleaseTop = ", swReleaseTop |
732 |
< |
|
471 |
> |
|
472 |
|
## check if working area is release top |
473 |
|
if swReleaseTop == '' or swArea == swReleaseTop: |
474 |
+ |
common.logger.debug("swArea = "+swArea+" swReleaseTop ="+swReleaseTop) |
475 |
|
return |
476 |
|
|
477 |
|
import tarfile |
478 |
|
try: # create tar ball |
479 |
< |
tar = tarfile.open(self.tgzNameWithPath, "w:gz") |
479 |
> |
#tar = tarfile.open(self.tgzNameWithPath, "w:gz") |
480 |
> |
tar = tarfile.open(self.tarNameWithPath, "w") |
481 |
|
## First find the executable |
482 |
|
if (self.executable != ''): |
483 |
|
exeWithPath = self.scram.findFile_(executable) |
484 |
|
if ( not exeWithPath ): |
485 |
|
raise CrabException('User executable '+executable+' not found') |
486 |
< |
|
486 |
> |
|
487 |
|
## then check if it's private or not |
488 |
|
if exeWithPath.find(swReleaseTop) == -1: |
489 |
|
# the exe is private, so we must ship |
490 |
< |
common.logger.debug(5,"Exe "+exeWithPath+" to be tarred") |
490 |
> |
common.logger.debug("Exe "+exeWithPath+" to be tarred") |
491 |
|
path = swArea+'/' |
492 |
|
# distinguish case when script is in user project area or given by full path somewhere else |
493 |
|
if exeWithPath.find(path) >= 0 : |
494 |
|
exe = string.replace(exeWithPath, path,'') |
495 |
< |
tar.add(path+exe,os.path.basename(executable)) |
495 |
> |
tar.add(path+exe,exe) |
496 |
|
else : |
497 |
|
tar.add(exeWithPath,os.path.basename(executable)) |
498 |
|
pass |
499 |
|
else: |
500 |
|
# the exe is from release, we'll find it on WN |
501 |
|
pass |
502 |
< |
|
502 |
> |
|
503 |
|
## Now get the libraries: only those in local working area |
504 |
+ |
tar.dereference=True |
505 |
|
libDir = 'lib' |
506 |
|
lib = swArea+'/' +libDir |
507 |
< |
common.logger.debug(5,"lib "+lib+" to be tarred") |
507 |
> |
common.logger.debug("lib "+lib+" to be tarred") |
508 |
|
if os.path.exists(lib): |
509 |
|
tar.add(lib,libDir) |
510 |
< |
|
510 |
> |
|
511 |
|
## Now check if module dir is present |
512 |
|
moduleDir = 'module' |
513 |
|
module = swArea + '/' + moduleDir |
514 |
|
if os.path.isdir(module): |
515 |
|
tar.add(module,moduleDir) |
516 |
+ |
tar.dereference=False |
517 |
|
|
518 |
|
## Now check if any data dir(s) is present |
519 |
< |
swAreaLen=len(swArea) |
520 |
< |
for root, dirs, files in os.walk(swArea): |
521 |
< |
if "data" in dirs: |
522 |
< |
common.logger.debug(5,"data "+root+"/data"+" to be tarred") |
523 |
< |
tar.add(root+"/data",root[swAreaLen:]+"/data") |
524 |
< |
|
525 |
< |
## Add ProdAgent dir to tar |
526 |
< |
paDir = 'ProdAgentApi' |
527 |
< |
pa = os.environ['CRABDIR'] + '/' + 'ProdAgentApi' |
528 |
< |
if os.path.isdir(pa): |
529 |
< |
tar.add(pa,paDir) |
530 |
< |
|
531 |
< |
### FEDE FOR DBS PUBLICATION |
532 |
< |
## Add PRODCOMMON dir to tar |
533 |
< |
prodcommonDir = 'ProdCommon' |
534 |
< |
prodcommonPath = os.environ['CRABDIR'] + '/' + 'ProdCommon' |
535 |
< |
if os.path.isdir(prodcommonPath): |
536 |
< |
tar.add(prodcommonPath,prodcommonDir) |
537 |
< |
############################# |
538 |
< |
|
539 |
< |
common.logger.debug(5,"Files added to "+self.tgzNameWithPath+" : "+str(tar.getnames())) |
519 |
> |
self.dataExist = False |
520 |
> |
todo_list = [(i, i) for i in os.listdir(swArea+"/src")] |
521 |
> |
while len(todo_list): |
522 |
> |
entry, name = todo_list.pop() |
523 |
> |
if name.startswith('crab_0_') or name.startswith('.') or name == 'CVS': |
524 |
> |
continue |
525 |
> |
if os.path.isdir(swArea+"/src/"+entry): |
526 |
> |
entryPath = entry + '/' |
527 |
> |
todo_list += [(entryPath + i, i) for i in os.listdir(swArea+"/src/"+entry)] |
528 |
> |
if name == 'data': |
529 |
> |
self.dataExist=True |
530 |
> |
common.logger.debug("data "+entry+" to be tarred") |
531 |
> |
tar.add(swArea+"/src/"+entry,"src/"+entry) |
532 |
> |
pass |
533 |
> |
pass |
534 |
> |
|
535 |
> |
### CMSSW ParameterSet |
536 |
> |
if not self.pset is None: |
537 |
> |
cfg_file = common.work_space.jobDir()+self.configFilename() |
538 |
> |
tar.add(cfg_file,self.configFilename()) |
539 |
> |
|
540 |
> |
try: |
541 |
> |
crab_cfg_file = common.work_space.shareDir()+'/crab.cfg' |
542 |
> |
tar.add(crab_cfg_file,'crab.cfg') |
543 |
> |
except: |
544 |
> |
pass |
545 |
> |
|
546 |
> |
## Add ProdCommon dir to tar |
547 |
> |
prodcommonDir = './' |
548 |
> |
prodcommonPath = os.environ['CRABDIR'] + '/' + 'external/' |
549 |
> |
neededStuff = ['ProdCommon/__init__.py','ProdCommon/FwkJobRep', 'ProdCommon/CMSConfigTools', \ |
550 |
> |
'ProdCommon/Core', 'ProdCommon/MCPayloads', 'IMProv', 'ProdCommon/Storage', \ |
551 |
> |
'WMCore/__init__.py','WMCore/Algorithms'] |
552 |
> |
for file in neededStuff: |
553 |
> |
tar.add(prodcommonPath+file,prodcommonDir+file) |
554 |
> |
|
555 |
> |
##### ML stuff |
556 |
> |
ML_file_list=['report.py', 'DashboardAPI.py', 'Logger.py', 'ProcInfo.py', 'apmon.py'] |
557 |
> |
path=os.environ['CRABDIR'] + '/python/' |
558 |
> |
for file in ML_file_list: |
559 |
> |
tar.add(path+file,file) |
560 |
> |
|
561 |
> |
##### Utils |
562 |
> |
Utils_file_list=['parseCrabFjr.py','writeCfg.py', 'fillCrabFjr.py','cmscp.py'] |
563 |
> |
for file in Utils_file_list: |
564 |
> |
tar.add(path+file,file) |
565 |
> |
|
566 |
> |
##### AdditionalFiles |
567 |
> |
tar.dereference=True |
568 |
> |
for file in self.additional_inbox_files: |
569 |
> |
tar.add(file,string.split(file,'/')[-1]) |
570 |
> |
tar.dereference=False |
571 |
> |
common.logger.log(10-1,"Files in "+self.tarNameWithPath+" : "+str(tar.getnames())) |
572 |
> |
|
573 |
|
tar.close() |
574 |
< |
except : |
575 |
< |
raise CrabException('Could not create tar-ball') |
574 |
> |
except IOError, exc: |
575 |
> |
msg = 'Could not create tar-ball %s \n'%self.tarNameWithPath |
576 |
> |
msg += str(exc) |
577 |
> |
raise CrabException(msg) |
578 |
> |
except tarfile.TarError, exc: |
579 |
> |
msg = 'Could not create tar-ball %s \n'%self.tarNameWithPath |
580 |
> |
msg += str(exc) |
581 |
> |
raise CrabException(msg) |
582 |
> |
|
583 |
> |
def zipTarFile(self): |
584 |
> |
|
585 |
> |
cmd = "gzip -c %s > %s "%(self.tarNameWithPath,self.tgzNameWithPath) |
586 |
> |
res=runCommand(cmd) |
587 |
|
|
801 |
– |
## check for tarball size |
588 |
|
tarballinfo = os.stat(self.tgzNameWithPath) |
589 |
|
if ( tarballinfo.st_size > self.MaxTarBallSize*1024*1024 ) : |
590 |
< |
raise CrabException('Input sandbox size of ' + str(float(tarballinfo.st_size)/1024.0/1024.0) + ' MB is larger than the allowed ' + str(self.MaxTarBallSize) + ' MB input sandbox limit and not supported by the used GRID submission system. Please make sure that no unnecessary files are in all data directories in your local CMSSW project area as they are automatically packed into the input sandbox.') |
590 |
> |
msg = 'Input sandbox size of ' + str(float(tarballinfo.st_size)/1024.0/1024.0) + ' MB is larger than the allowed ' + str(self.MaxTarBallSize) \ |
591 |
> |
+'MB input sandbox limit \n' |
592 |
> |
msg += ' and not supported by the direct GRID submission system.\n' |
593 |
> |
msg += ' Please use the CRAB server mode by setting server_name=<NAME> in section [CRAB] of your crab.cfg.\n' |
594 |
> |
msg += ' For further infos please see https://twiki.cern.ch/twiki/bin/view/CMS/CrabServer#CRABSERVER_for_Users' |
595 |
> |
raise CrabException(msg) |
596 |
|
|
597 |
|
## create tar-ball with ML stuff |
598 |
< |
self.MLtgzfile = common.work_space.pathForTgz()+'share/MLfiles.tgz' |
599 |
< |
try: |
809 |
< |
tar = tarfile.open(self.MLtgzfile, "w:gz") |
810 |
< |
path=os.environ['CRABDIR'] + '/python/' |
811 |
< |
for file in ['report.py', 'DashboardAPI.py', 'Logger.py', 'ProcInfo.py', 'apmon.py', 'parseCrabFjr.py']: |
812 |
< |
tar.add(path+file,file) |
813 |
< |
common.logger.debug(5,"Files added to "+self.MLtgzfile+" : "+str(tar.getnames())) |
814 |
< |
tar.close() |
815 |
< |
except : |
816 |
< |
raise CrabException('Could not create ML files tar-ball') |
817 |
< |
|
818 |
< |
return |
819 |
< |
|
820 |
< |
def wsSetupEnvironment(self, nj): |
598 |
> |
|
599 |
> |
def wsSetupEnvironment(self, nj=0): |
600 |
|
""" |
601 |
|
Returns part of a job script which prepares |
602 |
|
the execution environment for the job 'nj'. |
603 |
|
""" |
604 |
+ |
# FUTURE: Drop support for .cfg when possible |
605 |
+ |
if (self.CMSSW_major >= 2 and self.CMSSW_minor >= 1) or (self.CMSSW_major >= 3): |
606 |
+ |
psetName = 'pset.py' |
607 |
+ |
else: |
608 |
+ |
psetName = 'pset.cfg' |
609 |
|
# Prepare JobType-independent part |
610 |
< |
txt = '' |
611 |
< |
|
612 |
< |
## OLI_Daniele at this level middleware already known |
829 |
< |
|
830 |
< |
txt += 'if [ $middleware == LCG ]; then \n' |
610 |
> |
txt = '\n#Written by cms_cmssw::wsSetupEnvironment\n' |
611 |
> |
txt += 'echo ">>> setup environment"\n' |
612 |
> |
txt += 'if [ $middleware == LCG ] || [ $middleware == CAF ] || [ $middleware == LSF ]; then \n' |
613 |
|
txt += self.wsSetupCMSLCGEnvironment_() |
614 |
|
txt += 'elif [ $middleware == OSG ]; then\n' |
615 |
|
txt += ' WORKING_DIR=`/bin/mktemp -d $OSG_WN_TMP/cms_XXXXXXXXXXXX`\n' |
616 |
< |
txt += ' echo "Created working directory: $WORKING_DIR"\n' |
617 |
< |
txt += ' if [ ! -d $WORKING_DIR ] ;then\n' |
618 |
< |
txt += ' echo "SET_CMS_ENV 10016 ==> OSG $WORKING_DIR could not be created on WN `hostname`"\n' |
619 |
< |
txt += ' echo "JOB_EXIT_STATUS = 10016"\n' |
838 |
< |
txt += ' echo "JobExitCode=10016" | tee -a $RUNTIME_AREA/$repo\n' |
839 |
< |
txt += ' dumpStatus $RUNTIME_AREA/$repo\n' |
840 |
< |
txt += ' rm -f $RUNTIME_AREA/$repo \n' |
841 |
< |
txt += ' echo "MonitorJobID=`echo $MonitorJobID`" | tee -a $RUNTIME_AREA/$repo \n' |
842 |
< |
txt += ' echo "MonitorID=`echo $MonitorID`" | tee -a $RUNTIME_AREA/$repo\n' |
843 |
< |
txt += ' exit 1\n' |
616 |
> |
txt += ' if [ ! $? == 0 ] ;then\n' |
617 |
> |
txt += ' echo "ERROR ==> OSG $WORKING_DIR could not be created on WN `hostname`"\n' |
618 |
> |
txt += ' job_exit_code=10016\n' |
619 |
> |
txt += ' func_exit\n' |
620 |
|
txt += ' fi\n' |
621 |
+ |
txt += ' echo ">>> Created working directory: $WORKING_DIR"\n' |
622 |
|
txt += '\n' |
623 |
|
txt += ' echo "Change to working directory: $WORKING_DIR"\n' |
624 |
|
txt += ' cd $WORKING_DIR\n' |
625 |
< |
txt += self.wsSetupCMSOSGEnvironment_() |
625 |
> |
txt += ' echo ">>> current directory (WORKING_DIR): $WORKING_DIR"\n' |
626 |
> |
txt += self.wsSetupCMSOSGEnvironment_() |
627 |
> |
#Setup SGE Environment |
628 |
> |
txt += 'elif [ $middleware == SGE ]; then\n' |
629 |
> |
txt += self.wsSetupCMSLCGEnvironment_() |
630 |
> |
|
631 |
> |
txt += 'elif [ $middleware == ARC ]; then\n' |
632 |
> |
txt += self.wsSetupCMSLCGEnvironment_() |
633 |
> |
|
634 |
|
txt += 'fi\n' |
635 |
|
|
636 |
|
# Prepare JobType-specific part |
637 |
|
scram = self.scram.commandName() |
638 |
|
txt += '\n\n' |
639 |
< |
txt += 'echo "### SPECIFIC JOB SETUP ENVIRONMENT ###"\n' |
640 |
< |
txt += 'echo "Setting SCRAM_ARCH='+self.executable_arch+'"\n' |
856 |
< |
txt += 'export SCRAM_ARCH='+self.executable_arch+'\n' |
639 |
> |
txt += 'echo ">>> specific cmssw setup environment:"\n' |
640 |
> |
txt += 'echo "CMSSW_VERSION = '+self.version+'"\n' |
641 |
|
txt += scram+' project CMSSW '+self.version+'\n' |
642 |
|
txt += 'status=$?\n' |
643 |
|
txt += 'if [ $status != 0 ] ; then\n' |
644 |
< |
txt += ' echo "SET_EXE_ENV 10034 ==>ERROR CMSSW '+self.version+' not found on `hostname`" \n' |
645 |
< |
txt += ' echo "JOB_EXIT_STATUS = 10034"\n' |
646 |
< |
txt += ' echo "JobExitCode=10034" | tee -a $RUNTIME_AREA/$repo\n' |
863 |
< |
txt += ' dumpStatus $RUNTIME_AREA/$repo\n' |
864 |
< |
txt += ' rm -f $RUNTIME_AREA/$repo \n' |
865 |
< |
txt += ' echo "MonitorJobID=`echo $MonitorJobID`" | tee -a $RUNTIME_AREA/$repo \n' |
866 |
< |
txt += ' echo "MonitorID=`echo $MonitorID`" | tee -a $RUNTIME_AREA/$repo\n' |
867 |
< |
## OLI_Daniele |
868 |
< |
txt += ' if [ $middleware == OSG ]; then \n' |
869 |
< |
txt += ' echo "Remove working directory: $WORKING_DIR"\n' |
870 |
< |
txt += ' cd $RUNTIME_AREA\n' |
871 |
< |
txt += ' /bin/rm -rf $WORKING_DIR\n' |
872 |
< |
txt += ' if [ -d $WORKING_DIR ] ;then\n' |
873 |
< |
txt += ' echo "SET_CMS_ENV 10018 ==> OSG $WORKING_DIR could not be deleted on WN `hostname` after CMSSW CMSSW_0_6_1 not found on `hostname`"\n' |
874 |
< |
txt += ' echo "JOB_EXIT_STATUS = 10018"\n' |
875 |
< |
txt += ' echo "JobExitCode=10018" | tee -a $RUNTIME_AREA/$repo\n' |
876 |
< |
txt += ' dumpStatus $RUNTIME_AREA/$repo\n' |
877 |
< |
txt += ' rm -f $RUNTIME_AREA/$repo \n' |
878 |
< |
txt += ' echo "MonitorJobID=`echo $MonitorJobID`" | tee -a $RUNTIME_AREA/$repo \n' |
879 |
< |
txt += ' echo "MonitorID=`echo $MonitorID`" | tee -a $RUNTIME_AREA/$repo\n' |
880 |
< |
txt += ' fi\n' |
881 |
< |
txt += ' fi \n' |
882 |
< |
txt += ' exit 1 \n' |
644 |
> |
txt += ' echo "ERROR ==> CMSSW '+self.version+' not found on `hostname`" \n' |
645 |
> |
txt += ' job_exit_code=10034\n' |
646 |
> |
txt += ' func_exit\n' |
647 |
|
txt += 'fi \n' |
884 |
– |
txt += 'echo "CMSSW_VERSION = '+self.version+'"\n' |
648 |
|
txt += 'cd '+self.version+'\n' |
649 |
< |
### needed grep for bug in scramv1 ### |
650 |
< |
txt += scram+' runtime -sh\n' |
649 |
> |
txt += 'SOFTWARE_DIR=`pwd`; export SOFTWARE_DIR\n' |
650 |
> |
txt += 'echo ">>> current directory (SOFTWARE_DIR): $SOFTWARE_DIR" \n' |
651 |
|
txt += 'eval `'+scram+' runtime -sh | grep -v SCRAMRT_LSB_JOBNAME`\n' |
652 |
< |
txt += 'echo $PATH\n' |
653 |
< |
|
652 |
> |
txt += 'if [ $? != 0 ] ; then\n' |
653 |
> |
txt += ' echo "ERROR ==> Problem with the command: "\n' |
654 |
> |
txt += ' echo "eval \`'+scram+' runtime -sh | grep -v SCRAMRT_LSB_JOBNAME \` at `hostname`"\n' |
655 |
> |
txt += ' job_exit_code=10034\n' |
656 |
> |
txt += ' func_exit\n' |
657 |
> |
txt += 'fi \n' |
658 |
|
# Handle the arguments: |
659 |
|
txt += "\n" |
660 |
|
txt += "## number of arguments (first argument always jobnumber)\n" |
661 |
|
txt += "\n" |
662 |
< |
# txt += "narg=$#\n" |
896 |
< |
txt += "if [ $nargs -lt 2 ]\n" |
662 |
> |
txt += "if [ $nargs -lt "+str(self.argsList)+" ]\n" |
663 |
|
txt += "then\n" |
664 |
< |
txt += " echo 'SET_EXE_ENV 1 ==> ERROR Too few arguments' +$nargs+ \n" |
665 |
< |
txt += ' echo "JOB_EXIT_STATUS = 50113"\n' |
666 |
< |
txt += ' echo "JobExitCode=50113" | tee -a $RUNTIME_AREA/$repo\n' |
901 |
< |
txt += ' dumpStatus $RUNTIME_AREA/$repo\n' |
902 |
< |
txt += ' rm -f $RUNTIME_AREA/$repo \n' |
903 |
< |
txt += ' echo "MonitorJobID=`echo $MonitorJobID`" | tee -a $RUNTIME_AREA/$repo \n' |
904 |
< |
txt += ' echo "MonitorID=`echo $MonitorID`" | tee -a $RUNTIME_AREA/$repo\n' |
905 |
< |
## OLI_Daniele |
906 |
< |
txt += ' if [ $middleware == OSG ]; then \n' |
907 |
< |
txt += ' echo "Remove working directory: $WORKING_DIR"\n' |
908 |
< |
txt += ' cd $RUNTIME_AREA\n' |
909 |
< |
txt += ' /bin/rm -rf $WORKING_DIR\n' |
910 |
< |
txt += ' if [ -d $WORKING_DIR ] ;then\n' |
911 |
< |
txt += ' echo "SET_EXE_ENV 50114 ==> OSG $WORKING_DIR could not be deleted on WN `hostname` after Too few arguments for CRAB job wrapper"\n' |
912 |
< |
txt += ' echo "JOB_EXIT_STATUS = 50114"\n' |
913 |
< |
txt += ' echo "JobExitCode=50114" | tee -a $RUNTIME_AREA/$repo\n' |
914 |
< |
txt += ' dumpStatus $RUNTIME_AREA/$repo\n' |
915 |
< |
txt += ' rm -f $RUNTIME_AREA/$repo \n' |
916 |
< |
txt += ' echo "MonitorJobID=`echo $MonitorJobID`" | tee -a $RUNTIME_AREA/$repo \n' |
917 |
< |
txt += ' echo "MonitorID=`echo $MonitorID`" | tee -a $RUNTIME_AREA/$repo\n' |
918 |
< |
txt += ' fi\n' |
919 |
< |
txt += ' fi \n' |
920 |
< |
txt += " exit 1\n" |
664 |
> |
txt += " echo 'ERROR ==> Too few arguments' +$nargs+ \n" |
665 |
> |
txt += ' job_exit_code=50113\n' |
666 |
> |
txt += " func_exit\n" |
667 |
|
txt += "fi\n" |
668 |
|
txt += "\n" |
669 |
|
|
670 |
|
# Prepare job-specific part |
671 |
|
job = common.job_list[nj] |
672 |
< |
### FEDE FOR DBS OUTPUT PUBLICATION |
673 |
< |
if (self.datasetPath): |
672 |
> |
if (self.datasetPath): |
673 |
> |
self.primaryDataset = self.datasetPath.split("/")[1] |
674 |
> |
DataTier = self.datasetPath.split("/")[2] |
675 |
|
txt += '\n' |
676 |
|
txt += 'DatasetPath='+self.datasetPath+'\n' |
677 |
|
|
678 |
< |
datasetpath_split = self.datasetPath.split("/") |
679 |
< |
|
680 |
< |
txt += 'PrimaryDataset='+datasetpath_split[1]+'\n' |
934 |
< |
txt += 'DataTier='+datasetpath_split[2]+'\n' |
935 |
< |
txt += 'ProcessedDataset='+datasetpath_split[3]+'\n' |
936 |
< |
txt += 'ApplicationFamily=Online\n' |
678 |
> |
txt += 'PrimaryDataset='+self.primaryDataset +'\n' |
679 |
> |
txt += 'DataTier='+DataTier+'\n' |
680 |
> |
txt += 'ApplicationFamily=cmsRun\n' |
681 |
|
|
682 |
|
else: |
683 |
+ |
self.primaryDataset = 'null' |
684 |
|
txt += 'DatasetPath=MCDataTier\n' |
685 |
|
txt += 'PrimaryDataset=null\n' |
686 |
|
txt += 'DataTier=null\n' |
942 |
– |
txt += 'ProcessedDataset=null\n' |
687 |
|
txt += 'ApplicationFamily=MCDataTier\n' |
688 |
< |
################## |
945 |
< |
if self.pset != None: #CarlosDaniele |
688 |
> |
if self.pset != None: |
689 |
|
pset = os.path.basename(job.configFilename()) |
690 |
|
txt += '\n' |
691 |
< |
if (self.datasetPath): # standard job |
949 |
< |
#txt += 'InputFiles=$2\n' |
950 |
< |
txt += 'InputFiles=${args[1]}\n' |
951 |
< |
txt += 'MaxEvents=${args[2]}\n' |
952 |
< |
txt += 'SkipEvents=${args[3]}\n' |
953 |
< |
txt += 'echo "Inputfiles:<$InputFiles>"\n' |
954 |
< |
txt += 'sed "s#{\'INPUT\'}#$InputFiles#" '+pset+' > tmp && mv -f tmp '+pset+'\n' |
955 |
< |
txt += 'echo "MaxEvents:<$MaxEvents>"\n' |
956 |
< |
txt += 'sed "s#INPUTMAXEVENTS#$MaxEvents#" '+pset+' > tmp && mv -f tmp '+pset+'\n' |
957 |
< |
txt += 'echo "SkipEvents:<$SkipEvents>"\n' |
958 |
< |
txt += 'sed "s#INPUTSKIPEVENTS#$SkipEvents#" '+pset+' > tmp && mv -f tmp '+pset+'\n' |
959 |
< |
else: # pythia like job |
960 |
< |
seedIndex=1 |
961 |
< |
if (self.firstRun): |
962 |
< |
txt += 'FirstRun=${args['+str(seedIndex)+']}\n' |
963 |
< |
txt += 'echo "FirstRun: <$FirstRun>"\n' |
964 |
< |
txt += 'sed "s#\<INPUTFIRSTRUN\>#$FirstRun#" '+pset+' > tmp && mv -f tmp '+pset+'\n' |
965 |
< |
seedIndex=seedIndex+1 |
966 |
< |
|
967 |
< |
if (self.sourceSeed): |
968 |
< |
txt += 'Seed=${args['+str(seedIndex)+']}\n' |
969 |
< |
txt += 'sed "s#\<INPUT\>#$Seed#" '+pset+' > tmp && mv -f tmp '+pset+'\n' |
970 |
< |
seedIndex=seedIndex+1 |
971 |
< |
## the following seeds are not always present |
972 |
< |
if (self.sourceSeedVtx): |
973 |
< |
txt += 'VtxSeed=${args['+str(seedIndex)+']}\n' |
974 |
< |
txt += 'echo "VtxSeed: <$VtxSeed>"\n' |
975 |
< |
txt += 'sed "s#\<INPUTVTX\>#$VtxSeed#" '+pset+' > tmp && mv -f tmp '+pset+'\n' |
976 |
< |
seedIndex += 1 |
977 |
< |
if (self.sourceSeedG4): |
978 |
< |
txt += 'G4Seed=${args['+str(seedIndex)+']}\n' |
979 |
< |
txt += 'echo "G4Seed: <$G4Seed>"\n' |
980 |
< |
txt += 'sed "s#\<INPUTG4\>#$G4Seed#" '+pset+' > tmp && mv -f tmp '+pset+'\n' |
981 |
< |
seedIndex += 1 |
982 |
< |
if (self.sourceSeedMix): |
983 |
< |
txt += 'mixSeed=${args['+str(seedIndex)+']}\n' |
984 |
< |
txt += 'echo "MixSeed: <$mixSeed>"\n' |
985 |
< |
txt += 'sed "s#\<INPUTMIX\>#$mixSeed#" '+pset+' > tmp && mv -f tmp '+pset+'\n' |
986 |
< |
seedIndex += 1 |
987 |
< |
pass |
988 |
< |
pass |
989 |
< |
txt += 'mv -f '+pset+' pset.cfg\n' |
691 |
> |
txt += 'cp $RUNTIME_AREA/'+pset+' .\n' |
692 |
|
|
693 |
< |
if len(self.additional_inbox_files) > 0: |
694 |
< |
for file in self.additional_inbox_files: |
695 |
< |
relFile = file.split("/")[-1] |
696 |
< |
txt += 'if [ -e $RUNTIME_AREA/'+relFile+' ] ; then\n' |
697 |
< |
txt += ' cp $RUNTIME_AREA/'+relFile+' .\n' |
698 |
< |
txt += ' chmod +x '+relFile+'\n' |
699 |
< |
txt += 'fi\n' |
998 |
< |
pass |
999 |
< |
|
1000 |
< |
if self.pset != None: #CarlosDaniele |
1001 |
< |
txt += 'echo "### END JOB SETUP ENVIRONMENT ###"\n\n' |
1002 |
< |
|
1003 |
< |
txt += '\n' |
1004 |
< |
txt += 'echo "***** cat pset.cfg *********"\n' |
1005 |
< |
txt += 'cat pset.cfg\n' |
1006 |
< |
txt += 'echo "****** end pset.cfg ********"\n' |
1007 |
< |
txt += '\n' |
1008 |
< |
### FEDE FOR DBS OUTPUT PUBLICATION |
1009 |
< |
txt += 'PSETHASH=`EdmConfigHash < pset.cfg`' |
1010 |
< |
############## |
693 |
> |
txt += 'PreserveSeeds=' + ','.join(self.preserveSeeds) + '; export PreserveSeeds\n' |
694 |
> |
txt += 'IncrementSeeds=' + ','.join(self.incrementSeeds) + '; export IncrementSeeds\n' |
695 |
> |
txt += 'echo "PreserveSeeds: <$PreserveSeeds>"\n' |
696 |
> |
txt += 'echo "IncrementSeeds:<$IncrementSeeds>"\n' |
697 |
> |
|
698 |
> |
txt += 'mv -f ' + pset + ' ' + psetName + '\n' |
699 |
> |
else: |
700 |
|
txt += '\n' |
701 |
< |
# txt += 'echo "***** cat pset1.cfg *********"\n' |
702 |
< |
# txt += 'cat pset1.cfg\n' |
1014 |
< |
# txt += 'echo "****** end pset1.cfg ********"\n' |
701 |
> |
txt += 'export AdditionalArgs=%s\n'%(self.AdditionalArgs) |
702 |
> |
|
703 |
|
return txt |
704 |
|
|
705 |
< |
def wsBuildExe(self, nj=0): |
705 |
> |
def wsUntarSoftware(self, nj=0): |
706 |
|
""" |
707 |
|
Put in the script the commands to build an executable |
708 |
|
or a library. |
709 |
|
""" |
710 |
|
|
711 |
< |
txt = "" |
711 |
> |
txt = '\n#Written by cms_cmssw::wsUntarSoftware\n' |
712 |
|
|
713 |
|
if os.path.isfile(self.tgzNameWithPath): |
714 |
< |
txt += 'echo "tar xzvf $RUNTIME_AREA/'+os.path.basename(self.tgzNameWithPath)+'"\n' |
715 |
< |
txt += 'tar xzvf $RUNTIME_AREA/'+os.path.basename(self.tgzNameWithPath)+'\n' |
714 |
> |
txt += 'echo ">>> tar xzvf $RUNTIME_AREA/'+os.path.basename(self.tgzNameWithPath)+' :" \n' |
715 |
> |
txt += 'tar zxvf $RUNTIME_AREA/'+os.path.basename(self.tgzNameWithPath)+'\n' |
716 |
> |
if self.debug_wrapper==1 : |
717 |
> |
txt += 'ls -Al \n' |
718 |
|
txt += 'untar_status=$? \n' |
719 |
|
txt += 'if [ $untar_status -ne 0 ]; then \n' |
720 |
< |
txt += ' echo "SET_EXE 1 ==> ERROR Untarring .tgz file failed"\n' |
721 |
< |
txt += ' echo "JOB_EXIT_STATUS = $untar_status" \n' |
722 |
< |
txt += ' echo "JobExitCode=$untar_status" | tee -a $RUNTIME_AREA/$repo\n' |
1033 |
< |
txt += ' if [ $middleware == OSG ]; then \n' |
1034 |
< |
txt += ' echo "Remove working directory: $WORKING_DIR"\n' |
1035 |
< |
txt += ' cd $RUNTIME_AREA\n' |
1036 |
< |
txt += ' /bin/rm -rf $WORKING_DIR\n' |
1037 |
< |
txt += ' if [ -d $WORKING_DIR ] ;then\n' |
1038 |
< |
txt += ' echo "SET_EXE 50999 ==> OSG $WORKING_DIR could not be deleted on WN `hostname` after Untarring .tgz file failed"\n' |
1039 |
< |
txt += ' echo "JOB_EXIT_STATUS = 50999"\n' |
1040 |
< |
txt += ' echo "JobExitCode=50999" | tee -a $RUNTIME_AREA/$repo\n' |
1041 |
< |
txt += ' dumpStatus $RUNTIME_AREA/$repo\n' |
1042 |
< |
txt += ' rm -f $RUNTIME_AREA/$repo \n' |
1043 |
< |
txt += ' echo "MonitorJobID=`echo $MonitorJobID`" | tee -a $RUNTIME_AREA/$repo \n' |
1044 |
< |
txt += ' echo "MonitorID=`echo $MonitorID`" | tee -a $RUNTIME_AREA/$repo\n' |
1045 |
< |
txt += ' fi\n' |
1046 |
< |
txt += ' fi \n' |
1047 |
< |
txt += ' \n' |
1048 |
< |
txt += ' exit 1 \n' |
720 |
> |
txt += ' echo "ERROR ==> Untarring .tgz file failed"\n' |
721 |
> |
txt += ' job_exit_code=$untar_status\n' |
722 |
> |
txt += ' func_exit\n' |
723 |
|
txt += 'else \n' |
724 |
|
txt += ' echo "Successful untar" \n' |
725 |
|
txt += 'fi \n' |
726 |
|
txt += '\n' |
727 |
< |
txt += 'echo "Include ProdAgentApi and PRODCOMMON in PYTHONPATH"\n' |
727 |
> |
txt += 'echo ">>> Include $RUNTIME_AREA in PYTHONPATH:"\n' |
728 |
|
txt += 'if [ -z "$PYTHONPATH" ]; then\n' |
729 |
< |
#### FEDE FOR DBS OUTPUT PUBLICATION |
1056 |
< |
txt += ' export PYTHONPATH=`pwd`/ProdAgentApi:`pwd`/ProdCommon\n' |
1057 |
< |
#txt += ' export PYTHONPATH=ProdAgentApi\n' |
729 |
> |
txt += ' export PYTHONPATH=$RUNTIME_AREA/\n' |
730 |
|
txt += 'else\n' |
731 |
< |
txt += ' export PYTHONPATH=`pwd`/ProdAgentApi:`pwd`/ProdCommon:${PYTHONPATH}\n' |
1060 |
< |
#txt += ' export PYTHONPATH=ProdAgentApi:${PYTHONPATH}\n' |
731 |
> |
txt += ' export PYTHONPATH=$RUNTIME_AREA/:${PYTHONPATH}\n' |
732 |
|
txt += 'echo "PYTHONPATH=$PYTHONPATH"\n' |
1062 |
– |
################### |
733 |
|
txt += 'fi\n' |
734 |
|
txt += '\n' |
735 |
|
|
736 |
|
pass |
737 |
< |
|
737 |
> |
|
738 |
|
return txt |
739 |
|
|
740 |
< |
def modifySteeringCards(self, nj): |
740 |
> |
def wsBuildExe(self, nj=0): |
741 |
|
""" |
742 |
< |
modify the card provided by the user, |
743 |
< |
writing a new card into share dir |
742 |
> |
Put in the script the commands to build an executable |
743 |
> |
or a library. |
744 |
|
""" |
745 |
< |
|
745 |
> |
|
746 |
> |
txt = '\n#Written by cms_cmssw::wsBuildExe\n' |
747 |
> |
txt += 'echo ">>> moving CMSSW software directories in `pwd`" \n' |
748 |
> |
|
749 |
> |
txt += 'rm -r lib/ module/ \n' |
750 |
> |
txt += 'mv $RUNTIME_AREA/lib/ . \n' |
751 |
> |
txt += 'mv $RUNTIME_AREA/module/ . \n' |
752 |
> |
if self.dataExist == True: |
753 |
> |
txt += 'rm -r src/ \n' |
754 |
> |
txt += 'mv $RUNTIME_AREA/src/ . \n' |
755 |
> |
if len(self.additional_inbox_files)>0: |
756 |
> |
for file in self.additional_inbox_files: |
757 |
> |
txt += 'mv $RUNTIME_AREA/'+os.path.basename(file)+' . \n' |
758 |
> |
# txt += 'mv $RUNTIME_AREA/ProdCommon/ . \n' |
759 |
> |
# txt += 'mv $RUNTIME_AREA/IMProv/ . \n' |
760 |
> |
|
761 |
> |
txt += 'echo ">>> Include $RUNTIME_AREA in PYTHONPATH:"\n' |
762 |
> |
txt += 'if [ -z "$PYTHONPATH" ]; then\n' |
763 |
> |
txt += ' export PYTHONPATH=$RUNTIME_AREA/\n' |
764 |
> |
txt += 'else\n' |
765 |
> |
txt += ' export PYTHONPATH=$RUNTIME_AREA/:${PYTHONPATH}\n' |
766 |
> |
txt += 'echo "PYTHONPATH=$PYTHONPATH"\n' |
767 |
> |
txt += 'fi\n' |
768 |
> |
txt += '\n' |
769 |
> |
|
770 |
> |
if self.pset != None: |
771 |
> |
# FUTURE: Drop support for .cfg when possible |
772 |
> |
if (self.CMSSW_major >= 2 and self.CMSSW_minor >= 1) or (self.CMSSW_major >= 3): |
773 |
> |
psetName = 'pset.py' |
774 |
> |
else: |
775 |
> |
psetName = 'pset.cfg' |
776 |
> |
# FUTURE: Can simply for 2_1_x and higher |
777 |
> |
txt += '\n' |
778 |
> |
if self.debug_wrapper == 1: |
779 |
> |
txt += 'echo "***** cat ' + psetName + ' *********"\n' |
780 |
> |
txt += 'cat ' + psetName + '\n' |
781 |
> |
txt += 'echo "****** end ' + psetName + ' ********"\n' |
782 |
> |
txt += '\n' |
783 |
> |
txt += 'echo "***********************" \n' |
784 |
> |
txt += 'which edmConfigHash \n' |
785 |
> |
txt += 'echo "***********************" \n' |
786 |
> |
if (self.CMSSW_major >= 2 and self.CMSSW_minor >= 1) or (self.CMSSW_major >= 3): |
787 |
> |
txt += 'edmConfigHash ' + psetName + ' \n' |
788 |
> |
txt += 'PSETHASH=`edmConfigHash ' + psetName + '` \n' |
789 |
> |
else: |
790 |
> |
txt += 'PSETHASH=`edmConfigHash < ' + psetName + '` \n' |
791 |
> |
txt += 'echo "PSETHASH = $PSETHASH" \n' |
792 |
> |
#### FEDE temporary fix for noEdm files ##### |
793 |
> |
txt += 'if [ -z "$PSETHASH" ]; then \n' |
794 |
> |
txt += ' export PSETHASH=null\n' |
795 |
> |
txt += 'fi \n' |
796 |
> |
############################################# |
797 |
> |
txt += '\n' |
798 |
> |
return txt |
799 |
> |
|
800 |
> |
|
801 |
|
def executableName(self): |
802 |
< |
if self.scriptExe: #CarlosDaniele |
802 |
> |
if self.scriptExe: |
803 |
|
return "sh " |
804 |
|
else: |
805 |
|
return self.executable |
806 |
|
|
807 |
|
def executableArgs(self): |
808 |
< |
if self.scriptExe:#CarlosDaniele |
809 |
< |
return self.scriptExe + " $NJob" |
810 |
< |
else: |
811 |
< |
return " -p pset.cfg" |
808 |
> |
# FUTURE: This function tests the CMSSW version. Can be simplified as we drop support for old versions |
809 |
> |
if self.scriptExe: |
810 |
> |
return self.scriptExe + " $NJob $AdditionalArgs" |
811 |
> |
else: |
812 |
> |
ex_args = "" |
813 |
> |
ex_args += " -j $RUNTIME_AREA/crab_fjr_$NJob.xml" |
814 |
> |
# Type of config file depends on CMSSW version |
815 |
> |
if self.CMSSW_major >= 2 : |
816 |
> |
ex_args += " -p pset.py" |
817 |
> |
else: |
818 |
> |
ex_args += " -p pset.cfg" |
819 |
> |
return ex_args |
820 |
|
|
821 |
|
def inputSandbox(self, nj): |
822 |
|
""" |
823 |
|
Returns a list of filenames to be put in JDL input sandbox. |
824 |
|
""" |
825 |
|
inp_box = [] |
1093 |
– |
# # dict added to delete duplicate from input sandbox file list |
1094 |
– |
# seen = {} |
1095 |
– |
## code |
826 |
|
if os.path.isfile(self.tgzNameWithPath): |
827 |
|
inp_box.append(self.tgzNameWithPath) |
828 |
< |
if os.path.isfile(self.MLtgzfile): |
1099 |
< |
inp_box.append(self.MLtgzfile) |
1100 |
< |
## config |
1101 |
< |
if not self.pset is None: |
1102 |
< |
inp_box.append(common.work_space.pathForTgz() + 'job/' + self.configFilename()) |
1103 |
< |
## additional input files |
1104 |
< |
for file in self.additional_inbox_files: |
1105 |
< |
inp_box.append(file) |
828 |
> |
inp_box.append(common.work_space.jobDir() + self.scriptName) |
829 |
|
return inp_box |
830 |
|
|
831 |
|
def outputSandbox(self, nj): |
836 |
|
|
837 |
|
## User Declared output files |
838 |
|
for out in (self.output_file+self.output_file_sandbox): |
839 |
< |
n_out = nj + 1 |
840 |
< |
out_box.append(self.numberFile_(out,str(n_out))) |
839 |
> |
n_out = nj + 1 |
840 |
> |
out_box.append(numberFile(out,str(n_out))) |
841 |
|
return out_box |
842 |
|
|
1120 |
– |
def prepareSteeringCards(self): |
1121 |
– |
""" |
1122 |
– |
Make initial modifications of the user's steering card file. |
1123 |
– |
""" |
1124 |
– |
return |
843 |
|
|
844 |
|
def wsRenameOutput(self, nj): |
845 |
|
""" |
846 |
|
Returns part of a job script which renames the produced files. |
847 |
|
""" |
848 |
|
|
849 |
< |
txt = '\n' |
850 |
< |
txt += '# directory content\n' |
851 |
< |
txt += 'ls \n' |
849 |
> |
txt = '\n#Written by cms_cmssw::wsRenameOutput\n' |
850 |
> |
txt += 'echo ">>> current directory (SOFTWARE_DIR): $SOFTWARE_DIR" \n' |
851 |
> |
txt += 'echo ">>> current directory content:"\n' |
852 |
> |
if self.debug_wrapper==1: |
853 |
> |
txt += 'ls -Al\n' |
854 |
> |
txt += '\n' |
855 |
|
|
856 |
< |
for fileWithSuffix in (self.output_file+self.output_file_sandbox): |
857 |
< |
output_file_num = self.numberFile_(fileWithSuffix, '$NJob') |
856 |
> |
for fileWithSuffix in (self.output_file): |
857 |
> |
output_file_num = numberFile(fileWithSuffix, '$NJob') |
858 |
|
txt += '\n' |
859 |
|
txt += '# check output file\n' |
860 |
< |
txt += 'ls '+fileWithSuffix+'\n' |
861 |
< |
txt += 'ls_result=$?\n' |
862 |
< |
txt += 'if [ $ls_result -ne 0 ] ; then\n' |
863 |
< |
txt += ' exit_status=60302\n' |
864 |
< |
txt += ' echo "ERROR: Problem with output file"\n' |
865 |
< |
if common.scheduler.boss_scheduler_name == 'condor_g': |
860 |
> |
txt += 'if [ -e ./'+fileWithSuffix+' ] ; then\n' |
861 |
> |
if (self.copy_data == 1): # For OSG nodes, file is in $WORKING_DIR, should not be moved to $RUNTIME_AREA |
862 |
> |
txt += ' mv '+fileWithSuffix+' '+output_file_num+'\n' |
863 |
> |
txt += ' ln -s `pwd`/'+output_file_num+' $RUNTIME_AREA/'+fileWithSuffix+'\n' |
864 |
> |
else: |
865 |
> |
txt += ' mv '+fileWithSuffix+' $RUNTIME_AREA/'+output_file_num+'\n' |
866 |
> |
txt += ' ln -s $RUNTIME_AREA/'+output_file_num+' $RUNTIME_AREA/'+fileWithSuffix+'\n' |
867 |
> |
txt += 'else\n' |
868 |
> |
txt += ' job_exit_code=60302\n' |
869 |
> |
txt += ' echo "WARNING: Output file '+fileWithSuffix+' not found"\n' |
870 |
> |
if common.scheduler.name().upper() == 'CONDOR_G': |
871 |
|
txt += ' if [ $middleware == OSG ]; then \n' |
872 |
|
txt += ' echo "prepare dummy output file"\n' |
873 |
|
txt += ' echo "Processing of job output failed" > $RUNTIME_AREA/'+output_file_num+'\n' |
874 |
|
txt += ' fi \n' |
1149 |
– |
txt += 'else\n' |
1150 |
– |
### FEDE FOR DBS OUTPUT PUBLICATION |
1151 |
– |
txt += ' mv '+fileWithSuffix+' $RUNTIME_AREA\n' |
1152 |
– |
txt += ' cp $RUNTIME_AREA/'+fileWithSuffix+' $RUNTIME_AREA/'+output_file_num+'\n' |
1153 |
– |
################################# |
875 |
|
txt += 'fi\n' |
876 |
< |
|
877 |
< |
txt += 'cd $RUNTIME_AREA\n' |
878 |
< |
### OLI_DANIELE |
1158 |
< |
txt += 'if [ $middleware == OSG ]; then\n' |
1159 |
< |
txt += ' cd $RUNTIME_AREA\n' |
1160 |
< |
txt += ' echo "Remove working directory: $WORKING_DIR"\n' |
1161 |
< |
txt += ' /bin/rm -rf $WORKING_DIR\n' |
1162 |
< |
txt += ' if [ -d $WORKING_DIR ] ;then\n' |
1163 |
< |
txt += ' echo "SET_EXE 60999 ==> OSG $WORKING_DIR could not be deleted on WN `hostname` after cleanup of WN"\n' |
1164 |
< |
txt += ' echo "JOB_EXIT_STATUS = 60999"\n' |
1165 |
< |
txt += ' echo "JobExitCode=60999" | tee -a $RUNTIME_AREA/$repo\n' |
1166 |
< |
txt += ' dumpStatus $RUNTIME_AREA/$repo\n' |
1167 |
< |
txt += ' rm -f $RUNTIME_AREA/$repo \n' |
1168 |
< |
txt += ' echo "MonitorJobID=`echo $MonitorJobID`" | tee -a $RUNTIME_AREA/$repo \n' |
1169 |
< |
txt += ' echo "MonitorID=`echo $MonitorID`" | tee -a $RUNTIME_AREA/$repo\n' |
1170 |
< |
txt += ' fi\n' |
1171 |
< |
txt += 'fi\n' |
1172 |
< |
txt += '\n' |
1173 |
< |
|
1174 |
< |
file_list = '' |
1175 |
< |
## Add to filelist only files to be possibly copied to SE |
1176 |
< |
for fileWithSuffix in self.output_file: |
1177 |
< |
output_file_num = self.numberFile_(fileWithSuffix, '$NJob') |
1178 |
< |
file_list=file_list+output_file_num+' ' |
1179 |
< |
file_list=file_list[:-1] |
1180 |
< |
txt += 'file_list="'+file_list+'"\n' |
876 |
> |
file_list = [] |
877 |
> |
for fileWithSuffix in (self.output_file): |
878 |
> |
file_list.append(numberFile('$SOFTWARE_DIR/'+fileWithSuffix, '$NJob')) |
879 |
|
|
880 |
+ |
txt += 'file_list="'+string.join(file_list,',')+'"\n' |
881 |
+ |
txt += '\n' |
882 |
+ |
txt += 'echo ">>> current directory (SOFTWARE_DIR): $SOFTWARE_DIR" \n' |
883 |
+ |
txt += 'echo ">>> current directory content:"\n' |
884 |
+ |
if self.debug_wrapper==1: |
885 |
+ |
txt += 'ls -Al\n' |
886 |
+ |
txt += '\n' |
887 |
+ |
txt += 'cd $RUNTIME_AREA\n' |
888 |
+ |
txt += 'echo ">>> current directory (RUNTIME_AREA): $RUNTIME_AREA"\n' |
889 |
|
return txt |
890 |
|
|
1184 |
– |
def numberFile_(self, file, txt): |
1185 |
– |
""" |
1186 |
– |
append _'txt' before last extension of a file |
1187 |
– |
""" |
1188 |
– |
p = string.split(file,".") |
1189 |
– |
# take away last extension |
1190 |
– |
name = p[0] |
1191 |
– |
for x in p[1:-1]: |
1192 |
– |
name=name+"."+x |
1193 |
– |
# add "_txt" |
1194 |
– |
if len(p)>1: |
1195 |
– |
ext = p[len(p)-1] |
1196 |
– |
result = name + '_' + txt + "." + ext |
1197 |
– |
else: |
1198 |
– |
result = name + '_' + txt |
1199 |
– |
|
1200 |
– |
return result |
1201 |
– |
|
891 |
|
def getRequirements(self, nj=[]): |
892 |
|
""" |
893 |
< |
return job requirements to add to jdl files |
893 |
> |
return job requirements to add to jdl files |
894 |
|
""" |
895 |
|
req = '' |
896 |
|
if self.version: |
897 |
|
req='Member("VO-cms-' + \ |
898 |
|
self.version + \ |
899 |
|
'", other.GlueHostApplicationSoftwareRunTimeEnvironment)' |
900 |
< |
# if self.executable_arch: |
901 |
< |
# req='Member("VO-cms-' + \ |
902 |
< |
# self.executable_arch + \ |
903 |
< |
# '", other.GlueHostApplicationSoftwareRunTimeEnvironment)' |
900 |
> |
if self.executable_arch: |
901 |
> |
req+=' && Member("VO-cms-' + \ |
902 |
> |
self.executable_arch + \ |
903 |
> |
'", other.GlueHostApplicationSoftwareRunTimeEnvironment)' |
904 |
|
|
905 |
|
req = req + ' && (other.GlueHostNetworkAdapterOutboundIP)' |
906 |
+ |
if ( common.scheduler.name() == "glitecoll" ) or ( common.scheduler.name() == "glite"): |
907 |
+ |
req += ' && other.GlueCEStateStatus == "Production" ' |
908 |
|
|
909 |
|
return req |
910 |
|
|
911 |
|
def configFilename(self): |
912 |
|
""" return the config filename """ |
913 |
< |
return self.name()+'.cfg' |
913 |
> |
# FUTURE: Can remove cfg mode for CMSSW >= 2_1_x |
914 |
> |
if (self.CMSSW_major >= 2 and self.CMSSW_minor >= 1) or (self.CMSSW_major >= 3): |
915 |
> |
return self.name()+'.py' |
916 |
> |
else: |
917 |
> |
return self.name()+'.cfg' |
918 |
|
|
1224 |
– |
### OLI_DANIELE |
919 |
|
def wsSetupCMSOSGEnvironment_(self): |
920 |
|
""" |
921 |
|
Returns part of a job script which is prepares |
922 |
|
the execution environment and which is common for all CMS jobs. |
923 |
|
""" |
924 |
< |
txt = '\n' |
925 |
< |
txt += ' echo "### SETUP CMS OSG ENVIRONMENT ###"\n' |
926 |
< |
txt += ' if [ -f $GRID3_APP_DIR/cmssoft/cmsset_default.sh ] ;then\n' |
927 |
< |
txt += ' # Use $GRID3_APP_DIR/cmssoft/cmsset_default.sh to setup cms software\n' |
928 |
< |
txt += ' export SCRAM_ARCH='+self.executable_arch+'\n' |
929 |
< |
txt += ' source $GRID3_APP_DIR/cmssoft/cmsset_default.sh '+self.version+'\n' |
1236 |
< |
txt += ' elif [ -f $OSG_APP/cmssoft/cms/cmsset_default.sh ] ;then\n' |
924 |
> |
txt = '\n#Written by cms_cmssw::wsSetupCMSOSGEnvironment_\n' |
925 |
> |
txt += ' echo ">>> setup CMS OSG environment:"\n' |
926 |
> |
txt += ' echo "set SCRAM ARCH to ' + self.executable_arch + '"\n' |
927 |
> |
txt += ' export SCRAM_ARCH='+self.executable_arch+'\n' |
928 |
> |
txt += ' echo "SCRAM_ARCH = $SCRAM_ARCH"\n' |
929 |
> |
txt += ' if [ -f $OSG_APP/cmssoft/cms/cmsset_default.sh ] ;then\n' |
930 |
|
txt += ' # Use $OSG_APP/cmssoft/cms/cmsset_default.sh to setup cms software\n' |
931 |
< |
txt += ' export SCRAM_ARCH='+self.executable_arch+'\n' |
932 |
< |
txt += ' source $OSG_APP/cmssoft/cms/cmsset_default.sh '+self.version+'\n' |
933 |
< |
txt += ' else\n' |
934 |
< |
txt += ' echo "SET_CMS_ENV 10020 ==> ERROR $GRID3_APP_DIR/cmssoft/cmsset_default.sh and $OSG_APP/cmssoft/cms/cmsset_default.sh file not found"\n' |
935 |
< |
txt += ' echo "JOB_EXIT_STATUS = 10020"\n' |
936 |
< |
txt += ' echo "JobExitCode=10020" | tee -a $RUNTIME_AREA/$repo\n' |
1244 |
< |
txt += ' dumpStatus $RUNTIME_AREA/$repo\n' |
1245 |
< |
txt += ' rm -f $RUNTIME_AREA/$repo \n' |
1246 |
< |
txt += ' echo "MonitorJobID=`echo $MonitorJobID`" | tee -a $RUNTIME_AREA/$repo \n' |
1247 |
< |
txt += ' echo "MonitorID=`echo $MonitorID`" | tee -a $RUNTIME_AREA/$repo\n' |
1248 |
< |
txt += ' exit 1\n' |
1249 |
< |
txt += '\n' |
1250 |
< |
txt += ' echo "Remove working directory: $WORKING_DIR"\n' |
1251 |
< |
txt += ' cd $RUNTIME_AREA\n' |
1252 |
< |
txt += ' /bin/rm -rf $WORKING_DIR\n' |
1253 |
< |
txt += ' if [ -d $WORKING_DIR ] ;then\n' |
1254 |
< |
txt += ' echo "SET_CMS_ENV 10017 ==> OSG $WORKING_DIR could not be deleted on WN `hostname` after $GRID3_APP_DIR/cmssoft/cmsset_default.sh and $OSG_APP/cmssoft/cms/cmsset_default.sh file not found"\n' |
1255 |
< |
txt += ' echo "JOB_EXIT_STATUS = 10017"\n' |
1256 |
< |
txt += ' echo "JobExitCode=10017" | tee -a $RUNTIME_AREA/$repo\n' |
1257 |
< |
txt += ' dumpStatus $RUNTIME_AREA/$repo\n' |
1258 |
< |
txt += ' rm -f $RUNTIME_AREA/$repo \n' |
1259 |
< |
txt += ' echo "MonitorJobID=`echo $MonitorJobID`" | tee -a $RUNTIME_AREA/$repo \n' |
1260 |
< |
txt += ' echo "MonitorID=`echo $MonitorID`" | tee -a $RUNTIME_AREA/$repo\n' |
1261 |
< |
txt += ' fi\n' |
1262 |
< |
txt += '\n' |
1263 |
< |
txt += ' exit 1\n' |
1264 |
< |
txt += ' fi\n' |
931 |
> |
txt += ' source $OSG_APP/cmssoft/cms/cmsset_default.sh '+self.version+'\n' |
932 |
> |
txt += ' else\n' |
933 |
> |
txt += ' echo "ERROR ==> $OSG_APP/cmssoft/cms/cmsset_default.sh file not found"\n' |
934 |
> |
txt += ' job_exit_code=10020\n' |
935 |
> |
txt += ' func_exit\n' |
936 |
> |
txt += ' fi\n' |
937 |
|
txt += '\n' |
938 |
< |
txt += ' echo "SET_CMS_ENV 0 ==> setup cms environment ok"\n' |
939 |
< |
txt += ' echo " END SETUP CMS OSG ENVIRONMENT "\n' |
938 |
> |
txt += ' echo "==> setup cms environment ok"\n' |
939 |
> |
txt += ' echo "SCRAM_ARCH = $SCRAM_ARCH"\n' |
940 |
|
|
941 |
|
return txt |
942 |
< |
|
1271 |
< |
### OLI_DANIELE |
942 |
> |
|
943 |
|
def wsSetupCMSLCGEnvironment_(self): |
944 |
|
""" |
945 |
|
Returns part of a job script which is prepares |
946 |
|
the execution environment and which is common for all CMS jobs. |
947 |
|
""" |
948 |
< |
txt = ' \n' |
949 |
< |
txt += ' echo " ### SETUP CMS LCG ENVIRONMENT ### "\n' |
950 |
< |
txt += ' if [ ! $VO_CMS_SW_DIR ] ;then\n' |
951 |
< |
txt += ' echo "SET_CMS_ENV 10031 ==> ERROR CMS software dir not found on WN `hostname`"\n' |
952 |
< |
txt += ' echo "JOB_EXIT_STATUS = 10031" \n' |
953 |
< |
txt += ' echo "JobExitCode=10031" | tee -a $RUNTIME_AREA/$repo\n' |
954 |
< |
txt += ' dumpStatus $RUNTIME_AREA/$repo\n' |
955 |
< |
txt += ' rm -f $RUNTIME_AREA/$repo \n' |
956 |
< |
txt += ' echo "MonitorJobID=`echo $MonitorJobID`" | tee -a $RUNTIME_AREA/$repo \n' |
957 |
< |
txt += ' echo "MonitorID=`echo $MonitorID`" | tee -a $RUNTIME_AREA/$repo\n' |
958 |
< |
txt += ' exit 1\n' |
959 |
< |
txt += ' else\n' |
960 |
< |
txt += ' echo "Sourcing environment... "\n' |
961 |
< |
txt += ' if [ ! -s $VO_CMS_SW_DIR/cmsset_default.sh ] ;then\n' |
962 |
< |
txt += ' echo "SET_CMS_ENV 10020 ==> ERROR cmsset_default.sh file not found into dir $VO_CMS_SW_DIR"\n' |
963 |
< |
txt += ' echo "JOB_EXIT_STATUS = 10020"\n' |
964 |
< |
txt += ' echo "JobExitCode=10020" | tee -a $RUNTIME_AREA/$repo\n' |
965 |
< |
txt += ' dumpStatus $RUNTIME_AREA/$repo\n' |
966 |
< |
txt += ' rm -f $RUNTIME_AREA/$repo \n' |
967 |
< |
txt += ' echo "MonitorJobID=`echo $MonitorJobID`" | tee -a $RUNTIME_AREA/$repo \n' |
968 |
< |
txt += ' echo "MonitorID=`echo $MonitorID`" | tee -a $RUNTIME_AREA/$repo\n' |
969 |
< |
txt += ' exit 1\n' |
970 |
< |
txt += ' fi\n' |
971 |
< |
txt += ' echo "sourcing $VO_CMS_SW_DIR/cmsset_default.sh"\n' |
972 |
< |
txt += ' source $VO_CMS_SW_DIR/cmsset_default.sh\n' |
973 |
< |
txt += ' result=$?\n' |
974 |
< |
txt += ' if [ $result -ne 0 ]; then\n' |
975 |
< |
txt += ' echo "SET_CMS_ENV 10032 ==> ERROR problem sourcing $VO_CMS_SW_DIR/cmsset_default.sh"\n' |
976 |
< |
txt += ' echo "JOB_EXIT_STATUS = 10032"\n' |
977 |
< |
txt += ' echo "JobExitCode=10032" | tee -a $RUNTIME_AREA/$repo\n' |
978 |
< |
txt += ' dumpStatus $RUNTIME_AREA/$repo\n' |
979 |
< |
txt += ' rm -f $RUNTIME_AREA/$repo \n' |
980 |
< |
txt += ' echo "MonitorJobID=`echo $MonitorJobID`" | tee -a $RUNTIME_AREA/$repo \n' |
981 |
< |
txt += ' echo "MonitorID=`echo $MonitorID`" | tee -a $RUNTIME_AREA/$repo\n' |
982 |
< |
txt += ' exit 1\n' |
983 |
< |
txt += ' fi\n' |
984 |
< |
txt += ' fi\n' |
985 |
< |
txt += ' \n' |
986 |
< |
txt += ' echo "SET_CMS_ENV 0 ==> setup cms environment ok"\n' |
987 |
< |
txt += ' echo "### END SETUP CMS LCG ENVIRONMENT ###"\n' |
948 |
> |
txt = '\n#Written by cms_cmssw::wsSetupCMSLCGEnvironment_\n' |
949 |
> |
txt += ' echo ">>> setup CMS LCG environment:"\n' |
950 |
> |
txt += ' echo "set SCRAM ARCH and BUILD_ARCH to ' + self.executable_arch + ' ###"\n' |
951 |
> |
txt += ' export SCRAM_ARCH='+self.executable_arch+'\n' |
952 |
> |
txt += ' export BUILD_ARCH='+self.executable_arch+'\n' |
953 |
> |
txt += ' if [ ! $VO_CMS_SW_DIR ] ;then\n' |
954 |
> |
txt += ' echo "ERROR ==> CMS software dir not found on WN `hostname`"\n' |
955 |
> |
txt += ' job_exit_code=10031\n' |
956 |
> |
txt += ' func_exit\n' |
957 |
> |
txt += ' else\n' |
958 |
> |
txt += ' echo "Sourcing environment... "\n' |
959 |
> |
txt += ' if [ ! -s $VO_CMS_SW_DIR/cmsset_default.sh ] ;then\n' |
960 |
> |
txt += ' echo "ERROR ==> cmsset_default.sh file not found into dir $VO_CMS_SW_DIR"\n' |
961 |
> |
txt += ' job_exit_code=10020\n' |
962 |
> |
txt += ' func_exit\n' |
963 |
> |
txt += ' fi\n' |
964 |
> |
txt += ' echo "sourcing $VO_CMS_SW_DIR/cmsset_default.sh"\n' |
965 |
> |
txt += ' source $VO_CMS_SW_DIR/cmsset_default.sh\n' |
966 |
> |
txt += ' result=$?\n' |
967 |
> |
txt += ' if [ $result -ne 0 ]; then\n' |
968 |
> |
txt += ' echo "ERROR ==> problem sourcing $VO_CMS_SW_DIR/cmsset_default.sh"\n' |
969 |
> |
txt += ' job_exit_code=10032\n' |
970 |
> |
txt += ' func_exit\n' |
971 |
> |
txt += ' fi\n' |
972 |
> |
txt += ' fi\n' |
973 |
> |
txt += ' \n' |
974 |
> |
txt += ' echo "==> setup cms environment ok"\n' |
975 |
> |
return txt |
976 |
> |
|
977 |
> |
def wsModifyReport(self, nj): |
978 |
> |
""" |
979 |
> |
insert the part of the script that modifies the FrameworkJob Report |
980 |
> |
""" |
981 |
> |
|
982 |
> |
txt = '' |
983 |
> |
publish_data = int(self.cfg_params.get('USER.publish_data',0)) |
984 |
> |
#if (publish_data == 1): |
985 |
> |
if (self.copy_data == 1): |
986 |
> |
txt = '\n#Written by cms_cmssw::wsModifyReport\n' |
987 |
> |
publish_data = int(self.cfg_params.get('USER.publish_data',0)) |
988 |
> |
|
989 |
> |
|
990 |
> |
txt += 'if [ $StageOutExitStatus -eq 0 ]; then\n' |
991 |
> |
txt += ' FOR_LFN=$LFNBaseName\n' |
992 |
> |
txt += 'else\n' |
993 |
> |
txt += ' FOR_LFN=/copy_problems/ \n' |
994 |
> |
txt += 'fi\n' |
995 |
> |
|
996 |
> |
txt += 'echo ">>> Modify Job Report:" \n' |
997 |
> |
txt += 'chmod a+x $RUNTIME_AREA/ProdCommon/FwkJobRep/ModifyJobReport.py\n' |
998 |
> |
txt += 'echo "SE = $SE"\n' |
999 |
> |
txt += 'echo "SE_PATH = $SE_PATH"\n' |
1000 |
> |
txt += 'echo "FOR_LFN = $FOR_LFN" \n' |
1001 |
> |
txt += 'echo "CMSSW_VERSION = $CMSSW_VERSION"\n\n' |
1002 |
> |
|
1003 |
> |
|
1004 |
> |
args = 'fjr $RUNTIME_AREA/crab_fjr_$NJob.xml n_job $NJob for_lfn $FOR_LFN PrimaryDataset $PrimaryDataset ApplicationFamily $ApplicationFamily ApplicationName $executable cmssw_version $CMSSW_VERSION psethash $PSETHASH se_name $SE se_path $SE_PATH' |
1005 |
> |
if (publish_data == 1): |
1006 |
> |
processedDataset = self.cfg_params['USER.publish_data_name'] |
1007 |
> |
txt += 'ProcessedDataset='+processedDataset+'\n' |
1008 |
> |
txt += 'echo "ProcessedDataset = $ProcessedDataset"\n' |
1009 |
> |
args += ' UserProcessedDataset $USER-$ProcessedDataset-$PSETHASH' |
1010 |
> |
|
1011 |
> |
txt += 'echo "$RUNTIME_AREA/ProdCommon/FwkJobRep/ModifyJobReport.py '+str(args)+'"\n' |
1012 |
> |
txt += '$RUNTIME_AREA/ProdCommon/FwkJobRep/ModifyJobReport.py '+str(args)+'\n' |
1013 |
> |
txt += 'modifyReport_result=$?\n' |
1014 |
> |
txt += 'if [ $modifyReport_result -ne 0 ]; then\n' |
1015 |
> |
txt += ' modifyReport_result=70500\n' |
1016 |
> |
txt += ' job_exit_code=$modifyReport_result\n' |
1017 |
> |
txt += ' echo "ModifyReportResult=$modifyReport_result" | tee -a $RUNTIME_AREA/$repo\n' |
1018 |
> |
txt += ' echo "WARNING: Problem with ModifyJobReport"\n' |
1019 |
> |
txt += 'else\n' |
1020 |
> |
txt += ' mv NewFrameworkJobReport.xml $RUNTIME_AREA/crab_fjr_$NJob.xml\n' |
1021 |
> |
txt += 'fi\n' |
1022 |
|
return txt |
1023 |
|
|
1024 |
< |
### FEDE FOR DBS OUTPUT PUBLICATION |
1320 |
< |
def modifyReport(self, nj): |
1024 |
> |
def wsParseFJR(self): |
1025 |
|
""" |
1026 |
< |
insert the part of the script that modifies the FrameworkJob Report |
1026 |
> |
Parse the FrameworkJobReport to obtain useful infos |
1027 |
|
""" |
1028 |
< |
|
1029 |
< |
txt = '' |
1030 |
< |
txt += 'echo "Modify Job Report" \n' |
1031 |
< |
txt += 'chmod a+x $RUNTIME_AREA/'+self.version+'/ProdAgentApi/FwkJobRep/ModifyJobReport.py\n' |
1032 |
< |
txt += 'if [ -z "$SE" ]; then\n' |
1033 |
< |
txt += ' SE="" \n' |
1034 |
< |
txt += 'fi \n' |
1035 |
< |
txt += 'if [ -z "$SE_PATH" ]; then\n' |
1036 |
< |
txt += ' SE_PATH="" \n' |
1037 |
< |
txt += 'fi \n' |
1038 |
< |
txt += 'echo "SE = $SE"\n' |
1039 |
< |
txt += 'echo "SE_PATH = $SE_PATH"\n' |
1040 |
< |
txt += 'FOR_LFN=$DatasetPath/$MonitorID\n' |
1041 |
< |
txt += 'echo "FOR_LFN = $FOR_LFN"\n' |
1042 |
< |
txt += 'echo "CMSSW_VERSION = $CMSSW_VERSION"\n' |
1043 |
< |
txt += 'echo "$RUNTIME_AREA/'+self.version+'/ProdAgentApi/FwkJobRep/ModifyJobReport.py crab_fjr_$NJob.xml $NJob $FOR_LFN $PrimaryDataset $DataTier $ProcessedDataset $ApplicationFamily $executable $CMSSW_VERSION $PSETHASH $SE $SE_PATH"\n' |
1044 |
< |
txt += '$RUNTIME_AREA/'+self.version+'/ProdAgentApi/FwkJobRep/ModifyJobReport.py crab_fjr_$NJob.xml $NJob $FOR_LFN $PrimaryDataset $DataTier $ProcessedDataset $ApplicationFamily $executable $CMSSW_VERSION $PSETHASH $SE $SE_PATH\n' |
1045 |
< |
txt += 'modifyReport_result=$?\n' |
1046 |
< |
txt += 'echo modifyReport_result = $modifyReport_result\n' |
1047 |
< |
txt += 'if [ $modify_result -ne 0 ]; then\n' |
1048 |
< |
txt += ' exit_status=1\n' |
1049 |
< |
txt += ' echo "ERROR: Problem with ModifyJobReport"\n' |
1028 |
> |
txt = '\n#Written by cms_cmssw::wsParseFJR\n' |
1029 |
> |
txt += 'echo ">>> Parse FrameworkJobReport crab_fjr.xml"\n' |
1030 |
> |
txt += 'if [ -s $RUNTIME_AREA/crab_fjr_$NJob.xml ]; then\n' |
1031 |
> |
txt += ' if [ -s $RUNTIME_AREA/parseCrabFjr.py ]; then\n' |
1032 |
> |
txt += ' cmd_out=`python $RUNTIME_AREA/parseCrabFjr.py --input $RUNTIME_AREA/crab_fjr_$NJob.xml --dashboard $MonitorID,$MonitorJobID '+self.debugWrap+'`\n' |
1033 |
> |
if self.debug_wrapper==1 : |
1034 |
> |
txt += ' echo "Result of parsing the FrameworkJobReport crab_fjr.xml: $cmd_out"\n' |
1035 |
> |
txt += ' executable_exit_status=`python $RUNTIME_AREA/parseCrabFjr.py --input $RUNTIME_AREA/crab_fjr_$NJob.xml --exitcode`\n' |
1036 |
> |
txt += ' if [ $executable_exit_status -eq 50115 ];then\n' |
1037 |
> |
txt += ' echo ">>> crab_fjr.xml contents: "\n' |
1038 |
> |
txt += ' cat $RUNTIME_AREA/crab_fjr_$NJob.xml\n' |
1039 |
> |
txt += ' echo "Wrong FrameworkJobReport --> does not contain useful info. ExitStatus: $executable_exit_status"\n' |
1040 |
> |
txt += ' elif [ $executable_exit_status -eq -999 ];then\n' |
1041 |
> |
txt += ' echo "ExitStatus from FrameworkJobReport not available. not available. Using exit code of executable from command line."\n' |
1042 |
> |
txt += ' else\n' |
1043 |
> |
txt += ' echo "Extracted ExitStatus from FrameworkJobReport parsing output: $executable_exit_status"\n' |
1044 |
> |
txt += ' fi\n' |
1045 |
> |
txt += ' else\n' |
1046 |
> |
txt += ' echo "CRAB python script to parse CRAB FrameworkJobReport crab_fjr.xml is not available, using exit code of executable from command line."\n' |
1047 |
> |
txt += ' fi\n' |
1048 |
> |
#### Patch to check input data reading for CMSSW16x Hopefully we-ll remove it asap |
1049 |
> |
txt += ' if [ $executable_exit_status -eq 0 ];then\n' |
1050 |
> |
txt += ' echo ">>> Executable succeded $executable_exit_status"\n' |
1051 |
> |
## This cannot more work given the changes on the Job argumentsJob |
1052 |
> |
""" |
1053 |
> |
if (self.datasetPath and not (self.dataset_pu or self.useParent==1)) : |
1054 |
> |
# VERIFY PROCESSED DATA |
1055 |
> |
txt += ' echo ">>> Verify list of processed files:"\n' |
1056 |
> |
txt += ' echo $InputFiles |tr -d \'\\\\\' |tr \',\' \'\\n\'|tr -d \'"\' > input-files.txt\n' |
1057 |
> |
txt += ' python $RUNTIME_AREA/parseCrabFjr.py --input $RUNTIME_AREA/crab_fjr_$NJob.xml --lfn > processed-files.txt\n' |
1058 |
> |
txt += ' cat input-files.txt | sort | uniq > tmp.txt\n' |
1059 |
> |
txt += ' mv tmp.txt input-files.txt\n' |
1060 |
> |
txt += ' echo "cat input-files.txt"\n' |
1061 |
> |
txt += ' echo "----------------------"\n' |
1062 |
> |
txt += ' cat input-files.txt\n' |
1063 |
> |
txt += ' cat processed-files.txt | sort | uniq > tmp.txt\n' |
1064 |
> |
txt += ' mv tmp.txt processed-files.txt\n' |
1065 |
> |
txt += ' echo "----------------------"\n' |
1066 |
> |
txt += ' echo "cat processed-files.txt"\n' |
1067 |
> |
txt += ' echo "----------------------"\n' |
1068 |
> |
txt += ' cat processed-files.txt\n' |
1069 |
> |
txt += ' echo "----------------------"\n' |
1070 |
> |
txt += ' diff -qbB input-files.txt processed-files.txt\n' |
1071 |
> |
txt += ' fileverify_status=$?\n' |
1072 |
> |
txt += ' if [ $fileverify_status -ne 0 ]; then\n' |
1073 |
> |
txt += ' executable_exit_status=30001\n' |
1074 |
> |
txt += ' echo "ERROR ==> not all input files processed"\n' |
1075 |
> |
txt += ' echo " ==> list of processed files from crab_fjr.xml differs from list in pset.cfg"\n' |
1076 |
> |
txt += ' echo " ==> diff input-files.txt processed-files.txt"\n' |
1077 |
> |
txt += ' fi\n' |
1078 |
> |
""" |
1079 |
> |
txt += ' fi\n' |
1080 |
|
txt += 'else\n' |
1081 |
< |
txt += ' mv NewFrameworkJobReport.xml crab_fjr_$NJob.xml\n' |
1081 |
> |
txt += ' echo "CRAB FrameworkJobReport crab_fjr.xml is not available, using exit code of executable from command line."\n' |
1082 |
|
txt += 'fi\n' |
1083 |
+ |
txt += '\n' |
1084 |
+ |
txt += 'if [ $executable_exit_status -ne 0 ] && [ $executable_exit_status -ne 50115 ] && [ $executable_exit_status -ne 50117 ] && [ $executable_exit_status -ne 30001 ];then\n' |
1085 |
+ |
txt += ' echo ">>> Executable failed $executable_exit_status"\n' |
1086 |
+ |
txt += ' echo "ExeExitCode=$executable_exit_status" | tee -a $RUNTIME_AREA/$repo\n' |
1087 |
+ |
txt += ' echo "EXECUTABLE_EXIT_STATUS = $executable_exit_status"\n' |
1088 |
+ |
txt += ' job_exit_code=$executable_exit_status\n' |
1089 |
+ |
txt += ' func_exit\n' |
1090 |
+ |
txt += 'fi\n\n' |
1091 |
+ |
txt += 'echo "ExeExitCode=$executable_exit_status" | tee -a $RUNTIME_AREA/$repo\n' |
1092 |
+ |
txt += 'echo "EXECUTABLE_EXIT_STATUS = $executable_exit_status"\n' |
1093 |
+ |
txt += 'job_exit_code=$executable_exit_status\n' |
1094 |
+ |
|
1095 |
|
return txt |
1350 |
– |
################# |
1096 |
|
|
1097 |
|
def setParam_(self, param, value): |
1098 |
|
self._params[param] = value |
1100 |
|
def getParams(self): |
1101 |
|
return self._params |
1102 |
|
|
1103 |
< |
def setTaskid_(self): |
1104 |
< |
self._taskId = self.cfg_params['taskId'] |
1105 |
< |
|
1106 |
< |
def getTaskid(self): |
1107 |
< |
return self._taskId |
1108 |
< |
|
1109 |
< |
####################################################################### |
1110 |
< |
def uniquelist(self, old): |
1111 |
< |
""" |
1112 |
< |
remove duplicates from a list |
1113 |
< |
""" |
1114 |
< |
nd={} |
1115 |
< |
for e in old: |
1116 |
< |
nd[e]=0 |
1117 |
< |
return nd.keys() |
1103 |
> |
def outList(self,list=False): |
1104 |
> |
""" |
1105 |
> |
check the dimension of the output files |
1106 |
> |
""" |
1107 |
> |
txt = '' |
1108 |
> |
txt += 'echo ">>> list of expected files on output sandbox"\n' |
1109 |
> |
listOutFiles = [] |
1110 |
> |
stdout = 'CMSSW_$NJob.stdout' |
1111 |
> |
stderr = 'CMSSW_$NJob.stderr' |
1112 |
> |
if len(self.output_file) <= 0: |
1113 |
> |
msg ="WARNING: no output files name have been defined!!\n" |
1114 |
> |
msg+="\tno output files will be reported back/staged\n" |
1115 |
> |
common.logger.info(msg) |
1116 |
> |
if (self.return_data == 1): |
1117 |
> |
for file in (self.output_file+self.output_file_sandbox): |
1118 |
> |
listOutFiles.append(numberFile(file, '$NJob')) |
1119 |
> |
listOutFiles.append(stdout) |
1120 |
> |
listOutFiles.append(stderr) |
1121 |
> |
else: |
1122 |
> |
for file in (self.output_file_sandbox): |
1123 |
> |
listOutFiles.append(numberFile(file, '$NJob')) |
1124 |
> |
listOutFiles.append(stdout) |
1125 |
> |
listOutFiles.append(stderr) |
1126 |
> |
txt += 'echo "output files: '+string.join(listOutFiles,' ')+'"\n' |
1127 |
> |
txt += 'filesToCheck="'+string.join(listOutFiles,' ')+'"\n' |
1128 |
> |
txt += 'export filesToCheck\n' |
1129 |
> |
|
1130 |
> |
if list : return self.output_file |
1131 |
> |
return txt |