1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
|
from builtins import range
import os
import re
import sys
import shutil
import importlib
import sqlalchemy
import subprocess
import CondCore.Utilities.conddblib as conddb
from functools import reduce
def create_single_iov_db(inputs, run_number, output_db):
"""Create an sqlite file with single-IOV tags for alignment payloads.
Arguments:
- `inputs`: dictionary with input needed for payload extraction
- `run_number`: run for which the IOVs are selected
- `output_db`: name of the output sqlite file
"""
# find the IOV containing `run_number`
for record,tag in inputs.items():
run_is_covered = False
for iov in reversed(tag["iovs"]):
if iov <= run_number:
tag["since"] = str(iov)
run_is_covered = True
break
if not run_is_covered:
msg = ("Run number {0:d} is not covered in '{1:s}' ({2:s}) from"
" '{3:s}'.".format(run_number, tag["tag"], record,
global_tag))
print(msg)
print("Aborting...")
sys.exit(1)
result = {}
remove_existing_object(output_db)
for record,tag in inputs.items():
result[record] = {"connect": "sqlite_file:"+output_db,
"tag": "_".join([tag["tag"], tag["since"]])}
if tag["connect"] == "pro":
source_connect = "frontier://FrontierProd/CMS_CONDITIONS"
elif tag["connect"] == "dev":
source_connect = "frontier://FrontierPrep/CMS_CONDITIONS"
else:
source_connect = tag["connect"]
cmd = ("conddb_import",
"-f", source_connect,
"-c", result[record]["connect"],
"-i", tag["tag"],
"-t", result[record]["tag"],
"-b", str(run_number),
"-e", str(run_number))
run_checked(cmd)
if len(inputs) > 0:
run_checked(["sqlite3", output_db, "update iov set since=1"])
return result
def run_checked(cmd, suppress_stderr = False):
"""Run `cmd` and exit in case of failures.
Arguments:
- `cmd`: list containing the strings of the command
- `suppress_stderr`: suppress output from stderr
"""
try:
with open(os.devnull, "w") as devnull:
if suppress_stderr:
subprocess.check_call(cmd, stdout = devnull, stderr = devnull)
else:
subprocess.check_call(cmd, stdout = devnull)
except subprocess.CalledProcessError as e:
print("Problem in running the following command:")
print(" ".join(e.cmd))
sys.exit(1)
def get_process_object(cfg):
"""Returns cms.Process object defined in `cfg`.
Arguments:
- `cfg`: path to CMSSW config file
"""
sys.path.append(os.path.dirname(cfg)) # add location to python path
cache_stdout = sys.stdout
sys.stdout = open(os.devnull, "w") # suppress unwanted output
try:
__configuration = \
importlib.import_module(os.path.splitext(os.path.basename(cfg))[0])
except Exception as e:
print("Problem detected in configuration file '{0}'.".format(cfg))
raise e
sys.stdout = cache_stdout
sys.path.pop() # clean up python path again
try:
os.remove(cfg+"c") # try to remove temporary .pyc file
except OSError as e:
if e.args == (2, "No such file or directory"): pass
else: raise
return __configuration.process
def make_unique_runranges(ali_producer):
"""Derive unique run ranges from AlignmentProducer PSet.
Arguments:
- `ali_producer`: cms.PSet containing AlignmentProducer configuration
"""
if (hasattr(ali_producer, "RunRangeSelection") and
len(ali_producer.RunRangeSelection) > 0):
iovs = set([int(iov)
for sel in ali_producer.RunRangeSelection
for iov in sel.RunRanges])
if len(iovs) == 0: return [1] # single IOV starting from run 1
return sorted(iovs)
else:
return [1] # single IOV starting from run 1
def get_tags(global_tag, records):
"""Get tags for `records` contained in `global_tag`.
Arguments:
- `global_tag`: global tag of interest
- `records`: database records of interest
"""
if len(records) == 0: return {} # avoid useless DB query
# check for auto GT
if global_tag.startswith("auto:"):
import Configuration.AlCa.autoCond as AC
try:
global_tag = AC.autoCond[global_tag.split("auto:")[-1]]
except KeyError:
print("Unsupported auto GT:", global_tag)
sys.exit(1)
# setting up the DB session
con = conddb.connect(url = conddb.make_url())
session = con.session()
GlobalTagMap = session.get_dbtype(conddb.GlobalTagMap)
# query tag names for records of interest contained in `global_tag`
tags = session.query(GlobalTagMap.record, GlobalTagMap.tag_name).\
filter(GlobalTagMap.global_tag_name == global_tag,
GlobalTagMap.record.in_(records)).all()
# closing the DB session
session.close()
return {item[0]: {"tag": item[1], "connect": "pro"} for item in tags}
def get_iovs(db, tag):
"""Retrieve the list of IOVs from `db` for `tag`.
Arguments:
- `db`: database connection string
- `tag`: tag of database record
"""
db = db.replace("sqlite_file:", "").replace("sqlite:", "")
db = db.replace("frontier://FrontierProd/CMS_CONDITIONS", "pro")
db = db.replace("frontier://FrontierPrep/CMS_CONDITIONS", "dev")
con = conddb.connect(url = conddb.make_url(db))
session = con.session()
IOV = session.get_dbtype(conddb.IOV)
iovs = set(session.query(IOV.since).filter(IOV.tag_name == tag).all())
if len(iovs) == 0:
print("No IOVs found for tag '"+tag+"' in database '"+db+"'.")
sys.exit(1)
session.close()
return sorted([int(item[0]) for item in iovs])
def replace_factors(product_string, name, value):
"""Takes a `product_string` and replaces all factors with `name` by `value`.
Arguments:
- `product_string`: input string containing a product
- `name`: name of the factor
- `value`: value of the factor
"""
value = str(value) # ensure it's a string
return re.sub(r"^"+name+r"$", value, # single factor
re.sub(r"[*]"+name+r"$", r"*"+value, # rhs
re.sub(r"^"+name+r"[*]", value+r"*", # lhs
re.sub(r"[*]"+name+r"[*]", r"*"+value+r"*",
product_string))))
def compute_product_string(product_string):
"""Takes `product_string` and returns the product of the factors as string.
Arguments:
- `product_string`: string containing product ('<factor>*<factor>*...')
"""
factors = [float(f) for f in product_string.split("*")]
return str(reduce(lambda x,y: x*y, factors))
def check_proxy():
"""Check if GRID proxy has been initialized."""
try:
with open(os.devnull, "w") as dump:
subprocess.check_call(["voms-proxy-info", "--exists"],
stdout = dump, stderr = dump)
except subprocess.CalledProcessError:
return False
return True
def remove_existing_object(path):
"""
Tries to remove file or directory located at `path`. If the user
has no delete permissions, the object is moved to a backup
file. If this fails it tries 5 times in total and then asks to
perform a cleanup by a user with delete permissions.
Arguments:
- `name`: name of the object to be (re)moved
"""
if os.path.exists(path):
remove_method = shutil.rmtree if os.path.isdir(path) else os.remove
move_method = shutil.move if os.path.isdir(path) else os.rename
try:
remove_method(path)
except OSError as e:
if e.args != (13, "Permission denied"): raise
backup_path = path.rstrip("/")+"~"
for _ in range(5):
try:
if os.path.exists(backup_path): remove_method(backup_path)
move_method(path, backup_path)
break
except OSError as e:
if e.args != (13, "Permission denied"): raise
backup_path += "~"
if os.path.exists(path):
msg = ("Cannot remove '{}' due to missing 'delete' ".format(path)
+"permissions and the limit of 5 backups is reached. Please "
"ask a user with 'delete' permissions to clean up.")
print(msg)
sys.exit(1)
|