rucio 35.7.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 (493) hide show
  1. rucio/__init__.py +17 -0
  2. rucio/alembicrevision.py +15 -0
  3. rucio/client/__init__.py +15 -0
  4. rucio/client/accountclient.py +433 -0
  5. rucio/client/accountlimitclient.py +183 -0
  6. rucio/client/baseclient.py +974 -0
  7. rucio/client/client.py +76 -0
  8. rucio/client/configclient.py +126 -0
  9. rucio/client/credentialclient.py +59 -0
  10. rucio/client/didclient.py +866 -0
  11. rucio/client/diracclient.py +56 -0
  12. rucio/client/downloadclient.py +1785 -0
  13. rucio/client/exportclient.py +44 -0
  14. rucio/client/fileclient.py +50 -0
  15. rucio/client/importclient.py +42 -0
  16. rucio/client/lifetimeclient.py +90 -0
  17. rucio/client/lockclient.py +109 -0
  18. rucio/client/metaconventionsclient.py +140 -0
  19. rucio/client/pingclient.py +44 -0
  20. rucio/client/replicaclient.py +454 -0
  21. rucio/client/requestclient.py +125 -0
  22. rucio/client/rseclient.py +746 -0
  23. rucio/client/ruleclient.py +294 -0
  24. rucio/client/scopeclient.py +90 -0
  25. rucio/client/subscriptionclient.py +173 -0
  26. rucio/client/touchclient.py +82 -0
  27. rucio/client/uploadclient.py +955 -0
  28. rucio/common/__init__.py +13 -0
  29. rucio/common/cache.py +74 -0
  30. rucio/common/config.py +801 -0
  31. rucio/common/constants.py +159 -0
  32. rucio/common/constraints.py +17 -0
  33. rucio/common/didtype.py +189 -0
  34. rucio/common/dumper/__init__.py +335 -0
  35. rucio/common/dumper/consistency.py +452 -0
  36. rucio/common/dumper/data_models.py +318 -0
  37. rucio/common/dumper/path_parsing.py +64 -0
  38. rucio/common/exception.py +1151 -0
  39. rucio/common/extra.py +36 -0
  40. rucio/common/logging.py +420 -0
  41. rucio/common/pcache.py +1408 -0
  42. rucio/common/plugins.py +153 -0
  43. rucio/common/policy.py +84 -0
  44. rucio/common/schema/__init__.py +150 -0
  45. rucio/common/schema/atlas.py +413 -0
  46. rucio/common/schema/belleii.py +408 -0
  47. rucio/common/schema/domatpc.py +401 -0
  48. rucio/common/schema/escape.py +426 -0
  49. rucio/common/schema/generic.py +433 -0
  50. rucio/common/schema/generic_multi_vo.py +412 -0
  51. rucio/common/schema/icecube.py +406 -0
  52. rucio/common/stomp_utils.py +159 -0
  53. rucio/common/stopwatch.py +55 -0
  54. rucio/common/test_rucio_server.py +148 -0
  55. rucio/common/types.py +403 -0
  56. rucio/common/utils.py +2238 -0
  57. rucio/core/__init__.py +13 -0
  58. rucio/core/account.py +496 -0
  59. rucio/core/account_counter.py +236 -0
  60. rucio/core/account_limit.py +423 -0
  61. rucio/core/authentication.py +620 -0
  62. rucio/core/config.py +456 -0
  63. rucio/core/credential.py +225 -0
  64. rucio/core/did.py +3000 -0
  65. rucio/core/did_meta_plugins/__init__.py +252 -0
  66. rucio/core/did_meta_plugins/did_column_meta.py +331 -0
  67. rucio/core/did_meta_plugins/did_meta_plugin_interface.py +165 -0
  68. rucio/core/did_meta_plugins/filter_engine.py +613 -0
  69. rucio/core/did_meta_plugins/json_meta.py +240 -0
  70. rucio/core/did_meta_plugins/mongo_meta.py +216 -0
  71. rucio/core/did_meta_plugins/postgres_meta.py +316 -0
  72. rucio/core/dirac.py +237 -0
  73. rucio/core/distance.py +187 -0
  74. rucio/core/exporter.py +59 -0
  75. rucio/core/heartbeat.py +363 -0
  76. rucio/core/identity.py +300 -0
  77. rucio/core/importer.py +259 -0
  78. rucio/core/lifetime_exception.py +377 -0
  79. rucio/core/lock.py +576 -0
  80. rucio/core/message.py +282 -0
  81. rucio/core/meta_conventions.py +203 -0
  82. rucio/core/monitor.py +447 -0
  83. rucio/core/naming_convention.py +195 -0
  84. rucio/core/nongrid_trace.py +136 -0
  85. rucio/core/oidc.py +1461 -0
  86. rucio/core/permission/__init__.py +119 -0
  87. rucio/core/permission/atlas.py +1348 -0
  88. rucio/core/permission/belleii.py +1077 -0
  89. rucio/core/permission/escape.py +1078 -0
  90. rucio/core/permission/generic.py +1130 -0
  91. rucio/core/permission/generic_multi_vo.py +1150 -0
  92. rucio/core/quarantined_replica.py +223 -0
  93. rucio/core/replica.py +4158 -0
  94. rucio/core/replica_sorter.py +366 -0
  95. rucio/core/request.py +3089 -0
  96. rucio/core/rse.py +1875 -0
  97. rucio/core/rse_counter.py +186 -0
  98. rucio/core/rse_expression_parser.py +459 -0
  99. rucio/core/rse_selector.py +302 -0
  100. rucio/core/rule.py +4483 -0
  101. rucio/core/rule_grouping.py +1618 -0
  102. rucio/core/scope.py +180 -0
  103. rucio/core/subscription.py +364 -0
  104. rucio/core/topology.py +490 -0
  105. rucio/core/trace.py +375 -0
  106. rucio/core/transfer.py +1517 -0
  107. rucio/core/vo.py +169 -0
  108. rucio/core/volatile_replica.py +150 -0
  109. rucio/daemons/__init__.py +13 -0
  110. rucio/daemons/abacus/__init__.py +13 -0
  111. rucio/daemons/abacus/account.py +116 -0
  112. rucio/daemons/abacus/collection_replica.py +124 -0
  113. rucio/daemons/abacus/rse.py +117 -0
  114. rucio/daemons/atropos/__init__.py +13 -0
  115. rucio/daemons/atropos/atropos.py +242 -0
  116. rucio/daemons/auditor/__init__.py +289 -0
  117. rucio/daemons/auditor/hdfs.py +97 -0
  118. rucio/daemons/auditor/srmdumps.py +355 -0
  119. rucio/daemons/automatix/__init__.py +13 -0
  120. rucio/daemons/automatix/automatix.py +293 -0
  121. rucio/daemons/badreplicas/__init__.py +13 -0
  122. rucio/daemons/badreplicas/minos.py +322 -0
  123. rucio/daemons/badreplicas/minos_temporary_expiration.py +171 -0
  124. rucio/daemons/badreplicas/necromancer.py +196 -0
  125. rucio/daemons/bb8/__init__.py +13 -0
  126. rucio/daemons/bb8/bb8.py +353 -0
  127. rucio/daemons/bb8/common.py +759 -0
  128. rucio/daemons/bb8/nuclei_background_rebalance.py +153 -0
  129. rucio/daemons/bb8/t2_background_rebalance.py +153 -0
  130. rucio/daemons/c3po/__init__.py +13 -0
  131. rucio/daemons/c3po/algorithms/__init__.py +13 -0
  132. rucio/daemons/c3po/algorithms/simple.py +134 -0
  133. rucio/daemons/c3po/algorithms/t2_free_space.py +128 -0
  134. rucio/daemons/c3po/algorithms/t2_free_space_only_pop.py +130 -0
  135. rucio/daemons/c3po/algorithms/t2_free_space_only_pop_with_network.py +294 -0
  136. rucio/daemons/c3po/c3po.py +371 -0
  137. rucio/daemons/c3po/collectors/__init__.py +13 -0
  138. rucio/daemons/c3po/collectors/agis.py +108 -0
  139. rucio/daemons/c3po/collectors/free_space.py +81 -0
  140. rucio/daemons/c3po/collectors/jedi_did.py +57 -0
  141. rucio/daemons/c3po/collectors/mock_did.py +51 -0
  142. rucio/daemons/c3po/collectors/network_metrics.py +71 -0
  143. rucio/daemons/c3po/collectors/workload.py +112 -0
  144. rucio/daemons/c3po/utils/__init__.py +13 -0
  145. rucio/daemons/c3po/utils/dataset_cache.py +50 -0
  146. rucio/daemons/c3po/utils/expiring_dataset_cache.py +56 -0
  147. rucio/daemons/c3po/utils/expiring_list.py +62 -0
  148. rucio/daemons/c3po/utils/popularity.py +85 -0
  149. rucio/daemons/c3po/utils/timeseries.py +89 -0
  150. rucio/daemons/cache/__init__.py +13 -0
  151. rucio/daemons/cache/consumer.py +197 -0
  152. rucio/daemons/common.py +415 -0
  153. rucio/daemons/conveyor/__init__.py +13 -0
  154. rucio/daemons/conveyor/common.py +562 -0
  155. rucio/daemons/conveyor/finisher.py +529 -0
  156. rucio/daemons/conveyor/poller.py +404 -0
  157. rucio/daemons/conveyor/preparer.py +205 -0
  158. rucio/daemons/conveyor/receiver.py +249 -0
  159. rucio/daemons/conveyor/stager.py +132 -0
  160. rucio/daemons/conveyor/submitter.py +403 -0
  161. rucio/daemons/conveyor/throttler.py +532 -0
  162. rucio/daemons/follower/__init__.py +13 -0
  163. rucio/daemons/follower/follower.py +101 -0
  164. rucio/daemons/hermes/__init__.py +13 -0
  165. rucio/daemons/hermes/hermes.py +774 -0
  166. rucio/daemons/judge/__init__.py +13 -0
  167. rucio/daemons/judge/cleaner.py +159 -0
  168. rucio/daemons/judge/evaluator.py +185 -0
  169. rucio/daemons/judge/injector.py +162 -0
  170. rucio/daemons/judge/repairer.py +154 -0
  171. rucio/daemons/oauthmanager/__init__.py +13 -0
  172. rucio/daemons/oauthmanager/oauthmanager.py +198 -0
  173. rucio/daemons/reaper/__init__.py +13 -0
  174. rucio/daemons/reaper/dark_reaper.py +278 -0
  175. rucio/daemons/reaper/reaper.py +743 -0
  176. rucio/daemons/replicarecoverer/__init__.py +13 -0
  177. rucio/daemons/replicarecoverer/suspicious_replica_recoverer.py +626 -0
  178. rucio/daemons/rsedecommissioner/__init__.py +13 -0
  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 +13 -0
  186. rucio/daemons/storage/consistency/__init__.py +13 -0
  187. rucio/daemons/storage/consistency/actions.py +846 -0
  188. rucio/daemons/tracer/__init__.py +13 -0
  189. rucio/daemons/tracer/kronos.py +536 -0
  190. rucio/daemons/transmogrifier/__init__.py +13 -0
  191. rucio/daemons/transmogrifier/transmogrifier.py +762 -0
  192. rucio/daemons/undertaker/__init__.py +13 -0
  193. rucio/daemons/undertaker/undertaker.py +137 -0
  194. rucio/db/__init__.py +13 -0
  195. rucio/db/sqla/__init__.py +52 -0
  196. rucio/db/sqla/constants.py +201 -0
  197. rucio/db/sqla/migrate_repo/__init__.py +13 -0
  198. rucio/db/sqla/migrate_repo/env.py +110 -0
  199. rucio/db/sqla/migrate_repo/versions/01eaf73ab656_add_new_rule_notification_state_progress.py +70 -0
  200. rucio/db/sqla/migrate_repo/versions/0437a40dbfd1_add_eol_at_in_rules.py +47 -0
  201. rucio/db/sqla/migrate_repo/versions/0f1adb7a599a_create_transfer_hops_table.py +59 -0
  202. rucio/db/sqla/migrate_repo/versions/102efcf145f4_added_stuck_at_column_to_rules.py +43 -0
  203. rucio/db/sqla/migrate_repo/versions/13d4f70c66a9_introduce_transfer_limits.py +91 -0
  204. rucio/db/sqla/migrate_repo/versions/140fef722e91_cleanup_distances_table.py +76 -0
  205. rucio/db/sqla/migrate_repo/versions/14ec5aeb64cf_add_request_external_host.py +43 -0
  206. rucio/db/sqla/migrate_repo/versions/156fb5b5a14_add_request_type_to_requests_idx.py +50 -0
  207. rucio/db/sqla/migrate_repo/versions/1677d4d803c8_split_rse_availability_into_multiple.py +68 -0
  208. rucio/db/sqla/migrate_repo/versions/16a0aca82e12_create_index_on_table_replicas_path.py +40 -0
  209. rucio/db/sqla/migrate_repo/versions/1803333ac20f_adding_provenance_and_phys_group.py +45 -0
  210. rucio/db/sqla/migrate_repo/versions/1a29d6a9504c_add_didtype_chck_to_requests.py +60 -0
  211. rucio/db/sqla/migrate_repo/versions/1a80adff031a_create_index_on_rules_hist_recent.py +40 -0
  212. rucio/db/sqla/migrate_repo/versions/1c45d9730ca6_increase_identity_length.py +140 -0
  213. rucio/db/sqla/migrate_repo/versions/1d1215494e95_add_quarantined_replicas_table.py +73 -0
  214. rucio/db/sqla/migrate_repo/versions/1d96f484df21_asynchronous_rules_and_rule_approval.py +74 -0
  215. rucio/db/sqla/migrate_repo/versions/1f46c5f240ac_add_bytes_column_to_bad_replicas.py +43 -0
  216. rucio/db/sqla/migrate_repo/versions/1fc15ab60d43_add_message_history_table.py +50 -0
  217. rucio/db/sqla/migrate_repo/versions/2190e703eb6e_move_rse_settings_to_rse_attributes.py +134 -0
  218. rucio/db/sqla/migrate_repo/versions/21d6b9dc9961_add_mismatch_scheme_state_to_requests.py +64 -0
  219. rucio/db/sqla/migrate_repo/versions/22cf51430c78_add_availability_column_to_table_rses.py +39 -0
  220. rucio/db/sqla/migrate_repo/versions/22d887e4ec0a_create_sources_table.py +64 -0
  221. rucio/db/sqla/migrate_repo/versions/25821a8a45a3_remove_unique_constraint_on_requests.py +51 -0
  222. rucio/db/sqla/migrate_repo/versions/25fc855625cf_added_unique_constraint_to_rules.py +41 -0
  223. rucio/db/sqla/migrate_repo/versions/269fee20dee9_add_repair_cnt_to_locks.py +43 -0
  224. rucio/db/sqla/migrate_repo/versions/271a46ea6244_add_ignore_availability_column_to_rules.py +44 -0
  225. rucio/db/sqla/migrate_repo/versions/277b5fbb41d3_switch_heartbeats_executable.py +53 -0
  226. rucio/db/sqla/migrate_repo/versions/27e3a68927fb_remove_replicas_tombstone_and_replicas_.py +38 -0
  227. rucio/db/sqla/migrate_repo/versions/2854cd9e168_added_rule_id_column.py +47 -0
  228. rucio/db/sqla/migrate_repo/versions/295289b5a800_processed_by_and__at_in_requests.py +45 -0
  229. rucio/db/sqla/migrate_repo/versions/2962ece31cf4_add_nbaccesses_column_in_the_did_table.py +45 -0
  230. rucio/db/sqla/migrate_repo/versions/2af3291ec4c_added_replicas_history_table.py +57 -0
  231. rucio/db/sqla/migrate_repo/versions/2b69addda658_add_columns_for_third_party_copy_read_.py +45 -0
  232. rucio/db/sqla/migrate_repo/versions/2b8e7bcb4783_add_config_table.py +69 -0
  233. rucio/db/sqla/migrate_repo/versions/2ba5229cb54c_add_submitted_at_to_requests_table.py +43 -0
  234. rucio/db/sqla/migrate_repo/versions/2cbee484dcf9_added_column_volume_to_rse_transfer_.py +42 -0
  235. rucio/db/sqla/migrate_repo/versions/2edee4a83846_add_source_to_requests_and_requests_.py +47 -0
  236. rucio/db/sqla/migrate_repo/versions/2eef46be23d4_change_tokens_pk.py +46 -0
  237. rucio/db/sqla/migrate_repo/versions/2f648fc909f3_index_in_rule_history_on_scope_name.py +40 -0
  238. rucio/db/sqla/migrate_repo/versions/3082b8cef557_add_naming_convention_table_and_closed_.py +67 -0
  239. rucio/db/sqla/migrate_repo/versions/30fa38b6434e_add_index_on_service_column_in_the_message_table.py +44 -0
  240. rucio/db/sqla/migrate_repo/versions/3152492b110b_added_staging_area_column.py +77 -0
  241. rucio/db/sqla/migrate_repo/versions/32c7d2783f7e_create_bad_replicas_table.py +60 -0
  242. rucio/db/sqla/migrate_repo/versions/3345511706b8_replicas_table_pk_definition_is_in_.py +72 -0
  243. rucio/db/sqla/migrate_repo/versions/35ef10d1e11b_change_index_on_table_requests.py +42 -0
  244. rucio/db/sqla/migrate_repo/versions/379a19b5332d_create_rse_limits_table.py +65 -0
  245. rucio/db/sqla/migrate_repo/versions/384b96aa0f60_created_rule_history_tables.py +133 -0
  246. rucio/db/sqla/migrate_repo/versions/3ac1660a1a72_extend_distance_table.py +55 -0
  247. rucio/db/sqla/migrate_repo/versions/3ad36e2268b0_create_collection_replicas_updates_table.py +76 -0
  248. rucio/db/sqla/migrate_repo/versions/3c9df354071b_extend_waiting_request_state.py +60 -0
  249. rucio/db/sqla/migrate_repo/versions/3d9813fab443_add_a_new_state_lost_in_badfilesstatus.py +44 -0
  250. rucio/db/sqla/migrate_repo/versions/40ad39ce3160_add_transferred_at_to_requests_table.py +43 -0
  251. rucio/db/sqla/migrate_repo/versions/4207be2fd914_add_notification_column_to_rules.py +64 -0
  252. rucio/db/sqla/migrate_repo/versions/42db2617c364_create_index_on_requests_external_id.py +40 -0
  253. rucio/db/sqla/migrate_repo/versions/436827b13f82_added_column_activity_to_table_requests.py +43 -0
  254. rucio/db/sqla/migrate_repo/versions/44278720f774_update_requests_typ_sta_upd_idx_index.py +44 -0
  255. rucio/db/sqla/migrate_repo/versions/45378a1e76a8_create_collection_replica_table.py +78 -0
  256. rucio/db/sqla/migrate_repo/versions/469d262be19_removing_created_at_index.py +41 -0
  257. rucio/db/sqla/migrate_repo/versions/4783c1f49cb4_create_distance_table.py +59 -0
  258. rucio/db/sqla/migrate_repo/versions/49a21b4d4357_create_index_on_table_tokens.py +44 -0
  259. rucio/db/sqla/migrate_repo/versions/4a2cbedda8b9_add_source_replica_expression_column_to_.py +43 -0
  260. rucio/db/sqla/migrate_repo/versions/4a7182d9578b_added_bytes_length_accessed_at_columns.py +49 -0
  261. rucio/db/sqla/migrate_repo/versions/4bab9edd01fc_create_index_on_requests_rule_id.py +40 -0
  262. rucio/db/sqla/migrate_repo/versions/4c3a4acfe006_new_attr_account_table.py +63 -0
  263. rucio/db/sqla/migrate_repo/versions/4cf0a2e127d4_adding_transient_metadata.py +43 -0
  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 +45 -0
  266. rucio/db/sqla/migrate_repo/versions/52153819589c_add_rse_id_to_replicas_table.py +43 -0
  267. rucio/db/sqla/migrate_repo/versions/52fd9f4916fa_added_activity_to_rules.py +43 -0
  268. rucio/db/sqla/migrate_repo/versions/53b479c3cb0f_fix_did_meta_table_missing_updated_at_.py +45 -0
  269. rucio/db/sqla/migrate_repo/versions/5673b4b6e843_add_wfms_metadata_to_rule_tables.py +47 -0
  270. rucio/db/sqla/migrate_repo/versions/575767d9f89_added_source_history_table.py +58 -0
  271. rucio/db/sqla/migrate_repo/versions/58bff7008037_add_started_at_to_requests.py +45 -0
  272. rucio/db/sqla/migrate_repo/versions/58c8b78301ab_rename_callback_to_message.py +106 -0
  273. rucio/db/sqla/migrate_repo/versions/5f139f77382a_added_child_rule_id_column.py +55 -0
  274. rucio/db/sqla/migrate_repo/versions/688ef1840840_adding_did_meta_table.py +50 -0
  275. rucio/db/sqla/migrate_repo/versions/6e572a9bfbf3_add_new_split_container_column_to_rules.py +47 -0
  276. rucio/db/sqla/migrate_repo/versions/70587619328_add_comment_column_for_subscriptions.py +43 -0
  277. rucio/db/sqla/migrate_repo/versions/739064d31565_remove_history_table_pks.py +41 -0
  278. rucio/db/sqla/migrate_repo/versions/7541902bf173_add_didsfollowed_and_followevents_table.py +91 -0
  279. rucio/db/sqla/migrate_repo/versions/7ec22226cdbf_new_replica_state_for_temporary_.py +72 -0
  280. rucio/db/sqla/migrate_repo/versions/810a41685bc1_added_columns_rse_transfer_limits.py +49 -0
  281. rucio/db/sqla/migrate_repo/versions/83f991c63a93_correct_rse_expression_length.py +43 -0
  282. rucio/db/sqla/migrate_repo/versions/8523998e2e76_increase_size_of_extended_attributes_.py +43 -0
  283. rucio/db/sqla/migrate_repo/versions/8ea9122275b1_adding_missing_function_based_indices.py +53 -0
  284. rucio/db/sqla/migrate_repo/versions/90f47792bb76_add_clob_payload_to_messages.py +45 -0
  285. rucio/db/sqla/migrate_repo/versions/914b8f02df38_new_table_for_lifetime_model_exceptions.py +68 -0
  286. rucio/db/sqla/migrate_repo/versions/94a5961ddbf2_add_estimator_columns.py +45 -0
  287. rucio/db/sqla/migrate_repo/versions/9a1b149a2044_add_saml_identity_type.py +94 -0
  288. rucio/db/sqla/migrate_repo/versions/9a45bc4ea66d_add_vp_table.py +54 -0
  289. rucio/db/sqla/migrate_repo/versions/9eb936a81eb1_true_is_true.py +72 -0
  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 +76 -0
  292. rucio/db/sqla/migrate_repo/versions/a193a275255c_add_status_column_in_messages.py +47 -0
  293. rucio/db/sqla/migrate_repo/versions/a5f6f6e928a7_1_7_0.py +121 -0
  294. rucio/db/sqla/migrate_repo/versions/a616581ee47_added_columns_to_table_requests.py +59 -0
  295. rucio/db/sqla/migrate_repo/versions/a6eb23955c28_state_idx_non_functional.py +52 -0
  296. rucio/db/sqla/migrate_repo/versions/a74275a1ad30_added_global_quota_table.py +54 -0
  297. rucio/db/sqla/migrate_repo/versions/a93e4e47bda_heartbeats.py +64 -0
  298. rucio/db/sqla/migrate_repo/versions/ae2a56fcc89_added_comment_column_to_rules.py +49 -0
  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 +43 -0
  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 +91 -0
  303. rucio/db/sqla/migrate_repo/versions/b818052fa670_add_index_to_quarantined_replicas.py +40 -0
  304. rucio/db/sqla/migrate_repo/versions/b8caac94d7f0_add_comments_column_for_subscriptions_.py +43 -0
  305. rucio/db/sqla/migrate_repo/versions/b96a1c7e1cc4_new_bad_pfns_table_and_bad_replicas_.py +143 -0
  306. rucio/db/sqla/migrate_repo/versions/bb695f45c04_extend_request_state.py +76 -0
  307. rucio/db/sqla/migrate_repo/versions/bc68e9946deb_add_staging_timestamps_to_request.py +50 -0
  308. rucio/db/sqla/migrate_repo/versions/bf3baa1c1474_correct_pk_and_idx_for_history_tables.py +72 -0
  309. rucio/db/sqla/migrate_repo/versions/c0937668555f_add_qos_policy_map_table.py +55 -0
  310. rucio/db/sqla/migrate_repo/versions/c129ccdb2d5_add_lumiblocknr_to_dids.py +43 -0
  311. rucio/db/sqla/migrate_repo/versions/ccdbcd48206e_add_did_type_column_index_on_did_meta_.py +65 -0
  312. rucio/db/sqla/migrate_repo/versions/cebad904c4dd_new_payload_column_for_heartbeats.py +47 -0
  313. rucio/db/sqla/migrate_repo/versions/d1189a09c6e0_oauth2_0_and_jwt_feature_support_adding_.py +146 -0
  314. rucio/db/sqla/migrate_repo/versions/d23453595260_extend_request_state_for_preparer.py +104 -0
  315. rucio/db/sqla/migrate_repo/versions/d6dceb1de2d_added_purge_column_to_rules.py +44 -0
  316. rucio/db/sqla/migrate_repo/versions/d6e2c3b2cf26_remove_third_party_copy_column_from_rse.py +43 -0
  317. rucio/db/sqla/migrate_repo/versions/d91002c5841_new_account_limits_table.py +103 -0
  318. rucio/db/sqla/migrate_repo/versions/e138c364ebd0_extending_columns_for_filter_and_.py +49 -0
  319. rucio/db/sqla/migrate_repo/versions/e59300c8b179_support_for_archive.py +104 -0
  320. rucio/db/sqla/migrate_repo/versions/f1b14a8c2ac1_postgres_use_check_constraints.py +29 -0
  321. rucio/db/sqla/migrate_repo/versions/f41ffe206f37_oracle_global_temporary_tables.py +74 -0
  322. rucio/db/sqla/migrate_repo/versions/f85a2962b021_adding_transfertool_column_to_requests_.py +47 -0
  323. rucio/db/sqla/migrate_repo/versions/fa7a7d78b602_increase_refresh_token_size.py +43 -0
  324. rucio/db/sqla/migrate_repo/versions/fb28a95fe288_add_replicas_rse_id_tombstone_idx.py +37 -0
  325. rucio/db/sqla/migrate_repo/versions/fe1a65b176c9_set_third_party_copy_read_and_write_.py +43 -0
  326. rucio/db/sqla/migrate_repo/versions/fe8ea2fa9788_added_third_party_copy_column_to_rse_.py +43 -0
  327. rucio/db/sqla/models.py +1740 -0
  328. rucio/db/sqla/sautils.py +55 -0
  329. rucio/db/sqla/session.py +498 -0
  330. rucio/db/sqla/types.py +206 -0
  331. rucio/db/sqla/util.py +543 -0
  332. rucio/gateway/__init__.py +13 -0
  333. rucio/gateway/account.py +339 -0
  334. rucio/gateway/account_limit.py +286 -0
  335. rucio/gateway/authentication.py +375 -0
  336. rucio/gateway/config.py +217 -0
  337. rucio/gateway/credential.py +71 -0
  338. rucio/gateway/did.py +970 -0
  339. rucio/gateway/dirac.py +81 -0
  340. rucio/gateway/exporter.py +59 -0
  341. rucio/gateway/heartbeat.py +74 -0
  342. rucio/gateway/identity.py +204 -0
  343. rucio/gateway/importer.py +45 -0
  344. rucio/gateway/lifetime_exception.py +120 -0
  345. rucio/gateway/lock.py +153 -0
  346. rucio/gateway/meta_conventions.py +87 -0
  347. rucio/gateway/permission.py +71 -0
  348. rucio/gateway/quarantined_replica.py +78 -0
  349. rucio/gateway/replica.py +529 -0
  350. rucio/gateway/request.py +321 -0
  351. rucio/gateway/rse.py +600 -0
  352. rucio/gateway/rule.py +417 -0
  353. rucio/gateway/scope.py +99 -0
  354. rucio/gateway/subscription.py +277 -0
  355. rucio/gateway/vo.py +122 -0
  356. rucio/rse/__init__.py +96 -0
  357. rucio/rse/protocols/__init__.py +13 -0
  358. rucio/rse/protocols/bittorrent.py +184 -0
  359. rucio/rse/protocols/cache.py +122 -0
  360. rucio/rse/protocols/dummy.py +111 -0
  361. rucio/rse/protocols/gfal.py +703 -0
  362. rucio/rse/protocols/globus.py +243 -0
  363. rucio/rse/protocols/gsiftp.py +92 -0
  364. rucio/rse/protocols/http_cache.py +82 -0
  365. rucio/rse/protocols/mock.py +123 -0
  366. rucio/rse/protocols/ngarc.py +209 -0
  367. rucio/rse/protocols/posix.py +250 -0
  368. rucio/rse/protocols/protocol.py +594 -0
  369. rucio/rse/protocols/rclone.py +364 -0
  370. rucio/rse/protocols/rfio.py +136 -0
  371. rucio/rse/protocols/srm.py +338 -0
  372. rucio/rse/protocols/ssh.py +413 -0
  373. rucio/rse/protocols/storm.py +206 -0
  374. rucio/rse/protocols/webdav.py +550 -0
  375. rucio/rse/protocols/xrootd.py +301 -0
  376. rucio/rse/rsemanager.py +764 -0
  377. rucio/tests/__init__.py +13 -0
  378. rucio/tests/common.py +270 -0
  379. rucio/tests/common_server.py +132 -0
  380. rucio/transfertool/__init__.py +13 -0
  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 +1596 -0
  385. rucio/transfertool/fts3_plugins.py +152 -0
  386. rucio/transfertool/globus.py +201 -0
  387. rucio/transfertool/globus_library.py +181 -0
  388. rucio/transfertool/mock.py +90 -0
  389. rucio/transfertool/transfertool.py +221 -0
  390. rucio/vcsversion.py +11 -0
  391. rucio/version.py +38 -0
  392. rucio/web/__init__.py +13 -0
  393. rucio/web/rest/__init__.py +13 -0
  394. rucio/web/rest/flaskapi/__init__.py +13 -0
  395. rucio/web/rest/flaskapi/authenticated_bp.py +27 -0
  396. rucio/web/rest/flaskapi/v1/__init__.py +13 -0
  397. rucio/web/rest/flaskapi/v1/accountlimits.py +236 -0
  398. rucio/web/rest/flaskapi/v1/accounts.py +1089 -0
  399. rucio/web/rest/flaskapi/v1/archives.py +102 -0
  400. rucio/web/rest/flaskapi/v1/auth.py +1644 -0
  401. rucio/web/rest/flaskapi/v1/common.py +426 -0
  402. rucio/web/rest/flaskapi/v1/config.py +304 -0
  403. rucio/web/rest/flaskapi/v1/credentials.py +212 -0
  404. rucio/web/rest/flaskapi/v1/dids.py +2334 -0
  405. rucio/web/rest/flaskapi/v1/dirac.py +116 -0
  406. rucio/web/rest/flaskapi/v1/export.py +75 -0
  407. rucio/web/rest/flaskapi/v1/heartbeats.py +127 -0
  408. rucio/web/rest/flaskapi/v1/identities.py +261 -0
  409. rucio/web/rest/flaskapi/v1/import.py +132 -0
  410. rucio/web/rest/flaskapi/v1/lifetime_exceptions.py +312 -0
  411. rucio/web/rest/flaskapi/v1/locks.py +358 -0
  412. rucio/web/rest/flaskapi/v1/main.py +91 -0
  413. rucio/web/rest/flaskapi/v1/meta_conventions.py +241 -0
  414. rucio/web/rest/flaskapi/v1/metrics.py +36 -0
  415. rucio/web/rest/flaskapi/v1/nongrid_traces.py +97 -0
  416. rucio/web/rest/flaskapi/v1/ping.py +88 -0
  417. rucio/web/rest/flaskapi/v1/redirect.py +365 -0
  418. rucio/web/rest/flaskapi/v1/replicas.py +1890 -0
  419. rucio/web/rest/flaskapi/v1/requests.py +998 -0
  420. rucio/web/rest/flaskapi/v1/rses.py +2239 -0
  421. rucio/web/rest/flaskapi/v1/rules.py +854 -0
  422. rucio/web/rest/flaskapi/v1/scopes.py +159 -0
  423. rucio/web/rest/flaskapi/v1/subscriptions.py +650 -0
  424. rucio/web/rest/flaskapi/v1/templates/auth_crash.html +80 -0
  425. rucio/web/rest/flaskapi/v1/templates/auth_granted.html +82 -0
  426. rucio/web/rest/flaskapi/v1/traces.py +100 -0
  427. rucio/web/rest/flaskapi/v1/types.py +20 -0
  428. rucio/web/rest/flaskapi/v1/vos.py +278 -0
  429. rucio/web/rest/main.py +18 -0
  430. rucio/web/rest/metrics.py +27 -0
  431. rucio/web/rest/ping.py +27 -0
  432. rucio-35.7.0.data/data/rucio/etc/alembic.ini.template +71 -0
  433. rucio-35.7.0.data/data/rucio/etc/alembic_offline.ini.template +74 -0
  434. rucio-35.7.0.data/data/rucio/etc/globus-config.yml.template +5 -0
  435. rucio-35.7.0.data/data/rucio/etc/ldap.cfg.template +30 -0
  436. rucio-35.7.0.data/data/rucio/etc/mail_templates/rule_approval_request.tmpl +38 -0
  437. rucio-35.7.0.data/data/rucio/etc/mail_templates/rule_approved_admin.tmpl +4 -0
  438. rucio-35.7.0.data/data/rucio/etc/mail_templates/rule_approved_user.tmpl +17 -0
  439. rucio-35.7.0.data/data/rucio/etc/mail_templates/rule_denied_admin.tmpl +6 -0
  440. rucio-35.7.0.data/data/rucio/etc/mail_templates/rule_denied_user.tmpl +17 -0
  441. rucio-35.7.0.data/data/rucio/etc/mail_templates/rule_ok_notification.tmpl +19 -0
  442. rucio-35.7.0.data/data/rucio/etc/rse-accounts.cfg.template +25 -0
  443. rucio-35.7.0.data/data/rucio/etc/rucio.cfg.atlas.client.template +42 -0
  444. rucio-35.7.0.data/data/rucio/etc/rucio.cfg.template +257 -0
  445. rucio-35.7.0.data/data/rucio/etc/rucio_multi_vo.cfg.template +234 -0
  446. rucio-35.7.0.data/data/rucio/requirements.server.txt +268 -0
  447. rucio-35.7.0.data/data/rucio/tools/bootstrap.py +34 -0
  448. rucio-35.7.0.data/data/rucio/tools/merge_rucio_configs.py +144 -0
  449. rucio-35.7.0.data/data/rucio/tools/reset_database.py +40 -0
  450. rucio-35.7.0.data/scripts/rucio +2542 -0
  451. rucio-35.7.0.data/scripts/rucio-abacus-account +74 -0
  452. rucio-35.7.0.data/scripts/rucio-abacus-collection-replica +46 -0
  453. rucio-35.7.0.data/scripts/rucio-abacus-rse +78 -0
  454. rucio-35.7.0.data/scripts/rucio-admin +2447 -0
  455. rucio-35.7.0.data/scripts/rucio-atropos +60 -0
  456. rucio-35.7.0.data/scripts/rucio-auditor +205 -0
  457. rucio-35.7.0.data/scripts/rucio-automatix +50 -0
  458. rucio-35.7.0.data/scripts/rucio-bb8 +57 -0
  459. rucio-35.7.0.data/scripts/rucio-c3po +85 -0
  460. rucio-35.7.0.data/scripts/rucio-cache-client +134 -0
  461. rucio-35.7.0.data/scripts/rucio-cache-consumer +42 -0
  462. rucio-35.7.0.data/scripts/rucio-conveyor-finisher +58 -0
  463. rucio-35.7.0.data/scripts/rucio-conveyor-poller +66 -0
  464. rucio-35.7.0.data/scripts/rucio-conveyor-preparer +37 -0
  465. rucio-35.7.0.data/scripts/rucio-conveyor-receiver +43 -0
  466. rucio-35.7.0.data/scripts/rucio-conveyor-stager +76 -0
  467. rucio-35.7.0.data/scripts/rucio-conveyor-submitter +139 -0
  468. rucio-35.7.0.data/scripts/rucio-conveyor-throttler +104 -0
  469. rucio-35.7.0.data/scripts/rucio-dark-reaper +53 -0
  470. rucio-35.7.0.data/scripts/rucio-dumper +160 -0
  471. rucio-35.7.0.data/scripts/rucio-follower +44 -0
  472. rucio-35.7.0.data/scripts/rucio-hermes +54 -0
  473. rucio-35.7.0.data/scripts/rucio-judge-cleaner +89 -0
  474. rucio-35.7.0.data/scripts/rucio-judge-evaluator +137 -0
  475. rucio-35.7.0.data/scripts/rucio-judge-injector +44 -0
  476. rucio-35.7.0.data/scripts/rucio-judge-repairer +44 -0
  477. rucio-35.7.0.data/scripts/rucio-kronos +43 -0
  478. rucio-35.7.0.data/scripts/rucio-minos +53 -0
  479. rucio-35.7.0.data/scripts/rucio-minos-temporary-expiration +50 -0
  480. rucio-35.7.0.data/scripts/rucio-necromancer +120 -0
  481. rucio-35.7.0.data/scripts/rucio-oauth-manager +63 -0
  482. rucio-35.7.0.data/scripts/rucio-reaper +83 -0
  483. rucio-35.7.0.data/scripts/rucio-replica-recoverer +248 -0
  484. rucio-35.7.0.data/scripts/rucio-rse-decommissioner +66 -0
  485. rucio-35.7.0.data/scripts/rucio-storage-consistency-actions +74 -0
  486. rucio-35.7.0.data/scripts/rucio-transmogrifier +77 -0
  487. rucio-35.7.0.data/scripts/rucio-undertaker +76 -0
  488. rucio-35.7.0.dist-info/METADATA +72 -0
  489. rucio-35.7.0.dist-info/RECORD +493 -0
  490. rucio-35.7.0.dist-info/WHEEL +5 -0
  491. rucio-35.7.0.dist-info/licenses/AUTHORS.rst +97 -0
  492. rucio-35.7.0.dist-info/licenses/LICENSE +201 -0
  493. rucio-35.7.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,13 @@
