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");
@@ -15,8 +14,8 @@
15
14
 
16
15
  from typing import TYPE_CHECKING
17
16
 
18
- from sqlalchemy.orm.exc import NoResultFound
19
- from sqlalchemy.sql import func, select, literal
17
+ from sqlalchemy.exc import NoResultFound
18
+ from sqlalchemy.sql import func, literal, select
20
19
  from sqlalchemy.sql.expression import and_, or_
21
20
 
22
21
  from rucio.core.account import get_all_rse_usages_per_account
@@ -99,9 +98,17 @@ def get_global_account_limits(account=None, *, session: "Session"):
99
98
  :return: Dict {'MOCK': {'resolved_rses': ['MOCK'], 'limit': 10, 'resolved_rse_ids': [123]}}.
100
99
  """
101
100
  if account:
102
- global_account_limits = session.query(models.AccountGlobalLimit).filter_by(account=account).all()
101
+ stmt = select(
102
+ models.AccountGlobalLimit
103
+ ).where(
104
+ models.AccountGlobalLimit.account == account
105
+ )
106
+ global_account_limits = session.execute(stmt).scalars().all()
103
107
  else:
104
- global_account_limits = session.query(models.AccountGlobalLimit).all()
108
+ stmt = select(
109
+ models.AccountGlobalLimit
110
+ )
111
+ global_account_limits = session.execute(stmt).scalars().all()
105
112
 
106
113
  resolved_global_account_limits = {}
107
114
  for limit in global_account_limits:
@@ -131,7 +138,13 @@ def get_global_account_limit(account, rse_expression, *, session: "Session"):
131
138
  :return: Limit in Bytes.
132
139
  """
133
140
  try:
134
- global_account_limit = session.query(models.AccountGlobalLimit).filter_by(account=account, rse_expression=rse_expression).one()
141
+ stmt = select(
142
+ models.AccountGlobalLimit
143
+ ).where(
144
+ and_(models.AccountGlobalLimit.account == account,
145
+ models.AccountGlobalLimit.rse_expression == rse_expression)
146
+ )
147
+ global_account_limit = session.execute(stmt).scalar_one()
135
148
  if global_account_limit.bytes == -1:
136
149
  return float("inf")
137
150
  else:
@@ -151,8 +164,13 @@ def get_local_account_limit(account, rse_id, *, session: "Session"):
151
164
  :return: Limit in Bytes.
152
165
  """
153
166
  try:
154
- account_limit = session.query(models.AccountLimit).filter(models.AccountLimit.account == account,
155
- models.AccountLimit.rse_id == rse_id).one()
167
+ stmt = select(
168
+ models.AccountLimit
169
+ ).where(
170
+ and_(models.AccountLimit.account == account,
171
+ models.AccountLimit.rse_id == rse_id)
172
+ )
173
+ account_limit = session.execute(stmt).scalar_one()
156
174
  if account_limit.bytes == -1:
157
175
  return float("inf")
158
176
  else:
@@ -176,17 +194,28 @@ def get_local_account_limits(account, rse_ids=None, *, session: "Session"):
176
194
  if rse_ids:
177
195
  rse_id_clauses = []
178
196
  for rse_id in rse_ids:
179
- rse_id_clauses.append(and_(models.AccountLimit.rse_id == rse_id, models.AccountLimit.account == account))
197
+ rse_id_clauses.append(and_(models.AccountLimit.rse_id == rse_id,
198
+ models.AccountLimit.account == account))
180
199
  rse_id_clause_chunks = [rse_id_clauses[x:x + 10] for x in range(0, len(rse_id_clauses), 10)]
181
200
  for rse_id_chunk in rse_id_clause_chunks:
182
- tmp_limits = session.query(models.AccountLimit).filter(or_(*rse_id_chunk)).all()
201
+ stmt = select(
202
+ models.AccountLimit
203
+ ).where(
204
+ or_(*rse_id_chunk)
205
+ )
206
+ tmp_limits = session.execute(stmt).scalars().all()
183
207
  for limit in tmp_limits:
184
208
  if limit.bytes == -1:
185
209
  account_limits[limit.rse_id] = float("inf")
186
210
  else:
187
211
  account_limits[limit.rse_id] = limit.bytes
188
212
  else:
189
- account_limits_tmp = session.query(models.AccountLimit).filter(models.AccountLimit.account == account).all()
213
+ stmt = select(
214
+ models.AccountLimit
215
+ ).where(
216
+ models.AccountLimit.account == account
217
+ )
218
+ account_limits_tmp = session.execute(stmt).scalars().all()
190
219
  for limit in account_limits_tmp:
191
220
  if limit.bytes == -1:
192
221
  account_limits[limit.rse_id] = float("inf")
@@ -206,8 +235,13 @@ def set_local_account_limit(account, rse_id, bytes_, *, session: "Session"):
206
235
  :param session: Database session in use.
207
236
  """
208
237
  try:
209
- account_limit = session.query(models.AccountLimit).filter(models.AccountLimit.account == account,
210
- models.AccountLimit.rse_id == rse_id).one()
238
+ stmt = select(
239
+ models.AccountLimit
240
+ ).where(
241
+ and_(models.AccountLimit.account == account,
242
+ models.AccountLimit.rse_id == rse_id)
243
+ )
244
+ account_limit = session.execute(stmt).scalar_one()
211
245
  account_limit.bytes = bytes_
212
246
  except NoResultFound:
213
247
  models.AccountLimit(account=account, rse_id=rse_id, bytes=bytes_).save(session=session)
@@ -224,8 +258,13 @@ def set_global_account_limit(account, rse_expression, bytes_, *, session: "Sessi
224
258
  :param session: Database session in use.
225
259
  """
226
260
  try:
227
- account_limit = session.query(models.AccountGlobalLimit).filter(models.AccountGlobalLimit.account == account,
228
- models.AccountGlobalLimit.rse_expression == rse_expression).one()
261
+ stmt = select(
262
+ models.AccountGlobalLimit
263
+ ).where(
264
+ and_(models.AccountGlobalLimit.account == account,
265
+ models.AccountGlobalLimit.rse_expression == rse_expression)
266
+ )
267
+ account_limit = session.execute(stmt).scalar_one()
229
268
  account_limit.bytes = bytes_
230
269
  except NoResultFound:
231
270
  models.AccountGlobalLimit(account=account, rse_expression=rse_expression, bytes=bytes_).save(session=session)
@@ -242,8 +281,14 @@ def delete_local_account_limit(account, rse_id, *, session: "Session"):
242
281
  :returns: True if something was deleted; False otherwise.
243
282
  """
244
283
  try:
245
- session.query(models.AccountLimit).filter(models.AccountLimit.account == account,
246
- models.AccountLimit.rse_id == rse_id).one().delete(session=session)
284
+ stmt = select(
285
+ models.AccountLimit
286
+ ).where(
287
+ and_(models.AccountLimit.account == account,
288
+ models.AccountLimit.rse_id == rse_id)
289
+ )
290
+ result = session.execute(stmt).scalar_one()
291
+ result.delete(session=session)
247
292
  return True
248
293
  except NoResultFound:
249
294
  return False
@@ -260,8 +305,14 @@ def delete_global_account_limit(account, rse_expression, *, session: "Session"):
260
305
  :returns: True if something was deleted; False otherwise.
261
306
  """
262
307
  try:
263
- session.query(models.AccountGlobalLimit).filter(models.AccountGlobalLimit.account == account,
264
- models.AccountGlobalLimit.rse_expression == rse_expression).one().delete(session=session)
308
+ stmt = select(
309
+ models.AccountGlobalLimit
310
+ ).where(
311
+ and_(models.AccountGlobalLimit.account == account,
312
+ models.AccountGlobalLimit.rse_expression == rse_expression)
313
+ )
314
+ result = session.execute(stmt).scalar_one()
315
+ result.delete(session=session)
265
316
  return True
266
317
  except NoResultFound:
267
318
  return False
@@ -279,14 +330,22 @@ def get_local_account_usage(account, rse_id=None, *, session: "Session"):
279
330
  :returns: List of dicts {'rse_id', 'rse', 'bytes', 'files', 'bytes_limit', 'bytes_remaining'}
280
331
  """
281
332
 
333
+ stmt = select(
334
+ models.AccountUsage
335
+ ).where(
336
+ models.AccountUsage.account == account
337
+ )
282
338
  if not rse_id:
283
339
  # All RSESs
284
340
  limits = get_local_account_limits(account=account, session=session)
285
- counters = {c.rse_id: c for c in session.query(models.AccountUsage).filter_by(account=account).all()}
341
+ counters = {c.rse_id: c for c in session.execute(stmt).scalars().all()}
286
342
  else:
287
343
  # One RSE
344
+ stmt.where(
345
+ models.AccountUsage.rse_id == rse_id
346
+ )
288
347
  limits = get_local_account_limits(account=account, rse_ids=[rse_id], session=session)
289
- counters = {c.rse_id: c for c in session.query(models.AccountUsage).filter_by(account=account, rse_id=rse_id).all()}
348
+ counters = {c.rse_id: c for c in session.execute(stmt).scalars().all()}
290
349
  result_list = []
291
350
 
292
351
  for rse_id in set(limits).union(counters):
@@ -341,9 +400,16 @@ def get_global_account_usage(account, rse_expression=None, *, session: "Session"
341
400
  limit = get_global_account_limit(account=account, rse_expression=rse_expression, session=session)
342
401
  vo = account.vo
343
402
  resolved_rses = [resolved_rse['id'] for resolved_rse in parse_expression(rse_expression, filter_={'vo': vo}, session=session)]
344
- usage = session.query(func.sum(models.AccountUsage.bytes), func.sum(models.AccountUsage.files))\
345
- .filter(models.AccountUsage.account == account, models.AccountUsage.rse_id.in_(resolved_rses))\
346
- .group_by(models.AccountUsage.account).first()
403
+ stmt = select(
404
+ func.sum(models.AccountUsage.bytes),
405
+ func.sum(models.AccountUsage.files)
406
+ ).where(
407
+ and_(models.AccountUsage.account == account,
408
+ models.AccountUsage.rse_id.in_(resolved_rses))
409
+ ).group_by(
410
+ models.AccountUsage.account
411
+ )
412
+ usage = session.execute(stmt).first()
347
413
  if limit is None:
348
414
  limit = 0
349
415
  if usage is None:
@@ -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");
@@ -20,27 +19,27 @@ import re
20
19
  import sys
21
20
  import traceback
22
21
  from base64 import b64decode
23
- from typing import TYPE_CHECKING
22
+ from typing import TYPE_CHECKING, Optional, Union, cast
24
23
 
25
24
  import paramiko
26
25
  from dogpile.cache import make_region
27
- from dogpile.cache.api import NO_VALUE
26
+ from dogpile.cache.api import NO_VALUE, NoValue
28
27
  from sqlalchemy import delete, null, or_, select
29
28
 
30
29
  from rucio.common.cache import make_region_memcached
31
30
  from rucio.common.config import config_get_bool
32
31
  from rucio.common.exception import CannotAuthenticate, RucioException
33
- from rucio.common.utils import chunks, generate_uuid, date_to_str
32
+ from rucio.common.utils import chunks, date_to_str, generate_uuid
34
33
  from rucio.core.account import account_exists
35
34
  from rucio.core.oidc import validate_jwt
36
- from rucio.db.sqla import filter_thread_work
37
- from rucio.db.sqla import models
35
+ from rucio.db.sqla import filter_thread_work, models
38
36
  from rucio.db.sqla.constants import IdentityType
39
37
  from rucio.db.sqla.session import read_session, transactional_session
40
38
 
41
39
  if TYPE_CHECKING:
42
40
  from sqlalchemy.orm import Session
43
- from typing import Any, Union
41
+
42
+ from rucio.common.types import InternalAccount, TokenDict, TokenValidationDict
44
43
 
45
44
 
46
45
  def strip_x509_proxy_attributes(dn: str) -> str:
@@ -90,7 +89,15 @@ else:
90
89
 
91
90
 
92
91
  @transactional_session
93
- def get_auth_token_user_pass(account, username, password, appid, ip=None, *, session: "Session"):
92
+ def get_auth_token_user_pass(
93
+ account: "InternalAccount",
94
+ username: str,
95
+ password: str,
96
+ appid: str,
97
+ ip: Optional[str] = None,
98
+ *,
99
+ session: "Session"
100
+ ) -> Optional["TokenDict"]:
94
101
  """
95
102
  Authenticate a Rucio account temporarily via username and password.
96
103
 
@@ -150,7 +157,14 @@ def get_auth_token_user_pass(account, username, password, appid, ip=None, *, ses
150
157
 
151
158
 
152
159
  @transactional_session
153
- def get_auth_token_x509(account, dn, appid, ip=None, *, session: "Session"):
160
+ def get_auth_token_x509(
161
+ account: "InternalAccount",
162
+ dn: str,
163
+ appid: str,
164
+ ip: Optional[str] = None,
165
+ *,
166
+ session: "Session"
167
+ ) -> Optional["TokenDict"]:
154
168
  """
155
169
  Authenticate a Rucio account temporarily via an x509 certificate.
156
170
 
@@ -182,7 +196,14 @@ def get_auth_token_x509(account, dn, appid, ip=None, *, session: "Session"):
182
196
 
183
197
 
184
198
  @transactional_session
185
- def get_auth_token_gss(account, gsstoken, appid, ip=None, *, session: "Session"):
199
+ def get_auth_token_gss(
200
+ account: "InternalAccount",
201
+ gsstoken: str,
202
+ appid: str,
203
+ ip: Optional[str] = None,
204
+ *,
205
+ session: "Session"
206
+ ) -> Optional["TokenDict"]:
186
207
  """
187
208
  Authenticate a Rucio account temporarily via a GSS token.
188
209
 
@@ -214,22 +235,34 @@ def get_auth_token_gss(account, gsstoken, appid, ip=None, *, session: "Session")
214
235
 
215
236
 
216
237
  @transactional_session
217
- def get_auth_token_ssh(account, signature, appid, ip=None, *, session: "Session"):
238
+ def get_auth_token_ssh(
239
+ account: "InternalAccount",
240
+ signature: str,
241
+ appid: str,
242
+ ip: Optional[str] = None,
243
+ *,
244
+ session: "Session"
245
+ ) -> Optional["TokenDict"]:
218
246
  """
219
247
  Authenticate a Rucio account temporarily via SSH key exchange.
220
248
 
221
249
  The token lifetime is 1 hour.
222
250
 
223
251
  :param account: Account identifier as a string.
224
- :param signature: Response to server challenge signed with SSH private key as string.
252
+ :param signature: Response to server challenge signed with SSH private key as a base64 encoded string.
225
253
  :param appid: The application identifier as a string.
226
254
  :param ip: IP address of the client as a string.
227
255
  :param session: The database session in use.
228
256
 
229
257
  :returns: A dict with token and expires_at entries.
230
258
  """
231
- if not isinstance(signature, bytes):
232
- signature = signature.encode()
259
+
260
+ # decode the signature which must come in base64 encoded
261
+ try:
262
+ signature += '=' * ((4 - len(signature) % 4) % 4) # adding required padding
263
+ decoded_signature = b64decode(signature)
264
+ except TypeError:
265
+ raise CannotAuthenticate(f'Cannot authenticate to account {account} with malformed signature')
233
266
 
234
267
  # Make sure the account exists
235
268
  if not account_exists(account, session=session):
@@ -266,7 +299,7 @@ def get_auth_token_ssh(account, signature, appid, ip=None, *, session: "Session"
266
299
  pub_k = paramiko.RSAKey(data=b64decode(data))
267
300
  for challenge_token in active_challenge_tokens:
268
301
  if pub_k.verify_ssh_sig(str(challenge_token['token']).encode(),
269
- paramiko.Message(signature)):
302
+ paramiko.Message(decoded_signature)):
270
303
  match = True
271
304
  break
272
305
  if match:
@@ -288,7 +321,13 @@ def get_auth_token_ssh(account, signature, appid, ip=None, *, session: "Session"
288
321
 
289
322
 
290
323
  @transactional_session
291
- def get_ssh_challenge_token(account, appid, ip=None, *, session: "Session"):
324
+ def get_ssh_challenge_token(
325
+ account: "InternalAccount",
326
+ appid: str,
327
+ ip: Optional[str] = None,
328
+ *,
329
+ session: "Session"
330
+ ) -> Optional["TokenDict"]:
292
331
  """
293
332
  Prepare a challenge token for subsequent SSH public key authentication.
294
333
 
@@ -324,7 +363,14 @@ def get_ssh_challenge_token(account, appid, ip=None, *, session: "Session"):
324
363
 
325
364
 
326
365
  @transactional_session
327
- def get_auth_token_saml(account, saml_nameid, appid, ip=None, *, session: "Session"):
366
+ def get_auth_token_saml(
367
+ account: "InternalAccount",
368
+ saml_nameid: str,
369
+ appid: str,
370
+ ip: Optional[str] = None,
371
+ *,
372
+ session: "Session"
373
+ ) -> Optional["TokenDict"]:
328
374
  """
329
375
  Authenticate a Rucio account temporarily via SAML.
330
376
 
@@ -355,7 +401,12 @@ def get_auth_token_saml(account, saml_nameid, appid, ip=None, *, session: "Sessi
355
401
 
356
402
 
357
403
  @transactional_session
358
- def redirect_auth_oidc(auth_code, fetchtoken=False, *, session: "Session"):
404
+ def redirect_auth_oidc(
405
+ auth_code: str,
406
+ fetchtoken: bool = False,
407
+ *,
408
+ session: "Session"
409
+ ) -> Optional[str]:
359
410
  """
360
411
  Finds the Authentication URL in the Rucio DB oauth_requests table
361
412
  and redirects user's browser to this URL.
@@ -396,7 +447,13 @@ def redirect_auth_oidc(auth_code, fetchtoken=False, *, session: "Session"):
396
447
 
397
448
 
398
449
  @transactional_session
399
- def delete_expired_tokens(total_workers, worker_number, limit=1000, *, session: "Session"):
450
+ def delete_expired_tokens(
451
+ total_workers: int,
452
+ worker_number: int,
453
+ limit: int = 1000,
454
+ *,
455
+ session: "Session"
456
+ ) -> int:
400
457
  """
401
458
  Delete expired tokens.
402
459
 
@@ -456,7 +513,7 @@ def delete_expired_tokens(total_workers, worker_number, limit=1000, *, session:
456
513
 
457
514
 
458
515
  @read_session
459
- def query_token(token, *, session: "Session"):
516
+ def query_token(token: str, *, session: "Session") -> Optional["TokenValidationDict"]:
460
517
  """
461
518
  Validate an authentication token using the database. This method will only be called
462
519
  if no entry could be found in the according cache.
@@ -484,12 +541,12 @@ def query_token(token, *, session: "Session"):
484
541
  )
485
542
  result = session.execute(query).first()
486
543
  if result:
487
- return result._asdict()
544
+ return cast("TokenValidationDict", result._asdict())
488
545
  return None
489
546
 
490
547
 
491
548
  @transactional_session
492
- def validate_auth_token(token: str, *, session: "Session") -> "dict[str, Any]":
549
+ def validate_auth_token(token: str, *, session: "Session") -> "TokenValidationDict":
493
550
  """
494
551
  Validate an authentication token.
495
552
 
@@ -510,12 +567,12 @@ def validate_auth_token(token: str, *, session: "Session") -> "dict[str, Any]":
510
567
  token = token.strip()
511
568
  cache_key = token.replace(' ', '')
512
569
 
513
- # Check if token ca be found in cache region
514
- value: "Union[NO_VALUE, dict[str, Any]]" = TOKENREGION.get(cache_key)
570
+ # Check if token can be found in cache region
571
+ value: Union[NoValue, "TokenValidationDict"] = TOKENREGION.get(cache_key)
515
572
  if value is NO_VALUE: # no cached entry found
516
573
  value = query_token(token, session=session)
517
574
  if not value:
518
- # identify JWT access token and validte
575
+ # identify JWT access token and validate
519
576
  # & save it in Rucio if scope and audience are correct
520
577
  if len(token.split(".")) == 3:
521
578
  value = validate_jwt(token, session=session)
@@ -523,19 +580,19 @@ def validate_auth_token(token: str, *, session: "Session") -> "dict[str, Any]":
523
580
  raise CannotAuthenticate(traceback.format_exc())
524
581
  # save token in the cache
525
582
  TOKENREGION.set(cache_key, value)
526
- lifetime = value.get('lifetime', datetime.datetime(1970, 1, 1))
583
+ lifetime = value.get('lifetime', datetime.datetime(1970, 1, 1)) # type: ignore (value is narrowed to dict, but type-checker doesn't see it)
527
584
  if lifetime < datetime.datetime.utcnow(): # check if expired
528
585
  TOKENREGION.delete(cache_key)
529
586
  raise CannotAuthenticate(f"Token found but expired since {date_to_str(lifetime)}.")
530
- return value
587
+ return cast("TokenValidationDict", value)
531
588
 
532
589
 
533
- def token_dictionary(token: models.Token):
590
+ def token_dictionary(token: models.Token) -> "TokenDict":
534
591
  return {'token': token.token, 'expires_at': token.expired_at}
535
592
 
536
593
 
537
594
  @transactional_session
538
- def __delete_expired_tokens_account(account, *, session: "Session"):
595
+ def __delete_expired_tokens_account(account: "InternalAccount", *, session: "Session") -> None:
539
596
  """"
540
597
  Deletes expired tokens from the database.
541
598