panda-client-light 2.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- panda_client_light-2.0.1.dist-info/METADATA +56 -0
- panda_client_light-2.0.1.dist-info/RECORD +46 -0
- panda_client_light-2.0.1.dist-info/WHEEL +4 -0
- panda_client_light-2.0.1.dist-info/licenses/LICENSE +201 -0
- pandaclient/AthenaUtils.py +1601 -0
- pandaclient/BookConfig.py +89 -0
- pandaclient/Client.py +1995 -0
- pandaclient/CommonArgs.py +213 -0
- pandaclient/FileSpec.py +130 -0
- pandaclient/Group_argparse.py +107 -0
- pandaclient/JobSpec.py +992 -0
- pandaclient/LocalJobSpec.py +401 -0
- pandaclient/LocalJobsetSpec.py +288 -0
- pandaclient/MiscUtils.py +371 -0
- pandaclient/PBookCore.py +506 -0
- pandaclient/PBookScript.py +670 -0
- pandaclient/PChainScript_native.py +414 -0
- pandaclient/PLogger.py +51 -0
- pandaclient/PandaToolsPkgInfo.py +1 -0
- pandaclient/ParseJobXML.py +395 -0
- pandaclient/PathenaScript.py +3231 -0
- pandaclient/PchainScript.py +323 -0
- pandaclient/PcontainerScript.py +13 -0
- pandaclient/PhpoScript.py +616 -0
- pandaclient/PrunScript.py +2782 -0
- pandaclient/PsubUtils.py +789 -0
- pandaclient/__init__.py +0 -0
- pandaclient/example_task.py +64 -0
- pandaclient/idds_api.py +61 -0
- pandaclient/localSpecs.py +142 -0
- pandaclient/openidc_utils.py +245 -0
- pandaclient/panda_api.py +301 -0
- pandaclient/panda_gui.py +124 -0
- pandaclient/panda_jupyter.py +140 -0
- pandaclient/pcontainer_core.py +174 -0
- pandaclient/test_client_file.py +14 -0
- pandaclient/test_client_job.py +18 -0
- pandaclient/test_client_misc.py +18 -0
- pandaclient/test_client_submit_job.py +20 -0
- pandaclient/test_client_task.py +89 -0
- pandaclient/time_utils.py +21 -0
- pandaclient/workflow_description.py +512 -0
- pandaclient/workflow_template_dispatcher.py +37 -0
- pandaclient/workflow_templates/__init__.py +5 -0
- pandaclient/workflow_templates/multistep_merge.py +143 -0
- pandaclient/workflow_utils.py +34 -0
|
@@ -0,0 +1,1601 @@
|
|
|
1
|
+
import copy
|
|
2
|
+
import json
|
|
3
|
+
import os
|
|
4
|
+
import re
|
|
5
|
+
import sys
|
|
6
|
+
|
|
7
|
+
from . import MiscUtils, PLogger
|
|
8
|
+
from .MiscUtils import commands_fail_on_non_zero_exit_status, commands_get_output, commands_get_output_with_env
|
|
9
|
+
from .PsubUtils import check_invalid_char
|
|
10
|
+
|
|
11
|
+
# error code
|
|
12
|
+
EC_Config = 10
|
|
13
|
+
EC_Archive = 60
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
# get CMT projects
|
|
17
|
+
def getCmtProjects(dir="."):
|
|
18
|
+
# cmt or cmake
|
|
19
|
+
if not useCMake():
|
|
20
|
+
# keep current dir
|
|
21
|
+
curdir = os.getcwd()
|
|
22
|
+
# change dir
|
|
23
|
+
os.chdir(dir)
|
|
24
|
+
# get projects
|
|
25
|
+
out = commands_get_output_with_env("cmt show projects")
|
|
26
|
+
lines = out.split("\n")
|
|
27
|
+
# remove CMT warnings
|
|
28
|
+
tupLines = tuple(lines)
|
|
29
|
+
lines = []
|
|
30
|
+
for line in tupLines:
|
|
31
|
+
if "CMTUSERCONTEXT" in line:
|
|
32
|
+
continue
|
|
33
|
+
if not line.startswith("#"):
|
|
34
|
+
lines.append(line)
|
|
35
|
+
# back to the current dir
|
|
36
|
+
os.chdir(curdir)
|
|
37
|
+
# return
|
|
38
|
+
return lines, out
|
|
39
|
+
else:
|
|
40
|
+
lines = []
|
|
41
|
+
# use current dir as test area
|
|
42
|
+
tmpStr = f"(in {os.getcwd()})"
|
|
43
|
+
lines.append(tmpStr)
|
|
44
|
+
# AtlasProject
|
|
45
|
+
if not "AtlasProject" in os.environ:
|
|
46
|
+
return [], "AtlasProject is not defined in runtime environment"
|
|
47
|
+
tmpStr = "{0} (in {0}/{1})".format(os.environ["AtlasProject"], os.environ["AtlasVersion"])
|
|
48
|
+
lines.append(tmpStr)
|
|
49
|
+
if "AtlasOffline_VERSION" in os.environ:
|
|
50
|
+
tmpStr = "{0} (in {0}/{1})".format("AtlasOffline", os.environ["AtlasOffline_VERSION"])
|
|
51
|
+
lines.append(tmpStr)
|
|
52
|
+
prodVerStr = "{}_VERSION".format(os.environ["AtlasProject"])
|
|
53
|
+
if prodVerStr in os.environ:
|
|
54
|
+
tmpStr = "{0} (in {0}/{1})".format(os.environ["AtlasProject"], os.environ[prodVerStr])
|
|
55
|
+
lines.append(tmpStr)
|
|
56
|
+
return lines, ""
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
# check if ath release
|
|
60
|
+
def isAthRelease(cacheVer):
|
|
61
|
+
try:
|
|
62
|
+
if "AthAnalysis" in cacheVer or re.search("Ath[a-zA-Z]+Base", cacheVer) is not None:
|
|
63
|
+
return True
|
|
64
|
+
except Exception:
|
|
65
|
+
pass
|
|
66
|
+
return False
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
# get Athena version
|
|
70
|
+
def getAthenaVer(verbose=True):
|
|
71
|
+
# get logger
|
|
72
|
+
tmpLog = PLogger.getPandaLogger()
|
|
73
|
+
# get project parameters
|
|
74
|
+
lines, out = getCmtProjects()
|
|
75
|
+
if len(lines) < 2:
|
|
76
|
+
# make a tmp dir to execute cmt
|
|
77
|
+
tmpDir = "cmttmp.%s" % MiscUtils.wrappedUuidGen()
|
|
78
|
+
os.mkdir(tmpDir)
|
|
79
|
+
# try cmt under a subdir since it doesn't work in top dir
|
|
80
|
+
lines, tmpOut = getCmtProjects(tmpDir)
|
|
81
|
+
# delete the tmp dir
|
|
82
|
+
commands_get_output("rm -rf %s" % tmpDir)
|
|
83
|
+
if len(lines) < 2:
|
|
84
|
+
if verbose:
|
|
85
|
+
print(out)
|
|
86
|
+
tmpLog.error("cmt gave wrong info")
|
|
87
|
+
return False, {}
|
|
88
|
+
# private work area
|
|
89
|
+
res = re.search(r"\(in ([^\)]+)\)", lines[0])
|
|
90
|
+
if res is None:
|
|
91
|
+
print(lines[0])
|
|
92
|
+
tmpLog.error("no TestArea. could not get path to private work area")
|
|
93
|
+
return False, {}
|
|
94
|
+
workArea = os.path.realpath(res.group(1))
|
|
95
|
+
# get Athena version and group area
|
|
96
|
+
athenaVer = ""
|
|
97
|
+
groupArea = ""
|
|
98
|
+
cacheVer = ""
|
|
99
|
+
nightVer = ""
|
|
100
|
+
cmtConfig = ""
|
|
101
|
+
for line in lines[1:]:
|
|
102
|
+
res = re.search(r"\(in ([^\)]+)\)", line)
|
|
103
|
+
if res is not None:
|
|
104
|
+
items = line.split()
|
|
105
|
+
if (
|
|
106
|
+
items[0].startswith("Athena")
|
|
107
|
+
or items[0].startswith("Analysis")
|
|
108
|
+
or items[0] in ["AthDerivations", "AnalysisBase", "AthSimulation", "AthDerivation", "AthAnalysis", "AthGeneration", "AtlasStats"]
|
|
109
|
+
):
|
|
110
|
+
isGitBase = True
|
|
111
|
+
else:
|
|
112
|
+
isGitBase = False
|
|
113
|
+
# base release
|
|
114
|
+
if items[0] in ("dist", "AtlasRelease", "AtlasOffline", "AtlasAnalysis", "AtlasTrigger", "AtlasReconstruction") or isGitBase:
|
|
115
|
+
# Atlas release
|
|
116
|
+
if "AtlasBuildStamp" in os.environ and ("AtlasReleaseType" not in os.environ or os.environ["AtlasReleaseType"] != "stable"):
|
|
117
|
+
athenaVer = os.environ["AtlasBuildStamp"]
|
|
118
|
+
useBuildStamp = True
|
|
119
|
+
else:
|
|
120
|
+
athenaVer = os.path.basename(res.group(1))
|
|
121
|
+
useBuildStamp = False
|
|
122
|
+
# nightly
|
|
123
|
+
if athenaVer.startswith("rel") or useBuildStamp or isGitBase:
|
|
124
|
+
# extract base release
|
|
125
|
+
if not useCMake():
|
|
126
|
+
tmpMatch = re.search(r"/([^/]+)(/rel_\d+)*/Atlas[^/]+/rel_\d+", line)
|
|
127
|
+
if tmpMatch is None:
|
|
128
|
+
tmpLog.error("unsupported nightly %s" % line)
|
|
129
|
+
return False, {}
|
|
130
|
+
# set athenaVer and cacheVer
|
|
131
|
+
cacheVer = "-AtlasOffline_%s" % athenaVer
|
|
132
|
+
athenaVer = tmpMatch.group(1)
|
|
133
|
+
else:
|
|
134
|
+
if athenaVer.startswith("rel"):
|
|
135
|
+
tmpLog.error("Nightlies with AFS setup are unsupported on the grid. Setup with CVMFS")
|
|
136
|
+
return False, {}
|
|
137
|
+
if isGitBase:
|
|
138
|
+
cacheVer = f"-{items[0]}_{athenaVer}"
|
|
139
|
+
else:
|
|
140
|
+
cacheVer = "-AtlasOffline_%s" % athenaVer
|
|
141
|
+
if useBuildStamp:
|
|
142
|
+
athenaVer = os.environ["AtlasBuildBranch"]
|
|
143
|
+
break
|
|
144
|
+
# cache or analysis projects
|
|
145
|
+
elif (
|
|
146
|
+
items[0] in ["AtlasProduction", "AtlasPoint1", "AtlasTier0", "AtlasP1HLT", "AtlasDerivation", "TrigMC"]
|
|
147
|
+
or isAthRelease(items[0])
|
|
148
|
+
or items[1].count(".") >= 4
|
|
149
|
+
):
|
|
150
|
+
# cache is used
|
|
151
|
+
if cacheVer != "":
|
|
152
|
+
continue
|
|
153
|
+
# production cache
|
|
154
|
+
cacheTag = os.path.basename(res.group(1))
|
|
155
|
+
if items[0] == "AtlasProduction" and cacheTag.startswith("rel"):
|
|
156
|
+
# nightlies for cache
|
|
157
|
+
tmpMatch = re.search(r"/([^/]+)(/rel_\d+)*/Atlas[^/]+/rel_\d+", line)
|
|
158
|
+
if tmpMatch is None:
|
|
159
|
+
tmpLog.error("unsupported nightly %s" % line)
|
|
160
|
+
return False, {}
|
|
161
|
+
cacheVer = "-AtlasOffline_%s" % cacheTag
|
|
162
|
+
athenaVer = tmpMatch.group(1)
|
|
163
|
+
break
|
|
164
|
+
elif items[0] == "TrigMC" and cacheTag.startswith("rel"):
|
|
165
|
+
# nightlies for cache
|
|
166
|
+
tmpMatch = re.search(r"/([^/]+)(/rel_\d+)*/[^/]+/rel_\d+", line)
|
|
167
|
+
if tmpMatch is None:
|
|
168
|
+
tmpLog.error("unsupported nightly %s" % line)
|
|
169
|
+
return False, {}
|
|
170
|
+
cacheVer = "-{}_{}".format(items[0], cacheTag)
|
|
171
|
+
athenaVer = tmpMatch.group(1)
|
|
172
|
+
break
|
|
173
|
+
elif isAthRelease(items[0]):
|
|
174
|
+
cacheVer = "-{}_{}".format(items[0], cacheTag)
|
|
175
|
+
else:
|
|
176
|
+
# doesn't use when it is a base release since it is not installed in EGEE
|
|
177
|
+
if re.search(r"^\d+\.\d+\.\d+$", cacheTag) is None:
|
|
178
|
+
cacheVer = "-{}_{}".format(items[0], cacheTag)
|
|
179
|
+
# no more check for AthAnalysis
|
|
180
|
+
if isAthRelease(items[0]):
|
|
181
|
+
break
|
|
182
|
+
else:
|
|
183
|
+
# group area
|
|
184
|
+
groupArea = os.path.realpath(res.group(1))
|
|
185
|
+
# cmtconfig
|
|
186
|
+
if "CMTCONFIG" in os.environ:
|
|
187
|
+
cmtConfig = os.environ["CMTCONFIG"]
|
|
188
|
+
# last resort
|
|
189
|
+
if athenaVer == "":
|
|
190
|
+
if "AtlasProject" in os.environ and "AtlasBuildBranch" in os.environ:
|
|
191
|
+
prodVerStr = "{}_VERSION".format(os.environ["AtlasProject"])
|
|
192
|
+
if prodVerStr in os.environ:
|
|
193
|
+
athenaVer = os.environ["AtlasBuildBranch"]
|
|
194
|
+
cacheVer = "-{}_{}".format(os.environ["AtlasProject"], os.environ[prodVerStr])
|
|
195
|
+
groupArea = ""
|
|
196
|
+
# pack return values
|
|
197
|
+
retVal = {
|
|
198
|
+
"workArea": workArea,
|
|
199
|
+
"athenaVer": athenaVer,
|
|
200
|
+
"groupArea": groupArea,
|
|
201
|
+
"cacheVer": cacheVer,
|
|
202
|
+
"nightVer": nightVer,
|
|
203
|
+
"cmtConfig": cmtConfig,
|
|
204
|
+
}
|
|
205
|
+
# check error
|
|
206
|
+
if athenaVer == "" and not isAthRelease(cacheVer):
|
|
207
|
+
tmpStr = ""
|
|
208
|
+
for line in lines:
|
|
209
|
+
tmpStr += line + "\n"
|
|
210
|
+
tmpLog.info("cmt showed\n" + tmpStr)
|
|
211
|
+
tmpLog.error("could not get Athena version. perhaps your requirements file doesn't have ATLAS_TEST_AREA")
|
|
212
|
+
return False, retVal
|
|
213
|
+
# return
|
|
214
|
+
return True, retVal
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
# wrapper for attribute access
|
|
218
|
+
class ConfigAttr(dict):
|
|
219
|
+
# override __getattribute__ for dot access
|
|
220
|
+
def __getattribute__(self, name):
|
|
221
|
+
if name in dict.__dict__.keys():
|
|
222
|
+
return dict.__getattribute__(self, name)
|
|
223
|
+
if name.startswith("__"):
|
|
224
|
+
return dict.__getattribute__(self, name)
|
|
225
|
+
if name in dict.keys(self):
|
|
226
|
+
return dict.__getitem__(self, name)
|
|
227
|
+
return False
|
|
228
|
+
|
|
229
|
+
def __setattr__(self, name, value):
|
|
230
|
+
if name in dict.__dict__.keys():
|
|
231
|
+
dict.__setattr__(self, name, value)
|
|
232
|
+
else:
|
|
233
|
+
dict.__setitem__(self, name, value)
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
# extract run configuration
|
|
237
|
+
def extractRunConfig(jobO, supStream, shipinput, trf, verbose=False, useAMI=False, inDS="", tmpDir=".", one_liner=""):
|
|
238
|
+
# get logger
|
|
239
|
+
tmpLog = PLogger.getPandaLogger()
|
|
240
|
+
outputConfig = ConfigAttr()
|
|
241
|
+
inputConfig = ConfigAttr()
|
|
242
|
+
otherConfig = ConfigAttr()
|
|
243
|
+
statsCode = True
|
|
244
|
+
if trf:
|
|
245
|
+
pass
|
|
246
|
+
else:
|
|
247
|
+
# use AMI
|
|
248
|
+
amiJobO = ""
|
|
249
|
+
if useAMI:
|
|
250
|
+
amiJobO = getJobOtoUseAmiForAutoConf(inDS, tmpDir)
|
|
251
|
+
baseName = os.environ["PANDA_SYS"] + "/etc/panda/share"
|
|
252
|
+
if " - " in jobO:
|
|
253
|
+
jobO = re.sub(" - ", " %s/ConfigExtractor.py - " % baseName, jobO)
|
|
254
|
+
else:
|
|
255
|
+
jobO = jobO + " %s/ConfigExtractor.py " % baseName
|
|
256
|
+
com = "athena.py "
|
|
257
|
+
if one_liner:
|
|
258
|
+
com += '-c "%s" ' % one_liner
|
|
259
|
+
com += "{} {}/FakeAppMgr.py {}".format(amiJobO, baseName, jobO)
|
|
260
|
+
if verbose:
|
|
261
|
+
tmpLog.debug(com)
|
|
262
|
+
# run ConfigExtractor for normal jobO
|
|
263
|
+
out = commands_get_output_with_env(com)
|
|
264
|
+
failExtractor = True
|
|
265
|
+
outputConfig["alloutputs"] = []
|
|
266
|
+
skipOutName = False
|
|
267
|
+
for line in out.split("\n"):
|
|
268
|
+
match = re.findall("^ConfigExtractor > (.+)", line)
|
|
269
|
+
if len(match):
|
|
270
|
+
# suppress some streams
|
|
271
|
+
if match[0].startswith("Output="):
|
|
272
|
+
tmpSt0 = "NoneNoneNone"
|
|
273
|
+
tmpSt1 = "NoneNoneNone"
|
|
274
|
+
tmpSt2 = "NoneNoneNone"
|
|
275
|
+
try:
|
|
276
|
+
tmpSt0 = match[0].replace("=", " ").split()[1].upper()
|
|
277
|
+
except Exception:
|
|
278
|
+
pass
|
|
279
|
+
try:
|
|
280
|
+
tmpSt1 = match[0].replace("=", " ").split()[-1].upper()
|
|
281
|
+
except Exception:
|
|
282
|
+
pass
|
|
283
|
+
try:
|
|
284
|
+
tmpSt2 = match[0].replace("=", " ").split()[2].upper()
|
|
285
|
+
except Exception:
|
|
286
|
+
pass
|
|
287
|
+
toBeSuppressed = False
|
|
288
|
+
# normal check
|
|
289
|
+
if tmpSt0 in supStream or tmpSt1 in supStream or tmpSt2 in supStream:
|
|
290
|
+
toBeSuppressed = True
|
|
291
|
+
# wild card check
|
|
292
|
+
if not toBeSuppressed:
|
|
293
|
+
for tmpPatt in supStream:
|
|
294
|
+
if "*" in tmpPatt:
|
|
295
|
+
tmpPatt = "^" + tmpPatt.replace("*", ".*")
|
|
296
|
+
tmpPatt = tmpPatt.upper()
|
|
297
|
+
if re.search(tmpPatt, tmpSt0) is not None or re.search(tmpPatt, tmpSt1) is not None or re.search(tmpPatt, tmpSt2) is not None:
|
|
298
|
+
toBeSuppressed = True
|
|
299
|
+
break
|
|
300
|
+
# suppressed
|
|
301
|
+
if toBeSuppressed:
|
|
302
|
+
tmpLog.info("%s is suppressed" % line)
|
|
303
|
+
# set skipOutName to ignore output filename in the next loop
|
|
304
|
+
skipOutName = True
|
|
305
|
+
continue
|
|
306
|
+
failExtractor = False
|
|
307
|
+
# AIDA HIST
|
|
308
|
+
if match[0].startswith("Output=HIST"):
|
|
309
|
+
outputConfig["outHist"] = True
|
|
310
|
+
# AIDA NTuple
|
|
311
|
+
if match[0].startswith("Output=NTUPLE"):
|
|
312
|
+
if "outNtuple" not in outputConfig:
|
|
313
|
+
outputConfig["outNtuple"] = []
|
|
314
|
+
tmpItems = match[0].split()
|
|
315
|
+
outputConfig["outNtuple"].append(tmpItems[1])
|
|
316
|
+
# RDO
|
|
317
|
+
if match[0].startswith("Output=RDO"):
|
|
318
|
+
outputConfig["outRDO"] = match[0].split()[1]
|
|
319
|
+
# ESD
|
|
320
|
+
if match[0].startswith("Output=ESD"):
|
|
321
|
+
outputConfig["outESD"] = match[0].split()[1]
|
|
322
|
+
# AOD
|
|
323
|
+
if match[0].startswith("Output=AOD"):
|
|
324
|
+
outputConfig["outAOD"] = match[0].split()[1]
|
|
325
|
+
# TAG output
|
|
326
|
+
if match[0] == "Output=TAG":
|
|
327
|
+
outputConfig["outTAG"] = True
|
|
328
|
+
# TAGCOM
|
|
329
|
+
if match[0].startswith("Output=TAGX"):
|
|
330
|
+
if "outTAGX" not in outputConfig:
|
|
331
|
+
outputConfig["outTAGX"] = []
|
|
332
|
+
tmpItems = match[0].split()
|
|
333
|
+
outputConfig["outTAGX"].append(tuple(tmpItems[1:]))
|
|
334
|
+
# AANT
|
|
335
|
+
if match[0].startswith("Output=AANT"):
|
|
336
|
+
if "outAANT" not in outputConfig:
|
|
337
|
+
outputConfig["outAANT"] = []
|
|
338
|
+
tmpItems = match[0].split()
|
|
339
|
+
outputConfig["outAANT"].append(tuple(tmpItems[1:]))
|
|
340
|
+
# THIST
|
|
341
|
+
if match[0].startswith("Output=THIST"):
|
|
342
|
+
if "outTHIST" not in outputConfig:
|
|
343
|
+
outputConfig["outTHIST"] = []
|
|
344
|
+
tmpItems = match[0].split()
|
|
345
|
+
if not tmpItems[1] in outputConfig["outTHIST"]:
|
|
346
|
+
outputConfig["outTHIST"].append(tmpItems[1])
|
|
347
|
+
# IROOT
|
|
348
|
+
if match[0].startswith("Output=IROOT"):
|
|
349
|
+
if "outIROOT" not in outputConfig:
|
|
350
|
+
outputConfig["outIROOT"] = []
|
|
351
|
+
tmpItems = match[0].split()
|
|
352
|
+
outputConfig["outIROOT"].append(tmpItems[1])
|
|
353
|
+
# Stream1
|
|
354
|
+
if match[0].startswith("Output=STREAM1"):
|
|
355
|
+
outputConfig["outStream1"] = match[0].split()[1]
|
|
356
|
+
# Stream2
|
|
357
|
+
if match[0].startswith("Output=STREAM2"):
|
|
358
|
+
outputConfig["outStream2"] = match[0].split()[1]
|
|
359
|
+
# ByteStream output
|
|
360
|
+
if match[0] == "Output=BS":
|
|
361
|
+
outputConfig["outBS"] = True
|
|
362
|
+
# General Stream
|
|
363
|
+
if match[0].startswith("Output=STREAMG"):
|
|
364
|
+
tmpItems = match[0].split()
|
|
365
|
+
outputConfig["outStreamG"] = []
|
|
366
|
+
for tmpNames in tmpItems[1].split(","):
|
|
367
|
+
outputConfig["outStreamG"].append(tmpNames.split(":"))
|
|
368
|
+
# Metadata
|
|
369
|
+
if match[0].startswith("Output=META"):
|
|
370
|
+
if "outMeta" not in outputConfig:
|
|
371
|
+
outputConfig["outMeta"] = []
|
|
372
|
+
tmpItems = match[0].split()
|
|
373
|
+
outputConfig["outMeta"].append(tuple(tmpItems[1:]))
|
|
374
|
+
# UserDataSvc
|
|
375
|
+
if match[0].startswith("Output=USERDATA"):
|
|
376
|
+
if "outUserData" not in outputConfig:
|
|
377
|
+
outputConfig["outUserData"] = []
|
|
378
|
+
tmpItems = match[0].split()
|
|
379
|
+
outputConfig["outUserData"].append(tmpItems[-1])
|
|
380
|
+
# MultipleStream
|
|
381
|
+
if match[0].startswith("Output=MS"):
|
|
382
|
+
if "outMS" not in outputConfig:
|
|
383
|
+
outputConfig["outMS"] = []
|
|
384
|
+
tmpItems = match[0].split()
|
|
385
|
+
outputConfig["outMS"].append(tuple(tmpItems[1:]))
|
|
386
|
+
# No input
|
|
387
|
+
if match[0] == "No Input":
|
|
388
|
+
inputConfig["noInput"] = True
|
|
389
|
+
# ByteStream input
|
|
390
|
+
if match[0] == "Input=BS":
|
|
391
|
+
inputConfig["inBS"] = True
|
|
392
|
+
# selected ByteStream
|
|
393
|
+
if match[0].startswith("Output=SelBS"):
|
|
394
|
+
tmpItems = match[0].split()
|
|
395
|
+
inputConfig["outSelBS"] = tmpItems[1]
|
|
396
|
+
# TAG input
|
|
397
|
+
if match[0] == "Input=COLL":
|
|
398
|
+
inputConfig["inColl"] = True
|
|
399
|
+
# POOL references
|
|
400
|
+
if match[0].startswith("Input=COLLREF"):
|
|
401
|
+
tmpRef = match[0].split()[-1]
|
|
402
|
+
if tmpRef == "Input=COLLREF":
|
|
403
|
+
# use default token when ref is empty
|
|
404
|
+
tmpRef = "Token"
|
|
405
|
+
elif tmpRef != "Token" and (not tmpRef.endswith("_ref")):
|
|
406
|
+
# append _ref
|
|
407
|
+
tmpRef += "_ref"
|
|
408
|
+
inputConfig["collRefName"] = tmpRef
|
|
409
|
+
# TAG Query
|
|
410
|
+
if match[0].startswith("Input=COLLQUERY"):
|
|
411
|
+
tmpQuery = re.sub("Input=COLLQUERY", "", match[0])
|
|
412
|
+
tmpQuery = tmpQuery.strip()
|
|
413
|
+
inputConfig["tagQuery"] = tmpQuery
|
|
414
|
+
# Minimum bias
|
|
415
|
+
if match[0] == "Input=MINBIAS":
|
|
416
|
+
inputConfig["inMinBias"] = True
|
|
417
|
+
# Cavern input
|
|
418
|
+
if match[0] == "Input=CAVERN":
|
|
419
|
+
inputConfig["inCavern"] = True
|
|
420
|
+
# Beam halo
|
|
421
|
+
if match[0] == "Input=BEAMHALO":
|
|
422
|
+
inputConfig["inBeamHalo"] = True
|
|
423
|
+
# Beam gas
|
|
424
|
+
if match[0] == "Input=BEAMGAS":
|
|
425
|
+
inputConfig["inBeamGas"] = True
|
|
426
|
+
# Back navigation
|
|
427
|
+
if match[0] == "BackNavigation=ON":
|
|
428
|
+
inputConfig["backNavi"] = True
|
|
429
|
+
# Random stream
|
|
430
|
+
if match[0].startswith("RndmStream"):
|
|
431
|
+
if "rndmStream" not in otherConfig:
|
|
432
|
+
otherConfig["rndmStream"] = []
|
|
433
|
+
tmpItems = match[0].split()
|
|
434
|
+
otherConfig["rndmStream"].append(tmpItems[1])
|
|
435
|
+
# Generator file
|
|
436
|
+
if match[0].startswith("RndmGenFile"):
|
|
437
|
+
if "rndmGenFile" not in otherConfig:
|
|
438
|
+
otherConfig["rndmGenFile"] = []
|
|
439
|
+
tmpItems = match[0].split()
|
|
440
|
+
otherConfig["rndmGenFile"].append(tmpItems[-1])
|
|
441
|
+
# G4 Random seeds
|
|
442
|
+
if match[0].startswith("G4RandomSeeds"):
|
|
443
|
+
otherConfig["G4RandomSeeds"] = True
|
|
444
|
+
# input files for direct input
|
|
445
|
+
if match[0].startswith("InputFiles"):
|
|
446
|
+
if shipinput:
|
|
447
|
+
tmpItems = match[0].split()
|
|
448
|
+
otherConfig["inputFiles"] = tmpItems[1:]
|
|
449
|
+
else:
|
|
450
|
+
continue
|
|
451
|
+
# condition file
|
|
452
|
+
if match[0].startswith("CondInput"):
|
|
453
|
+
if "condInput" not in otherConfig:
|
|
454
|
+
otherConfig["condInput"] = []
|
|
455
|
+
tmpItems = match[0].split()
|
|
456
|
+
otherConfig["condInput"].append(tmpItems[-1])
|
|
457
|
+
# collect all outputs
|
|
458
|
+
if match[0].startswith(" Name:"):
|
|
459
|
+
# skipped output
|
|
460
|
+
if skipOutName:
|
|
461
|
+
skipOutName = False
|
|
462
|
+
continue
|
|
463
|
+
outputConfig["alloutputs"].append(match[0].split()[-1])
|
|
464
|
+
continue
|
|
465
|
+
tmpLog.info(line)
|
|
466
|
+
skipOutName = False
|
|
467
|
+
# extractor failed
|
|
468
|
+
if failExtractor:
|
|
469
|
+
print(out)
|
|
470
|
+
tmpLog.error("Could not parse jobOptions")
|
|
471
|
+
statsCode = False
|
|
472
|
+
# return
|
|
473
|
+
retConfig = ConfigAttr()
|
|
474
|
+
retConfig["input"] = inputConfig
|
|
475
|
+
retConfig["other"] = otherConfig
|
|
476
|
+
retConfig["output"] = outputConfig
|
|
477
|
+
return statsCode, retConfig
|
|
478
|
+
|
|
479
|
+
|
|
480
|
+
# extPoolRefs for old releases which don't contain CollectionTools
|
|
481
|
+
athenaStuff = []
|
|
482
|
+
|
|
483
|
+
# jobO files with full path names
|
|
484
|
+
fullPathJobOs = {}
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
# convert fullPathJobOs to str
|
|
488
|
+
def convFullPathJobOsToStr():
|
|
489
|
+
tmpStr = ""
|
|
490
|
+
for fullJobO in fullPathJobOs:
|
|
491
|
+
localName = fullPathJobOs[fullJobO]
|
|
492
|
+
tmpStr += "{}:{},".format(fullJobO, localName)
|
|
493
|
+
tmpStr = tmpStr[:-1]
|
|
494
|
+
return tmpStr
|
|
495
|
+
|
|
496
|
+
|
|
497
|
+
# convert str to fullPathJobOs
|
|
498
|
+
def convStrToFullPathJobOs(tmpStr):
|
|
499
|
+
retMap = {}
|
|
500
|
+
for tmpItem in tmpStr.split(","):
|
|
501
|
+
fullJobO, localName = tmpItem.split(":")
|
|
502
|
+
retMap[fullJobO] = localName
|
|
503
|
+
return retMap
|
|
504
|
+
|
|
505
|
+
|
|
506
|
+
# copy some athena specific files and full-path jobOs
|
|
507
|
+
def copyAthenaStuff(currentDir):
|
|
508
|
+
baseName = os.environ["PANDA_SYS"] + "/etc/panda/share"
|
|
509
|
+
for tmpFile in athenaStuff:
|
|
510
|
+
com = "cp -p {}/{} {}".format(baseName, tmpFile, currentDir)
|
|
511
|
+
commands_get_output(com)
|
|
512
|
+
for fullJobO in fullPathJobOs:
|
|
513
|
+
localName = fullPathJobOs[fullJobO]
|
|
514
|
+
com = "cp -p {} {}/{}".format(fullJobO, currentDir, localName)
|
|
515
|
+
commands_get_output(com)
|
|
516
|
+
|
|
517
|
+
|
|
518
|
+
# delete some athena specific files and copied jobOs
|
|
519
|
+
def deleteAthenaStuff(currentDir):
|
|
520
|
+
for tmpFile in athenaStuff:
|
|
521
|
+
com = "rm -f {}/{}".format(currentDir, tmpFile)
|
|
522
|
+
commands_get_output(com)
|
|
523
|
+
for tmpFile in fullPathJobOs.values():
|
|
524
|
+
com = "rm -f {}/{}".format(currentDir, tmpFile)
|
|
525
|
+
commands_get_output(com)
|
|
526
|
+
|
|
527
|
+
|
|
528
|
+
# set extFile
|
|
529
|
+
extFile = []
|
|
530
|
+
user_set_ext_files = []
|
|
531
|
+
|
|
532
|
+
|
|
533
|
+
def setExtFile(v_extFile):
|
|
534
|
+
global extFile
|
|
535
|
+
extFile = v_extFile
|
|
536
|
+
|
|
537
|
+
|
|
538
|
+
def set_user_set_ext_files(v_user_set_ext_files):
|
|
539
|
+
global user_set_ext_files
|
|
540
|
+
user_set_ext_files = copy.copy(v_user_set_ext_files)
|
|
541
|
+
|
|
542
|
+
|
|
543
|
+
# set excludeFile
|
|
544
|
+
excludeFile = []
|
|
545
|
+
|
|
546
|
+
|
|
547
|
+
def setExcludeFile(strExcludeFile):
|
|
548
|
+
# empty
|
|
549
|
+
if strExcludeFile == "":
|
|
550
|
+
strExcludeFile = "jobReport.json,jobReport.txt,jobReportExtract.pickle"
|
|
551
|
+
else:
|
|
552
|
+
strExcludeFile += ",jobReport.json,jobReport.txt,jobReportExtract.pickle"
|
|
553
|
+
# convert to list
|
|
554
|
+
global excludeFile
|
|
555
|
+
for tmpItem in strExcludeFile.split(","):
|
|
556
|
+
tmpItem = tmpItem.strip()
|
|
557
|
+
if tmpItem == "":
|
|
558
|
+
continue
|
|
559
|
+
# change . to \. for regexp
|
|
560
|
+
tmpItem = tmpItem.replace(".", r"\.")
|
|
561
|
+
# change * to .* for regexp
|
|
562
|
+
tmpItem = tmpItem.replace("*", ".*")
|
|
563
|
+
# append
|
|
564
|
+
excludeFile.append(tmpItem)
|
|
565
|
+
|
|
566
|
+
|
|
567
|
+
# matching for extFiles
|
|
568
|
+
def matchExtFile(fileName):
|
|
569
|
+
# check exclude files
|
|
570
|
+
for tmpPatt in excludeFile:
|
|
571
|
+
if re.search(tmpPatt, fileName) is not None:
|
|
572
|
+
return False
|
|
573
|
+
# gather files with special extensions
|
|
574
|
+
for tmpExtention in [".py", ".dat", ".C", ".xml", "Makefile", ".cc", ".cxx", ".h", ".hh", ".sh", ".cpp", ".hpp"]:
|
|
575
|
+
if fileName.endswith(tmpExtention):
|
|
576
|
+
return True
|
|
577
|
+
# check filename
|
|
578
|
+
baseName = fileName.split("/")[-1]
|
|
579
|
+
for patt in extFile:
|
|
580
|
+
if patt.find("*") == -1:
|
|
581
|
+
# regular matching
|
|
582
|
+
if patt == baseName:
|
|
583
|
+
return True
|
|
584
|
+
# patt may contain / for sub dir
|
|
585
|
+
if patt != "" and re.search(patt, fileName) is not None:
|
|
586
|
+
return True
|
|
587
|
+
else:
|
|
588
|
+
# use regex for *
|
|
589
|
+
tmpPatt = patt.replace("*", ".*")
|
|
590
|
+
if re.search(tmpPatt, baseName) is not None:
|
|
591
|
+
return True
|
|
592
|
+
# patt may contain / for sub dir
|
|
593
|
+
if patt != "" and re.search(tmpPatt, fileName) is not None:
|
|
594
|
+
return True
|
|
595
|
+
# not matched
|
|
596
|
+
return False
|
|
597
|
+
|
|
598
|
+
|
|
599
|
+
# get extended extra stream name
|
|
600
|
+
def getExtendedExtStreamName(sIndex, sName, enableExtension=False, addEXTNPrefix=True):
|
|
601
|
+
tmpBaseExtName = "EXT%s" % sIndex if addEXTNPrefix else ""
|
|
602
|
+
|
|
603
|
+
if enableExtension:
|
|
604
|
+
if addEXTNPrefix:
|
|
605
|
+
tmpBaseExtName += "_"
|
|
606
|
+
|
|
607
|
+
# change * to X and add .tgz
|
|
608
|
+
if sName.find("*") != -1:
|
|
609
|
+
sName = sName.replace("*", "XYZ")
|
|
610
|
+
sName = "%s.tgz" % sName
|
|
611
|
+
|
|
612
|
+
# use extended extra stream name
|
|
613
|
+
tmpItems = sName.split(".")
|
|
614
|
+
if len(tmpItems) > 0:
|
|
615
|
+
tmpBaseExtName += tmpItems[0]
|
|
616
|
+
|
|
617
|
+
tmpLog = PLogger.getPandaLogger()
|
|
618
|
+
if not tmpBaseExtName:
|
|
619
|
+
tmpLog.error(
|
|
620
|
+
"Invalid stream extension name! If you use --useFileFieldAsStream, all %OUT instances in --trf must contain a distinct suffix, e.g. %OUT.AOD.pool.root"
|
|
621
|
+
)
|
|
622
|
+
sys.exit(EC_Config)
|
|
623
|
+
|
|
624
|
+
return tmpBaseExtName
|
|
625
|
+
|
|
626
|
+
|
|
627
|
+
# special files to be treated carefully
|
|
628
|
+
specialFilesForAthena = ["dblookup.xml"]
|
|
629
|
+
|
|
630
|
+
|
|
631
|
+
# archive source files
|
|
632
|
+
def archiveSourceFiles(workArea, runDir, currentDir, tmpDir, verbose, gluePackages=[], dereferenceSymLinks=False, archiveName=""):
|
|
633
|
+
# archive sources
|
|
634
|
+
tmpLog = PLogger.getPandaLogger()
|
|
635
|
+
tmpLog.info("archiving source files")
|
|
636
|
+
|
|
637
|
+
#####################################################################
|
|
638
|
+
# subroutines
|
|
639
|
+
|
|
640
|
+
# scan InstallArea to get a list of local packages
|
|
641
|
+
def getFileList(dir, files, forPackage, readLink=True):
|
|
642
|
+
try:
|
|
643
|
+
list = os.listdir(dir)
|
|
644
|
+
except Exception:
|
|
645
|
+
return
|
|
646
|
+
for item in list:
|
|
647
|
+
# skip if doc or .svn
|
|
648
|
+
if item in ["doc", ".svn", "_CPack_Packages"]:
|
|
649
|
+
continue
|
|
650
|
+
fullName = dir + "/" + item
|
|
651
|
+
if os.path.isdir(fullName):
|
|
652
|
+
# ignore symlinked dir just under InstallArea/include
|
|
653
|
+
# they are created for g77
|
|
654
|
+
if os.path.islink(fullName) and re.search("/InstallArea/include$", dir) is not None:
|
|
655
|
+
pass
|
|
656
|
+
elif os.path.islink(fullName) and readLink and forPackage:
|
|
657
|
+
# resolve symlink
|
|
658
|
+
getFileList(os.readlink(fullName), files, forPackage, readLink)
|
|
659
|
+
else:
|
|
660
|
+
getFileList(fullName, files, forPackage, readLink)
|
|
661
|
+
else:
|
|
662
|
+
if os.path.islink(fullName):
|
|
663
|
+
if readLink:
|
|
664
|
+
tmpLink = os.readlink(fullName)
|
|
665
|
+
# put base dir when relative path
|
|
666
|
+
if not tmpLink.startswith("/"):
|
|
667
|
+
tmpLink = dir + "/" + tmpLink
|
|
668
|
+
tmpLink = os.path.abspath(tmpLink)
|
|
669
|
+
appFileName = tmpLink
|
|
670
|
+
else:
|
|
671
|
+
appFileName = os.path.abspath(fullName)
|
|
672
|
+
else:
|
|
673
|
+
appFileName = os.path.abspath(fullName)
|
|
674
|
+
# remove redundant //
|
|
675
|
+
appFilename = re.sub("//", "/", appFileName)
|
|
676
|
+
# append
|
|
677
|
+
files.append(appFileName)
|
|
678
|
+
|
|
679
|
+
# get package list
|
|
680
|
+
def getPackages(_workArea, gluePackages=[]):
|
|
681
|
+
# get logger
|
|
682
|
+
tmpLog = PLogger.getPandaLogger()
|
|
683
|
+
# special packages
|
|
684
|
+
specialPackages = {"External/Lhapdf": "external/MCGenerators/lhapdf"}
|
|
685
|
+
# get file list
|
|
686
|
+
installFiles = []
|
|
687
|
+
getFileList(_workArea + "/InstallArea", installFiles, True)
|
|
688
|
+
# get list of packages
|
|
689
|
+
cmt_config = os.environ["CMTCONFIG"]
|
|
690
|
+
_packages = []
|
|
691
|
+
for iFile in installFiles:
|
|
692
|
+
# ignore InstallArea stuff
|
|
693
|
+
if re.search("/InstallArea/", iFile):
|
|
694
|
+
continue
|
|
695
|
+
# converted to real path
|
|
696
|
+
file = os.path.realpath(iFile)
|
|
697
|
+
# remove special characters
|
|
698
|
+
sString = re.sub(r"[\+]", ".", os.path.realpath(_workArea))
|
|
699
|
+
# look for /share/ , /python/, /i686-slc3-gcc323-opt/, .h
|
|
700
|
+
for target in ("share/", "python/", cmt_config + "/", r"[^/]+\.h"):
|
|
701
|
+
res = re.search(sString + "/(.+)/" + target, file)
|
|
702
|
+
if res:
|
|
703
|
+
# append
|
|
704
|
+
pName = res.group(1)
|
|
705
|
+
if target in [r"[^/]+\.h"]:
|
|
706
|
+
# convert PackageDir/PackageName/PackageName to PackageDir/PackageName
|
|
707
|
+
pName = re.sub("/[^/]+$", "", pName)
|
|
708
|
+
if pName not in _packages:
|
|
709
|
+
if os.path.isdir(_workArea + "/" + pName):
|
|
710
|
+
_packages.append(pName)
|
|
711
|
+
break
|
|
712
|
+
# check special packages just in case
|
|
713
|
+
for pName in specialPackages:
|
|
714
|
+
pPath = specialPackages[pName]
|
|
715
|
+
if pName not in _packages:
|
|
716
|
+
# look for path pattern
|
|
717
|
+
if re.search(pPath, file) is not None:
|
|
718
|
+
if os.path.isdir(_workArea + "/" + pName):
|
|
719
|
+
# check structured style
|
|
720
|
+
tmpDirList = os.listdir(_workArea + "/" + pName)
|
|
721
|
+
useSS = False
|
|
722
|
+
for tmpDir in tmpDirList:
|
|
723
|
+
if re.search(r"-\d+-\d+-\d+$", tmpDir) is not None:
|
|
724
|
+
_packages.append(pName + "/" + tmpDir)
|
|
725
|
+
useSS = True
|
|
726
|
+
break
|
|
727
|
+
# normal structure
|
|
728
|
+
if not useSS:
|
|
729
|
+
_packages.append(pName)
|
|
730
|
+
# delete since no needs anymore
|
|
731
|
+
del specialPackages[pName]
|
|
732
|
+
break
|
|
733
|
+
# check glue packages
|
|
734
|
+
for pName in gluePackages:
|
|
735
|
+
if pName not in _packages:
|
|
736
|
+
if os.path.isdir(_workArea + "/" + pName):
|
|
737
|
+
# check structured style
|
|
738
|
+
tmpDirList = os.listdir(_workArea + "/" + pName)
|
|
739
|
+
useSS = False
|
|
740
|
+
for tmpDir in tmpDirList:
|
|
741
|
+
if re.search(r"-\d+-\d+-\d+$", tmpDir) is not None:
|
|
742
|
+
fullPName = pName + "/" + tmpDir
|
|
743
|
+
if fullPName not in _packages:
|
|
744
|
+
_packages.append(fullPName)
|
|
745
|
+
useSS = True
|
|
746
|
+
break
|
|
747
|
+
# normal structure
|
|
748
|
+
if not useSS:
|
|
749
|
+
_packages.append(pName)
|
|
750
|
+
else:
|
|
751
|
+
tmpLog.warning("glue package {} not found under {}".format(pName, _workArea))
|
|
752
|
+
# return
|
|
753
|
+
return _packages
|
|
754
|
+
|
|
755
|
+
# archive files
|
|
756
|
+
def archiveFiles(_workArea, _packages, _archiveFullName):
|
|
757
|
+
excludePattern = ".svn"
|
|
758
|
+
for tmpPatt in excludeFile:
|
|
759
|
+
# reverse regexp change
|
|
760
|
+
tmpPatt = tmpPatt.replace(".*", "*")
|
|
761
|
+
tmpPatt = tmpPatt.replace(r"\.", ".")
|
|
762
|
+
excludePattern += " --exclude '%s'" % tmpPatt
|
|
763
|
+
_curdir = os.getcwd()
|
|
764
|
+
# change dir
|
|
765
|
+
os.chdir(_workArea)
|
|
766
|
+
for pack in _packages:
|
|
767
|
+
# archive subdirs
|
|
768
|
+
list = os.listdir(pack)
|
|
769
|
+
for item in list:
|
|
770
|
+
# ignore libraries
|
|
771
|
+
if (
|
|
772
|
+
item.startswith("i686")
|
|
773
|
+
or item.startswith("i386")
|
|
774
|
+
or item.startswith("x86_64")
|
|
775
|
+
or item == "pool"
|
|
776
|
+
or item == "pool_plugins"
|
|
777
|
+
or item == "doc"
|
|
778
|
+
or item == ".svn"
|
|
779
|
+
):
|
|
780
|
+
continue
|
|
781
|
+
# check exclude files
|
|
782
|
+
excludeFileFlag = False
|
|
783
|
+
for tmpPatt in excludeFile:
|
|
784
|
+
if re.search(tmpPatt, "{}/{}".format(pack, item)) is not None:
|
|
785
|
+
excludeFileFlag = True
|
|
786
|
+
break
|
|
787
|
+
if excludeFileFlag:
|
|
788
|
+
continue
|
|
789
|
+
# run dir
|
|
790
|
+
if item == "run":
|
|
791
|
+
files = []
|
|
792
|
+
getFileList("{}/{}/run".format(_workArea, pack), files, False)
|
|
793
|
+
# not resolve symlink (appending instead of replacing for backward compatibility)
|
|
794
|
+
tmpFiles = []
|
|
795
|
+
getFileList("{}/{}/run".format(_workArea, pack), tmpFiles, False, False)
|
|
796
|
+
for tmpFile in tmpFiles:
|
|
797
|
+
if tmpFile not in files:
|
|
798
|
+
files.append(tmpFile)
|
|
799
|
+
for iFile in files:
|
|
800
|
+
# converted to real path
|
|
801
|
+
file = os.path.realpath(iFile)
|
|
802
|
+
# archive .py/.dat/.C files only
|
|
803
|
+
if matchExtFile(file):
|
|
804
|
+
# remove special characters
|
|
805
|
+
sString = re.sub(r"[\+]", ".", os.path.realpath(_workArea))
|
|
806
|
+
relPath = re.sub("^%s/" % sString, "", file)
|
|
807
|
+
# if replace is failed or the file is symlink, try non-converted path names
|
|
808
|
+
if relPath.startswith("/") or os.path.islink(iFile):
|
|
809
|
+
sString = re.sub(r"[\+]", ".", workArea)
|
|
810
|
+
relPath = re.sub(sString + "/", "", iFile)
|
|
811
|
+
if os.path.islink(iFile):
|
|
812
|
+
comStr = "tar -rh '{}' -f '{}' --exclude '{}'".format(relPath, _archiveFullName, excludePattern)
|
|
813
|
+
else:
|
|
814
|
+
comStr = "tar rf '{}' '{}' --exclude '{}'".format(_archiveFullName, relPath, excludePattern)
|
|
815
|
+
if verbose:
|
|
816
|
+
print(relPath)
|
|
817
|
+
|
|
818
|
+
commands_fail_on_non_zero_exit_status(comStr, EC_Archive, logger=tmpLog, error_log_msg="tarball creation failed")
|
|
819
|
+
continue
|
|
820
|
+
# else
|
|
821
|
+
if dereferenceSymLinks:
|
|
822
|
+
comStr = "tar rfh '{}' '{}/{}' --exclude '{}'".format(_archiveFullName, pack, item, excludePattern)
|
|
823
|
+
else:
|
|
824
|
+
comStr = "tar rf '{}' '{}/{}' --exclude '{}'".format(_archiveFullName, pack, item, excludePattern)
|
|
825
|
+
|
|
826
|
+
if verbose:
|
|
827
|
+
print("{}/{}".format(pack, item))
|
|
828
|
+
|
|
829
|
+
commands_fail_on_non_zero_exit_status(comStr, EC_Archive, logger=tmpLog, error_log_msg="tarball creation failed")
|
|
830
|
+
# back to previous dir
|
|
831
|
+
os.chdir(_curdir)
|
|
832
|
+
|
|
833
|
+
#####################################################################
|
|
834
|
+
# execute
|
|
835
|
+
|
|
836
|
+
# get packages in private area
|
|
837
|
+
packages = getPackages(workArea, gluePackages)
|
|
838
|
+
# check TestRelease since it doesn't create any links in InstallArea
|
|
839
|
+
if os.path.exists("%s/TestRelease" % workArea):
|
|
840
|
+
# the TestRelease could be created by hand
|
|
841
|
+
packages.append("TestRelease")
|
|
842
|
+
|
|
843
|
+
if verbose:
|
|
844
|
+
tmpLog.debug("== private packages ==")
|
|
845
|
+
for pack in packages:
|
|
846
|
+
print(pack)
|
|
847
|
+
tmpLog.debug("== private files ==")
|
|
848
|
+
|
|
849
|
+
# create archive
|
|
850
|
+
if archiveName == "":
|
|
851
|
+
archiveName = "sources.%s.tar" % MiscUtils.wrappedUuidGen()
|
|
852
|
+
archiveFullName = "{}/{}".format(tmpDir, archiveName)
|
|
853
|
+
# archive private area
|
|
854
|
+
archiveFiles(workArea, packages, archiveFullName)
|
|
855
|
+
# archive current (run) dir
|
|
856
|
+
files = []
|
|
857
|
+
os.chdir(workArea)
|
|
858
|
+
getFileList("{}/{}".format(workArea, runDir), files, False, False)
|
|
859
|
+
files_in_run_dir = []
|
|
860
|
+
for file in files:
|
|
861
|
+
# remove special characters
|
|
862
|
+
sString = re.sub(r"[\+]", ".", os.path.realpath(workArea))
|
|
863
|
+
relPath = re.sub(sString + "/", "", os.path.realpath(file))
|
|
864
|
+
# if replace is failed or the file is symlink, try non-converted path names
|
|
865
|
+
if relPath.startswith("/") or os.path.islink(file):
|
|
866
|
+
sString = re.sub(r"[\+]", ".", workArea)
|
|
867
|
+
relPath = re.sub(sString + "/", "", file)
|
|
868
|
+
# archive .py/.dat/.C/.xml files only
|
|
869
|
+
if not matchExtFile(relPath):
|
|
870
|
+
continue
|
|
871
|
+
# ignore InstallArea
|
|
872
|
+
if relPath.startswith("InstallArea"):
|
|
873
|
+
continue
|
|
874
|
+
# check special files
|
|
875
|
+
spBaseName = relPath
|
|
876
|
+
if re.search("/", spBaseName) is not None:
|
|
877
|
+
spBaseName = spBaseName.split("/")[-1]
|
|
878
|
+
if spBaseName in specialFilesForAthena:
|
|
879
|
+
warStr = "%s in the current dir is sent to remote WNs, which might cause a database problem. " % spBaseName
|
|
880
|
+
warStr += "If this is intentional please ignore this WARNING"
|
|
881
|
+
tmpLog.warning(warStr)
|
|
882
|
+
# check if already archived
|
|
883
|
+
alreadyFlag = False
|
|
884
|
+
for pack in packages:
|
|
885
|
+
if relPath.startswith(pack):
|
|
886
|
+
alreadyFlag = True
|
|
887
|
+
break
|
|
888
|
+
# archive
|
|
889
|
+
if not alreadyFlag:
|
|
890
|
+
if os.path.islink(file):
|
|
891
|
+
comStr = "tar -rh '{}' -f '{}'".format(relPath, archiveFullName)
|
|
892
|
+
else:
|
|
893
|
+
comStr = "tar rf '{}' '{}'".format(archiveFullName, relPath)
|
|
894
|
+
if verbose:
|
|
895
|
+
print(relPath)
|
|
896
|
+
|
|
897
|
+
commands_fail_on_non_zero_exit_status(comStr, EC_Archive, logger=tmpLog, error_log_msg="tarball creation failed")
|
|
898
|
+
files_in_run_dir.append(os.path.abspath(file))
|
|
899
|
+
# check if extFile is includedor tmp_file_path in files_in_run_dir):
|
|
900
|
+
for tmp_ext_file in user_set_ext_files:
|
|
901
|
+
is_included = False
|
|
902
|
+
for tmp_file_path in files_in_run_dir:
|
|
903
|
+
if re.search(tmp_ext_file, tmp_file_path):
|
|
904
|
+
is_included = True
|
|
905
|
+
break
|
|
906
|
+
if not is_included:
|
|
907
|
+
tmpLog.warning("%s is specified as extFile but not found in the current dir" % tmp_ext_file)
|
|
908
|
+
# back to current dir
|
|
909
|
+
os.chdir(currentDir)
|
|
910
|
+
# return
|
|
911
|
+
return archiveName, archiveFullName
|
|
912
|
+
|
|
913
|
+
|
|
914
|
+
# archive jobO files
|
|
915
|
+
def archiveJobOFiles(workArea, runDir, currentDir, tmpDir, verbose, archiveName=""):
|
|
916
|
+
# archive jobO files
|
|
917
|
+
tmpLog = PLogger.getPandaLogger()
|
|
918
|
+
tmpLog.info("archiving jobOs and modules")
|
|
919
|
+
|
|
920
|
+
# get real jobOs
|
|
921
|
+
def getJobOs(dir, files):
|
|
922
|
+
list = os.listdir(dir)
|
|
923
|
+
for item in list:
|
|
924
|
+
if item in ["_CPack_Packages"]:
|
|
925
|
+
continue
|
|
926
|
+
fullName = dir + "/" + item
|
|
927
|
+
if os.path.isdir(fullName):
|
|
928
|
+
# skip symlinks in include since they cause full scan on releases
|
|
929
|
+
if os.path.islink(fullName) and re.search("InstallArea/include$", dir) is not None:
|
|
930
|
+
continue
|
|
931
|
+
# dir
|
|
932
|
+
getJobOs(fullName, files)
|
|
933
|
+
else:
|
|
934
|
+
# python and other extFiles
|
|
935
|
+
if matchExtFile(fullName):
|
|
936
|
+
files.append(fullName)
|
|
937
|
+
|
|
938
|
+
# get jobOs
|
|
939
|
+
files = []
|
|
940
|
+
os.chdir(workArea)
|
|
941
|
+
getJobOs("%s" % workArea, files)
|
|
942
|
+
# create archive
|
|
943
|
+
if archiveName == "":
|
|
944
|
+
archiveName = "jobO.%s.tar" % MiscUtils.wrappedUuidGen()
|
|
945
|
+
archiveFullName = "{}/{}".format(tmpDir, archiveName)
|
|
946
|
+
# archive
|
|
947
|
+
if verbose:
|
|
948
|
+
tmpLog.debug("== py files ==")
|
|
949
|
+
for file in files:
|
|
950
|
+
# remove special characters
|
|
951
|
+
sString = re.sub(r"[\+]", ".", workArea)
|
|
952
|
+
relPath = re.sub(sString + "/", "", file)
|
|
953
|
+
# append
|
|
954
|
+
comStr = "tar -rh '{}' -f '{}'".format(relPath, archiveFullName)
|
|
955
|
+
if verbose:
|
|
956
|
+
print(relPath)
|
|
957
|
+
|
|
958
|
+
commands_fail_on_non_zero_exit_status(comStr, EC_Archive, logger=tmpLog, error_log_msg="tarball creation failed")
|
|
959
|
+
|
|
960
|
+
# return
|
|
961
|
+
return archiveName, archiveFullName
|
|
962
|
+
|
|
963
|
+
|
|
964
|
+
# archive InstallArea
|
|
965
|
+
def archiveInstallArea(workArea, groupArea, archiveName, archiveFullName, tmpDir, nobuild, verbose):
|
|
966
|
+
# archive jobO files
|
|
967
|
+
tmpLog = PLogger.getPandaLogger()
|
|
968
|
+
tmpLog.info("archiving InstallArea")
|
|
969
|
+
|
|
970
|
+
# get file list
|
|
971
|
+
def getFiles(dir, files, ignoreLib, ignoreSymLink):
|
|
972
|
+
if verbose:
|
|
973
|
+
tmpLog.debug(" getFiles(%s)" % dir)
|
|
974
|
+
try:
|
|
975
|
+
list = os.listdir(dir)
|
|
976
|
+
except Exception:
|
|
977
|
+
return
|
|
978
|
+
for item in list:
|
|
979
|
+
if ignoreLib and (item.startswith("i686") or item.startswith("i386") or item.startswith("x86_64")):
|
|
980
|
+
continue
|
|
981
|
+
fullName = dir + "/" + item
|
|
982
|
+
if os.path.isdir(fullName):
|
|
983
|
+
# ignore symlinked dir just under InstallArea/include
|
|
984
|
+
if ignoreSymLink and os.path.islink(fullName) and re.search("InstallArea/include$", dir) is not None:
|
|
985
|
+
continue
|
|
986
|
+
# dir
|
|
987
|
+
getFiles(fullName, files, False, ignoreSymLink)
|
|
988
|
+
else:
|
|
989
|
+
files.append(fullName)
|
|
990
|
+
|
|
991
|
+
# get cmt files
|
|
992
|
+
def getCMTFiles(dir, files):
|
|
993
|
+
list = os.listdir(dir)
|
|
994
|
+
for item in list:
|
|
995
|
+
fullName = dir + "/" + item
|
|
996
|
+
if os.path.isdir(fullName):
|
|
997
|
+
# dir
|
|
998
|
+
getCMTFiles(fullName, files)
|
|
999
|
+
else:
|
|
1000
|
+
if re.search("cmt/requirements$", fullName) is not None:
|
|
1001
|
+
files.append(fullName)
|
|
1002
|
+
|
|
1003
|
+
# get files
|
|
1004
|
+
areaList = []
|
|
1005
|
+
# workArea must be first
|
|
1006
|
+
areaList.append(workArea)
|
|
1007
|
+
if groupArea != "":
|
|
1008
|
+
areaList.append(groupArea)
|
|
1009
|
+
# groupArea archive
|
|
1010
|
+
groupFileName = re.sub("^sources", "groupArea", archiveName)
|
|
1011
|
+
groupFullName = "{}/{}".format(tmpDir, groupFileName)
|
|
1012
|
+
allFiles = []
|
|
1013
|
+
for areaName in areaList:
|
|
1014
|
+
# archive
|
|
1015
|
+
if verbose:
|
|
1016
|
+
tmpLog.debug("== InstallArea under %s ==" % areaName)
|
|
1017
|
+
files = []
|
|
1018
|
+
cmtFiles = []
|
|
1019
|
+
os.chdir(areaName)
|
|
1020
|
+
if areaName == workArea:
|
|
1021
|
+
if not nobuild:
|
|
1022
|
+
# ignore i686 and include for workArea
|
|
1023
|
+
getFiles("InstallArea", files, True, True)
|
|
1024
|
+
else:
|
|
1025
|
+
# ignore include for workArea
|
|
1026
|
+
getFiles("InstallArea", files, False, True)
|
|
1027
|
+
else:
|
|
1028
|
+
# groupArea
|
|
1029
|
+
if not os.path.exists("InstallArea"):
|
|
1030
|
+
if verbose:
|
|
1031
|
+
print(" Doesn't exist. Skip")
|
|
1032
|
+
continue
|
|
1033
|
+
getFiles("InstallArea", files, False, False)
|
|
1034
|
+
# cmt/requirements is needed for non-release packages
|
|
1035
|
+
for itemDir in os.listdir(areaName):
|
|
1036
|
+
if itemDir != "InstallArea" and os.path.isdir(itemDir) and (not os.path.islink(itemDir)):
|
|
1037
|
+
getCMTFiles(itemDir, cmtFiles)
|
|
1038
|
+
# remove special characters
|
|
1039
|
+
sString = re.sub(r"[\+]", ".", os.path.realpath(areaName))
|
|
1040
|
+
# archive files if they are under the area
|
|
1041
|
+
for file in files + cmtFiles:
|
|
1042
|
+
relPath = re.sub(sString + "/", "", os.path.realpath(file))
|
|
1043
|
+
# check exclude files
|
|
1044
|
+
excludeFileFlag = False
|
|
1045
|
+
for tmpPatt in excludeFile:
|
|
1046
|
+
if re.search(tmpPatt, relPath) is not None:
|
|
1047
|
+
excludeFileFlag = True
|
|
1048
|
+
break
|
|
1049
|
+
if excludeFileFlag:
|
|
1050
|
+
continue
|
|
1051
|
+
if not relPath.startswith("/"):
|
|
1052
|
+
# use files in private InstallArea instead of group InstallArea
|
|
1053
|
+
if file not in allFiles:
|
|
1054
|
+
# append
|
|
1055
|
+
if file in files:
|
|
1056
|
+
comStr = "tar -rh '{}' -f '{}'".format(file, archiveFullName)
|
|
1057
|
+
else:
|
|
1058
|
+
# requirements files
|
|
1059
|
+
comStr = "tar -rh '{}' -f '{}'".format(file, groupFullName)
|
|
1060
|
+
allFiles.append(file)
|
|
1061
|
+
if verbose:
|
|
1062
|
+
print(file)
|
|
1063
|
+
|
|
1064
|
+
commands_fail_on_non_zero_exit_status(comStr, EC_Archive, logger=tmpLog, error_log_msg="tarball creation failed")
|
|
1065
|
+
|
|
1066
|
+
# append groupArea to sources
|
|
1067
|
+
if groupArea != "" and (not nobuild):
|
|
1068
|
+
os.chdir(tmpDir)
|
|
1069
|
+
if os.path.exists(groupFileName):
|
|
1070
|
+
comStr = "tar -rh '{}' -f '{}'".format(groupFileName, archiveFullName)
|
|
1071
|
+
commands_fail_on_non_zero_exit_status(comStr, EC_Archive, logger=tmpLog, error_log_msg="tarball creation failed")
|
|
1072
|
+
|
|
1073
|
+
commands_get_output("rm -rf %s" % groupFullName)
|
|
1074
|
+
|
|
1075
|
+
|
|
1076
|
+
# archive with cpack
|
|
1077
|
+
def archiveWithCpack(withSource, tmpDir, verbose):
|
|
1078
|
+
tmpLog = PLogger.getPandaLogger()
|
|
1079
|
+
# define archive name
|
|
1080
|
+
if withSource:
|
|
1081
|
+
tmpLog.info("archiving source files with cpack")
|
|
1082
|
+
archiveName = "sources.%s" % MiscUtils.wrappedUuidGen()
|
|
1083
|
+
else:
|
|
1084
|
+
tmpLog.info("archiving jobOs and modules with cpack")
|
|
1085
|
+
archiveName = "jobO.%s" % MiscUtils.wrappedUuidGen()
|
|
1086
|
+
archiveFullName = "{}/{}".format(tmpDir, archiveName)
|
|
1087
|
+
# extract build dir
|
|
1088
|
+
buildDir = os.environ["CMAKE_PREFIX_PATH"]
|
|
1089
|
+
buildDir = os.path.dirname(buildDir.split(":")[0])
|
|
1090
|
+
_curdir = os.getcwd()
|
|
1091
|
+
os.chdir(buildDir)
|
|
1092
|
+
tmpLog.info(f"the build directory is {buildDir}")
|
|
1093
|
+
check_file = "CPackConfig.cmake"
|
|
1094
|
+
if os.path.exists(os.path.join(buildDir, check_file)):
|
|
1095
|
+
use_cpack = True
|
|
1096
|
+
comStr = f"cpack -B {tmpDir} -D CPACK_PACKAGE_FILE_NAME={archiveName} -G TGZ "
|
|
1097
|
+
comStr += '-D CPACK_PACKAGE_NAME="" -D CPACK_PACKAGE_VERSION="" -D CPACK_PACKAGE_VERSION_MAJOR="" '
|
|
1098
|
+
comStr += '-D CPACK_PACKAGE_VERSION_MINOR="" -D CPACK_PACKAGE_VERSION_PATCH="" '
|
|
1099
|
+
comStr += '-D CPACK_PACKAGE_DESCRIPTION="" '
|
|
1100
|
+
|
|
1101
|
+
commands_fail_on_non_zero_exit_status(comStr, EC_Config, verbose_cmd=verbose, verbose_output=verbose, logger=tmpLog, error_log_msg="cpack failed")
|
|
1102
|
+
|
|
1103
|
+
else:
|
|
1104
|
+
use_cpack = False
|
|
1105
|
+
tmpLog.info(f"skip cpack since {check_file} is missing in the build directory")
|
|
1106
|
+
|
|
1107
|
+
archiveName += ".tar"
|
|
1108
|
+
archiveFullName += ".tar"
|
|
1109
|
+
os.chdir(tmpDir)
|
|
1110
|
+
if use_cpack:
|
|
1111
|
+
# recreate tar to allow appending other files in the subsequent steps, as gzip decompress is not enough
|
|
1112
|
+
comStr = "tar xfz {0}.gz; tar cf {0} usr > /dev/null 2>&1; rm -rf usr _CPack_Packages {0}.gz".format(archiveName)
|
|
1113
|
+
else:
|
|
1114
|
+
comStr = f"tar cf {archiveName} -T /dev/null > /dev/null 2>&1"
|
|
1115
|
+
|
|
1116
|
+
commands_fail_on_non_zero_exit_status(comStr, EC_Archive, logger=tmpLog, error_log_msg="tarball creation failed")
|
|
1117
|
+
|
|
1118
|
+
os.chdir(_curdir)
|
|
1119
|
+
return archiveName, archiveFullName
|
|
1120
|
+
|
|
1121
|
+
|
|
1122
|
+
# convert runConfig to outMap
|
|
1123
|
+
def convertConfToOutput(
|
|
1124
|
+
runConfig,
|
|
1125
|
+
extOutFile,
|
|
1126
|
+
original_outDS,
|
|
1127
|
+
destination="",
|
|
1128
|
+
spaceToken="",
|
|
1129
|
+
descriptionInLFN="",
|
|
1130
|
+
allowNoOutput=None,
|
|
1131
|
+
appendFileFieldToStreamName=False,
|
|
1132
|
+
useEXTStreamName=True,
|
|
1133
|
+
extOutStreams=None,
|
|
1134
|
+
):
|
|
1135
|
+
tmpLog = PLogger.getPandaLogger()
|
|
1136
|
+
outMap = {}
|
|
1137
|
+
paramList = []
|
|
1138
|
+
# add IROOT
|
|
1139
|
+
if "IROOT" not in outMap:
|
|
1140
|
+
outMap["IROOT"] = []
|
|
1141
|
+
# remove /
|
|
1142
|
+
outDSwoSlash = re.sub("/$", "", original_outDS)
|
|
1143
|
+
outDsNameBase = outDSwoSlash
|
|
1144
|
+
tmpMatch = re.search(r"^([^\.]+)\.([^\.]+)\.", original_outDS)
|
|
1145
|
+
if tmpMatch is not None and original_outDS.endswith("/"):
|
|
1146
|
+
outDSwoSlash = "{}.{}".format(tmpMatch.group(1), tmpMatch.group(2))
|
|
1147
|
+
if descriptionInLFN != "":
|
|
1148
|
+
outDSwoSlash += descriptionInLFN
|
|
1149
|
+
outDSwoSlash += ".$JEDITASKID"
|
|
1150
|
+
# start conversion
|
|
1151
|
+
if runConfig.output.outNtuple:
|
|
1152
|
+
for sName in runConfig.output.outNtuple:
|
|
1153
|
+
lfn = "{}.{}._${{SN/P}}.root".format(outDSwoSlash, sName)
|
|
1154
|
+
tmpSuffix = "_%s" % sName
|
|
1155
|
+
dataset = outDsNameBase + tmpSuffix + "/"
|
|
1156
|
+
if "ntuple" not in outMap:
|
|
1157
|
+
outMap["ntuple"] = []
|
|
1158
|
+
outMap["ntuple"].append((sName, lfn))
|
|
1159
|
+
paramList += MiscUtils.makeJediJobParam(lfn, dataset, "output", hidden=True, allowNoOutput=allowNoOutput)
|
|
1160
|
+
if runConfig.output.outHist:
|
|
1161
|
+
lfn = "%s.hist._${SN/P}.root" % outDSwoSlash
|
|
1162
|
+
tmpSuffix = "_HIST"
|
|
1163
|
+
dataset = outDsNameBase + tmpSuffix + "/"
|
|
1164
|
+
outMap["hist"] = lfn
|
|
1165
|
+
paramList += MiscUtils.makeJediJobParam(lfn, dataset, "output", hidden=True, allowNoOutput=allowNoOutput)
|
|
1166
|
+
if runConfig.output.outRDO:
|
|
1167
|
+
lfn = "%s.RDO._${SN/P}.pool.root" % outDSwoSlash
|
|
1168
|
+
tmpSuffix = "_RDO"
|
|
1169
|
+
dataset = outDsNameBase + tmpSuffix + "/"
|
|
1170
|
+
outMap["IROOT"].append((runConfig.output.outRDO, lfn))
|
|
1171
|
+
paramList += MiscUtils.makeJediJobParam(lfn, dataset, "output", hidden=True, allowNoOutput=allowNoOutput)
|
|
1172
|
+
if runConfig.output.outESD:
|
|
1173
|
+
lfn = "%s.ESD._${SN/P}.pool.root" % outDSwoSlash
|
|
1174
|
+
tmpSuffix = "_ESD"
|
|
1175
|
+
dataset = outDsNameBase + tmpSuffix + "/"
|
|
1176
|
+
outMap["IROOT"].append((runConfig.output.outESD, lfn))
|
|
1177
|
+
paramList += MiscUtils.makeJediJobParam(lfn, dataset, "output", hidden=True, allowNoOutput=allowNoOutput)
|
|
1178
|
+
if runConfig.output.outAOD:
|
|
1179
|
+
lfn = "%s.AOD._${SN/P}.pool.root" % outDSwoSlash
|
|
1180
|
+
tmpSuffix = "_AOD"
|
|
1181
|
+
dataset = outDsNameBase + tmpSuffix + "/"
|
|
1182
|
+
outMap["IROOT"].append((runConfig.output.outAOD, lfn))
|
|
1183
|
+
paramList += MiscUtils.makeJediJobParam(lfn, dataset, "output", hidden=True, allowNoOutput=allowNoOutput)
|
|
1184
|
+
if runConfig.output.outTAG:
|
|
1185
|
+
lfn = "%s.TAG._${SN/P}.coll.root" % outDSwoSlash
|
|
1186
|
+
tmpSuffix = "_TAG"
|
|
1187
|
+
dataset = outDsNameBase + tmpSuffix + "/"
|
|
1188
|
+
outMap["TAG"] = lfn
|
|
1189
|
+
paramList += MiscUtils.makeJediJobParam(lfn, dataset, "output", hidden=True, allowNoOutput=allowNoOutput)
|
|
1190
|
+
if runConfig.output.outAANT:
|
|
1191
|
+
sNameList = []
|
|
1192
|
+
fsNameMap = {}
|
|
1193
|
+
for aName, sName, fName in runConfig.output.outAANT:
|
|
1194
|
+
# use first sName when multiple streams write to the same file
|
|
1195
|
+
realStreamName = sName
|
|
1196
|
+
if fName in fsNameMap:
|
|
1197
|
+
sName = fsNameMap[fName]
|
|
1198
|
+
else:
|
|
1199
|
+
fsNameMap[fName] = sName
|
|
1200
|
+
lfn = "{}.{}._${{SN/P}}.root".format(outDSwoSlash, sName)
|
|
1201
|
+
tmpSuffix = "_%s" % sName
|
|
1202
|
+
dataset = outDsNameBase + tmpSuffix + "/"
|
|
1203
|
+
if sName not in sNameList:
|
|
1204
|
+
sNameList.append(sName)
|
|
1205
|
+
if "AANT" not in outMap:
|
|
1206
|
+
outMap["AANT"] = []
|
|
1207
|
+
outMap["AANT"].append((aName, realStreamName, lfn))
|
|
1208
|
+
paramList += MiscUtils.makeJediJobParam(lfn, dataset, "output", hidden=True, allowNoOutput=allowNoOutput)
|
|
1209
|
+
if runConfig.output.outTHIST:
|
|
1210
|
+
for sName in runConfig.output.outTHIST:
|
|
1211
|
+
lfn = "{}.{}._${{SN/P}}.root".format(outDSwoSlash, sName)
|
|
1212
|
+
tmpSuffix = "_%s" % sName
|
|
1213
|
+
dataset = outDsNameBase + tmpSuffix + "/"
|
|
1214
|
+
if "THIST" not in outMap:
|
|
1215
|
+
outMap["THIST"] = []
|
|
1216
|
+
outMap["THIST"].append((sName, lfn))
|
|
1217
|
+
paramList += MiscUtils.makeJediJobParam(lfn, dataset, "output", hidden=True, allowNoOutput=allowNoOutput)
|
|
1218
|
+
if runConfig.output.outIROOT:
|
|
1219
|
+
for sIndex, sName in enumerate(runConfig.output.outIROOT):
|
|
1220
|
+
lfn = "{}.iROOT{}._${{SN/P}}.{}".format(outDSwoSlash, sIndex, sName)
|
|
1221
|
+
tmpSuffix = "_iROOT%s" % sIndex
|
|
1222
|
+
dataset = outDsNameBase + tmpSuffix + "/"
|
|
1223
|
+
outMap["IROOT"].append((sName, lfn))
|
|
1224
|
+
paramList += MiscUtils.makeJediJobParam(lfn, dataset, "output", hidden=True, allowNoOutput=allowNoOutput)
|
|
1225
|
+
if extOutFile:
|
|
1226
|
+
if extOutStreams is not None:
|
|
1227
|
+
if len(extOutStreams) != len(extOutFile):
|
|
1228
|
+
tmpLog.error("Missmatched --outputStreamNames (%s) to ext output files (%s)" % extOutStreams, extOutFile)
|
|
1229
|
+
sys.exit(EC_Config)
|
|
1230
|
+
if len(extOutStreams) != len(set(extOutStreams)):
|
|
1231
|
+
tmpLog.error("All output stream names indicated with --outputStreamNames (%s) must be different" % extOutStreams)
|
|
1232
|
+
sys.exit(EC_Config)
|
|
1233
|
+
streams = []
|
|
1234
|
+
for sIndex, sName in enumerate(extOutFile):
|
|
1235
|
+
# change * to X and add .tgz
|
|
1236
|
+
origSName = sName
|
|
1237
|
+
if sName.find("*") != -1:
|
|
1238
|
+
sName = sName.replace("*", "XYZ")
|
|
1239
|
+
sName = "%s.tgz" % sName
|
|
1240
|
+
tmpStreamName = (
|
|
1241
|
+
getExtendedExtStreamName(sIndex, sName, appendFileFieldToStreamName, useEXTStreamName) if extOutStreams is None else extOutStreams[sIndex]
|
|
1242
|
+
)
|
|
1243
|
+
streams.append(tmpStreamName)
|
|
1244
|
+
lfn = "{}.{}._${{SN/P}}.{}".format(outDSwoSlash, tmpStreamName, sName)
|
|
1245
|
+
tmpSuffix = "_%s" % tmpStreamName
|
|
1246
|
+
dataset = outDsNameBase + tmpSuffix + "/"
|
|
1247
|
+
outMap["IROOT"].append((origSName, lfn))
|
|
1248
|
+
paramList += MiscUtils.makeJediJobParam(lfn, dataset, "output", hidden=True, allowNoOutput=allowNoOutput)
|
|
1249
|
+
if len(streams) != len(set(streams)):
|
|
1250
|
+
tmpLog.error("All output stream names taken from the %OUT declarations (e.g. %OUT.streamname.root) and --extOutFile must be different")
|
|
1251
|
+
sys.exit(EC_Config)
|
|
1252
|
+
if runConfig.output.outTAGX:
|
|
1253
|
+
for sName, oName in runConfig.output.outTAGX:
|
|
1254
|
+
lfn = "{}.{}._${{SN/P}}.{}".format(outDSwoSlash, sName, oName)
|
|
1255
|
+
tmpSuffix = "_%s" % sName
|
|
1256
|
+
dataset = outDsNameBase + tmpSuffix + "/"
|
|
1257
|
+
if "IROOT" not in outMap:
|
|
1258
|
+
outMap["IROOT"] = []
|
|
1259
|
+
outMap["IROOT"].append((oName, lfn))
|
|
1260
|
+
paramList += MiscUtils.makeJediJobParam(lfn, dataset, "output", hidden=True, allowNoOutput=allowNoOutput)
|
|
1261
|
+
if runConfig.output.outStream1:
|
|
1262
|
+
lfn = "%s.Stream1._${SN/P}.pool.root" % outDSwoSlash
|
|
1263
|
+
tmpSuffix = "_Stream1"
|
|
1264
|
+
dataset = outDsNameBase + tmpSuffix + "/"
|
|
1265
|
+
outMap["IROOT"].append((runConfig.output.outStream1, lfn))
|
|
1266
|
+
paramList += MiscUtils.makeJediJobParam(lfn, dataset, "output", hidden=True, allowNoOutput=allowNoOutput)
|
|
1267
|
+
if runConfig.output.outStream2:
|
|
1268
|
+
lfn = "%s.Stream2._${SN/P}.pool.root" % outDSwoSlash
|
|
1269
|
+
tmpSuffix = "_Stream2"
|
|
1270
|
+
dataset = outDsNameBase + tmpSuffix + "/"
|
|
1271
|
+
outMap["IROOT"].append((runConfig.output.outStream2, lfn))
|
|
1272
|
+
paramList += MiscUtils.makeJediJobParam(lfn, dataset, "output", hidden=True, allowNoOutput=allowNoOutput)
|
|
1273
|
+
if runConfig.output.outBS:
|
|
1274
|
+
lfn = "%s.BS._${SN/P}.data" % outDSwoSlash
|
|
1275
|
+
tmpSuffix = "_BS"
|
|
1276
|
+
dataset = outDsNameBase + tmpSuffix + "/"
|
|
1277
|
+
outMap["BS"] = lfn
|
|
1278
|
+
paramList += MiscUtils.makeJediJobParam(lfn, dataset, "output", hidden=True, allowNoOutput=allowNoOutput)
|
|
1279
|
+
if runConfig.output.outSelBS:
|
|
1280
|
+
lfn = "{}.{}._${{SN/P}}.data".format(outDSwoSlash, runConfig.output.outSelBS)
|
|
1281
|
+
tmpSuffix = "_SelBS"
|
|
1282
|
+
dataset = outDsNameBase + tmpSuffix + "/"
|
|
1283
|
+
if "IROOT" not in outMap:
|
|
1284
|
+
outMap["IROOT"] = []
|
|
1285
|
+
outMap["IROOT"].append(("%s.*.data" % runConfig.output.outSelBS, lfn))
|
|
1286
|
+
paramList += MiscUtils.makeJediJobParam(lfn, dataset, "output", hidden=True, allowNoOutput=allowNoOutput)
|
|
1287
|
+
if runConfig.output.outStreamG:
|
|
1288
|
+
for sName, sOrigFileName in runConfig.output.outStreamG:
|
|
1289
|
+
lfn = "{}.{}._${{SN/P}}.pool.root".format(outDSwoSlash, sName)
|
|
1290
|
+
tmpSuffix = "_%s" % sName
|
|
1291
|
+
dataset = outDsNameBase + tmpSuffix + "/"
|
|
1292
|
+
outMap["IROOT"].append((sOrigFileName, lfn))
|
|
1293
|
+
paramList += MiscUtils.makeJediJobParam(lfn, dataset, "output", hidden=True, allowNoOutput=allowNoOutput)
|
|
1294
|
+
if runConfig.output.outMeta:
|
|
1295
|
+
iMeta = 0
|
|
1296
|
+
for sName, sAsso in runConfig.output.outMeta:
|
|
1297
|
+
foundLFN = ""
|
|
1298
|
+
if sAsso == "None":
|
|
1299
|
+
# non-associated metadata
|
|
1300
|
+
lfn = "{}.META{}._${{SN/P}}.root".format(outDSwoSlash, iMeta)
|
|
1301
|
+
tmpSuffix = "_META%s" % iMeta
|
|
1302
|
+
dataset = outDsNameBase + tmpSuffix + "/"
|
|
1303
|
+
paramList += MiscUtils.makeJediJobParam(lfn, dataset, "output", hidden=True, allowNoOutput=allowNoOutput)
|
|
1304
|
+
iMeta += 1
|
|
1305
|
+
foundLFN = lfn
|
|
1306
|
+
elif sAsso in outMap:
|
|
1307
|
+
# Stream1,2
|
|
1308
|
+
foundLFN = outMap[sAsso]
|
|
1309
|
+
elif sAsso in ["StreamESD", "StreamAOD"]:
|
|
1310
|
+
# ESD,AOD
|
|
1311
|
+
stKey = re.sub("^Stream", "", sAsso)
|
|
1312
|
+
if stKey in outMap:
|
|
1313
|
+
foundLFN = outMap[stKey]
|
|
1314
|
+
else:
|
|
1315
|
+
# check StreamG when ESD/AOD are not defined as algorithms
|
|
1316
|
+
if "StreamG" in outMap:
|
|
1317
|
+
for tmpStName, tmpLFN in outMap["StreamG"]:
|
|
1318
|
+
if tmpStName == sAsso:
|
|
1319
|
+
foundLFN = tmpLFN
|
|
1320
|
+
elif sAsso == "StreamRDO" and "StreamRDO" in outMap:
|
|
1321
|
+
# RDO
|
|
1322
|
+
stKey = re.sub("^Stream", "", sAsso)
|
|
1323
|
+
if stKey in outMap:
|
|
1324
|
+
foundLFN = outMap[stKey]
|
|
1325
|
+
else:
|
|
1326
|
+
# general stream
|
|
1327
|
+
if "StreamG" in outMap:
|
|
1328
|
+
for tmpStName, tmpLFN in outMap["StreamG"]:
|
|
1329
|
+
if tmpStName == sAsso:
|
|
1330
|
+
foundLFN = tmpLFN
|
|
1331
|
+
if foundLFN != "":
|
|
1332
|
+
if "Meta" not in outMap:
|
|
1333
|
+
outMap["Meta"] = []
|
|
1334
|
+
outMap["Meta"].append((sName, foundLFN))
|
|
1335
|
+
if runConfig.output.outMS:
|
|
1336
|
+
for sName, sAsso in runConfig.output.outMS:
|
|
1337
|
+
lfn = "{}.{}._${{SN/P}}.pool.root".format(outDSwoSlash, sName)
|
|
1338
|
+
tmpSuffix = "_%s" % sName
|
|
1339
|
+
dataset = outDsNameBase + tmpSuffix + "/"
|
|
1340
|
+
if "IROOT" not in outMap:
|
|
1341
|
+
outMap["IROOT"] = []
|
|
1342
|
+
outMap["IROOT"].append((sAsso, lfn))
|
|
1343
|
+
paramList += MiscUtils.makeJediJobParam(lfn, dataset, "output", hidden=True, allowNoOutput=allowNoOutput)
|
|
1344
|
+
if runConfig.output.outUserData:
|
|
1345
|
+
for sAsso in runConfig.output.outUserData:
|
|
1346
|
+
# look for associated LFN
|
|
1347
|
+
foundLFN = ""
|
|
1348
|
+
if sAsso in outMap:
|
|
1349
|
+
# Stream1,2
|
|
1350
|
+
foundLFN = outMap[sAsso]
|
|
1351
|
+
elif sAsso in ["StreamRDO", "StreamESD", "StreamAOD"]:
|
|
1352
|
+
# RDO,ESD,AOD
|
|
1353
|
+
stKey = re.sub("^Stream", "", sAsso)
|
|
1354
|
+
if stKey in outMap:
|
|
1355
|
+
foundLFN = outMap[stKey]
|
|
1356
|
+
else:
|
|
1357
|
+
# general stream
|
|
1358
|
+
if "StreamG" in outMap:
|
|
1359
|
+
for tmpStName, tmpLFN in outMap["StreamG"]:
|
|
1360
|
+
if tmpStName == sAsso:
|
|
1361
|
+
foundLFN = tmpLFN
|
|
1362
|
+
if foundLFN != "":
|
|
1363
|
+
if "UserData" not in outMap:
|
|
1364
|
+
outMap["UserData"] = []
|
|
1365
|
+
outMap["UserData"].append(foundLFN)
|
|
1366
|
+
# remove IROOT if unnecessary
|
|
1367
|
+
if "IROOT" in outMap:
|
|
1368
|
+
if outMap["IROOT"] == []:
|
|
1369
|
+
del outMap["IROOT"]
|
|
1370
|
+
else:
|
|
1371
|
+
# check invalid characters
|
|
1372
|
+
for stream, lfn in outMap["IROOT"]:
|
|
1373
|
+
checked = check_invalid_char(stream, is_file=True)
|
|
1374
|
+
if checked is not None:
|
|
1375
|
+
tmp_log = PLogger.getPandaLogger()
|
|
1376
|
+
tmp_log.error('Invalid character "{}" used in output filename {}'.format(checked, stream))
|
|
1377
|
+
sys.exit(EC_Config)
|
|
1378
|
+
|
|
1379
|
+
# set destination
|
|
1380
|
+
if destination != "":
|
|
1381
|
+
for tmpParam in paramList:
|
|
1382
|
+
tmpParam["destination"] = destination
|
|
1383
|
+
# set token
|
|
1384
|
+
if spaceToken != "":
|
|
1385
|
+
for tmpParam in paramList:
|
|
1386
|
+
tmpParam["token"] = spaceToken
|
|
1387
|
+
# return
|
|
1388
|
+
return outMap, paramList
|
|
1389
|
+
|
|
1390
|
+
|
|
1391
|
+
# get CMTCONFIG + IMG
|
|
1392
|
+
def getCmtConfigImg(athenaVer=None, cacheVer=None, nightVer=None, cmtConfig=None, verbose=False, architecture=None):
|
|
1393
|
+
# check if json
|
|
1394
|
+
is_json = False
|
|
1395
|
+
if architecture and "{" in architecture:
|
|
1396
|
+
try:
|
|
1397
|
+
architecture = json.loads(architecture)
|
|
1398
|
+
is_json = True
|
|
1399
|
+
except Exception as e:
|
|
1400
|
+
tmp_log = PLogger.getPandaLogger()
|
|
1401
|
+
tmp_log.error("failed to parse architecture {} : {}".format(architecture, e))
|
|
1402
|
+
sys.exit(EC_Config)
|
|
1403
|
+
# get CMTCONFIG
|
|
1404
|
+
cmt_config = ""
|
|
1405
|
+
spec_str = ""
|
|
1406
|
+
if architecture and not is_json:
|
|
1407
|
+
tmp_m = re.search("^[^@&#]+", architecture)
|
|
1408
|
+
if tmp_m:
|
|
1409
|
+
cmt_config = tmp_m.group(0)
|
|
1410
|
+
spec_str = architecture.replace(cmt_config, "")
|
|
1411
|
+
else:
|
|
1412
|
+
tmp_m = re.search("[@&#].+$", architecture)
|
|
1413
|
+
if tmp_m:
|
|
1414
|
+
spec_str = tmp_m.group(0)
|
|
1415
|
+
if not cmt_config:
|
|
1416
|
+
cmt_config = getCmtConfig(athenaVer, cacheVer, nightVer, cmtConfig, verbose)
|
|
1417
|
+
if is_json and cmt_config and "sw_platform" not in architecture:
|
|
1418
|
+
architecture["sw_platform"] = cmt_config
|
|
1419
|
+
# get base platform + HW specs
|
|
1420
|
+
if spec_str:
|
|
1421
|
+
pass
|
|
1422
|
+
elif "ALRB_USER_PLATFORM" in os.environ:
|
|
1423
|
+
# base platform + HW specs from ALRB
|
|
1424
|
+
spec_str = "@" + os.environ["ALRB_USER_PLATFORM"]
|
|
1425
|
+
if is_json and "cpu_specs" not in architecture and "gpu_spec" not in architecture:
|
|
1426
|
+
architecture["encoded_platform"] = os.environ["ALRB_USER_PLATFORM"]
|
|
1427
|
+
else:
|
|
1428
|
+
# architecture w/o base platform or even empty architecture
|
|
1429
|
+
spec_str = architecture
|
|
1430
|
+
# append base platform + HW specs if any
|
|
1431
|
+
if spec_str and not is_json:
|
|
1432
|
+
if cmt_config is None:
|
|
1433
|
+
cmt_config = ""
|
|
1434
|
+
cmt_config = cmt_config + spec_str
|
|
1435
|
+
if is_json:
|
|
1436
|
+
return json.dumps(architecture)
|
|
1437
|
+
return cmt_config
|
|
1438
|
+
|
|
1439
|
+
|
|
1440
|
+
# get CMTCONFIG
|
|
1441
|
+
def getCmtConfig(athenaVer=None, cacheVer=None, nightVer=None, cmtConfig=None, verbose=False):
|
|
1442
|
+
# use user-specified cmtconfig
|
|
1443
|
+
if cmtConfig:
|
|
1444
|
+
return cmtConfig
|
|
1445
|
+
# local settting
|
|
1446
|
+
if "CMTCONFIG" in os.environ:
|
|
1447
|
+
return os.environ["CMTCONFIG"]
|
|
1448
|
+
# undefined in Athena
|
|
1449
|
+
if athenaVer or cacheVer:
|
|
1450
|
+
# get logger
|
|
1451
|
+
tmpLog = PLogger.getPandaLogger()
|
|
1452
|
+
tmpLog.error("environment variable CMTCONFIG is undefined. Please set --cmtConfig")
|
|
1453
|
+
sys.exit(EC_Config)
|
|
1454
|
+
return None
|
|
1455
|
+
|
|
1456
|
+
|
|
1457
|
+
# check CMTCONFIG
|
|
1458
|
+
def checkCmtConfig(localCmtConfig, userCmtConfig, noBuild):
|
|
1459
|
+
# didn't specify CMTCONFIG
|
|
1460
|
+
if userCmtConfig in ["", None]:
|
|
1461
|
+
return True
|
|
1462
|
+
# CVMFS version format
|
|
1463
|
+
if re.search(r"-gcc\d+\.\d+$", userCmtConfig) is not None:
|
|
1464
|
+
return True
|
|
1465
|
+
# get logger
|
|
1466
|
+
tmpLog = PLogger.getPandaLogger()
|
|
1467
|
+
# CMTCONFIG is undefined locally
|
|
1468
|
+
if localCmtConfig in ["", None]:
|
|
1469
|
+
return True
|
|
1470
|
+
# user-specified CMTCONFIG is inconsitent with local CMTCONFIG
|
|
1471
|
+
if userCmtConfig != localCmtConfig and noBuild:
|
|
1472
|
+
errStr = "You cannot use --noBuild when --cmtConfig={} is inconsistent with local CMTCONFIG={} ".format(userCmtConfig, localCmtConfig)
|
|
1473
|
+
errStr += "since you need re-compile source files on remote worker-node. Please remove --noBuild"
|
|
1474
|
+
tmpLog.error(errStr)
|
|
1475
|
+
return False
|
|
1476
|
+
# return OK
|
|
1477
|
+
return True
|
|
1478
|
+
|
|
1479
|
+
|
|
1480
|
+
# use AMI for AutoConf
|
|
1481
|
+
def getJobOtoUseAmiForAutoConf(inDS, tmpDir):
|
|
1482
|
+
# no input
|
|
1483
|
+
if inDS == "":
|
|
1484
|
+
return ""
|
|
1485
|
+
# use first one
|
|
1486
|
+
amiURL = "ami://%s" % inDS.split(",")[0]
|
|
1487
|
+
# remove /
|
|
1488
|
+
if amiURL.endswith("/"):
|
|
1489
|
+
amiURL = amiURL[:-1]
|
|
1490
|
+
inputFiles = [amiURL]
|
|
1491
|
+
# create jobO fragment
|
|
1492
|
+
optFileName = tmpDir + "/" + MiscUtils.wrappedUuidGen() + ".py"
|
|
1493
|
+
oFile = open(optFileName, "w")
|
|
1494
|
+
oFile.write(
|
|
1495
|
+
"""
|
|
1496
|
+
try:
|
|
1497
|
+
import AthenaCommon.AthenaCommonFlags
|
|
1498
|
+
|
|
1499
|
+
def _dummyFilesInput(*argv):
|
|
1500
|
+
return %s
|
|
1501
|
+
|
|
1502
|
+
AthenaCommon.AthenaCommonFlags.FilesInput.__call__ = _dummyFilesInput
|
|
1503
|
+
except Exception:
|
|
1504
|
+
pass
|
|
1505
|
+
|
|
1506
|
+
try:
|
|
1507
|
+
import AthenaCommon.AthenaCommonFlags
|
|
1508
|
+
|
|
1509
|
+
def _dummyGet_Value(*argv):
|
|
1510
|
+
return %s
|
|
1511
|
+
|
|
1512
|
+
for tmpAttr in dir (AthenaCommon.AthenaCommonFlags):
|
|
1513
|
+
import re
|
|
1514
|
+
if re.search('^(Pool|BS).*Input$',tmpAttr) is not None:
|
|
1515
|
+
try:
|
|
1516
|
+
getattr(AthenaCommon.AthenaCommonFlags,tmpAttr).get_Value = _dummyGet_Value
|
|
1517
|
+
except Exception:
|
|
1518
|
+
pass
|
|
1519
|
+
except Exception:
|
|
1520
|
+
pass
|
|
1521
|
+
"""
|
|
1522
|
+
% (inputFiles, inputFiles)
|
|
1523
|
+
)
|
|
1524
|
+
oFile.close()
|
|
1525
|
+
# return file name
|
|
1526
|
+
return optFileName
|
|
1527
|
+
|
|
1528
|
+
|
|
1529
|
+
# use CMake
|
|
1530
|
+
def useCMake():
|
|
1531
|
+
return "CMAKE_PREFIX_PATH" in os.environ
|
|
1532
|
+
|
|
1533
|
+
|
|
1534
|
+
# parse athenaTag
|
|
1535
|
+
def parse_athena_tag(athena_tag, verbose, tmp_log):
|
|
1536
|
+
athenaVer = ""
|
|
1537
|
+
cacheVer = ""
|
|
1538
|
+
nightVer = ""
|
|
1539
|
+
# loop over all tags
|
|
1540
|
+
items = athena_tag.split(",")
|
|
1541
|
+
usingNightlies = False
|
|
1542
|
+
for item in items:
|
|
1543
|
+
# releases
|
|
1544
|
+
match = re.search(r"^(\d+\.\d+\.\d+)", item)
|
|
1545
|
+
if match:
|
|
1546
|
+
athenaVer = "Atlas-%s" % match.group(1)
|
|
1547
|
+
# cache
|
|
1548
|
+
cmatch = re.search(r"^(\d+\.\d+\.\d+\.\d+\.*\d*)$", item)
|
|
1549
|
+
if cmatch is not None:
|
|
1550
|
+
cacheVer += "_%s" % cmatch.group(1)
|
|
1551
|
+
else:
|
|
1552
|
+
cacheVer += "_%s" % match.group(1)
|
|
1553
|
+
continue
|
|
1554
|
+
# nightlies
|
|
1555
|
+
match = re.search(r"^(\d+\.\d+\.X|\d+\.X\.\d+)$", item)
|
|
1556
|
+
if match:
|
|
1557
|
+
athenaVer = "Atlas-%s" % match.group(1)
|
|
1558
|
+
continue
|
|
1559
|
+
# master or XX.YY
|
|
1560
|
+
match = re.search(r"^\d+\.\d+$", item)
|
|
1561
|
+
if item.startswith("master") or match or item == "main":
|
|
1562
|
+
athenaVer = "Atlas-%s" % item
|
|
1563
|
+
continue
|
|
1564
|
+
# old nightlies
|
|
1565
|
+
if item.startswith("rel_"):
|
|
1566
|
+
usingNightlies = True
|
|
1567
|
+
if "dev" in items:
|
|
1568
|
+
athenaVer = "Atlas-dev"
|
|
1569
|
+
elif "devval" in items:
|
|
1570
|
+
athenaVer = "Atlas-devval"
|
|
1571
|
+
cacheVer = "-AtlasOffline_%s" % item
|
|
1572
|
+
continue
|
|
1573
|
+
# nightlies
|
|
1574
|
+
if item in ["latest", "r27"] or re.search(r"^\d{4}-\d{2}-\d{2}T\d{4}$", item):
|
|
1575
|
+
cacheVer += "_%s" % item
|
|
1576
|
+
continue
|
|
1577
|
+
# CMTCONFIG
|
|
1578
|
+
if item in ["32", "64"]:
|
|
1579
|
+
tmp_log.error("%s in --athenaTag is unsupported. Please use --cmtConfig instead" % item)
|
|
1580
|
+
sys.exit(EC_Config)
|
|
1581
|
+
# ignoring AtlasOffline
|
|
1582
|
+
if item in ["AtlasOffline"]:
|
|
1583
|
+
continue
|
|
1584
|
+
# regarded as project
|
|
1585
|
+
cacheVer = "-" + item + cacheVer
|
|
1586
|
+
# check cache
|
|
1587
|
+
if re.search(r"^-.+_.+$", cacheVer) is None:
|
|
1588
|
+
if re.search(r"^_\d+\.\d+\.\d+\.\d+$", cacheVer) is not None:
|
|
1589
|
+
# use AtlasProduction
|
|
1590
|
+
cacheVer = "-AtlasProduction" + cacheVer
|
|
1591
|
+
elif "AthAnalysisBase" in cacheVer or "AthAnalysis" in cacheVer:
|
|
1592
|
+
# AthAnalysis
|
|
1593
|
+
cacheVer = cacheVer + "_%s" % athenaVer
|
|
1594
|
+
athenaVer = ""
|
|
1595
|
+
else:
|
|
1596
|
+
# unknown
|
|
1597
|
+
cacheVer = ""
|
|
1598
|
+
# use dev nightlies
|
|
1599
|
+
if usingNightlies and athenaVer == "":
|
|
1600
|
+
athenaVer = "Atlas-dev"
|
|
1601
|
+
return athenaVer, cacheVer, nightVer
|