10 from fnmatch
import fnmatch
11 from concurrent.futures
import ThreadPoolExecutor
12 from collections
import defaultdict
13 from basf2
import B2INFO, B2ERROR, B2WARNING, LogPythonInterface
15 from terminal_utils
import Pager
16 from conditions_db
import set_cdb_authentication_token
22 def get_all_iovsets(existing_payloads, run_range=None):
23 """Given a list of PayloadInformation objects, return a reduced list PayloadInformation
24 objects with the single iovs replaced with IoVSets. Payloads with the same
25 name and revision will be merged.
27 Overlaps will raise an B2ERROR
29 all_payloads = defaultdict(
lambda: IoVSet(allow_overlaps=
True))
30 by_name = defaultdict(
lambda: IoVSet(allow_overlaps=
False))
32 for payload
in existing_payloads:
34 iov = IntervalOfValidity(payload.iov)
36 if run_range
is not None:
42 all_payloads[payload.name, payload.revision].add(iov)
44 infos[payload.name, payload.revision] = payload
48 by_name[payload.name].add(iov)
49 except ValueError
as e:
50 B2ERROR(f
"Overlap for payload {payload.name} r{payload.revision}: {e}")
54 for (name, revision), iov
in all_payloads.items():
55 info = infos[name, revision]
63 def create_iov_wrapper(db, globaltag_id, payload):
65 Wrapper function for adding payloads into a given globaltag.
67 for iov
in payload.iov:
68 if db.create_iov(globaltag_id, payload.payload_id, *iov.tuple)
is None:
69 raise RuntimeError(f
"Cannot create iov for {payload.name} r{payload.revision}")
72 def command_tag_merge(args, db=None):
74 Merge a list of globaltags in the order they are given.
76 This command allows to merge a number of globaltags into a single globaltag.
77 Payloads from later globaltags in the list of arguments are used to fill gaps
78 present in earlier globaltags.
80 The result is equivalent to having multiple globaltags setup in the conditions
81 access for basf2 (highest priority goes first).
84 The order of the globaltags is highest priority first, so payloads from
85 globaltags earlier on the command line will be taken with before globaltags
88 This command requires that all globaltags are overlap free.
90 For each globaltag in the list we copy all payloads to the output globaltag
91 if there is no payload of that name valid for the given interval of validity
92 in any previous globaltags in the list.
94 If the payload overlaps partially with a payload from a previous globaltag
95 in the list the interval of validity is shortened (and possibly split) to
96 not overlap but to just fill the gaps.
100 globaltag A contains ::
102 payload1, rev 2, valid from 1,0 to 1,10
103 payload1, rev 3, valid from 1,20 to 1,22
104 payload2, rev 1, valid from 1,0 to 1,-1
106 globaltag B contains ::
108 payload1, rev 1, valid from 1,1 to 1,30
109 payload2, rev 2, valid from 0,1 to 1,20
111 Then running ``b2conditionsdb tag merge -o output A B``, the output globaltag
112 after the merge will contain::
114 payload1, rev 2, valid from 1,0 to 1,10
115 payload1, rev 1, valid from 1,11 to 1,19
116 payload1, rev 3, valid from 1,20 to 1,22
117 payload1, rev 1, valid from 1,23 to 1,30
118 payload2, rev 2, valid from 0,1 to 0,-1
119 payload2, rev 1, valid from 1,0 to 1,-1
121 When finished, this command will print a table of payloads and their
122 validity and from which globaltag they were taken. If ``--dry-run`` is given
123 it will only print the list of payloads.
125 Optionally one can specify ``--run-range`` to limit the run range for which
126 the merging should take place. In the example above, running with
127 ``--run-range 1 0 1 21`` the result would be ::
129 payload1, rev 2, valid from 1,0 to 1,10
130 payload1, rev 1, valid from 1,11 to 1,19
131 payload1, rev 3, valid from 1,20 to 1,21
132 payload2, rev 1, valid from 1,0 to 1,21
134 .. versionadded:: release-05-01-00
138 args.add_argument(
"globaltag", nargs=
"+", help=
"name of the globaltag")
139 group = args.add_argument_group(
"required named arguments")
140 group.add_argument(
"-o",
"--output", required=
True, help=
"Name of the output globaltag")
141 args.add_argument(
"--dry-run", help=
"Don't do anything, just print a table with the results",
142 action=
"store_true", default=
False)
143 args.add_argument(
"--run-range", nargs=4, default=
None, type=int,
144 metavar=(
"FIRST_EXP",
"FIRST_RUN",
"FINAL_EXP",
"FINAL_RUN"),
145 help=
"Can be for numbers to limit the run range to put"
146 "in the output globaltag: All iovs will be limited to "
148 args.add_argument(
"-j", type=int, default=10, dest=
"nprocess",
149 help=
"Number of concurrent threads to use for "
150 "creating payloads into the output globaltag.")
154 set_cdb_authentication_token(db, args.auth_token)
157 support_color = LogPythonInterface.terminal_supports_colors()
159 colors =
"\x1b[32m \x1b[34m \x1b[35m \x1b[31m".split()
160 colors = {tag: color
for tag, color
in zip(args.globaltag, colors)}
162 def color_row(row, _, line):
163 """Color the lines depending on which globaltag the payload comes from"""
164 if not support_color:
166 begin = colors.get(row[-1],
"")
168 return begin + line + end
170 with Pager(
"Result of merging globaltags",
True):
172 output_id = db.get_globalTagInfo(args.output)
173 if output_id
is None:
174 B2ERROR(
"Output globaltag doesn't exist. Please create it first with a proper description")
177 output_id = output_id[
"globalTagId"]
180 if any(db.get_globalTagInfo(tag)
is None for tag
in args.globaltag):
185 existing = defaultdict(
lambda: IoVSet(allow_overlaps=
True))
186 if args.run_range
is not None:
187 args.run_range = IntervalOfValidity(args.run_range)
190 for tag
in args.globaltag:
192 all_payloads = db.get_all_iovs(tag)
194 all_payloads.sort(key=
lambda p: p.revision, reverse=
True)
197 all_payloads.sort(key=
lambda p: p.name, reverse=
False)
199 payloads = get_all_iovsets(all_payloads, args.run_range)
200 for payload
in payloads:
202 payload.iov.remove(existing[payload.name])
206 existing[payload.name] |= payload.iov
208 final.append(payload)
210 for iov
in payload.iov:
211 table.append([payload.name, payload.revision] + list(iov.tuple) + [tag])
214 table.sort(key=
lambda r: (r[0], r[3:5]))
217 table.insert(0, [
"Name",
"Rev",
"First Exp",
"First Run",
"Final Exp",
"Final Run",
"Source"])
218 columns = [
"+", -8, 6, 6, 6, 6, max(len(_)
for _
in args.globaltag)]
220 B2INFO(f
"Result of merging the globaltags {', '.join(args.globaltag)}")
222 pretty_print_table(table, columns, transform=color_row)
226 B2INFO(f
'Now copying the {len(final)} payloads into {args.output} to create {len(table)-1} iovs ...')
227 create_iov = functools.partial(create_iov_wrapper, db, output_id)
229 with ThreadPoolExecutor(max_workers=args.nprocess)
as pool:
230 start = time.monotonic()
231 for payload, _
in enumerate(pool.map(create_iov, final), 1):
232 eta = (time.monotonic() - start) / payload * (len(final) - payload)
233 B2INFO(f
"{payload}/{len(final)} payloads copied, ETA: {eta:.1f} seconds")
235 B2ERROR(
"Not all iovs could be created. This could be a server/network problem "
236 "or the destination globaltag was not empty or not writeable. Please make "
237 "sure the target tag is empty and try again")
243 def command_tag_runningupdate(args, db=None):
245 Update a running globaltag with payloads from a staging tag
247 This command will calculate and apply the necessary updates to a running
248 globaltag with a given staging globaltag
250 Running tags are defined as "immutable for existing data but conditions for
251 newer runs may be added" and the only modification allowed is to add new
252 payloads for new runs or close existing payloads to no longer be valid for
255 This command takes previously prepared and validated payloads in a staging
256 globaltag and will then calculate which payloads to close and what to add to
257 the running globaltag.
259 For this to work we require
261 1. A running globaltag in the state "RUNNING"
263 2. A (experiment, run) number from which run on the update should be valid.
264 This run number needs to be
266 a) bigger than the start of validity for all iovs in the running tag
267 b) bigger than the end of validity for all closed iovs (i.e. not valid
268 to infinity) in the running tag
270 3. A staging globaltag with the new payloads in state "VALIDATED"
272 a) payloads in the staging tag starting at (0,0) will be interpreted as
273 starting at the first valid run for the update
274 b) all other payloads need to start at or after the first valid run for
276 c) The globaltag needs to be gap and overlap free
277 d) All payloads in the staging tag should have as last iov an open iov
278 (i.e. valid to infinity) but this can be disabled.
280 The script will check all the above requirements and will then calculate the
281 necessary operations to
283 1. Add all payloads from the staging tag where a start validity of (0, 0) is
284 replaced by the starting run for which this update should be valid.
285 2. close all iovs for payloads in the running tags just before the
286 corresponding iov of the same payload in the staging tag, so either at the
287 first run for the update to be valid or later
288 3. Optionally, make sure all payloads in the staging tag end in an open iov.
292 running tag contains ::
294 payload1, rev 1, valid from 0,1 to 1,0
295 payload1, rev 2, valid from 1,1 to -1,-1
296 payload2, rev 1, valid from 0,1 to -1,-1
297 payload3, rev 1, valid from 0,1 to 1,0
298 payload4, rev 1, valid from 0,1 to -1,-1
299 payload5, rev 1, valid from 0,1 to -1,-1
301 staging tag contains ::
303 payload1, rev 3, valid from 0,0 to 1,8
304 payload1, rev 4, valid from 1,9 to 1,20
305 payload2, rev 2, valid from 1,5 to 1,20
306 payload3, rev 2, valid from 0,0 to -1,-1
307 payload4, rev 1, valid from 0,0 to 1,20
309 Then running ``b2conditionsdb tag runningupdate running staging --run 1 2 --allow-closed``,
310 the running globaltag after the update will contain ::
312 payload1, rev 1, valid from 0,1 to 1,0
313 payload1, rev 2, valid from 1,1 to 1,1
314 payload1, rev 3, valid from 1,2 to 1,8
315 payload1, rev 4, valid from 1,9 to 1,20
316 payload2, rev 1, valid from 0,1 to 1,4
317 payload2, rev 2, valid from 1,5 to 1,20
318 payload3, rev 1, valid from 0,1 to 1,0
319 payload3, rev 2, valid from 1,2 to -1,-1
320 payload4, rev 1, valid from 0,1 to 1,20
321 payload5, rev 1, valid from 0,1 to -1,-1
325 - the start of payload1 and payload3 in staging has been adjusted
326 - payload2 in the running tag as been closed at 1,4, just before the
327 validity from the staging tag
328 - payload3 was already closed in the running tag so no change is
329 performed. This might result in gaps but is intentional
330 - payload4 was not closed at rim 1,2 because the staging tag had the same
331 revision of the payload so the these were merged to one long validity.
332 - payload5 was not closed as there was no update to it in the staging tag.
333 If we would have run with ``--full-replacement`` it would have been closed.
334 - if we would have chosen ``--run 1 1`` the update would have failed because
335 payload1, rev2 in running starts at 1,1 so we would have a conflict
336 - if we would have chosen ``--run 1 6`` the update would have failed because
337 payload2 in the staging tag starts before this run
338 - if we would have chosen to open the final iovs in staging by using
339 ``--fix-closed``, payload1, rev 4; payload2, rev 2 and payload4 rev 1
340 would be valid until -1,-1 after the running tag. In fact, payload 4
341 would not be changed at all.
344 args.add_argument(
"running", help=
"name of the running globaltag")
345 args.add_argument(
"staging", help=
"name of the staging globaltag")
346 group = args.add_argument_group(
"required named arguments")
347 group.add_argument(
"-r",
"--run", required=
True, nargs=2, type=int, metavar=(
"EXP",
"RUN"),
348 help=
"First experiment + run number for which the update should be "
349 "valid. Two numbers separated by space")
350 choice = args.add_mutually_exclusive_group()
351 choice.add_argument(
"--allow-closed", dest=
"mode", action=
"store_const",
352 const=RunningTagUpdateMode.ALLOW_CLOSED,
353 default=RunningTagUpdateMode.STRICT,
354 help=
"if given allow payloads in the staging tag to not "
355 "be open, i.e. they don't have to be open ended in the "
356 "update. Useful to retire a payload by adding one last update")
357 choice.add_argument(
"--fix-closed", dest=
"mode", action=
"store_const",
358 const=RunningTagUpdateMode.FIX_CLOSED,
359 help=
"if given automatically open the last iov for each "
360 "payload in staging if it is closed.")
361 choice.add_argument(
"--simple-mode", dest=
"mode", action=
"store_const",
362 const=RunningTagUpdateMode.SIMPLE,
363 help=
"if given require the staging tag to solely consist "
364 "of fully infinite validities: Only one iov per payload "
365 "with a validity of (0,0,-1,-1)")
366 choice.add_argument(
"--full-replacement", dest=
"mode", action=
"store_const",
367 const=RunningTagUpdateMode.FULL_REPLACEMENT,
368 help=
"if given perform a full replacement and close all "
369 "open iovs in the running tag not present in the staging tag. "
370 "After such an update exactly the payloads in the staging tag "
371 "will be valid after the given run. This allows for closed iovs "
372 "in the staging tag as with ``--allow-closed``")
373 args.add_argument(
"--dry-run", default=
False, action=
"store_true",
374 help=
"Only show the changes, don't try to apply them")
378 set_cdb_authentication_token(db, args.auth_token)
381 updater = RunningTagUpdater(db, args.running, args.staging, args.run, args.mode, args.dry_run)
382 operations = updater.calculate_update()
383 except RunningTagUpdaterError
as e:
384 B2ERROR(e, **e.extra_vars)
389 B2INFO(
"Nothing to do, please check the globaltags given are correct")
394 last_valid = tuple(args.run)
396 "first valid run": last_valid,
397 "payloads closed": 0,
398 "payloads updated": 0,
399 "payload iovs added": 0,
400 "next possible update": last_valid,
403 updated_payloads = set()
404 for op, payload
in operations:
407 summary[
'payloads closed'] += 1
409 updated_payloads.add(payload.name)
410 summary[
'payload iovs added'] += 1
412 last_valid = max(payload.iov[:2], last_valid)
414 if payload.iov[2:] != (-1, -1):
415 last_valid = max(payload.iov[2:], last_valid)
417 table.append([op, payload.name, payload.revision] + list(payload.iov))
420 summary[
'next possible update'] = (last_valid[0] + (1
if last_valid[1] < 0
else 0), last_valid[1] + 1)
422 summary[
'payloads updated'] = len(updated_payloads)
425 support_color = LogPythonInterface.terminal_supports_colors()
427 def color_row(row, _, line):
428 """Color the lines depending on which globaltag the payload comes from"""
429 if not support_color:
431 begin =
"" if row[0] !=
"CLOSE" else "\x1b[31m"
433 return begin + line + end
436 table.sort(key=
lambda x: (x[1], x[3:], x[2], x[0]))
437 table.insert(0, [
"Action",
"Payload",
"Rev",
"First Exp",
"First Run",
"Final Exp",
"Final Run"])
438 columns = [6,
'*', -6, 6, 6, 6, 6]
440 with Pager(f
"Changes to running tag {args.running}:",
True):
441 B2INFO(f
"Changes to be applied to the running tag {args.running}")
442 pretty_print_table(table, columns, transform=color_row)
445 B2INFO(
"Running in dry mode, not applying any changes.", **summary)
448 B2WARNING(
"Applying these changes cannot be undone and further updates to "
449 "this run range will **NOT** be possible", **summary)
451 answer = input(
"Are you sure you want to continue? [yes/No]: ")
452 while answer.lower().strip()
not in [
'yes',
'no',
'n',
'']:
453 answer = input(
"Please enter 'yes' or 'no': ")
455 if answer.lower().strip() !=
'yes':
456 B2INFO(
"Aborted by user ...")
461 updater.apply_update()
464 except RunningTagUpdaterError
as e:
465 B2ERROR(e, **e.extra_vars)
469 def command_iovs(args, db=None):
471 Modify, delete or copy iovs from a globaltags.
473 This command allows to modify, delete or copy iovs of a globaltag. If no other command is given do nothing.
482 class CommandIoVsHelper:
484 Class to unify common parts of b2conditionsdb iovs commands
486 This class defines common argparse arguments,
487 common filter of iovs and common multithreading
491 """initialization, just remember the arguments or parser and the database instance
494 whichcommand (str): from whichcommand it is called (copy, delete or modify)
495 args (argparse.ArgumentParser): where to append new arguments
496 db (conditions_db.ConditionsDB): database instance to be used
510 self.
past_dictpast_dict = {
"delete":
"deleted",
"modify":
"modified",
"copy":
"copied",
"create":
"created"}
513 """Add arguments to the parser"""
515 self.
_args_args.add_argument(
"tag", metavar=
"INPUT_TAGNAME",
516 help=f
"globaltag for which the the IoVs should be {self.past_dict[self.whichcommand]}")
518 self.
_args_args.add_argument(
"output", metavar=
"OUTPUT_TAGNAME", help=
"globaltag to which the the IoVs should be copied")
520 self.
_args_args.add_argument(
"new_iov", metavar=
"NEW_IOV", help=
"New iov to be set to all considered iovs."
521 " It should be a string with 4 numbers separated by spaces."
522 " Use * to mark the fields that should not be modified. For example"
523 " if 7 0 * * is given the iov (7, 1, 9, 42) will become (7 0 9 42).")
524 self.
_args_args.add_argument(
"--iov-id", default=
None, type=int,
525 help=
"IoVid of the iov to be considered")
526 self.
_args_args.add_argument(
529 help=
"whitespace-separated string with pattern of the iov to be considered. "
530 " Use * to mark the fields that shold be ignored. Valid patterns are 0 0 -1 -1"
531 " (a very specific IoV), 0 * -1 -1 (any iov that starts in any run of exp 0 and ends exactly in exp -1, run -1)"
532 ", * * 3 45 (any Iov ending in exp 3, run 45, regardless from where it starts).")
533 self.
_args_args.add_argument(
"--run-range", nargs=4, default=
None, type=int,
534 metavar=(
"FIRST_EXP",
"FIRST_RUN",
"FINAL_EXP",
"FINAL_RUN"),
535 help=
"Can be four numbers to limit the run range to be considered"
536 " Only iovs overlapping, even partially, with this range will be considered.")
537 self.
_args_args.add_argument(
"--fully-contained", action=
"store_true",
538 help=
"If given together with --run_range limit the list of payloads "
539 "to the ones fully contained in the given run range")
541 self.
_args_args.add_argument(
"--set-run-range", action=
"store_true",
542 help=
"If given together with --run_range modify the interval of validity"
543 " of partially overlapping iovs to be fully contained in the given run range")
545 self.
_args_args.add_argument(
"--revision", metavar=
'revision', type=int,
546 help=
"Specify the revision of the payload to be removed")
547 self.
_args_args.add_argument(
"--dry-run", help=
"Don't do anything, just print what would be done",
548 action=
"store_true", default=
False)
550 self.
_args_args.add_argument(
"--replace", help=
"Modify the iovs in the output tag to avoid overlaps",
551 action=
"store_true", default=
False)
552 self.
_args_args.add_argument(
"-j", type=int, default=10, dest=
"nprocess",
553 help=
"Number of concurrent threads to use.")
556 """Get the iovs already filtered"""
557 if not self.
iovfilteriovfilter.check_arguments():
558 B2ERROR(
"Issue with arguments")
560 all_iovs = self.
dbdb.get_all_iovs(
562 run_range=self.
_args_args.run_range,
563 fully_contained=self.
_args_args.fully_contained,
568 if self.
_args_args.iov_id
and iov.iov_id != self.
_args_args.iov_id:
570 if not self.
iovfilteriovfilter.check(iov.name):
572 if self.
_args_args.iov_pattern
and not fnmatch(
"{} {} {} {}".format(*iov.iov),
573 "{} {} {} {}".format(*self.
_args_args.iov_pattern.split())):
575 if self.
_args_args.revision
and iov.revision != self.
_args_args.revision:
577 iovs_to_return.append(iov)
578 return iovs_to_return
580 def modify_db(self, func, func_args, whichcommand=None):
581 """Modify the database using multithreading"""
582 if whichcommand
is None:
585 with ThreadPoolExecutor(max_workers=self.
_args_args.nprocess)
as pool:
586 start = time.monotonic()
587 for iov_num, _
in enumerate(pool.map(func, func_args), 1):
588 eta = (time.monotonic() - start) / iov_num * (len(func_args) - iov_num)
589 B2INFO(f
"{iov_num}/{len(func_args)} iovs {self.past_dict[whichcommand]}, ETA: {eta:.1f} seconds")
591 B2ERROR(f
"Not all iovs could be {self.past_dict[whichcommand]}. This could be a server/network problem "
592 "or the destination globaltag was not writeable.")
596 def command_iovs_delete(args, db=None):
598 Delete iovs from a globaltag
600 This command allows to delete the iovs from a globaltags, optionally limiting the iovs to be deleted to those
601 of a specific payload, revision, IoVid or run range.
605 command_iovs_helper.add_arguments()
608 iovs_to_delete = command_iovs_helper.get_iovs()
610 table = [[i.iov_id, i.name, i.revision] + list(i.iov)
for i
in iovs_to_delete]
611 table.insert(0, [
"IovId",
"Name",
"Rev",
"First Exp",
"First Run",
"Final Exp",
"Final Run"])
612 columns = [9,
"+", 6, 6, 6, 6, 6]
614 if command_iovs_helper.num_all_iovs == len(iovs_to_delete)
and args.run_range
is None:
615 B2WARNING(f
"All the iovs in the globaltag {args.tag} will be deleted!")
616 gt_check = input(
'Please enter the global tag name again to confirm this action: ')
617 if gt_check != args.tag:
618 B2ERROR(
'global tag names do not match.')
621 B2INFO(
"Deleting the following iovs")
622 pretty_print_table(table, columns)
625 set_cdb_authentication_token(db, args.auth_token)
627 command_iovs_helper.modify_db(db.delete_iov, [i.iov_id
for i
in iovs_to_delete])
634 def command_iovs_copy(args, db=None):
636 Copy iovs from a globaltag to another one
638 This command allows to copy the iovs from a globaltags to another one, optionally limiting
639 the iovs to be copied to those of a specific payload, revision, IoV id or run range.
643 command_iovs_helper.add_arguments()
646 iovs_to_copy = command_iovs_helper.get_iovs()
649 by_name = defaultdict(
lambda:
IoVSet(allow_overlaps=
False))
650 for iov
in iovs_to_copy:
651 if args.run_range
and args.set_run_range:
654 by_name[iov.name].add(iov.iov)
655 except ValueError
as e:
656 B2ERROR(f
"Overlap for payload {iov.name} r{iov.revision}: {e}")
661 output_id = db.get_globalTagInfo(args.output)
662 if output_id
is None:
663 B2ERROR(
"Output globaltag doesn't exist. Please create it first with a proper description")
665 output_id = output_id[
"globalTagId"]
668 iovs_output = db.get_all_iovs(args.output)
669 iovs_output.sort(key=
lambda i: i.iov[:2])
670 payloads_output = defaultdict(list)
671 for iov
in iovs_output:
673 payloads_output[iov.name].append(iov)
676 iovs_in_output = [(i.checksum, i.iov)
for i
in iovs_output]
677 iovs_to_copy = [i
for i
in iovs_to_copy
if (i.checksum, i.iov)
not in iovs_in_output]
680 iovs_not_to_copy = []
684 for iov_to_copy
in iovs_to_copy:
687 for iov_present
in payloads_output[iov_to_copy.name]:
688 if iov_present.newiov & iov_:
689 if still_to_copy
and iov_to_copy.checksum == iov_present.checksum:
690 iov_present.newiov.add(iov_, allow_overlaps=
True)
691 iovs_not_to_copy.append(iov_to_copy)
692 still_to_copy =
False
694 iov_present.newiov -= iov_
701 for iov_present
in sum(payloads_output.values(), []):
703 if len(iov_present.newiov) == 0:
704 iovs_to_delete.append(iov_present)
706 elif len(iov_present.newiov) == 1:
707 if not list(iov_present.newiov)[0].tuple == iov_present.iov:
708 iovs_to_modify.append((iov_present, list(iov_present.newiov)[0].tuple))
711 newiovs = list(iov_present.newiov)
712 iovs_to_modify.append((iov_present, newiovs[0].tuple))
713 for newiov
in newiovs[1:]:
714 iovs_to_create.append((iov_present, newiov.tuple))
718 iovs_to_copy = [i
for i
in iovs_to_copy
if i
not in iovs_not_to_copy]
721 table = [[i.iov_id, i.name, i.revision] + list(i.iov)
for i
in iovs_to_copy]
722 table.insert(0, [
"IovId",
"Name",
"Rev",
"First Exp",
"First Run",
"Final Exp",
"Final Run"])
723 columns = [9,
"+", 6, 6, 6, 6, 6]
724 B2INFO(f
"Copying the following iovs to {args.output}")
725 pretty_print_table(table, columns)
727 if (iovs_to_delete
or iovs_to_modify
or iovs_to_create)
and not args.replace:
728 B2WARNING(
"Inserting the iovs will create overlaps,"
729 f
" to avoid them the changes below should be implemented on {args.tag}")
732 B2WARNING(
"iovs to be deleted")
734 iovs_to_delete.sort(key=
lambda x: x.iov[:2])
735 iovs_to_delete.sort(key=
lambda x: x.name)
737 table = [[i.iov_id, i.name, i.revision] + list(i.iov)
for i
in iovs_to_delete]
738 table.insert(0, [
"IovId",
"Name",
"Rev",
"First Exp",
"First Run",
"Final Exp",
"Final Run"])
739 columns = [9,
"+", 6, 6, 6, 6, 6]
740 pretty_print_table(table, columns)
742 B2WARNING(
"iovs to be modified")
744 iovs_to_modify.sort(key=
lambda x: x[0].iov[:2])
745 iovs_to_modify.sort(key=
lambda x: x[0].name)
747 table = [[i[0].iov_id, i[0].name, i[0].revision] + list(i[0].iov) + list(i[1])
for i
in iovs_to_modify]
748 table.insert(0, [
"IovId",
"Name",
"Rev",
"Old First Exp",
"Old First Run",
"Old Final Exp",
"Old Final Run",
749 "New First Exp",
"New First Run",
"New Final Exp",
"New Final Run"])
750 columns = [9,
"+", 6, 6, 6, 6, 6, 6, 6, 6, 6]
751 pretty_print_table(table, columns)
753 B2WARNING(
"iovs to be created")
755 iovs_to_create.sort(key=
lambda x: x[1][:2])
756 iovs_to_create.sort(key=
lambda x: x[0].name)
758 table = [[i[0].name, i[0].revision] + list(i[1])
for i
in iovs_to_create]
759 table.insert(0, [
"Name",
"Rev",
"First Exp",
"First Run",
"Final Exp",
"Final Run"])
760 columns = [
"+", 6, 6, 6, 6, 6]
761 pretty_print_table(table, columns)
763 if (iovs_to_delete
or iovs_to_modify
or iovs_to_create)
and not args.replace:
764 B2WARNING(
"To apply them use the option --replace")
765 B2WARNING(
"If instead you want these overlaps to be present enter"
766 " the output global tag name again to confirm this action: ")
768 if gt_check != args.output:
769 B2ERROR(
"global tag names do not match.")
773 set_cdb_authentication_token(db, args.auth_token)
775 command_iovs_helper.modify_db(
lambda args: db.create_iov(output_id, *args),
776 [(i.payload_id, *i.iov)
for i
in iovs_to_copy])
778 command_iovs_helper.modify_db(db.delete_iov, [i.iov_id
for i
in iovs_to_delete],
"delete")
779 command_iovs_helper.modify_db(
lambda args: db.modify_iov(*args),
780 [(i[0].iov_id, *i[1])
for i
in iovs_to_modify],
"modify")
781 command_iovs_helper.modify_db(
lambda args: db.create_iov(output_id, *args),
782 [(i[0].payload_id, *i[1])
for i
in iovs_to_create],
"create")
789 def command_iovs_modify(args, db=None):
791 Modify iovs from a globaltag
793 This command allows to modify the iovs from a globaltags, optionally limiting the iovs to be modified to those
794 of a specific payload, revision, IoV id or run range.
798 command_iovs_helper.add_arguments()
801 new_iov = args.new_iov.split()
803 for i
in range(len(new_iov)):
805 new_iov[i] = int(new_iov[i])
807 if new_iov[i] !=
'*':
808 raise ValueError(f
"Invalid IOV value: {new_iov[i]} should be an integer or '*'")
811 for iov
in command_iovs_helper.get_iovs():
812 new_iow_ = new_iov.copy()
813 for i
in range(len(new_iow_)):
814 if new_iow_[i] ==
'*':
815 new_iow_[i] = iov.iov[i]
816 iovs_to_modify.append((iov, new_iow_))
818 table = [[i[0].iov_id, i[0].name, i[0].revision] + list(i[0].iov) + list(i[1])
for i
in iovs_to_modify]
819 table.insert(0, [
"IovId",
"Name",
"Rev",
"Old First Exp",
"Old First Run",
"Old Final Exp",
"Old Final Run",
820 "New First Exp",
"New First Run",
"New Final Exp",
"New Final Run"])
821 columns = [9,
"+", 6, 6, 6, 6, 6, 6, 6, 6, 6]
823 B2INFO(
"Changing the following iovs")
824 pretty_print_table(table, columns)
827 set_cdb_authentication_token(db, args.auth_token)
829 command_iovs_helper.modify_db(
lambda args: db.modify_iov(*args),
830 [(i[0].iov_id, *i[1])
for i
in iovs_to_modify])
_args
argparse.ArgumentParser instance
past_dict
Dictionary with past participles.
def modify_db(self, func, func_args, whichcommand=None)
db
conditions_db.ConditionsDB instance
num_all_iovs
number of iovs before payload and revision selection
def __init__(self, whichcommand, args, db)
whichcommand
from whichcommand it is called (copy, delete or modify)