rucio 32.8.6__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 (481) hide show
  1. rucio/__init__.py +18 -0
  2. rucio/alembicrevision.py +16 -0
  3. rucio/api/__init__.py +14 -0
  4. rucio/api/account.py +266 -0
  5. rucio/api/account_limit.py +287 -0
  6. rucio/api/authentication.py +302 -0
  7. rucio/api/config.py +218 -0
  8. rucio/api/credential.py +60 -0
  9. rucio/api/did.py +726 -0
  10. rucio/api/dirac.py +71 -0
  11. rucio/api/exporter.py +60 -0
  12. rucio/api/heartbeat.py +62 -0
  13. rucio/api/identity.py +160 -0
  14. rucio/api/importer.py +46 -0
  15. rucio/api/lifetime_exception.py +95 -0
  16. rucio/api/lock.py +131 -0
  17. rucio/api/meta.py +85 -0
  18. rucio/api/permission.py +72 -0
  19. rucio/api/quarantined_replica.py +69 -0
  20. rucio/api/replica.py +528 -0
  21. rucio/api/request.py +220 -0
  22. rucio/api/rse.py +601 -0
  23. rucio/api/rule.py +335 -0
  24. rucio/api/scope.py +89 -0
  25. rucio/api/subscription.py +255 -0
  26. rucio/api/temporary_did.py +49 -0
  27. rucio/api/vo.py +112 -0
  28. rucio/client/__init__.py +16 -0
  29. rucio/client/accountclient.py +413 -0
  30. rucio/client/accountlimitclient.py +155 -0
  31. rucio/client/baseclient.py +929 -0
  32. rucio/client/client.py +77 -0
  33. rucio/client/configclient.py +113 -0
  34. rucio/client/credentialclient.py +54 -0
  35. rucio/client/didclient.py +691 -0
  36. rucio/client/diracclient.py +48 -0
  37. rucio/client/downloadclient.py +1674 -0
  38. rucio/client/exportclient.py +44 -0
  39. rucio/client/fileclient.py +51 -0
  40. rucio/client/importclient.py +42 -0
  41. rucio/client/lifetimeclient.py +74 -0
  42. rucio/client/lockclient.py +99 -0
  43. rucio/client/metaclient.py +137 -0
  44. rucio/client/pingclient.py +45 -0
  45. rucio/client/replicaclient.py +444 -0
  46. rucio/client/requestclient.py +109 -0
  47. rucio/client/rseclient.py +664 -0
  48. rucio/client/ruleclient.py +287 -0
  49. rucio/client/scopeclient.py +88 -0
  50. rucio/client/subscriptionclient.py +161 -0
  51. rucio/client/touchclient.py +78 -0
  52. rucio/client/uploadclient.py +871 -0
  53. rucio/common/__init__.py +14 -0
  54. rucio/common/cache.py +74 -0
  55. rucio/common/config.py +796 -0
  56. rucio/common/constants.py +92 -0
  57. rucio/common/constraints.py +18 -0
  58. rucio/common/didtype.py +187 -0
  59. rucio/common/dumper/__init__.py +306 -0
  60. rucio/common/dumper/consistency.py +449 -0
  61. rucio/common/dumper/data_models.py +325 -0
  62. rucio/common/dumper/path_parsing.py +65 -0
  63. rucio/common/exception.py +1092 -0
  64. rucio/common/extra.py +37 -0
  65. rucio/common/logging.py +404 -0
  66. rucio/common/pcache.py +1387 -0
  67. rucio/common/policy.py +84 -0
  68. rucio/common/schema/__init__.py +143 -0
  69. rucio/common/schema/atlas.py +411 -0
  70. rucio/common/schema/belleii.py +406 -0
  71. rucio/common/schema/cms.py +478 -0
  72. rucio/common/schema/domatpc.py +399 -0
  73. rucio/common/schema/escape.py +424 -0
  74. rucio/common/schema/generic.py +431 -0
  75. rucio/common/schema/generic_multi_vo.py +410 -0
  76. rucio/common/schema/icecube.py +404 -0
  77. rucio/common/schema/lsst.py +423 -0
  78. rucio/common/stomp_utils.py +160 -0
  79. rucio/common/stopwatch.py +56 -0
  80. rucio/common/test_rucio_server.py +148 -0
  81. rucio/common/types.py +158 -0
  82. rucio/common/utils.py +1946 -0
  83. rucio/core/__init__.py +14 -0
  84. rucio/core/account.py +426 -0
  85. rucio/core/account_counter.py +171 -0
  86. rucio/core/account_limit.py +357 -0
  87. rucio/core/authentication.py +563 -0
  88. rucio/core/config.py +386 -0
  89. rucio/core/credential.py +218 -0
  90. rucio/core/did.py +3102 -0
  91. rucio/core/did_meta_plugins/__init__.py +250 -0
  92. rucio/core/did_meta_plugins/did_column_meta.py +326 -0
  93. rucio/core/did_meta_plugins/did_meta_plugin_interface.py +116 -0
  94. rucio/core/did_meta_plugins/filter_engine.py +573 -0
  95. rucio/core/did_meta_plugins/json_meta.py +215 -0
  96. rucio/core/did_meta_plugins/mongo_meta.py +199 -0
  97. rucio/core/did_meta_plugins/postgres_meta.py +317 -0
  98. rucio/core/dirac.py +208 -0
  99. rucio/core/distance.py +164 -0
  100. rucio/core/exporter.py +59 -0
  101. rucio/core/heartbeat.py +263 -0
  102. rucio/core/identity.py +290 -0
  103. rucio/core/importer.py +248 -0
  104. rucio/core/lifetime_exception.py +377 -0
  105. rucio/core/lock.py +474 -0
  106. rucio/core/message.py +241 -0
  107. rucio/core/meta.py +190 -0
  108. rucio/core/monitor.py +441 -0
  109. rucio/core/naming_convention.py +154 -0
  110. rucio/core/nongrid_trace.py +124 -0
  111. rucio/core/oidc.py +1339 -0
  112. rucio/core/permission/__init__.py +107 -0
  113. rucio/core/permission/atlas.py +1333 -0
  114. rucio/core/permission/belleii.py +1076 -0
  115. rucio/core/permission/cms.py +1166 -0
  116. rucio/core/permission/escape.py +1076 -0
  117. rucio/core/permission/generic.py +1128 -0
  118. rucio/core/permission/generic_multi_vo.py +1148 -0
  119. rucio/core/quarantined_replica.py +190 -0
  120. rucio/core/replica.py +3627 -0
  121. rucio/core/replica_sorter.py +368 -0
  122. rucio/core/request.py +2241 -0
  123. rucio/core/rse.py +1835 -0
  124. rucio/core/rse_counter.py +155 -0
  125. rucio/core/rse_expression_parser.py +460 -0
  126. rucio/core/rse_selector.py +277 -0
  127. rucio/core/rule.py +3419 -0
  128. rucio/core/rule_grouping.py +1473 -0
  129. rucio/core/scope.py +152 -0
  130. rucio/core/subscription.py +316 -0
  131. rucio/core/temporary_did.py +188 -0
  132. rucio/core/topology.py +448 -0
  133. rucio/core/trace.py +361 -0
  134. rucio/core/transfer.py +1233 -0
  135. rucio/core/vo.py +151 -0
  136. rucio/core/volatile_replica.py +123 -0
  137. rucio/daemons/__init__.py +14 -0
  138. rucio/daemons/abacus/__init__.py +14 -0
  139. rucio/daemons/abacus/account.py +106 -0
  140. rucio/daemons/abacus/collection_replica.py +113 -0
  141. rucio/daemons/abacus/rse.py +107 -0
  142. rucio/daemons/atropos/__init__.py +14 -0
  143. rucio/daemons/atropos/atropos.py +243 -0
  144. rucio/daemons/auditor/__init__.py +261 -0
  145. rucio/daemons/auditor/hdfs.py +86 -0
  146. rucio/daemons/auditor/srmdumps.py +284 -0
  147. rucio/daemons/automatix/__init__.py +14 -0
  148. rucio/daemons/automatix/automatix.py +281 -0
  149. rucio/daemons/badreplicas/__init__.py +14 -0
  150. rucio/daemons/badreplicas/minos.py +311 -0
  151. rucio/daemons/badreplicas/minos_temporary_expiration.py +173 -0
  152. rucio/daemons/badreplicas/necromancer.py +200 -0
  153. rucio/daemons/bb8/__init__.py +14 -0
  154. rucio/daemons/bb8/bb8.py +356 -0
  155. rucio/daemons/bb8/common.py +762 -0
  156. rucio/daemons/bb8/nuclei_background_rebalance.py +147 -0
  157. rucio/daemons/bb8/t2_background_rebalance.py +146 -0
  158. rucio/daemons/c3po/__init__.py +14 -0
  159. rucio/daemons/c3po/algorithms/__init__.py +14 -0
  160. rucio/daemons/c3po/algorithms/simple.py +131 -0
  161. rucio/daemons/c3po/algorithms/t2_free_space.py +125 -0
  162. rucio/daemons/c3po/algorithms/t2_free_space_only_pop.py +127 -0
  163. rucio/daemons/c3po/algorithms/t2_free_space_only_pop_with_network.py +279 -0
  164. rucio/daemons/c3po/c3po.py +342 -0
  165. rucio/daemons/c3po/collectors/__init__.py +14 -0
  166. rucio/daemons/c3po/collectors/agis.py +108 -0
  167. rucio/daemons/c3po/collectors/free_space.py +62 -0
  168. rucio/daemons/c3po/collectors/jedi_did.py +48 -0
  169. rucio/daemons/c3po/collectors/mock_did.py +46 -0
  170. rucio/daemons/c3po/collectors/network_metrics.py +63 -0
  171. rucio/daemons/c3po/collectors/workload.py +110 -0
  172. rucio/daemons/c3po/utils/__init__.py +14 -0
  173. rucio/daemons/c3po/utils/dataset_cache.py +40 -0
  174. rucio/daemons/c3po/utils/expiring_dataset_cache.py +45 -0
  175. rucio/daemons/c3po/utils/expiring_list.py +63 -0
  176. rucio/daemons/c3po/utils/popularity.py +82 -0
  177. rucio/daemons/c3po/utils/timeseries.py +76 -0
  178. rucio/daemons/cache/__init__.py +14 -0
  179. rucio/daemons/cache/consumer.py +191 -0
  180. rucio/daemons/common.py +391 -0
  181. rucio/daemons/conveyor/__init__.py +14 -0
  182. rucio/daemons/conveyor/common.py +530 -0
  183. rucio/daemons/conveyor/finisher.py +492 -0
  184. rucio/daemons/conveyor/poller.py +372 -0
  185. rucio/daemons/conveyor/preparer.py +198 -0
  186. rucio/daemons/conveyor/receiver.py +206 -0
  187. rucio/daemons/conveyor/stager.py +127 -0
  188. rucio/daemons/conveyor/submitter.py +379 -0
  189. rucio/daemons/conveyor/throttler.py +468 -0
  190. rucio/daemons/follower/__init__.py +14 -0
  191. rucio/daemons/follower/follower.py +97 -0
  192. rucio/daemons/hermes/__init__.py +14 -0
  193. rucio/daemons/hermes/hermes.py +738 -0
  194. rucio/daemons/judge/__init__.py +14 -0
  195. rucio/daemons/judge/cleaner.py +149 -0
  196. rucio/daemons/judge/evaluator.py +172 -0
  197. rucio/daemons/judge/injector.py +154 -0
  198. rucio/daemons/judge/repairer.py +144 -0
  199. rucio/daemons/oauthmanager/__init__.py +14 -0
  200. rucio/daemons/oauthmanager/oauthmanager.py +199 -0
  201. rucio/daemons/reaper/__init__.py +14 -0
  202. rucio/daemons/reaper/dark_reaper.py +272 -0
  203. rucio/daemons/reaper/light_reaper.py +255 -0
  204. rucio/daemons/reaper/reaper.py +701 -0
  205. rucio/daemons/replicarecoverer/__init__.py +14 -0
  206. rucio/daemons/replicarecoverer/suspicious_replica_recoverer.py +487 -0
  207. rucio/daemons/storage/__init__.py +14 -0
  208. rucio/daemons/storage/consistency/__init__.py +14 -0
  209. rucio/daemons/storage/consistency/actions.py +753 -0
  210. rucio/daemons/tracer/__init__.py +14 -0
  211. rucio/daemons/tracer/kronos.py +513 -0
  212. rucio/daemons/transmogrifier/__init__.py +14 -0
  213. rucio/daemons/transmogrifier/transmogrifier.py +753 -0
  214. rucio/daemons/undertaker/__init__.py +14 -0
  215. rucio/daemons/undertaker/undertaker.py +137 -0
  216. rucio/db/__init__.py +14 -0
  217. rucio/db/sqla/__init__.py +38 -0
  218. rucio/db/sqla/constants.py +192 -0
  219. rucio/db/sqla/migrate_repo/__init__.py +14 -0
  220. rucio/db/sqla/migrate_repo/env.py +111 -0
  221. rucio/db/sqla/migrate_repo/versions/01eaf73ab656_add_new_rule_notification_state_progress.py +71 -0
  222. rucio/db/sqla/migrate_repo/versions/0437a40dbfd1_add_eol_at_in_rules.py +50 -0
  223. rucio/db/sqla/migrate_repo/versions/0f1adb7a599a_create_transfer_hops_table.py +61 -0
  224. rucio/db/sqla/migrate_repo/versions/102efcf145f4_added_stuck_at_column_to_rules.py +46 -0
  225. rucio/db/sqla/migrate_repo/versions/13d4f70c66a9_introduce_transfer_limits.py +93 -0
  226. rucio/db/sqla/migrate_repo/versions/140fef722e91_cleanup_distances_table.py +78 -0
  227. rucio/db/sqla/migrate_repo/versions/14ec5aeb64cf_add_request_external_host.py +46 -0
  228. rucio/db/sqla/migrate_repo/versions/156fb5b5a14_add_request_type_to_requests_idx.py +53 -0
  229. rucio/db/sqla/migrate_repo/versions/1677d4d803c8_split_rse_availability_into_multiple.py +69 -0
  230. rucio/db/sqla/migrate_repo/versions/16a0aca82e12_create_index_on_table_replicas_path.py +42 -0
  231. rucio/db/sqla/migrate_repo/versions/1803333ac20f_adding_provenance_and_phys_group.py +46 -0
  232. rucio/db/sqla/migrate_repo/versions/1a29d6a9504c_add_didtype_chck_to_requests.py +61 -0
  233. rucio/db/sqla/migrate_repo/versions/1a80adff031a_create_index_on_rules_hist_recent.py +42 -0
  234. rucio/db/sqla/migrate_repo/versions/1c45d9730ca6_increase_identity_length.py +141 -0
  235. rucio/db/sqla/migrate_repo/versions/1d1215494e95_add_quarantined_replicas_table.py +75 -0
  236. rucio/db/sqla/migrate_repo/versions/1d96f484df21_asynchronous_rules_and_rule_approval.py +75 -0
  237. rucio/db/sqla/migrate_repo/versions/1f46c5f240ac_add_bytes_column_to_bad_replicas.py +46 -0
  238. rucio/db/sqla/migrate_repo/versions/1fc15ab60d43_add_message_history_table.py +51 -0
  239. rucio/db/sqla/migrate_repo/versions/2190e703eb6e_move_rse_settings_to_rse_attributes.py +135 -0
  240. rucio/db/sqla/migrate_repo/versions/21d6b9dc9961_add_mismatch_scheme_state_to_requests.py +65 -0
  241. rucio/db/sqla/migrate_repo/versions/22cf51430c78_add_availability_column_to_table_rses.py +42 -0
  242. rucio/db/sqla/migrate_repo/versions/22d887e4ec0a_create_sources_table.py +66 -0
  243. rucio/db/sqla/migrate_repo/versions/25821a8a45a3_remove_unique_constraint_on_requests.py +54 -0
  244. rucio/db/sqla/migrate_repo/versions/25fc855625cf_added_unique_constraint_to_rules.py +43 -0
  245. rucio/db/sqla/migrate_repo/versions/269fee20dee9_add_repair_cnt_to_locks.py +46 -0
  246. rucio/db/sqla/migrate_repo/versions/271a46ea6244_add_ignore_availability_column_to_rules.py +47 -0
  247. rucio/db/sqla/migrate_repo/versions/277b5fbb41d3_switch_heartbeats_executable.py +54 -0
  248. rucio/db/sqla/migrate_repo/versions/27e3a68927fb_remove_replicas_tombstone_and_replicas_.py +39 -0
  249. rucio/db/sqla/migrate_repo/versions/2854cd9e168_added_rule_id_column.py +48 -0
  250. rucio/db/sqla/migrate_repo/versions/295289b5a800_processed_by_and__at_in_requests.py +47 -0
  251. rucio/db/sqla/migrate_repo/versions/2962ece31cf4_add_nbaccesses_column_in_the_did_table.py +48 -0
  252. rucio/db/sqla/migrate_repo/versions/2af3291ec4c_added_replicas_history_table.py +59 -0
  253. rucio/db/sqla/migrate_repo/versions/2b69addda658_add_columns_for_third_party_copy_read_.py +47 -0
  254. rucio/db/sqla/migrate_repo/versions/2b8e7bcb4783_add_config_table.py +72 -0
  255. rucio/db/sqla/migrate_repo/versions/2ba5229cb54c_add_submitted_at_to_requests_table.py +46 -0
  256. rucio/db/sqla/migrate_repo/versions/2cbee484dcf9_added_column_volume_to_rse_transfer_.py +45 -0
  257. rucio/db/sqla/migrate_repo/versions/2edee4a83846_add_source_to_requests_and_requests_.py +48 -0
  258. rucio/db/sqla/migrate_repo/versions/2eef46be23d4_change_tokens_pk.py +48 -0
  259. rucio/db/sqla/migrate_repo/versions/2f648fc909f3_index_in_rule_history_on_scope_name.py +42 -0
  260. rucio/db/sqla/migrate_repo/versions/3082b8cef557_add_naming_convention_table_and_closed_.py +69 -0
  261. rucio/db/sqla/migrate_repo/versions/30fa38b6434e_add_index_on_service_column_in_the_message_table.py +46 -0
  262. rucio/db/sqla/migrate_repo/versions/3152492b110b_added_staging_area_column.py +78 -0
  263. rucio/db/sqla/migrate_repo/versions/32c7d2783f7e_create_bad_replicas_table.py +62 -0
  264. rucio/db/sqla/migrate_repo/versions/3345511706b8_replicas_table_pk_definition_is_in_.py +74 -0
  265. rucio/db/sqla/migrate_repo/versions/35ef10d1e11b_change_index_on_table_requests.py +44 -0
  266. rucio/db/sqla/migrate_repo/versions/379a19b5332d_create_rse_limits_table.py +67 -0
  267. rucio/db/sqla/migrate_repo/versions/384b96aa0f60_created_rule_history_tables.py +134 -0
  268. rucio/db/sqla/migrate_repo/versions/3ac1660a1a72_extend_distance_table.py +58 -0
  269. rucio/db/sqla/migrate_repo/versions/3ad36e2268b0_create_collection_replicas_updates_table.py +79 -0
  270. rucio/db/sqla/migrate_repo/versions/3c9df354071b_extend_waiting_request_state.py +61 -0
  271. rucio/db/sqla/migrate_repo/versions/3d9813fab443_add_a_new_state_lost_in_badfilesstatus.py +45 -0
  272. rucio/db/sqla/migrate_repo/versions/40ad39ce3160_add_transferred_at_to_requests_table.py +46 -0
  273. rucio/db/sqla/migrate_repo/versions/4207be2fd914_add_notification_column_to_rules.py +65 -0
  274. rucio/db/sqla/migrate_repo/versions/42db2617c364_create_index_on_requests_external_id.py +42 -0
  275. rucio/db/sqla/migrate_repo/versions/436827b13f82_added_column_activity_to_table_requests.py +46 -0
  276. rucio/db/sqla/migrate_repo/versions/44278720f774_update_requests_typ_sta_upd_idx_index.py +46 -0
  277. rucio/db/sqla/migrate_repo/versions/45378a1e76a8_create_collection_replica_table.py +80 -0
  278. rucio/db/sqla/migrate_repo/versions/469d262be19_removing_created_at_index.py +43 -0
  279. rucio/db/sqla/migrate_repo/versions/4783c1f49cb4_create_distance_table.py +61 -0
  280. rucio/db/sqla/migrate_repo/versions/49a21b4d4357_create_index_on_table_tokens.py +47 -0
  281. rucio/db/sqla/migrate_repo/versions/4a2cbedda8b9_add_source_replica_expression_column_to_.py +46 -0
  282. rucio/db/sqla/migrate_repo/versions/4a7182d9578b_added_bytes_length_accessed_at_columns.py +52 -0
  283. rucio/db/sqla/migrate_repo/versions/4bab9edd01fc_create_index_on_requests_rule_id.py +42 -0
  284. rucio/db/sqla/migrate_repo/versions/4c3a4acfe006_new_attr_account_table.py +65 -0
  285. rucio/db/sqla/migrate_repo/versions/4cf0a2e127d4_adding_transient_metadata.py +46 -0
  286. rucio/db/sqla/migrate_repo/versions/50280c53117c_add_qos_class_to_rse.py +47 -0
  287. rucio/db/sqla/migrate_repo/versions/52153819589c_add_rse_id_to_replicas_table.py +45 -0
  288. rucio/db/sqla/migrate_repo/versions/52fd9f4916fa_added_activity_to_rules.py +46 -0
  289. rucio/db/sqla/migrate_repo/versions/53b479c3cb0f_fix_did_meta_table_missing_updated_at_.py +48 -0
  290. rucio/db/sqla/migrate_repo/versions/5673b4b6e843_add_wfms_metadata_to_rule_tables.py +50 -0
  291. rucio/db/sqla/migrate_repo/versions/575767d9f89_added_source_history_table.py +59 -0
  292. rucio/db/sqla/migrate_repo/versions/58bff7008037_add_started_at_to_requests.py +48 -0
  293. rucio/db/sqla/migrate_repo/versions/58c8b78301ab_rename_callback_to_message.py +108 -0
  294. rucio/db/sqla/migrate_repo/versions/5f139f77382a_added_child_rule_id_column.py +57 -0
  295. rucio/db/sqla/migrate_repo/versions/688ef1840840_adding_did_meta_table.py +51 -0
  296. rucio/db/sqla/migrate_repo/versions/6e572a9bfbf3_add_new_split_container_column_to_rules.py +50 -0
  297. rucio/db/sqla/migrate_repo/versions/70587619328_add_comment_column_for_subscriptions.py +46 -0
  298. rucio/db/sqla/migrate_repo/versions/739064d31565_remove_history_table_pks.py +42 -0
  299. rucio/db/sqla/migrate_repo/versions/7541902bf173_add_didsfollowed_and_followevents_table.py +93 -0
  300. rucio/db/sqla/migrate_repo/versions/7ec22226cdbf_new_replica_state_for_temporary_.py +73 -0
  301. rucio/db/sqla/migrate_repo/versions/810a41685bc1_added_columns_rse_transfer_limits.py +52 -0
  302. rucio/db/sqla/migrate_repo/versions/83f991c63a93_correct_rse_expression_length.py +45 -0
  303. rucio/db/sqla/migrate_repo/versions/8523998e2e76_increase_size_of_extended_attributes_.py +46 -0
  304. rucio/db/sqla/migrate_repo/versions/8ea9122275b1_adding_missing_function_based_indices.py +54 -0
  305. rucio/db/sqla/migrate_repo/versions/90f47792bb76_add_clob_payload_to_messages.py +48 -0
  306. rucio/db/sqla/migrate_repo/versions/914b8f02df38_new_table_for_lifetime_model_exceptions.py +70 -0
  307. rucio/db/sqla/migrate_repo/versions/94a5961ddbf2_add_estimator_columns.py +48 -0
  308. rucio/db/sqla/migrate_repo/versions/9a1b149a2044_add_saml_identity_type.py +95 -0
  309. rucio/db/sqla/migrate_repo/versions/9a45bc4ea66d_add_vp_table.py +55 -0
  310. rucio/db/sqla/migrate_repo/versions/9eb936a81eb1_true_is_true.py +74 -0
  311. rucio/db/sqla/migrate_repo/versions/a118956323f8_added_vo_table_and_vo_col_to_rse.py +78 -0
  312. rucio/db/sqla/migrate_repo/versions/a193a275255c_add_status_column_in_messages.py +49 -0
  313. rucio/db/sqla/migrate_repo/versions/a5f6f6e928a7_1_7_0.py +124 -0
  314. rucio/db/sqla/migrate_repo/versions/a616581ee47_added_columns_to_table_requests.py +60 -0
  315. rucio/db/sqla/migrate_repo/versions/a6eb23955c28_state_idx_non_functional.py +53 -0
  316. rucio/db/sqla/migrate_repo/versions/a74275a1ad30_added_global_quota_table.py +56 -0
  317. rucio/db/sqla/migrate_repo/versions/a93e4e47bda_heartbeats.py +67 -0
  318. rucio/db/sqla/migrate_repo/versions/ae2a56fcc89_added_comment_column_to_rules.py +50 -0
  319. rucio/db/sqla/migrate_repo/versions/b4293a99f344_added_column_identity_to_table_tokens.py +46 -0
  320. rucio/db/sqla/migrate_repo/versions/b7d287de34fd_removal_of_replicastate_source.py +92 -0
  321. rucio/db/sqla/migrate_repo/versions/b818052fa670_add_index_to_quarantined_replicas.py +42 -0
  322. rucio/db/sqla/migrate_repo/versions/b8caac94d7f0_add_comments_column_for_subscriptions_.py +46 -0
  323. rucio/db/sqla/migrate_repo/versions/b96a1c7e1cc4_new_bad_pfns_table_and_bad_replicas_.py +147 -0
  324. rucio/db/sqla/migrate_repo/versions/bb695f45c04_extend_request_state.py +78 -0
  325. rucio/db/sqla/migrate_repo/versions/bc68e9946deb_add_staging_timestamps_to_request.py +53 -0
  326. rucio/db/sqla/migrate_repo/versions/bf3baa1c1474_correct_pk_and_idx_for_history_tables.py +74 -0
  327. rucio/db/sqla/migrate_repo/versions/c0937668555f_add_qos_policy_map_table.py +56 -0
  328. rucio/db/sqla/migrate_repo/versions/c129ccdb2d5_add_lumiblocknr_to_dids.py +46 -0
  329. rucio/db/sqla/migrate_repo/versions/ccdbcd48206e_add_did_type_column_index_on_did_meta_.py +68 -0
  330. rucio/db/sqla/migrate_repo/versions/cebad904c4dd_new_payload_column_for_heartbeats.py +48 -0
  331. rucio/db/sqla/migrate_repo/versions/d1189a09c6e0_oauth2_0_and_jwt_feature_support_adding_.py +149 -0
  332. rucio/db/sqla/migrate_repo/versions/d23453595260_extend_request_state_for_preparer.py +106 -0
  333. rucio/db/sqla/migrate_repo/versions/d6dceb1de2d_added_purge_column_to_rules.py +47 -0
  334. rucio/db/sqla/migrate_repo/versions/d6e2c3b2cf26_remove_third_party_copy_column_from_rse.py +45 -0
  335. rucio/db/sqla/migrate_repo/versions/d91002c5841_new_account_limits_table.py +105 -0
  336. rucio/db/sqla/migrate_repo/versions/e138c364ebd0_extending_columns_for_filter_and_.py +52 -0
  337. rucio/db/sqla/migrate_repo/versions/e59300c8b179_support_for_archive.py +106 -0
  338. rucio/db/sqla/migrate_repo/versions/f1b14a8c2ac1_postgres_use_check_constraints.py +30 -0
  339. rucio/db/sqla/migrate_repo/versions/f41ffe206f37_oracle_global_temporary_tables.py +75 -0
  340. rucio/db/sqla/migrate_repo/versions/f85a2962b021_adding_transfertool_column_to_requests_.py +49 -0
  341. rucio/db/sqla/migrate_repo/versions/fa7a7d78b602_increase_refresh_token_size.py +45 -0
  342. rucio/db/sqla/migrate_repo/versions/fb28a95fe288_add_replicas_rse_id_tombstone_idx.py +38 -0
  343. rucio/db/sqla/migrate_repo/versions/fe1a65b176c9_set_third_party_copy_read_and_write_.py +44 -0
  344. rucio/db/sqla/migrate_repo/versions/fe8ea2fa9788_added_third_party_copy_column_to_rse_.py +46 -0
  345. rucio/db/sqla/models.py +1834 -0
  346. rucio/db/sqla/sautils.py +48 -0
  347. rucio/db/sqla/session.py +470 -0
  348. rucio/db/sqla/types.py +207 -0
  349. rucio/db/sqla/util.py +521 -0
  350. rucio/rse/__init__.py +97 -0
  351. rucio/rse/protocols/__init__.py +14 -0
  352. rucio/rse/protocols/cache.py +123 -0
  353. rucio/rse/protocols/dummy.py +112 -0
  354. rucio/rse/protocols/gfal.py +701 -0
  355. rucio/rse/protocols/globus.py +243 -0
  356. rucio/rse/protocols/gsiftp.py +93 -0
  357. rucio/rse/protocols/http_cache.py +83 -0
  358. rucio/rse/protocols/mock.py +124 -0
  359. rucio/rse/protocols/ngarc.py +210 -0
  360. rucio/rse/protocols/posix.py +251 -0
  361. rucio/rse/protocols/protocol.py +530 -0
  362. rucio/rse/protocols/rclone.py +365 -0
  363. rucio/rse/protocols/rfio.py +137 -0
  364. rucio/rse/protocols/srm.py +339 -0
  365. rucio/rse/protocols/ssh.py +414 -0
  366. rucio/rse/protocols/storm.py +207 -0
  367. rucio/rse/protocols/webdav.py +547 -0
  368. rucio/rse/protocols/xrootd.py +295 -0
  369. rucio/rse/rsemanager.py +752 -0
  370. rucio/tests/__init__.py +14 -0
  371. rucio/tests/common.py +244 -0
  372. rucio/tests/common_server.py +132 -0
  373. rucio/transfertool/__init__.py +14 -0
  374. rucio/transfertool/fts3.py +1484 -0
  375. rucio/transfertool/globus.py +200 -0
  376. rucio/transfertool/globus_library.py +182 -0
  377. rucio/transfertool/mock.py +81 -0
  378. rucio/transfertool/transfertool.py +212 -0
  379. rucio/vcsversion.py +11 -0
  380. rucio/version.py +46 -0
  381. rucio/web/__init__.py +14 -0
  382. rucio/web/rest/__init__.py +14 -0
  383. rucio/web/rest/flaskapi/__init__.py +14 -0
  384. rucio/web/rest/flaskapi/authenticated_bp.py +28 -0
  385. rucio/web/rest/flaskapi/v1/__init__.py +14 -0
  386. rucio/web/rest/flaskapi/v1/accountlimits.py +234 -0
  387. rucio/web/rest/flaskapi/v1/accounts.py +1088 -0
  388. rucio/web/rest/flaskapi/v1/archives.py +100 -0
  389. rucio/web/rest/flaskapi/v1/auth.py +1642 -0
  390. rucio/web/rest/flaskapi/v1/common.py +385 -0
  391. rucio/web/rest/flaskapi/v1/config.py +305 -0
  392. rucio/web/rest/flaskapi/v1/credentials.py +213 -0
  393. rucio/web/rest/flaskapi/v1/dids.py +2204 -0
  394. rucio/web/rest/flaskapi/v1/dirac.py +116 -0
  395. rucio/web/rest/flaskapi/v1/export.py +77 -0
  396. rucio/web/rest/flaskapi/v1/heartbeats.py +129 -0
  397. rucio/web/rest/flaskapi/v1/identities.py +263 -0
  398. rucio/web/rest/flaskapi/v1/import.py +133 -0
  399. rucio/web/rest/flaskapi/v1/lifetime_exceptions.py +315 -0
  400. rucio/web/rest/flaskapi/v1/locks.py +360 -0
  401. rucio/web/rest/flaskapi/v1/main.py +83 -0
  402. rucio/web/rest/flaskapi/v1/meta.py +226 -0
  403. rucio/web/rest/flaskapi/v1/metrics.py +37 -0
  404. rucio/web/rest/flaskapi/v1/nongrid_traces.py +97 -0
  405. rucio/web/rest/flaskapi/v1/ping.py +89 -0
  406. rucio/web/rest/flaskapi/v1/redirect.py +366 -0
  407. rucio/web/rest/flaskapi/v1/replicas.py +1866 -0
  408. rucio/web/rest/flaskapi/v1/requests.py +841 -0
  409. rucio/web/rest/flaskapi/v1/rses.py +2204 -0
  410. rucio/web/rest/flaskapi/v1/rules.py +824 -0
  411. rucio/web/rest/flaskapi/v1/scopes.py +161 -0
  412. rucio/web/rest/flaskapi/v1/subscriptions.py +646 -0
  413. rucio/web/rest/flaskapi/v1/templates/auth_crash.html +80 -0
  414. rucio/web/rest/flaskapi/v1/templates/auth_granted.html +82 -0
  415. rucio/web/rest/flaskapi/v1/tmp_dids.py +115 -0
  416. rucio/web/rest/flaskapi/v1/traces.py +100 -0
  417. rucio/web/rest/flaskapi/v1/vos.py +280 -0
  418. rucio/web/rest/main.py +19 -0
  419. rucio/web/rest/metrics.py +28 -0
  420. rucio-32.8.6.data/data/rucio/etc/alembic.ini.template +71 -0
  421. rucio-32.8.6.data/data/rucio/etc/alembic_offline.ini.template +74 -0
  422. rucio-32.8.6.data/data/rucio/etc/globus-config.yml.template +5 -0
  423. rucio-32.8.6.data/data/rucio/etc/ldap.cfg.template +30 -0
  424. rucio-32.8.6.data/data/rucio/etc/mail_templates/rule_approval_request.tmpl +38 -0
  425. rucio-32.8.6.data/data/rucio/etc/mail_templates/rule_approved_admin.tmpl +4 -0
  426. rucio-32.8.6.data/data/rucio/etc/mail_templates/rule_approved_user.tmpl +17 -0
  427. rucio-32.8.6.data/data/rucio/etc/mail_templates/rule_denied_admin.tmpl +6 -0
  428. rucio-32.8.6.data/data/rucio/etc/mail_templates/rule_denied_user.tmpl +17 -0
  429. rucio-32.8.6.data/data/rucio/etc/mail_templates/rule_ok_notification.tmpl +19 -0
  430. rucio-32.8.6.data/data/rucio/etc/rse-accounts.cfg.template +25 -0
  431. rucio-32.8.6.data/data/rucio/etc/rucio.cfg.atlas.client.template +42 -0
  432. rucio-32.8.6.data/data/rucio/etc/rucio.cfg.template +257 -0
  433. rucio-32.8.6.data/data/rucio/etc/rucio_multi_vo.cfg.template +234 -0
  434. rucio-32.8.6.data/data/rucio/requirements.txt +55 -0
  435. rucio-32.8.6.data/data/rucio/tools/bootstrap.py +34 -0
  436. rucio-32.8.6.data/data/rucio/tools/merge_rucio_configs.py +147 -0
  437. rucio-32.8.6.data/data/rucio/tools/reset_database.py +40 -0
  438. rucio-32.8.6.data/scripts/rucio +2540 -0
  439. rucio-32.8.6.data/scripts/rucio-abacus-account +75 -0
  440. rucio-32.8.6.data/scripts/rucio-abacus-collection-replica +47 -0
  441. rucio-32.8.6.data/scripts/rucio-abacus-rse +79 -0
  442. rucio-32.8.6.data/scripts/rucio-admin +2434 -0
  443. rucio-32.8.6.data/scripts/rucio-atropos +61 -0
  444. rucio-32.8.6.data/scripts/rucio-auditor +199 -0
  445. rucio-32.8.6.data/scripts/rucio-automatix +51 -0
  446. rucio-32.8.6.data/scripts/rucio-bb8 +58 -0
  447. rucio-32.8.6.data/scripts/rucio-c3po +86 -0
  448. rucio-32.8.6.data/scripts/rucio-cache-client +135 -0
  449. rucio-32.8.6.data/scripts/rucio-cache-consumer +43 -0
  450. rucio-32.8.6.data/scripts/rucio-conveyor-finisher +59 -0
  451. rucio-32.8.6.data/scripts/rucio-conveyor-poller +67 -0
  452. rucio-32.8.6.data/scripts/rucio-conveyor-preparer +38 -0
  453. rucio-32.8.6.data/scripts/rucio-conveyor-receiver +44 -0
  454. rucio-32.8.6.data/scripts/rucio-conveyor-stager +77 -0
  455. rucio-32.8.6.data/scripts/rucio-conveyor-submitter +140 -0
  456. rucio-32.8.6.data/scripts/rucio-conveyor-throttler +105 -0
  457. rucio-32.8.6.data/scripts/rucio-dark-reaper +54 -0
  458. rucio-32.8.6.data/scripts/rucio-dumper +159 -0
  459. rucio-32.8.6.data/scripts/rucio-follower +45 -0
  460. rucio-32.8.6.data/scripts/rucio-hermes +55 -0
  461. rucio-32.8.6.data/scripts/rucio-judge-cleaner +90 -0
  462. rucio-32.8.6.data/scripts/rucio-judge-evaluator +138 -0
  463. rucio-32.8.6.data/scripts/rucio-judge-injector +45 -0
  464. rucio-32.8.6.data/scripts/rucio-judge-repairer +45 -0
  465. rucio-32.8.6.data/scripts/rucio-kronos +45 -0
  466. rucio-32.8.6.data/scripts/rucio-light-reaper +53 -0
  467. rucio-32.8.6.data/scripts/rucio-minos +54 -0
  468. rucio-32.8.6.data/scripts/rucio-minos-temporary-expiration +51 -0
  469. rucio-32.8.6.data/scripts/rucio-necromancer +121 -0
  470. rucio-32.8.6.data/scripts/rucio-oauth-manager +64 -0
  471. rucio-32.8.6.data/scripts/rucio-reaper +84 -0
  472. rucio-32.8.6.data/scripts/rucio-replica-recoverer +249 -0
  473. rucio-32.8.6.data/scripts/rucio-storage-consistency-actions +75 -0
  474. rucio-32.8.6.data/scripts/rucio-transmogrifier +78 -0
  475. rucio-32.8.6.data/scripts/rucio-undertaker +77 -0
  476. rucio-32.8.6.dist-info/METADATA +83 -0
  477. rucio-32.8.6.dist-info/RECORD +481 -0
  478. rucio-32.8.6.dist-info/WHEEL +5 -0
  479. rucio-32.8.6.dist-info/licenses/AUTHORS.rst +94 -0
  480. rucio-32.8.6.dist-info/licenses/LICENSE +201 -0
  481. rucio-32.8.6.dist-info/top_level.txt +1 -0
