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,277 @@
1
+ # Copyright European Organization for Nuclear Research (CERN) since 2012
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from collections import namedtuple
16
+ from collections.abc import Iterator
17
+ from json import dumps, loads
18
+ from typing import TYPE_CHECKING, Any, Literal, Optional, Union
19
+
20
+ from rucio.common.exception import AccessDenied, InvalidObject
21
+ from rucio.common.schema import validate_schema
22
+ from rucio.common.types import InternalAccount, InternalScope
23
+ from rucio.core import subscription
24
+ from rucio.db.sqla.session import read_session, stream_session, transactional_session
25
+ from rucio.gateway.permission import has_permission
26
+
27
+ if TYPE_CHECKING:
28
+ from sqlalchemy.orm import Session
29
+
30
+
31
+ SubscriptionRuleState = namedtuple('SubscriptionRuleState', ['account', 'name', 'state', 'count'])
32
+
33
+
34
+ @transactional_session
35
+ def add_subscription(
36
+ name: str,
37
+ account: str,
38
+ filter_: dict[str, Any],
39
+ replication_rules: list[dict[str, Any]],
40
+ comments: str,
41
+ lifetime: Union[int, Literal[False]],
42
+ retroactive: bool,
43
+ dry_run: bool,
44
+ priority: Optional[int] = None,
45
+ issuer: Optional[str] = None,
46
+ vo: str = 'def',
47
+ *,
48
+ session: "Session"
49
+ ) -> str:
50
+ """
51
+ Adds a new subscription which will be verified against every new added file and dataset
52
+
53
+ :param account: Account identifier
54
+ :param name: Name of the subscription
55
+ :param filter_: Dictionary of attributes by which the input data should be filtered
56
+ **Example**: ``{'dsn': 'data11_hi*.express_express.*,data11_hi*physics_MinBiasOverlay*', 'account': 'tzero'}``
57
+ :param replication_rules: Replication rules to be set : Dictionary with keys copies, rse_expression, weight, rse_expression
58
+ :param comments: Comments for the subscription
59
+ :param lifetime: Subscription's lifetime (seconds); False if subscription has no lifetime
60
+ :param retroactive: Flag to know if the subscription should be applied on previous data
61
+ :param dry_run: Just print the subscriptions actions without actually executing them (Useful if retroactive flag is set)
62
+ :param priority: The priority of the subscription
63
+ :param issuer: The account issuing this operation.
64
+ :param vo: The VO to act on.
65
+ :param session: The database session in use.
66
+ :returns: subscription_id
67
+ """
68
+ if not has_permission(issuer=issuer, vo=vo, action='add_subscription', kwargs={'account': account}, session=session):
69
+ raise AccessDenied('Account %s can not add subscription' % (issuer))
70
+ try:
71
+ if filter_:
72
+ if not isinstance(filter_, dict):
73
+ raise TypeError('filter should be a dict')
74
+ validate_schema(name='subscription_filter', obj=filter_, vo=vo)
75
+ if replication_rules:
76
+ if not isinstance(replication_rules, list):
77
+ raise TypeError('replication_rules should be a list')
78
+ else:
79
+ for rule in replication_rules:
80
+ validate_schema(name='activity', obj=rule.get('activity', 'default'), vo=vo)
81
+ else:
82
+ raise InvalidObject('You must specify a rule')
83
+ except ValueError as error:
84
+ raise TypeError(error)
85
+
86
+ internal_account = InternalAccount(account, vo=vo)
87
+
88
+ keys = ['scope', 'account']
89
+ types = [InternalScope, InternalAccount]
90
+ for _key, _type in zip(keys, types):
91
+ if _key in filter_:
92
+ if isinstance(filter_[_key], list):
93
+ filter_[_key] = [_type(val, vo=vo).internal for val in filter_[_key]]
94
+ else:
95
+ filter_[_key] = _type(filter_[_key], vo=vo).internal
96
+
97
+ return subscription.add_subscription(name=name, account=internal_account, filter_=dumps(filter_), replication_rules=dumps(replication_rules),
98
+ comments=comments, lifetime=lifetime, retroactive=retroactive, dry_run=dry_run, priority=priority,
99
+ session=session)
100
+
101
+
102
+ @transactional_session
103
+ def update_subscription(
104
+ name: str,
105
+ account: str,
106
+ metadata: Optional[dict[str, Any]] = None,
107
+ issuer: Optional[str] = None,
108
+ vo: str = 'def',
109
+ *,
110
+ session: "Session"
111
+ ) -> None:
112
+ """
113
+ Updates a subscription
114
+
115
+ :param name: Name of the subscription
116
+ :param account: Account identifier
117
+ :param metadata: Dictionary of metadata to update. Supported keys : filter, replication_rules, comments, lifetime, retroactive, dry_run, priority, last_processed
118
+ :param issuer: The account issuing this operation.
119
+ :param vo: The VO to act on.
120
+ :param session: The database session in use.
121
+ :raises: SubscriptionNotFound if subscription is not found
122
+ """
123
+ if not has_permission(issuer=issuer, vo=vo, action='update_subscription', kwargs={'account': account}, session=session):
124
+ raise AccessDenied('Account %s can not update subscription' % (issuer))
125
+ try:
126
+ if not isinstance(metadata, dict):
127
+ raise TypeError('metadata should be a dict')
128
+ if 'filter' in metadata and metadata['filter']:
129
+ if not isinstance(metadata['filter'], dict):
130
+ raise TypeError('filter should be a dict')
131
+ validate_schema(name='subscription_filter', obj=metadata['filter'], vo=vo)
132
+ if 'replication_rules' in metadata and metadata['replication_rules']:
133
+ if not isinstance(metadata['replication_rules'], list):
134
+ raise TypeError('replication_rules should be a list')
135
+ else:
136
+ for rule in metadata['replication_rules']:
137
+ validate_schema(name='activity', obj=rule.get('activity', 'default'), vo=vo)
138
+ except ValueError as error:
139
+ raise TypeError(error)
140
+
141
+ internal_account = InternalAccount(account, vo=vo)
142
+
143
+ if 'filter' in metadata and metadata['filter'] is not None:
144
+ filter_ = metadata['filter']
145
+ keys = ['scope', 'account']
146
+ types = [InternalScope, InternalAccount]
147
+
148
+ for _key, _type in zip(keys, types):
149
+ if _key in filter_ and filter_[_key] is not None:
150
+ if isinstance(filter_[_key], list):
151
+ filter_[_key] = [_type(val, vo=vo).internal for val in filter_[_key]]
152
+ else:
153
+ filter_[_key] = _type(filter_[_key], vo=vo).internal
154
+
155
+ return subscription.update_subscription(name=name, account=internal_account, metadata=metadata, session=session)
156
+
157
+
158
+ @stream_session
159
+ def list_subscriptions(
160
+ name: Optional[str] = None,
161
+ account: Optional[str] = None,
162
+ state: Optional[str] = None,
163
+ vo: str = 'def',
164
+ *,
165
+ session: "Session"
166
+ ) -> Iterator[dict[str, Any]]:
167
+ """
168
+ Returns a dictionary with the subscription information :
169
+ Examples: ``{'status': 'INACTIVE/ACTIVE/BROKEN', 'last_modified_date': ...}``
170
+
171
+ :param name: Name of the subscription
172
+ :param account: Account identifier
173
+ :param state: Filter for subscription state
174
+ :param vo: The VO to act on.
175
+ :param session: The database session in use.
176
+ :returns: Dictionary containing subscription parameter
177
+ :raises: exception.NotFound if subscription is not found
178
+ """
179
+
180
+ if account:
181
+ internal_account = InternalAccount(account, vo=vo)
182
+ else:
183
+ internal_account = InternalAccount('*', vo=vo)
184
+
185
+ subs = subscription.list_subscriptions(name, internal_account, state, session=session)
186
+
187
+ for sub in subs:
188
+ sub['account'] = sub['account'].external
189
+
190
+ if 'filter' in sub:
191
+ fil = loads(sub['filter'])
192
+ if 'account' in fil:
193
+ fil['account'] = [InternalAccount(acc, fromExternal=False).external for acc in fil['account']]
194
+ if 'scope' in fil:
195
+ fil['scope'] = [InternalScope(sco, fromExternal=False).external for sco in fil['scope']]
196
+ sub['filter'] = dumps(fil)
197
+
198
+ yield sub
199
+
200
+
201
+ @stream_session
202
+ def list_subscription_rule_states(
203
+ name: Optional[str] = None,
204
+ account: Optional[str] = None,
205
+ vo: str = 'def',
206
+ *,
207
+ session: "Session"
208
+ ) -> Iterator[SubscriptionRuleState]:
209
+ """Returns a list of with the number of rules per state for a subscription.
210
+
211
+ :param name: Name of the subscription
212
+ :param account: Account identifier
213
+ :param vo: The VO to act on.
214
+ :param session: The database session in use.
215
+ :returns: Sequence with SubscriptionRuleState named tuples (account, name, state, count)
216
+ """
217
+ if account is not None:
218
+ internal_account = InternalAccount(account, vo=vo)
219
+ else:
220
+ internal_account = InternalAccount('*', vo=vo)
221
+ subs = subscription.list_subscription_rule_states(name, internal_account, session=session)
222
+ for sub in subs:
223
+ # sub is an immutable Row so return new named tuple with edited entries
224
+ d = sub._asdict()
225
+ d['account'] = d['account'].external
226
+ yield SubscriptionRuleState(**d)
227
+
228
+
229
+ @transactional_session
230
+ def delete_subscription(
231
+ subscription_id: str,
232
+ vo: str = 'def',
233
+ *,
234
+ session: "Session"
235
+ ) -> None:
236
+ """
237
+ Deletes a subscription
238
+
239
+ :param subscription_id: Subscription identifier
240
+ :param vo: The VO of the user issuing command
241
+ :param session: The database session in use.
242
+ """
243
+
244
+ raise NotImplementedError
245
+
246
+
247
+ @read_session
248
+ def get_subscription_by_id(
249
+ subscription_id: str,
250
+ vo: str = 'def',
251
+ *,
252
+ session: "Session"
253
+ ) -> dict[str, Any]:
254
+ """
255
+ Get a specific subscription by id.
256
+
257
+ :param subscription_id: The subscription_id to select.
258
+ :param vo: The VO of the user issuing command.
259
+ :param session: The database session in use.
260
+
261
+ :raises: SubscriptionNotFound if no Subscription can be found.
262
+ """
263
+ sub = subscription.get_subscription_by_id(subscription_id, session=session)
264
+ if sub['account'].vo != vo:
265
+ raise AccessDenied('Unable to get subscription')
266
+
267
+ sub['account'] = sub['account'].external
268
+
269
+ if 'filter' in sub:
270
+ fil = loads(sub['filter'])
271
+ if 'account' in fil:
272
+ fil['account'] = [InternalAccount(acc, fromExternal=False).external for acc in fil['account']]
273
+ if 'scope' in fil:
274
+ fil['scope'] = [InternalScope(sco, fromExternal=False).external for sco in fil['scope']]
275
+ sub['filter'] = dumps(fil)
276
+
277
+ return sub
rucio/gateway/vo.py ADDED
@@ -0,0 +1,122 @@
1
+ # Copyright European Organization for Nuclear Research (CERN) since 2012
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from typing import TYPE_CHECKING, Any, Optional
16
+
17
+ from rucio.common import exception
18
+ from rucio.common.schema import validate_schema
19
+ from rucio.common.types import InternalAccount
20
+ from rucio.core import identity
21
+ from rucio.core import vo as vo_core
22
+ from rucio.db.sqla.constants import IdentityType
23
+ from rucio.db.sqla.session import read_session, transactional_session
24
+ from rucio.gateway.permission import has_permission
25
+
26
+ if TYPE_CHECKING:
27
+ from sqlalchemy.orm import Session
28
+
29
+
30
+ @transactional_session
31
+ def add_vo(new_vo: str, issuer: str, description: Optional[str] = None, email: Optional[str] = None, vo: str = 'def', *, session: "Session") -> None:
32
+ '''
33
+ Add a new VO.
34
+
35
+ :param new_vo: The name/tag of the VO to add (3 characters).
36
+ :param description: A description of the VO. e.g the full name or a brief description
37
+ :param email: A contact for the VO.
38
+ :param issuer: The user issuing the command.
39
+ :param vo: The vo of the user issuing the command.
40
+ :param session: The database session in use.
41
+ '''
42
+
43
+ new_vo = vo_core.map_vo(new_vo)
44
+ validate_schema('vo', new_vo, vo=vo)
45
+
46
+ kwargs = {}
47
+ if not has_permission(issuer=issuer, action='add_vo', kwargs=kwargs, vo=vo, session=session):
48
+ raise exception.AccessDenied('Account {} cannot add a VO'.format(issuer))
49
+
50
+ vo_core.add_vo(vo=new_vo, description=description, email=email, session=session)
51
+
52
+
53
+ @read_session
54
+ def list_vos(issuer: str, vo: str = 'def', *, session: "Session") -> list[dict[str, Any]]:
55
+ '''
56
+ List the VOs.
57
+
58
+ :param issuer: The user issuing the command.
59
+ :param vo: The vo of the user issuing the command.
60
+ :param session: The database session in use.
61
+ '''
62
+ kwargs = {}
63
+ if not has_permission(issuer=issuer, action='list_vos', kwargs=kwargs, vo=vo, session=session):
64
+ raise exception.AccessDenied('Account {} cannot list VOs'.format(issuer))
65
+
66
+ return vo_core.list_vos(session=session)
67
+
68
+
69
+ @transactional_session
70
+ def recover_vo_root_identity(
71
+ root_vo: str,
72
+ identity_key: str,
73
+ id_type: str,
74
+ email: str,
75
+ issuer: str,
76
+ default: bool = False,
77
+ password: Optional[str] = None,
78
+ vo: str = 'def',
79
+ *,
80
+ session: "Session"
81
+ ) -> None:
82
+ """
83
+ Adds a membership association between identity and the root account for given VO.
84
+
85
+ :param root_vo: The VO whose root needs recovery
86
+ :param identity_key: The identity key name. For example x509 DN, or a username.
87
+ :param id_type: The type of the authentication (x509, gss, userpass, ssh, saml).
88
+ :param email: The Email address associated with the identity.
89
+ :param issuer: The issuer account.
90
+ :param default: If True, the account should be used by default with the provided identity.
91
+ :param password: Password if id_type is userpass.
92
+ :param vo: the VO to act on.
93
+ :param session: The database session in use.
94
+ """
95
+ kwargs = {}
96
+ root_vo = vo_core.map_vo(root_vo)
97
+ if not has_permission(issuer=issuer, vo=vo, action='recover_vo_root_identity', kwargs=kwargs, session=session):
98
+ raise exception.AccessDenied('Account %s can not recover root identity' % (issuer))
99
+
100
+ account = InternalAccount('root', vo=root_vo)
101
+
102
+ return identity.add_account_identity(identity=identity_key, type_=IdentityType[id_type.upper()], default=default,
103
+ email=email, account=account, password=password, session=session)
104
+
105
+
106
+ @transactional_session
107
+ def update_vo(updated_vo: str, parameters: dict[str, Any], issuer: str, vo: str = 'def', *, session: "Session") -> None:
108
+ """
109
+ Update VO properties (email, description).
110
+
111
+ :param updated_vo: The VO to update.
112
+ :param parameters: A dictionary with the new properties.
113
+ :param issuer: The user issuing the command.
114
+ :param vo: The VO of the user issusing the command.
115
+ :param session: The database session in use.
116
+ """
117
+ kwargs = {}
118
+ updated_vo = vo_core.map_vo(updated_vo)
119
+ if not has_permission(issuer=issuer, action='update_vo', kwargs=kwargs, vo=vo, session=session):
120
+ raise exception.AccessDenied('Account {} cannot update VO'.format(issuer))
121
+
122
+ return vo_core.update_vo(vo=updated_vo, parameters=parameters, session=session)
rucio/rse/__init__.py ADDED
@@ -0,0 +1,96 @@
1
+ # Copyright European Organization for Nuclear Research (CERN) since 2012
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from dogpile.cache import make_region
16
+
17
+ from rucio.common.utils import is_client
18
+ from rucio.rse import rsemanager
19
+
20
+ if is_client():
21
+ setattr(rsemanager, 'CLIENT_MODE', True)
22
+ setattr(rsemanager, 'SERVER_MODE', False)
23
+ else:
24
+ setattr(rsemanager, 'CLIENT_MODE', False)
25
+ setattr(rsemanager, 'SERVER_MODE', True)
26
+
27
+
28
+ def get_rse_client(rse, vo='def', **kwarg):
29
+ '''
30
+ get_rse_client
31
+ '''
32
+ from rucio.client.rseclient import RSEClient
33
+ client = RSEClient(vo=vo)
34
+ return client.get_rse(rse)
35
+
36
+
37
+ def get_signed_url_client(rse, service, op, url, vo='def'):
38
+ '''
39
+ get_signed_url_client
40
+ '''
41
+ from rucio.client.credentialclient import CredentialClient
42
+ return CredentialClient(vo=vo).get_signed_url(rse, service, op, url)
43
+
44
+
45
+ def get_signed_url_server(rse, service, op, url, vo='def'):
46
+ '''
47
+ get_signed_url_server
48
+ '''
49
+ from rucio.core.credential import get_signed_url
50
+ from rucio.core.rse import get_rse_id
51
+
52
+ rse_id = get_rse_id(rse=rse, vo=vo)
53
+ return get_signed_url(rse_id, service, op, url)
54
+
55
+
56
+ def rse_key_generator(namespace, fn, **kwargs):
57
+ '''
58
+ Key generator for RSE
59
+ '''
60
+ def generate_key(rse, vo='def', session=None):
61
+ '''
62
+ generate_key
63
+ '''
64
+ return '{}:{}'.format(rse, vo)
65
+ return generate_key
66
+
67
+
68
+ if rsemanager.CLIENT_MODE: # pylint:disable=no-member
69
+ setattr(rsemanager, '__request_rse_info', get_rse_client)
70
+ setattr(rsemanager, '__get_signed_url', get_signed_url_client)
71
+
72
+ # Preparing region for dogpile.cache
73
+ RSE_REGION = make_region(function_key_generator=rse_key_generator).configure(
74
+ 'dogpile.cache.memory',
75
+ expiration_time=900)
76
+ setattr(rsemanager, 'RSE_REGION', RSE_REGION)
77
+
78
+
79
+ if rsemanager.SERVER_MODE: # pylint:disable=no-member
80
+ from rucio.common.cache import make_region_memcached
81
+ from rucio.core.rse import get_rse_id, get_rse_protocols
82
+ from rucio.core.vo import map_vo
83
+
84
+ def tmp_rse_info(rse=None, vo='def', rse_id=None, session=None):
85
+ if rse_id is None:
86
+ # This can be called directly by client tools if they're co-located on a server
87
+ # i.e. running rucio cli on a server and during the test suite.
88
+ # We have to map to VO name here for this situations, despite this nominally
89
+ # not being a client interface.
90
+ rse_id = get_rse_id(rse=rse, vo=map_vo(vo))
91
+ return get_rse_protocols(rse_id=rse_id, session=session)
92
+
93
+ setattr(rsemanager, '__request_rse_info', tmp_rse_info)
94
+ setattr(rsemanager, '__get_signed_url', get_signed_url_server)
95
+ RSE_REGION = make_region_memcached(expiration_time=900)
96
+ setattr(rsemanager, 'RSE_REGION', RSE_REGION)
@@ -0,0 +1,13 @@
1
+ # Copyright European Organization for Nuclear Research (CERN) since 2012
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
@@ -0,0 +1,184 @@
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 base64
16
+ import logging
17
+ import os.path
18
+ import time
19
+ from urllib.parse import parse_qs, urlencode, urlparse
20
+
21
+ from rucio.common import exception
22
+ from rucio.common.extra import import_extras
23
+ from rucio.common.utils import construct_torrent, resolve_ip
24
+ from rucio.rse import rsemanager
25
+ from rucio.rse.protocols.protocol import RSEProtocol
26
+
27
+ EXTRA_MODULES = import_extras(['libtorrent'])
28
+
29
+ lt = None
30
+ if EXTRA_MODULES['libtorrent']:
31
+ import libtorrent as lt # pylint: disable=E0401
32
+
33
+ if getattr(rsemanager, 'CLIENT_MODE', None):
34
+ from rucio.client.didclient import DIDClient
35
+
36
+ def _fetch_meta_client(rse_id: str, scope: str, name: str):
37
+ return DIDClient().get_metadata(scope=scope, name=name, plugin='all')
38
+
39
+ _fetch_meta = _fetch_meta_client
40
+ else:
41
+ from rucio.common.types import InternalScope
42
+ from rucio.core.did import get_metadata
43
+ from rucio.core.rse import get_rse_vo
44
+
45
+ def _fetch_meta_server(rse_id: str, scope: str, name: str):
46
+ vo = get_rse_vo(rse_id)
47
+ return get_metadata(scope=InternalScope(scope, vo=vo), name=name, plugin='all')
48
+
49
+ _fetch_meta = _fetch_meta_server
50
+
51
+
52
+ class Default(RSEProtocol):
53
+
54
+ def __init__(self, protocol_attr, rse_settings, logger=logging.log):
55
+ super(Default, self).__init__(protocol_attr, rse_settings, logger=logger)
56
+ self.logger = logger
57
+
58
+ def lfns2pfns(self, lfns):
59
+ pfns = {}
60
+ prefix = self.attributes['prefix']
61
+
62
+ if not prefix.startswith('/'):
63
+ prefix = ''.join(['/', prefix])
64
+ if not prefix.endswith('/'):
65
+ prefix = ''.join([prefix, '/'])
66
+
67
+ host_port = '%s:%s' % (self.attributes['hostname'], str(self.attributes['port']))
68
+
69
+ lfns = [lfns] if isinstance(lfns, dict) else lfns
70
+ for lfn in lfns:
71
+ scope, name = lfn['scope'], lfn['name']
72
+
73
+ if 'path' in lfn and lfn['path'] is not None:
74
+ path = lfn['path'] if not lfn['path'].startswith('/') else lfn['path'][1:]
75
+ else:
76
+ path = self._get_path(scope=scope, name=name)
77
+
78
+ scope_name = '%s:%s' % (scope, name)
79
+
80
+ query = {
81
+ 'x.pe': host_port,
82
+ 'x.rucio_scope': scope,
83
+ 'x.rucio_name': name,
84
+ 'x.rucio_path': ''.join((prefix, path))
85
+ }
86
+ pfns[scope_name] = 'magnet:?' + urlencode(query)
87
+
88
+ return pfns
89
+
90
+ def parse_pfns(self, pfns):
91
+ ret = dict()
92
+ pfns = [pfns] if isinstance(pfns, str) else pfns
93
+
94
+ for pfn in pfns:
95
+ parsed = urlparse(pfn)
96
+ scheme = parsed.scheme
97
+
98
+ query = parse_qs(parsed.query)
99
+ host_port = next(iter(query.get('x.pe', [])), ':')
100
+ hostname, port = host_port.split(':')
101
+ port = int(port)
102
+ path = next(iter(query.get('x.rucio_path', [])), '')
103
+ scope = next(iter(query.get('x.rucio_scope', [])), '')
104
+ name = next(iter(query.get('x.rucio_name', [])), '')
105
+
106
+ # Protect against 'lazy' defined prefixes for RSEs in the repository
107
+ if not self.attributes['prefix'].startswith('/'):
108
+ self.attributes['prefix'] = '/' + self.attributes['prefix']
109
+ if not self.attributes['prefix'].endswith('/'):
110
+ self.attributes['prefix'] += '/'
111
+
112
+ if self.attributes['hostname'] != hostname:
113
+ if self.attributes['hostname'] != 'localhost': # In the database empty hostnames are replaced with localhost but for some URIs (e.g. file) a hostname is not included
114
+ raise exception.RSEFileNameNotSupported('Invalid hostname: provided \'%s\', expected \'%s\'' % (hostname, self.attributes['hostname']))
115
+
116
+ if self.attributes['port'] != port:
117
+ raise exception.RSEFileNameNotSupported('Invalid port: provided \'%s\', expected \'%s\'' % (port, self.attributes['port']))
118
+
119
+ if not path.startswith(self.attributes['prefix']):
120
+ raise exception.RSEFileNameNotSupported('Invalid prefix: provided \'%s\', expected \'%s\'' % ('/'.join(path.split('/')[0:len(self.attributes['prefix'].split('/')) - 1]),
121
+ self.attributes['prefix'])) # len(...)-1 due to the leading '/
122
+
123
+ # Splitting parsed.path into prefix, path, filename
124
+ prefix = self.attributes['prefix']
125
+ path = path.partition(self.attributes['prefix'])[2]
126
+ path = '/'.join(path.split('/')[:-1])
127
+ if not path.startswith('/'):
128
+ path = '/' + path
129
+ if path != '/' and not path.endswith('/'):
130
+ path = path + '/'
131
+ ret[pfn] = {'path': path, 'scope': scope, 'name': name, 'scheme': scheme, 'prefix': prefix, 'port': port, 'hostname': hostname, }
132
+
133
+ return ret
134
+
135
+ def connect(self):
136
+ pass
137
+
138
+ def close(self):
139
+ pass
140
+
141
+ def get(self, path, dest, transfer_timeout=None):
142
+ if not lt:
143
+ raise exception.RucioException('The libtorrent python package is required to perform this operation')
144
+
145
+ [lfn] = self.parse_pfns([path]).values()
146
+ scope = lfn['scope']
147
+ name = lfn['name']
148
+ hostname = lfn['hostname']
149
+ port = lfn['port']
150
+
151
+ meta = _fetch_meta(rse_id=self.rse['id'], scope=scope, name=name)
152
+ pieces_root = base64.b64decode(meta.get('bittorrent_pieces_root', ''))
153
+ if not pieces_root:
154
+ raise exception.RucioException('Torrent metadata missing. Cannot download file.')
155
+
156
+ length = meta.get('bytes')
157
+ piece_length = meta.get('bittorrent_piece_length', 0)
158
+ pieces_layers = base64.b64decode(meta.get('bittorrent_pieces_layers', ''))
159
+
160
+ _, torrent = construct_torrent(
161
+ scope=scope,
162
+ name=name,
163
+ length=length,
164
+ piece_length=piece_length,
165
+ pieces_root=pieces_root,
166
+ pieces_layers=pieces_layers,
167
+ )
168
+
169
+ ses = lt.session() # type: ignore # noqa
170
+ params = {
171
+ 'ti': lt.torrent_info(torrent), # type: ignore # noqa
172
+ 'save_path': os.path.dirname(dest),
173
+ 'name': os.path.basename(dest),
174
+ 'renamed_files': {0: os.path.basename(dest)},
175
+ }
176
+
177
+ handle = ses.add_torrent(params)
178
+ try:
179
+ handle.resume()
180
+ handle.connect_peer((resolve_ip(hostname), port))
181
+ while handle.status().progress != 1.0:
182
+ time.sleep(0.25)
183
+ finally:
184
+ ses.remove_torrent(handle)