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,159 @@
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 enum
16
+ from collections import namedtuple
17
+ from typing import Literal, get_args
18
+
19
+ from rucio.common.config import config_get_bool
20
+
21
+ """
22
+ Constants.
23
+
24
+ """
25
+
26
+ RESERVED_KEYS = ['scope', 'name', 'account', 'did_type', 'is_open', 'monotonic', 'obsolete', 'complete',
27
+ 'availability', 'suppressed', 'bytes', 'length', 'md5', 'adler32', 'rule_evaluation_action',
28
+ 'rule_evaluation_required', 'expired_at', 'deleted_at', 'created_at', 'updated_at']
29
+ # collection_keys =
30
+ # file_keys =
31
+
32
+ KEY_TYPES = ['ALL', 'COLLECTION', 'FILE', 'DERIVED']
33
+ # all(container, dataset, file), collection(dataset or container), file, derived(compute from file for collection)
34
+
35
+ SCHEME_MAP = {'srm': ['srm', 'gsiftp'],
36
+ 'gsiftp': ['srm', 'gsiftp'],
37
+ 'https': ['https', 'davs', 'srm+https', 'cs3s'],
38
+ 'davs': ['https', 'davs', 'srm+https', 'cs3s'],
39
+ 'srm+https': ['https', 'davs', 'srm+https', 'cs3s'],
40
+ 'cs3s': ['https', 'davs', 'srm+https', 'cs3s'],
41
+ 'root': ['root'],
42
+ 'scp': ['scp'],
43
+ 'rsync': ['rsync'],
44
+ 'rclone': ['rclone']}
45
+ if config_get_bool('transfers', 'srm_https_compatibility', raise_exception=False, default=False):
46
+ SCHEME_MAP['srm'].append('https')
47
+ SCHEME_MAP['https'].append('srm')
48
+ SCHEME_MAP['srm'].append('davs')
49
+ SCHEME_MAP['davs'].append('srm')
50
+
51
+ SORTING_ALGORITHMS_LITERAL = Literal['geoip', 'closeness', 'custom_table', 'dynamic', 'ranking', 'random']
52
+ SORTING_ALGORITHMS = list(get_args(SORTING_ALGORITHMS_LITERAL))
53
+
54
+ SUPPORTED_PROTOCOLS_LITERAL = Literal['gsiftp', 'srm', 'root', 'davs', 'http', 'https', 'file', 'storm', 'srm+https', 'scp', 'rsync', 'rclone', 'magnet']
55
+ SUPPORTED_PROTOCOLS: list[str] = list(get_args(SUPPORTED_PROTOCOLS_LITERAL))
56
+
57
+ RSE_SUPPORTED_PROTOCOL_DOMAINS_LITERAL = Literal['ALL', 'LAN', 'WAN']
58
+
59
+ RSE_SUPPORTED_PROTOCOL_OPERATIONS_LITERAL = Literal['read', 'write', 'delete', 'third_party_copy_read', 'third_party_copy_write']
60
+ RSE_SUPPORTED_PROTOCOL_OPERATIONS: list[str] = list(get_args(RSE_SUPPORTED_PROTOCOL_OPERATIONS_LITERAL))
61
+
62
+ FTS_STATE = namedtuple('FTS_STATE', ['SUBMITTED', 'READY', 'ACTIVE', 'FAILED', 'FINISHED', 'FINISHEDDIRTY', 'NOT_USED',
63
+ 'CANCELED'])('SUBMITTED', 'READY', 'ACTIVE', 'FAILED', 'FINISHED', 'FINISHEDDIRTY',
64
+ 'NOT_USED', 'CANCELED')
65
+
66
+ FTS_COMPLETE_STATE = namedtuple('FTS_COMPLETE_STATE', ['OK', 'ERROR'])('Ok', 'Error')
67
+
68
+ # https://gitlab.cern.ch/fts/fts3/-/blob/master/src/db/generic/Job.h#L41
69
+ FTS_JOB_TYPE = namedtuple('FTS_JOB_TYPE', ['MULTIPLE_REPLICA', 'MULTI_HOP', 'SESSION_REUSE', 'REGULAR'])('R', 'H', 'Y', 'N')
70
+
71
+
72
+ # Messages constants
73
+
74
+ MAX_MESSAGE_LENGTH = 4000
75
+
76
+
77
+ class SuspiciousAvailability(enum.Enum):
78
+ ALL = 0
79
+ EXIST_COPIES = 1
80
+ LAST_COPY = 2
81
+
82
+
83
+ class ReplicaState(enum.Enum):
84
+ # From rucio.db.sqla.constants, update that file at the same time as this
85
+ AVAILABLE = 'A'
86
+ UNAVAILABLE = 'U'
87
+ COPYING = 'C'
88
+ BEING_DELETED = 'B'
89
+ BAD = 'D'
90
+ TEMPORARY_UNAVAILABLE = 'T'
91
+
92
+
93
+ @enum.unique
94
+ class HermesService(str, enum.Enum):
95
+ """
96
+ The services supported by Hermes2.
97
+ """
98
+ INFLUX = "INFLUX"
99
+ ELASTIC = "ELASTIC"
100
+ EMAIL = "EMAIL"
101
+ ACTIVEMQ = "ACTIVEMQ"
102
+
103
+
104
+ class RseAttr:
105
+
106
+ """
107
+ List of functional RSE attributes.
108
+
109
+ This class acts as a namespace containing all RSE attributes referenced in
110
+ the Rucio source code. Setting them affects Rucio's behaviour in some way.
111
+ """
112
+
113
+ ARCHIVE_TIMEOUT = 'archive_timeout'
114
+ ASSOCIATED_SITES = 'associated_sites'
115
+ AUTO_APPROVE_BYTES = 'auto_approve_bytes'
116
+ AUTO_APPROVE_FILES = 'auto_approve_files'
117
+ BITTORRENT_TRACKER_ADDR = 'bittorrent_tracker_addr'
118
+ BLOCK_MANUAL_APPROVAL = 'block_manual_approval'
119
+ COUNTRY = 'country'
120
+ DECOMMISSION = 'decommission'
121
+ DEFAULT_ACCOUNT_LIMIT_BYTES = 'default_account_limit_bytes'
122
+ FTS = 'fts'
123
+ GLOBUS_ENDPOINT_ID = 'globus_endpoint_id'
124
+ GREEDYDELETION = 'greedyDeletion'
125
+ IS_OBJECT_STORE = 'is_object_store'
126
+ LFN2PFN_ALGORITHM = 'lfn2pfn_algorithm'
127
+ MAXIMUM_PIN_LIFETIME = 'maximum_pin_lifetime'
128
+ MULTIHOP_TOMBSTONE_DELAY = 'multihop_tombstone_delay'
129
+ NAMING_CONVENTION = 'naming_convention'
130
+ OIDC_BASE_PATH = 'oidc_base_path'
131
+ OIDC_SUPPORT = 'oidc_support'
132
+ PHYSGROUP = 'physgroup'
133
+ QBITTORRENT_MANAGEMENT_ADDRESS = 'qbittorrent_management_address'
134
+ RESTRICTED_READ = 'restricted_read'
135
+ RESTRICTED_WRITE = 'restricted_write'
136
+ RULE_APPROVERS = 'rule_approvers'
137
+ S3_URL_STYLE = 's3_url_style'
138
+ SIGN_URL = 'sign_url'
139
+ SIMULATE_MULTIRANGE = 'simulate_multirange'
140
+ SITE = 'site'
141
+ SKIP_UPLOAD_STAT = 'skip_upload_stat'
142
+ SOURCE_FOR_TOTAL_SPACE = 'source_for_total_space'
143
+ SOURCE_FOR_USED_SPACE = 'source_for_used_space'
144
+ STAGING_BUFFER = 'staging_buffer'
145
+ STAGING_REQUIRED = 'staging_required'
146
+ STRICT_COPY = 'strict_copy'
147
+ TOMBSTONE_DELAY = 'tombstone_delay'
148
+ TYPE = 'type'
149
+ USE_IPV4 = 'use_ipv4'
150
+ VERIFY_CHECKSUM = 'verify_checksum'
151
+
152
+ # The following RSE attributes are exclusively used in the permission layer
153
+ # and are likely VO-specific.
154
+
155
+ BLOCK_MANUAL_APPROVE = 'block_manual_approve'
156
+ CMS_TYPE = 'cms_type'
157
+ DEFAULT_LIMIT_FILES = 'default_limit_files'
158
+ QUOTA_APPROVERS = 'quota_approvers'
159
+ RULE_DELETERS = 'rule_deleters'
@@ -0,0 +1,17 @@
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
+ # List of authorized value types for key
16
+ AUTHORIZED_VALUE_TYPES = (float, int, str)
17
+ STRING_TYPES = (str, )
@@ -0,0 +1,189 @@
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
+ DID type to represent a did and to simplify operations on it
17
+ """
18
+
19
+ from typing import Union
20
+
21
+ from rucio.common.exception import DIDError
22
+
23
+
24
+ class DID:
25
+
26
+ """
27
+ Class used to store a DID
28
+ Given an object did of type DID
29
+ scope is stored in did.scope
30
+ name is stored in did.name
31
+ """
32
+
33
+ SCOPE_SEPARATOR = ':'
34
+ IMPLICIT_SCOPE_SEPARATOR = '.'
35
+ IMPLICIT_SCOPE_TO_LEN = {'user': 2, 'group': 2}
36
+ __slots__ = ['scope', 'name']
37
+
38
+ def __init__(self, *args, **kwargs):
39
+ """
40
+ Constructs the DID object. Possible parameter combinations are:
41
+ DID()
42
+ DID('scope:name.did.str')
43
+ DID('user.implicit.scope.in.name')
44
+ DID('custom.scope', 'custom.name')
45
+ DID(['list.scope', 'list.name'])
46
+ DID(('tuple.scope', 'tuple.name'))
47
+ DID({'scope': 'dict.scope', 'name': 'dict.name'})
48
+ DID(scope='kw.scope')
49
+ DID(name='kw.name')
50
+ DID(name='user.kw.implicit.scope')
51
+ DID(scope='kw.scope', name='kw.name')
52
+ DID(did={'scope': 'kw.did.scope', 'name': 'kw.did.name'})
53
+ DID(did=['kw.list.scope', 'kw.list.name'])
54
+ DID(did=('kw.tuple.scope', 'kw.tuple.name'))
55
+ DID('arg.scope', name='kwarg.name')
56
+ DID('arg.name', scope='kwarg.scope')
57
+ """
58
+ self.scope: str = ''
59
+ self.name: str = ''
60
+
61
+ num_args = len(args)
62
+ num_kwargs = len(kwargs)
63
+ if (num_args + num_kwargs) > 2:
64
+ raise DIDError('Constructor takes at most 2 arguments. Given number: {}'.format(num_args + num_kwargs))
65
+
66
+ did: Union["DID", str, tuple[str, str], list[str], dict[str, str]] = ''
67
+ if num_args == 1:
68
+ did = args[0]
69
+
70
+ if num_kwargs == 1:
71
+ if isinstance(did, str):
72
+ k, v = next(iter(kwargs.items()))
73
+ if k == 'scope':
74
+ did = (v, did)
75
+ elif k == 'name':
76
+ did = (did, v)
77
+ else:
78
+ raise DIDError('Constructor got unexpected keyword argument: {}'.format(k))
79
+ else:
80
+ raise DIDError('First argument of constructor is expected to be string type'
81
+ 'when keyword argument is given. Given type: {}'.format(type(did)))
82
+ elif num_args == 0:
83
+ did = kwargs.get('did', kwargs)
84
+ else:
85
+ did = args
86
+
87
+ if isinstance(did, dict):
88
+ self.scope = did.get('scope', '')
89
+ self.name = did.get('name', '')
90
+ if not self.has_scope():
91
+ self.update_implicit_scope()
92
+ elif isinstance(did, tuple) or isinstance(did, list):
93
+ if len(did) != 2:
94
+ raise DIDError('Construction from tuple or list requires exactly 2 elements')
95
+ self.scope = did[0]
96
+ self.name = did[1]
97
+ elif isinstance(did, str):
98
+ did_parts = did.split(DID.SCOPE_SEPARATOR, 1)
99
+ if len(did_parts) == 1:
100
+ self.name = did
101
+ self.update_implicit_scope()
102
+ if not self.has_scope():
103
+ raise DIDError('Object construction from non-splitable string is ambigious')
104
+ else:
105
+ self.scope = did_parts[0]
106
+ self.name = did_parts[1]
107
+ elif isinstance(did, DID):
108
+ self.scope = did.scope
109
+ self.name = did.name
110
+ else:
111
+ raise DIDError('Cannot build object from: {}'.format(type(did)))
112
+
113
+ if self.name.endswith('/'):
114
+ self.name = self.name[:-1]
115
+
116
+ if not self.is_valid_format():
117
+ raise DIDError('Object has invalid format after construction: {}'.format(str(self)))
118
+
119
+ def update_implicit_scope(self) -> None:
120
+ """
121
+ This method sets the scope if it is implicitly given in self.name
122
+ """
123
+ did_parts = self.name.split(DID.IMPLICIT_SCOPE_SEPARATOR)
124
+ num_scope_parts = DID.IMPLICIT_SCOPE_TO_LEN.get(did_parts[0], 0)
125
+ if num_scope_parts > 0:
126
+ self.scope = '.'.join(did_parts[0:num_scope_parts])
127
+
128
+ def is_valid_format(self) -> bool:
129
+ """
130
+ Method to check if the stored DID has a valid format
131
+ :return: bool
132
+ """
133
+ if self.scope.count(DID.SCOPE_SEPARATOR) or self.name.count(DID.SCOPE_SEPARATOR):
134
+ return False
135
+ return True
136
+
137
+ def has_scope(self) -> bool:
138
+ """
139
+ Method to check if the scope part was set
140
+ :return: bool
141
+ """
142
+ return len(self.scope) > 0
143
+
144
+ def has_name(self) -> bool:
145
+ """
146
+ Method to check if the name part was set
147
+ :return: bool
148
+ """
149
+ return len(self.name) > 0
150
+
151
+ def __str__(self) -> str:
152
+ """
153
+ Creates the string representation of self
154
+ :return: string
155
+ """
156
+ if self.has_scope() and self.has_name():
157
+ return '{}{}{}'.format(self.scope, DID.SCOPE_SEPARATOR, self.name)
158
+ elif self.has_scope():
159
+ return self.scope
160
+ return self.name
161
+
162
+ def __eq__(self, other: Union[str, "DID"]) -> bool:
163
+ """
164
+ Equality comparison with another object
165
+ :return: bool
166
+ """
167
+ if isinstance(other, str):
168
+ return str(self) == other
169
+ elif not isinstance(other, DID):
170
+ try:
171
+ other = DID(other)
172
+ except DIDError:
173
+ return False
174
+
175
+ return self.scope == other.scope and self.name == other.name
176
+
177
+ def __ne__(self, other: Union[str, "DID"]) -> bool:
178
+ """
179
+ Inequality comparison with another object
180
+ :return: bool
181
+ """
182
+ return not self.__eq__(other)
183
+
184
+ def __hash__(self) -> int:
185
+ """
186
+ Uses the string representation of self to create a hash
187
+ :return: int
188
+ """
189
+ return hash(str(self))
@@ -0,0 +1,335 @@
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 bz2
16
+ import contextlib
17
+ import datetime
18
+ import gzip
19
+ import logging
20
+ import os
21
+ import re
22
+ import sys
23
+ import tempfile
24
+ from typing import TYPE_CHECKING, Any, Literal, Optional, Union
25
+
26
+ import gfal2
27
+ import magic
28
+ import requests
29
+
30
+ from rucio.common import config
31
+ from rucio.core.rse import get_rse_id, get_rse_protocols
32
+
33
+ if TYPE_CHECKING:
34
+ from collections.abc import Iterator
35
+ from multiprocessing.connection import Connection
36
+ from types import ModuleType
37
+ from typing import IO, TextIO
38
+
39
+ from _typeshed import FileDescriptorOrPath, GenericPath, StrOrBytesPath
40
+
41
+ from rucio.common.types import RSEProtocolDict
42
+
43
+
44
+ class HTTPDownloadFailed(Exception):
45
+ def __init__(self, msg: str = '', code: Optional[str] = None):
46
+ self.code = code
47
+ if code is not None:
48
+ msg = '{0} (Status {1})'.format(msg, code)
49
+ super(HTTPDownloadFailed, self).__init__(msg)
50
+
51
+
52
+ class LogPipeHandler(logging.Handler):
53
+ def __init__(self, pipe: "Connection"):
54
+ super(LogPipeHandler, self).__init__()
55
+ self.pipe = pipe
56
+
57
+ def emit(self, record: logging.LogRecord) -> None:
58
+ self.pipe.send(self.format(record))
59
+
60
+ def close(self) -> None:
61
+ super(LogPipeHandler, self).close()
62
+ self.pipe.close()
63
+
64
+
65
+ def error(text: str, exit_code: int = 1) -> None:
66
+ '''
67
+ Log and print `text` error. This function ends the execution of the program with exit code
68
+ `exit_code` (defaults to 1).
69
+ '''
70
+ logger = logging.getLogger('dumper.__init__')
71
+ logger.error(text)
72
+ sys.stderr.write(text + '\n')
73
+ exit(1)
74
+
75
+
76
+ def mkdir(dir_: "StrOrBytesPath") -> None:
77
+ '''
78
+ This functions creates the `dir_` directory if it doesn't exist. If `dir_`
79
+ already exists this function does nothing.
80
+ '''
81
+ try:
82
+ os.mkdir(dir_)
83
+ except OSError as error:
84
+ if error.errno != 17:
85
+ raise error
86
+
87
+
88
+ def cacert_config(config: "ModuleType", rucio_home: str) -> Optional[Union["FileDescriptorOrPath", Literal[False]]]:
89
+ logger = logging.getLogger('dumper.__init__')
90
+ try:
91
+ cacert = config.config_get('client', 'ca_cert').replace('$RUCIO_HOME', rucio_home)
92
+ except KeyError:
93
+ cacert = None
94
+
95
+ if cacert is None or not os.path.exists(cacert):
96
+ logger.warning('Configured CA Certificate file "%s" not found: Host certificate verification disabled', cacert)
97
+ cacert = False
98
+
99
+ return cacert
100
+
101
+
102
+ def rucio_home() -> str:
103
+ return os.environ.get('RUCIO_HOME', '/opt/rucio')
104
+
105
+
106
+ def get_requests_session() -> requests.Session:
107
+ requests_session = requests.Session()
108
+ requests_session.verify = cacert_config(config, rucio_home()) # type: ignore
109
+ requests_session.stream = True
110
+ return requests_session
111
+
112
+
113
+ DUMPS_CACHE_DIR = 'cache'
114
+ RESULTS_DIR = 'results'
115
+ CHUNK_SIZE = 4194304 # 4MiB
116
+
117
+
118
+ # There are two Python modules with the name `magic`, luckily both do
119
+ # the same thing.
120
+ # pylint: disable=no-member
121
+ if 'open' in dir(magic):
122
+ _mime = magic.open(magic.MAGIC_MIME)
123
+ _mime.load()
124
+ mimetype = _mime.file
125
+ else:
126
+ mimetype = lambda filename: magic.from_file(filename, mime=True) # NOQA
127
+ # pylint: enable=no-member
128
+
129
+
130
+ def isplaintext(filename: "GenericPath") -> bool:
131
+ '''
132
+ Returns True if `filename` has mimetype == 'text/plain'.
133
+ '''
134
+ if os.path.islink(filename):
135
+ filename = os.readlink(filename)
136
+ return mimetype(filename).split(';')[0] == 'text/plain'
137
+
138
+
139
+ def smart_open(filename: "GenericPath") -> Optional[Union["TextIO", gzip.GzipFile]]:
140
+ '''
141
+ Returns an open file object if `filename` is plain text, else assumes
142
+ it is a bzip2 compressed file and returns a file-like object to
143
+ handle it.
144
+ '''
145
+ f = None
146
+ if isplaintext(filename):
147
+ f = open(filename, 'rt')
148
+ else:
149
+ file_type = mimetype(filename)
150
+ if file_type.find('gzip') > -1:
151
+ f = gzip.GzipFile(filename, 'rt')
152
+ elif file_type.find('bzip2') > -1:
153
+ f = bz2.open(filename, 'rt')
154
+ else:
155
+ pass # Not supported format
156
+ return f
157
+
158
+
159
+ @contextlib.contextmanager
160
+ def temp_file(
161
+ directory: str,
162
+ final_name: Optional[str] = None,
163
+ binary: bool = False
164
+ ) -> "Iterator[tuple[IO[Any], StrOrBytesPath]]":
165
+ '''
166
+ Allows to create a temporal file to store partial results, when the
167
+ file is complete it is renamed to `final_name`.
168
+
169
+ - `directory`: working path to create the temporal and the final file.
170
+ - `final_name`: Path of the final file, relative to `directory`.
171
+ If the `final_name` is omitted or None the renaming step is omitted,
172
+ leaving the temporal file with the results.
173
+ - `binary`: whether to open the file in binary mode (default: False).
174
+
175
+ Important: `directory` and `final_name` must be in the same filesystem as
176
+ a hardlink is used to rename the temporal file.
177
+
178
+ Example:
179
+ >>> with temp_file('/tmp', final_name='b') as (f, fname):
180
+ >>> print('The temporary file is named', fname)
181
+ >>> f.write('x')
182
+ >>> assert not os.path.exist('/tmp/' + fname)
183
+ >>> assert os.path.exist('/tmp/b')
184
+ '''
185
+ logger = logging.getLogger('dumper.__init__')
186
+
187
+ fd, tpath = tempfile.mkstemp(dir=directory)
188
+ tmp = os.fdopen(fd, 'wb' if binary else 'w')
189
+
190
+ try:
191
+ yield tmp, os.path.basename(tpath)
192
+ except:
193
+ # Close and remove temporal file on failure
194
+ tmp.close()
195
+ os.unlink(tpath)
196
+ raise
197
+
198
+ tmp.close()
199
+ if final_name is not None:
200
+ dst_path = os.path.join(directory, final_name)
201
+ logger.debug('Renaming "%s" to "%s"', tpath, dst_path)
202
+ os.link(tpath, dst_path)
203
+ os.unlink(tpath)
204
+
205
+
206
+ DATETIME_FORMAT = '%Y-%m-%d %H:%M:%S'
207
+ DATETIME_FORMAT_FULL = '%Y-%m-%dT%H:%M:%S'
208
+ MILLISECONDS_RE = re.compile(r'\.(\d{3})Z$')
209
+
210
+
211
+ def to_datetime(str_or_datetime: Union[datetime.datetime, str]) -> Optional[datetime.datetime]:
212
+ """
213
+ Convert string to datetime. The format is somewhat flexible.
214
+ Timezone information is ignored.
215
+ """
216
+ logger = logging.getLogger('dumper.__init__')
217
+ if isinstance(str_or_datetime, datetime.datetime):
218
+ return str_or_datetime
219
+ elif str_or_datetime.strip() == '':
220
+ return None
221
+
222
+ str_or_datetime = str_or_datetime.replace('T', ' ')
223
+ try:
224
+ logger.debug(
225
+ 'Trying to parse "%s" date with '
226
+ 'resolution of seconds or tenths of seconds',
227
+ str_or_datetime,
228
+ )
229
+ str_or_datetime = re.sub(r'\.\d$', '', str_or_datetime)
230
+ date = datetime.datetime.strptime(
231
+ str_or_datetime,
232
+ DATETIME_FORMAT,
233
+ )
234
+ except ValueError:
235
+ logger.debug(
236
+ 'Trying to parse "%s" date with resolution of milliseconds',
237
+ str_or_datetime,
238
+ )
239
+ milliseconds = int(MILLISECONDS_RE.search(str_or_datetime).group(1))
240
+ str_or_datetime = MILLISECONDS_RE.sub('', str_or_datetime)
241
+ date = datetime.datetime.strptime(
242
+ str_or_datetime,
243
+ DATETIME_FORMAT,
244
+ )
245
+ date = date + datetime.timedelta(microseconds=milliseconds * 1000)
246
+ return date
247
+
248
+
249
+ def ddmendpoint_preferred_protocol(ddmendpoint: str) -> "RSEProtocolDict":
250
+ return next(p for p in get_rse_protocols(get_rse_id(ddmendpoint))['protocols'] if p['domains']['wan']['read'] == 1)
251
+
252
+
253
+ def ddmendpoint_url(ddmendpoint: str) -> str:
254
+ preferred_protocol = ddmendpoint_preferred_protocol(ddmendpoint)
255
+ prefix = re.sub(r'rucio/$', '', preferred_protocol['prefix'])
256
+ return '{scheme}://{hostname}:{port}'.format(**preferred_protocol) + prefix
257
+
258
+
259
+ def http_download_to_file(url: str, file_: "IO", session: Optional[requests.Session] = None) -> None:
260
+ '''
261
+ Download the file in `url` storing it in the `file_` file-like
262
+ object.
263
+ If given `session` must be a requests.Session instance, and will be
264
+ used to download the file, otherwise requests.get() will be used.
265
+ '''
266
+ def _do_download(url, file_, session, try_decode=False):
267
+ if session is None:
268
+ response = requests.get(url, stream=True)
269
+ else:
270
+ response = session.get(url)
271
+
272
+ if response.status_code != 200:
273
+ logging.error(
274
+ 'Retrieving %s returned %d status code',
275
+ url,
276
+ response.status_code,
277
+ )
278
+ raise HTTPDownloadFailed('Error downloading ' + url, str(response.status_code))
279
+
280
+ if try_decode:
281
+ if response.encoding is None:
282
+ response.encoding = 'utf-8'
283
+ for chunk in response.iter_content(CHUNK_SIZE, decode_unicode=True):
284
+ file_.write(chunk)
285
+ else:
286
+ for chunk in response.iter_content(CHUNK_SIZE):
287
+ file_.write(chunk)
288
+
289
+ try:
290
+ # try without decoding first
291
+ _do_download(url, file_, session, False)
292
+ except TypeError:
293
+ # if that fails due to writing binary data to text file, try to force decode
294
+ _do_download(url, file_, session, True)
295
+
296
+
297
+ def http_download(url: str, filename: "FileDescriptorOrPath") -> None:
298
+ '''
299
+ Download the file in `url` storing it in the path given by `filename`.
300
+ '''
301
+ with open(filename, 'w') as f:
302
+ http_download_to_file(url, f)
303
+
304
+
305
+ def gfal_download_to_file(url: str, file_: "IO") -> None:
306
+ '''
307
+ Download the file in `url` storing it in the `file_` file-like
308
+ object.
309
+ '''
310
+ logger = logging.getLogger('dumper.__init__')
311
+ ctx = gfal2.creat_context() # pylint: disable=no-member
312
+ infile = ctx.open(url, 'r')
313
+
314
+ try:
315
+ chunk = infile.read(CHUNK_SIZE)
316
+ except gfal2.GError as e:
317
+ if e.code == 70:
318
+ logger.debug('GError(70) raised, using GRIDFTP PLUGIN:STAT_ON_OPEN=False workaround to download %s', url)
319
+ ctx.set_opt_boolean('GRIDFTP PLUGIN', 'STAT_ON_OPEN', False)
320
+ infile = ctx.open(url, 'r')
321
+ chunk = infile.read(CHUNK_SIZE)
322
+ else:
323
+ raise
324
+
325
+ while chunk:
326
+ file_.write(chunk)
327
+ chunk = infile.read(CHUNK_SIZE)
328
+
329
+
330
+ def gfal_download(url: str, filename: "FileDescriptorOrPath") -> None:
331
+ '''
332
+ Download the file in `url` storing it in the path given by `filename`.
333
+ '''
334
+ with open(filename, 'w') as f:
335
+ gfal_download_to_file(url, f)