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
rucio/core/heartbeat.py CHANGED
@@ -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");
@@ -15,26 +14,45 @@
15
14
 
16
15
  import datetime
17
16
  import hashlib
18
- from typing import TYPE_CHECKING
17
+ from typing import TYPE_CHECKING, Optional
19
18
 
20
- from sqlalchemy import func
21
- from sqlalchemy.sql import distinct
19
+ from sqlalchemy import and_, delete, func, select, update
22
20
 
23
21
  from rucio.common.exception import DatabaseException
24
22
  from rucio.common.utils import pid_exists
25
- from rucio.db.sqla.models import Heartbeats
23
+ from rucio.db.sqla.models import Heartbeat
26
24
  from rucio.db.sqla.session import read_session, transactional_session
27
25
 
28
26
  if TYPE_CHECKING:
27
+ from threading import Thread
28
+ from typing import TypedDict
29
+
29
30
  from sqlalchemy.orm import Session
30
31
 
32
+ class HeartbeatDict(TypedDict):
33
+ readable: Optional[str]
34
+ hostname: str
35
+ pid: int
36
+ thread_name: Optional[str]
37
+ updated_at: datetime.datetime
38
+ created_at: datetime.datetime
39
+ payload: Optional[str]
40
+ test: int
31
41
 
32
42
  DEFAULT_EXPIRATION_DELAY = datetime.timedelta(days=1).total_seconds()
33
43
 
34
44
 
35
45
  @transactional_session
36
- def sanity_check(executable, hostname, hash_executable=None, pid=None, thread=None,
37
- expiration_delay=DEFAULT_EXPIRATION_DELAY, *, session: "Session"):
46
+ def sanity_check(
47
+ executable: str,
48
+ hostname: str,
49
+ hash_executable: Optional[str] = None,
50
+ pid: Optional[int] = None,
51
+ thread: Optional["Thread"] = None,
52
+ expiration_delay: float = DEFAULT_EXPIRATION_DELAY,
53
+ *,
54
+ session: "Session"
55
+ ) -> None:
38
56
  """
39
57
  sanity_check wrapper to ignore DatabaseException errors.
40
58
 
@@ -57,7 +75,14 @@ def sanity_check(executable, hostname, hash_executable=None, pid=None, thread=No
57
75
 
58
76
 
59
77
  @transactional_session
60
- def _sanity_check(executable, hostname, hash_executable=None, expiration_delay=DEFAULT_EXPIRATION_DELAY, *, session: "Session"):
78
+ def _sanity_check(
79
+ executable: str,
80
+ hostname: str,
81
+ hash_executable: Optional[str] = None,
82
+ expiration_delay: float = DEFAULT_EXPIRATION_DELAY,
83
+ *,
84
+ session: "Session"
85
+ ) -> None:
61
86
  """
62
87
  Check if processes on the host are still running.
63
88
 
@@ -67,24 +92,56 @@ def _sanity_check(executable, hostname, hash_executable=None, expiration_delay=D
67
92
  :param expiration_delay: time (in seconds) after which any inactive health check will be removed
68
93
  :param session: The database session in use.
69
94
  """
95
+ base_stmt = select(
96
+ Heartbeat.pid
97
+ ).distinct(
98
+ ).where(
99
+ Heartbeat.hostname == hostname
100
+ )
70
101
  if executable:
71
102
  if not hash_executable:
72
103
  hash_executable = calc_hash(executable)
73
104
 
74
- for pid, in session.query(distinct(Heartbeats.pid)).filter_by(executable=hash_executable, hostname=hostname):
105
+ stmt = base_stmt.where(
106
+ Heartbeat.executable == hash_executable
107
+ )
108
+ for pid in session.execute(stmt).scalars().all():
75
109
  if not pid_exists(pid):
76
- session.query(Heartbeats).filter_by(executable=hash_executable, hostname=hostname, pid=pid).delete()
110
+ stmt = delete(
111
+ Heartbeat
112
+ ).where(
113
+ and_(Heartbeat.executable == hash_executable,
114
+ Heartbeat.hostname == hostname,
115
+ Heartbeat.pid == pid)
116
+ )
117
+ session.execute(stmt)
77
118
  else:
78
- for pid, in session.query(distinct(Heartbeats.pid)).filter_by(hostname=hostname):
119
+ for pid in session.execute(base_stmt).scalars().all():
79
120
  if not pid_exists(pid):
80
- session.query(Heartbeats).filter_by(hostname=hostname, pid=pid).delete()
121
+ stmt = delete(
122
+ Heartbeat
123
+ ).where(
124
+ and_(Heartbeat.hostname == hostname,
125
+ Heartbeat.pid == pid)
126
+ )
127
+ session.execute(stmt)
81
128
 
82
129
  if expiration_delay:
83
130
  cardiac_arrest(older_than=expiration_delay, session=session)
84
131
 
85
132
 
86
133
  @transactional_session
87
- def live(executable, hostname, pid, thread=None, older_than=600, hash_executable=None, payload=None, *, session: "Session"):
134
+ def live(
135
+ executable: str,
136
+ hostname: str,
137
+ pid: int,
138
+ thread: Optional["Thread"] = None,
139
+ older_than: int = 600,
140
+ hash_executable: Optional[str] = None,
141
+ payload: Optional[str] = None,
142
+ *,
143
+ session: "Session"
144
+ ) -> dict[str, int]:
88
145
  """
89
146
  Register a heartbeat for a process/thread on a given node.
90
147
  The executable name is used for the calculation of thread assignments.
@@ -114,35 +171,48 @@ def live(executable, hostname, pid, thread=None, older_than=600, hash_executable
114
171
  thread_name = "thread"
115
172
 
116
173
  # upsert the heartbeat
117
- rowcount = session.query(Heartbeats)\
118
- .filter_by(executable=hash_executable,
119
- hostname=hostname,
120
- pid=pid,
121
- thread_id=thread_id)\
122
- .update({'updated_at': datetime.datetime.utcnow(), 'payload': payload})
123
- if not rowcount:
124
- Heartbeats(executable=hash_executable,
125
- readable=executable[:Heartbeats.readable.property.columns[0].type.length],
126
- hostname=hostname,
127
- pid=pid,
128
- thread_id=thread_id,
129
- thread_name=thread_name,
130
- payload=payload).save(session=session)
174
+ stmt = update(
175
+ Heartbeat
176
+ ).where(
177
+ and_(Heartbeat.executable == hash_executable,
178
+ Heartbeat.hostname == hostname,
179
+ Heartbeat.pid == pid,
180
+ Heartbeat.thread_id == thread_id)
181
+ ).values({
182
+ Heartbeat.updated_at: datetime.datetime.utcnow(),
183
+ Heartbeat.payload: payload
184
+ })
185
+ if not session.execute(stmt).rowcount:
186
+ Heartbeat(executable=hash_executable,
187
+ readable=executable[:Heartbeat.readable.property.columns[0].type.length],
188
+ hostname=hostname,
189
+ pid=pid,
190
+ thread_id=thread_id,
191
+ thread_name=thread_name,
192
+ payload=payload).save(session=session)
131
193
 
132
194
  # assign thread identifier
133
- query = session.query(Heartbeats.hostname,
134
- Heartbeats.pid,
135
- Heartbeats.thread_id)\
136
- .with_hint(Heartbeats, "index(HEARTBEATS HEARTBEATS_PK)", 'oracle')\
137
- .filter(Heartbeats.executable == hash_executable)\
138
- .filter(Heartbeats.updated_at >= datetime.datetime.utcnow() - datetime.timedelta(seconds=older_than))\
139
- .group_by(Heartbeats.hostname,
140
- Heartbeats.pid,
141
- Heartbeats.thread_id)\
142
- .order_by(Heartbeats.hostname,
143
- Heartbeats.pid,
144
- Heartbeats.thread_id)
145
- result = query.all()
195
+ stmt = select(
196
+ Heartbeat.hostname,
197
+ Heartbeat.pid,
198
+ Heartbeat.thread_id
199
+ ).with_hint(
200
+ Heartbeat,
201
+ 'INDEX(HEARTBEATS HEARTBEATS_PK)',
202
+ 'oracle'
203
+ ).where(
204
+ and_(Heartbeat.executable == hash_executable,
205
+ Heartbeat.updated_at >= datetime.datetime.utcnow() - datetime.timedelta(seconds=older_than))
206
+ ).group_by(
207
+ Heartbeat.hostname,
208
+ Heartbeat.pid,
209
+ Heartbeat.thread_id
210
+ ).order_by(
211
+ Heartbeat.hostname,
212
+ Heartbeat.pid,
213
+ Heartbeat.thread_id
214
+ )
215
+ result = session.execute(stmt).all()
146
216
 
147
217
  # there is no universally applicable rownumber in SQLAlchemy
148
218
  # so we have to do it in Python
@@ -157,7 +227,16 @@ def live(executable, hostname, pid, thread=None, older_than=600, hash_executable
157
227
 
158
228
 
159
229
  @transactional_session
160
- def die(executable, hostname, pid, thread, older_than=None, hash_executable=None, *, session: "Session"):
230
+ def die(
231
+ executable: str,
232
+ hostname: str,
233
+ pid: int,
234
+ thread: "Thread",
235
+ older_than: Optional[int] = None,
236
+ hash_executable: Optional[str] = None,
237
+ *,
238
+ session: "Session"
239
+ ) -> None:
161
240
  """
162
241
  Remove a single heartbeat older than specified.
163
242
 
@@ -168,25 +247,28 @@ def die(executable, hostname, pid, thread, older_than=None, hash_executable=None
168
247
  :param older_than: Removes specified heartbeats older than specified nr of seconds
169
248
  :param hash_executable: Hash of the executable.
170
249
  :param session: The database session in use.
171
-
172
- :returns heartbeats: Dictionary {assign_thread, nr_threads}
173
250
  """
174
251
  if not hash_executable:
175
252
  hash_executable = calc_hash(executable)
176
253
 
177
- query = session.query(Heartbeats).filter_by(executable=hash_executable,
178
- hostname=hostname,
179
- pid=pid,
180
- thread_id=thread.ident)
254
+ stmt = delete(
255
+ Heartbeat
256
+ ).where(
257
+ and_(Heartbeat.executable == hash_executable,
258
+ Heartbeat.hostname == hostname,
259
+ Heartbeat.pid == pid,
260
+ Heartbeat.thread_id == thread.ident)
261
+ )
181
262
 
182
263
  if older_than:
183
- query = query.filter(Heartbeats.updated_at < datetime.datetime.utcnow() - datetime.timedelta(seconds=older_than))
184
-
185
- query.delete()
264
+ stmt = stmt.where(
265
+ Heartbeat.updated_at < datetime.datetime.utcnow() - datetime.timedelta(seconds=older_than)
266
+ )
267
+ session.execute(stmt)
186
268
 
187
269
 
188
270
  @transactional_session
189
- def cardiac_arrest(older_than=None, *, session: "Session"):
271
+ def cardiac_arrest(older_than: Optional[int] = None, *, session: "Session") -> None:
190
272
  """
191
273
  Removes all heartbeats older than specified.
192
274
 
@@ -194,35 +276,42 @@ def cardiac_arrest(older_than=None, *, session: "Session"):
194
276
  :param session: The database session in use.
195
277
  """
196
278
 
197
- query = session.query(Heartbeats)
279
+ stmt = delete(
280
+ Heartbeat
281
+ )
198
282
 
199
283
  if older_than:
200
- query = query.filter(Heartbeats.updated_at < datetime.datetime.utcnow() - datetime.timedelta(seconds=older_than))
201
-
202
- query.delete()
284
+ stmt = stmt.where(
285
+ Heartbeat.updated_at < datetime.datetime.utcnow() - datetime.timedelta(seconds=older_than)
286
+ )
287
+ session.execute(stmt)
203
288
 
204
289
 
205
290
  @read_session
206
- def list_heartbeats(*, session: "Session"):
291
+ def list_heartbeats(*, session: "Session") -> list["HeartbeatDict"]:
207
292
  """
208
293
  List all heartbeats.
209
294
 
210
295
  :param session: The database session in use.
211
296
 
212
- :returns: List of tuples
297
+ :returns: List of dicts
213
298
  """
214
299
 
215
- query = session.query(Heartbeats.readable,
216
- Heartbeats.hostname,
217
- Heartbeats.pid,
218
- Heartbeats.thread_name,
219
- Heartbeats.updated_at,
220
- Heartbeats.created_at,
221
- Heartbeats.payload).order_by(Heartbeats.readable,
222
- Heartbeats.hostname,
223
- Heartbeats.thread_name)
224
-
225
- result = query.all()
300
+ stmt = select(
301
+ Heartbeat.readable,
302
+ Heartbeat.hostname,
303
+ Heartbeat.pid,
304
+ Heartbeat.thread_name,
305
+ Heartbeat.updated_at,
306
+ Heartbeat.created_at,
307
+ Heartbeat.payload
308
+ ).order_by(
309
+ Heartbeat.readable,
310
+ Heartbeat.hostname,
311
+ Heartbeat.thread_name
312
+ )
313
+
314
+ result = session.execute(stmt).all()
226
315
  json_result = []
227
316
  for element in result:
228
317
  json_result.append(element._asdict())
@@ -230,7 +319,13 @@ def list_heartbeats(*, session: "Session"):
230
319
 
231
320
 
232
321
  @read_session
233
- def list_payload_counts(executable, older_than=600, hash_executable=None, *, session: "Session"):
322
+ def list_payload_counts(
323
+ executable: str,
324
+ older_than: int = 600,
325
+ hash_executable: Optional[str] = None,
326
+ *,
327
+ session: "Session"
328
+ ) -> dict[str, int]:
234
329
  """
235
330
  Give the counts of number of threads per payload for a certain executable.
236
331
 
@@ -239,22 +334,27 @@ def list_payload_counts(executable, older_than=600, hash_executable=None, *, ses
239
334
  :param hash_executable: Hash of the executable.
240
335
  :param session: The database session in use.
241
336
 
242
- :returns: List of tuples
337
+ :returns: Dict
243
338
  """
244
339
 
245
340
  if not hash_executable:
246
341
  hash_executable = calc_hash(executable)
247
- query = session.query(Heartbeats.payload,
248
- func.count(Heartbeats.payload))\
249
- .filter(Heartbeats.executable == hash_executable)\
250
- .filter(Heartbeats.updated_at >= datetime.datetime.utcnow() - datetime.timedelta(seconds=older_than))\
251
- .group_by(Heartbeats.payload)\
252
- .order_by(Heartbeats.payload)
253
-
254
- return dict((payload, count) for payload, count in query.all() if payload)
255
-
256
-
257
- def calc_hash(executable):
342
+ stmt = select(
343
+ Heartbeat.payload,
344
+ func.count(Heartbeat.payload)
345
+ ).where(
346
+ and_(Heartbeat.executable == hash_executable,
347
+ Heartbeat.updated_at >= datetime.datetime.utcnow() - datetime.timedelta(seconds=older_than))
348
+ ).group_by(
349
+ Heartbeat.payload
350
+ ).order_by(
351
+ Heartbeat.payload
352
+ )
353
+
354
+ return dict((payload, count) for payload, count in session.execute(stmt).all() if payload)
355
+
356
+
357
+ def calc_hash(executable: str) -> str:
258
358
  """
259
359
  Calculates a SHA256 hash.
260
360
 
rucio/core/identity.py CHANGED
@@ -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,8 +15,7 @@
16
15
  import hashlib
17
16
  import os
18
17
  from re import match
19
- from typing import Optional
20
- from typing import TYPE_CHECKING
18
+ from typing import TYPE_CHECKING, Optional
21
19
 
22
20
  from sqlalchemy import select, true
23
21
  from sqlalchemy.exc import IntegrityError
@@ -30,11 +28,14 @@ from rucio.db.sqla.constants import IdentityType
30
28
  from rucio.db.sqla.session import read_session, transactional_session
31
29
 
32
30
  if TYPE_CHECKING:
31
+ from collections.abc import Sequence
32
+
33
+ from sqlalchemy import Row
33
34
  from sqlalchemy.orm import Session
34
35
 
35
36
 
36
37
  @transactional_session
37
- def add_identity(identity: str, type_: IdentityType, email: str, password: Optional[str] = None, *, session: "Session"):
38
+ def add_identity(identity: str, type_: IdentityType, email: str, password: Optional[str] = None, *, session: "Session") -> None:
38
39
  """
39
40
  Creates a user identity.
40
41
 
@@ -103,7 +104,7 @@ def verify_identity(identity: str, type_: IdentityType, password: Optional[str]
103
104
 
104
105
 
105
106
  @transactional_session
106
- def del_identity(identity: str, type_: IdentityType, *, session: "Session"):
107
+ def del_identity(identity: str, type_: IdentityType, *, session: "Session") -> None:
107
108
  """
108
109
  Deletes a user identity.
109
110
 
@@ -125,7 +126,16 @@ def del_identity(identity: str, type_: IdentityType, *, session: "Session"):
125
126
 
126
127
 
127
128
  @transactional_session
128
- def add_account_identity(identity: str, type_: IdentityType, account: InternalAccount, email: str, default: bool = False, password: str = None, *, session: "Session"):
129
+ def add_account_identity(
130
+ identity: str,
131
+ type_: IdentityType,
132
+ account: InternalAccount,
133
+ email: str,
134
+ default: bool = False,
135
+ password: Optional[str] = None,
136
+ *,
137
+ session: "Session"
138
+ ) -> None:
129
139
  """
130
140
  Adds a membership association between identity and account.
131
141
 
@@ -167,7 +177,7 @@ def add_account_identity(identity: str, type_: IdentityType, account: InternalAc
167
177
 
168
178
 
169
179
  @read_session
170
- def exist_identity_account(identity: str, type_: IdentityType, account: InternalAccount, *, session: "Session"):
180
+ def exist_identity_account(identity: str, type_: IdentityType, account: InternalAccount, *, session: "Session") -> bool:
171
181
  """
172
182
  Check if an identity is mapped to an account.
173
183
 
@@ -189,13 +199,13 @@ def exist_identity_account(identity: str, type_: IdentityType, account: Internal
189
199
 
190
200
 
191
201
  @read_session
192
- def get_default_account(identity: str, type_: IdentityType, oldest_if_none: bool = False, *, session: "Session"):
202
+ def get_default_account(identity: str, type_: IdentityType, oldest_if_none: bool = False, *, session: "Session") -> Optional[InternalAccount]:
193
203
  """
194
204
  Retrieves the default account mapped to an identity.
195
205
 
196
206
  :param identity: The identity key name. For example, x509DN, or a username.
197
207
  :param type_: The type of the authentication (x509, gss, userpass, saml, oidc).
198
- :param oldest_if_none: If True and no default account it found the oldes known
208
+ :param oldest_if_none: If True and no default account it found the oldest known
199
209
  account of that identity will be chosen, if False and
200
210
  no default account is found, exception will be raised.
201
211
  :param session: The database session to use.
@@ -230,7 +240,7 @@ def get_default_account(identity: str, type_: IdentityType, oldest_if_none: bool
230
240
 
231
241
 
232
242
  @transactional_session
233
- def del_account_identity(identity: str, type_: IdentityType, account: InternalAccount, *, session: "Session"):
243
+ def del_account_identity(identity: str, type_: IdentityType, account: InternalAccount, *, session: "Session") -> None:
234
244
  """
235
245
  Removes a membership association between identity and account.
236
246
 
@@ -253,7 +263,7 @@ def del_account_identity(identity: str, type_: IdentityType, account: InternalAc
253
263
 
254
264
 
255
265
  @read_session
256
- def list_identities(*, session: "Session", **kwargs):
266
+ def list_identities(*, session: "Session", **kwargs) -> "Sequence[Row[tuple[str, IdentityType]]]":
257
267
  """
258
268
  Returns a list of all identities.
259
269
 
@@ -271,7 +281,7 @@ def list_identities(*, session: "Session", **kwargs):
271
281
 
272
282
 
273
283
  @read_session
274
- def list_accounts_for_identity(identity: str, type_: IdentityType, *, session: "Session"):
284
+ def list_accounts_for_identity(identity: str, type_: IdentityType, *, session: "Session") -> "Sequence[InternalAccount]":
275
285
  """
276
286
  Returns a list of all accounts for an identity.
277
287
 
rucio/core/importer.py CHANGED
@@ -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");
@@ -13,14 +12,21 @@
13
12
  # See the License for the specific language governing permissions and
14
13
  # limitations under the License.
15
14
 
16
- from typing import TYPE_CHECKING
15
+ from collections.abc import Iterable
16
+ from typing import TYPE_CHECKING, Any
17
+
18
+ from sqlalchemy import select
17
19
 
18
20
  from rucio.common.config import config_get
21
+ from rucio.common.constants import RseAttr
19
22
  from rucio.common.exception import RSEOperationNotSupported
20
23
  from rucio.common.types import InternalAccount
21
- from rucio.core import rse as rse_module, distance as distance_module, account as account_module, identity as identity_module
24
+ from rucio.core import account as account_module
25
+ from rucio.core import distance as distance_module
26
+ from rucio.core import identity as identity_module
27
+ from rucio.core import rse as rse_module
22
28
  from rucio.db.sqla import models
23
- from rucio.db.sqla.constants import RSEType, AccountType, IdentityType
29
+ from rucio.db.sqla.constants import AccountType, IdentityType, RSEType
24
30
  from rucio.db.sqla.session import transactional_session
25
31
 
26
32
  if TYPE_CHECKING:
@@ -28,7 +34,7 @@ if TYPE_CHECKING:
28
34
 
29
35
 
30
36
  @transactional_session
31
- def import_rses(rses, rse_sync_method='edit', attr_sync_method='edit', protocol_sync_method='edit', vo='def', *, session: "Session"):
37
+ def import_rses(rses: dict[str, dict[str, Any]], rse_sync_method: str = 'edit', attr_sync_method: str = 'edit', protocol_sync_method: str = 'edit', vo: str = 'def', *, session: "Session") -> None:
32
38
  new_rses = []
33
39
  for rse_name in rses:
34
40
  rse = rses[rse_name]
@@ -104,8 +110,8 @@ def import_rses(rses, rse_sync_method='edit', attr_sync_method='edit', protocol_
104
110
 
105
111
  # Attributes
106
112
  attributes = rse.get('attributes', {})
107
- attributes['lfn2pfn_algorithm'] = rse.get('lfn2pfn_algorithm')
108
- attributes['verify_checksum'] = rse.get('verify_checksum')
113
+ attributes[RseAttr.LFN2PFN_ALGORITHM] = rse.get('lfn2pfn_algorithm')
114
+ attributes[RseAttr.VERIFY_CHECKSUM] = rse.get('verify_checksum')
109
115
 
110
116
  old_attributes = rse_module.list_rse_attributes(rse_id=rse_id, session=session)
111
117
  missing_attributes = [attribute for attribute in old_attributes if attribute not in attributes]
@@ -136,7 +142,7 @@ def import_rses(rses, rse_sync_method='edit', attr_sync_method='edit', protocol_
136
142
 
137
143
 
138
144
  @transactional_session
139
- def import_distances(distances, vo='def', *, session: "Session"):
145
+ def import_distances(distances, vo: str = 'def', *, session: "Session") -> None:
140
146
  for src_rse_name in distances:
141
147
  src = rse_module.get_rse_id(rse=src_rse_name, vo=vo, session=session)
142
148
  for dest_rse_name in distances[src_rse_name]:
@@ -156,7 +162,7 @@ def import_distances(distances, vo='def', *, session: "Session"):
156
162
 
157
163
 
158
164
  @transactional_session
159
- def import_identities(identities, account_name, old_identities, old_identity_account, account_email, *, session: "Session"):
165
+ def import_identities(identities: Iterable[dict[str, Any]], account_name: str, old_identities: Iterable[tuple], old_identity_account: tuple[str, str, str], account_email: str, *, session: "Session") -> None:
160
166
  for identity in identities:
161
167
  identity['type'] = IdentityType[identity['type'].upper()]
162
168
 
@@ -185,14 +191,19 @@ def import_identities(identities, account_name, old_identities, old_identity_acc
185
191
 
186
192
 
187
193
  @transactional_session
188
- def import_accounts(accounts, vo='def', *, session: "Session"):
194
+ def import_accounts(accounts: Iterable[dict[str, Any]], vo: str = 'def', *, session: "Session") -> None:
189
195
  vo_filter = {'account': InternalAccount(account='*', vo=vo)}
190
196
  old_accounts = {account['account']: account for account in account_module.list_accounts(filter_=vo_filter, session=session)}
191
197
  missing_accounts = [account for account in accounts if account['account'] not in old_accounts]
192
198
  outdated_accounts = [account for account in accounts if account['account'] in old_accounts]
193
199
  to_be_removed_accounts = [old_account for old_account in old_accounts if old_account not in [account['account'] for account in accounts]]
194
200
  old_identities = identity_module.list_identities(session=session)
195
- old_identity_account = session.query(models.IdentityAccountAssociation.identity, models.IdentityAccountAssociation.identity_type, models.IdentityAccountAssociation.account).all()
201
+ stmt = select(
202
+ models.IdentityAccountAssociation.identity,
203
+ models.IdentityAccountAssociation.identity_type,
204
+ models.IdentityAccountAssociation.account
205
+ )
206
+ old_identity_account = session.execute(stmt).all()
196
207
 
197
208
  # add missing accounts
198
209
  for account_dict in missing_accounts:
@@ -222,7 +233,7 @@ def import_accounts(accounts, vo='def', *, session: "Session"):
222
233
 
223
234
 
224
235
  @transactional_session
225
- def import_data(data, vo='def', *, session: "Session"):
236
+ def import_data(data: dict[str, Any], vo: str = 'def', *, session: "Session") -> None:
226
237
  """
227
238
  Import data to add and update records in Rucio.
228
239