rucio 32.8.6__py3-none-any.whl → 35.8.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 (502) hide show
  1. rucio/__init__.py +0 -1
  2. rucio/alembicrevision.py +1 -2
  3. rucio/client/__init__.py +0 -1
  4. rucio/client/accountclient.py +45 -25
  5. rucio/client/accountlimitclient.py +37 -9
  6. rucio/client/baseclient.py +199 -154
  7. rucio/client/client.py +2 -3
  8. rucio/client/configclient.py +19 -6
  9. rucio/client/credentialclient.py +9 -4
  10. rucio/client/didclient.py +238 -63
  11. rucio/client/diracclient.py +13 -5
  12. rucio/client/downloadclient.py +162 -51
  13. rucio/client/exportclient.py +4 -4
  14. rucio/client/fileclient.py +3 -4
  15. rucio/client/importclient.py +4 -4
  16. rucio/client/lifetimeclient.py +21 -5
  17. rucio/client/lockclient.py +18 -8
  18. rucio/client/{metaclient.py → metaconventionsclient.py} +18 -15
  19. rucio/client/pingclient.py +0 -1
  20. rucio/client/replicaclient.py +15 -5
  21. rucio/client/requestclient.py +35 -19
  22. rucio/client/rseclient.py +133 -51
  23. rucio/client/ruleclient.py +29 -22
  24. rucio/client/scopeclient.py +8 -6
  25. rucio/client/subscriptionclient.py +47 -35
  26. rucio/client/touchclient.py +8 -4
  27. rucio/client/uploadclient.py +166 -82
  28. rucio/common/__init__.py +0 -1
  29. rucio/common/cache.py +4 -4
  30. rucio/common/config.py +52 -47
  31. rucio/common/constants.py +69 -2
  32. rucio/common/constraints.py +0 -1
  33. rucio/common/didtype.py +24 -22
  34. rucio/common/dumper/__init__.py +70 -41
  35. rucio/common/dumper/consistency.py +26 -22
  36. rucio/common/dumper/data_models.py +16 -23
  37. rucio/common/dumper/path_parsing.py +0 -1
  38. rucio/common/exception.py +281 -222
  39. rucio/common/extra.py +0 -1
  40. rucio/common/logging.py +54 -38
  41. rucio/common/pcache.py +122 -101
  42. rucio/common/plugins.py +153 -0
  43. rucio/common/policy.py +4 -4
  44. rucio/common/schema/__init__.py +17 -10
  45. rucio/common/schema/atlas.py +7 -5
  46. rucio/common/schema/belleii.py +7 -5
  47. rucio/common/schema/domatpc.py +7 -5
  48. rucio/common/schema/escape.py +7 -5
  49. rucio/common/schema/generic.py +8 -6
  50. rucio/common/schema/generic_multi_vo.py +7 -5
  51. rucio/common/schema/icecube.py +7 -5
  52. rucio/common/stomp_utils.py +0 -1
  53. rucio/common/stopwatch.py +0 -1
  54. rucio/common/test_rucio_server.py +2 -2
  55. rucio/common/types.py +262 -17
  56. rucio/common/utils.py +743 -451
  57. rucio/core/__init__.py +0 -1
  58. rucio/core/account.py +99 -29
  59. rucio/core/account_counter.py +89 -24
  60. rucio/core/account_limit.py +90 -24
  61. rucio/core/authentication.py +86 -29
  62. rucio/core/config.py +108 -38
  63. rucio/core/credential.py +14 -7
  64. rucio/core/did.py +680 -782
  65. rucio/core/did_meta_plugins/__init__.py +8 -6
  66. rucio/core/did_meta_plugins/did_column_meta.py +17 -12
  67. rucio/core/did_meta_plugins/did_meta_plugin_interface.py +60 -11
  68. rucio/core/did_meta_plugins/filter_engine.py +90 -50
  69. rucio/core/did_meta_plugins/json_meta.py +41 -16
  70. rucio/core/did_meta_plugins/mongo_meta.py +25 -8
  71. rucio/core/did_meta_plugins/postgres_meta.py +3 -4
  72. rucio/core/dirac.py +46 -17
  73. rucio/core/distance.py +66 -43
  74. rucio/core/exporter.py +5 -5
  75. rucio/core/heartbeat.py +181 -81
  76. rucio/core/identity.py +22 -12
  77. rucio/core/importer.py +23 -12
  78. rucio/core/lifetime_exception.py +32 -32
  79. rucio/core/lock.py +244 -142
  80. rucio/core/message.py +79 -38
  81. rucio/core/{meta.py → meta_conventions.py} +57 -44
  82. rucio/core/monitor.py +19 -13
  83. rucio/core/naming_convention.py +68 -27
  84. rucio/core/nongrid_trace.py +17 -5
  85. rucio/core/oidc.py +151 -29
  86. rucio/core/permission/__init__.py +18 -6
  87. rucio/core/permission/atlas.py +50 -35
  88. rucio/core/permission/belleii.py +6 -5
  89. rucio/core/permission/escape.py +8 -6
  90. rucio/core/permission/generic.py +82 -80
  91. rucio/core/permission/generic_multi_vo.py +9 -7
  92. rucio/core/quarantined_replica.py +91 -58
  93. rucio/core/replica.py +1303 -772
  94. rucio/core/replica_sorter.py +10 -12
  95. rucio/core/request.py +1133 -285
  96. rucio/core/rse.py +142 -102
  97. rucio/core/rse_counter.py +49 -18
  98. rucio/core/rse_expression_parser.py +6 -7
  99. rucio/core/rse_selector.py +41 -16
  100. rucio/core/rule.py +1538 -474
  101. rucio/core/rule_grouping.py +213 -68
  102. rucio/core/scope.py +50 -22
  103. rucio/core/subscription.py +92 -44
  104. rucio/core/topology.py +66 -24
  105. rucio/core/trace.py +42 -28
  106. rucio/core/transfer.py +543 -259
  107. rucio/core/vo.py +36 -18
  108. rucio/core/volatile_replica.py +59 -32
  109. rucio/daemons/__init__.py +0 -1
  110. rucio/daemons/abacus/__init__.py +0 -1
  111. rucio/daemons/abacus/account.py +29 -19
  112. rucio/daemons/abacus/collection_replica.py +21 -10
  113. rucio/daemons/abacus/rse.py +22 -12
  114. rucio/daemons/atropos/__init__.py +0 -1
  115. rucio/daemons/atropos/atropos.py +1 -2
  116. rucio/daemons/auditor/__init__.py +56 -28
  117. rucio/daemons/auditor/hdfs.py +17 -6
  118. rucio/daemons/auditor/srmdumps.py +116 -45
  119. rucio/daemons/automatix/__init__.py +0 -1
  120. rucio/daemons/automatix/automatix.py +30 -18
  121. rucio/daemons/badreplicas/__init__.py +0 -1
  122. rucio/daemons/badreplicas/minos.py +29 -18
  123. rucio/daemons/badreplicas/minos_temporary_expiration.py +5 -7
  124. rucio/daemons/badreplicas/necromancer.py +9 -13
  125. rucio/daemons/bb8/__init__.py +0 -1
  126. rucio/daemons/bb8/bb8.py +10 -13
  127. rucio/daemons/bb8/common.py +151 -154
  128. rucio/daemons/bb8/nuclei_background_rebalance.py +15 -9
  129. rucio/daemons/bb8/t2_background_rebalance.py +15 -8
  130. rucio/daemons/c3po/__init__.py +0 -1
  131. rucio/daemons/c3po/algorithms/__init__.py +0 -1
  132. rucio/daemons/c3po/algorithms/simple.py +8 -5
  133. rucio/daemons/c3po/algorithms/t2_free_space.py +10 -7
  134. rucio/daemons/c3po/algorithms/t2_free_space_only_pop.py +10 -7
  135. rucio/daemons/c3po/algorithms/t2_free_space_only_pop_with_network.py +30 -15
  136. rucio/daemons/c3po/c3po.py +81 -52
  137. rucio/daemons/c3po/collectors/__init__.py +0 -1
  138. rucio/daemons/c3po/collectors/agis.py +17 -17
  139. rucio/daemons/c3po/collectors/free_space.py +32 -13
  140. rucio/daemons/c3po/collectors/jedi_did.py +14 -5
  141. rucio/daemons/c3po/collectors/mock_did.py +11 -6
  142. rucio/daemons/c3po/collectors/network_metrics.py +12 -4
  143. rucio/daemons/c3po/collectors/workload.py +21 -19
  144. rucio/daemons/c3po/utils/__init__.py +0 -1
  145. rucio/daemons/c3po/utils/dataset_cache.py +15 -5
  146. rucio/daemons/c3po/utils/expiring_dataset_cache.py +16 -5
  147. rucio/daemons/c3po/utils/expiring_list.py +6 -7
  148. rucio/daemons/c3po/utils/popularity.py +5 -2
  149. rucio/daemons/c3po/utils/timeseries.py +25 -12
  150. rucio/daemons/cache/__init__.py +0 -1
  151. rucio/daemons/cache/consumer.py +21 -15
  152. rucio/daemons/common.py +42 -18
  153. rucio/daemons/conveyor/__init__.py +0 -1
  154. rucio/daemons/conveyor/common.py +69 -37
  155. rucio/daemons/conveyor/finisher.py +83 -46
  156. rucio/daemons/conveyor/poller.py +101 -69
  157. rucio/daemons/conveyor/preparer.py +35 -28
  158. rucio/daemons/conveyor/receiver.py +64 -21
  159. rucio/daemons/conveyor/stager.py +33 -28
  160. rucio/daemons/conveyor/submitter.py +71 -47
  161. rucio/daemons/conveyor/throttler.py +99 -35
  162. rucio/daemons/follower/__init__.py +0 -1
  163. rucio/daemons/follower/follower.py +12 -8
  164. rucio/daemons/hermes/__init__.py +0 -1
  165. rucio/daemons/hermes/hermes.py +57 -21
  166. rucio/daemons/judge/__init__.py +0 -1
  167. rucio/daemons/judge/cleaner.py +27 -17
  168. rucio/daemons/judge/evaluator.py +31 -18
  169. rucio/daemons/judge/injector.py +31 -23
  170. rucio/daemons/judge/repairer.py +28 -18
  171. rucio/daemons/oauthmanager/__init__.py +0 -1
  172. rucio/daemons/oauthmanager/oauthmanager.py +7 -8
  173. rucio/daemons/reaper/__init__.py +0 -1
  174. rucio/daemons/reaper/dark_reaper.py +15 -9
  175. rucio/daemons/reaper/reaper.py +109 -67
  176. rucio/daemons/replicarecoverer/__init__.py +0 -1
  177. rucio/daemons/replicarecoverer/suspicious_replica_recoverer.py +255 -116
  178. rucio/{api → daemons/rsedecommissioner}/__init__.py +0 -1
  179. rucio/daemons/rsedecommissioner/config.py +81 -0
  180. rucio/daemons/rsedecommissioner/profiles/__init__.py +24 -0
  181. rucio/daemons/rsedecommissioner/profiles/atlas.py +60 -0
  182. rucio/daemons/rsedecommissioner/profiles/generic.py +451 -0
  183. rucio/daemons/rsedecommissioner/profiles/types.py +92 -0
  184. rucio/daemons/rsedecommissioner/rse_decommissioner.py +280 -0
  185. rucio/daemons/storage/__init__.py +0 -1
  186. rucio/daemons/storage/consistency/__init__.py +0 -1
  187. rucio/daemons/storage/consistency/actions.py +152 -59
  188. rucio/daemons/tracer/__init__.py +0 -1
  189. rucio/daemons/tracer/kronos.py +47 -24
  190. rucio/daemons/transmogrifier/__init__.py +0 -1
  191. rucio/daemons/transmogrifier/transmogrifier.py +35 -26
  192. rucio/daemons/undertaker/__init__.py +0 -1
  193. rucio/daemons/undertaker/undertaker.py +10 -10
  194. rucio/db/__init__.py +0 -1
  195. rucio/db/sqla/__init__.py +16 -2
  196. rucio/db/sqla/constants.py +10 -1
  197. rucio/db/sqla/migrate_repo/__init__.py +0 -1
  198. rucio/db/sqla/migrate_repo/env.py +0 -1
  199. rucio/db/sqla/migrate_repo/versions/01eaf73ab656_add_new_rule_notification_state_progress.py +0 -1
  200. rucio/db/sqla/migrate_repo/versions/0437a40dbfd1_add_eol_at_in_rules.py +0 -3
  201. rucio/db/sqla/migrate_repo/versions/0f1adb7a599a_create_transfer_hops_table.py +1 -3
  202. rucio/db/sqla/migrate_repo/versions/102efcf145f4_added_stuck_at_column_to_rules.py +0 -3
  203. rucio/db/sqla/migrate_repo/versions/13d4f70c66a9_introduce_transfer_limits.py +1 -3
  204. rucio/db/sqla/migrate_repo/versions/140fef722e91_cleanup_distances_table.py +1 -3
  205. rucio/db/sqla/migrate_repo/versions/14ec5aeb64cf_add_request_external_host.py +0 -3
  206. rucio/db/sqla/migrate_repo/versions/156fb5b5a14_add_request_type_to_requests_idx.py +1 -4
  207. rucio/db/sqla/migrate_repo/versions/1677d4d803c8_split_rse_availability_into_multiple.py +0 -1
  208. rucio/db/sqla/migrate_repo/versions/16a0aca82e12_create_index_on_table_replicas_path.py +0 -2
  209. rucio/db/sqla/migrate_repo/versions/1803333ac20f_adding_provenance_and_phys_group.py +0 -1
  210. rucio/db/sqla/migrate_repo/versions/1a29d6a9504c_add_didtype_chck_to_requests.py +0 -1
  211. rucio/db/sqla/migrate_repo/versions/1a80adff031a_create_index_on_rules_hist_recent.py +0 -2
  212. rucio/db/sqla/migrate_repo/versions/1c45d9730ca6_increase_identity_length.py +0 -1
  213. rucio/db/sqla/migrate_repo/versions/1d1215494e95_add_quarantined_replicas_table.py +1 -3
  214. rucio/db/sqla/migrate_repo/versions/1d96f484df21_asynchronous_rules_and_rule_approval.py +0 -1
  215. rucio/db/sqla/migrate_repo/versions/1f46c5f240ac_add_bytes_column_to_bad_replicas.py +0 -3
  216. rucio/db/sqla/migrate_repo/versions/1fc15ab60d43_add_message_history_table.py +0 -1
  217. rucio/db/sqla/migrate_repo/versions/2190e703eb6e_move_rse_settings_to_rse_attributes.py +1 -2
  218. rucio/db/sqla/migrate_repo/versions/21d6b9dc9961_add_mismatch_scheme_state_to_requests.py +0 -1
  219. rucio/db/sqla/migrate_repo/versions/22cf51430c78_add_availability_column_to_table_rses.py +0 -3
  220. rucio/db/sqla/migrate_repo/versions/22d887e4ec0a_create_sources_table.py +1 -3
  221. rucio/db/sqla/migrate_repo/versions/25821a8a45a3_remove_unique_constraint_on_requests.py +1 -4
  222. rucio/db/sqla/migrate_repo/versions/25fc855625cf_added_unique_constraint_to_rules.py +0 -2
  223. rucio/db/sqla/migrate_repo/versions/269fee20dee9_add_repair_cnt_to_locks.py +0 -3
  224. rucio/db/sqla/migrate_repo/versions/271a46ea6244_add_ignore_availability_column_to_rules.py +0 -3
  225. rucio/db/sqla/migrate_repo/versions/277b5fbb41d3_switch_heartbeats_executable.py +1 -2
  226. rucio/db/sqla/migrate_repo/versions/27e3a68927fb_remove_replicas_tombstone_and_replicas_.py +0 -1
  227. rucio/db/sqla/migrate_repo/versions/2854cd9e168_added_rule_id_column.py +0 -1
  228. rucio/db/sqla/migrate_repo/versions/295289b5a800_processed_by_and__at_in_requests.py +0 -2
  229. rucio/db/sqla/migrate_repo/versions/2962ece31cf4_add_nbaccesses_column_in_the_did_table.py +0 -3
  230. rucio/db/sqla/migrate_repo/versions/2af3291ec4c_added_replicas_history_table.py +1 -3
  231. rucio/db/sqla/migrate_repo/versions/2b69addda658_add_columns_for_third_party_copy_read_.py +0 -2
  232. rucio/db/sqla/migrate_repo/versions/2b8e7bcb4783_add_config_table.py +1 -4
  233. rucio/db/sqla/migrate_repo/versions/2ba5229cb54c_add_submitted_at_to_requests_table.py +0 -3
  234. rucio/db/sqla/migrate_repo/versions/2cbee484dcf9_added_column_volume_to_rse_transfer_.py +1 -4
  235. rucio/db/sqla/migrate_repo/versions/2edee4a83846_add_source_to_requests_and_requests_.py +0 -1
  236. rucio/db/sqla/migrate_repo/versions/2eef46be23d4_change_tokens_pk.py +1 -3
  237. rucio/db/sqla/migrate_repo/versions/2f648fc909f3_index_in_rule_history_on_scope_name.py +0 -2
  238. rucio/db/sqla/migrate_repo/versions/3082b8cef557_add_naming_convention_table_and_closed_.py +1 -3
  239. rucio/db/sqla/migrate_repo/versions/30fa38b6434e_add_index_on_service_column_in_the_message_table.py +1 -3
  240. rucio/db/sqla/migrate_repo/versions/3152492b110b_added_staging_area_column.py +1 -2
  241. rucio/db/sqla/migrate_repo/versions/32c7d2783f7e_create_bad_replicas_table.py +1 -3
  242. rucio/db/sqla/migrate_repo/versions/3345511706b8_replicas_table_pk_definition_is_in_.py +1 -3
  243. rucio/db/sqla/migrate_repo/versions/35ef10d1e11b_change_index_on_table_requests.py +0 -2
  244. rucio/db/sqla/migrate_repo/versions/379a19b5332d_create_rse_limits_table.py +1 -3
  245. rucio/db/sqla/migrate_repo/versions/384b96aa0f60_created_rule_history_tables.py +2 -3
  246. rucio/db/sqla/migrate_repo/versions/3ac1660a1a72_extend_distance_table.py +0 -3
  247. rucio/db/sqla/migrate_repo/versions/3ad36e2268b0_create_collection_replicas_updates_table.py +1 -4
  248. rucio/db/sqla/migrate_repo/versions/3c9df354071b_extend_waiting_request_state.py +0 -1
  249. rucio/db/sqla/migrate_repo/versions/3d9813fab443_add_a_new_state_lost_in_badfilesstatus.py +0 -1
  250. rucio/db/sqla/migrate_repo/versions/40ad39ce3160_add_transferred_at_to_requests_table.py +0 -3
  251. rucio/db/sqla/migrate_repo/versions/4207be2fd914_add_notification_column_to_rules.py +0 -1
  252. rucio/db/sqla/migrate_repo/versions/42db2617c364_create_index_on_requests_external_id.py +0 -2
  253. rucio/db/sqla/migrate_repo/versions/436827b13f82_added_column_activity_to_table_requests.py +0 -3
  254. rucio/db/sqla/migrate_repo/versions/44278720f774_update_requests_typ_sta_upd_idx_index.py +0 -2
  255. rucio/db/sqla/migrate_repo/versions/45378a1e76a8_create_collection_replica_table.py +2 -4
  256. rucio/db/sqla/migrate_repo/versions/469d262be19_removing_created_at_index.py +0 -2
  257. rucio/db/sqla/migrate_repo/versions/4783c1f49cb4_create_distance_table.py +1 -3
  258. rucio/db/sqla/migrate_repo/versions/49a21b4d4357_create_index_on_table_tokens.py +1 -4
  259. rucio/db/sqla/migrate_repo/versions/4a2cbedda8b9_add_source_replica_expression_column_to_.py +0 -3
  260. rucio/db/sqla/migrate_repo/versions/4a7182d9578b_added_bytes_length_accessed_at_columns.py +0 -3
  261. rucio/db/sqla/migrate_repo/versions/4bab9edd01fc_create_index_on_requests_rule_id.py +0 -2
  262. rucio/db/sqla/migrate_repo/versions/4c3a4acfe006_new_attr_account_table.py +1 -3
  263. rucio/db/sqla/migrate_repo/versions/4cf0a2e127d4_adding_transient_metadata.py +0 -3
  264. rucio/db/sqla/migrate_repo/versions/4df2c5ddabc0_remove_temporary_dids.py +55 -0
  265. rucio/db/sqla/migrate_repo/versions/50280c53117c_add_qos_class_to_rse.py +0 -2
  266. rucio/db/sqla/migrate_repo/versions/52153819589c_add_rse_id_to_replicas_table.py +0 -2
  267. rucio/db/sqla/migrate_repo/versions/52fd9f4916fa_added_activity_to_rules.py +0 -3
  268. rucio/db/sqla/migrate_repo/versions/53b479c3cb0f_fix_did_meta_table_missing_updated_at_.py +0 -3
  269. rucio/db/sqla/migrate_repo/versions/5673b4b6e843_add_wfms_metadata_to_rule_tables.py +0 -3
  270. rucio/db/sqla/migrate_repo/versions/575767d9f89_added_source_history_table.py +1 -2
  271. rucio/db/sqla/migrate_repo/versions/58bff7008037_add_started_at_to_requests.py +0 -3
  272. rucio/db/sqla/migrate_repo/versions/58c8b78301ab_rename_callback_to_message.py +1 -3
  273. rucio/db/sqla/migrate_repo/versions/5f139f77382a_added_child_rule_id_column.py +1 -3
  274. rucio/db/sqla/migrate_repo/versions/688ef1840840_adding_did_meta_table.py +1 -2
  275. rucio/db/sqla/migrate_repo/versions/6e572a9bfbf3_add_new_split_container_column_to_rules.py +0 -3
  276. rucio/db/sqla/migrate_repo/versions/70587619328_add_comment_column_for_subscriptions.py +0 -3
  277. rucio/db/sqla/migrate_repo/versions/739064d31565_remove_history_table_pks.py +1 -2
  278. rucio/db/sqla/migrate_repo/versions/7541902bf173_add_didsfollowed_and_followevents_table.py +2 -4
  279. rucio/db/sqla/migrate_repo/versions/7ec22226cdbf_new_replica_state_for_temporary_.py +0 -1
  280. rucio/db/sqla/migrate_repo/versions/810a41685bc1_added_columns_rse_transfer_limits.py +1 -4
  281. rucio/db/sqla/migrate_repo/versions/83f991c63a93_correct_rse_expression_length.py +0 -2
  282. rucio/db/sqla/migrate_repo/versions/8523998e2e76_increase_size_of_extended_attributes_.py +0 -3
  283. rucio/db/sqla/migrate_repo/versions/8ea9122275b1_adding_missing_function_based_indices.py +1 -2
  284. rucio/db/sqla/migrate_repo/versions/90f47792bb76_add_clob_payload_to_messages.py +0 -3
  285. rucio/db/sqla/migrate_repo/versions/914b8f02df38_new_table_for_lifetime_model_exceptions.py +1 -3
  286. rucio/db/sqla/migrate_repo/versions/94a5961ddbf2_add_estimator_columns.py +0 -3
  287. rucio/db/sqla/migrate_repo/versions/9a1b149a2044_add_saml_identity_type.py +0 -1
  288. rucio/db/sqla/migrate_repo/versions/9a45bc4ea66d_add_vp_table.py +1 -2
  289. rucio/db/sqla/migrate_repo/versions/9eb936a81eb1_true_is_true.py +0 -2
  290. rucio/db/sqla/migrate_repo/versions/a08fa8de1545_transfer_stats_table.py +55 -0
  291. rucio/db/sqla/migrate_repo/versions/a118956323f8_added_vo_table_and_vo_col_to_rse.py +1 -3
  292. rucio/db/sqla/migrate_repo/versions/a193a275255c_add_status_column_in_messages.py +0 -2
  293. rucio/db/sqla/migrate_repo/versions/a5f6f6e928a7_1_7_0.py +1 -4
  294. rucio/db/sqla/migrate_repo/versions/a616581ee47_added_columns_to_table_requests.py +0 -1
  295. rucio/db/sqla/migrate_repo/versions/a6eb23955c28_state_idx_non_functional.py +0 -1
  296. rucio/db/sqla/migrate_repo/versions/a74275a1ad30_added_global_quota_table.py +1 -3
  297. rucio/db/sqla/migrate_repo/versions/a93e4e47bda_heartbeats.py +1 -4
  298. rucio/db/sqla/migrate_repo/versions/ae2a56fcc89_added_comment_column_to_rules.py +0 -1
  299. rucio/db/sqla/migrate_repo/versions/b0070f3695c8_add_deletedidmeta_table.py +57 -0
  300. rucio/db/sqla/migrate_repo/versions/b4293a99f344_added_column_identity_to_table_tokens.py +0 -3
  301. rucio/db/sqla/migrate_repo/versions/b5493606bbf5_fix_primary_key_for_subscription_history.py +41 -0
  302. rucio/db/sqla/migrate_repo/versions/b7d287de34fd_removal_of_replicastate_source.py +1 -2
  303. rucio/db/sqla/migrate_repo/versions/b818052fa670_add_index_to_quarantined_replicas.py +1 -3
  304. rucio/db/sqla/migrate_repo/versions/b8caac94d7f0_add_comments_column_for_subscriptions_.py +0 -3
  305. rucio/db/sqla/migrate_repo/versions/b96a1c7e1cc4_new_bad_pfns_table_and_bad_replicas_.py +1 -5
  306. rucio/db/sqla/migrate_repo/versions/bb695f45c04_extend_request_state.py +1 -3
  307. rucio/db/sqla/migrate_repo/versions/bc68e9946deb_add_staging_timestamps_to_request.py +0 -3
  308. rucio/db/sqla/migrate_repo/versions/bf3baa1c1474_correct_pk_and_idx_for_history_tables.py +1 -3
  309. rucio/db/sqla/migrate_repo/versions/c0937668555f_add_qos_policy_map_table.py +1 -2
  310. rucio/db/sqla/migrate_repo/versions/c129ccdb2d5_add_lumiblocknr_to_dids.py +0 -3
  311. rucio/db/sqla/migrate_repo/versions/ccdbcd48206e_add_did_type_column_index_on_did_meta_.py +1 -4
  312. rucio/db/sqla/migrate_repo/versions/cebad904c4dd_new_payload_column_for_heartbeats.py +1 -2
  313. rucio/db/sqla/migrate_repo/versions/d1189a09c6e0_oauth2_0_and_jwt_feature_support_adding_.py +1 -4
  314. rucio/db/sqla/migrate_repo/versions/d23453595260_extend_request_state_for_preparer.py +1 -3
  315. rucio/db/sqla/migrate_repo/versions/d6dceb1de2d_added_purge_column_to_rules.py +1 -4
  316. rucio/db/sqla/migrate_repo/versions/d6e2c3b2cf26_remove_third_party_copy_column_from_rse.py +0 -2
  317. rucio/db/sqla/migrate_repo/versions/d91002c5841_new_account_limits_table.py +1 -3
  318. rucio/db/sqla/migrate_repo/versions/e138c364ebd0_extending_columns_for_filter_and_.py +0 -3
  319. rucio/db/sqla/migrate_repo/versions/e59300c8b179_support_for_archive.py +1 -3
  320. rucio/db/sqla/migrate_repo/versions/f1b14a8c2ac1_postgres_use_check_constraints.py +0 -1
  321. rucio/db/sqla/migrate_repo/versions/f41ffe206f37_oracle_global_temporary_tables.py +1 -2
  322. rucio/db/sqla/migrate_repo/versions/f85a2962b021_adding_transfertool_column_to_requests_.py +1 -3
  323. rucio/db/sqla/migrate_repo/versions/fa7a7d78b602_increase_refresh_token_size.py +0 -2
  324. rucio/db/sqla/migrate_repo/versions/fb28a95fe288_add_replicas_rse_id_tombstone_idx.py +0 -1
  325. rucio/db/sqla/migrate_repo/versions/fe1a65b176c9_set_third_party_copy_read_and_write_.py +1 -2
  326. rucio/db/sqla/migrate_repo/versions/fe8ea2fa9788_added_third_party_copy_column_to_rse_.py +0 -3
  327. rucio/db/sqla/models.py +122 -216
  328. rucio/db/sqla/sautils.py +12 -5
  329. rucio/db/sqla/session.py +71 -43
  330. rucio/db/sqla/types.py +3 -4
  331. rucio/db/sqla/util.py +91 -69
  332. rucio/gateway/__init__.py +13 -0
  333. rucio/{api → gateway}/account.py +119 -46
  334. rucio/{api → gateway}/account_limit.py +12 -13
  335. rucio/{api → gateway}/authentication.py +106 -33
  336. rucio/{api → gateway}/config.py +12 -13
  337. rucio/{api → gateway}/credential.py +15 -4
  338. rucio/{api → gateway}/did.py +384 -140
  339. rucio/{api → gateway}/dirac.py +16 -6
  340. rucio/{api → gateway}/exporter.py +3 -4
  341. rucio/{api → gateway}/heartbeat.py +17 -5
  342. rucio/{api → gateway}/identity.py +63 -19
  343. rucio/{api → gateway}/importer.py +3 -4
  344. rucio/{api → gateway}/lifetime_exception.py +35 -10
  345. rucio/{api → gateway}/lock.py +34 -12
  346. rucio/{api/meta.py → gateway/meta_conventions.py} +18 -16
  347. rucio/{api → gateway}/permission.py +4 -5
  348. rucio/{api → gateway}/quarantined_replica.py +13 -4
  349. rucio/{api → gateway}/replica.py +12 -11
  350. rucio/{api → gateway}/request.py +129 -28
  351. rucio/{api → gateway}/rse.py +11 -12
  352. rucio/{api → gateway}/rule.py +117 -35
  353. rucio/{api → gateway}/scope.py +24 -14
  354. rucio/{api → gateway}/subscription.py +65 -43
  355. rucio/{api → gateway}/vo.py +17 -7
  356. rucio/rse/__init__.py +3 -4
  357. rucio/rse/protocols/__init__.py +0 -1
  358. rucio/rse/protocols/bittorrent.py +184 -0
  359. rucio/rse/protocols/cache.py +1 -2
  360. rucio/rse/protocols/dummy.py +1 -2
  361. rucio/rse/protocols/gfal.py +12 -10
  362. rucio/rse/protocols/globus.py +7 -7
  363. rucio/rse/protocols/gsiftp.py +2 -3
  364. rucio/rse/protocols/http_cache.py +1 -2
  365. rucio/rse/protocols/mock.py +1 -2
  366. rucio/rse/protocols/ngarc.py +1 -2
  367. rucio/rse/protocols/posix.py +12 -13
  368. rucio/rse/protocols/protocol.py +116 -52
  369. rucio/rse/protocols/rclone.py +6 -7
  370. rucio/rse/protocols/rfio.py +4 -5
  371. rucio/rse/protocols/srm.py +9 -10
  372. rucio/rse/protocols/ssh.py +8 -9
  373. rucio/rse/protocols/storm.py +2 -3
  374. rucio/rse/protocols/webdav.py +17 -14
  375. rucio/rse/protocols/xrootd.py +23 -17
  376. rucio/rse/rsemanager.py +19 -7
  377. rucio/tests/__init__.py +0 -1
  378. rucio/tests/common.py +43 -17
  379. rucio/tests/common_server.py +3 -3
  380. rucio/transfertool/__init__.py +0 -1
  381. rucio/transfertool/bittorrent.py +199 -0
  382. rucio/transfertool/bittorrent_driver.py +52 -0
  383. rucio/transfertool/bittorrent_driver_qbittorrent.py +133 -0
  384. rucio/transfertool/fts3.py +250 -138
  385. rucio/transfertool/fts3_plugins.py +152 -0
  386. rucio/transfertool/globus.py +9 -8
  387. rucio/transfertool/globus_library.py +1 -2
  388. rucio/transfertool/mock.py +21 -12
  389. rucio/transfertool/transfertool.py +33 -24
  390. rucio/vcsversion.py +4 -4
  391. rucio/version.py +5 -13
  392. rucio/web/__init__.py +0 -1
  393. rucio/web/rest/__init__.py +0 -1
  394. rucio/web/rest/flaskapi/__init__.py +0 -1
  395. rucio/web/rest/flaskapi/authenticated_bp.py +0 -1
  396. rucio/web/rest/flaskapi/v1/__init__.py +0 -1
  397. rucio/web/rest/flaskapi/v1/accountlimits.py +15 -13
  398. rucio/web/rest/flaskapi/v1/accounts.py +49 -48
  399. rucio/web/rest/flaskapi/v1/archives.py +12 -10
  400. rucio/web/rest/flaskapi/v1/auth.py +146 -144
  401. rucio/web/rest/flaskapi/v1/common.py +82 -41
  402. rucio/web/rest/flaskapi/v1/config.py +5 -6
  403. rucio/web/rest/flaskapi/v1/credentials.py +7 -8
  404. rucio/web/rest/flaskapi/v1/dids.py +158 -28
  405. rucio/web/rest/flaskapi/v1/dirac.py +8 -8
  406. rucio/web/rest/flaskapi/v1/export.py +3 -5
  407. rucio/web/rest/flaskapi/v1/heartbeats.py +3 -5
  408. rucio/web/rest/flaskapi/v1/identities.py +3 -5
  409. rucio/web/rest/flaskapi/v1/import.py +3 -4
  410. rucio/web/rest/flaskapi/v1/lifetime_exceptions.py +6 -9
  411. rucio/web/rest/flaskapi/v1/locks.py +2 -4
  412. rucio/web/rest/flaskapi/v1/main.py +10 -2
  413. rucio/web/rest/flaskapi/v1/{meta.py → meta_conventions.py} +26 -11
  414. rucio/web/rest/flaskapi/v1/metrics.py +1 -2
  415. rucio/web/rest/flaskapi/v1/nongrid_traces.py +4 -4
  416. rucio/web/rest/flaskapi/v1/ping.py +6 -7
  417. rucio/web/rest/flaskapi/v1/redirect.py +8 -9
  418. rucio/web/rest/flaskapi/v1/replicas.py +43 -19
  419. rucio/web/rest/flaskapi/v1/requests.py +178 -21
  420. rucio/web/rest/flaskapi/v1/rses.py +61 -26
  421. rucio/web/rest/flaskapi/v1/rules.py +48 -18
  422. rucio/web/rest/flaskapi/v1/scopes.py +3 -5
  423. rucio/web/rest/flaskapi/v1/subscriptions.py +22 -18
  424. rucio/web/rest/flaskapi/v1/traces.py +4 -4
  425. rucio/web/rest/flaskapi/v1/types.py +20 -0
  426. rucio/web/rest/flaskapi/v1/vos.py +3 -5
  427. rucio/web/rest/main.py +0 -1
  428. rucio/web/rest/metrics.py +0 -1
  429. rucio/web/rest/ping.py +27 -0
  430. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/ldap.cfg.template +1 -1
  431. rucio-35.8.0.data/data/rucio/requirements.server.txt +268 -0
  432. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/tools/bootstrap.py +3 -3
  433. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/tools/merge_rucio_configs.py +2 -5
  434. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/tools/reset_database.py +3 -3
  435. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio +87 -85
  436. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-abacus-account +0 -1
  437. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-abacus-collection-replica +0 -1
  438. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-abacus-rse +0 -1
  439. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-admin +45 -32
  440. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-atropos +0 -1
  441. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-auditor +13 -7
  442. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-automatix +1 -2
  443. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-bb8 +0 -1
  444. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-c3po +0 -1
  445. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-cache-client +2 -3
  446. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-cache-consumer +0 -1
  447. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-conveyor-finisher +1 -2
  448. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-conveyor-poller +0 -1
  449. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-conveyor-preparer +0 -1
  450. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-conveyor-receiver +0 -1
  451. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-conveyor-stager +0 -1
  452. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-conveyor-submitter +2 -3
  453. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-conveyor-throttler +0 -1
  454. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-dark-reaper +0 -1
  455. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-dumper +11 -10
  456. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-follower +0 -1
  457. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-hermes +0 -1
  458. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-judge-cleaner +0 -1
  459. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-judge-evaluator +2 -3
  460. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-judge-injector +0 -1
  461. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-judge-repairer +0 -1
  462. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-kronos +1 -3
  463. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-minos +0 -1
  464. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-minos-temporary-expiration +0 -1
  465. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-necromancer +1 -2
  466. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-oauth-manager +2 -3
  467. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-reaper +0 -1
  468. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-replica-recoverer +6 -7
  469. rucio-35.8.0.data/scripts/rucio-rse-decommissioner +66 -0
  470. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-storage-consistency-actions +0 -1
  471. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-transmogrifier +0 -1
  472. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-undertaker +1 -2
  473. rucio-35.8.0.dist-info/METADATA +72 -0
  474. rucio-35.8.0.dist-info/RECORD +493 -0
  475. {rucio-32.8.6.dist-info → rucio-35.8.0.dist-info}/WHEEL +1 -1
  476. {rucio-32.8.6.dist-info → rucio-35.8.0.dist-info}/licenses/AUTHORS.rst +3 -0
  477. rucio/api/temporary_did.py +0 -49
  478. rucio/common/schema/cms.py +0 -478
  479. rucio/common/schema/lsst.py +0 -423
  480. rucio/core/permission/cms.py +0 -1166
  481. rucio/core/temporary_did.py +0 -188
  482. rucio/daemons/reaper/light_reaper.py +0 -255
  483. rucio/web/rest/flaskapi/v1/tmp_dids.py +0 -115
  484. rucio-32.8.6.data/data/rucio/requirements.txt +0 -55
  485. rucio-32.8.6.data/scripts/rucio-light-reaper +0 -53
  486. rucio-32.8.6.dist-info/METADATA +0 -83
  487. rucio-32.8.6.dist-info/RECORD +0 -481
  488. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/alembic.ini.template +0 -0
  489. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/alembic_offline.ini.template +0 -0
  490. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/globus-config.yml.template +0 -0
  491. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/mail_templates/rule_approval_request.tmpl +0 -0
  492. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/mail_templates/rule_approved_admin.tmpl +0 -0
  493. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/mail_templates/rule_approved_user.tmpl +0 -0
  494. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/mail_templates/rule_denied_admin.tmpl +0 -0
  495. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/mail_templates/rule_denied_user.tmpl +0 -0
  496. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/mail_templates/rule_ok_notification.tmpl +0 -0
  497. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/rse-accounts.cfg.template +0 -0
  498. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/rucio.cfg.atlas.client.template +0 -0
  499. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/rucio.cfg.template +0 -0
  500. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/rucio_multi_vo.cfg.template +0 -0
  501. {rucio-32.8.6.dist-info → rucio-35.8.0.dist-info}/licenses/LICENSE +0 -0
  502. {rucio-32.8.6.dist-info → rucio-35.8.0.dist-info}/top_level.txt +0 -0
@@ -1,4 +1,3 @@
1
- # -*- coding: utf-8 -*-
2
1
  # Copyright European Organization for Nuclear Research (CERN) since 2012
3
2
  #
4
3
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,21 +13,26 @@
14
13
  # limitations under the License.
15
14
 
16
15
  import logging
16
+ from collections.abc import Sequence
17
17
  from datetime import datetime
18
- from typing import TYPE_CHECKING
18
+ from typing import TYPE_CHECKING, Any, Optional
19
19
 
20
- from sqlalchemy import func
21
- from sqlalchemy.orm.exc import NoResultFound
20
+ from sqlalchemy import and_, func, select
21
+ from sqlalchemy.exc import NoResultFound
22
22
 
23
23
  import rucio.core.did
24
24
  import rucio.core.lock
25
25
  import rucio.core.replica
26
26
  from rucio.common.config import config_get_int
27
+ from rucio.common.constants import RseAttr
27
28
  from rucio.common.exception import InsufficientTargetRSEs
28
- from rucio.core import account_counter, rse_counter, request as request_core
29
+ from rucio.common.types import InternalScope
30
+ from rucio.core import account_counter, rse_counter
31
+ from rucio.core import request as request_core
29
32
  from rucio.core.rse import get_rse, get_rse_attribute, get_rse_name