1
+ # Copyright European Organization for Nuclear Research (CERN) since 2012
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
@@ -0,0 +1,536 @@
1
+ # Copyright European Organization for Nuclear Research (CERN) since 2012
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """
16
+ This daemon consumes tracer messages from ActiveMQ and updates the atime for replicas.
17
+ """
18
+
19
+ import functools
20
+ import logging
21
+ import re
22
+ from configparser import NoOptionError, NoSectionError
23
+ from datetime import datetime
24
+ from json import dumps as jdumps
25
+ from json import loads as jloads
26
+ from queue import Queue
27
+ from threading import Event, Thread
28
+ from time import time
29
+ from typing import TYPE_CHECKING, Optional
30
+
31
+ import rucio.db.sqla.util
32
+ from rucio.common.config import config_get, config_get_bool, config_get_int, config_get_list
33
+ from rucio.common.exception import DatabaseException, RSENotFound
34
+ from rucio.common.logging import setup_logging
35
+ from rucio.common.stomp_utils import StompConnectionManager
36
+ from rucio.common.stopwatch import Stopwatch
37
+ from rucio.common.types import InternalAccount, InternalScope, LoggerFunction
38
+ from rucio.core.did import list_parent_dids, touch_dids
39
+ from rucio.core.lock import touch_dataset_locks
40
+ from rucio.core.monitor import MetricManager
41
+ from rucio.core.replica import declare_bad_file_replicas, touch_collection_replicas, touch_replica
42
+ from rucio.core.rse import get_rse_id
43
+ from rucio.daemons.common import HeartbeatHandler, run_daemon
44
+ from rucio.db.sqla.constants import BadFilesStatus, DIDType
45
+
46
+ if TYPE_CHECKING:
47
+ from collections.abc import Set
48
+ from types import FrameType
49
+
50
+ from stomp import Connection
51
+ from stomp.utils import Frame
52
+
53
+
54
+ logging.getLogger("stomp").setLevel(logging.CRITICAL)
55
+
56
+ METRICS = MetricManager(module=__name__)
57
+ graceful_stop = Event()
58
+
59
+
60
+ class AMQConsumer:
61
+ """ActiveMQ message consumer"""
62
+
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
+ ):
75
+ self.__broker = broker
76
+ self.__conn = conn
77
+ self.__queue = queue
78
+ self.__reports = []
79
+ self.__ids = []
80
+ self.__chunksize = chunksize
81
+ self.__subscription_id = subscription_id
82
+ # excluded states empty for the moment, maybe that should be recosidered in the future
83
+ self.__excluded_states = set([])
84
+ # exclude specific usrdns like GangaRBT
85
+ self.__excluded_usrdns = excluded_usrdns
86
+ self.__dataset_queue = dataset_queue
87
+ self.__bad_files_patterns = bad_files_patterns
88
+ self.__logger = logger
89
+
90
+ @METRICS.count_it
91
+ def on_heartbeat_timeout(self) -> None:
92
+ self.__conn.disconnect()
93
+
94
+ @METRICS.count_it
95
+ def on_error(self, frame: "Frame") -> None:
96
+ self.__logger(logging.ERROR, 'Message receive error: [%s] %s' % (self.__broker, frame.body))
97
+
98
+ @METRICS.count_it
99
+ def on_message(self, frame: "Frame") -> None:
100
+ appversion = 'dq2'
101
+ msg_id = frame.headers['message-id']
102
+ if 'appversion' in frame.headers:
103
+ appversion = frame.headers['appversion']
104
+
105
+ if 'resubmitted' in frame.headers:
106
+ METRICS.counter('received_resubmitted').inc()
107
+
108
+ try:
109
+ if appversion == 'dq2':
110
+ self.__conn.ack(msg_id, self.__subscription_id)
111
+ return
112
+ else:
113
+ report = jloads(frame.body) # type: ignore
114
+ except Exception:
115
+ # message is corrupt, not much to do here
116
+ # send count to graphite, send ack to broker and return
117
+ METRICS.counter('json_error').inc()
118
+ self.__logger(logging.ERROR, 'json error', exc_info=True)
119
+ self.__conn.ack(msg_id, self.__subscription_id)
120
+ return
121
+
122
+ self.__ids.append(msg_id)
123
+ self.__reports.append(report)
124
+
125
+ try:
126
+ self.__logger(logging.DEBUG, 'message received: %s %s %s' % (str(report['eventType']), report['filename'], report['remoteSite']))
127
+ except Exception:
128
+ pass
129
+
130
+ if len(self.__ids) >= self.__chunksize:
131
+ self.__update_atime()
132
+ for msg_id in self.__ids:
133
+ self.__conn.ack(msg_id, self.__subscription_id)
134
+
135
+ self.__reports = []
136
+ self.__ids = []
137
+
138
+ def __update_atime(self) -> None:
139
+ """
140
+ Bulk update atime.
141
+ """
142
+ replicas = []
143
+ rses = []
144
+ for report in self.__reports:
145
+ if 'vo' not in report:
146
+ report['vo'] = 'def'
147
+
148
+ try:
149
+ # Identify suspicious files
150
+ try:
151
+ if self.__bad_files_patterns and report['eventType'] in ['get_sm', 'get_sm_a', 'get'] and 'clientState' in report and report['clientState'] not in ['DONE', 'FOUND_ROOT', 'ALREADY_DONE']:
152
+ for pattern in self.__bad_files_patterns:
153
+ if 'stateReason' in report and report['stateReason'] and isinstance(report['stateReason'], str) and pattern.match(report['stateReason']):
154
+ reason = report['stateReason'][:255]
155
+ if 'url' not in report or not report['url']:
156
+ self.__logger(logging.ERROR, 'Missing url in the following trace : ' + str(report))
157
+ else:
158
+ try:
159
+ pfn = report['url']
160
+ declare_bad_file_replicas([pfn, ], reason=reason, issuer=InternalAccount('root', vo=report['vo']), status=BadFilesStatus.SUSPICIOUS)
161
+ self.__logger(logging.INFO, 'Declare suspicious file %s with reason %s' % (report['url'], reason))
162
+ except Exception as error:
163
+ self.__logger(logging.ERROR, 'Failed to declare suspicious file' + str(error))
164
+ except Exception as error:
165
+ self.__logger(logging.ERROR, 'Problem with bad trace : %s . Error %s' % (str(report), str(error)))
166
+
167
+ # check if scope in report. if not skip this one.
168
+ if 'scope' not in report:
169
+ METRICS.counter('missing_scope').inc()
170
+ if report['eventType'] != 'touch':
171
+ continue
172
+ else:
173
+ METRICS.counter('with_scope').inc()
174
+ report['scope'] = InternalScope(report['scope'], report['vo'])
175
+
176
+ # handle all events starting with get* and download and touch events.
177
+ if not report['eventType'].startswith('get') and not report['eventType'].startswith('sm_get') and not report['eventType'] == 'download' and not report['eventType'] == 'touch':
178
+ continue
179
+ if report['eventType'].endswith('_es'):
180
+ continue
181
+ METRICS.counter('total_get').inc()
182
+ if report['eventType'] == 'get':
183
+ METRICS.counter('dq2clients').inc()
184
+ elif report['eventType'] == 'get_sm' or report['eventType'] == 'sm_get':
185
+ if report['eventVersion'] == 'aCT':
186
+ METRICS.counter('panda_production_act').inc()
187
+ else:
188
+ METRICS.counter('panda_production').inc()
189
+ elif report['eventType'] == 'get_sm_a' or report['eventType'] == 'sm_get_a':
190
+ if report['eventVersion'] == 'aCT':
191
+ METRICS.counter('panda_analysis_act').inc()
192
+ else:
193
+ METRICS.counter('panda_analysis').inc()
194
+ elif report['eventType'] == 'download':
195
+ METRICS.counter('rucio_download').inc()
196
+ elif report['eventType'] == 'touch':
197
+ METRICS.counter('rucio_touch').inc()
198
+ else:
199
+ METRICS.counter('other_get').inc()
200
+
201
+ if report['eventType'] == 'download' or report['eventType'] == 'touch':
202
+ report['usrdn'] = report['account']
203
+
204
+ if report['usrdn'] in self.__excluded_usrdns:
205
+ continue
206
+ # handle touch and non-touch traces differently
207
+ if report['eventType'] != 'touch':
208
+ # check if the report has the right state.
209
+ if 'eventVersion' in report:
210
+ if report['eventVersion'] != 'aCT':
211
+ if report['clientState'] in self.__excluded_states:
212
+ continue
213
+
214
+ if 'remoteSite' not in report:
215
+ continue
216
+ if not report['remoteSite']:
217
+ continue
218
+
219
+ if 'filename' not in report:
220
+ if 'name' in report:
221
+ report['filename'] = report['name']
222
+
223
+ rses = report['remoteSite'].strip().split(',')
224
+ for rse in rses:
225
+ try:
226
+ rse_id = get_rse_id(rse=rse, vo=report['vo'])
227
+ except RSENotFound:
228
+ self.__logger(logging.WARNING, "Cannot lookup rse_id for %s. Will skip this report.", rse)
229
+ METRICS.counter('rse_not_found').inc()
230
+ continue
231
+ replicas.append({'name': report['filename'], 'scope': report['scope'], 'rse': rse, 'rse_id': rse_id, 'accessed_at': datetime.utcfromtimestamp(report['traceTimeentryUnix']),
232
+ 'traceTimeentryUnix': report['traceTimeentryUnix'], 'eventVersion': report['eventVersion']})
233
+ else:
234
+ # if touch event and if datasetScope is in the report then it means
235
+ # that there is no file scope/name and therefore only the dataset is
236
+ # put in the queue to be updated and the rest is skipped.
237
+ rse_id = None
238
+ rse = None
239
+ if 'remoteSite' in report:
240
+ rse = report['remoteSite']
241
+ try:
242
+ rse_id = get_rse_id(rse=rse, vo=report['vo'])
243
+ except RSENotFound:
244
+ self.__logger(logging.WARNING, "Cannot lookup rse_id for %s.", rse)
245
+ METRICS.counter('rse_not_found').inc()
246
+ if 'datasetScope' in report:
247
+ self.__dataset_queue.put({'scope': InternalScope(report['datasetScope'], vo=report['vo']),
248
+ 'name': report['dataset'],
249
+ 'rse_id': rse_id,
250
+ 'accessed_at': datetime.utcfromtimestamp(report['traceTimeentryUnix'])})
251
+ continue
252
+ else:
253
+ if 'remoteSite' not in report:
254
+ continue
255
+ replicas.append({'name': report['filename'],
256
+ 'scope': report['scope'],
257
+ 'rse': rse,
258
+ 'rse_id': rse_id,
259
+ 'accessed_at': datetime.utcfromtimestamp(report['traceTimeentryUnix'])})
260
+
261
+ except (KeyError, AttributeError):
262
+ self.__logger(logging.ERROR, "Cannot handle report.", exc_info=True)
263
+ METRICS.counter('report_error').inc()
264
+ continue
265
+ except Exception:
266
+ self.__logger(logging.ERROR, "Exception", exc_info=True)
267
+ continue
268
+
269
+ for did in list_parent_dids(report['scope'], report['filename']):
270
+ if did['type'] != DIDType.DATASET:
271
+ continue
272
+ # do not update _dis datasets
273
+ if did['scope'].external == 'panda' and '_dis' in did['name']:
274
+ continue
275
+ for rse in rses:
276
+ try:
277
+ rse_id = get_rse_id(rse=rse, vo=report['vo'])
278
+ except RSENotFound:
279
+ self.__logger(logging.WARNING, "Cannot lookup rse_id for %s. Will skip this report.", rse)
280
+ METRICS.counter('rse_not_found').inc()
281
+ continue
282
+ self.__dataset_queue.put({'scope': did['scope'], 'name': did['name'], 'did_type': did['type'], 'rse_id': rse_id, 'accessed_at': datetime.utcfromtimestamp(report['traceTimeentryUnix'])})
283
+
284
+ if not len(replicas):
285
+ return
286
+
287
+ self.__logger(logging.DEBUG, "trying to update replicas: %s", replicas)
288
+
289
+ stopwatch = Stopwatch()
290
+ try:
291
+ for replica in replicas:
292
+ # if touch replica hits a locked row put the trace back into queue for later retry
293
+ if not touch_replica(replica):
294
+ resubmit = {'filename': replica['name'],
295
+ 'scope': replica['scope'].external,
296
+ 'remoteSite': replica['rse'],
297
+ 'traceTimeentryUnix': replica['traceTimeentryUnix'],
298
+ 'eventType': 'get',
299
+ 'usrdn': 'someuser',
300
+ 'clientState': 'DONE',
301
+ 'eventVersion': replica['eventVersion']}
302
+ if replica['scope'].vo != 'def':
303
+ resubmit['vo'] = replica['scope'].vo
304
+ self.__conn.send(body=jdumps(resubmit), destination=self.__queue, headers={'appversion': 'rucio', 'resubmitted': '1'})
305
+ METRICS.counter('sent_resubmitted').inc()
306
+ METRICS.timer('update_atime').observe(stopwatch.elapsed)
307
+ except Exception:
308
+ self.__logger(logging.ERROR, "Cannot update replicas.", exc_info=True)
309
+ METRICS.counter('update_error').inc()
310
+
311
+ METRICS.counter('updated_replicas').inc()
312
+
313
+
314
+ def kronos_file(
315
+ once: bool = False,
316
+ dataset_queue: Optional[Queue] = None,
317
+ sleep_time: int = 60
318
+ ) -> None:
319
+ """
320
+ Main loop to consume tracer reports.
321
+ """
322
+ stomp_conn_mngr = StompConnectionManager()
323
+ run_daemon(
324
+ once=once,
325
+ graceful_stop=graceful_stop,
326
+ executable='kronos-file',
327
+ partition_wait_time=1,
328
+ sleep_time=sleep_time,
329
+ run_once_fnc=functools.partial(
330
+ run_once_kronos_file,
331
+ stomp_conn_mngr=stomp_conn_mngr,
332
+ dataset_queue=dataset_queue, # type: ignore
333
+ sleep_time=sleep_time,
334
+ )
335
+ )
336
+ stomp_conn_mngr.disconnect()
337
+
338
+
339
+ def run_once_kronos_file(heartbeat_handler: HeartbeatHandler, stomp_conn_mngr: StompConnectionManager, dataset_queue: Queue, sleep_time: int, **kwargs) -> None:
340
+ """
341
+ Run the amq consumer once.
342
+ """
343
+ _, _, logger = heartbeat_handler.live()
344
+
345
+ chunksize = config_get_int('tracer-kronos', 'chunksize')
346
+ prefetch_size = config_get_int('tracer-kronos', 'prefetch_size')
347
+ subscription_id = config_get('tracer-kronos', 'subscription_id')
348
+ # Load bad file patterns from config
349
+ try:
350
+ bad_files_patterns = []
351
+ pattern = config_get(section='kronos', option='bad_files_patterns', session=None)
352
+ pattern = str(pattern)
353
+ patterns = pattern.split(",")
354
+ for pat in patterns:
355
+ bad_files_patterns.append(re.compile(pat.strip()))
356
+ except (NoOptionError, NoSectionError, RuntimeError):
357
+ bad_files_patterns = []
358
+ except Exception as error:
359
+ logger.error(f'Failed to get bad_file_patterns {str(error)}')
360
+ bad_files_patterns = []
361
+
362
+ use_ssl = config_get_bool('tracer-kronos', 'use_ssl', default=True, raise_exception=False)
363
+ if not use_ssl:
364
+ username = config_get('tracer-kronos', 'username')
365
+ password = config_get('tracer-kronos', 'password')
366
+
367
+ excluded_usrdns = set(config_get('tracer-kronos', 'excluded_usrdns').split(','))
368
+ vhost = config_get('tracer-kronos', 'broker_virtual_host', raise_exception=False)
369
+
370
+ brokers_alias = config_get_list('tracer-kronos', 'brokers')
371
+ port = config_get_int('tracer-kronos', 'port')
372
+ reconnect_attempts = config_get_int('tracer-kronos', 'reconnect_attempts')
373
+ ssl_key_file = config_get('tracer-kronos', 'ssl_key_file', raise_exception=False)
374
+ ssl_cert_file = config_get('tracer-kronos', 'ssl_cert_file', raise_exception=False)
375
+
376
+ created_conns, _ = stomp_conn_mngr.re_configure(
377
+ brokers=brokers_alias,
378
+ port=port,
379
+ use_ssl=use_ssl,
380
+ vhost=vhost,
381
+ reconnect_attempts=reconnect_attempts,
382
+ ssl_key_file=ssl_key_file,
383
+ ssl_cert_file=ssl_cert_file,
384
+ timeout=sleep_time,
385
+ heartbeats=(0, 5000),
386
+ logger=logger,
387
+ )
388
+
389
+ for conn in created_conns:
390
+ if not conn.is_connected():
391
+ logger(logging.INFO, 'connecting to %s' % str(conn.transport._Transport__host_and_ports[0]))
392
+ METRICS.counter('reconnect.{host}').labels(host=conn.transport._Transport__host_and_ports[0][0]).inc()
393
+ conn.set_listener('rucio-tracer-kronos', AMQConsumer(broker=conn.transport._Transport__host_and_ports[0],
394
+ conn=conn,
395
+ queue=config_get('tracer-kronos', 'queue'),
396
+ chunksize=chunksize,
397
+ subscription_id=subscription_id,
398
+ excluded_usrdns=excluded_usrdns,
399
+ dataset_queue=dataset_queue,
400
+ bad_files_patterns=bad_files_patterns,
401
+ logger=logger))
402
+ if not use_ssl:
403
+ conn.connect(username, password)
404
+ else:
405
+ conn.connect()
406
+ conn.subscribe(destination=config_get('tracer-kronos', 'queue'), ack='client-individual', id=subscription_id, headers={'activemq.prefetchSize': prefetch_size})
407
+
408
+
409
+ def kronos_dataset(dataset_queue: Queue, once: bool = False, sleep_time: int = 60) -> None:
410
+ return_values = {'heartbeat_handler': HeartbeatHandler("kronos-dataset", 10)}
411
+ run_daemon(
412
+ once=once,
413
+ graceful_stop=graceful_stop,
414
+ executable='kronos-dataset',
415
+ partition_wait_time=1,
416
+ sleep_time=sleep_time,
417
+ run_once_fnc=functools.partial(
418
+ run_once_kronos_dataset,
419
+ dataset_queue=dataset_queue,
420
+ return_values=return_values,
421
+ )
422
+ )
423
+
424
+ # once again for potential backlog
425
+ run_once_kronos_dataset(dataset_queue=dataset_queue, return_values=return_values, heartbeat_handler=return_values['heartbeat_handler'], sleep_time=sleep_time)
426
+
427
+
428
+ def run_once_kronos_dataset(dataset_queue: Queue, return_values: dict, heartbeat_handler: HeartbeatHandler, **kwargs) -> None:
429
+ if heartbeat_handler is None:
430
+ if "heartbeat_handler" not in return_values.keys():
431
+ return_values["heartbeat_handler"] = HeartbeatHandler("kronos-dataset", 10)
432
+ heartbeat_handler = return_values["heartbeat_handler"]
433
+
434
+ _, _, logger = heartbeat_handler.live()
435
+ len_ds = dataset_queue.qsize()
436
+ datasets = {}
437
+ dslocks = {}
438
+ now = time()
439
+ for _ in range(0, len_ds):
440
+ dataset = dataset_queue.get()
441
+ did = '%s:%s' % (dataset['scope'].internal, dataset['name'])
442
+ rse = dataset['rse_id']
443
+ if did not in datasets:
444
+ datasets[did] = dataset['accessed_at']
445
+ else:
446
+ datasets[did] = max(datasets[did], dataset['accessed_at'])
447
+
448
+ if rse is None:
449
+ continue
450
+ if did not in dslocks:
451
+ dslocks[did] = {}
452
+ if rse not in dslocks[did]:
453
+ dslocks[did][rse] = dataset['accessed_at']
454
+ else:
455
+ dslocks[did][rse] = max(dataset['accessed_at'], dslocks[did][rse])
456
+ logger(logging.INFO, 'fetched %d datasets from queue (%ds)' % (len_ds, time() - now))
457
+
458
+ total, failed, start = 0, 0, time()
459
+ for did, accessed_at in datasets.items():
460
+ scope, name = did.split(':')
461
+ scope = InternalScope(scope, fromExternal=False)
462
+ update_did = {'scope': scope, 'name': name, 'type': DIDType.DATASET, 'accessed_at': accessed_at}
463
+ # if update fails, put back in queue and retry next time
464
+ if not touch_dids((update_did,)):
465
+ update_did['rse_id'] = None
466
+ dataset_queue.put(update_did)
467
+ failed += 1
468
+ total += 1
469
+ logger(logging.INFO, 'update done for %d datasets, %d failed (%ds)' % (total, failed, time() - start))
470
+
471
+ total, failed, start = 0, 0, time()
472
+ for did, rses in dslocks.items():
473
+ scope, name = did.split(':')
474
+ scope = InternalScope(scope, fromExternal=False)
475
+ for rse, accessed_at in rses.items():
476
+ update_dslock = {'scope': scope, 'name': name, 'rse_id': rse, 'accessed_at': accessed_at}
477
+ # if update fails, put back in queue and retry next time
478
+ if not touch_dataset_locks((update_dslock,)):
479
+ dataset_queue.put(update_dslock)
480
+ failed += 1
481
+ total += 1
482
+ logger(logging.INFO, 'update done for %d locks, %d failed (%ds)' % (total, failed, time() - start))
483
+
484
+ total, failed, start = 0, 0, time()
485
+ for did, rses in dslocks.items():
486
+ scope, name = did.split(':')
487
+ scope = InternalScope(scope, fromExternal=False)
488
+ for rse, accessed_at in rses.items():
489
+ update_dslock = {'scope': scope, 'name': name, 'rse_id': rse, 'accessed_at': accessed_at}
490
+ # if update fails, put back in queue and retry next time
491
+ if not touch_collection_replicas((update_dslock,)):
492
+ dataset_queue.put(update_dslock)
493
+ failed += 1
494
+ total += 1
495
+ logger(logging.INFO, 'update done for %d collection replicas, %d failed (%ds)' % (total, failed, time() - start))
496
+
497
+
498
+ def stop(signum: Optional[int] = None, frame: Optional["FrameType"] = None) -> None:
499
+ """
500
+ Graceful exit.
501
+ """
502
+ graceful_stop.set()
503
+
504
+
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:
511
+ """
512
+ Starts up the consumer threads
513
+ """
514
+ setup_logging(process_name='tracer-kronos')
515
+
516
+ if rucio.db.sqla.util.is_old_db():
517
+ raise DatabaseException('Database was not updated, daemon won\'t start')
518
+
519
+ dataset_queue = Queue()
520
+ logging.info('starting tracer consumer threads')
521
+
522
+ thread_list = []
523
+ for _ in range(0, threads):
524
+ thread_list.append(Thread(target=kronos_file, kwargs={'once': once,
525
+ 'sleep_time': sleep_time_files,
526
+ 'dataset_queue': dataset_queue}))
527
+ thread_list.append(Thread(target=kronos_dataset, kwargs={'once': once,
528
+ 'sleep_time': sleep_time_datasets,
529
+ 'dataset_queue': dataset_queue}))
530
+
531
+ [thread.start() for thread in thread_list]
532
+
533
+ logging.info('waiting for interrupts')
534
+
535
+ while len(thread_list) > 0:
536
+ thread_list = [thread.join(timeout=3) for thread in thread_list if thread and thread.is_alive()]
@@ -0,0 +1,13 @@
1
+ # Copyright European Organization for Nuclear Research (CERN) since 2012
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.