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");
@@ -24,9 +23,9 @@ import logging
24
23
  import re
25
24
  import threading
26
25
  import time
26
+ from collections.abc import Mapping, Sequence
27
27
  from itertools import groupby
28
- from types import FrameType
29
- from typing import TYPE_CHECKING, Mapping, Optional, Sequence
28
+ from typing import TYPE_CHECKING, Any, Optional
30
29
 
31
30
  from requests.exceptions import RequestException
32
31
  from sqlalchemy.exc import DatabaseError
@@ -36,18 +35,20 @@ from rucio.common.config import config_get, config_get_bool
36
35
  from rucio.common.exception import DatabaseException, TransferToolTimeout, TransferToolWrongAnswer
37
36
  from rucio.common.logging import setup_logging
38
37
  from rucio.common.stopwatch import Stopwatch
39
- from rucio.common.types import InternalAccount
38
+ from rucio.common.types import InternalAccount, LoggerFunction
40
39
  from rucio.common.utils import dict_chunks
41
- from rucio.core import transfer as transfer_core, request as request_core
40
+ from rucio.core import request as request_core
41
+ from rucio.core import transfer as transfer_core
42
42
  from rucio.core.monitor import MetricManager
43
- from rucio.core.topology import Topology, ExpiringObjectCache
44
- from rucio.daemons.common import db_workqueue, ProducerConsumerDaemon
45
- from rucio.db.sqla.constants import RequestState, RequestType
43
+ from rucio.core.topology import ExpiringObjectCache, Topology
44
+ from rucio.daemons.common import ProducerConsumerDaemon, db_workqueue
45
+ from rucio.db.sqla.constants import MYSQL_LOCK_WAIT_TIMEOUT_EXCEEDED, ORACLE_DEADLOCK_DETECTED_REGEX, ORACLE_RESOURCE_BUSY_REGEX, RequestState, RequestType
46
46
  from rucio.transfertool.fts3 import FTS3Transfertool
47
- from rucio.transfertool.globus import GlobusTransferTool
48
- from rucio.transfertool.mock import MockTransfertool
47
+ from rucio.transfertool.transfertool import Transfertool
49
48
 
50
49
  if TYPE_CHECKING:
50
+ from types import FrameType
51
+
51
52
  from rucio.daemons.common import HeartbeatHandler
52
53
 
53
54
  GRACEFUL_STOP = threading.Event()
@@ -59,16 +60,16 @@ FILTER_TRANSFERTOOL = config_get('conveyor', 'filter_transfertool', False, None)
59
60
 
60
61
 
61
62
  def _fetch_requests(
62
- db_bulk,
63
- older_than,
64
- activity_shares,
65
- transfertool,
66
- filter_transfertool,
67
- cached_topology,
68
- activity,
63
+ db_bulk: int,
64
+ older_than: int,
65
+ activity_shares: Optional[Mapping[str, float]],
66
+ transfertool: Optional[str],
67
+ filter_transfertool: Optional[str],
68
+ cached_topology: Optional[ExpiringObjectCache],
69
+ activity: str,
69
70
  set_last_processed_by: bool,
70
- heartbeat_handler
71
- ):
71
+ heartbeat_handler: "HeartbeatHandler"
72
+ ) -> tuple[bool, list[dict[str, Any]]]:
72
73
  worker_number, total_workers, logger = heartbeat_handler.live()
73
74
 
74
75
  logger(logging.DEBUG, 'Start to poll transfers older than %i seconds for activity %s using transfer tool: %s' % (older_than, activity, filter_transfertool))