33
+ from rucio.core.rse_selector import RSESelector
30
34
  from rucio.db.sqla import models
31
- from rucio.db.sqla.constants import LockState, RuleGrouping, ReplicaState, RequestType, DIDType, OBSOLETE
35
+ from rucio.db.sqla.constants import OBSOLETE, DIDType, LockState, ReplicaState, RequestType, RuleGrouping
32
36
  from rucio.db.sqla.session import transactional_session
33
37
 
34
38
  if TYPE_CHECKING:
@@ -36,7 +40,20 @@ if TYPE_CHECKING:
36
40
 
37
41
 
38
42
  @transactional_session
39
- def apply_rule_grouping(datasetfiles, locks, replicas, source_replicas, rseselector, rule, preferred_rse_ids=[], source_rses=[], *, session: "Session"):
43
+ def apply_rule_grouping(
44
+ datasetfiles: Sequence[dict[str, Any]],
45
+ locks: dict[tuple[InternalScope, str], Sequence[models.ReplicaLock]],
46
+ replicas: dict[tuple[InternalScope, str], Sequence[models.CollectionReplica]],
47
+ source_replicas: dict[tuple[InternalScope, str], Sequence[models.CollectionReplica]],
48
+ rseselector: RSESelector,
49
+ rule: models.ReplicationRule,
50
+ preferred_rse_ids: Optional[Sequence[str]] = None,
51
+ source_rses: Optional[Sequence[str]] = None,
52
+ *,
53
+ session: "Session"
54
+ ) -> tuple[dict[str, list[dict[str, models.RSEFileAssociation]]],
55
+ dict[str, list[dict[str, models.ReplicaLock]]],
56
+ list[dict[str, Any]]]:
40
57
  """
41
58
  Apply rule grouping to files.
42
59
 
@@ -47,9 +64,9 @@ def apply_rule_grouping(datasetfiles, locks, replicas, source_replicas, rseselec
47
64
  :param rseselector: The RSESelector to be used.
48
65
  :param rule: The rule object.
49
66
  :param preferred_rse_ids: Preferred RSE's to select.
50
- :param source_rses: RSE ids of eglible source replicas.
67
+ :param source_rses: RSE ids of eligible source replicas.
51
68
  :param session: Session of the db.
52
- :returns: List of replicas to create, List of locks to create, List of transfers to create
69
+ :returns: Dict of replicas to create, Dict of locks to create, List of transfers to create
53
70
  :raises: InsufficientQuota, InsufficientTargetRSEs, RSEOverQuota
54
71
  :attention: This method modifies the contents of the locks and replicas input parameters.
55
72
  """
