ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/COMP/CRAB/python/cms_cmssw.py
(Generate patch)

Comparing COMP/CRAB/python/cms_cmssw.py (file contents):
Revision 1.231 by spiga, Mon Aug 25 16:13:05 2008 UTC vs.
Revision 1.324 by spiga, Thu Jul 23 12:43:54 2009 UTC

# Line 1 | Line 1
1   from JobType import JobType
2 from crab_logger import Logger
2   from crab_exceptions import *
3   from crab_util import *
5 from BlackWhiteListParser import SEBlackWhiteListParser
4   import common
5   import Scram
6 < from LFNBaseName import *
6 > from Splitter import JobSplitter
7  
8 + from IMProv.IMProvNode import IMProvNode
9   import os, string, glob
10  
11   class Cmssw(JobType):
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 <
17 <        self.argsList = []
19 <
16 >        self.argsList = 1
17 >        self.NumEvents=0
18          self._params = {}
19          self.cfg_params = cfg_params
22        # init BlackWhiteListParser
23        self.blackWhiteListParser = SEBlackWhiteListParser(cfg_params)
20  
21 <        self.MaxTarBallSize = float(self.cfg_params.get('EDG.maxtarballsize',9.5))
21 >        ### Temporary patch to automatically skip the ISB size check:
22 >        self.server = self.cfg_params.get('CRAB.server_name',None) or \
23 >                      self.cfg_params.get('CRAB.use_server',0)
24 >        size = 9.5
25 >        if self.server or common.scheduler.name().upper() in ['LSF','CAF']:
26 >            size = 99999
27 >        self.MaxTarBallSize = float(self.cfg_params.get('GRID.maxtarballsize',size))
28  
29          # number of jobs requested to be created, limit obj splitting
30          self.ncjobs = ncjobs
31  
30        log = common.logger
31
32          self.scram = Scram.Scram(cfg_params)
33          self.additional_inbox_files = []
34          self.scriptExe = ''
# Line 39 | Line 39 | class Cmssw(JobType):
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.logger.log(10-1,"CMSSW version is: "+str(self.version))
48          version_array = self.version.split('_')
49          self.CMSSW_major = 0
50          self.CMSSW_minor = 0
# Line 55 | Line 57 | class Cmssw(JobType):
57              msg = "Cannot parse CMSSW version string: " + self.version + " for major and minor release number!"
58              raise CrabException(msg)
59  
60 +        if self.CMSSW_major < 1 or (self.CMSSW_major == 1 and self.CMSSW_minor < 5):
61 +            msg = "CRAB supports CMSSW >= 1_5_x only. Use an older CRAB version."
62 +            raise CrabException(msg)
63 +            """
64 +            As CMSSW versions are dropped we can drop more code:
65 +            1.X dropped: drop support for running .cfg on WN
66 +            2.0 dropped: drop all support for cfg here and in writeCfg
67 +            2.0 dropped: Recheck the random number seed support
68 +            """
69 +
70          ### collect Data cards
71  
60        if not cfg_params.has_key('CMSSW.datasetpath'):
61            msg = "Error: datasetpath not defined "
62            raise CrabException(msg)
72  
73          ### Temporary: added to remove input file control in the case of PU
74          self.dataset_pu = cfg_params.get('CMSSW.dataset_pu', None)
75  
76          tmp =  cfg_params['CMSSW.datasetpath']
77 <        log.debug(6, "CMSSW::CMSSW(): datasetPath = "+tmp)
78 <        if string.lower(tmp)=='none':
77 >        common.logger.log(10-1, "CMSSW::CMSSW(): datasetPath = "+tmp)
78 >
79 >        if tmp =='':
80 >            msg = "Error: datasetpath not defined "
81 >            raise CrabException(msg)
82 >        elif string.lower(tmp)=='none':
83              self.datasetPath = None
84              self.selectNoInput = 1
85 +            self.primaryDataset = 'null'
86          else:
87              self.datasetPath = tmp
88              self.selectNoInput = 0
89 +            self.primaryDataset = self.datasetPath.split("/")[1]
90 +            self.dataTier = self.datasetPath.split("/")[2]
91  
92          self.dataTiers = []
93 <        self.debugWrap = ''
94 <        self.debug_wrapper = cfg_params.get('USER.debug_wrapper',False)
95 <        if self.debug_wrapper: self.debugWrap='--debug'
93 >
94 >        self.debugWrap=''
95 >        self.debug_wrapper = int(cfg_params.get('USER.debug_wrapper',0))
96 >        if self.debug_wrapper == 1: self.debugWrap='--debug'
97 >
98          ## now the application
99 +        self.managedGenerators = ['madgraph', 'comphep', 'lhe']
100 +        self.generator = cfg_params.get('CMSSW.generator','pythia').lower()
101          self.executable = cfg_params.get('CMSSW.executable','cmsRun')
102 <        log.debug(6, "CMSSW::CMSSW(): executable = "+self.executable)
102 >        common.logger.log(10-1, "CMSSW::CMSSW(): executable = "+self.executable)
103  
104          if not cfg_params.has_key('CMSSW.pset'):
105              raise CrabException("PSet file missing. Cannot run cmsRun ")
106          self.pset = cfg_params['CMSSW.pset']
107 <        log.debug(6, "Cmssw::Cmssw(): PSet file = "+self.pset)
107 >        common.logger.log(10-1, "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")
# Line 116 | Line 136 | class Cmssw(JobType):
136                  raise CrabException(msg)
137              self.additional_inbox_files.append(string.strip(self.scriptExe))
138  
139 +        self.AdditionalArgs = cfg_params.get('USER.script_arguments',None)
140 +        if self.AdditionalArgs : self.AdditionalArgs = string.replace(self.AdditionalArgs,',',' ')
141 +
142          if self.datasetPath == None and self.pset == None and self.scriptExe == '' :
143              msg ="Error. script_exe  not defined"
144              raise CrabException(msg)
145  
146          # use parent files...
147 <        self.useParent = self.cfg_params.get('CMSSW.use_parent',False)
147 >        self.useParent = int(self.cfg_params.get('CMSSW.use_parent',0))
148  
149          ## additional input files
150          if cfg_params.has_key('USER.additional_input_files'):
# Line 144 | Line 167 | class Cmssw(JobType):
167                      self.additional_inbox_files.append(string.strip(file))
168                  pass
169              pass
170 <            common.logger.debug(5,"Additional input files: "+str(self.additional_inbox_files))
170 >            common.logger.debug("Additional input files: "+str(self.additional_inbox_files))
171          pass
172  
150        ## Events per job
151        if cfg_params.has_key('CMSSW.events_per_job'):
152            self.eventsPerJob =int( cfg_params['CMSSW.events_per_job'])
153            self.selectEventsPerJob = 1
154        else:
155            self.eventsPerJob = -1
156            self.selectEventsPerJob = 0
157
158        ## number of jobs
159        if cfg_params.has_key('CMSSW.number_of_jobs'):
160            self.theNumberOfJobs =int( cfg_params['CMSSW.number_of_jobs'])
161            self.selectNumberOfJobs = 1
162        else:
163            self.theNumberOfJobs = 0
164            self.selectNumberOfJobs = 0
165
166        if cfg_params.has_key('CMSSW.total_number_of_events'):
167            self.total_number_of_events = int(cfg_params['CMSSW.total_number_of_events'])
168            self.selectTotalNumberEvents = 1
169            if self.selectNumberOfJobs  == 1:
170                if (self.total_number_of_events != -1) and int(self.total_number_of_events) < int(self.theNumberOfJobs):
171                    msg = 'Must specify at least one event per job. total_number_of_events > number_of_jobs '
172                    raise CrabException(msg)
173        else:
174            self.total_number_of_events = 0
175            self.selectTotalNumberEvents = 0
176
177        if self.pset != None:
178             if ( (self.selectTotalNumberEvents + self.selectEventsPerJob + self.selectNumberOfJobs) != 2 ):
179                 msg = 'Must define exactly two of total_number_of_events, events_per_job, or number_of_jobs.'
180                 raise CrabException(msg)
181        else:
182             if (self.selectNumberOfJobs == 0):
183                 msg = 'Must specify  number_of_jobs.'
184                 raise CrabException(msg)
173  
174          ## New method of dealing with seeds
175          self.incrementSeeds = []
# Line 197 | Line 185 | class Cmssw(JobType):
185                  tmp.strip()
186                  self.incrementSeeds.append(tmp)
187  
200        ## FUTURE: Can remove in CRAB 2.4.0
201        self.sourceSeed    = cfg_params.get('CMSSW.pythia_seed',None)
202        self.sourceSeedVtx = cfg_params.get('CMSSW.vtx_seed',None)
203        self.sourceSeedG4  = cfg_params.get('CMSSW.g4_seed',None)
204        self.sourceSeedMix = cfg_params.get('CMSSW.mix_seed',None)
205        if self.sourceSeed or self.sourceSeedVtx or self.sourceSeedG4 or self.sourceSeedMix:
206            msg = 'pythia_seed, vtx_seed, g4_seed, and mix_seed are no longer valid settings. You must use increment_seeds or preserve_seeds'
207            raise CrabException(msg)
208
188          self.firstRun = cfg_params.get('CMSSW.first_run',None)
189  
190 <        # Copy/return
190 >        # Copy/return/publish
191          self.copy_data = int(cfg_params.get('USER.copy_data',0))
192          self.return_data = int(cfg_params.get('USER.return_data',0))
193 +        ### FEDE ###
194 +        self.publish_data = int(cfg_params.get('USER.publish_data',0))
195 +        if (self.publish_data == 1):
196 +            if not cfg_params.has_key('USER.publish_data_name'):
197 +                raise CrabException('Cannot publish output data, because you did not specify USER.publish_data_name parameter in the crab.cfg file')
198 +            else:
199 +                self.processedDataset = cfg_params['USER.publish_data_name']
200 +            #### check of lenght of datasetname to publish ####
201 +                common.logger.debug("test 100 char limit on datasetname")
202 +                user = getUserName()
203 +                common.logger.debug("user = " + user)
204 +                len_user_name = len(user)
205 +                common.logger.debug("len_user_name = " + str(len_user_name))
206 +                len_processedDataset = len(self.processedDataset)
207 +                common.logger.debug("processedDataset " + self.processedDataset)
208 +                common.logger.debug("len_processedDataset = " + str(len_processedDataset))
209 +                if (self.datasetPath != None ):
210 +                   len_primary = len(self.primaryDataset)
211 +                   common.logger.debug("primaryDataset = " + self.primaryDataset)
212 +                   common.logger.debug("len_primary = " + str(len_primary))
213 +                   #common.logger.info("59 - len_user_name - len_primary = " + str(59 - len_user_name - len_primary))
214 +                   if (len_processedDataset > (59 - len_user_name - len_primary)):
215 +                      raise CrabException("Warning: publication name too long. USER.publish_data_name has to be < " + str(59 - len_user_name - len_primary) + " characters")
216 +                else:
217 +                   if (len_processedDataset > (59 - len_user_name) / 2):
218 +                       raise CrabException("Warning: publication name too long. USER.publish_data_name has to be < " + str((59 - len_user_name) / 2) + " characters")
219  
220 +        self.conf = {}
221 +        self.conf['pubdata'] = None
222 +        # number of jobs requested to be created, limit obj splitting DD
223          #DBSDLS-start
224          ## Initialize the variables that are extracted from DBS/DLS and needed in other places of the code
225          self.maxEvents=0  # max events available   ( --> check the requested nb. of evts in Creator.py)
# Line 223 | Line 231 | class Cmssw(JobType):
231          if self.datasetPath:
232              blockSites = self.DataDiscoveryAndLocation(cfg_params)
233          #DBSDLS-end
234 +        self.conf['blockSites']=blockSites
235  
236          ## Select Splitting
237 +        splitByRun = int(cfg_params.get('CMSSW.split_by_run',0))
238 +
239          if self.selectNoInput:
240              if self.pset == None:
241 <                self.jobSplittingForScript()
241 >                self.algo = 'ForScript'
242              else:
243 <                self.jobSplittingNoInput()
243 >                self.algo = 'NoInput'
244 >                self.conf['managedGenerators']=self.managedGenerators
245 >                self.conf['generator']=self.generator
246 >        elif splitByRun ==1:
247 >            self.algo = 'RunBased'
248          else:
249 <            self.jobSplittingByBlocks(blockSites)
249 >            self.algo = 'EventBased'
250 >
251 > #        self.algo = 'LumiBased'
252 >        splitter = JobSplitter(self.cfg_params,self.conf)
253 >        self.dict = splitter.Algos()[self.algo]()
254  
255 +        self.argsFile= '%s/arguments.xml'%common.work_space.shareDir()
256 +        self.rootArgsFilename= 'arguments'
257          # modify Pset only the first time
258          if isNew:
259 <            if self.pset != None:
260 <                import PsetManipulator as pp
240 <                PsetEdit = pp.PsetManipulator(self.pset)
241 <                try:
242 <                    # Add FrameworkJobReport to parameter-set, set max events.
243 <                    # Reset later for data jobs by writeCFG which does all modifications
244 <                    PsetEdit.addCrabFJR(self.fjrFileName) # FUTURE: Job report addition not needed by CMSSW>1.5
245 <                    PsetEdit.maxEvent(self.eventsPerJob)
246 <                    PsetEdit.psetWriter(self.configFilename())
247 <                    ## If present, add TFileService to output files
248 <                    if not int(cfg_params.get('CMSSW.skip_TFileService_output',0)):
249 <                        tfsOutput = PsetEdit.getTFileService()
250 <                        if tfsOutput:
251 <                            if tfsOutput in self.output_file:
252 <                                common.logger.debug(5,"Output from TFileService "+tfsOutput+" already in output files")
253 <                            else:
254 <                                outfileflag = True #output found
255 <                                self.output_file.append(tfsOutput)
256 <                                common.logger.message("Adding "+tfsOutput+" to output files (from TFileService)")
257 <                            pass
258 <                        pass
259 <                    ## If present and requested, add PoolOutputModule to output files
260 <                    if int(cfg_params.get('CMSSW.get_edm_output',0)):
261 <                        edmOutput = PsetEdit.getPoolOutputModule()
262 <                        if edmOutput:
263 <                            if edmOutput in self.output_file:
264 <                                common.logger.debug(5,"Output from PoolOutputModule "+edmOutput+" already in output files")
265 <                            else:
266 <                                self.output_file.append(edmOutput)
267 <                                common.logger.message("Adding "+edmOutput+" to output files (from PoolOutputModule)")
268 <                            pass
269 <                        pass
270 <                except CrabException:
271 <                    msg='Error while manipulating ParameterSet: exiting...'
272 <                    raise CrabException(msg)
259 >            if self.pset != None: self.ModifyPset()
260 >
261              ## Prepare inputSandbox TarBall (only the first time)
262 <            self.tgzNameWithPath = self.getTarBall(self.executable)
262 >            self.tarNameWithPath = self.getTarBall(self.executable)
263 >
264 >
265 >    def ModifyPset(self):
266 >        import PsetManipulator as pp
267 >        PsetEdit = pp.PsetManipulator(self.pset)
268 >        try:
269 >            # Add FrameworkJobReport to parameter-set, set max events.
270 >            # Reset later for data jobs by writeCFG which does all modifications
271 >            PsetEdit.maxEvent(1)
272 >            PsetEdit.skipEvent(0)
273 >            PsetEdit.psetWriter(self.configFilename())
274 >            ## If present, add TFileService to output files
275 >            if not int(self.cfg_params.get('CMSSW.skip_TFileService_output',0)):
276 >                tfsOutput = PsetEdit.getTFileService()
277 >                if tfsOutput:
278 >                    if tfsOutput in self.output_file:
279 >                        common.logger.debug("Output from TFileService "+tfsOutput+" already in output files")
280 >                    else:
281 >                        outfileflag = True #output found
282 >                        self.output_file.append(tfsOutput)
283 >                        common.logger.info("Adding "+tfsOutput+" (from TFileService) to list of output files")
284 >                    pass
285 >                pass
286 >            # If present and requested, add PoolOutputModule to output files
287 >            edmOutput = PsetEdit.getPoolOutputModule()
288 >            if int(self.cfg_params.get('CMSSW.get_edm_output',0)):
289 >                if edmOutput:
290 >                    for outputFile in edmOutput:
291 >                        if outputFile in self.output_file:
292 >                            common.logger.debug("Output from PoolOutputModule "+edmOutput+" already in output files")
293 >                        else:
294 >                            self.output_file.append(outputFile)
295 >                            common.logger.info("Adding "+outputFile+" (from PoolOutputModule) to list of output files")
296 >            # not requested, check anyhow to avoid accidental T2 overload
297 >            else:
298 >                if edmOutput:
299 >                    missedFiles = []
300 >                    for outputFile in edmOutput:
301 >                        if outputFile not in self.output_file:
302 >                            missedFiles.append(outputFile)
303 >                    if missedFiles:
304 >                        msg  = "ERROR: PoolOutputModule(s) are present in your ParameteSet %s \n"%self.pset
305 >                        msg += "    but the file(s) produced ( %s ) are not in the list of output files\n" % ', '.join(missedFiles)
306 >                        msg += "WARNING: please remove them. If you want to keep them, add the file(s) to output_files or use CMSSW.get_edm_output = 1\n"
307 >                        if int(self.cfg_params.get('CMSSW.ignore_edm_output',0)):
308 >                            msg += "    CMSSW.ignore_edm_output==1 : Hope you know what you are doing...\n"
309 >                            common.logger.info(msg)
310 >                        else :
311 >                            raise CrabException(msg)
312 >
313 >            if (PsetEdit.getBadFilesSetting()):
314 >                msg = "WARNING: You have set skipBadFiles to True. This will continue processing on some errors and you may not be notified."
315 >                common.logger.info(msg)
316 >
317 >        except CrabException, msg:
318 >            common.logger.info(str(msg))
319 >            msg='Error while manipulating ParameterSet (see previous message, if any): exiting...'
320 >            raise CrabException(msg)
321 >
322  
323      def DataDiscoveryAndLocation(self, cfg_params):
324  
325          import DataDiscovery
326          import DataLocation
327 <        common.logger.debug(10,"CMSSW::DataDiscoveryAndLocation()")
327 >        common.logger.log(10-1,"CMSSW::DataDiscoveryAndLocation()")
328  
329          datasetPath=self.datasetPath
330  
331          ## Contact the DBS
332 <        common.logger.message("Contacting Data Discovery Services ...")
332 >        common.logger.info("Contacting Data Discovery Services ...")
333          try:
334              self.pubdata=DataDiscovery.DataDiscovery(datasetPath, cfg_params,self.skip_blocks)
335              self.pubdata.fetchDBSInfo()
# Line 298 | Line 345 | class Cmssw(JobType):
345              raise CrabException(msg)
346  
347          self.filesbyblock=self.pubdata.getFiles()
348 <        self.eventsbyblock=self.pubdata.getEventsPerBlock()
349 <        self.eventsbyfile=self.pubdata.getEventsPerFile()
303 <        self.parentFiles=self.pubdata.getParent()
348 >        #print self.filesbyblock
349 >        self.conf['pubdata']=self.pubdata
350  
351          ## get max number of events
352          self.maxEvents=self.pubdata.getMaxEvents()
# Line 309 | Line 355 | class Cmssw(JobType):
355          try:
356              dataloc=DataLocation.DataLocation(self.filesbyblock.keys(),cfg_params)
357              dataloc.fetchDLSInfo()
358 +
359          except DataLocation.DataLocationError , ex:
360              msg = 'ERROR ***: failed Data Location in DLS \n %s '%ex.getErrorMessage()
361              raise CrabException(msg)
362  
363  
364 <        sites = dataloc.getSites()
364 >        unsorted_sites = dataloc.getSites()
365 >        sites = self.filesbyblock.fromkeys(self.filesbyblock,'')
366 >        for lfn in self.filesbyblock.keys():
367 >            if unsorted_sites.has_key(lfn):
368 >                sites[lfn]=unsorted_sites[lfn]
369 >            else:
370 >                sites[lfn]=[]
371 >
372 >        if len(sites)==0:
373 >            msg = 'ERROR ***: no location for any of the blocks of this dataset: \n\t %s \n'%datasetPath
374 >            msg += "\tMaybe the dataset is located only at T1's (or at T0), where analysis jobs are not allowed\n"
375 >            msg += "\tPlease check DataDiscovery page https://cmsweb.cern.ch/dbs_discovery/\n"
376 >            raise CrabException(msg)
377 >
378          allSites = []
379          listSites = sites.values()
380          for listSite in listSites:
381              for oneSite in listSite:
382                  allSites.append(oneSite)
383 <        allSites = self.uniquelist(allSites)
383 >        [allSites.append(it) for it in allSites if not allSites.count(it)]
384  
325        # screen output
326        common.logger.message("Requested dataset: " + datasetPath + " has " + str(self.maxEvents) + " events in " + str(len(self.filesbyblock.keys())) + " blocks.\n")
327
328        return sites
329
330    def jobSplittingByBlocks(self, blockSites):
331        """
332        Perform job splitting. Jobs run over an integer number of files
333        and no more than one block.
334        ARGUMENT: blockSites: dictionary with blocks as keys and list of host sites as values
335        REQUIRES: self.selectTotalNumberEvents, self.selectEventsPerJob, self.selectNumberofJobs,
336                  self.total_number_of_events, self.eventsPerJob, self.theNumberOfJobs,
337                  self.maxEvents, self.filesbyblock
338        SETS: self.jobDestination - Site destination(s) for each job (a list of lists)
339              self.total_number_of_jobs - Total # of jobs
340              self.list_of_args - File(s) job will run on (a list of lists)
341        """
342
343        # ---- Handle the possible job splitting configurations ---- #
344        if (self.selectTotalNumberEvents):
345            totalEventsRequested = self.total_number_of_events
346        if (self.selectEventsPerJob):
347            eventsPerJobRequested = self.eventsPerJob
348            if (self.selectNumberOfJobs):
349                totalEventsRequested = self.theNumberOfJobs * self.eventsPerJob
350
351        # If user requested all the events in the dataset
352        if (totalEventsRequested == -1):
353            eventsRemaining=self.maxEvents
354        # If user requested more events than are in the dataset
355        elif (totalEventsRequested > self.maxEvents):
356            eventsRemaining = self.maxEvents
357            common.logger.message("Requested "+str(self.total_number_of_events)+ " events, but only "+str(self.maxEvents)+" events are available.")
358        # If user requested less events than are in the dataset
359        else:
360            eventsRemaining = totalEventsRequested
361
362        # If user requested more events per job than are in the dataset
363        if (self.selectEventsPerJob and eventsPerJobRequested > self.maxEvents):
364            eventsPerJobRequested = self.maxEvents
365
366        # For user info at end
367        totalEventCount = 0
368
369        if (self.selectTotalNumberEvents and self.selectNumberOfJobs):
370            eventsPerJobRequested = int(eventsRemaining/self.theNumberOfJobs)
371
372        if (self.selectNumberOfJobs):
373            common.logger.message("May not create the exact number_of_jobs requested.")
374
375        if ( self.ncjobs == 'all' ) :
376            totalNumberOfJobs = 999999999
377        else :
378            totalNumberOfJobs = self.ncjobs
379
380        blocks = blockSites.keys()
381        blockCount = 0
382        # Backup variable in case self.maxEvents counted events in a non-included block
383        numBlocksInDataset = len(blocks)
384
385        jobCount = 0
386        list_of_lists = []
387
388        # list tracking which jobs are in which jobs belong to which block
389        jobsOfBlock = {}
390
391        # ---- Iterate over the blocks in the dataset until ---- #
392        # ---- we've met the requested total # of events    ---- #
393        while ( (eventsRemaining > 0) and (blockCount < numBlocksInDataset) and (jobCount < totalNumberOfJobs)):
394            block = blocks[blockCount]
395            blockCount += 1
396            if block not in jobsOfBlock.keys() :
397                jobsOfBlock[block] = []
398
399            if self.eventsbyblock.has_key(block) :
400                numEventsInBlock = self.eventsbyblock[block]
401                common.logger.debug(5,'Events in Block File '+str(numEventsInBlock))
402
403                files = self.filesbyblock[block]
404                numFilesInBlock = len(files)
405                if (numFilesInBlock <= 0):
406                    continue
407                fileCount = 0
408
409                # ---- New block => New job ---- #
410                parString = ""
411                # counter for number of events in files currently worked on
412                filesEventCount = 0
413                # flag if next while loop should touch new file
414                newFile = 1
415                # job event counter
416                jobSkipEventCount = 0
417
418                # ---- Iterate over the files in the block until we've met the requested ---- #
419                # ---- total # of events or we've gone over all the files in this block  ---- #
420                pString=''
421                while ( (eventsRemaining > 0) and (fileCount < numFilesInBlock) and (jobCount < totalNumberOfJobs) ):
422                    file = files[fileCount]
423                    if self.useParent:
424                        parent = self.parentFiles[file]
425                        for f in parent :
426                            pString += '\\\"' + f + '\\\"\,'
427                        common.logger.debug(6, "File "+str(file)+" has the following parents: "+str(parent))
428                        common.logger.write("File "+str(file)+" has the following parents: "+str(parent))
429                    if newFile :
430                        try:
431                            numEventsInFile = self.eventsbyfile[file]
432                            common.logger.debug(6, "File "+str(file)+" has "+str(numEventsInFile)+" events")
433                            # increase filesEventCount
434                            filesEventCount += numEventsInFile
435                            # Add file to current job
436                            parString += '\\\"' + file + '\\\"\,'
437                            newFile = 0
438                        except KeyError:
439                            common.logger.message("File "+str(file)+" has unknown number of events: skipping")
440
441                    eventsPerJobRequested = min(eventsPerJobRequested, eventsRemaining)
442                    # if less events in file remain than eventsPerJobRequested
443                    if ( filesEventCount - jobSkipEventCount < eventsPerJobRequested):
444                        # if last file in block
445                        if ( fileCount == numFilesInBlock-1 ) :
446                            # end job using last file, use remaining events in block
447                            # close job and touch new file
448                            fullString = parString[:-2]
449                            if self.useParent:
450                                fullParentString = pString[:-2]
451                                list_of_lists.append([fullString,fullParentString,str(-1),str(jobSkipEventCount)])
452                            else:
453                                list_of_lists.append([fullString,str(-1),str(jobSkipEventCount)])
454                            common.logger.debug(3,"Job "+str(jobCount+1)+" can run over "+str(filesEventCount - jobSkipEventCount)+" events (last file in block).")
455                            self.jobDestination.append(blockSites[block])
456                            common.logger.debug(5,"Job "+str(jobCount+1)+" Destination: "+str(self.jobDestination[jobCount]))
457                            # fill jobs of block dictionary
458                            jobsOfBlock[block].append(jobCount+1)
459                            # reset counter
460                            jobCount = jobCount + 1
461                            totalEventCount = totalEventCount + filesEventCount - jobSkipEventCount
462                            eventsRemaining = eventsRemaining - filesEventCount + jobSkipEventCount
463                            jobSkipEventCount = 0
464                            # reset file
465                            pString = ""
466                            parString = ""
467                            filesEventCount = 0
468                            newFile = 1
469                            fileCount += 1
470                        else :
471                            # go to next file
472                            newFile = 1
473                            fileCount += 1
474                    # if events in file equal to eventsPerJobRequested
475                    elif ( filesEventCount - jobSkipEventCount == eventsPerJobRequested ) :
476                        # close job and touch new file
477                        fullString = parString[:-2]
478                        if self.useParent:
479                            fullParentString = pString[:-2]
480                            list_of_lists.append([fullString,fullParentString,str(eventsPerJobRequested),str(jobSkipEventCount)])
481                        else:
482                            list_of_lists.append([fullString,str(eventsPerJobRequested),str(jobSkipEventCount)])
483                        common.logger.debug(3,"Job "+str(jobCount+1)+" can run over "+str(eventsPerJobRequested)+" events.")
484                        self.jobDestination.append(blockSites[block])
485                        common.logger.debug(5,"Job "+str(jobCount+1)+" Destination: "+str(self.jobDestination[jobCount]))
486                        jobsOfBlock[block].append(jobCount+1)
487                        # reset counter
488                        jobCount = jobCount + 1
489                        totalEventCount = totalEventCount + eventsPerJobRequested
490                        eventsRemaining = eventsRemaining - eventsPerJobRequested
491                        jobSkipEventCount = 0
492                        # reset file
493                        pString = ""
494                        parString = ""
495                        filesEventCount = 0
496                        newFile = 1
497                        fileCount += 1
498
499                    # if more events in file remain than eventsPerJobRequested
500                    else :
501                        # close job but don't touch new file
502                        fullString = parString[:-2]
503                        if self.useParent:
504                            fullParentString = pString[:-2]
505                            list_of_lists.append([fullString,fullParentString,str(eventsPerJobRequested),str(jobSkipEventCount)])
506                        else:
507                            list_of_lists.append([fullString,str(eventsPerJobRequested),str(jobSkipEventCount)])
508                        common.logger.debug(3,"Job "+str(jobCount+1)+" can run over "+str(eventsPerJobRequested)+" events.")
509                        self.jobDestination.append(blockSites[block])
510                        common.logger.debug(5,"Job "+str(jobCount+1)+" Destination: "+str(self.jobDestination[jobCount]))
511                        jobsOfBlock[block].append(jobCount+1)
512                        # increase counter
513                        jobCount = jobCount + 1
514                        totalEventCount = totalEventCount + eventsPerJobRequested
515                        eventsRemaining = eventsRemaining - eventsPerJobRequested
516                        # calculate skip events for last file
517                        # use filesEventCount (contains several files), jobSkipEventCount and eventsPerJobRequest
518                        jobSkipEventCount = eventsPerJobRequested - (filesEventCount - jobSkipEventCount - self.eventsbyfile[file])
519                        # remove all but the last file
520                        filesEventCount = self.eventsbyfile[file]
521                        if self.useParent:
522                            for f in parent : pString += '\\\"' + f + '\\\"\,'
523                        parString = '\\\"' + file + '\\\"\,'
524                    pass # END if
525                pass # END while (iterate over files in the block)
526        pass # END while (iterate over blocks in the dataset)
527        self.ncjobs = self.total_number_of_jobs = jobCount
528        if (eventsRemaining > 0 and jobCount < totalNumberOfJobs ):
529            common.logger.message("Could not run on all requested events because some blocks not hosted at allowed sites.")
530        common.logger.message(str(jobCount)+" job(s) can run on "+str(totalEventCount)+" events.\n")
385  
386          # screen output
387 <        screenOutput = "List of jobs and available destination sites:\n\n"
534 <
535 <        # keep trace of block with no sites to print a warning at the end
536 <        noSiteBlock = []
537 <        bloskNoSite = []
538 <
539 <        blockCounter = 0
540 <        for block in blocks:
541 <            if block in jobsOfBlock.keys() :
542 <                blockCounter += 1
543 <                screenOutput += "Block %5i: jobs %20s: sites: %s\n" % (blockCounter,spanRanges(jobsOfBlock[block]),
544 <                    ','.join(self.blackWhiteListParser.checkWhiteList(self.blackWhiteListParser.checkBlackList(blockSites[block],block),block)))
545 <                if len(self.blackWhiteListParser.checkWhiteList(self.blackWhiteListParser.checkBlackList(blockSites[block],block),block)) == 0:
546 <                    noSiteBlock.append( spanRanges(jobsOfBlock[block]) )
547 <                    bloskNoSite.append( blockCounter )
548 <
549 <        common.logger.message(screenOutput)
550 <        if len(noSiteBlock) > 0 and len(bloskNoSite) > 0:
551 <            msg = 'WARNING: No sites are hosting any part of data for block:\n                '
552 <            virgola = ""
553 <            if len(bloskNoSite) > 1:
554 <                virgola = ","
555 <            for block in bloskNoSite:
556 <                msg += ' ' + str(block) + virgola
557 <            msg += '\n               Related jobs:\n                 '
558 <            virgola = ""
559 <            if len(noSiteBlock) > 1:
560 <                virgola = ","
561 <            for range_jobs in noSiteBlock:
562 <                msg += str(range_jobs) + virgola
563 <            msg += '\n               will not be submitted and this block of data can not be analyzed!\n'
564 <            if self.cfg_params.has_key('EDG.se_white_list'):
565 <                msg += 'WARNING: SE White List: '+self.cfg_params['EDG.se_white_list']+'\n'
566 <                msg += '(Hint: By whitelisting you force the job to run at this particular site(s).\n'
567 <                msg += 'Please check if the dataset is available at this site!)\n'
568 <            if self.cfg_params.has_key('EDG.ce_white_list'):
569 <                msg += 'WARNING: CE White List: '+self.cfg_params['EDG.ce_white_list']+'\n'
570 <                msg += '(Hint: By whitelisting you force the job to run at this particular site(s).\n'
571 <                msg += 'Please check if the dataset is available at this site!)\n'
572 <
573 <            common.logger.message(msg)
574 <
575 <        self.list_of_args = list_of_lists
576 <        return
577 <
578 <    def jobSplittingNoInput(self):
579 <        """
580 <        Perform job splitting based on number of event per job
581 <        """
582 <        common.logger.debug(5,'Splitting per events')
583 <
584 <        if (self.selectEventsPerJob):
585 <            common.logger.message('Required '+str(self.eventsPerJob)+' events per job ')
586 <        if (self.selectNumberOfJobs):
587 <            common.logger.message('Required '+str(self.theNumberOfJobs)+' jobs in total ')
588 <        if (self.selectTotalNumberEvents):
589 <            common.logger.message('Required '+str(self.total_number_of_events)+' events in total ')
590 <
591 <        if (self.total_number_of_events < 0):
592 <            msg='Cannot split jobs per Events with "-1" as total number of events'
593 <            raise CrabException(msg)
594 <
595 <        if (self.selectEventsPerJob):
596 <            if (self.selectTotalNumberEvents):
597 <                self.total_number_of_jobs = int(self.total_number_of_events/self.eventsPerJob)
598 <            elif(self.selectNumberOfJobs) :
599 <                self.total_number_of_jobs =self.theNumberOfJobs
600 <                self.total_number_of_events =int(self.theNumberOfJobs*self.eventsPerJob)
601 <
602 <        elif (self.selectNumberOfJobs) :
603 <            self.total_number_of_jobs = self.theNumberOfJobs
604 <            self.eventsPerJob = int(self.total_number_of_events/self.total_number_of_jobs)
605 <
606 <        common.logger.debug(5,'N jobs  '+str(self.total_number_of_jobs))
607 <
608 <        # is there any remainder?
609 <        check = int(self.total_number_of_events) - (int(self.total_number_of_jobs)*self.eventsPerJob)
610 <
611 <        common.logger.debug(5,'Check  '+str(check))
612 <
613 <        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')
614 <        if check > 0:
615 <            common.logger.message('Warning: asked '+str(self.total_number_of_events)+' but can do only '+str(int(self.total_number_of_jobs)*self.eventsPerJob))
616 <
617 <        # argument is seed number.$i
618 <        self.list_of_args = []
619 <        for i in range(self.total_number_of_jobs):
620 <            ## Since there is no input, any site is good
621 <            self.jobDestination.append([""]) #must be empty to write correctly the xml
622 <            args=[]
623 <            if (self.firstRun):
624 <                ## pythia first run
625 <                args.append(str(self.firstRun)+str(i))
626 <            self.list_of_args.append(args)
627 <
628 <        return
629 <
630 <
631 <    def jobSplittingForScript(self):
632 <        """
633 <        Perform job splitting based on number of job
634 <        """
635 <        common.logger.debug(5,'Splitting per job')
636 <        common.logger.message('Required '+str(self.theNumberOfJobs)+' jobs in total ')
387 >        common.logger.info("Requested dataset: " + datasetPath + " has " + str(self.maxEvents) + " events in " + str(len(self.filesbyblock.keys())) + " blocks.\n")
388  
389 <        self.total_number_of_jobs = self.theNumberOfJobs
639 <
640 <        common.logger.debug(5,'N jobs  '+str(self.total_number_of_jobs))
389 >        return sites
390  
642        common.logger.message(str(self.total_number_of_jobs)+' jobs can be created')
643
644        # argument is seed number.$i
645        self.list_of_args = []
646        for i in range(self.total_number_of_jobs):
647            self.jobDestination.append([""])
648            self.list_of_args.append([str(i)])
649        return
391  
392      def split(self, jobParams,firstJobID):
393  
394 <        njobs = self.total_number_of_jobs
395 <        arglist = self.list_of_args
394 >        jobParams = self.dict['args']
395 >        njobs = self.dict['njobs']
396 >        self.jobDestination = self.dict['jobDestination']
397 >
398 >        if njobs==0:
399 >            raise CrabException("Ask to split "+str(njobs)+" jobs: aborting")
400 >        if not self.server and njobs > 500:
401 >            raise CrabException("The CRAB client will not submit more than 500 jobs. You must use the server mode.")
402 >
403          # create the empty structure
404          for i in range(njobs):
405              jobParams.append("")
406  
407          listID=[]
408          listField=[]
409 +        listDictions=[]
410 +        exist= os.path.exists(self.argsFile)
411          for id in range(njobs):
412              job = id + int(firstJobID)
663            jobParams[id] = arglist[id]
413              listID.append(job+1)
414              job_ToSave ={}
415              concString = ' '
416              argu=''
417 +            str_argu = str(job+1)
418              if len(jobParams[id]):
419 <                argu +=   concString.join(jobParams[id] )
420 <            job_ToSave['arguments']= str(job+1)+' '+argu
419 >                argu = {'JobID': job+1}
420 >                for i in range(len(jobParams[id])):
421 >                    argu[self.dict['params'][i]]=jobParams[id][i]
422 >                    if len(jobParams[id])==1: self.NumEvents = jobParams[id][i]
423 >                # just for debug
424 >                str_argu += concString.join(jobParams[id])
425 >            if argu != '': listDictions.append(argu)
426 >            job_ToSave['arguments']= str(job+1)
427              job_ToSave['dlsDestination']= self.jobDestination[id]
428              listField.append(job_ToSave)
429 <            msg="Job "+str(job)+" Arguments:   "+str(job+1)+" "+argu+"\n"  \
430 <            +"                     Destination: "+str(self.jobDestination[id])
431 <            common.logger.debug(5,msg)
429 >            from ProdCommon.SiteDB.CmsSiteMapper import CmsSEMap
430 >            cms_se = CmsSEMap()
431 >            msg="Job  %s  Arguments:  %s\n"%(str(job+1),str_argu)
432 >            msg+="\t  Destination: %s "%(str(self.jobDestination[id]))
433 >            SEDestination = [cms_se[dest] for dest in self.jobDestination[id]]
434 >            msg+="\t  CMSDestination: %s "%(str(SEDestination))
435 >            common.logger.log(10-1,msg)
436 >        # write xml
437 >        if len(listDictions):
438 >            if exist==False: self.CreateXML()
439 >            self.addEntry(listDictions)
440 >           # self.zipXMLfile()
441          common._db.updateJob_(listID,listField)
442 <        self.argsList = (len(jobParams[0])+1)
442 >        return
443 >
444 >   # def zipXMLfile(self):
445  
446 +    #    import tarfile
447 +    #    try:
448 +    #        tar = tarfile.open(self.tarNameWithPath, "a")
449 +    #        tar.add(self.argsFile, os.path.basename(self.argsFile))
450 +    #        tar.close()
451 +    #    except IOError, exc:
452 +    #        msg = 'Could not add %s to %s \n'%(self.argsFile,self.tarNameWithPath)
453 +    #        msg += str(exc)
454 +    #        raise CrabException(msg)
455 +    #    except tarfile.TarError, exc:
456 +    #        msg = 'Could not add %s to %s \n'%(self.argsFile,self.tarNameWithPath)
457 +    #        msg += str(exc)
458 +    #        raise CrabException(msg)
459 +    
460 +    def CreateXML(self):
461 +        """
462 +        """
463 +        result = IMProvNode( self.rootArgsFilename )
464 +        outfile = file( self.argsFile, 'w').write(str(result))
465 +        return
466 +
467 +    def addEntry(self, listDictions):
468 +        """
469 +        _addEntry_
470 +
471 +        add an entry to the xml file
472 +        """
473 +        from IMProv.IMProvLoader import loadIMProvFile
474 +        ## load xml
475 +        improvDoc = loadIMProvFile(self.argsFile)
476 +        entrname= 'Job'
477 +        for dictions in listDictions:
478 +           report = IMProvNode(entrname , None, **dictions)
479 +           improvDoc.addNode(report)
480 +        outfile = file( self.argsFile, 'w').write(str(improvDoc))
481          return
482  
483      def numberOfJobs(self):
484 <        return self.total_number_of_jobs
484 >        return self.dict['njobs']
485  
486      def getTarBall(self, exe):
487          """
488          Return the TarBall with lib and exe
489          """
490 <        self.tgzNameWithPath = common.work_space.pathForTgz()+'share/'+self.tgz_name
490 >        self.tgzNameWithPath = common.work_space.pathForTgz()+self.tgz_name
491          if os.path.exists(self.tgzNameWithPath):
492              return self.tgzNameWithPath
493  
# Line 702 | Line 504 | class Cmssw(JobType):
504  
505          ## check if working area is release top
506          if swReleaseTop == '' or swArea == swReleaseTop:
507 <            common.logger.debug(3,"swArea = "+swArea+" swReleaseTop ="+swReleaseTop)
507 >            common.logger.debug("swArea = "+swArea+" swReleaseTop ="+swReleaseTop)
508              return
509  
510          import tarfile
# Line 717 | Line 519 | class Cmssw(JobType):
519                  ## then check if it's private or not
520                  if exeWithPath.find(swReleaseTop) == -1:
521                      # the exe is private, so we must ship
522 <                    common.logger.debug(5,"Exe "+exeWithPath+" to be tarred")
522 >                    common.logger.debug("Exe "+exeWithPath+" to be tarred")
523                      path = swArea+'/'
524                      # distinguish case when script is in user project area or given by full path somewhere else
525                      if exeWithPath.find(path) >= 0 :
# Line 731 | Line 533 | class Cmssw(JobType):
533                      pass
534  
535              ## Now get the libraries: only those in local working area
536 +            tar.dereference=True
537              libDir = 'lib'
538              lib = swArea+'/' +libDir
539 <            common.logger.debug(5,"lib "+lib+" to be tarred")
539 >            common.logger.debug("lib "+lib+" to be tarred")
540              if os.path.exists(lib):
541                  tar.add(lib,libDir)
542  
# Line 742 | Line 545 | class Cmssw(JobType):
545              module = swArea + '/' + moduleDir
546              if os.path.isdir(module):
547                  tar.add(module,moduleDir)
548 +            tar.dereference=False
549  
550              ## Now check if any data dir(s) is present
551              self.dataExist = False
# Line 755 | Line 559 | class Cmssw(JobType):
559                      todo_list += [(entryPath + i, i) for i in  os.listdir(swArea+"/src/"+entry)]
560                      if name == 'data':
561                          self.dataExist=True
562 <                        common.logger.debug(5,"data "+entry+" to be tarred")
562 >                        common.logger.debug("data "+entry+" to be tarred")
563                          tar.add(swArea+"/src/"+entry,"src/"+entry)
564                      pass
565                  pass
# Line 764 | Line 568 | class Cmssw(JobType):
568              if not self.pset is None:
569                  cfg_file = common.work_space.jobDir()+self.configFilename()
570                  tar.add(cfg_file,self.configFilename())
767                common.logger.debug(5,"File added to "+self.tgzNameWithPath+" : "+str(tar.getnames()))
571  
572 +            try:
573 +                crab_cfg_file = common.work_space.shareDir()+'/crab.cfg'
574 +                tar.add(crab_cfg_file,'crab.cfg')
575 +            except:
576 +                pass
577  
578              ## Add ProdCommon dir to tar
579              prodcommonDir = './'
580              prodcommonPath = os.environ['CRABDIR'] + '/' + 'external/'
581 <            neededStuff = ['ProdCommon/__init__.py','ProdCommon/FwkJobRep', 'ProdCommon/CMSConfigTools','ProdCommon/Core','ProdCommon/MCPayloads', 'IMProv']
581 >            neededStuff = ['ProdCommon/__init__.py','ProdCommon/FwkJobRep', 'ProdCommon/CMSConfigTools', \
582 >                           'ProdCommon/Core', 'ProdCommon/MCPayloads', 'IMProv', 'ProdCommon/Storage', \
583 >                           'WMCore/__init__.py','WMCore/Algorithms']
584              for file in neededStuff:
585                  tar.add(prodcommonPath+file,prodcommonDir+file)
776            common.logger.debug(5,"Files added to "+self.tgzNameWithPath+" : "+str(tar.getnames()))
586  
587              ##### ML stuff
588              ML_file_list=['report.py', 'DashboardAPI.py', 'Logger.py', 'ProcInfo.py', 'apmon.py']
589              path=os.environ['CRABDIR'] + '/python/'
590              for file in ML_file_list:
591                  tar.add(path+file,file)
783            common.logger.debug(5,"Files added to "+self.tgzNameWithPath+" : "+str(tar.getnames()))
592  
593              ##### Utils
594 <            Utils_file_list=['parseCrabFjr.py','writeCfg.py', 'fillCrabFjr.py']
594 >            Utils_file_list=['parseCrabFjr.py','writeCfg.py', 'fillCrabFjr.py','cmscp.py']
595              for file in Utils_file_list:
596                  tar.add(path+file,file)
789            common.logger.debug(5,"Files added to "+self.tgzNameWithPath+" : "+str(tar.getnames()))
597  
598              ##### AdditionalFiles
599 +            tar.dereference=True
600              for file in self.additional_inbox_files:
601                  tar.add(file,string.split(file,'/')[-1])
602 <            common.logger.debug(5,"Files added to "+self.tgzNameWithPath+" : "+str(tar.getnames()))
602 >            tar.dereference=False
603 >            common.logger.log(10-1,"Files in "+self.tgzNameWithPath+" : "+str(tar.getnames()))
604  
605              tar.close()
606 <        except IOError:
607 <            raise CrabException('Could not create tar-ball '+self.tgzNameWithPath)
608 <        except tarfile.TarError:
609 <            raise CrabException('Could not create tar-ball '+self.tgzNameWithPath)
606 >        except IOError, exc:
607 >            msg = 'Could not create tar-ball %s \n'%self.tgzNameWithPath
608 >            msg += str(exc)
609 >            raise CrabException(msg)
610 >        except tarfile.TarError, exc:
611 >            msg = 'Could not create tar-ball %s \n'%self.tgzNameWithPath
612 >            msg += str(exc)
613 >            raise CrabException(msg)
614  
802        ## check for tarball size
615          tarballinfo = os.stat(self.tgzNameWithPath)
616          if ( tarballinfo.st_size > self.MaxTarBallSize*1024*1024 ) :
617 <            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.')
617 >            msg  = 'Input sandbox size of ' + str(float(tarballinfo.st_size)/1024.0/1024.0) + ' MB is larger than the allowed ' + str(self.MaxTarBallSize) \
618 >               +'MB input sandbox limit \n'
619 >            msg += '      and not supported by the direct GRID submission system.\n'
620 >            msg += '      Please use the CRAB server mode by setting server_name=<NAME> in section [CRAB] of your crab.cfg.\n'
621 >            msg += '      For further infos please see https://twiki.cern.ch/twiki/bin/view/CMS/CrabServer#CRABSERVER_for_Users'
622 >            raise CrabException(msg)
623  
624          ## create tar-ball with ML stuff
625  
# Line 811 | Line 628 | class Cmssw(JobType):
628          Returns part of a job script which prepares
629          the execution environment for the job 'nj'.
630          """
631 +        # FUTURE: Drop support for .cfg when possible
632          if (self.CMSSW_major >= 2 and self.CMSSW_minor >= 1) or (self.CMSSW_major >= 3):
633              psetName = 'pset.py'
634          else:
# Line 818 | Line 636 | class Cmssw(JobType):
636          # Prepare JobType-independent part
637          txt = '\n#Written by cms_cmssw::wsSetupEnvironment\n'
638          txt += 'echo ">>> setup environment"\n'
639 <        txt += 'if [ $middleware == LCG ]; then \n'
639 >        txt += 'if [ $middleware == LCG ] || [ $middleware == CAF ] || [ $middleware == LSF ]; then \n'
640          txt += self.wsSetupCMSLCGEnvironment_()
641          txt += 'elif [ $middleware == OSG ]; then\n'
642          txt += '    WORKING_DIR=`/bin/mktemp  -d $OSG_WN_TMP/cms_XXXXXXXXXXXX`\n'
# Line 833 | Line 651 | class Cmssw(JobType):
651          txt += '    cd $WORKING_DIR\n'
652          txt += '    echo ">>> current directory (WORKING_DIR): $WORKING_DIR"\n'
653          txt += self.wsSetupCMSOSGEnvironment_()
654 +        #Setup SGE Environment
655 +        txt += 'elif [ $middleware == SGE ]; then\n'
656 +        txt += self.wsSetupCMSLCGEnvironment_()
657 +
658 +        txt += 'elif [ $middleware == ARC ]; then\n'
659 +        txt += self.wsSetupCMSLCGEnvironment_()
660 +
661          txt += 'fi\n'
662  
663          # Prepare JobType-specific part
# Line 848 | Line 673 | class Cmssw(JobType):
673          txt += '    func_exit\n'
674          txt += 'fi \n'
675          txt += 'cd '+self.version+'\n'
676 <        txt += 'SOFTWARE_DIR=`pwd`\n'
676 >        txt += 'SOFTWARE_DIR=`pwd`; export SOFTWARE_DIR\n'
677          txt += 'echo ">>> current directory (SOFTWARE_DIR): $SOFTWARE_DIR" \n'
678          txt += 'eval `'+scram+' runtime -sh | grep -v SCRAMRT_LSB_JOBNAME`\n'
679          txt += 'if [ $? != 0 ] ; then\n'
# Line 872 | Line 697 | class Cmssw(JobType):
697          # Prepare job-specific part
698          job = common.job_list[nj]
699          if (self.datasetPath):
700 +            #self.primaryDataset = self.datasetPath.split("/")[1]
701 +            #DataTier = self.datasetPath.split("/")[2]
702              txt += '\n'
703              txt += 'DatasetPath='+self.datasetPath+'\n'
704  
705 <            datasetpath_split = self.datasetPath.split("/")
706 <            ### FEDE FOR NEW LFN ###
880 <            self.primaryDataset = datasetpath_split[1]
881 <            ########################
882 <            txt += 'PrimaryDataset='+datasetpath_split[1]+'\n'
883 <            txt += 'DataTier='+datasetpath_split[2]+'\n'
705 >            txt += 'PrimaryDataset='+self.primaryDataset +'\n'
706 >            txt += 'DataTier='+self.dataTier+'\n'
707              txt += 'ApplicationFamily=cmsRun\n'
708  
709          else:
710 +            #self.primaryDataset = 'null'
711              txt += 'DatasetPath=MCDataTier\n'
888            ### FEDE FOR NEW LFN ###
889            self.primaryDataset = 'null'
890            ########################
712              txt += 'PrimaryDataset=null\n'
713              txt += 'DataTier=null\n'
714              txt += 'ApplicationFamily=MCDataTier\n'
# Line 895 | Line 716 | class Cmssw(JobType):
716              pset = os.path.basename(job.configFilename())
717              txt += '\n'
718              txt += 'cp  $RUNTIME_AREA/'+pset+' .\n'
898            if (self.datasetPath): # standard job
899                txt += 'InputFiles=${args[1]}; export InputFiles\n'
900                if (self.useParent):
901                    txt += 'ParentFiles=${args[2]}; export ParentFiles\n'
902                    txt += 'MaxEvents=${args[3]}; export MaxEvents\n'
903                    txt += 'SkipEvents=${args[4]}; export SkipEvents\n'
904                else:
905                    txt += 'MaxEvents=${args[2]}; export MaxEvents\n'
906                    txt += 'SkipEvents=${args[3]}; export SkipEvents\n'
907                txt += 'echo "Inputfiles:<$InputFiles>"\n'
908                if (self.useParent): txt += 'echo "ParentFiles:<$ParentFiles>"\n'
909                txt += 'echo "MaxEvents:<$MaxEvents>"\n'
910                txt += 'echo "SkipEvents:<$SkipEvents>"\n'
911            else:  # pythia like job
912                txt += 'PreserveSeeds='  + ','.join(self.preserveSeeds)  + '; export PreserveSeeds\n'
913                txt += 'IncrementSeeds=' + ','.join(self.incrementSeeds) + '; export IncrementSeeds\n'
914                txt += 'echo "PreserveSeeds: <$PreserveSeeds>"\n'
915                txt += 'echo "IncrementSeeds:<$IncrementSeeds>"\n'
916                if (self.firstRun):
917                    txt += 'FirstRun=${args[1]}; export FirstRun\n'
918                    txt += 'echo "FirstRun: <$FirstRun>"\n'
719  
720 <            txt += 'mv -f ' + pset + ' ' + psetName + '\n'
720 >            txt += 'PreserveSeeds='  + ','.join(self.preserveSeeds)  + '; export PreserveSeeds\n'
721 >            txt += 'IncrementSeeds=' + ','.join(self.incrementSeeds) + '; export IncrementSeeds\n'
722 >            txt += 'echo "PreserveSeeds: <$PreserveSeeds>"\n'
723 >            txt += 'echo "IncrementSeeds:<$IncrementSeeds>"\n'
724  
725 <
726 <        if self.pset != None:
924 <            # FUTURE: Can simply for 2_1_x and higher
925 <            txt += '\n'
926 <            if self.debug_wrapper==True:
927 <                txt += 'echo "***** cat ' + psetName + ' *********"\n'
928 <                txt += 'cat ' + psetName + '\n'
929 <                txt += 'echo "****** end ' + psetName + ' ********"\n'
930 <                txt += '\n'
931 <            if (self.CMSSW_major >= 2 and self.CMSSW_minor >= 1) or (self.CMSSW_major >= 3):
932 <                txt += 'PSETHASH=`edmConfigHash ' + psetName + '` \n'
933 <            else:
934 <                txt += 'PSETHASH=`edmConfigHash < ' + psetName + '` \n'
935 <            txt += 'echo "PSETHASH = $PSETHASH" \n'
725 >            txt += 'mv -f ' + pset + ' ' + psetName + '\n'
726 >        else:
727              txt += '\n'
728 +            if self.AdditionalArgs: txt += 'export AdditionalArgs=%s\n'%(self.AdditionalArgs)
729 +            if int(self.NumEvents) != 0: txt += 'export MaxEvents=%s\n'%str(self.NumEvents)
730          return txt
731  
732      def wsUntarSoftware(self, nj=0):
# Line 946 | Line 739 | class Cmssw(JobType):
739  
740          if os.path.isfile(self.tgzNameWithPath):
741              txt += 'echo ">>> tar xzvf $RUNTIME_AREA/'+os.path.basename(self.tgzNameWithPath)+' :" \n'
742 <            txt += 'tar xzvf $RUNTIME_AREA/'+os.path.basename(self.tgzNameWithPath)+'\n'
743 <            if  self.debug_wrapper:
742 >            txt += 'tar zxvf $RUNTIME_AREA/'+os.path.basename(self.tgzNameWithPath)+'\n'
743 >            if  self.debug_wrapper==1 :
744                  txt += 'ls -Al \n'
745              txt += 'untar_status=$? \n'
746              txt += 'if [ $untar_status -ne 0 ]; then \n'
# Line 1001 | Line 794 | class Cmssw(JobType):
794          txt += 'fi\n'
795          txt += '\n'
796  
797 +        if self.pset != None:
798 +            # FUTURE: Drop support for .cfg when possible
799 +            if (self.CMSSW_major >= 2 and self.CMSSW_minor >= 1) or (self.CMSSW_major >= 3):
800 +                psetName = 'pset.py'
801 +            else:
802 +                psetName = 'pset.cfg'
803 +            # FUTURE: Can simply for 2_1_x and higher
804 +            txt += '\n'
805 +            if self.debug_wrapper == 1:
806 +                txt += 'echo "***** cat ' + psetName + ' *********"\n'
807 +                txt += 'cat ' + psetName + '\n'
808 +                txt += 'echo "****** end ' + psetName + ' ********"\n'
809 +                txt += '\n'
810 +                txt += 'echo "***********************" \n'
811 +                txt += 'which edmConfigHash \n'
812 +                txt += 'echo "***********************" \n'
813 +            if (self.CMSSW_major >= 2 and self.CMSSW_minor >= 1) or (self.CMSSW_major >= 3):
814 +                txt += 'edmConfigHash ' + psetName + ' \n'
815 +                txt += 'PSETHASH=`edmConfigHash ' + psetName + '` \n'
816 +            else:
817 +                txt += 'PSETHASH=`edmConfigHash < ' + psetName + '` \n'
818 +            txt += 'echo "PSETHASH = $PSETHASH" \n'
819 +            #### FEDE temporary fix for noEdm files #####
820 +            txt += 'if [ -z "$PSETHASH" ]; then \n'
821 +            txt += '   export PSETHASH=null\n'
822 +            txt += 'fi \n'
823 +            #############################################
824 +            txt += '\n'
825          return txt
826  
827  
# Line 1012 | Line 833 | class Cmssw(JobType):
833  
834      def executableArgs(self):
835          # FUTURE: This function tests the CMSSW version. Can be simplified as we drop support for old versions
836 <        if self.scriptExe:#CarlosDaniele
837 <            return   self.scriptExe + " $NJob"
836 >        if self.scriptExe:
837 >            return self.scriptExe + " $NJob $AdditionalArgs"
838          else:
839              ex_args = ""
840 <            # FUTURE: This tests the CMSSW version. Can remove code as versions deprecated
841 <            # Framework job report
1021 <            if (self.CMSSW_major >= 1 and self.CMSSW_minor >= 5) or (self.CMSSW_major >= 2):
1022 <                ex_args += " -j $RUNTIME_AREA/crab_fjr_$NJob.xml"
1023 <            # Type of config file
840 >            ex_args += " -j $RUNTIME_AREA/crab_fjr_$NJob.xml"
841 >            # Type of config file depends on CMSSW version
842              if self.CMSSW_major >= 2 :
843                  ex_args += " -p pset.py"
844              else:
# Line 1034 | Line 852 | class Cmssw(JobType):
852          inp_box = []
853          if os.path.isfile(self.tgzNameWithPath):
854              inp_box.append(self.tgzNameWithPath)
855 <        wrapper = os.path.basename(str(common._db.queryTask('scriptName')))
856 <        inp_box.append(common.work_space.pathForTgz() +'job/'+ wrapper)
855 >        if os.path.isfile(self.argsFile):
856 >            inp_box.append(self.argsFile)
857 >        inp_box.append(common.work_space.jobDir() + self.scriptName)
858          return inp_box
859  
860      def outputSandbox(self, nj):
# Line 1059 | Line 878 | class Cmssw(JobType):
878          txt = '\n#Written by cms_cmssw::wsRenameOutput\n'
879          txt += 'echo ">>> current directory (SOFTWARE_DIR): $SOFTWARE_DIR" \n'
880          txt += 'echo ">>> current directory content:"\n'
881 <        if self.debug_wrapper:
881 >        if self.debug_wrapper==1:
882              txt += 'ls -Al\n'
883          txt += '\n'
884  
# Line 1085 | Line 904 | class Cmssw(JobType):
904              txt += 'fi\n'
905          file_list = []
906          for fileWithSuffix in (self.output_file):
907 <             file_list.append(numberFile(fileWithSuffix, '$NJob'))
907 >             file_list.append(numberFile('$SOFTWARE_DIR/'+fileWithSuffix, '$NJob'))
908  
909 <        txt += 'file_list="'+string.join(file_list,' ')+'"\n'
909 >        txt += 'file_list="'+string.join(file_list,',')+'"\n'
910          txt += '\n'
911          txt += 'echo ">>> current directory (SOFTWARE_DIR): $SOFTWARE_DIR" \n'
912          txt += 'echo ">>> current directory content:"\n'
913 <        if self.debug_wrapper:
913 >        if self.debug_wrapper==1:
914              txt += 'ls -Al\n'
915          txt += '\n'
916          txt += 'cd $RUNTIME_AREA\n'
# Line 1114 | Line 933 | class Cmssw(JobType):
933  
934          req = req + ' && (other.GlueHostNetworkAdapterOutboundIP)'
935          if ( common.scheduler.name() == "glitecoll" ) or ( common.scheduler.name() == "glite"):
936 <            req += ' && other.GlueCEStateStatus == "Production" '
936 >            ## 25-Jun-2009 SL: patch to use Cream enabled WMS
937 >            if ( self.cfg_params.get('GRID.use_cream',None) ):
938 >                req += ' && (other.GlueCEStateStatus == "Production" || other.GlueCEStateStatus == "Special")'
939 >            else:
940 >                req += ' && other.GlueCEStateStatus == "Production" '
941  
942          return req
943  
# Line 1122 | Line 945 | class Cmssw(JobType):
945          """ return the config filename """
946          # FUTURE: Can remove cfg mode for CMSSW >= 2_1_x
947          if (self.CMSSW_major >= 2 and self.CMSSW_minor >= 1) or (self.CMSSW_major >= 3):
948 <          return self.name()+'.py'
948 >            return self.name()+'.py'
949          else:
950 <          return self.name()+'.cfg'
950 >            return self.name()+'.cfg'
951  
952      def wsSetupCMSOSGEnvironment_(self):
953          """
# Line 1184 | Line 1007 | class Cmssw(JobType):
1007          txt += '    echo "==> setup cms environment ok"\n'
1008          return txt
1009  
1010 <    def modifyReport(self, nj):
1010 >    def wsModifyReport(self, nj):
1011          """
1012          insert the part of the script that modifies the FrameworkJob Report
1013          """
1014 <        txt = '\n#Written by cms_cmssw::modifyReport\n'
1015 <        publish_data = int(self.cfg_params.get('USER.publish_data',0))
1016 <        if (publish_data == 1):
1017 <            processedDataset = self.cfg_params['USER.publish_data_name']
1018 <            if (self.primaryDataset == 'null'):
1019 <                 self.primaryDataset = processedDataset
1020 <            if (common.scheduler.name().upper() == "CAF" or common.scheduler.name().upper() == "LSF"):
1021 <                ### FEDE FOR NEW LFN ###
1022 <                LFNBaseName = LFNBase(self.primaryDataset, processedDataset, LocalUser=True)
1023 <                self.user = getUserName(LocalUser=True)
1201 <                ########################
1202 <            else :
1203 <                ### FEDE FOR NEW LFN ###
1204 <                LFNBaseName = LFNBase(self.primaryDataset, processedDataset)
1205 <                self.user = getUserName()
1206 <                ########################
1207 <
1208 <            txt += 'if [ $copy_exit_status -eq 0 ]; then\n'
1209 <            ### FEDE FOR NEW LFN ###
1210 <            #txt += '    FOR_LFN=%s_${PSETHASH}/\n'%(LFNBaseName)
1211 <            txt += '    FOR_LFN=%s/${PSETHASH}/\n'%(LFNBaseName)
1212 <            ########################
1014 >
1015 >        txt = ''
1016 >        #publish_data = int(self.cfg_params.get('USER.publish_data',0))
1017 >        if (self.copy_data == 1):
1018 >            txt = '\n#Written by cms_cmssw::wsModifyReport\n'
1019 >            #publish_data = int(self.cfg_params.get('USER.publish_data',0))
1020 >
1021 >
1022 >            txt += 'if [ $StageOutExitStatus -eq 0 ]; then\n'
1023 >            txt += '    FOR_LFN=$LFNBaseName\n'
1024              txt += 'else\n'
1025              txt += '    FOR_LFN=/copy_problems/ \n'
1215            txt += '    SE=""\n'
1216            txt += '    SE_PATH=""\n'
1026              txt += 'fi\n'
1027  
1028              txt += 'echo ">>> Modify Job Report:" \n'
1029              txt += 'chmod a+x $RUNTIME_AREA/ProdCommon/FwkJobRep/ModifyJobReport.py\n'
1221            txt += 'ProcessedDataset='+processedDataset+'\n'
1222            txt += 'echo "ProcessedDataset = $ProcessedDataset"\n'
1030              txt += 'echo "SE = $SE"\n'
1031              txt += 'echo "SE_PATH = $SE_PATH"\n'
1032              txt += 'echo "FOR_LFN = $FOR_LFN" \n'
1033              txt += 'echo "CMSSW_VERSION = $CMSSW_VERSION"\n\n'
1034 <            ### FEDE FOR NEW LFN ###
1035 <            txt += 'echo "$RUNTIME_AREA/ProdCommon/FwkJobRep/ModifyJobReport.py $RUNTIME_AREA/crab_fjr_$NJob.xml $NJob $FOR_LFN $PrimaryDataset $DataTier ' + self.user + '-$ProcessedDataset-$PSETHASH $ApplicationFamily $executable $CMSSW_VERSION $PSETHASH $SE $SE_PATH"\n'
1036 <            txt += '$RUNTIME_AREA/ProdCommon/FwkJobRep/ModifyJobReport.py $RUNTIME_AREA/crab_fjr_$NJob.xml $NJob $FOR_LFN $PrimaryDataset $DataTier ' + self.user + '-$ProcessedDataset-$PSETHASH $ApplicationFamily $executable $CMSSW_VERSION $PSETHASH $SE $SE_PATH\n'
1037 <            ########################
1034 >
1035 >
1036 >            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 file_list $file_list'
1037 >            if (self.publish_data == 1):
1038 >                #processedDataset = self.cfg_params['USER.publish_data_name']
1039 >                txt += 'ProcessedDataset='+self.processedDataset+'\n'
1040 >                txt += 'echo "ProcessedDataset = $ProcessedDataset"\n'
1041 >                args += ' UserProcessedDataset $USER-$ProcessedDataset-$PSETHASH'
1042 >
1043 >            txt += 'echo "$RUNTIME_AREA/ProdCommon/FwkJobRep/ModifyJobReport.py '+str(args)+'"\n'
1044 >            txt += '$RUNTIME_AREA/ProdCommon/FwkJobRep/ModifyJobReport.py '+str(args)+'\n'
1045              txt += 'modifyReport_result=$?\n'
1046              txt += 'if [ $modifyReport_result -ne 0 ]; then\n'
1047              txt += '    modifyReport_result=70500\n'
# Line 1248 | Line 1062 | class Cmssw(JobType):
1062          txt += 'if [ -s $RUNTIME_AREA/crab_fjr_$NJob.xml ]; then\n'
1063          txt += '    if [ -s $RUNTIME_AREA/parseCrabFjr.py ]; then\n'
1064          txt += '        cmd_out=`python $RUNTIME_AREA/parseCrabFjr.py --input $RUNTIME_AREA/crab_fjr_$NJob.xml --dashboard $MonitorID,$MonitorJobID '+self.debugWrap+'`\n'
1065 <        if self.debug_wrapper :
1065 >        if self.debug_wrapper==1 :
1066              txt += '        echo "Result of parsing the FrameworkJobReport crab_fjr.xml: $cmd_out"\n'
1067          txt += '        executable_exit_status=`python $RUNTIME_AREA/parseCrabFjr.py --input $RUNTIME_AREA/crab_fjr_$NJob.xml --exitcode`\n'
1068          txt += '        if [ $executable_exit_status -eq 50115 ];then\n'
# Line 1264 | Line 1078 | class Cmssw(JobType):
1078          txt += '        echo "CRAB python script to parse CRAB FrameworkJobReport crab_fjr.xml is not available, using exit code of executable from command line."\n'
1079          txt += '    fi\n'
1080            #### Patch to check input data reading for CMSSW16x Hopefully we-ll remove it asap
1081 <
1082 <        if (self.datasetPath and not (self.dataset_pu or self.useParent) :
1081 >        txt += '    if [ $executable_exit_status -eq 0 ];then\n'
1082 >        txt += '        echo ">>> Executable succeded  $executable_exit_status"\n'
1083 >        ## This cannot more work given the changes on the Job argumentsJob
1084 >        """
1085 >        if (self.datasetPath and not (self.dataset_pu or self.useParent==1)) :
1086            # VERIFY PROCESSED DATA
1087 <            txt += '    if [ $executable_exit_status -eq 0 ];then\n'
1088 <            txt += '      echo ">>> Verify list of processed files:"\n'
1089 <            txt += '      echo $InputFiles |tr -d \'\\\\\' |tr \',\' \'\\n\'|tr -d \'"\' > input-files.txt\n'
1090 <            txt += '      python $RUNTIME_AREA/parseCrabFjr.py --input $RUNTIME_AREA/crab_fjr_$NJob.xml --lfn > processed-files.txt\n'
1091 <            txt += '      cat input-files.txt  | sort | uniq > tmp.txt\n'
1092 <            txt += '      mv tmp.txt input-files.txt\n'
1093 <            txt += '      echo "cat input-files.txt"\n'
1094 <            txt += '      echo "----------------------"\n'
1095 <            txt += '      cat input-files.txt\n'
1096 <            txt += '      cat processed-files.txt | sort | uniq > tmp.txt\n'
1097 <            txt += '      mv tmp.txt processed-files.txt\n'
1098 <            txt += '      echo "----------------------"\n'
1099 <            txt += '      echo "cat processed-files.txt"\n'
1100 <            txt += '      echo "----------------------"\n'
1101 <            txt += '      cat processed-files.txt\n'
1102 <            txt += '      echo "----------------------"\n'
1103 <            txt += '      diff -q input-files.txt processed-files.txt\n'
1104 <            txt += '      fileverify_status=$?\n'
1105 <            txt += '      if [ $fileverify_status -ne 0 ]; then\n'
1106 <            txt += '         executable_exit_status=30001\n'
1107 <            txt += '         echo "ERROR ==> not all input files processed"\n'
1108 <            txt += '         echo "      ==> list of processed files from crab_fjr.xml differs from list in pset.cfg"\n'
1109 <            txt += '         echo "      ==> diff input-files.txt processed-files.txt"\n'
1110 <            txt += '      fi\n'
1111 <            txt += '    fi\n'
1295 <            txt += '\n'
1087 >            txt += '        echo ">>> Verify list of processed files:"\n'
1088 >            txt += '        echo $InputFiles |tr -d \'\\\\\' |tr \',\' \'\\n\'|tr -d \'"\' > input-files.txt\n'
1089 >            txt += '        python $RUNTIME_AREA/parseCrabFjr.py --input $RUNTIME_AREA/crab_fjr_$NJob.xml --lfn > processed-files.txt\n'
1090 >            txt += '        cat input-files.txt  | sort | uniq > tmp.txt\n'
1091 >            txt += '        mv tmp.txt input-files.txt\n'
1092 >            txt += '        echo "cat input-files.txt"\n'
1093 >            txt += '        echo "----------------------"\n'
1094 >            txt += '        cat input-files.txt\n'
1095 >            txt += '        cat processed-files.txt | sort | uniq > tmp.txt\n'
1096 >            txt += '        mv tmp.txt processed-files.txt\n'
1097 >            txt += '        echo "----------------------"\n'
1098 >            txt += '        echo "cat processed-files.txt"\n'
1099 >            txt += '        echo "----------------------"\n'
1100 >            txt += '        cat processed-files.txt\n'
1101 >            txt += '        echo "----------------------"\n'
1102 >            txt += '        diff -qbB input-files.txt processed-files.txt\n'
1103 >            txt += '        fileverify_status=$?\n'
1104 >            txt += '        if [ $fileverify_status -ne 0 ]; then\n'
1105 >            txt += '            executable_exit_status=30001\n'
1106 >            txt += '            echo "ERROR ==> not all input files processed"\n'
1107 >            txt += '            echo "      ==> list of processed files from crab_fjr.xml differs from list in pset.cfg"\n'
1108 >            txt += '            echo "      ==> diff input-files.txt processed-files.txt"\n'
1109 >            txt += '        fi\n'
1110 >        """
1111 >        txt += '    fi\n'
1112          txt += 'else\n'
1113          txt += '    echo "CRAB FrameworkJobReport crab_fjr.xml is not available, using exit code of executable from command line."\n'
1114          txt += 'fi\n'
1115          txt += '\n'
1116 +        txt += 'if [ $executable_exit_status -ne 0 ] && [ $executable_exit_status -ne 50115 ] && [ $executable_exit_status -ne 50117 ] && [ $executable_exit_status -ne 30001 ];then\n'
1117 +        txt += '    echo ">>> Executable failed  $executable_exit_status"\n'
1118 +        txt += '    echo "ExeExitCode=$executable_exit_status" | tee -a $RUNTIME_AREA/$repo\n'
1119 +        txt += '    echo "EXECUTABLE_EXIT_STATUS = $executable_exit_status"\n'
1120 +        txt += '    job_exit_code=$executable_exit_status\n'
1121 +        txt += '    func_exit\n'
1122 +        txt += 'fi\n\n'
1123          txt += 'echo "ExeExitCode=$executable_exit_status" | tee -a $RUNTIME_AREA/$repo\n'
1124          txt += 'echo "EXECUTABLE_EXIT_STATUS = $executable_exit_status"\n'
1125          txt += 'job_exit_code=$executable_exit_status\n'
# Line 1309 | Line 1132 | class Cmssw(JobType):
1132      def getParams(self):
1133          return self._params
1134  
1135 <    def uniquelist(self, old):
1313 <        """
1314 <        remove duplicates from a list
1315 <        """
1316 <        nd={}
1317 <        for e in old:
1318 <            nd[e]=0
1319 <        return nd.keys()
1320 <
1321 <    def outList(self):
1135 >    def outList(self,list=False):
1136          """
1137          check the dimension of the output files
1138          """
# Line 1327 | Line 1141 | class Cmssw(JobType):
1141          listOutFiles = []
1142          stdout = 'CMSSW_$NJob.stdout'
1143          stderr = 'CMSSW_$NJob.stderr'
1144 +        if len(self.output_file) <= 0:
1145 +            msg ="WARNING: no output files name have been defined!!\n"
1146 +            msg+="\tno output files will be reported back/staged\n"
1147 +            common.logger.info(msg)
1148          if (self.return_data == 1):
1149              for file in (self.output_file+self.output_file_sandbox):
1150                  listOutFiles.append(numberFile(file, '$NJob'))
# Line 1340 | Line 1158 | class Cmssw(JobType):
1158          txt += 'echo "output files: '+string.join(listOutFiles,' ')+'"\n'
1159          txt += 'filesToCheck="'+string.join(listOutFiles,' ')+'"\n'
1160          txt += 'export filesToCheck\n'
1161 +
1162 +        if list : return self.output_file
1163          return txt

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines