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");
@@ -28,8 +27,9 @@ import threading
28
27
  import time
29
28
  import traceback
30
29
  from datetime import datetime
31
- from typing import TYPE_CHECKING
30
+ from typing import TYPE_CHECKING, Any, Optional
32
31
 
32
+ from sqlalchemy import and_, delete
33
33
  from sqlalchemy.exc import DatabaseError, IntegrityError
34
34
  from sqlalchemy.orm.exc import FlushError
35
35
 
@@ -37,21 +37,25 @@ from rucio.common import exception
37
37
  from rucio.common.logging import formatted_logger, setup_logging
38
38
  from rucio.common.types import InternalAccount, InternalScope
39
39
  from rucio.common.utils import daemon_sleep
40
- from rucio.core.heartbeat import live, die, sanity_check
40
+ from rucio.core.heartbeat import die, live, sanity_check
41
41
  from rucio.core.monitor import MetricManager
42
42
  from rucio.core.quarantined_replica import add_quarantined_replicas
43
43
  from rucio.core.replica import __exist_replicas, update_replicas_states
44
- from rucio.core.rse import list_rses, get_rse_id
44
+ from rucio.core.rse import get_rse_id, list_rses
45
+
45
46
  # FIXME: these are needed by local version of declare_bad_file_replicas()
46
47
  # TODO: remove after move of this code to core/replica.py - see https://github.com/rucio/rucio/pull/5068
47
48
  from rucio.db.sqla import models
48
- from rucio.db.sqla.constants import (ReplicaState, BadFilesStatus)
49
+ from rucio.db.sqla.constants import BadFilesStatus, ReplicaState
49
50
  from rucio.db.sqla.session import transactional_session
50
- from rucio.rse.rsemanager import lfns2pfns, get_rse_info, parse_pfns
51
+ from rucio.rse.rsemanager import get_rse_info, lfns2pfns, parse_pfns
51
52
 
52
53
  if TYPE_CHECKING:
54
+ from collections.abc import Iterable, Sequence
53
55
  from types import FrameType
54
- from typing import Optional
56
+
57
+ from _typeshed import FileDescriptorOrPath, SupportsKeysAndGetItem
58
+ from sqlalchemy.orm import Session
55
59
 
56
60
  METRICS = MetricManager(module=__name__)
57
61
  graceful_stop = threading.Event()
@@ -62,8 +66,16 @@ DAEMON_NAME = 'storage-consistency-actions'
62
66
 
63
67
 
64
68
  @transactional_session
65
- def declare_bad_file_replicas(dids, rse_id, reason, issuer,
66
- status=BadFilesStatus.BAD, scheme=None, *, session=None):
69
+ def declare_bad_file_replicas(
70
+ dids: "Iterable[dict[str, str]]",
71
+ rse_id: str,
72
+ reason: str,
73
+ issuer: InternalAccount,
74
+ status=BadFilesStatus.BAD,
75
+ scheme: Optional[str] = None,
76
+ *,
77
+ session: Optional["Session"] = None
78
+ ):
67
79
  """
68
80
  Declare a list of bad replicas.
69
81
 
@@ -87,12 +99,20 @@ def declare_bad_file_replicas(dids, rse_id, reason, issuer,
87
99
  already_declared) or str(status) == str(BadFilesStatus.SUSPICIOUS)):
88
100
  replicas.append({'scope': scope, 'name': name, 'rse_id': rse_id,
89
101
  'state': ReplicaState.BAD})
90
- new_bad_replica = models.BadReplicas(scope=scope, name=name, rse_id=rse_id,
91
- reason=reason, state=status, account=issuer,
92
- bytes=size)
102
+ new_bad_replica = models.BadReplica(scope=scope, name=name, rse_id=rse_id,
103
+ reason=reason, state=status, account=issuer,
104
+ bytes=size)
93
105
  new_bad_replica.save(session=session, flush=False)
94
- session.query(models.Source).filter_by(scope=scope, name=name,
95
- rse_id=rse_id).delete(synchronize_session=False)
106
+ stmt = delete(
107
+ models.Source
108
+ ).where(
109
+ and_(models.Source.scope == scope,
110
+ models.Source.name == name,
111
+ models.Source.rse_id == rse_id)
112
+ ).execution_options(
113
+ synchronize_session=False
114
+ )
115
+ session.execute(stmt) # type: ignore (session could be None)
96
116
  else:
97
117
  if already_declared:
98
118
  unknown_replicas.append('%s:%s %s' % (did['scope'], did['name'],
@@ -108,7 +128,7 @@ def declare_bad_file_replicas(dids, rse_id, reason, issuer,
108
128
  except exception.UnsupportedOperation:
109
129
  raise exception.ReplicaNotFound("One or several replicas don't exist.")
110
130
  try:
111
- session.flush()
131
+ session.flush() # type: ignore (session could be None)
112
132
  except IntegrityError as error:
113
133
  raise exception.RucioException(error.args)
114
134
  except DatabaseError as error:
@@ -122,27 +142,27 @@ def declare_bad_file_replicas(dids, rse_id, reason, issuer,
122
142
  # TODO: This is Igor's Stats class.It will be factored out as a separate class in a future version of the code.
123
143
  # - Igor Mandrichenko <ivm@fnal.gov>, 2018
124
144
 
125
- class Stats(object):
145
+ class Stats:
126
146
 
127
- def __init__(self, path):
147
+ def __init__(self, path: "FileDescriptorOrPath"):
128
148
  self.path = path
129
149
  self.Data = {}
130
150
 
131
- def __getitem__(self, name):
151
+ def __getitem__(self, name: str) -> Any:
132
152
  return self.Data[name]
133
153
 
134
- def __setitem__(self, name, value):
154
+ def __setitem__(self, name: str, value: Any) -> None:
135
155
  self.Data[name] = value
136
156
  self.save()
137
157
 
138
- def get(self, name, default=None):
158
+ def get(self, name, default: Any = None) -> Any:
139
159
  return self.Data.get(name, default)
140
160
 
141
- def update(self, data):
161
+ def update(self, data: "SupportsKeysAndGetItem") -> None:
142
162
  self.Data.update(data)
143
163
  self.save()
144
164
 
145
- def save(self):
165
+ def save(self) -> None:
146
166
  try:
147
167
  with open(self.path, "r") as f:
148
168
  data = f.read()
@@ -153,7 +173,11 @@ class Stats(object):
153
173
  open(self.path, "w").write(json.dumps(data, indent=4))
154
174
 
155
175
 
156
- def write_stats(my_stats, stats_file, stats_key=None):
176
+ def write_stats(
177
+ my_stats: Any,
178
+ stats_file: "FileDescriptorOrPath",
179
+ stats_key: Optional[str] = None
180
+ ):
157
181
  if stats_file:
158
182
  stats = {}
159
183
  if os.path.isfile(stats_file):
@@ -168,13 +192,18 @@ def write_stats(my_stats, stats_file, stats_key=None):
168
192
  # TODO: Consider breaking the logic into two functions, following discussion in https://github.com/rucio/rucio/pull/5120#discussion_r792673599
169
193
 
170
194
 
171
- def cmp2dark(new_list, old_list, comm_list, stats_file):
195
+ def cmp2dark(
196
+ new_list: "FileDescriptorOrPath",
197
+ old_list: "FileDescriptorOrPath",
198
+ comm_list: "FileDescriptorOrPath",
199
+ stats_file: "FileDescriptorOrPath"
200
+ ) -> None:
172
201
 
173
202
  t0 = time.time()
174
203
  stats_key = "cmp2dark"
175
204
  my_stats = stats = None
176
205
 
177
- with open(new_list, "r") as a_list, open(old_list, "r") as b_list,\
206
+ with open(new_list, "r") as a_list, open(old_list, "r") as b_list, \
178
207
  open(comm_list, "w") as out_list:
179
208
 
180
209
  if stats_file is not None:
@@ -210,7 +239,7 @@ def cmp2dark(new_list, old_list, comm_list, stats_file):
210
239
 
211
240
 
212
241
  # TODO: Changes suggested in https://github.com/rucio/rucio/pull/5120#discussion_r792681245
213
- def parse_filename(fn):
242
+ def parse_filename(fn: str) -> tuple[str, str, str, str]:
214
243
  # filename looks like this:
215
244
  #
216
245
  # <rse>_%Y_%m_%d_%H_%M_<type>.<extension>
@@ -224,7 +253,7 @@ def parse_filename(fn):
224
253
  return rse, timestamp, typ, ext
225
254
 
226
255
 
227
- def list_cc_scanned_rses(path):
256
+ def list_cc_scanned_rses(path: "FileDescriptorOrPath") -> list[str]:
228
257
  files = glob.glob(f"{path}/*_stats.json")
229
258
  rses = set()
230
259
  for path in files:
@@ -234,7 +263,11 @@ def list_cc_scanned_rses(path):
234
263
  return sorted(list(rses))
235
264
 
236
265
 
237
- def list_runs_by_age(path, rse, reffile):
266
+ def list_runs_by_age(
267
+ path: "FileDescriptorOrPath",
268
+ rse: str,
269
+ reffile: str
270
+ ) -> dict[str, int]:
238
271
  files = glob.glob(f"{path}/{rse}_*_stats.json")
239
272
  r, reftimestamp, typ, ext = parse_filename(reffile)
240
273
  reftime = datetime.strptime(reftimestamp, '%Y_%m_%d_%H_%M')
@@ -253,7 +286,11 @@ def list_runs_by_age(path, rse, reffile):
253
286
  return {k: v for k, v in sorted(runs.items(), reverse=True)}
254
287
 
255
288
 
256
- def list_runs(path, rse, nlast=0):
289
+ def list_runs(
290
+ path: "FileDescriptorOrPath",
291
+ rse: str,
292
+ nlast: int = 0
293
+ ) -> list[str]:
257
294
  files = glob.glob(f"{path}/{rse}_*_stats.json")
258
295
  runs = []
259
296
  for path in files:
@@ -269,7 +306,11 @@ def list_runs(path, rse, nlast=0):
269
306
  return sorted(runs, reverse=False)[-nlast:]
270
307
 
271
308
 
272
- def list_unprocessed_runs(path, rse, nlast=0):
309
+ def list_unprocessed_runs(
310
+ path: "FileDescriptorOrPath",
311
+ rse: str,
312
+ nlast: int = 0
313
+ ) -> list[str]:
273
314
  files = glob.glob(f"{path}/{rse}_*_stats.json")
274
315
  unproc_runs = []
275
316
  for path in files:
@@ -286,7 +327,9 @@ def list_unprocessed_runs(path, rse, nlast=0):
286
327
  return sorted(unproc_runs, reverse=True)[-nlast:]
287
328
 
288
329
 
289
- def was_cc_attempted(stats_file):
330
+ def was_cc_attempted(
331
+ stats_file: "FileDescriptorOrPath"
332
+ ) -> Optional[bool]:
290
333
  try:
291
334
  f = open(stats_file, "r")
292
335
  except:
@@ -299,7 +342,9 @@ def was_cc_attempted(stats_file):
299
342
  return False
300
343
 
301
344
 
302
- def was_cc_processed(stats_file):
345
+ def was_cc_processed(
346
+ stats_file: "FileDescriptorOrPath"
347
+ ) -> Optional[bool]:
303
348
  try:
304
349
  f = open(stats_file, "r")
305
350
  except:
@@ -320,8 +365,16 @@ def was_cc_processed(stats_file):
320
365
  return False
321
366
 
322
367
 
323
- def process_dark_files(path, scope, rse, latest_run, max_dark_fraction,
324
- max_files_at_site, old_enough_run, force_proceed):
368
+ def process_dark_files(
369
+ path: "FileDescriptorOrPath",
370
+ scope: str,
371
+ rse: str,
372
+ latest_run: str,
373
+ max_dark_fraction: float,
374
+ max_files_at_site: int,
375
+ old_enough_run: str,
376
+ force_proceed: bool
377
+ ) -> None:
325
378
 
326
379
  """
327
380
  Process the Dark Files.
@@ -434,8 +487,16 @@ def process_dark_files(path, scope, rse, latest_run, max_dark_fraction,
434
487
  METRICS.gauge('actions_dark_files_deleted.{rse}').labels(**labels).set(deleted_files)
435
488
 
436
489
 
437
- def process_miss_files(path, scope, rse, latest_run, max_miss_fraction,
438
- max_files_at_site, old_enough_run, force_proceed):
490
+ def process_miss_files(
491
+ path: "FileDescriptorOrPath",
492
+ scope: str,
493
+ rse: str,
494
+ latest_run: str,
495
+ max_miss_fraction: float,
496
+ max_files_at_site: int,
497
+ old_enough_run: Optional[str],
498
+ force_proceed: bool
499
+ ) -> None:
439
500
 
440
501
  """
441
502
  Process the Missing Replicas.
@@ -529,8 +590,15 @@ def process_miss_files(path, scope, rse, latest_run, max_miss_fraction,
529
590
  METRICS.gauge('actions_miss_files_to_retransfer.{rse}').labels(**labels).set(invalidated_files)
530
591
 
531
592
 
532
- def deckard(scope, rse, dark_min_age, dark_threshold_percent, miss_threshold_percent,
533
- force_proceed, scanner_files_path):
593
+ def deckard(
594
+ scope: str,
595
+ rse: str,
596
+ dark_min_age: int,
597
+ dark_threshold_percent: float,
598
+ miss_threshold_percent: float,
599
+ force_proceed: bool,
600
+ scanner_files_path: "FileDescriptorOrPath"
601
+ ) -> None:
534
602
 
535
603
  """
536
604
  The core of CC actions.
@@ -611,7 +679,7 @@ def deckard(scope, rse, dark_min_age, dark_threshold_percent, miss_threshold_per
611
679
  max_files_at_site, old_enough_run, force_proceed)
612
680
  else:
613
681
  logger(logging.INFO, 'There is no other run for this RSE at least %d days older,\
614
- so cannot safely proceed with dark files deleteion.' % minagedark)
682
+ so cannot safely proceed with dark files deletion.' % minagedark)
615
683
 
616
684
  process_miss_files(path, scope, rse, latest_run, max_miss_fraction,
617
685
  max_files_at_site, old_enough_run, force_proceed)
@@ -625,8 +693,15 @@ def deckard(scope, rse, dark_min_age, dark_threshold_percent, miss_threshold_per
625
693
  logger(logging.INFO, 'No scans available for this RSE')
626
694
 
627
695
 
628
- def deckard_loop(scope, rses, dark_min_age, dark_threshold_percent, miss_threshold_percent,
629
- force_proceed, scanner_files_path):
696
+ def deckard_loop(
697
+ scope: str,
698
+ rses: "Iterable[str]",
699
+ dark_min_age: int,
700
+ dark_threshold_percent: float,
701
+ miss_threshold_percent: float,
702
+ force_proceed: bool,
703
+ scanner_files_path: "FileDescriptorOrPath"
704
+ ) -> None:
630
705
 
631
706
  prefix = 'storage-consistency-actions (deckard_loop())'
632
707
  logger = formatted_logger(logging.log, prefix + '%s')
@@ -637,8 +712,17 @@ def deckard_loop(scope, rses, dark_min_age, dark_threshold_percent, miss_thresho
637
712
  force_proceed, scanner_files_path)
638
713
 
639
714
 
640
- def actions_loop(once, scope, rses, sleep_time, dark_min_age, dark_threshold_percent,
641
- miss_threshold_percent, force_proceed, scanner_files_path):
715
+ def actions_loop(
716
+ once: bool,
717
+ scope: str,
718
+ rses: "Sequence[str]",
719
+ sleep_time: int,
720
+ dark_min_age: int,
721
+ dark_threshold_percent: float,
722
+ miss_threshold_percent: float,
723
+ force_proceed: bool,
724
+ scanner_files_path: "FileDescriptorOrPath"
725
+ ) -> None:
642
726
 
643
727
  """
644
728
  Main loop to apply the CC actions
@@ -687,16 +771,25 @@ def actions_loop(once, scope, rses, sleep_time, dark_min_age, dark_threshold_per
687
771
  die(executable=DAEMON_NAME, hostname=hostname, pid=pid, thread=current_thread)
688
772
 
689
773
 
690
- def stop(signum: "Optional[int]" = None, frame: "Optional[FrameType]" = None) -> None:
774
+ def stop(signum: Optional[int] = None, frame: Optional["FrameType"] = None) -> None:
691
775
  """
692
776
  Graceful exit.
693
777
  """
694
778
  graceful_stop.set()
695
779
 
696
780
 
697
- def run(once=False, scope=None, rses=None, sleep_time=60, default_dark_min_age=28, default_dark_threshold_percent=1.0,
698
- default_miss_threshold_percent=1.0, force_proceed=False, default_scanner_files_path="/var/cache/consistency-dump",
699
- threads=1):
781
+ def run(
782
+ once: bool = False,
783
+ scope: Optional[str] = None,
784
+ rses: Optional["Sequence[str]"] = None,
785
+ sleep_time: int = 60,
786
+ default_dark_min_age: int = 28,
787
+ default_dark_threshold_percent: float = 1.0,
788
+ default_miss_threshold_percent: float = 1.0,
789
+ force_proceed: bool = False,
790
+ default_scanner_files_path: "FileDescriptorOrPath" = "/var/cache/consistency-dump",
791
+ threads: int = 1
792
+ ) -> None:
700
793
  """
701
794
  Starts up the Consistency-Actions.
702
795
  """
@@ -735,19 +828,19 @@ def run(once=False, scope=None, rses=None, sleep_time=60, default_dark_min_age=2
735
828
  threads = 1
736
829
 
737
830
  if once:
738
- actions_loop(once, scope, rses, sleep_time, dark_min_age, dark_threshold_percent,
831
+ actions_loop(once, scope, rses, sleep_time, dark_min_age, dark_threshold_percent, # type: ignore (scope and rses might be None)
739
832
  miss_threshold_percent, force_proceed, scanner_files_path)
740
833
  else:
741
834
  logging.info('Consistency Actions starting %s threads' % str(threads))
742
- threads = [threading.Thread(target=actions_loop,
743
- kwargs={'once': once, 'scope': scope, 'rses': rses, 'sleep_time': sleep_time,
744
- 'dark_min_age': dark_min_age,
745
- 'dark_threshold_percent': dark_threshold_percent,
746
- 'miss_threshold_percent': miss_threshold_percent,
747
- 'force_proceed': force_proceed,
748
- 'scanner_files_path': scanner_files_path}) for i in range(0, threads)]
749
- logger(logging.INFO, 'Threads: %d' % len(threads))
750
- [t.start() for t in threads]
835
+ thread_list = [threading.Thread(target=actions_loop,
836
+ kwargs={'once': once, 'scope': scope, 'rses': rses, 'sleep_time': sleep_time,
837
+ 'dark_min_age': dark_min_age,
838
+ 'dark_threshold_percent': dark_threshold_percent,
839
+ 'miss_threshold_percent': miss_threshold_percent,
840
+ 'force_proceed': force_proceed,
841
+ 'scanner_files_path': scanner_files_path}) for i in range(0, threads)]
842
+ logger(logging.INFO, 'Threads: %d' % len(thread_list))
843
+ [t.start() for t in thread_list]
751
844
  # Interruptible joins require a timeout.
752
- while threads[0].is_alive():
753
- [t.join(timeout=3.14) for t in threads]
845
+ while thread_list[0].is_alive():
846
+ [t.join(timeout=3.14) for t in thread_list]
@@ -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");
@@ -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");
@@ -22,30 +21,34 @@ import logging
22
21
  import re
23
22
  from configparser import NoOptionError, NoSectionError
24
23
  from datetime import datetime
25
- from json import loads as jloads, dumps as jdumps
24
+ from json import dumps as jdumps
25
+ from json import loads as jloads
26
26
  from queue import Queue
27
27
  from threading import Event, Thread
28
28
  from time import time
29
- from typing import TYPE_CHECKING
29
+ from typing import TYPE_CHECKING, Optional
30
30
 
31
31
  import rucio.db.sqla.util
32
32
  from rucio.common.config import config_get, config_get_bool, config_get_int, config_get_list
33
- from rucio.common.exception import RSENotFound, DatabaseException
33
+ from rucio.common.exception import DatabaseException, RSENotFound
34
34
  from rucio.common.logging import setup_logging
35
35
  from rucio.common.stomp_utils import StompConnectionManager
36
36
  from rucio.common.stopwatch import Stopwatch
37
- from rucio.common.types import InternalAccount, InternalScope
38
- from rucio.core.did import touch_dids, list_parent_dids
37
+ from rucio.common.types import InternalAccount, InternalScope, LoggerFunction
38
+ from rucio.core.did import list_parent_dids, touch_dids
39
39
  from rucio.core.lock import touch_dataset_locks
40
40
  from rucio.core.monitor import MetricManager
41
- from rucio.core.replica import touch_replica, touch_collection_replicas, declare_bad_file_replicas
41
+ from rucio.core.replica import declare_bad_file_replicas, touch_collection_replicas, touch_replica
42
42
  from rucio.core.rse import get_rse_id
43
43
  from rucio.daemons.common import HeartbeatHandler, run_daemon
44
- from rucio.db.sqla.constants import DIDType, BadFilesStatus
44
+ from rucio.db.sqla.constants import BadFilesStatus, DIDType
45
45
 
46
46
  if TYPE_CHECKING:
47
+ from collections.abc import Set
47
48
  from types import FrameType
48
- from typing import Optional
49
+
50
+ from stomp import Connection
51
+ from stomp.utils import Frame
49
52
 
50
53
 
51
54
  logging.getLogger("stomp").setLevel(logging.CRITICAL)
@@ -57,7 +60,18 @@ graceful_stop = Event()
57
60
  class AMQConsumer:
58
61
  """ActiveMQ message consumer"""
59
62
 
60
- def __init__(self, broker, conn, queue, chunksize, subscription_id, excluded_usrdns, dataset_queue, bad_files_patterns, logger=logging.log):
63
+ def __init__(
64
+ self,
65
+ broker: str,
66
+ conn: "Connection",
67
+ queue: str,
68
+ chunksize: int,
69
+ subscription_id: str,
70
+ excluded_usrdns: "Set[str]",
71
+ dataset_queue: Queue,
72
+ bad_files_patterns: list[re.Pattern],
73
+ logger: LoggerFunction = logging.log
74
+ ):
61
75
  self.__broker = broker
62
76
  self.__conn = conn
63
77
  self.__queue = queue
@@ -74,15 +88,15 @@ class AMQConsumer:
74
88
  self.__logger = logger
75
89
 
76
90
  @METRICS.count_it
77
- def on_heartbeat_timeout(self):
91
+ def on_heartbeat_timeout(self) -> None:
78
92
  self.__conn.disconnect()
79
93
 
80
94
  @METRICS.count_it
81
- def on_error(self, frame):
95
+ def on_error(self, frame: "Frame") -> None:
82
96
  self.__logger(logging.ERROR, 'Message receive error: [%s] %s' % (self.__broker, frame.body))
83
97
 
84
98
  @METRICS.count_it
85
- def on_message(self, frame):
99
+ def on_message(self, frame: "Frame") -> None:
86
100
  appversion = 'dq2'
87
101
  msg_id = frame.headers['message-id']
88
102
  if 'appversion' in frame.headers:
@@ -96,7 +110,7 @@ class AMQConsumer:
96
110
  self.__conn.ack(msg_id, self.__subscription_id)
97
111
  return
98
112
  else:
99
- report = jloads(frame.body)
113
+ report = jloads(frame.body) # type: ignore
100
114
  except Exception:
101
115
  # message is corrupt, not much to do here
102
116
  # send count to graphite, send ack to broker and return
@@ -121,7 +135,7 @@ class AMQConsumer:
121
135
  self.__reports = []
122
136
  self.__ids = []
123
137
 
124
- def __update_atime(self):
138
+ def __update_atime(self) -> None:
125
139
  """
126
140
  Bulk update atime.
127
141
  """
@@ -142,8 +156,8 @@ class AMQConsumer:
142
156
  self.__logger(logging.ERROR, 'Missing url in the following trace : ' + str(report))
143
157
  else:
144
158
  try:
145
- surl = report['url']
146
- declare_bad_file_replicas([surl, ], reason=reason, issuer=InternalAccount('root', vo=report['vo']), status=BadFilesStatus.SUSPICIOUS)
159
+ pfn = report['url']
160
+ declare_bad_file_replicas([pfn, ], reason=reason, issuer=InternalAccount('root', vo=report['vo']), status=BadFilesStatus.SUSPICIOUS)
147
161
  self.__logger(logging.INFO, 'Declare suspicious file %s with reason %s' % (report['url'], reason))
148
162
  except Exception as error:
149
163
  self.__logger(logging.ERROR, 'Failed to declare suspicious file' + str(error))
@@ -297,7 +311,11 @@ class AMQConsumer:
297
311
  METRICS.counter('updated_replicas').inc()
298
312
 
299
313
 
300
- def kronos_file(once: bool = False, dataset_queue: Queue = None, sleep_time: int = 60):
314
+ def kronos_file(
315
+ once: bool = False,
316
+ dataset_queue: Optional[Queue] = None,
317
+ sleep_time: int = 60
318
+ ) -> None:
301
319
  """
302
320
  Main loop to consume tracer reports.
303
321
  """
@@ -311,14 +329,14 @@ def kronos_file(once: bool = False, dataset_queue: Queue = None, sleep_time: int
311
329
  run_once_fnc=functools.partial(
312
330
  run_once_kronos_file,
313
331
  stomp_conn_mngr=stomp_conn_mngr,
314
- dataset_queue=dataset_queue,
332
+ dataset_queue=dataset_queue, # type: ignore
315
333
  sleep_time=sleep_time,
316
334
  )
317
335
  )
318
336
  stomp_conn_mngr.disconnect()
319
337
 
320
338
 
321
- def run_once_kronos_file(heartbeat_handler: HeartbeatHandler, stomp_conn_mngr: StompConnectionManager, dataset_queue: Queue, sleep_time: int, **kwargs):
339
+ def run_once_kronos_file(heartbeat_handler: HeartbeatHandler, stomp_conn_mngr: StompConnectionManager, dataset_queue: Queue, sleep_time: int, **kwargs) -> None:
322
340
  """
323
341
  Run the amq consumer once.
324
342
  """
@@ -388,7 +406,7 @@ def run_once_kronos_file(heartbeat_handler: HeartbeatHandler, stomp_conn_mngr: S
388
406
  conn.subscribe(destination=config_get('tracer-kronos', 'queue'), ack='client-individual', id=subscription_id, headers={'activemq.prefetchSize': prefetch_size})
389
407
 
390
408
 
391
- def kronos_dataset(dataset_queue: Queue, once: bool = False, sleep_time: int = 60):
409
+ def kronos_dataset(dataset_queue: Queue, once: bool = False, sleep_time: int = 60) -> None:
392
410
  return_values = {'heartbeat_handler': HeartbeatHandler("kronos-dataset", 10)}
393
411
  run_daemon(
394
412
  once=once,
@@ -407,7 +425,7 @@ def kronos_dataset(dataset_queue: Queue, once: bool = False, sleep_time: int = 6
407
425
  run_once_kronos_dataset(dataset_queue=dataset_queue, return_values=return_values, heartbeat_handler=return_values['heartbeat_handler'], sleep_time=sleep_time)
408
426
 
409
427
 
410
- def run_once_kronos_dataset(dataset_queue: Queue, return_values: dict, heartbeat_handler: HeartbeatHandler, **kwargs):
428
+ def run_once_kronos_dataset(dataset_queue: Queue, return_values: dict, heartbeat_handler: HeartbeatHandler, **kwargs) -> None:
411
429
  if heartbeat_handler is None:
412
430
  if "heartbeat_handler" not in return_values.keys():
413
431
  return_values["heartbeat_handler"] = HeartbeatHandler("kronos-dataset", 10)
@@ -477,14 +495,19 @@ def run_once_kronos_dataset(dataset_queue: Queue, return_values: dict, heartbeat
477
495
  logger(logging.INFO, 'update done for %d collection replicas, %d failed (%ds)' % (total, failed, time() - start))
478
496
 
479
497
 
480
- def stop(signum: "Optional[int]" = None, frame: "Optional[FrameType]" = None) -> None:
498
+ def stop(signum: Optional[int] = None, frame: Optional["FrameType"] = None) -> None:
481
499
  """
482
500
  Graceful exit.
483
501
  """
484
502
  graceful_stop.set()
485
503
 
486
504
 
487
- def run(once=False, threads=1, sleep_time_datasets=60, sleep_time_files=60):
505
+ def run(
506
+ once: bool = False,
507
+ threads: int = 1,
508
+ sleep_time_datasets: int = 60,
509
+ sleep_time_files: int = 60
510
+ ) -> None:
488
511
  """
489
512
  Starts up the consumer threads
490
513
  """
@@ -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");