@@ -58,8 +75,10 @@ def apply_rule_grouping(datasetfiles, locks, replicas, source_replicas, rseselec
58
75
  # replicas_to_create = {'rse_id': [replicas]}
59
76
  # transfers_to_create = [{'dest_rse_id':, 'scope':, 'name':, 'request_type':, 'metadata':}]
60
77
 
78
+ preferred_rse_ids = preferred_rse_ids or []
79
+ source_rses = source_rses or []
61
80
  if rule.grouping == RuleGrouping.NONE:
62
- replicas_to_create, locks_to_create,\
81
+ replicas_to_create, locks_to_create, \
63
82
  transfers_to_create = __apply_rule_to_files_none_grouping(datasetfiles=datasetfiles,
64
83
  locks=locks,
65
84
  replicas=replicas,
@@ -70,7 +89,7 @@ def apply_rule_grouping(datasetfiles, locks, replicas, source_replicas, rseselec
70
89
  source_rses=source_rses,
71
90
  session=session)
72
91
  elif rule.grouping == RuleGrouping.ALL:
73
- replicas_to_create, locks_to_create,\
92
+ replicas_to_create, locks_to_create, \
74
93
  transfers_to_create = __apply_rule_to_files_all_grouping(datasetfiles=datasetfiles,
75
94
  locks=locks,
76
95
  replicas=replicas,
@@ -81,7 +100,7 @@ def apply_rule_grouping(datasetfiles, locks, replicas, source_replicas, rseselec
81
100
  source_rses=source_rses,
82
101
  session=session)
83
102
  else: # rule.grouping == RuleGrouping.DATASET:
84
- replicas_to_create, locks_to_create,\
103
+ replicas_to_create, locks_to_create, \
85
104
  transfers_to_create = __apply_rule_to_files_dataset_grouping(datasetfiles=datasetfiles,
86
105
  locks=locks,
87
106
  replicas=replicas,
@@ -96,7 +115,19 @@ def apply_rule_grouping(datasetfiles, locks, replicas, source_replicas, rseselec
96
115
 
97
116
 
98
117
  @transactional_session
99
- def repair_stuck_locks_and_apply_rule_grouping(datasetfiles, locks, replicas, source_replicas, rseselector, rule, source_rses, *, session: "Session"):
118
+ def repair_stuck_locks_and_apply_rule_grouping(
119
+ datasetfiles: Sequence[dict[str, Any]],
120
+ locks: dict[tuple[InternalScope, str], models.ReplicaLock],
121
+ replicas: dict[tuple[InternalScope, str], Any],
122
+ source_replicas: dict[tuple[InternalScope, str], Any],
123
+ rseselector: RSESelector, rule: models.ReplicationRule,
124
+ source_rses: Sequence[str],
125
+ *,
126
+ session: "Session"
127
+ ) -> tuple[dict[str, list[dict[str, models.RSEFileAssociation]]],
128
+ dict[str, list[dict[str, models.ReplicaLock]]],
129
+ list[dict[str, Any]],
130
+ dict[str, list[dict[str, models.ReplicaLock]]]]:
100
131
  """
101
132
  Apply rule grouping to files.
102
133
 
@@ -106,7 +137,7 @@ def repair_stuck_locks_and_apply_rule_grouping(datasetfiles, locks, replicas, so
106
137
  :param source_replicas: Dict holding all source_replicas.
107
138
  :param rseselector: The RSESelector to be used.
108
139
  :param rule: The rule object.
109
- :param source_rses: RSE ids of eglible source_rses.
140
+ :param source_rses: RSE ids of eligible source_rses.
110
141
  :param session: Session of the db.
111
142
  :returns: List of replicas to create, List of locks to create, List of transfers to create, List of locks to Delete
112
143
  :raises: InsufficientQuota, InsufficientTargetRSEs
@@ -119,7 +150,7 @@ def repair_stuck_locks_and_apply_rule_grouping(datasetfiles, locks, replicas, so
119
150
  # locks_to_delete = {'rse_id': [locks]}
120
151
 
121
152
  if rule.grouping == RuleGrouping.NONE:
122
- replicas_to_create, locks_to_create, transfers_to_create,\
153
+ replicas_to_create, locks_to_create, transfers_to_create, \
123
154
  locks_to_delete = __repair_stuck_locks_with_none_grouping(datasetfiles=datasetfiles,
124
155
  locks=locks,
125
156
  replicas=replicas,
@@ -129,7 +160,7 @@ def repair_stuck_locks_and_apply_rule_grouping(datasetfiles, locks, replicas, so
129
160
  source_rses=source_rses,
130
161
  session=session)
131
162
  elif rule.grouping == RuleGrouping.ALL:
132
- replicas_to_create, locks_to_create, transfers_to_create,\
163
+ replicas_to_create, locks_to_create, transfers_to_create, \
133
164
  locks_to_delete = __repair_stuck_locks_with_all_grouping(datasetfiles=datasetfiles,
134
165
  locks=locks,
135
166
  replicas=replicas,
@@ -139,7 +170,7 @@ def repair_stuck_locks_and_apply_rule_grouping(datasetfiles, locks, replicas, so
139
170
  source_rses=source_rses,
140
171
  session=session)
141
172
  else:
142
- replicas_to_create, locks_to_create, transfers_to_create,\
173
+ replicas_to_create, locks_to_create, transfers_to_create, \
143
174
  locks_to_delete = __repair_stuck_locks_with_dataset_grouping(datasetfiles=datasetfiles,
144
175
  locks=locks,
145
176
  replicas=replicas,
@@ -196,7 +227,20 @@ def create_transfer_dict(dest_rse_id, request_type, scope, name, rule, lock=None
196
227
 
197
228
 
198
229
  @transactional_session
199
- def __apply_rule_to_files_none_grouping(datasetfiles, locks, replicas, source_replicas, rseselector, rule, preferred_rse_ids=[], source_rses=[], *, session: "Session"):
230
+ def __apply_rule_to_files_none_grouping(
231
+ datasetfiles: Sequence[dict[str, Any]],
232
+ locks: dict[tuple[InternalScope, str], Sequence[models.ReplicaLock]],
233
+ replicas: dict[tuple[InternalScope, str], Sequence[models.CollectionReplica]],
234
+ source_replicas: dict[tuple[InternalScope, str], Sequence[models.CollectionReplica]],
235
+ rseselector: RSESelector,
236
+ rule: models.ReplicationRule,
237
+ preferred_rse_ids: Optional[Sequence[str]] = None,
238
+ source_rses: Optional[Sequence[str]] = None,
239
+ *,
240
+ session: "Session"
241
+ ) -> tuple[dict[str, list[dict[str, models.RSEFileAssociation]]],
242
+ dict[str, list[dict[str, models.ReplicaLock]]],
243
+ list[dict[str, Any]]]:
200
244
  """
201
245
  Apply a rule to files with NONE grouping.
202
246
 
@@ -207,7 +251,7 @@ def __apply_rule_to_files_none_grouping(datasetfiles, locks, replicas, source_re
207
251
  :param rseselector: The RSESelector to be used.
208
252
  :param rule: The rule object.
209
253
  :param preferred_rse_ids: Preferred RSE's to select.
210
- :param source_rses: RSE ids of eglible source replicas.
254
+ :param source_rses: RSE ids of eligible source replicas.
211
255
  :param session: Session of the db.
212
256
  :returns: replicas_to_create, locks_to_create, transfers_to_create
213
257
  :raises: InsufficientAccountLimit, InsufficientTargetRSEs
@@ -216,6 +260,8 @@ def __apply_rule_to_files_none_grouping(datasetfiles, locks, replicas, source_re
216
260
  locks_to_create = {} # {'rse_id': [locks]}
217
261
  replicas_to_create = {} # {'rse_id': [replicas]}
218
262
  transfers_to_create = [] # [{'dest_rse_id':, 'scope':, 'name':, 'request_type':, 'metadata':}]
263
+ preferred_rse_ids = preferred_rse_ids or []
264
+ source_rses = source_rses or []
219
265
 
220
266
  for dataset in datasetfiles:
221
267
  selected_rse_ids = []
@@ -223,16 +269,16 @@ def __apply_rule_to_files_none_grouping(datasetfiles, locks, replicas, source_re
223
269
  if len([lock for lock in locks[(file['scope'], file['name'])] if lock.rule_id == rule.id]) == rule.copies:
224
270
  # Nothing to do as the file already has the requested amount of locks
225
271
  continue
226
- rse_coverage = {replica.rse_id: file['bytes'] for replica in replicas[(file['scope'], file['name'])] if replica.state in (ReplicaState.AVAILABLE, ReplicaState.COPYING, ReplicaState.TEMPORARY_UNAVAILABLE)}
272
+ rse_coverage = {str(replica.rse_id): file['bytes'] for replica in replicas[(file['scope'], file['name'])] if replica.state in (ReplicaState.AVAILABLE, ReplicaState.COPYING, ReplicaState.TEMPORARY_UNAVAILABLE)}
227
273
  if len(preferred_rse_ids) == 0:
228
274
  rse_tuples = rseselector.select_rse(size=file['bytes'],
229
275
  preferred_rse_ids=rse_coverage.keys(),
230
- blocklist=[replica.rse_id for replica in replicas[(file['scope'], file['name'])] if replica.state == ReplicaState.BEING_DELETED],
276
+ blocklist=[str(replica.rse_id) for replica in replicas[(file['scope'], file['name'])] if replica.state == ReplicaState.BEING_DELETED],
231
277
  existing_rse_size=rse_coverage)
232
278
  else:
233
279
  rse_tuples = rseselector.select_rse(size=file['bytes'],
234
280
  preferred_rse_ids=preferred_rse_ids,
235
- blocklist=[replica.rse_id for replica in replicas[(file['scope'], file['name'])] if replica.state == ReplicaState.BEING_DELETED],
281
+ blocklist=[str(replica.rse_id) for replica in replicas[(file['scope'], file['name'])] if replica.state == ReplicaState.BEING_DELETED],
236
282
  existing_rse_size=rse_coverage)
237
283
  for rse_tuple in rse_tuples:
238
284
  if len([lock for lock in locks[(file['scope'], file['name'])] if lock.rule_id == rule.id and lock.rse_id == rse_tuple[0]]) == 1:
@@ -256,9 +302,14 @@ def __apply_rule_to_files_none_grouping(datasetfiles, locks, replicas, source_re
256
302
  if dataset['scope'] is not None:
257
303
  for rse_id in list(set(selected_rse_ids)):
258
304
  try:
259
- session.query(models.CollectionReplica).filter(models.CollectionReplica.scope == dataset['scope'],
260
- models.CollectionReplica.name == dataset['name'],
261
- models.CollectionReplica.rse_id == rse_id).one()
305
+ stmt = select(
306
+ models.CollectionReplica
307
+ ).where(
308
+ and_(models.CollectionReplica.scope == dataset['scope'],
309
+ models.CollectionReplica.name == dataset['name'],
310
+ models.CollectionReplica.rse_id == rse_id)
311
+ )
312
+ session.execute(stmt).one()
262
313
  except NoResultFound:
263
314
  models.CollectionReplica(scope=dataset['scope'],
264
315
  name=dataset['name'],
@@ -277,7 +328,20 @@ def __apply_rule_to_files_none_grouping(datasetfiles, locks, replicas, source_re
277
328
 
278
329
 
279
330
  @transactional_session
280
- def __apply_rule_to_files_all_grouping(datasetfiles, locks, replicas, source_replicas, rseselector, rule, preferred_rse_ids=[], source_rses=[], *, session: "Session"):
331
+ def __apply_rule_to_files_all_grouping(
332
+ datasetfiles: Sequence[dict[str, Any]],
333
+ locks: dict[tuple[InternalScope, str], Sequence[models.ReplicaLock]],
334
+ replicas: dict[tuple[InternalScope, str], Sequence[models.CollectionReplica]],
335
+ source_replicas: dict[tuple[InternalScope, str], Sequence[models.CollectionReplica]],
336
+ rseselector: RSESelector,
337
+ rule: models.ReplicationRule,
338
+ preferred_rse_ids: Optional[Sequence[str]] = None,
339
+ source_rses: Optional[Sequence[str]] = None,
340
+ *,
341
+ session: "Session"
342
+ ) -> tuple[dict[str, list[dict[str, models.RSEFileAssociation]]],
343
+ dict[str, list[dict[str, models.ReplicaLock]]],
344
+ list[dict[str, Any]]]:
281
345
  """
282
346
  Apply a rule to files with ALL grouping.
283
347
 
@@ -288,7 +352,7 @@ def __apply_rule_to_files_all_grouping(datasetfiles, locks, replicas, source_rep
288
352
  :param rseselector: The RSESelector to be used.
289
353
  :param rule: The rule object.
290
354
  :param preferred_rse_ids: Preferred RSE's to select.
291
- :param source_rses: RSE ids of eglible source replicas.
355
+ :param source_rses: RSE ids of eligible source replicas.
292
356
  :param session: Session of the db.
293
357
  :returns: replicas_to_create, locks_to_create, transfers_to_create
294
358
  :raises: InsufficientQuota, InsufficientTargetRSEs
@@ -298,6 +362,8 @@ def __apply_rule_to_files_all_grouping(datasetfiles, locks, replicas, source_rep
298
362
  locks_to_create = {} # {'rse_id': [locks]}
299
363
  replicas_to_create = {} # {'rse_id': [replicas]}
300
364
  transfers_to_create = [] # [{'dest_rse_id':, 'scope':, 'name':, 'request_type':, 'metadata':}]
365
+ preferred_rse_ids = preferred_rse_ids or []
366
+ source_rses = source_rses or []
301
367
 
302
368
  bytes_ = 0
303
369
  rse_coverage = {} # {'rse_id': coverage }
@@ -351,17 +417,28 @@ def __apply_rule_to_files_all_grouping(datasetfiles, locks, replicas, source_rep
351
417
  # Add a DatasetLock to the DB
352
418
  if dataset['scope'] is not None:
353
419
  try:
354
- session.query(models.DatasetLock).filter(models.DatasetLock.scope == dataset['scope'],
355
- models.DatasetLock.name == dataset['name'],
356
- models.DatasetLock.rule_id == rule.id,
357
- models.DatasetLock.rse_id == rse_tuple[0]).one()
420
+ stmt = select(
421
+ models.DatasetLock
422
+ ).where(
423
+ and_(models.DatasetLock.scope == dataset['scope'],
424
+ models.DatasetLock.name == dataset['name'],
425
+ models.DatasetLock.rule_id == rule.id,
426
+ models.DatasetLock.rse_id == rse_tuple[0])
427
+ )
428
+ session.execute(stmt).one()
358
429
  except NoResultFound:
359
430
  # Get dataset Information
360
431
  is_open, bytes_, length = True, 0, 0
361
432
  try:
362
- is_open, bytes_, length = session.query(models.DataIdentifier.is_open,
363
- models.DataIdentifier.bytes,
364
- models.DataIdentifier.length).filter_by(scope=dataset['scope'], name=dataset['name']).one()
433
+ stmt = select(
434
+ models.DataIdentifier.is_open,
435
+ models.DataIdentifier.bytes,
436
+ models.DataIdentifier.length
437
+ ).where(
438
+ and_(models.DataIdentifier.scope == dataset['scope'],
439
+ models.DataIdentifier.name == dataset['name'])
440
+ )
441
+ is_open, bytes_, length = session.execute(stmt).one()
365
442
  except NoResultFound:
366
443
  pass
367
444
 
@@ -376,9 +453,14 @@ def __apply_rule_to_files_all_grouping(datasetfiles, locks, replicas, source_rep
376
453
  # Add a Dataset Replica to the DB
377
454
  if dataset['scope'] is not None:
378
455
  try:
379
- session.query(models.CollectionReplica).filter(models.CollectionReplica.scope == dataset['scope'],
380
- models.CollectionReplica.name == dataset['name'],
381
- models.CollectionReplica.rse_id == rse_tuple[0]).one()
456
+ stmt = select(
457
+ models.CollectionReplica
458
+ ).where(
459
+ and_(models.CollectionReplica.scope == dataset['scope'],
460
+ models.CollectionReplica.name == dataset['name'],
461
+ models.CollectionReplica.rse_id == rse_tuple[0])
462
+ )
463
+ session.execute(stmt).one()
382
464
  except NoResultFound:
383
465
  models.CollectionReplica(scope=dataset['scope'],
384
466
  name=dataset['name'],
@@ -397,9 +479,22 @@ def __apply_rule_to_files_all_grouping(datasetfiles, locks, replicas, source_rep
397
479
 
398
480
 
399
481
  @transactional_session
400
- def __apply_rule_to_files_dataset_grouping(datasetfiles, locks, replicas, source_replicas, rseselector, rule, preferred_rse_ids=[], source_rses=[], *, session: "Session"):
482
+ def __apply_rule_to_files_dataset_grouping(
483
+ datasetfiles: Sequence[dict[str, Any]],
484
+ locks: dict[tuple[InternalScope, str], Sequence[models.ReplicaLock]],
485
+ replicas: dict[tuple[InternalScope, str], Sequence[models.CollectionReplica]],
486
+ source_replicas: dict[tuple[InternalScope, str], Sequence[models.CollectionReplica]],
487
+ rseselector: RSESelector,
488
+ rule: models.ReplicationRule,
489
+ preferred_rse_ids: Optional[Sequence[str]] = None,
490
+ source_rses: Optional[Sequence[str]] = None,
491
+ *,
492
+ session: "Session"
493
+ ) -> tuple[dict[str, list[dict[str, models.RSEFileAssociation]]],
494
+ dict[str, list[dict[str, models.ReplicaLock]]],
495
+ list[dict[str, Any]]]:
401
496
  """
402
- Apply a rule to files with ALL grouping.
497
+ Apply a rule to files with DATASET grouping.
403
498
 
404
499
  :param datasetfiles: Dict holding all datasets and files.
405
500
  :param locks: Dict holding all locks.
@@ -408,7 +503,7 @@ def __apply_rule_to_files_dataset_grouping(datasetfiles, locks, replicas, source
408
503
  :param rseselector: The RSESelector to be used.
409
504
  :param rule: The rule object.
410
505
  :param preferred_rse_ids: Preferred RSE's to select.
411
- :param source_rses: RSE ids of eglible source replicas.
506
+ :param source_rses: RSE ids of eligible source replicas.
412
507
  :param session: Session of the db.
413
508
  :returns: replicas_to_create, locks_to_create, transfers_to_create
414
509
  :raises: InsufficientQuota, InsufficientTargetRSEs
@@ -417,6 +512,8 @@ def __apply_rule_to_files_dataset_grouping(datasetfiles, locks, replicas, source
417
512
  locks_to_create = {} # {'rse_id': [locks]}
418
513
  replicas_to_create = {} # {'rse_id': [replicas]}
419
514
  transfers_to_create = [] # [{'dest_rse_id':, 'scope':, 'name':, 'request_type':, 'metadata':}]
515
+ preferred_rse_ids = preferred_rse_ids or []
516
+ source_rses = source_rses or []
420
517
 
421
518
  for dataset in datasetfiles:
422
519
  bytes_ = sum([file['bytes'] for file in dataset['files']])
@@ -468,17 +565,28 @@ def __apply_rule_to_files_dataset_grouping(datasetfiles, locks, replicas, source
468
565
  # Add a DatasetLock to the DB
469
566
  if dataset['scope'] is not None:
470
567
  try:
471
- session.query(models.DatasetLock).filter(models.DatasetLock.scope == dataset['scope'],
472
- models.DatasetLock.name == dataset['name'],
473
- models.DatasetLock.rule_id == rule.id,
474
- models.DatasetLock.rse_id == rse_tuple[0]).one()
568
+ stmt = select(
569
+ models.DatasetLock
570
+ ).where(
571
+ and_(models.DatasetLock.scope == dataset['scope'],
572
+ models.DatasetLock.name == dataset['name'],
573
+ models.DatasetLock.rule_id == rule.id,
574
+ models.DatasetLock.rse_id == rse_tuple[0])
575
+ )
576
+ session.execute(stmt).one()
475
577
  except NoResultFound:
476
578
  # Get dataset Information
477
579
  is_open, bytes_, length = True, None, None
478
580
  try:
479
- is_open, bytes_, length = session.query(models.DataIdentifier.is_open,
480
- models.DataIdentifier.bytes,
481
- models.DataIdentifier.length).filter_by(scope=dataset['scope'], name=dataset['name']).one()
581
+ stmt = select(
582
+ models.DataIdentifier.is_open,
583
+ models.DataIdentifier.bytes,
584
+ models.DataIdentifier.length
585
+ ).where(
586
+ and_(models.DataIdentifier.scope == dataset['scope'],
587
+ models.DataIdentifier.name == dataset['name'])
588
+ )
589
+ is_open, bytes_, length = session.execute(stmt).one()
482
590
  except NoResultFound:
483
591
  pass
484
592
 
@@ -494,9 +602,14 @@ def __apply_rule_to_files_dataset_grouping(datasetfiles, locks, replicas, source
494
602
  # Add a Dataset Replica to the DB
495
603
  if dataset['scope'] is not None:
496
604
  try:
497
- session.query(models.CollectionReplica).filter(models.CollectionReplica.scope == dataset['scope'],
498
- models.CollectionReplica.name == dataset['name'],
499
- models.CollectionReplica.rse_id == rse_tuple[0]).one()
605
+ stmt = select(
606
+ models.CollectionReplica
607
+ ).where(
608
+ and_(models.CollectionReplica.scope == dataset['scope'],
609
+ models.CollectionReplica.name == dataset['name'],
610
+ models.CollectionReplica.rse_id == rse_tuple[0])
611
+ )
612
+ session.execute(stmt).one()
500
613
  except NoResultFound:
501
614
  models.CollectionReplica(scope=dataset['scope'],
502
615
  name=dataset['name'],
@@ -525,7 +638,7 @@ def __repair_stuck_locks_with_none_grouping(datasetfiles, locks, replicas, sourc
525
638
  :param source_replicas: Dict holding all source_replicas.
526
639
  :param rseselector: The RSESelector to be used.
527
640
  :param rule: The rule object.
528
- :param source_rses: RSE ids of eglible source replicas.
641
+ :param source_rses: RSE ids of eligible source replicas.
529
642
  :param session: Session of the db.
530
643
  :param logger: Optional decorated logger that can be passed from the calling daemons or servers.
531
644
  :returns: replicas_to_create, locks_to_create, transfers_to_create, locks_to_delete
@@ -563,12 +676,21 @@ def __repair_stuck_locks_with_none_grouping(datasetfiles, locks, replicas, sourc
563
676
  # Recalculate the replica_lock_cnt
564
677
  associated_replica = [replica for replica in replicas[(file['scope'], file['name'])] if replica.state in [ReplicaState.AVAILABLE, ReplicaState.TEMPORARY_UNAVAILABLE] and replica.rse_id == lock.rse_id][0]
565
678
  associated_replica.tombstone = None
566
- associated_replica.lock_cnt = session.query(func.count(models.ReplicaLock.rule_id)).filter_by(scope=associated_replica.scope, name=associated_replica.name, rse_id=lock.rse_id).one()[0]
679
+ stmt = select(
680
+ func.count(models.ReplicaLock.rule_id)
681
+ ).select_from(
682
+ models.ReplicaLock
683
+ ).where(
684
+ and_(models.ReplicaLock.scope == associated_replica.scope,
685
+ models.ReplicaLock.name == associated_replica.name,
686
+ models.ReplicaLock.rse_id == lock.rse_id)
687
+ )
688
+ associated_replica.lock_cnt = session.execute(stmt).scalar_one()
567
689
  continue
568
690
  # Check if this is a STUCK lock due to source_replica filtering
569
691
  if source_rses:
570
692
  associated_replica = [replica for replica in replicas[(file['scope'], file['name'])] if replica.rse_id == lock.rse_id][0]
571
- # Check if there is an eglible source replica for this lock
693
+ # Check if there is an eligible source replica for this lock
572
694
  if set(source_replicas.get((file['scope'], file['name']), [])).intersection(source_rses) and (selector_rse_dict.get(lock.rse_id, {}).get('availability_write', True) or rule.ignore_availability):
573
695
  __update_lock_replica_and_create_transfer(lock=lock,
574
696
  replica=associated_replica,
@@ -632,7 +754,7 @@ def __repair_stuck_locks_with_all_grouping(datasetfiles, locks, replicas, source
632
754
  :param source_replicas: Dict holding all source_replicas.
633
755
  :param rseselector: The RSESelector to be used.
634
756
  :param rule: The rule object.
635
- :param source_rses: RSE ids of eglible source replicas.
757
+ :param source_rses: RSE ids of eligible source replicas.
636
758
  :param session: Session of the db.
637
759
  :param logger: Optional decorated logger that can be passed from the calling daemons or servers.
638
760
  :returns: replicas_to_create, locks_to_create, transfers_to_create, locks_to_delete
@@ -670,12 +792,21 @@ def __repair_stuck_locks_with_all_grouping(datasetfiles, locks, replicas, source
670
792
  # Recalculate the replica_lock_cnt
671
793
  associated_replica = [replica for replica in replicas[(file['scope'], file['name'])] if replica.state in [ReplicaState.AVAILABLE, ReplicaState.TEMPORARY_UNAVAILABLE] and replica.rse_id == lock.rse_id][0]
672
794
  associated_replica.tombstone = None
673
- associated_replica.lock_cnt = session.query(func.count(models.ReplicaLock.rule_id)).filter_by(scope=associated_replica.scope, name=associated_replica.name, rse_id=lock.rse_id).one()[0]
795
+ stmt = select(
796
+ func.count(models.ReplicaLock.rule_id)
797
+ ).select_from(
798
+ models.ReplicaLock
799
+ ).where(
800
+ and_(models.ReplicaLock.scope == associated_replica.scope,
801
+ models.ReplicaLock.name == associated_replica.name,
802
+ models.ReplicaLock.rse_id == lock.rse_id)
803
+ )
804
+ associated_replica.lock_cnt = session.execute(stmt).scalar_one()
674
805
  continue
675
806
  # Check if this is a STUCK lock due to source_replica filtering
676
807
  if source_rses:
677
808
  associated_replica = [replica for replica in replicas[(file['scope'], file['name'])] if replica.rse_id == lock.rse_id][0]
678
- # Check if there is an eglible source replica for this lock
809
+ # Check if there is an eligible source replica for this lock
679
810
  if set(source_replicas.get((file['scope'], file['name']), [])).intersection(source_rses) and (selector_rse_dict.get(lock.rse_id, {}).get('availability_write', True) or rule.ignore_availability):
680
811
  __update_lock_replica_and_create_transfer(lock=lock,
681
812
  replica=associated_replica,
@@ -708,7 +839,7 @@ def __repair_stuck_locks_with_dataset_grouping(datasetfiles, locks, replicas, so
708
839
  :param source_replicas: Dict holding all source_replicas.
709
840
  :param rseselector: The RSESelector to be used.
710
841
  :param rule: The rule object.
711
- :param source_rses: RSE ids of eglible source replicas.
842
+ :param source_rses: RSE ids of eligible source replicas.
712
843
  :param session: Session of the db.
713
844
  :param logger: Optional decorated logger that can be passed from the calling daemons or servers.
714
845
  :returns: replicas_to_create, locks_to_create, transfers_to_create, locks_to_delete
@@ -746,12 +877,21 @@ def __repair_stuck_locks_with_dataset_grouping(datasetfiles, locks, replicas, so
746
877
  # Recalculate the replica_lock_cnt
747
878
  associated_replica = [replica for replica in replicas[(file['scope'], file['name'])] if replica.state in [ReplicaState.AVAILABLE, ReplicaState.TEMPORARY_UNAVAILABLE] and replica.rse_id == lock.rse_id][0]
748
879
  associated_replica.tombstone = None
749
- associated_replica.lock_cnt = session.query(func.count(models.ReplicaLock.rule_id)).filter_by(scope=associated_replica.scope, name=associated_replica.name, rse_id=lock.rse_id).one()[0]
880
+ stmt = select(
881
+ func.count(models.ReplicaLock.rule_id)
882
+ ).select_from(
883
+ models.ReplicaLock
884
+ ).where(
885
+ and_(models.ReplicaLock.scope == associated_replica.scope,
886
+ models.ReplicaLock.name == associated_replica.name,
887
+ models.ReplicaLock.rse_id == lock.rse_id)
888
+ )
889
+ associated_replica.lock_cnt = session.execute(stmt).scalar_one()
750
890
  continue
751
891
  # Check if this is a STUCK lock due to source_replica filtering
752
892
  if source_rses:
753
893
  associated_replica = [replica for replica in replicas[(file['scope'], file['name'])] if replica.rse_id == lock.rse_id][0]
754
- # Check if there is an eglible source replica for this lock
894
+ # Check if there is an eligible source replica for this lock
755
895
  if set(source_replicas.get((file['scope'], file['name']), [])).intersection(source_rses) and (selector_rse_dict.get(lock.rse_id, {}).get('availability_write', True) or rule.ignore_availability):
756
896
  __update_lock_replica_and_create_transfer(lock=lock,
757
897
  replica=associated_replica,
@@ -818,7 +958,7 @@ def __create_lock_and_replica(file, dataset, rule, rse_id, staging_area, availab
818
958
  :param availability_write: Boolean variable if the RSE is write enabled.
819
959
  :param locks_to_create: Dictionary of the locks to create.
820
960
  :param locks: Dictionary of all locks.
821
- :param source_rses: RSE ids of eglible source replicas.
961
+ :param source_rses: RSE ids of eligible source replicas.
822
962
  :param replicas_to_create: Dictionary of the replicas to create.
823
963
  :param replicas: Dictionary of the replicas.
824
964
  :param source_replicas: Dictionary of the source replicas.
@@ -851,8 +991,8 @@ def __create_lock_and_replica(file, dataset, rule, rse_id, staging_area, availab
851
991
  session=session))
852
992
 
853
993
  # If staging_required type RSE then set pin to RSE attribute maximum_pin_lifetime
854
- staging_required = get_rse_attribute(rse_id, 'staging_required', session=session)
855
- maximum_pin_lifetime = get_rse_attribute(rse_id, 'maximum_pin_lifetime', session=session)
994
+ staging_required = get_rse_attribute(rse_id, RseAttr.STAGING_REQUIRED, session=session)
995
+ maximum_pin_lifetime = get_rse_attribute(rse_id, RseAttr.MAXIMUM_PIN_LIFETIME, session=session)
856
996
 
857
997
  if staging_required:
858
998
  if (not copy_pin_lifetime and maximum_pin_lifetime) or (copy_pin_lifetime and maximum_pin_lifetime and copy_pin_lifetime < int(maximum_pin_lifetime)):
@@ -900,7 +1040,7 @@ def __create_lock_and_replica(file, dataset, rule, rse_id, staging_area, availab
900
1040
  available_source_replica = True
901
1041
  if source_rses:
902
1042
  available_source_replica = False
903
- # Check if there is an eglible source replica for this lock
1043
+ # Check if there is an eligible source replica for this lock
904
1044
  if set(source_replicas.get((file['scope'], file['name']), [])).intersection(source_rses):
905
1045
  available_source_replica = True
906
1046
  new_lock = __create_lock(rule=rule,
@@ -947,7 +1087,7 @@ def __create_lock_and_replica(file, dataset, rule, rse_id, staging_area, availab
947
1087
  available_source_replica = True
948
1088
  if source_rses:
949
1089
  available_source_replica = False
950
- # Check if there is an eglible source replica for this lock
1090
+ # Check if there is an eligible source replica for this lock
951
1091
  if set(source_replicas.get((file['scope'], file['name']), [])).intersection(source_rses):
952
1092
  available_source_replica = True
953
1093
 
@@ -1281,7 +1421,7 @@ def apply_rule(did, rule, rses, source_rses, rseselector, *, session: "Session",
1281
1421
  datasets.append((did.scope, did.name, ))
1282
1422
  elif did.did_type == DIDType.CONTAINER:
1283
1423
  for child_dataset in rucio.core.did.list_child_datasets(scope=did.scope, name=did.name, session=session):
1284
- # ensure theer are no duplicates
1424
+ # ensure there are no duplicates
1285
1425
  newds = (child_dataset['scope'], child_dataset['name'], )
1286
1426
  if newds not in datasets:
1287
1427
  datasets.append(newds)
@@ -1450,9 +1590,14 @@ def apply_rule(did, rule, rses, source_rses, rseselector, *, session: "Session",
1450
1590
 
1451
1591
  # add dataset replica if not already existing (rule_id is not in PK)
1452
1592
  try:
1453
- session.query(models.CollectionReplica).filter(models.CollectionReplica.scope == ds_scope,
1454
- models.CollectionReplica.name == ds_name,
1455
- models.CollectionReplica.rse_id == u_rse).one()
1593
+ stmt = select(
1594
+ models.CollectionReplica
1595
+ ).where(
1596
+ and_(models.CollectionReplica.scope == ds_scope,
1597
+ models.CollectionReplica.name == ds_name,
1598
+ models.CollectionReplica.rse_id == u_rse)
1599
+ )
1600
+ session.execute(stmt).one()
1456
1601
  except NoResultFound:
1457
1602
  models.CollectionReplica(scope=ds_scope, name=ds_name, did_type=DIDType.DATASET,
1458
1603
  rse_id=u_rse,