rucio 37.5.0__py3-none-any.whl → 37.7.0__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.

Potentially problematic release.


This version of rucio might be problematic. Click here for more details.

Files changed (202) hide show
  1. rucio/cli/bin_legacy/rucio.py +41 -22
  2. rucio/cli/bin_legacy/rucio_admin.py +1 -1
  3. rucio/cli/did.py +2 -2
  4. rucio/cli/rse.py +2 -3
  5. rucio/cli/rule.py +9 -5
  6. rucio/cli/subscription.py +1 -1
  7. rucio/client/baseclient.py +9 -4
  8. rucio/client/didclient.py +16 -16
  9. rucio/client/downloadclient.py +16 -15
  10. rucio/client/exportclient.py +45 -4
  11. rucio/client/lockclient.py +3 -3
  12. rucio/client/pingclient.py +35 -4
  13. rucio/client/replicaclient.py +2 -2
  14. rucio/client/touchclient.py +3 -2
  15. rucio/client/uploadclient.py +728 -183
  16. rucio/common/cache.py +1 -2
  17. rucio/common/client.py +4 -30
  18. rucio/common/config.py +27 -3
  19. rucio/common/constants.py +5 -1
  20. rucio/common/didtype.py +2 -2
  21. rucio/common/dumper/__init__.py +1 -1
  22. rucio/common/pcache.py +20 -25
  23. rucio/common/plugins.py +12 -19
  24. rucio/common/policy.py +3 -2
  25. rucio/common/schema/__init__.py +11 -8
  26. rucio/common/types.py +7 -5
  27. rucio/common/utils.py +1 -1
  28. rucio/core/account.py +2 -1
  29. rucio/core/account_limit.py +3 -2
  30. rucio/core/authentication.py +1 -1
  31. rucio/core/credential.py +1 -1
  32. rucio/core/did.py +62 -61
  33. rucio/core/did_meta_plugins/__init__.py +10 -10
  34. rucio/core/did_meta_plugins/did_column_meta.py +9 -9
  35. rucio/core/did_meta_plugins/did_meta_plugin_interface.py +3 -3
  36. rucio/core/did_meta_plugins/elasticsearch_meta.py +7 -7
  37. rucio/core/did_meta_plugins/json_meta.py +2 -2
  38. rucio/core/did_meta_plugins/mongo_meta.py +9 -9
  39. rucio/core/did_meta_plugins/postgres_meta.py +7 -7
  40. rucio/core/dirac.py +3 -2
  41. rucio/core/distance.py +2 -1
  42. rucio/core/exporter.py +3 -2
  43. rucio/core/importer.py +5 -5
  44. rucio/core/lifetime_exception.py +2 -2
  45. rucio/core/lock.py +7 -7
  46. rucio/core/meta_conventions.py +2 -2
  47. rucio/core/monitor.py +1 -1
  48. rucio/core/naming_convention.py +1 -1
  49. rucio/core/nongrid_trace.py +2 -2
  50. rucio/core/oidc.py +2 -2
  51. rucio/core/permission/__init__.py +9 -6
  52. rucio/core/permission/generic.py +2 -2
  53. rucio/core/permission/generic_multi_vo.py +2 -2
  54. rucio/core/replica.py +22 -22
  55. rucio/core/request.py +2 -2
  56. rucio/core/rse.py +7 -7
  57. rucio/core/rule.py +38 -38
  58. rucio/core/rule_grouping.py +2 -3
  59. rucio/core/scope.py +1 -1
  60. rucio/core/trace.py +2 -2
  61. rucio/core/transfer.py +2 -2
  62. rucio/core/vo.py +2 -1
  63. rucio/daemons/atropos/atropos.py +2 -1
  64. rucio/daemons/auditor/__init__.py +1 -1
  65. rucio/daemons/automatix/automatix.py +5 -5
  66. rucio/daemons/badreplicas/minos.py +12 -5
  67. rucio/daemons/badreplicas/minos_temporary_expiration.py +5 -2
  68. rucio/daemons/badreplicas/necromancer.py +9 -3
  69. rucio/daemons/bb8/bb8.py +2 -1
  70. rucio/daemons/bb8/common.py +1 -1
  71. rucio/daemons/bb8/nuclei_background_rebalance.py +3 -3
  72. rucio/daemons/bb8/t2_background_rebalance.py +1 -1
  73. rucio/daemons/cache/consumer.py +1 -1
  74. rucio/daemons/conveyor/common.py +3 -3
  75. rucio/daemons/conveyor/finisher.py +13 -4
  76. rucio/daemons/conveyor/poller.py +5 -2
  77. rucio/daemons/conveyor/receiver.py +1 -1
  78. rucio/daemons/conveyor/submitter.py +2 -1
  79. rucio/daemons/follower/follower.py +1 -1
  80. rucio/daemons/hermes/hermes.py +29 -8
  81. rucio/daemons/judge/cleaner.py +2 -2
  82. rucio/daemons/judge/evaluator.py +7 -7
  83. rucio/daemons/judge/injector.py +2 -2
  84. rucio/daemons/judge/repairer.py +2 -2
  85. rucio/daemons/reaper/dark_reaper.py +5 -4
  86. rucio/daemons/reaper/reaper.py +7 -7
  87. rucio/daemons/replicarecoverer/suspicious_replica_recoverer.py +4 -4
  88. rucio/daemons/storage/consistency/actions.py +3 -3
  89. rucio/daemons/tracer/kronos.py +3 -2
  90. rucio/daemons/transmogrifier/transmogrifier.py +71 -69
  91. rucio/daemons/undertaker/undertaker.py +8 -7
  92. rucio/db/sqla/constants.py +4 -3
  93. rucio/db/sqla/migrate_repo/versions/3082b8cef557_add_naming_convention_table_and_closed_.py +1 -1
  94. rucio/db/sqla/migrate_repo/versions/4df2c5ddabc0_remove_temporary_dids.py +1 -1
  95. rucio/db/sqla/migrate_repo/versions/c129ccdb2d5_add_lumiblocknr_to_dids.py +1 -1
  96. rucio/db/sqla/models.py +3 -3
  97. rucio/db/sqla/session.py +7 -7
  98. rucio/db/sqla/util.py +3 -2
  99. rucio/gateway/account.py +77 -101
  100. rucio/gateway/account_limit.py +90 -116
  101. rucio/gateway/authentication.py +9 -8
  102. rucio/gateway/config.py +11 -10
  103. rucio/gateway/credential.py +2 -1
  104. rucio/gateway/did.py +58 -58
  105. rucio/gateway/dirac.py +3 -2
  106. rucio/gateway/exporter.py +2 -1
  107. rucio/gateway/heartbeat.py +3 -2
  108. rucio/gateway/identity.py +4 -3
  109. rucio/gateway/importer.py +2 -1
  110. rucio/gateway/lifetime_exception.py +5 -4
  111. rucio/gateway/lock.py +6 -5
  112. rucio/gateway/meta_conventions.py +3 -2
  113. rucio/gateway/permission.py +2 -1
  114. rucio/gateway/quarantined_replica.py +2 -1
  115. rucio/gateway/replica.py +20 -20
  116. rucio/gateway/request.py +10 -10
  117. rucio/gateway/rse.py +27 -26
  118. rucio/gateway/rule.py +12 -11
  119. rucio/gateway/scope.py +4 -3
  120. rucio/gateway/subscription.py +7 -6
  121. rucio/gateway/vo.py +5 -4
  122. rucio/rse/__init__.py +7 -6
  123. rucio/rse/protocols/ngarc.py +2 -2
  124. rucio/rse/protocols/srm.py +1 -1
  125. rucio/rse/protocols/webdav.py +8 -1
  126. rucio/rse/rsemanager.py +5 -4
  127. rucio/rse/translation.py +2 -2
  128. rucio/tests/common.py +6 -5
  129. rucio/vcsversion.py +3 -3
  130. rucio/web/rest/flaskapi/v1/accountlimits.py +5 -5
  131. rucio/web/rest/flaskapi/v1/accounts.py +20 -20
  132. rucio/web/rest/flaskapi/v1/archives.py +4 -3
  133. rucio/web/rest/flaskapi/v1/common.py +5 -4
  134. rucio/web/rest/flaskapi/v1/dids.py +382 -331
  135. rucio/web/rest/flaskapi/v1/lifetime_exceptions.py +5 -5
  136. rucio/web/rest/flaskapi/v1/locks.py +13 -13
  137. rucio/web/rest/flaskapi/v1/main.py +1 -0
  138. rucio/web/rest/flaskapi/v1/redirect.py +2 -2
  139. rucio/web/rest/flaskapi/v1/replicas.py +16 -16
  140. rucio/web/rest/flaskapi/v1/requests.py +16 -16
  141. rucio/web/rest/flaskapi/v1/subscriptions.py +7 -7
  142. {rucio-37.5.0.data → rucio-37.7.0.data}/scripts/rucio-abacus-account +8 -1
  143. {rucio-37.5.0.data → rucio-37.7.0.data}/scripts/rucio-abacus-rse +8 -1
  144. {rucio-37.5.0.data → rucio-37.7.0.data}/scripts/rucio-auditor +1 -1
  145. {rucio-37.5.0.data → rucio-37.7.0.data}/scripts/rucio-conveyor-throttler +7 -1
  146. {rucio-37.5.0.data → rucio-37.7.0.data}/scripts/rucio-follower +1 -1
  147. {rucio-37.5.0.data → rucio-37.7.0.data}/scripts/rucio-judge-cleaner +9 -1
  148. {rucio-37.5.0.data → rucio-37.7.0.data}/scripts/rucio-necromancer +7 -1
  149. {rucio-37.5.0.data → rucio-37.7.0.data}/scripts/rucio-replica-recoverer +31 -9
  150. {rucio-37.5.0.data → rucio-37.7.0.data}/scripts/rucio-undertaker +8 -2
  151. {rucio-37.5.0.dist-info → rucio-37.7.0.dist-info}/METADATA +1 -1
  152. {rucio-37.5.0.dist-info → rucio-37.7.0.dist-info}/RECORD +202 -202
  153. {rucio-37.5.0.data → rucio-37.7.0.data}/data/rucio/etc/alembic.ini.template +0 -0
  154. {rucio-37.5.0.data → rucio-37.7.0.data}/data/rucio/etc/alembic_offline.ini.template +0 -0
  155. {rucio-37.5.0.data → rucio-37.7.0.data}/data/rucio/etc/globus-config.yml.template +0 -0
  156. {rucio-37.5.0.data → rucio-37.7.0.data}/data/rucio/etc/ldap.cfg.template +0 -0
  157. {rucio-37.5.0.data → rucio-37.7.0.data}/data/rucio/etc/mail_templates/rule_approval_request.tmpl +0 -0
  158. {rucio-37.5.0.data → rucio-37.7.0.data}/data/rucio/etc/mail_templates/rule_approved_admin.tmpl +0 -0
  159. {rucio-37.5.0.data → rucio-37.7.0.data}/data/rucio/etc/mail_templates/rule_approved_user.tmpl +0 -0
  160. {rucio-37.5.0.data → rucio-37.7.0.data}/data/rucio/etc/mail_templates/rule_denied_admin.tmpl +0 -0
  161. {rucio-37.5.0.data → rucio-37.7.0.data}/data/rucio/etc/mail_templates/rule_denied_user.tmpl +0 -0
  162. {rucio-37.5.0.data → rucio-37.7.0.data}/data/rucio/etc/mail_templates/rule_ok_notification.tmpl +0 -0
  163. {rucio-37.5.0.data → rucio-37.7.0.data}/data/rucio/etc/rse-accounts.cfg.template +0 -0
  164. {rucio-37.5.0.data → rucio-37.7.0.data}/data/rucio/etc/rucio.cfg.atlas.client.template +0 -0
  165. {rucio-37.5.0.data → rucio-37.7.0.data}/data/rucio/etc/rucio.cfg.template +0 -0
  166. {rucio-37.5.0.data → rucio-37.7.0.data}/data/rucio/etc/rucio_multi_vo.cfg.template +0 -0
  167. {rucio-37.5.0.data → rucio-37.7.0.data}/data/rucio/requirements.server.txt +0 -0
  168. {rucio-37.5.0.data → rucio-37.7.0.data}/data/rucio/tools/bootstrap.py +0 -0
  169. {rucio-37.5.0.data → rucio-37.7.0.data}/data/rucio/tools/merge_rucio_configs.py +0 -0
  170. {rucio-37.5.0.data → rucio-37.7.0.data}/data/rucio/tools/reset_database.py +0 -0
  171. {rucio-37.5.0.data → rucio-37.7.0.data}/scripts/rucio +0 -0
  172. {rucio-37.5.0.data → rucio-37.7.0.data}/scripts/rucio-abacus-collection-replica +0 -0
  173. {rucio-37.5.0.data → rucio-37.7.0.data}/scripts/rucio-admin +0 -0
  174. {rucio-37.5.0.data → rucio-37.7.0.data}/scripts/rucio-atropos +0 -0
  175. {rucio-37.5.0.data → rucio-37.7.0.data}/scripts/rucio-automatix +0 -0
  176. {rucio-37.5.0.data → rucio-37.7.0.data}/scripts/rucio-bb8 +0 -0
  177. {rucio-37.5.0.data → rucio-37.7.0.data}/scripts/rucio-cache-client +0 -0
  178. {rucio-37.5.0.data → rucio-37.7.0.data}/scripts/rucio-cache-consumer +0 -0
  179. {rucio-37.5.0.data → rucio-37.7.0.data}/scripts/rucio-conveyor-finisher +0 -0
  180. {rucio-37.5.0.data → rucio-37.7.0.data}/scripts/rucio-conveyor-poller +0 -0
  181. {rucio-37.5.0.data → rucio-37.7.0.data}/scripts/rucio-conveyor-preparer +0 -0
  182. {rucio-37.5.0.data → rucio-37.7.0.data}/scripts/rucio-conveyor-receiver +0 -0
  183. {rucio-37.5.0.data → rucio-37.7.0.data}/scripts/rucio-conveyor-stager +0 -0
  184. {rucio-37.5.0.data → rucio-37.7.0.data}/scripts/rucio-conveyor-submitter +0 -0
  185. {rucio-37.5.0.data → rucio-37.7.0.data}/scripts/rucio-dark-reaper +0 -0
  186. {rucio-37.5.0.data → rucio-37.7.0.data}/scripts/rucio-dumper +0 -0
  187. {rucio-37.5.0.data → rucio-37.7.0.data}/scripts/rucio-hermes +0 -0
  188. {rucio-37.5.0.data → rucio-37.7.0.data}/scripts/rucio-judge-evaluator +0 -0
  189. {rucio-37.5.0.data → rucio-37.7.0.data}/scripts/rucio-judge-injector +0 -0
  190. {rucio-37.5.0.data → rucio-37.7.0.data}/scripts/rucio-judge-repairer +0 -0
  191. {rucio-37.5.0.data → rucio-37.7.0.data}/scripts/rucio-kronos +0 -0
  192. {rucio-37.5.0.data → rucio-37.7.0.data}/scripts/rucio-minos +0 -0
  193. {rucio-37.5.0.data → rucio-37.7.0.data}/scripts/rucio-minos-temporary-expiration +0 -0
  194. {rucio-37.5.0.data → rucio-37.7.0.data}/scripts/rucio-oauth-manager +0 -0
  195. {rucio-37.5.0.data → rucio-37.7.0.data}/scripts/rucio-reaper +0 -0
  196. {rucio-37.5.0.data → rucio-37.7.0.data}/scripts/rucio-rse-decommissioner +0 -0
  197. {rucio-37.5.0.data → rucio-37.7.0.data}/scripts/rucio-storage-consistency-actions +0 -0
  198. {rucio-37.5.0.data → rucio-37.7.0.data}/scripts/rucio-transmogrifier +0 -0
  199. {rucio-37.5.0.dist-info → rucio-37.7.0.dist-info}/WHEEL +0 -0
  200. {rucio-37.5.0.dist-info → rucio-37.7.0.dist-info}/licenses/AUTHORS.rst +0 -0
  201. {rucio-37.5.0.dist-info → rucio-37.7.0.dist-info}/licenses/LICENSE +0 -0
  202. {rucio-37.5.0.dist-info → rucio-37.7.0.dist-info}/top_level.txt +0 -0