@@ -94,7 +95,7 @@ def _fetch_requests(
94
95
  # only keep transfers which don't have any transfertool set, or have one equal to TRANSFER_TOOL
95
96
  transfs_tmp = [t for t in transfs if not t['transfertool'] or t['transfertool'] == transfertool]
96
97
  if len(transfs_tmp) != len(transfs):
97
- logger(logging.INFO, 'Skipping %i transfers because of missmatched transfertool', len(transfs) - len(transfs_tmp))
98
+ logger(logging.INFO, 'Skipping %i transfers because of mismatched transfertool', len(transfs) - len(transfs_tmp))
98
99
  transfs = transfs_tmp
99
100
 
100
101
  if transfs:
@@ -109,15 +110,16 @@ def _fetch_requests(
109
110
 
110
111
 
111
112
  def _handle_requests(
112
- transfs,
113
- fts_bulk,
114
- multi_vo,
115
- timeout,
116
- transfertool,
113
+ transfs: list[dict[str, Any]],
114
+ fts_bulk: int,
115
+ multi_vo: Optional[bool],
116
+ timeout: Optional[int],
117
+ transfertool: str,
118
+ transfer_stats_manager: request_core.TransferStatsManager,
117
119
  oidc_account: Optional[str],
118
120
  *,
119
- logger=logging.log,
120
- ):
121
+ logger: LoggerFunction = logging.log,
122
+ ) -> None:
121
123
  transfs.sort(key=lambda t: (t['external_host'] or '',
122
124
  t['scope'].vo if multi_vo else '',
123
125
  t['external_id'] or '',
@@ -130,19 +132,29 @@ def _handle_requests(
130
132
 
131
133
  for chunk in dict_chunks(transfers_by_eid, fts_bulk):
132
134
  try:
133
- if transfertool == 'mock':
134
- transfertool_obj = MockTransfertool(external_host=MockTransfertool.external_name)
135
- elif transfertool == 'globus':
136
- transfertool_obj = GlobusTransferTool(external_host=GlobusTransferTool.external_name)
137
- else:
135
+ transfertool_cls = transfer_core.TRANSFERTOOL_CLASSES_BY_NAME.get(transfertool, FTS3Transfertool)
136
+
137
+ transfertool_kwargs = {}
138
+ if transfertool_cls.external_name == FTS3Transfertool.external_name:
138
139
  account = None
139
140
  if oidc_account:
140
141
  if vo:
141
142
  account = InternalAccount(oidc_account, vo=vo)
142
143
  else:
143
144
  account = InternalAccount(oidc_account)
144
- transfertool_obj = FTS3Transfertool(external_host=external_host, vo=vo, oidc_account=account)
145
- poll_transfers(transfertool_obj=transfertool_obj, transfers_by_eid=chunk, timeout=timeout, logger=logger)
145
+ transfertool_kwargs.update({
146
+ 'vo': vo,
147
+ 'oidc_account': account,
148
+ })
149
+
150
+ transfertool_obj = transfertool_cls(external_host=external_host, **transfertool_kwargs)
151
+ poll_transfers(
152
+ transfertool_obj=transfertool_obj,
153
+ transfers_by_eid=chunk,
154
+ transfer_stats_manager=transfer_stats_manager,
155
+ timeout=timeout,
156
+ logger=logger,
157
+ )
146
158
  except Exception:
147
159
  logger(logging.ERROR, 'Exception', exc_info=True)
148
160
 
@@ -158,9 +170,9 @@ def poller(
158
170
  partition_wait_time: int = 10,
159
171
  transfertool: Optional[str] = TRANSFER_TOOL,
160
172
  filter_transfertool: Optional[str] = FILTER_TRANSFERTOOL,
161
- cached_topology=None,
173
+ cached_topology: Optional[ExpiringObjectCache] = None,
162
174
  total_threads: int = 1,
163
- ):
175
+ ) -> None:
164
176
  """
165
177
  Main loop to check the status of a transfer primitive with a transfertool.
166
178
  """
@@ -182,6 +194,8 @@ def poller(
182
194
  if filter_transfertool:
183
195
  executable += ' --filter-transfertool ' + filter_transfertool
184
196
 
197
+ transfer_stats_manager = request_core.TransferStatsManager()
198
+
185
199
  @db_workqueue(
186
200
  once=once,
187
201
  graceful_stop=GRACEFUL_STOP,
@@ -190,7 +204,11 @@ def poller(
190
204
  sleep_time=sleep_time,
191
205
  activities=activities,
192
206
  )
193
- def _db_producer(*, activity: str, heartbeat_handler: "HeartbeatHandler"):
207
+ def _db_producer(
208
+ *,
209
+ activity: str,
210
+ heartbeat_handler: "HeartbeatHandler"
211
+ ) -> tuple[bool, list[dict[str, Any]]]:
194
212
  return _fetch_requests(
195
213
  db_bulk=db_bulk,
196
214
  older_than=older_than,
@@ -203,24 +221,26 @@ def poller(
203
221
  heartbeat_handler=heartbeat_handler,
204
222
  )
205
223
 
206
- def _consumer(transfs):
224
+ def _consumer(transfs: list[dict[str, Any]]) -> None:
207
225
  return _handle_requests(
208
226
  transfs=transfs,
209
227
  fts_bulk=fts_bulk,
210
228
  multi_vo=multi_vo,
211
- timeout=timeout,
229
+ timeout=timeout, # type: ignore (unclear if timeout is meant to be int or float)
212
230
  oidc_account=oidc_account,
213
- transfertool=transfertool,
231
+ transfertool=transfertool, # type: ignore (transfertool is not None)
232
+ transfer_stats_manager=transfer_stats_manager,
214
233
  )
215
234
 
216
- ProducerConsumerDaemon(
217
- producers=[_db_producer],
218
- consumers=[_consumer for _ in range(total_threads)],
219
- graceful_stop=GRACEFUL_STOP,
220
- ).run()
235
+ with transfer_stats_manager:
236
+ ProducerConsumerDaemon(
237
+ producers=[_db_producer],
238
+ consumers=[_consumer for _ in range(total_threads)],
239
+ graceful_stop=GRACEFUL_STOP,
240
+ ).run()
221
241
 
222
242
 
223
- def stop(signum: Optional[int] = None, frame: Optional[FrameType] = None) -> None:
243
+ def stop(signum: Optional[int] = None, frame: Optional["FrameType"] = None) -> None:
224
244
  """
225
245
  Graceful exit.
226
246
  """
@@ -229,17 +249,17 @@ def stop(signum: Optional[int] = None, frame: Optional[FrameType] = None) -> Non
229
249
 
230
250
 
231
251
  def run(
232
- once=False,
233
- sleep_time=60,
234
- activities=None,
235
- fts_bulk=100,
236
- db_bulk=1000,
237
- older_than=60,
252
+ once: bool = False,
253
+ sleep_time: int = 60,
254
+ activities: Optional[Sequence[str]] = None,
255
+ fts_bulk: int = 100,
256
+ db_bulk: int = 1000,
257
+ older_than: int = 60,
238
258
  activity_shares: Optional[str] = None,
239
- total_threads=1
240
- ):
259
+ total_threads: int = 1
260
+ ) -> None:
241
261
  """
242
- Starts up the conveyer threads.
262
+ Starts up the conveyor threads.
243
263
  """
244
264
  setup_logging(process_name=DAEMON_NAME)
245
265
 
@@ -280,19 +300,20 @@ def run(
280
300
  )
281
301
 
282
302
 
283
- def poll_transfers(transfertool_obj, transfers_by_eid, timeout=None, logger=logging.log):
303
+ def poll_transfers(
304
+ transfertool_obj: Transfertool,
305
+ transfers_by_eid: Mapping[str, Mapping[str, Any]],
306
+ transfer_stats_manager: request_core.TransferStatsManager,
307
+ timeout: "Optional[int]" = None,
308
+ logger: "LoggerFunction" = logging.log
309
+ ) -> None:
284
310
  """
285
311
  Poll a list of transfers from an FTS server
286
-
287
- :param transfertool_obj: The Transfertool to use for query
288
- :param transfers_by_eid: Dict of the form {external_id: list_of_transfers}
289
- :param timeout: Timeout.
290
- :param logger: Optional decorated logger that can be passed from the calling daemons or servers.
291
312
  """
292
313
 
293
314
  poll_individual_transfers = False
294
315
  try:
295
- _poll_transfers(transfertool_obj, transfers_by_eid, timeout, logger)
316
+ _poll_transfers(transfertool_obj, transfers_by_eid, transfer_stats_manager, timeout, logger)
296
317
  except TransferToolWrongAnswer:
297
318
  poll_individual_transfers = True
298
319
 
@@ -301,12 +322,18 @@ def poll_transfers(transfertool_obj, transfers_by_eid, timeout=None, logger=logg
301
322
  for external_id, transfers in transfers_by_eid.items():
302
323
  logger(logging.DEBUG, 'Checking %s on %s' % (external_id, transfertool_obj))
303
324
  try:
304
- _poll_transfers(transfertool_obj, {external_id: transfers}, timeout, logger)
325
+ _poll_transfers(transfertool_obj, {external_id: transfers}, transfer_stats_manager, timeout, logger)
305
326
  except Exception as err:
306
327
  logger(logging.ERROR, 'Problem querying %s on %s . Error returned : %s' % (external_id, transfertool_obj, str(err)))
307
328
 
308
329
 
309
- def _poll_transfers(transfertool_obj, transfers_by_eid, timeout, logger):
330
+ def _poll_transfers(
331
+ transfertool_obj: Transfertool,
332
+ transfers_by_eid: Mapping[str, Mapping[str, Any]],
333
+ transfer_stats_manager: request_core.TransferStatsManager,
334
+ timeout: "Optional[int]" = None,
335
+ logger: "LoggerFunction" = logging.log
336
+ ) -> None:
310
337
  """
311
338
  Helper function for poll_transfers which performs the actual polling and database update.
312
339
  """
@@ -355,17 +382,22 @@ def _poll_transfers(transfertool_obj, transfers_by_eid, timeout, logger):
355
382
  METRICS.counter('query_transfer_exception').inc()
356
383
  else:
357
384
  for request_id in request_ids.intersection(transf_resp):
358
- ret = transfer_core.update_transfer_state(transf_resp[request_id], logger=logger)
359
- # if True, really update request content; if False, only touch request
385
+ ret = transfer_core.update_transfer_state(
386
+ tt_status_report=transf_resp[request_id],
387
+ stats_manager=transfer_stats_manager,
388
+ logger=logger,
389
+ )
390
+ cnt += ret
360
391
  if ret:
361
- cnt += 1
362
- METRICS.counter('update_request_state.{updated}').labels(updated=ret).inc()
392
+ METRICS.counter('update_request_state.{updated}').labels(updated=True).inc(delta=ret)
393
+ else:
394
+ METRICS.counter('update_request_state.{updated}').labels(updated=False).inc()
363
395
 
364
396
  # should touch transfers.
365
397
  # Otherwise if one bulk transfer includes many requests and one is not terminated, the transfer will be poll again.
366
398
  transfer_core.touch_transfer(transfertool_obj.external_host, transfer_id)
367
399
  except (DatabaseException, DatabaseError) as error:
368
- if re.match('.*ORA-00054.*', error.args[0]) or re.match('.*ORA-00060.*', error.args[0]) or 'ERROR 1205 (HY000)' in error.args[0]:
400
+ if re.match(ORACLE_RESOURCE_BUSY_REGEX, error.args[0]) or re.match(ORACLE_DEADLOCK_DETECTED_REGEX, error.args[0]) or MYSQL_LOCK_WAIT_TIMEOUT_EXCEEDED in error.args[0]:
369
401
  logger(logging.WARNING, "Lock detected when handling request %s - skipping" % transfer_id)
370
402
  else:
371
403
  logger(logging.ERROR, 'Exception', exc_info=True)
@@ -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");
@@ -16,7 +15,6 @@
16
15
  import logging
17
16
  import threading
18
17
  from time import time
19
- from types import FrameType
20
18
  from typing import TYPE_CHECKING, Optional
21
19
 
22
20
  import rucio.db.sqla.util
@@ -25,21 +23,26 @@ from rucio.common.config import config_get_list
25
23
  from rucio.common.exception import RucioException
26
24
  from rucio.common.logging import setup_logging
27
25
  from rucio.core import transfer as transfer_core
28
- from rucio.core.request import set_requests_state_if_possible, list_and_mark_transfer_requests_and_source_replicas
29
- from rucio.core.topology import Topology, ExpiringObjectCache
30
- from rucio.core.transfer import prepare_transfers, list_transfer_admin_accounts, build_transfer_paths, ProtocolFactory
31
- from rucio.daemons.common import db_workqueue, ProducerConsumerDaemon
26
+ from rucio.core.request import RequestWithSources, list_and_mark_transfer_requests_and_source_replicas, transition_requests_state_if_possible
27
+ from rucio.core.topology import ExpiringObjectCache, Topology
28
+ from rucio.core.transfer import ProtocolFactory, build_transfer_paths, list_transfer_admin_accounts, prepare_transfers
29
+ from rucio.daemons.common import ProducerConsumerDaemon, db_workqueue
32
30
  from rucio.db.sqla.constants import RequestState, RequestType
33
31
 
34
32
  if TYPE_CHECKING:
33
+ from collections.abc import Mapping
34
+ from types import FrameType
35
+
35
36
  from sqlalchemy.orm import Session
37
+
38
+ from rucio.common.types import LoggerFunction
36
39
  from rucio.daemons.common import HeartbeatHandler
37
40
 
38
41
  GRACEFUL_STOP = threading.Event()
39
42
  DAEMON_NAME = 'conveyor-preparer'
40
43
 
41
44
 
42
- def stop(signum: Optional[int] = None, frame: Optional[FrameType] = None) -> None:
45
+ def stop(signum: Optional[int] = None, frame: Optional["FrameType"] = None) -> None:
43
46
  """
44
47
  Graceful exit.
45
48
  """
@@ -48,12 +51,12 @@ def stop(signum: Optional[int] = None, frame: Optional[FrameType] = None) -> Non
48
51
 
49
52
 
50
53
  def run(
51
- once=False,
52
- threads=1,
53
- sleep_time=10,
54
- bulk=100,
54
+ once: bool = False,
55
+ threads: int = 1,
56
+ sleep_time: int = 10,
57
+ bulk: int = 100,
55
58
  ignore_availability: bool = False
56
- ):
59
+ ) -> None:
57
60
  """
58
61
  Running the preparer daemon either once or by default in a loop until stop is called.
59
62
  """
@@ -75,15 +78,15 @@ def run(
75
78
 
76
79
 
77
80
  def preparer(
78
- once,
81
+ once: bool,
79
82
  sleep_time: int = 10,
80
83
  bulk: int = 100,
81
84
  ignore_availability: bool = False,
82
85
  partition_wait_time: int = 10,
83
- transfertools=None,
84
- cached_topology=None,
85
- total_threads=1
86
- ):
86
+ transfertools: Optional[list[str]] = None,
87
+ cached_topology: Optional[ExpiringObjectCache] = None,
88
+ total_threads: int = 1
89
+ ) -> None:
87
90
  # Make an initial heartbeat so that all instanced daemons have the correct worker number on the next try
88
91
  executable = DAEMON_NAME
89
92
  if not transfertools:
@@ -95,7 +98,11 @@ def preparer(
95
98
  executable=executable,
96
99
  partition_wait_time=partition_wait_time,
97
100
  sleep_time=sleep_time)
98
- def _db_producer(*, activity: str, heartbeat_handler: "HeartbeatHandler"):
101
+ def _db_producer(
102
+ *,
103
+ activity: str,
104
+ heartbeat_handler: "HeartbeatHandler"
105
+ ) -> tuple[bool, tuple[Topology, dict[str, RequestWithSources]]]:
99
106
  return _fetch_requests(
100
107
  bulk=bulk,
101
108
  ignore_availability=ignore_availability,
@@ -104,7 +111,7 @@ def preparer(
104
111
  set_last_processed_by=not once,
105
112
  )
106
113
 
107
- def _consumer(batch):
114
+ def _consumer(batch: tuple[Topology, "Mapping[str, RequestWithSources]"]) -> None:
108
115
  return _handle_requests(
109
116
  batch,
110
117
  transfertools=transfertools,
@@ -121,12 +128,12 @@ def preparer(
121
128
  def _fetch_requests(
122
129
  bulk: int,
123
130
  ignore_availability: bool,
124
- cached_topology,
131
+ cached_topology: Optional[ExpiringObjectCache],
125
132
  heartbeat_handler: "HeartbeatHandler",
126
133
  set_last_processed_by: bool,
127
134
  *,
128
- session: "Optional[Session]" = None,
129
- ):
135
+ session: Optional["Session"] = None,
136
+ ) -> tuple[bool, tuple[Topology, dict[str, RequestWithSources]]]:
130
137
  worker_number, total_workers, logger = heartbeat_handler.live()
131
138
  topology = cached_topology.get() if cached_topology else Topology(ignore_availability=ignore_availability)
132
139
  topology.configure_multihop(logger=logger, session=session)
@@ -149,12 +156,12 @@ def _fetch_requests(
149
156
 
150
157
 
151
158
  def _handle_requests(
152
- batch,
159
+ batch: tuple[Topology, "Mapping[str, RequestWithSources]"],
153
160
  *,
154
161
  transfertools: Optional[list[str]] = None,
155
162
  bulk: int = 100,
156
- logger=logging.log,
157
- ):
163
+ logger: "LoggerFunction" = logging.log,
164
+ ) -> None:
158
165
  topology, requests_with_sources = batch
159
166
 
160
167
  if not transfertools:
@@ -185,13 +192,13 @@ def _handle_requests(
185
192
  reqs_no_source.update(reqs_no_transfertool)
186
193
  if reqs_no_source:
187
194
  logger(logging.INFO, "Marking requests as no-sources: %s", reqs_no_source)
188
- set_requests_state_if_possible(reqs_no_source, RequestState.NO_SOURCES, logger=logger)
195
+ transition_requests_state_if_possible(reqs_no_source, RequestState.NO_SOURCES, logger=logger)
189
196
  if reqs_only_tape_source:
190
197
  logger(logging.INFO, "Marking requests as only-tape-sources: %s", reqs_only_tape_source)
191
- set_requests_state_if_possible(reqs_only_tape_source, RequestState.ONLY_TAPE_SOURCES, logger=logger)
198
+ transition_requests_state_if_possible(reqs_only_tape_source, RequestState.ONLY_TAPE_SOURCES, logger=logger)
192
199
  if reqs_scheme_mismatch:
193
200
  logger(logging.INFO, "Marking requests as scheme-mismatch: %s", reqs_scheme_mismatch)
194
- set_requests_state_if_possible(reqs_scheme_mismatch, RequestState.MISMATCH_SCHEME, logger=logger)
201
+ transition_requests_state_if_possible(reqs_scheme_mismatch, RequestState.MISMATCH_SCHEME, logger=logger)
195
202
  except RucioException:
196
203
  logger(logging.ERROR, 'errored with a RucioException, retrying later', exc_info=True)
197
204
  updated_msg = 'errored'
@@ -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");
@@ -23,8 +22,7 @@ import socket
23
22
  import threading
24
23
  import time
25
24
  import traceback
26
- from types import FrameType
27
- from typing import Optional
25
+ from typing import TYPE_CHECKING, Any, Optional
28
26
 
29
27
  import stomp
30
28
 
@@ -33,12 +31,21 @@ from rucio.common import exception
33
31
  from rucio.common.config import config_get, config_get_bool, config_get_int
34
32
  from rucio.common.logging import setup_logging
35
33
  from rucio.common.policy import get_policy
34
+ from rucio.core import request as request_core
36
35
  from rucio.core import transfer as transfer_core
37
36
  from rucio.core.monitor import MetricManager
38
37
  from rucio.daemons.common import HeartbeatHandler
39
38
  from rucio.db.sqla.session import transactional_session
40
39
  from rucio.transfertool.fts3 import FTS3CompletionMessageTransferStatusReport
41
40
 
41
+ if TYPE_CHECKING:
42
+ from types import FrameType
43
+
44
+ from sqlalchemy.orm import Session
45
+ from stomp.utils import Frame
46
+
47
+ from rucio.common.types import LoggerFunction
48
+
42
49
  logging.getLogger("stomp").setLevel(logging.CRITICAL)
43
50
 
44
51
  METRICS = MetricManager(module=__name__)
@@ -46,21 +53,29 @@ GRACEFUL_STOP = threading.Event()
46
53
  DAEMON_NAME = 'conveyor-receiver'
47
54
 
48
55
 
49
- class Receiver(object):
56
+ class Receiver:
50
57
 
51
- def __init__(self, broker, id_, total_threads, all_vos=False):
58
+ def __init__(
59
+ self,
60
+ broker: str,
61
+ id_: str,
62
+ total_threads: int,
63
+ transfer_stats_manager: request_core.TransferStatsManager,
64
+ all_vos: bool = False
65
+ ):
52
66
  self.__all_vos = all_vos
53
67
  self.__broker = broker
54
68
  self.__id = id_
55
69
  self.__total_threads = total_threads
70
+ self._transfer_stats_manager = transfer_stats_manager
56
71
 
57
72
  @METRICS.count_it
58
- def on_error(self, frame):
73
+ def on_error(self, frame: "Frame") -> None:
59
74
  logging.error('[%s] %s' % (self.__broker, frame.body))
60
75
 
61
76
  @METRICS.count_it
62
- def on_message(self, frame):
63
- msg = json.loads(frame.body)
77
+ def on_message(self, frame: "Frame") -> None:
78
+ msg = json.loads(frame.body) # type: ignore
64
79
 
65
80
  if not self.__all_vos:
66
81
  if 'vo' not in msg or msg['vo'] != get_policy():
@@ -69,29 +84,47 @@ class Receiver(object):
69
84
  if 'job_metadata' in msg.keys() \
70
85
  and isinstance(msg['job_metadata'], dict) \
71
86
  and 'issuer' in msg['job_metadata'].keys() \
72
- and str(msg['job_metadata']['issuer']) == str('rucio'):
87
+ and str(msg['job_metadata']['issuer']) == 'rucio':
73
88
 
74
- if 'job_state' in msg.keys() and (str(msg['job_state']) != str('ACTIVE') or msg.get('job_multihop', False) is True):
89
+ if 'job_state' in msg.keys() and (str(msg['job_state']) != 'ACTIVE' or msg.get('job_multihop', False) is True):
75
90
  METRICS.counter('message_rucio').inc()
76
91
 
77
92
  self._perform_request_update(msg)
78
93
 
79
94
  @transactional_session
80
- def _perform_request_update(self, msg, *, session=None, logger=logging.log):
95
+ def _perform_request_update(
96
+ self,
97
+ msg: dict[str, Any],
98
+ *,
99
+ session: Optional["Session"] = None,
100
+ logger: "LoggerFunction" = logging.log
101
+ ) -> None:
81
102
  external_host = msg.get('endpnt', None)
82
103
  request_id = msg['file_metadata'].get('request_id', None)
83
104
  try:
84
105
  tt_status_report = FTS3CompletionMessageTransferStatusReport(external_host, request_id=request_id, fts_message=msg)
85
- if tt_status_report.get_db_fields_to_update(session=session, logger=logger):
106
+ if tt_status_report.get_db_fields_to_update(session=session, logger=logger): # type: ignore
86
107
  logging.info('RECEIVED %s', tt_status_report)
87
108
 
88
- ret = transfer_core.update_transfer_state(tt_status_report, session=session, logger=logger)
89
- METRICS.counter('update_request_state.{updated}').labels(updated=ret).inc()
109
+ ret = transfer_core.update_transfer_state(
110
+ tt_status_report=tt_status_report,
111
+ stats_manager=self._transfer_stats_manager,
112
+ session=session,
113
+ logger=logger,
114
+ )
115
+ if ret:
116
+ METRICS.counter('update_request_state.{updated}').labels(updated=True).inc(delta=ret)
117
+ else:
118
+ METRICS.counter('update_request_state.{updated}').labels(updated=False).inc()
90
119
  except Exception:
91
120
  logging.critical(traceback.format_exc())
92
121
 
93
122
 
94
- def receiver(id_, total_threads=1, all_vos=False):
123
+ def receiver(
124
+ id_: str,
125
+ total_threads: int = 1,
126
+ all_vos: bool = False
127
+ ) -> None:
95
128
  """
96
129
  Main loop to consume messages from the FTS3 producer.
97
130
  """
@@ -146,8 +179,8 @@ def receiver(id_, total_threads=1, all_vos=False):
146
179
 
147
180
  logging.info('receiver started')
148
181
 
149
- with HeartbeatHandler(executable=DAEMON_NAME, renewal_interval=30) as heartbeat_handler:
150
-
182
+ with (HeartbeatHandler(executable=DAEMON_NAME, renewal_interval=30) as heartbeat_handler,
183
+ request_core.TransferStatsManager() as transfer_stats_manager):
151
184
  while not GRACEFUL_STOP.is_set():
152
185
 
153
186
  _, _, logger = heartbeat_handler.live()
@@ -158,8 +191,15 @@ def receiver(id_, total_threads=1, all_vos=False):
158
191
  logger(logging.INFO, 'connecting to %s' % conn.transport._Transport__host_and_ports[0][0])
159
192
  METRICS.counter('reconnect.{host}').labels(host=conn.transport._Transport__host_and_ports[0][0].split('.')[0]).inc()
160
193
 
161
- conn.set_listener('rucio-messaging-fts3', Receiver(broker=conn.transport._Transport__host_and_ports[0],
162
- id_=id_, total_threads=total_threads, all_vos=all_vos))
194
+ conn.set_listener(
195
+ 'rucio-messaging-fts3',
196
+ Receiver(
197
+ broker=conn.transport._Transport__host_and_ports[0],
198
+ id_=id_,
199
+ total_threads=total_threads,
200
+ transfer_stats_manager=transfer_stats_manager,
201
+ all_vos=all_vos
202
+ ))
163
203
  if not use_ssl:
164
204
  conn.connect(username, password, wait=True)
165
205
  else:
@@ -176,7 +216,7 @@ def receiver(id_, total_threads=1, all_vos=False):
176
216
  pass
177
217
 
178
218
 
179
- def stop(signum: "Optional[int]" = None, frame: "Optional[FrameType]" = None) -> None:
219
+ def stop(signum: Optional[int] = None, frame: Optional["FrameType"] = None) -> None:
180
220
  """
181
221
  Graceful exit.
182
222
  """
@@ -184,7 +224,10 @@ def stop(signum: "Optional[int]" = None, frame: "Optional[FrameType]" = None) ->
184
224
  GRACEFUL_STOP.set()
185
225
 
186
226
 
187
- def run(once=False, total_threads=1):
227
+ def run(
228
+ once: bool = False,
229
+ total_threads: int = 1
230
+ ) -> None:
188
231
  """
189
232
  Starts up the receiver thread
190
233
  """