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,371 @@
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
+ Dynamic data placement daemon.
17
+ '''
18
+
19
+ import logging
20
+ from datetime import datetime
21
+ from hashlib import md5
22
+ from json import dumps
23
+ from queue import Queue
24
+ from threading import Event, Thread
25
+ from time import sleep
26
+ from typing import TYPE_CHECKING, Optional
27
+ from uuid import uuid4
28
+
29
+ from requests import post
30
+ from requests.auth import HTTPBasicAuth
31
+ from requests.exceptions import RequestException
32
+
33
+ import rucio.db.sqla.util
34
+ from rucio.client import Client
35
+ from rucio.common import exception
36
+ from rucio.common.config import config_get, config_get_options
37
+ from rucio.common.logging import setup_logging
38
+ from rucio.common.types import InternalScope
39
+ from rucio.daemons.c3po.collectors.free_space import FreeSpaceCollector
40
+ from rucio.daemons.c3po.collectors.jedi_did import JediDIDCollector
41
+ from rucio.daemons.c3po.collectors.workload import WorkloadCollector
42
+
43
+ if TYPE_CHECKING:
44
+ from types import FrameType
45
+
46
+ GRACEFUL_STOP = Event()
47
+ DAEMON_NAME = 'c3po'
48
+
49
+
50
+ def read_free_space(
51
+ once: bool = False,
52
+ thread: int = 0,
53
+ waiting_time: int = 1800,
54
+ sleep_time: int = 10
55
+ ) -> None:
56
+ """
57
+ Thread to collect the space usage information for RSEs.
58
+ """
59
+ free_space_collector = FreeSpaceCollector()
60
+ timer = waiting_time
61
+ while not GRACEFUL_STOP.is_set():
62
+ if timer < waiting_time:
63
+ timer += sleep_time
64
+ sleep(sleep_time)
65
+ continue
66
+
67
+ logging.info('collecting free space')
68
+ free_space_collector.collect_free_space()
69
+ timer = 0
70
+
71
+
72
+ def read_workload(
73
+ once: bool = False,
74
+ thread: int = 0,
75
+ waiting_time: int = 1800,
76
+ sleep_time: int = 10
77
+ ) -> None:
78
+ """
79
+ Thread to collect the workload information from PanDA.
80
+ """
81
+ workload_collector = WorkloadCollector()
82
+ timer = waiting_time
83
+ while not GRACEFUL_STOP.is_set():
84
+ if timer < waiting_time:
85
+ timer += sleep_time
86
+ sleep(sleep_time)
87
+ continue
88
+
89
+ logging.info('collecting workload')
90
+ workload_collector.collect_workload()
91
+ timer = 0
92
+
93
+
94
+ def print_workload(
95
+ once: bool = False,
96
+ thread: int = 0,
97
+ waiting_time: int = 600,
98
+ sleep_time: int = 10
99
+ ) -> None:
100
+ """
101
+ Thread to regularly output the workload to logs for debugging.
102
+ """
103
+ workload_collector = WorkloadCollector()
104
+ timer = waiting_time
105
+ while not GRACEFUL_STOP.is_set():
106
+ if timer < waiting_time:
107
+ timer += sleep_time
108
+ sleep(sleep_time)
109
+ continue
110
+
111
+ logging.info('Number of sites cached %d' % len(workload_collector.get_sites()))
112
+ for site in workload_collector.get_sites():
113
+ logging.info('%s: %d / %d / %d' % (site, workload_collector.get_cur_jobs(site), workload_collector.get_avg_jobs(site), workload_collector.get_max_jobs(site)))
114
+ timer = 0
115
+
116
+
117
+ def read_dids(
118
+ once: bool = False,
119
+ thread: int = 0,
120
+ did_collector: Optional[JediDIDCollector] = None,
121
+ waiting_time: int = 60,
122
+ sleep_time: int = 10
123
+ ) -> None:
124
+ """
125
+ Thread to collect DIDs for the placement algorithm.
126
+ """
127
+ timer = waiting_time
128
+ while not GRACEFUL_STOP.is_set():
129
+ if timer < waiting_time:
130
+ timer += sleep_time
131
+ sleep(sleep_time)
132
+ continue
133
+
134
+ if did_collector is not None:
135
+ did_collector.get_dids()
136
+ timer = 0
137
+
138
+
139
+ def add_rule(
140
+ client: Client,
141
+ did: dict[str, str],
142
+ src_rse: str,
143
+ dst_rse: str
144
+ ) -> None:
145
+ logging.debug('add rule for %s from %s to %s' % (did, src_rse, dst_rse))
146
+ r = client.add_replication_rule([did, ], 1, dst_rse, lifetime=604800, account='c3po', source_replica_expression=src_rse, activity='Data Brokering', asynchronous=True)
147
+ logging.debug(r)
148
+
149
+
150
+ def place_replica(
151
+ did_queue: Queue,
152
+ once: bool = False,
153
+ thread: int = 0,
154
+ waiting_time: int = 100,
155
+ dry_run: bool = False,
156
+ sampling: bool = False,
157
+ algorithms: str = 't2_free_space_only_pop_with_network',
158
+ datatypes: str = 'NTUP,DAOD',
159
+ dest_rse_expr: str = 'type=DATADISK',
160
+ max_bytes_hour: int = 100000000000000,
161
+ max_files_hour: int = 100000,
162
+ max_bytes_hour_rse: int = 50000000000000,
163
+ max_files_hour_rse: int = 10000,
164
+ min_popularity: int = 8,
165
+ min_recent_requests: int = 5,
166
+ max_replicas: int = 5,
167
+ sleep_time: int = 10
168
+ ) -> None:
169
+ """
170
+ Thread to run the placement algorithm to decide if and where to put new replicas.
171
+ """
172
+ try:
173
+ c3po_options = config_get_options('c3po')
174
+ client = None
175
+
176
+ if 'algorithms' in c3po_options:
177
+ algorithms = config_get('c3po', 'algorithms')
178
+
179
+ algorithms_list = algorithms.split(',')
180
+
181
+ if not dry_run:
182
+ if len(algorithms_list) != 1:
183
+ logging.error('Multiple algorithms are only allowed in dry_run mode')
184
+ return
185
+ client = Client(auth_type='x509_proxy', account='c3po', creds={'client_proxy': '/opt/rucio/etc/ddmadmin.long.proxy'})
186
+
187
+ vo = client.vo
188
+ instances = {}
189
+ for algorithm in algorithms_list:
190
+ module_path = 'rucio.daemons.c3po.algorithms.' + algorithm
191
+ module = __import__(module_path, globals(), locals(), ['PlacementAlgorithm'])
192
+ instance = module.PlacementAlgorithm(datatypes, dest_rse_expr, max_bytes_hour, max_files_hour, max_bytes_hour_rse, max_files_hour_rse, min_popularity, min_recent_requests, max_replicas)
193
+ instances[algorithm] = instance
194
+
195
+ params = {
196
+ 'dry_run': dry_run,
197
+ 'sampling': sampling,
198
+ 'datatypes': datatypes,
199
+ 'dest_rse_expr': dest_rse_expr,
200
+ 'max_bytes_hour': max_bytes_hour,
201
+ 'max_files_hour': max_files_hour,
202
+ 'max_bytes_hour_rse': max_bytes_hour_rse,
203
+ 'max_files_hour_rse': max_files_hour_rse,
204
+ 'min_recent_requests': min_recent_requests,
205
+ 'min_popularity': min_popularity
206
+ }
207
+
208
+ instance_id = str(uuid4()).split('-')[0]
209
+
210
+ elastic_url = config_get('c3po', 'elastic_url')
211
+ elastic_index = config_get('c3po', 'elastic_index')
212
+
213
+ ca_cert = False
214
+ if 'ca_cert' in c3po_options:
215
+ ca_cert = config_get('c3po', 'ca_cert')
216
+
217
+ auth = False
218
+ if ('elastic_user' in c3po_options) and ('elastic_pass' in c3po_options):
219
+ auth = HTTPBasicAuth(config_get('c3po', 'elastic_user'), config_get('c3po', 'elastic_pass'))
220
+
221
+ w = waiting_time
222
+ while not GRACEFUL_STOP.is_set():
223
+ if w < waiting_time:
224
+ w += sleep_time
225
+ sleep(sleep_time)
226
+ continue
227
+ len_dids = did_queue.qsize()
228
+
229
+ if len_dids > 0:
230
+ logging.debug('(%s) %d did(s) in queue' % (instance_id, len_dids))
231
+ else:
232
+ logging.debug('(%s) no dids in queue' % (instance_id))
233
+
234
+ for _ in range(0, len_dids):
235
+ did = did_queue.get()
236
+ if isinstance(did[0], str):
237
+ did[0] = InternalScope(did[0], vo=vo)
238
+ for algorithm, instance in instances.items():
239
+ logging.info('(%s:%s) Retrieved %s:%s from queue. Run placement algorithm' % (algorithm, instance_id, did[0], did[1]))
240
+ decision = instance.place(did)
241
+ decision['@timestamp'] = datetime.utcnow().isoformat()
242
+ decision['algorithm'] = algorithm
243
+ decision['instance_id'] = instance_id
244
+ decision['params'] = params
245
+
246
+ create_rule = True
247
+ if sampling and 'error_reason' not in decision:
248
+ create_rule = bool(ord(md5(decision['did']).hexdigest()[-1]) & 1)
249
+ decision['create_rule'] = create_rule
250
+ # write the output to ES for further analysis
251
+ index_url = elastic_url + '/' + elastic_index + '-' + datetime.utcnow().strftime('%Y-%m') + '/record/'
252
+ try:
253
+ if ca_cert:
254
+ r = post(index_url, data=dumps(decision), verify=ca_cert, auth=auth)
255
+ else:
256
+ r = post(index_url, data=dumps(decision))
257
+ if r.status_code != 201:
258
+ logging.error(r)
259
+ logging.error('(%s:%s) could not write to ElasticSearch' % (algorithm, instance_id))
260
+ except RequestException as e:
261
+ logging.error('(%s:%s) could not write to ElasticSearch' % (algorithm, instance_id))
262
+ logging.error(e)
263
+ continue
264
+
265
+ logging.debug(decision)
266
+ if 'error_reason' in decision:
267
+ logging.error('(%s:%s) The placement algorithm ran into an error: %s' % (algorithm, instance_id, decision['error_reason']))
268
+ continue
269
+
270
+ logging.info('(%s:%s) Decided to place a new replica for %s on %s' % (algorithm, instance_id, decision['did'], decision['destination_rse']))
271
+
272
+ if (not dry_run) and create_rule:
273
+ # DO IT!
274
+ try:
275
+ add_rule(client, {'scope': did[0].external, 'name': did[1]}, decision.get('source_rse'), decision.get('destination_rse')) # type: ignore
276
+ except exception.RucioException as e:
277
+ logging.debug(e)
278
+
279
+ w = 0
280
+ except Exception as e:
281
+ logging.critical(e)
282
+
283
+
284
+ def stop(signum: Optional[int] = None, frame: Optional['FrameType'] = None) -> None:
285
+ """
286
+ Graceful exit.
287
+ """
288
+ GRACEFUL_STOP.set()
289
+
290
+
291
+ def run(
292
+ once: bool = False,
293
+ threads: int = 1,
294
+ only_workload: bool = False,
295
+ dry_run: bool = False,
296
+ sampling: bool = False,
297
+ algorithms: str = 't2_free_space_only_pop_with_network',
298
+ datatypes: str = 'NTUP,DAOD',
299
+ dest_rse_expr: str = 'type=DATADISK',
300
+ max_bytes_hour: int = 100000000000000,
301
+ max_files_hour: int = 100000,
302
+ max_bytes_hour_rse: int = 50000000000000,
303
+ max_files_hour_rse: int = 10000,
304
+ min_popularity: int = 8,
305
+ min_recent_requests: int = 5,
306
+ max_replicas: int = 5,
307
+ waiting_time_read_free_space: int = 1800,
308
+ waiting_time_read_workload: int = 1800,
309
+ waiting_time_print_workload: int = 600,
310
+ waiting_time_read_dids: int = 60,
311
+ waiting_time_place_replica: int = 100,
312
+ sleep_time: int = 10
313
+ ) -> None:
314
+ """
315
+ Starts up the main thread
316
+ """
317
+ setup_logging(process_name=DAEMON_NAME)
318
+
319
+ if rucio.db.sqla.util.is_old_db():
320
+ raise exception.DatabaseException('Database was not updated, daemon won\'t start')
321
+
322
+ logging.info('activating C-3PO')
323
+
324
+ thread_list = []
325
+ try:
326
+ if only_workload:
327
+ logging.info('running in workload-collector-only mode')
328
+ thread_list.append(Thread(target=read_workload, name='read_workload', kwargs={'thread': 0,
329
+ 'waiting_time': waiting_time_read_workload,
330
+ 'sleep_time': sleep_time}))
331
+ thread_list.append(Thread(target=print_workload, name='print_workload', kwargs={'thread': 0,
332
+ 'waiting_time': waiting_time_print_workload,
333
+ 'sleep_time': sleep_time}))
334
+ else:
335
+ logging.info('running in placement mode')
336
+ did_queue = Queue()
337
+ dc = JediDIDCollector(did_queue)
338
+
339
+ thread_list.append(Thread(target=read_free_space, name='read_free_space', kwargs={'thread': 0,
340
+ 'waiting_time': waiting_time_read_free_space,
341
+ 'sleep_time': sleep_time}))
342
+ thread_list.append(Thread(target=read_dids, name='read_dids', kwargs={'thread': 0,
343
+ 'did_collector': dc,
344
+ 'waiting_time': waiting_time_read_dids,
345
+ 'sleep_time': sleep_time}))
346
+ thread_list.append(Thread(target=place_replica, name='place_replica', kwargs={'thread': 0,
347
+ 'did_queue': did_queue,
348
+ 'waiting_time': waiting_time_place_replica,
349
+ 'algorithms': algorithms,
350
+ 'dry_run': dry_run,
351
+ 'sampling': sampling,
352
+ 'datatypes': datatypes,
353
+ 'dest_rse_expr': dest_rse_expr,
354
+ 'max_bytes_hour': max_bytes_hour,
355
+ 'max_files_hour': max_files_hour,
356
+ 'max_bytes_hour_rse': max_bytes_hour_rse,
357
+ 'max_files_hour_rse': max_files_hour_rse,
358
+ 'min_popularity': min_popularity,
359
+ 'min_recent_requests': min_recent_requests,
360
+ 'max_replicas': max_replicas,
361
+ 'sleep_time': sleep_time}))
362
+
363
+ for t in thread_list:
364
+ t.start()
365
+
366
+ logging.info('waiting for interrupts')
367
+
368
+ while len(thread_list) > 0:
369
+ [t.join(timeout=3) for t in thread_list if t and t.is_alive()]
370
+ except Exception as error:
371
+ logging.critical(error)
@@ -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,108 @@
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
+ from json import loads
16
+ from typing import Optional
17
+
18
+ from requests import get
19
+
20
+ from rucio.common.config import config_get
21
+
22
+
23
+ class MappingCollector:
24
+ """
25
+ Provides mappings from PanDA / DDM resources to ATLAS sites and back.
26
+ """
27
+ class _MappingCollector:
28
+ '''
29
+ _MappingCollector
30
+ '''
31
+
32
+ def __init__(self):
33
+ '''
34
+ __init__
35
+ '''
36
+ self._fetch_panda_mapping()
37
+ self._fetch_ddm_mapping()
38
+
39
+ def _fetch_panda_mapping(self) -> None:
40
+ '''
41
+ _fetch_panda_mapping
42
+ '''
43
+ result = get(config_get('c3po-site-mapper', 'panda_url'))
44
+ data = loads(result.text)
45
+ self.panda_to_site = {}
46
+ self.site_to_panda = {}
47
+
48
+ for entry in data:
49
+ self.panda_to_site[entry['panda_resource']] = entry['atlas_site']
50
+ if entry['atlas_site'] not in self.site_to_panda:
51
+ self.site_to_panda[entry['atlas_site']] = []
52
+ self.site_to_panda[entry['atlas_site']].append(entry['panda_resource'])
53
+
54
+ def _fetch_ddm_mapping(self) -> None:
55
+ '''
56
+ _fetch_ddm_mapping
57
+ '''
58
+ result = get(config_get('c3po-site-mapper', 'ddm_url'))
59
+ data = loads(result.text)
60
+ self.site_to_ddm = {}
61
+ self.ddm_to_site = {}
62
+
63
+ for entry in data:
64
+ self.ddm_to_site[entry['name']] = entry['site']
65
+ if entry['site'] not in self.site_to_ddm:
66
+ self.site_to_ddm[entry['site']] = []
67
+ self.site_to_ddm[entry['site']].append(entry['name'])
68
+
69
+ instance = None
70
+
71
+ def __init__(self):
72
+ '''
73
+ __init__
74
+ '''
75
+ if not MappingCollector.instance:
76
+ MappingCollector.instance = MappingCollector._MappingCollector()
77
+
78
+ def ddm_to_site(self, ddm: str) -> Optional[str]:
79
+ '''
80
+ ddm_to_site
81
+ '''
82
+ if ddm not in self.instance.ddm_to_site: # type: ignore
83
+ return None
84
+ return self.instance.ddm_to_site[ddm] # type: ignore
85
+
86
+ def panda_to_site(self, panda: str) -> Optional[str]:
87
+ '''
88
+ panda_to_site
89
+ '''
90
+ if panda not in self.instance.panda_to_site: # type: ignore
91
+ return None
92
+ return self.instance.panda_to_site[panda] # type: ignore
93
+
94
+ def site_to_ddm(self, site: str) -> Optional[str]:
95
+ '''
96
+ site_to_ddm
97
+ '''
98
+ if site not in self.instance.site_to_ddm: # type: ignore
99
+ return None
100
+ return self.instance.site_to_ddm[site] # type: ignore
101
+
102
+ def site_to_panda(self, site: str) -> Optional[str]:
103
+ '''
104
+ site_to_panda
105
+ '''
106
+ if site not in self.instance.site_to_panda: # type: ignore
107
+ return None
108
+ return self.instance.site_to_panda[site] # type: ignore
@@ -0,0 +1,81 @@
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
+ Collector to get the SRM free and used information for DATADISK RSEs.
17
+ """
18
+
19
+ from typing import TYPE_CHECKING, Optional
20
+
21
+ from sqlalchemy import and_, select
22
+
23
+ from rucio.db.sqla.models import RSEAttrAssociation, RSEUsage
24
+ from rucio.db.sqla.session import read_session
25
+
26
+ if TYPE_CHECKING:
27
+ from sqlalchemy.orm import Session
28
+
29
+
30
+ class FreeSpaceCollector:
31
+ """
32
+ Collector to get the SRM free and used information for DATADISK RSEs.
33
+ """
34
+ class _FreeSpaceCollector:
35
+ """
36
+ Hidden implementation
37
+ """
38
+ def __init__(self):
39
+ self.rses = {}
40
+
41
+ @read_session
42
+ def _collect_free_space(
43
+ self,
44
+ *,
45
+ session: Optional["Session"] = None
46
+ ) -> None:
47
+ """
48
+ Retrieve free space from database
49
+ """
50
+ stmt = select(
51
+ RSEUsage.rse_id,
52
+ RSEUsage.free,
53
+ RSEUsage.used
54
+ ).join(
55
+ RSEAttrAssociation,
56
+ RSEAttrAssociation.rse_id == RSEUsage.rse_id
57
+ ).where(
58
+ and_(RSEUsage.source == 'storage',
59
+ RSEAttrAssociation.key == 'type',
60
+ RSEAttrAssociation.value == 'DATADISK'),
61
+ )
62
+ for rse_id, free, used in session.execute(stmt).all(): # type: ignore (session could be None)
63
+ self.rses[rse_id] = {'total': used + free, 'used': used, 'free': free}
64
+
65
+ instance = None
66
+
67
+ def __init__(self):
68
+ if not FreeSpaceCollector.instance:
69
+ FreeSpaceCollector.instance = FreeSpaceCollector._FreeSpaceCollector()
70
+
71
+ def collect_free_space(self) -> None:
72
+ """
73
+ Execute the free space collector
74
+ """
75
+ self.instance._collect_free_space() # type: ignore
76
+
77
+ def get_rse_space(self) -> dict[str, dict[str, int]]:
78
+ """
79
+ Return the RSE space
80
+ """
81
+ return self.instance.rses # type: ignore
@@ -0,0 +1,57 @@
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
+ import logging
16
+ from typing import TYPE_CHECKING, Optional
17
+
18
+ from rucio.db.sqla.session import read_session
19
+
20
+ if TYPE_CHECKING:
21
+ from queue import Queue
22
+
23
+ from sqlalchemy.orm import Session
24
+
25
+
26
+ class JediDIDCollector:
27
+ def __init__(self, queue: "Queue"):
28
+ self.queue = queue
29
+ self.max_tid = 0
30
+
31
+ @read_session
32
+ def get_dids(
33
+ self,
34
+ *,
35
+ session: Optional["Session"] = None
36
+ ) -> None:
37
+ query = """select t.jeditaskid, t.username, t.status, d.datasetname from ATLAS_PANDA.JEDI_TASKS t
38
+ inner join ATLAS_PANDA.JEDI_DATASETS d
39
+ on t.jeditaskid = d.jeditaskid
40
+ where t.creationdate > SYS_EXTRACT_UTC(systimestamp) - 5/(24*60) and t.tasktype = 'anal' and t.prodsourcelabel = 'user'
41
+ and d.type = 'input'
42
+ order by d.jeditaskid asc"""
43
+
44
+ tasks = session.execute(query) # type: ignore
45
+
46
+ for t in tasks.fetchall():
47
+ status = t[2]
48
+ if status == 'running':
49
+ continue
50
+ tid = t[0]
51
+ if tid < self.max_tid:
52
+ continue
53
+
54
+ logging.debug("Received task: " + str(t))
55
+ did = t[3].split(':')
56
+ self.queue.put((did[0], did[1]))
57
+ self.max_tid = tid
@@ -0,0 +1,51 @@
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
+ Mock DID collector
17
+ """
18
+
19
+ from secrets import choice
20
+ from typing import TYPE_CHECKING
21
+
22
+ if TYPE_CHECKING:
23
+ from multiprocessing import Queue
24
+
25
+ from _typeshed import FileDescriptorOrPath
26
+
27
+
28
+ class MockDIDCollector:
29
+ """
30
+ Simple collector that reads dids from a file. Used to
31
+ test the interface.
32
+ """
33
+ def __init__(self, queue: "Queue"):
34
+ self._queue = queue
35
+ self._read_file('/opt/rucio/etc/dids_mc15_13TeV.csv')
36
+
37
+ def _read_file(self, infile: "FileDescriptorOrPath") -> None:
38
+ dids = []
39
+ with open(infile, 'r') as f:
40
+ f.readline()
41
+ for line in f:
42
+ items = line.strip().split('\t')
43
+ scope = items[0]
44
+ name = items[1]
45
+ dids.append((scope, name))
46
+
47
+ self._dids = tuple(dids)
48
+
49
+ def get_dids(self) -> None:
50
+ did = choice(self._dids)
51
+ self._queue.put(did)