@@ -0,0 +1,14 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright European Organization for Nuclear Research (CERN) since 2012
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
@@ -0,0 +1,149 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright European Organization for Nuclear Research (CERN) since 2012
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ """
17
+ Judge-Cleaner is a daemon to clean expired replication rules.
18
+ """
19
+ import functools
20
+ import logging
21
+ import threading
22
+ import time
23
+ from copy import deepcopy
24
+ from datetime import datetime, timedelta
25
+ from random import randint
26
+ from re import match
27
+ from typing import TYPE_CHECKING
28
+
29
+ from sqlalchemy.exc import DatabaseError
30
+
31
+ import rucio.db.sqla.util
32
+ from rucio.common import exception
33
+ from rucio.common.exception import DatabaseException, UnsupportedOperation, RuleNotFound
34
+ from rucio.common.logging import setup_logging
35
+ from rucio.core.monitor import MetricManager
36
+ from rucio.core.rule import delete_rule, get_expired_rules
37
+ from rucio.daemons.common import run_daemon
38
+ from rucio.db.sqla.util import get_db_time
39
+
40
+ if TYPE_CHECKING:
41
+ from types import FrameType
42
+ from typing import Optional
43
+
44
+ METRICS = MetricManager(module=__name__)
45
+ graceful_stop = threading.Event()
46
+ DAEMON_NAME = 'judge-cleaner'
47
+
48
+
49
+ def rule_cleaner(once=False, sleep_time=60):
50
+ """
51
+ Main loop to check for expired replication rules
52
+ """
53
+ paused_rules = {} # {rule_id: datetime}
54
+ run_daemon(
55
+ once=once,
56
+ graceful_stop=graceful_stop,
57
+ executable=DAEMON_NAME,
58
+ partition_wait_time=1,
59
+ sleep_time=sleep_time,
60
+ run_once_fnc=functools.partial(
61
+ run_once,
62
+ paused_rules=paused_rules,
63
+ )
64
+ )
65
+
66
+
67
+ def run_once(paused_rules, heartbeat_handler, **_kwargs):
68
+ worker_number, total_workers, logger = heartbeat_handler.live()
69
+
70
+ start = time.time()
71
+
72
+ # Refresh paused rules
73
+ iter_paused_rules = deepcopy(paused_rules)
74
+ for key in iter_paused_rules:
75
+ if datetime.utcnow() > paused_rules[key]:
76
+ del paused_rules[key]
77
+
78
+ rules = get_expired_rules(total_workers=total_workers,
79
+ worker_number=worker_number,
80
+ limit=200,
81
+ blocked_rules=[key for key in paused_rules])
82
+ logger(logging.DEBUG, 'index query time %f fetch size is %d' % (time.time() - start, len(rules)))
83
+
84
+ if not rules:
85
+ logger(logging.DEBUG, 'did not get any work (paused_rules=%s)' % str(len(paused_rules)))
86
+ return
87
+
88
+ for rule in rules:
89
+ _, _, logger = heartbeat_handler.live()
90
+ rule_id = rule[0]
91
+ rule_expression = rule[1]
92
+ logger(logging.INFO, 'Deleting rule %s with expression %s' % (rule_id, rule_expression))
93
+ if graceful_stop.is_set():
94
+ break
95
+ try:
96
+ start = time.time()
97
+ delete_rule(rule_id=rule_id, nowait=True)
98
+ logger(logging.DEBUG, 'deletion of %s took %f' % (rule_id, time.time() - start))
99
+ except (DatabaseException, DatabaseError, UnsupportedOperation) as e:
100
+ if match('.*ORA-00054.*', str(e.args[0])):
101
+ paused_rules[rule_id] = datetime.utcnow() + timedelta(seconds=randint(600, 2400))
102
+ METRICS.counter('exceptions.{exception}').labels(exception='LocksDetected').inc()
103
+ logger(logging.WARNING, 'Locks detected for %s' % rule_id)
104
+ elif match('.*QueuePool.*', str(e.args[0])):
105
+ logger(logging.WARNING, 'DatabaseException', exc_info=True)
106
+ METRICS.counter('exceptions.{exception}').labels(exception=e.__class__.__name__).inc()
107
+ elif match('.*ORA-03135.*', str(e.args[0])):
108
+ logger(logging.WARNING, 'DatabaseException', exc_info=True)
109
+ METRICS.counter('exceptions.{exception}').labels(exception=e.__class__.__name__).inc()
110
+ else:
111
+ logger(logging.ERROR, 'DatabaseException', exc_info=True)
112
+ METRICS.counter('exceptions.{exception}').labels(exception=e.__class__.__name__).inc()
113
+ except RuleNotFound:
114
+ pass
115
+
116
+
117
+ def stop(signum: "Optional[int]" = None, frame: "Optional[FrameType]" = None) -> None:
118
+ """
119
+ Graceful exit.
120
+ """
121
+ graceful_stop.set()
122
+
123
+
124
+ def run(once=False, threads=1, sleep_time=60):
125
+ """
126
+ Starts up the Judge-Clean threads.
127
+ """
128
+ setup_logging(process_name=DAEMON_NAME)
129
+
130
+ if rucio.db.sqla.util.is_old_db():
131
+ raise exception.DatabaseException('Database was not updated, daemon won\'t start')
132
+
133
+ client_time, db_time = datetime.utcnow(), get_db_time()
134
+ max_offset = timedelta(hours=1, seconds=10)
135
+ if type(db_time) is datetime:
136
+ if db_time - client_time > max_offset or client_time - db_time > max_offset:
137
+ logging.critical('Offset between client and db time too big. Stopping Cleaner')
138
+ return
139
+
140
+ if once:
141
+ rule_cleaner(once)
142
+ else:
143
+ logging.info('Cleaner starting %s threads' % str(threads))
144
+ threads = [threading.Thread(target=rule_cleaner, kwargs={'once': once,
145
+ 'sleep_time': sleep_time}) for i in range(0, threads)]
146
+ [t.start() for t in threads]
147
+ # Interruptible joins require a timeout.
148
+ while threads[0].is_alive():
149
+ [t.join(timeout=3.14) for t in threads]
@@ -0,0 +1,172 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright European Organization for Nuclear Research (CERN) since 2012
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ """
17
+ Judge-Evaluator is a daemon to re-evaluate and execute replication rules.
18
+ """
19
+ import copy
20
+ import functools
21
+ import logging
22
+ import threading
23
+ import time
24
+ import traceback
25
+ from datetime import datetime, timedelta
26
+ from random import randint
27
+ from re import match
28
+ from typing import TYPE_CHECKING
29
+
30
+ from sqlalchemy.exc import DatabaseError
31
+ from sqlalchemy.orm.exc import FlushError
32
+
33
+ import rucio.db.sqla.util
34
+ from rucio.common.exception import DatabaseException, DataIdentifierNotFound, ReplicationRuleCreationTemporaryFailed
35
+ from rucio.common.logging import setup_logging
36
+ from rucio.common.types import InternalScope
37
+ from rucio.core.monitor import MetricManager
38
+ from rucio.core.rule import re_evaluate_did, get_updated_dids, delete_updated_did
39
+ from rucio.daemons.common import run_daemon
40
+
41
+ if TYPE_CHECKING:
42
+ from types import FrameType
43
+ from typing import Optional
44
+
45
+ METRICS = MetricManager(module=__name__)
46
+ graceful_stop = threading.Event()
47
+ DAEMON_NAME = 'judge-evaluator'
48
+
49
+
50
+ def re_evaluator(once=False, sleep_time=30, did_limit=100):
51
+ """
52
+ Main loop to check the re-evaluation of dids.
53
+ """
54
+
55
+ paused_dids = {} # {(scope, name): datetime}
56
+ run_daemon(
57
+ once=once,
58
+ graceful_stop=graceful_stop,
59
+ executable=DAEMON_NAME,
60
+ partition_wait_time=1,
61
+ sleep_time=sleep_time,
62
+ run_once_fnc=functools.partial(
63
+ run_once,
64
+ did_limit=did_limit,
65
+ paused_dids=paused_dids,
66
+ )
67
+ )
68
+
69
+
70
+ def run_once(paused_dids, did_limit, heartbeat_handler, **_kwargs):
71
+ worker_number, total_workers, logger = heartbeat_handler.live()
72
+
73
+ # heartbeat
74
+ start = time.time() # NOQA
75
+
76
+ # Refresh paused dids
77
+ iter_paused_dids = copy.copy(paused_dids)
78
+ for key in iter_paused_dids:
79
+ if datetime.utcnow() > paused_dids[key]:
80
+ del paused_dids[key]
81
+
82
+ # Select a bunch of dids for re evaluation for this worker
83
+ dids = get_updated_dids(total_workers=total_workers,
84
+ worker_number=worker_number,
85
+ limit=did_limit,
86
+ blocked_dids=[(InternalScope(key[0], fromExternal=False), key[1]) for key in paused_dids])
87
+ logger(logging.DEBUG, 'index query time %f fetch size is %d (%d blocked)', time.time() - start, len(dids),
88
+ len([(InternalScope(key[0], fromExternal=False), key[1]) for key in paused_dids]))
89
+
90
+ # If the list is empty, sent the worker to sleep
91
+ if not dids:
92
+ logger(logging.DEBUG, 'did not get any work (paused_dids=%s)', str(len(paused_dids)))
93
+ return
94
+
95
+ done_dids = {}
96
+ for did in dids:
97
+ _, _, logger = heartbeat_handler.live()
98
+ if graceful_stop.is_set():
99
+ break
100
+
101
+ # Check if this did has already been operated on
102
+ did_tag = '%s:%s' % (did.scope.internal, did.name)
103
+ if did_tag in done_dids:
104
+ if did.rule_evaluation_action in done_dids[did_tag]:
105
+ logger(logging.DEBUG, 'evaluation of %s:%s already done', did.scope, did.name)
106
+ delete_updated_did(id_=did.id)
107
+ continue
108
+ else:
109
+ done_dids[did_tag] = []
110
+
111
+ # Jump paused dids
112
+ if (did.scope.internal, did.name) in paused_dids:
113
+ continue
114
+
115
+ try:
116
+ start_time = time.time()
117
+ re_evaluate_did(scope=did.scope, name=did.name, rule_evaluation_action=did.rule_evaluation_action)
118
+ logger(logging.DEBUG, 'evaluation of %s:%s took %f', did.scope, did.name, time.time() - start_time)
119
+ delete_updated_did(id_=did.id)
120
+ done_dids[did_tag].append(did.rule_evaluation_action)
121
+ except DataIdentifierNotFound:
122
+ delete_updated_did(id_=did.id)
123
+ except (DatabaseException, DatabaseError) as e:
124
+ if match('.*ORA-000(01|54).*', str(e.args[0])):
125
+ paused_dids[(did.scope.internal, did.name)] = datetime.utcnow() + timedelta(seconds=randint(60, 600))
126
+ logger(logging.WARNING, 'Locks detected for %s:%s', did.scope, did.name)
127
+ METRICS.counter('exceptions.{exception}').labels(exception='LocksDetected').inc()
128
+ elif match('.*QueuePool.*', str(e.args[0])):
129
+ logger(logging.WARNING, traceback.format_exc())
130
+ METRICS.counter('exceptions.{exception}').labels(exception=e.__class__.__name__).inc()
131
+ elif match('.*ORA-03135.*', str(e.args[0])):
132
+ logger(logging.WARNING, traceback.format_exc())
133
+ METRICS.counter('exceptions.{exception}').labels(exception=e.__class__.__name__).inc()
134
+ else:
135
+ logger(logging.ERROR, traceback.format_exc())
136
+ METRICS.counter('exceptions.{exception}').labels(exception=e.__class__.__name__).inc()
137
+ except ReplicationRuleCreationTemporaryFailed as e:
138
+ METRICS.counter('exceptions.{exception}').labels(exception=e.__class__.__name__).inc()
139
+ logger(logging.WARNING, 'Replica Creation temporary failed, retrying later for %s:%s', did.scope, did.name)
140
+ except FlushError as e:
141
+ METRICS.counter('exceptions.{exception}').labels(exception=e.__class__.__name__).inc()
142
+ logger(logging.WARNING, 'Flush error for %s:%s', did.scope, did.name)
143
+
144
+
145
+ def stop(signum: "Optional[int]" = None, frame: "Optional[FrameType]" = None) -> None:
146
+ """
147
+ Graceful exit.
148
+ """
149
+
150
+ graceful_stop.set()
151
+
152
+
153
+ def run(once=False, threads=1, sleep_time=30, did_limit=100):
154
+ """
155
+ Starts up the Judge-Eval threads.
156
+ """
157
+ setup_logging(process_name=DAEMON_NAME)
158
+
159
+ if rucio.db.sqla.util.is_old_db():
160
+ raise DatabaseException('Database was not updated, daemon won\'t start')
161
+
162
+ if once:
163
+ re_evaluator(once=once, did_limit=did_limit)
164
+ else:
165
+ logging.info('Evaluator starting %s threads' % str(threads))
166
+ threads = [threading.Thread(target=re_evaluator, kwargs={'once': once,
167
+ 'sleep_time': sleep_time,
168
+ 'did_limit': did_limit}) for i in range(0, threads)]
169
+ [t.start() for t in threads]
170
+ # Interruptible joins require a timeout.
171
+ while threads[0].is_alive():
172
+ [t.join(timeout=3.14) for t in threads]
@@ -0,0 +1,154 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright European Organization for Nuclear Research (CERN) since 2012
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ """
17
+ Judge-Injector is a daemon to asynchronously create replication rules
18
+ """
19
+ import functools
20
+ import logging
21
+ import threading
22
+ import time
23
+ from copy import deepcopy
24
+ from datetime import datetime, timedelta
25
+ from random import randint
26
+ from re import match
27
+ from typing import TYPE_CHECKING
28
+
29
+ from sqlalchemy.exc import DatabaseError
30
+
31
+ import rucio.db.sqla.util
32
+ from rucio.common.exception import (DatabaseException, RuleNotFound, RSEWriteBlocked,
33
+ ReplicationRuleCreationTemporaryFailed, InsufficientAccountLimit)
34
+ from rucio.common.logging import setup_logging
35
+ from rucio.core.monitor import MetricManager
36
+ from rucio.core.rule import inject_rule, get_injected_rules, update_rule
37
+ from rucio.daemons.common import run_daemon
38
+
39
+ if TYPE_CHECKING:
40
+ from types import FrameType
41
+ from typing import Optional
42
+
43
+ METRICS = MetricManager(module=__name__)
44
+ graceful_stop = threading.Event()
45
+ DAEMON_NAME = 'judge-injector'
46
+
47
+
48
+ def rule_injector(once=False, sleep_time=60):
49
+ """
50
+ Main loop to check for asynchronous creation of replication rules
51
+ """
52
+ paused_rules = {} # {rule_id: datetime}
53
+ run_daemon(
54
+ once=once,
55
+ graceful_stop=graceful_stop,
56
+ executable=DAEMON_NAME,
57
+ partition_wait_time=1,
58
+ sleep_time=sleep_time,
59
+ run_once_fnc=functools.partial(
60
+ run_once,
61
+ paused_rules=paused_rules,
62
+ )
63
+ )
64
+
65
+
66
+ def run_once(paused_rules, heartbeat_handler, **_kwargs):
67
+ worker_number, total_workers, logger = heartbeat_handler.live()
68
+
69
+ start = time.time()
70
+
71
+ # Refresh paused rules
72
+ iter_paused_rules = deepcopy(paused_rules)
73
+ for key in iter_paused_rules:
74
+ if datetime.utcnow() > paused_rules[key]:
75
+ del paused_rules[key]
76
+
77
+ rules = get_injected_rules(total_workers=total_workers,
78
+ worker_number=worker_number,
79
+ limit=100,
80
+ blocked_rules=[key for key in paused_rules])
81
+ logger(logging.DEBUG, 'index query time %f fetch size is %d' % (time.time() - start, len(rules)))
82
+
83
+ if not rules:
84
+ logger(logging.DEBUG, 'did not get any work (paused_rules=%s)' % str(len(paused_rules)))
85
+ return
86
+
87
+ for rule in rules:
88
+ _, _, logger = heartbeat_handler.live()
89
+ rule_id = rule[0]
90
+ logger(logging.INFO, 'Injecting rule %s' % rule_id)
91
+ if graceful_stop.is_set():
92
+ break
93
+ try:
94
+ start = time.time()
95
+ inject_rule(rule_id=rule_id, logger=logger)
96
+ logger(logging.DEBUG, 'injection of %s took %f' % (rule_id, time.time() - start))
97
+ except (DatabaseException, DatabaseError) as e:
98
+ if match('.*ORA-00054.*', str(e.args[0])):
99
+ paused_rules[rule_id] = datetime.utcnow() + timedelta(seconds=randint(60, 600))
100
+ METRICS.counter('exceptions.{exception}').labels(exception='LocksDetected').inc()
101
+ logger(logging.WARNING, 'Locks detected for %s' % rule_id)
102
+ elif match('.*QueuePool.*', str(e.args[0])):
103
+ logger(logging.WARNING, 'DatabaseException', exc_info=True)
104
+ METRICS.counter('exceptions.{exception}').labels(exception=e.__class__.__name__).inc()
105
+ elif match('.*ORA-03135.*', str(e.args[0])):
106
+ logger(logging.WARNING, 'DatabaseException', exc_info=True)
107
+ METRICS.counter('exceptions.{exception}').labels(exception=e.__class__.__name__).inc()
108
+ else:
109
+ logger(logging.ERROR, 'DatabaseException', exc_info=True)
110
+ METRICS.counter('exceptions.{exception}').labels(exception=e.__class__.__name__).inc()
111
+ except (RSEWriteBlocked) as e:
112
+ paused_rules[rule_id] = datetime.utcnow() + timedelta(seconds=randint(60, 600))
113
+ logger(logging.WARNING, 'RSEWriteBlocked for rule %s' % rule_id)
114
+ METRICS.counter('exceptions.{exception}').labels(exception=e.__class__.__name__).inc()
115
+ except ReplicationRuleCreationTemporaryFailed as e:
116
+ paused_rules[rule_id] = datetime.utcnow() + timedelta(seconds=randint(60, 600))
117
+ logger(logging.WARNING, 'ReplicationRuleCreationTemporaryFailed for rule %s' % rule_id)
118
+ METRICS.counter('exceptions.{exception}').labels(exception=e.__class__.__name__).inc()
119
+ except RuleNotFound:
120
+ pass
121
+ except InsufficientAccountLimit:
122
+ # A rule with InsufficientAccountLimit on injection hangs there potentially forever
123
+ # It should be marked as SUSPENDED
124
+ logger(logging.INFO, 'Marking rule %s as SUSPENDED due to InsufficientAccountLimit' % rule_id)
125
+ update_rule(rule_id=rule_id, options={'state': 'SUSPENDED'})
126
+
127
+
128
+ def stop(signum: "Optional[int]" = None, frame: "Optional[FrameType]" = None) -> None:
129
+ """
130
+ Graceful exit.
131
+ """
132
+
133
+ graceful_stop.set()
134
+
135
+
136
+ def run(once=False, threads=1, sleep_time=60):
137
+ """
138
+ Starts up the Judge-Injector threads.
139
+ """
140
+ setup_logging(process_name=DAEMON_NAME)
141
+
142
+ if rucio.db.sqla.util.is_old_db():
143
+ raise DatabaseException('Database was not updated, daemon won\'t start')
144
+
145
+ if once:
146
+ rule_injector(once)
147
+ else:
148
+ logging.info('Injector starting %s threads' % str(threads))
149
+ threads = [threading.Thread(target=rule_injector, kwargs={'once': once,
150
+ 'sleep_time': sleep_time}) for i in range(0, threads)]
151
+ [t.start() for t in threads]
152
+ # Interruptible joins require a timeout.
153
+ while threads[0].is_alive():
154
+ [t.join(timeout=3.14) for t in threads]
@@ -0,0 +1,144 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright European Organization for Nuclear Research (CERN) since 2012
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ """
17
+ Judge-Repairer is a daemon to repair stuck replication rules.
18
+ """
19
+ import functools
20
+ import logging
21
+ import threading
22
+ import time
23
+ import traceback
24
+ from copy import deepcopy
25
+ from datetime import datetime, timedelta
26
+ from random import randint
27
+ from re import match
28
+ from typing import TYPE_CHECKING
29
+
30
+ from sqlalchemy.exc import DatabaseError
31
+
32
+ import rucio.db.sqla.util
33
+ from rucio.common import exception
34
+ from rucio.common.exception import DatabaseException
35
+ from rucio.common.logging import setup_logging
36
+ from rucio.core.monitor import MetricManager
37
+ from rucio.core.rule import repair_rule, get_stuck_rules
38
+ from rucio.daemons.common import run_daemon
39
+
40
+ if TYPE_CHECKING:
41
+ from types import FrameType
42
+ from typing import Optional
43
+
44
+ METRICS = MetricManager(module=__name__)
45
+ graceful_stop = threading.Event()
46
+ DAEMON_NAME = 'judge-repairer'
47
+
48
+
49
+ def rule_repairer(once=False, sleep_time=60):
50
+ """
51
+ Main loop to check for STUCK replication rules
52
+ """
53
+ paused_rules = {} # {rule_id: datetime}
54
+ run_daemon(
55
+ once=once,
56
+ graceful_stop=graceful_stop,
57
+ executable=DAEMON_NAME,
58
+ partition_wait_time=1,
59
+ sleep_time=sleep_time,
60
+ run_once_fnc=functools.partial(
61
+ run_once,
62
+ paused_rules=paused_rules,
63
+ delta=-1 if once else 1800,
64
+ )
65
+ )
66
+
67
+
68
+ def run_once(paused_rules, delta, heartbeat_handler, **_kwargs):
69
+ worker_number, total_workers, logger = heartbeat_handler.live()
70
+
71
+ start = time.time()
72
+
73
+ # Refresh paused rules
74
+ iter_paused_rules = deepcopy(paused_rules)
75
+ for key in iter_paused_rules:
76
+ if datetime.utcnow() > paused_rules[key]:
77
+ del paused_rules[key]
78
+
79
+ # Select a bunch of rules for this worker to repair
80
+ rules = get_stuck_rules(total_workers=total_workers,
81
+ worker_number=worker_number,
82
+ delta=delta,
83
+ limit=100,
84
+ blocked_rules=[key for key in paused_rules])
85
+
86
+ logger(logging.DEBUG, 'index query time %f fetch size is %d' % (time.time() - start, len(rules)))
87
+
88
+ if not rules:
89
+ logger(logging.DEBUG, 'did not get any work (paused_rules=%s)' % (str(len(paused_rules))))
90
+ return
91
+
92
+ for rule_id in rules:
93
+ _, _, logger = heartbeat_handler.live()
94
+ rule_id = rule_id[0]
95
+ logger(logging.INFO, 'Repairing rule %s' % (rule_id))
96
+ if graceful_stop.is_set():
97
+ break
98
+ try:
99
+ start = time.time()
100
+ repair_rule(rule_id=rule_id)
101
+ logger(logging.DEBUG, 'repairing of %s took %f' % (rule_id, time.time() - start))
102
+ except (DatabaseException, DatabaseError) as e:
103
+ if match('.*ORA-00054.*', str(e.args[0])):
104
+ paused_rules[rule_id] = datetime.utcnow() + timedelta(seconds=randint(600, 2400))
105
+ logger(logging.WARNING, 'Locks detected for %s' % (rule_id))
106
+ METRICS.counter('exceptions.{exception}').labels(exception='LocksDetected').inc()
107
+ elif match('.*QueuePool.*', str(e.args[0])):
108
+ logger(logging.WARNING, traceback.format_exc())
109
+ METRICS.counter('exceptions.{exception}').labels(exception=e.__class__.__name__).inc()
110
+ elif match('.*ORA-03135.*', str(e.args[0])):
111
+ logger(logging.WARNING, traceback.format_exc())
112
+ METRICS.counter('exceptions.{exception}').labels(exception=e.__class__.__name__).inc()
113
+ else:
114
+ logger(logging.ERROR, traceback.format_exc())
115
+ METRICS.counter('exceptions.{exception}').labels(exception=e.__class__.__name__).inc()
116
+
117
+
118
+ def stop(signum: "Optional[int]" = None, frame: "Optional[FrameType]" = None) -> None:
119
+ """
120
+ Graceful exit.
121
+ """
122
+
123
+ graceful_stop.set()
124
+
125
+
126
+ def run(once=False, threads=1, sleep_time=60):
127
+ """
128
+ Starts up the Judge-Repairer threads.
129
+ """
130
+ setup_logging(process_name=DAEMON_NAME)
131
+
132
+ if rucio.db.sqla.util.is_old_db():
133
+ raise exception.DatabaseException('Database was not updated, daemon won\'t start')
134
+
135
+ if once:
136
+ rule_repairer(once)
137
+ else:
138
+ logging.info('Repairer starting %s threads' % str(threads))
139
+ threads = [threading.Thread(target=rule_repairer, kwargs={'once': once,
140
+ 'sleep_time': sleep_time}) for i in range(0, threads)]
141
+ [t.start() for t in threads]
142
+ # Interruptible joins require a timeout.
143
+ while threads[0].is_alive():
144
+ [t.join(timeout=3.14) for t in threads]
@@ -0,0 +1,14 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright European Organization for Nuclear Research (CERN) since 2012
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.