@@ -124,7 +124,7 @@ def __split_rule_select_rses(
124
124
  weight: int,
125
125
  rse_expression: str,
126
126
  copies: int,
127
- blocklisted_rse_id: list,
127
+ blocklisted_rse_ids: list,
128
128
  logger: LoggerFunction,
129
129
  ) -> tuple[list, bool, bool]:
130
130
  """
@@ -138,7 +138,7 @@ def __split_rule_select_rses(
138
138
  :param weight: The weight of the rule.
139
139
  :param rse_expression: The RSE expression of the rule.
140
140
  :param copies: The number of copies.
141
- :param blocklisted_rse_id: The list of blocklisted_rse_id.
141
+ :param blocklisted_rse_ids: The list of blocklisted rse_ids.
142
142
  :param logger: The logger.
143
143
  :return: A tuple with list selected_rses, and 2 booleans create_rule, wont_reevaluate.
144
144
  """
@@ -172,7 +172,7 @@ def __split_rule_select_rses(
172
172
  copies=copies,
173
173
  size=0,
174
174
  preferred_rses=preferred_rses,
175
- blocklist=blocklisted_rse_id,
175
+ blocklist=blocklisted_rse_ids,
176
176
  )
177
177
  wont_reevaluate = True
178
178
  break
@@ -184,26 +184,22 @@ def __split_rule_select_rses(
184
184
  ) as error:
185
185
  logger(
186
186
  logging.WARNING,
187
- 'Problem getting RSEs for subscription "%s" for account %s : %s. %s'
188
- % (
189
- subscription_name,
190
- account,
191
- str(error),
192
- 'Try including blocklisted sites' if attempt == 0 else 'Skipping rule creation.'
193
- ),
187
+ 'Problem getting RSEs for subscription "%s" for account %s : %s. %s',
188
+ subscription_name,
189
+ account,
190
+ str(error),
191
+ 'Try including blocklisted sites' if attempt == 0 else 'Skipping rule creation.'
194
192
  )
195
193
  # Now including the blocklisted sites
196
- blocklisted_rse_id = []
194
+ blocklisted_rse_ids = []
197
195
  METRICS.counter(name="addnewrule.errortype.{exception}").labels(exception=str(error.__class__.__name__)).inc()
198
196
  wont_reevaluate = True
199
197
  except Exception as error:
200
198
  logger(
201
199
  logging.ERROR,
202
- "Problem resolving RSE expression %s : %s"
203
- % (
204
- rse_expression,
205
- str(error),
206
- )
200
+ "Problem resolving RSE expression %s : %s",
201
+ rse_expression,
202
+ str(error),
207
203
  )
208
204
  if len(preferred_rses) - len(preferred_unmatched) >= copies:
209
205
  create_rule = False
@@ -242,6 +238,7 @@ def get_subscriptions(logger: LoggerFunction = logging.log) -> list[dict]:
242
238
  break
243
239
  if rule.get("copies") == "*":
244
240
  rule["copies"] = len(list_rses_from_expression)
241
+ rule["wildcard"] = True
245
242
  overwrite_rules = True
246
243
  if skip_sub:
247
244
  continue
@@ -272,7 +269,7 @@ def get_subscriptions(logger: LoggerFunction = logging.log) -> list[dict]:
272
269
  subscriptions.extend(sub_dict[priority])
273
270
  logger(logging.INFO, "%i active subscriptions", len(subscriptions))
274
271
  except SubscriptionNotFound as error:
275
- logger(logging.WARNING, "No subscriptions defined: %s" % (str(error)))
272
+ logger(logging.WARNING, "No subscriptions defined: %s", (str(error)))
276
273
  return []
277
274
  except TypeError as error:
278
275
  logger(
@@ -307,7 +304,7 @@ def __is_matching_subscription(
307
304
  try:
308
305
  filter_string = loads(subscription["filter"])
309
306
  except ValueError as error:
310
- logging.error("%s : Subscription will be skipped" % error)
307
+ logging.error("%s : Subscription will be skipped", error)
311
308
  return False
312
309
  # Loop over the keys of filter_string for subscription
313
310
  for key in filter_string:
@@ -399,7 +396,7 @@ def select_algorithm(
399
396
  selected_rses = {}
400
397
  for rule_id in rule_ids:
401
398
  rule = get_rule(rule_id)
402
- logging.debug("In select_algorithm, %s", str(rule))
399
+ logger(logging.DEBUG, "In select_algorithm, %s", str(rule))
403
400
  rse = rule["rse_expression"]
404
401
  vo = rule["account"].vo
405
402
  if rse_exists(rse, vo=vo):
@@ -439,7 +436,7 @@ def select_algorithm(
439
436
  weight=rule.get("weight"),
440
437
  rse_expression=rse_expression,
441
438
  copies=rule.get('copies'),
442
- blocklisted_rse_id=params['blocklisted_rse_id'],
439
+ blocklisted_rse_ids=params['blocklisted_rse_ids'],
443
440
  logger=logger,
444
441
  )
445
442
  dict_selected_rses = {}
@@ -487,12 +484,13 @@ def run_once(heartbeat_handler: "HeartbeatHandler", bulk: int, **_kwargs) -> boo
487
484
 
488
485
  worker_number, total_workers, logger = heartbeat_handler.live()
489
486
  stopwatch = Stopwatch()
490
- blocklisted_rse_id = [rse["id"] for rse in list_rses({"availability_write": False})]
487
+ block_listed = {rse['rse']: rse["id"] for rse in list_rses({"availability_write": False})}
488
+ blocklisted_rse_ids = list(block_listed.values())
491
489
  identifiers = []
492
490
  # List all the active subscriptions
493
491
  subscriptions = get_subscriptions(logger=logger)
494
492
 
495
- # Loop over all the new dids
493
+ # Loop over all the new DIDs
496
494
  # Get the new DIDs based on the is_new flag
497
495
  logger(logging.DEBUG, "Listing new dids")
498
496
  for did in list_new_dids(
@@ -535,6 +533,7 @@ def run_once(heartbeat_handler: "HeartbeatHandler", bulk: int, **_kwargs) -> boo
535
533
  # Get all the rule and subscription parameters
536
534
  rule_dict = __get_rule_dict(rule_dict, subscription)
537
535
  weight = rule_dict.get("weight", None)
536
+ ignore_availability = rule_dict.get("ignore_availability", False)
538
537
  source_replica_expression = rule_dict.get(
539
538
  "source_replica_expression", None
540
539
  )
@@ -551,7 +550,7 @@ def run_once(heartbeat_handler: "HeartbeatHandler", bulk: int, **_kwargs) -> boo
551
550
  params['rse_expression'] = rule_dict.get("rse_expression")
552
551
  params['subscription_id'] = subscription["id"]
553
552
  params['subscription_name'] = subscription["name"]
554
- params['blocklisted_rse_id'] = blocklisted_rse_id
553
+ params['blocklisted_rse_ids'] = blocklisted_rse_ids
555
554
  if rule_dict.get("associated_site_idx", None):
556
555
  params["associated_site_idx"] = rule_dict.get(
557
556
  "associated_site_idx", None
@@ -583,7 +582,7 @@ def run_once(heartbeat_handler: "HeartbeatHandler", bulk: int, **_kwargs) -> boo
583
582
  weight=weight,
584
583
  rse_expression=rule_dict.get("rse_expression"),
585
584
  copies=copies,
586
- blocklisted_rse_id=blocklisted_rse_id,
585
+ blocklisted_rse_ids=blocklisted_rse_ids,
587
586
  logger=logger,
588
587
  )
589
588
  copies = 1
@@ -595,20 +594,26 @@ def run_once(heartbeat_handler: "HeartbeatHandler", bulk: int, **_kwargs) -> boo
595
594
  nb_rule = 0
596
595
  # Try to create the rule
597
596
  logger(logging.DEBUG, 'selected_rses : %s' % selected_rses)
598
- try:
599
- for rse in selected_rses:
600
- if isinstance(selected_rses, dict):
601
- # selected_rses is a dictionary only when split_rule is True or for chained subscriptions
602
- source_replica_expression = selected_rses[rse].get(
603
- "source_replica_expression",
604
- None,
605
- )
606
- weight = selected_rses[rse].get("weight", None)
607
- logger(
608
- logging.INFO,
609
- "Will insert one rule for %s:%s on %s"
610
- % (did["scope"], did["name"], rse),
597
+ for rse in selected_rses:
598
+ if isinstance(selected_rses, dict):
599
+ # selected_rses is a dictionary only when split_rule is True or for chained subscriptions
600
+ source_replica_expression = selected_rses[rse].get(
601
+ "source_replica_expression",
602
+ None,
611
603
  )
604
+ weight = selected_rses[rse].get("weight", None)
605
+ logger(
606
+ logging.INFO,
607
+ "Will insert one rule for %s:%s on %s",
608
+ did["scope"], did["name"], rse,
609
+ )
610
+ if rse in block_listed and rule_dict.get("wildcard"):
611
+ if ignore_availability:
612
+ logger(logging.WARNING, "RSE %s is unavailable, but wildcard number of copies is used with ignore_availability option. Creating a rule", rse)
613
+ else:
614
+ logger(logging.INFO, "RSE %s is unavailable and wildcard number of copies is used. Skipping rule creation", rse)
615
+ continue
616
+ try:
612
617
  rule_ids = add_rule(
613
618
  dids=[
614
619
  {
@@ -627,9 +632,7 @@ def run_once(heartbeat_handler: "HeartbeatHandler", bulk: int, **_kwargs) -> boo
627
632
  source_replica_expression=source_replica_expression,
628
633
  activity=rule_dict.get("activity"),
629
634
  purge_replicas=rule_dict.get("purge_replicas", False),
630
- ignore_availability=rule_dict.get(
631
- "ignore_availability", None
632
- ),
635
+ ignore_availability=ignore_availability,
633
636
  comment=rule_dict.get("comment"),
634
637
  delay_injection=rule_dict.get("delay_injection"),
635
638
  )
@@ -640,41 +643,40 @@ def run_once(heartbeat_handler: "HeartbeatHandler", bulk: int, **_kwargs) -> boo
640
643
  if split_rule:
641
644
  success = True
642
645
 
643
- METRICS.counter("addnewrule.done").inc(nb_rule)
644
- METRICS.counter("addnewrule.activity.{activity}").labels(activity="".join(rule_dict.get("activity").split())).inc(nb_rule)
645
- success = True
646
- except (
647
- InvalidReplicationRule,
648
- InvalidRuleWeight,
649
- InvalidRSEExpression,
650
- StagingAreaRuleRequiresLifetime,
651
- DuplicateRule,
652
- ) as error:
653
- # Errors that won't be retried
654
- success = True
655
- logger(logging.ERROR, str(error))
656
- METRICS.counter("addnewrule.errortype.{exception}").labels(exception=str(error.__class__.__name__)).inc()
657
- except Exception:
658
- # Errors that will be retried
659
- METRICS.counter("addnewrule.errortype.{exception}").labels(exception="unknown").inc()
660
- logger(logging.ERROR, "Unexpected error", exc_info=True)
646
+ except (
647
+ InvalidReplicationRule,
648
+ InvalidRuleWeight,
649
+ InvalidRSEExpression,
650
+ StagingAreaRuleRequiresLifetime,
651
+ DuplicateRule,
652
+ ) as error:
653
+ # Errors that won't be retried
654
+ success = True
655
+ logger(logging.ERROR, str(error))
656
+ METRICS.counter("addnewrule.errortype.{exception}").labels(exception=str(error.__class__.__name__)).inc()
657
+ except Exception:
658
+ # Errors that will be retried
659
+ METRICS.counter("addnewrule.errortype.{exception}").labels(exception="unknown").inc()
660
+ logger(logging.ERROR, "Unexpected error", exc_info=True)
661
+
662
+ METRICS.counter("addnewrule.done").inc(nb_rule)
663
+ METRICS.counter("addnewrule.activity.{activity}").labels(activity="".join(rule_dict.get("activity").split())).inc(nb_rule)
664
+ success = True
661
665
 
662
666
  did_success = did_success and success
663
667
  if not success:
664
668
  logger(
665
669
  logging.ERROR,
666
- "Rule for %s:%s on %s cannot be inserted"
667
- % (
668
- did["scope"],
669
- did["name"],
670
- rule_dict.get("rse_expression"),
671
- ),
670
+ "Rule for %s:%s on %s cannot be inserted",
671
+ did["scope"],
672
+ did["name"],
673
+ rule_dict.get("rse_expression"),
672
674
  )
673
675
  else:
674
676
  logger(
675
677
  logging.INFO,
676
- "%s rule(s) inserted in %f seconds"
677
- % (str(nb_rule), time.time() - stime),
678
+ "%s rule(s) inserted in %f seconds",
679
+ str(nb_rule), time.time() - stime,
678
680
  )
679
681
 
680
682
  if did_success:
@@ -697,7 +699,7 @@ def run_once(heartbeat_handler: "HeartbeatHandler", bulk: int, **_kwargs) -> boo
697
699
  flag_stopwatch = Stopwatch()
698
700
  for identifier in chunks(identifiers, 100):
699
701
  set_new_dids(identifier, None)
700
- logger(logging.DEBUG, "Time to set the new flag : %f" % flag_stopwatch.elapsed)
702
+ logger(logging.DEBUG, "Time to set the new flag : %f", flag_stopwatch.elapsed)
701
703
 
702
704
  stopwatch.stop()
703
705
 
@@ -709,9 +711,9 @@ def run_once(heartbeat_handler: "HeartbeatHandler", bulk: int, **_kwargs) -> boo
709
711
  )
710
712
  logger(
711
713
  logging.INFO,
712
- "It took %f seconds to process %i DIDs" % (stopwatch.elapsed, len(identifiers)),
714
+ "It took %f seconds to process %i DIDs", stopwatch.elapsed, len(identifiers),
713
715
  )
714
- logger(logging.DEBUG, "DIDs processed : %s" % (str(identifiers)))
716
+ logger(logging.DEBUG, "DIDs processed : %s", str(identifiers))
715
717
  METRICS.counter(name="transmogrifier.job.done").inc(1)
716
718
  METRICS.timer("job.duration").observe(stopwatch.elapsed)
717
719
  must_sleep = True
@@ -13,7 +13,7 @@
13
13
  # limitations under the License.
14
14
 
15
15
  '''
16
- Undertaker is a daemon to manage expired did.
16
+ Undertaker is a daemon to manage expired DID.
17
17
  '''
18
18
 
19
19
  import functools
@@ -29,6 +29,7 @@ from typing import TYPE_CHECKING
29
29
  from sqlalchemy.exc import DatabaseError
30
30
 
31
31
  import rucio.db.sqla.util
32
+ from rucio.common.constants import DEFAULT_VO
32
33
  from rucio.common.exception import DatabaseException, RuleNotFound, UnsupportedOperation
33
34
  from rucio.common.logging import setup_logging
34
35
  from rucio.common.types import InternalAccount
@@ -36,7 +37,7 @@ from rucio.common.utils import chunks
36
37
  from rucio.core.did import delete_dids, list_expired_dids
37
38
  from rucio.core.monitor import MetricManager
38
39
  from rucio.daemons.common import HeartbeatHandler, run_daemon
39
- from rucio.db.sqla.constants import MYSQL_LOCK_NOWAIT_REGEX, ORACLE_RESOURCE_BUSY_REGEX, PSQL_LOCK_NOT_AVAILABLE_REGEX
40
+ from rucio.db.sqla.constants import MYSQL_LOCK_NOWAIT_REGEX, ORACLE_RESOURCE_BUSY_REGEX, PSQL_LOCK_NOT_AVAILABLE_REGEX, PSQL_PSYCOPG_LOCK_NOT_AVAILABLE_REGEX
40
41
 
41
42
  if TYPE_CHECKING:
42
43
  from types import FrameType
@@ -51,7 +52,7 @@ DAEMON_NAME = 'undertaker'
51
52
 
52
53
  def undertaker(once: bool = False, sleep_time: int = 60, chunk_size: int = 10) -> None:
53
54
  """
54
- Main loop to select and delete dids.
55
+ Main loop to select and delete DIDs.
55
56
  """
56
57
  paused_dids = {} # {(scope, name): datetime}
57
58
  run_daemon(
@@ -72,7 +73,7 @@ def run_once(paused_dids: dict[tuple, datetime], chunk_size: int, heartbeat_hand
72
73
  worker_number, total_workers, logger = heartbeat_handler.live()
73
74
 
74
75
  try:
75
- # Refresh paused dids
76
+ # Refresh paused DIDs
76
77
  iter_paused_dids = deepcopy(paused_dids)
77
78
  for key in iter_paused_dids:
78
79
  if datetime.utcnow() > paused_dids[key]:
@@ -90,20 +91,20 @@ def run_once(paused_dids: dict[tuple, datetime], chunk_size: int, heartbeat_hand
90
91
  _, _, logger = heartbeat_handler.live()
91
92
  try:
92
93
  logger(logging.INFO, 'Receive %s dids to delete', len(chunk))
93
- delete_dids(dids=chunk, account=InternalAccount('root', vo='def'), expire_rules=True)
94
+ delete_dids(dids=chunk, account=InternalAccount('root', vo=DEFAULT_VO), expire_rules=True)
94
95
  logger(logging.INFO, 'Delete %s dids', len(chunk))
95
96
  METRICS.counter(name='undertaker.delete_dids').inc(len(chunk))
96
97
  except RuleNotFound as error:
97
98
  logger(logging.ERROR, error)
98
99
  except (DatabaseException, DatabaseError, UnsupportedOperation) as e:
99
- if match(ORACLE_RESOURCE_BUSY_REGEX, str(e.args[0])) or match(PSQL_LOCK_NOT_AVAILABLE_REGEX, str(e.args[0])) or match(MYSQL_LOCK_NOWAIT_REGEX, str(e.args[0])):
100
+ if match(ORACLE_RESOURCE_BUSY_REGEX, str(e.args[0])) or match(PSQL_LOCK_NOT_AVAILABLE_REGEX, str(e.args[0])) or match(PSQL_PSYCOPG_LOCK_NOT_AVAILABLE_REGEX, str(e.args[0])) or match(MYSQL_LOCK_NOWAIT_REGEX, str(e.args[0])):
100
101
  for did in chunk:
101
102
  paused_dids[(did['scope'], did['name'])] = datetime.utcnow() + timedelta(seconds=randint(600, 2400)) # noqa: S311
102
103
  METRICS.counter('delete_dids.exceptions.{exception}').labels(exception='LocksDetected').inc()
103
104
  logger(logging.WARNING, 'Locks detected for chunk')
104
105
  else:
105
106
  logger(logging.ERROR, 'Got database error %s.', str(e))
106
- except:
107
+ except Exception:
107
108
  logging.critical(traceback.format_exc())
108
109
 
109
110
 
@@ -26,6 +26,7 @@ ORACLE_DEADLOCK_DETECTED_REGEX = r".*ORA-00060.*"
26
26
  ORACLE_RESOURCE_BUSY_REGEX = r".*ORA-00054.*"
27
27
  ORACLE_UNIQUE_CONSTRAINT_VIOLATED_REGEX = r".*ORA-00001.*"
28
28
  PSQL_LOCK_NOT_AVAILABLE_REGEX = r".*55P03.*"
29
+ PSQL_PSYCOPG_LOCK_NOT_AVAILABLE_REGEX = r".*psycopg.errors.LockNotAvailable.*"
29
30
  MYSQL_LOCK_NOWAIT_REGEX = r".*3572.*"
30
31
  MYSQL_LOCK_WAIT_TIMEOUT_EXCEEDED = "ERROR 1205 (HY000)"
31
32
 
@@ -196,9 +197,9 @@ class SubscriptionState(Enum):
196
197
  BROKEN = 'B'
197
198
 
198
199
 
199
- #class TransferLimitDirection(Enum):
200
- # SOURCE = 'S'
201
- # DESTINATION = 'D'
200
+ # class TransferLimitDirection(Enum):
201
+ # SOURCE = 'S'
202
+ # DESTINATION = 'D'
202
203
 
203
204
 
204
205
  class DatabaseOperationType(Enum):
@@ -12,7 +12,7 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- ''' add convention table and closed_at to dids '''
15
+ ''' add convention table and closed_at to DIDs '''
16
16
 
17
17
  import datetime
18
18
 
@@ -12,7 +12,7 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- ''' remove temporary dids '''
15
+ ''' remove temporary DIDs '''
16
16
 
17
17
  import sqlalchemy as sa
18
18
  from alembic import context
@@ -12,7 +12,7 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- ''' add lumiblocknr to dids '''
15
+ ''' add lumiblocknr to DIDs '''
16
16
 
17
17
  import sqlalchemy as sa
18
18
  from alembic import context
rucio/db/sqla/models.py CHANGED
@@ -29,7 +29,7 @@ from sqlalchemy.types import LargeBinary
29
29
  # and it must be renamed to avoid conflicts with the policy package schema modules
30
30
  from rucio.common import schema as common_schema
31
31
  from rucio.common import utils
32
- from rucio.common.constants import TransferLimitDirection
32
+ from rucio.common.constants import DEFAULT_VO, TransferLimitDirection
33
33
  from rucio.common.types import InternalAccount, InternalScope # noqa: TCH001 (types are needed by SQLAlchemy)
34
34
  from rucio.db.sqla.constants import (
35
35
  AccountStatus,
@@ -563,7 +563,7 @@ class DeletedDataIdentifier(BASE, ModelBase):
563
563
 
564
564
 
565
565
  class UpdatedDID(BASE, ModelBase):
566
- """Represents the recently updated dids"""
566
+ """Represents the recently updated DIDs"""
567
567
  __tablename__ = 'updated_dids'
568
568
  id: Mapped[str] = mapped_column(GUID(), default=utils.generate_uuid)
569
569
  scope: Mapped[InternalScope] = mapped_column(InternalScopeString(common_schema.get_schema_value('SCOPE_LENGTH')))
@@ -776,7 +776,7 @@ class RSE(BASE, SoftModelBase):
776
776
  __tablename__ = 'rses'
777
777
  id: Mapped[str] = mapped_column(GUID(), default=utils.generate_uuid)
778
778
  rse: Mapped[str] = mapped_column(String(255))
779
- vo: Mapped[str] = mapped_column(String(3), nullable=False, server_default='def')
779
+ vo: Mapped[str] = mapped_column(String(3), nullable=False, server_default=DEFAULT_VO)
780
780
  rse_type: Mapped[RSEType] = mapped_column(Enum(RSEType, name='RSES_TYPE_CHK',
781
781
  create_constraint=True,
782
782
  values_callable=lambda obj: [e.value for e in obj]),
rucio/db/sqla/session.py CHANGED
@@ -54,7 +54,7 @@ if TYPE_CHECKING:
54
54
  try:
55
55
  main_script = os.path.basename(sys.argv[0])
56
56
  CURRENT_COMPONENT = main_script.split('-')[1]
57
- except:
57
+ except Exception:
58
58
  CURRENT_COMPONENT = None
59
59
 
60
60
  DATABASE_SECTION = 'database'
@@ -63,7 +63,7 @@ try:
63
63
  sql_connection = config_get('%s-database' % CURRENT_COMPONENT, 'default', check_config_table=False).strip()
64
64
  if sql_connection and len(sql_connection):
65
65
  DATABASE_SECTION = '%s-database' % CURRENT_COMPONENT
66
- except:
66
+ except Exception:
67
67
  pass
68
68
 
69
69
  DEFAULT_SCHEMA_NAME = config_get(DATABASE_SECTION, 'schema',
@@ -221,7 +221,7 @@ def get_engine() -> 'Engine':
221
221
  for param, param_type in config_params:
222
222
  try:
223
223
  params[param] = param_type(config_get(DATABASE_SECTION, param, check_config_table=False))
224
- except:
224
+ except Exception:
225
225
  pass
226
226
  _ENGINE = create_engine(sql_connection, **params)
227
227
  if 'mysql' in sql_connection:
@@ -406,7 +406,7 @@ def read_session(function: "Callable[P, R]"):
406
406
  except DatabaseError as error:
407
407
  session.rollback() # type: ignore
408
408
  raise DatabaseException(str(error))
409
- except:
409
+ except Exception:
410
410
  session.rollback() # type: ignore
411
411
  raise
412
412
  finally:
@@ -451,7 +451,7 @@ def stream_session(function: "Callable[P, R]"):
451
451
  except DatabaseError as error:
452
452
  session.rollback() # type: ignore
453
453
  raise DatabaseException(str(error))
454
- except:
454
+ except Exception:
455
455
  session.rollback() # type: ignore
456
456
  raise
457
457
  finally:
@@ -460,7 +460,7 @@ def stream_session(function: "Callable[P, R]"):
460
460
  try:
461
461
  for row in function(*args, session=session, **kwargs):
462
462
  yield row
463
- except:
463
+ except Exception:
464
464
  raise
465
465
  return _update_session_wrapper(new_funct, function)
466
466
 
@@ -491,7 +491,7 @@ def transactional_session(function: "Callable[P, R]") -> 'Callable':
491
491
  except DatabaseError as error:
492
492
  session.rollback() # type: ignore
493
493
  raise DatabaseException(str(error))
494
- except:
494
+ except Exception:
495
495
  session.rollback() # type: ignore
496
496
  raise
497
497
  finally:
rucio/db/sqla/util.py CHANGED
@@ -33,6 +33,7 @@ from sqlalchemy.sql.expression import select, text
33
33
  from rucio import alembicrevision
34
34
  from rucio.common.cache import MemcacheRegion
35
35
  from rucio.common.config import config_get, config_get_list
36
+ from rucio.common.constants import DEFAULT_VO
36
37
  from rucio.common.schema import get_schema_value
37
38
  from rucio.common.types import InternalAccount, LoggerFunction
38
39
  from rucio.common.utils import generate_uuid
@@ -136,7 +137,7 @@ def create_base_vo() -> None:
136
137
 
137
138
  session_scoped = get_session()
138
139
 
139
- vo = models.VO(vo='def', description='Default base VO', email='N/A')
140
+ vo = models.VO(vo=DEFAULT_VO, description='Default base VO', email='N/A')
140
141
  with session_scoped() as s:
141
142
  with s.begin():
142
143
  s.add_all([vo])
@@ -172,7 +173,7 @@ def create_root_account() -> None:
172
173
  else:
173
174
  access = 'root'
174
175
 
175
- account = models.Account(account=InternalAccount(access, 'def'), account_type=AccountType.SERVICE, status=AccountStatus.ACTIVE)
176
+ account = models.Account(account=InternalAccount(access, DEFAULT_VO), account_type=AccountType.SERVICE, status=AccountStatus.ACTIVE)
176
177
 
177
178
  salt = urandom(255)
178
179
  salted_password = salt + up_pwd.encode()