rucio 37.0.0rc1__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 (487) hide show
  1. rucio/__init__.py +17 -0
  2. rucio/alembicrevision.py +15 -0
  3. rucio/cli/__init__.py +14 -0
  4. rucio/cli/account.py +216 -0
  5. rucio/cli/bin_legacy/__init__.py +13 -0
  6. rucio/cli/bin_legacy/rucio.py +2825 -0
  7. rucio/cli/bin_legacy/rucio_admin.py +2500 -0
  8. rucio/cli/command.py +272 -0
  9. rucio/cli/config.py +72 -0
  10. rucio/cli/did.py +191 -0
  11. rucio/cli/download.py +128 -0
  12. rucio/cli/lifetime_exception.py +33 -0
  13. rucio/cli/replica.py +162 -0
  14. rucio/cli/rse.py +293 -0
  15. rucio/cli/rule.py +158 -0
  16. rucio/cli/scope.py +40 -0
  17. rucio/cli/subscription.py +73 -0
  18. rucio/cli/upload.py +60 -0
  19. rucio/cli/utils.py +226 -0
  20. rucio/client/__init__.py +15 -0
  21. rucio/client/accountclient.py +432 -0
  22. rucio/client/accountlimitclient.py +183 -0
  23. rucio/client/baseclient.py +983 -0
  24. rucio/client/client.py +120 -0
  25. rucio/client/configclient.py +126 -0
  26. rucio/client/credentialclient.py +59 -0
  27. rucio/client/didclient.py +868 -0
  28. rucio/client/diracclient.py +56 -0
  29. rucio/client/downloadclient.py +1783 -0
  30. rucio/client/exportclient.py +44 -0
  31. rucio/client/fileclient.py +50 -0
  32. rucio/client/importclient.py +42 -0
  33. rucio/client/lifetimeclient.py +90 -0
  34. rucio/client/lockclient.py +109 -0
  35. rucio/client/metaconventionsclient.py +140 -0
  36. rucio/client/pingclient.py +44 -0
  37. rucio/client/replicaclient.py +452 -0
  38. rucio/client/requestclient.py +125 -0
  39. rucio/client/richclient.py +317 -0
  40. rucio/client/rseclient.py +746 -0
  41. rucio/client/ruleclient.py +294 -0
  42. rucio/client/scopeclient.py +90 -0
  43. rucio/client/subscriptionclient.py +173 -0
  44. rucio/client/touchclient.py +82 -0
  45. rucio/client/uploadclient.py +969 -0
  46. rucio/common/__init__.py +13 -0
  47. rucio/common/bittorrent.py +234 -0
  48. rucio/common/cache.py +111 -0
  49. rucio/common/checksum.py +168 -0
  50. rucio/common/client.py +122 -0
  51. rucio/common/config.py +788 -0
  52. rucio/common/constants.py +217 -0
  53. rucio/common/constraints.py +17 -0
  54. rucio/common/didtype.py +237 -0
  55. rucio/common/dumper/__init__.py +342 -0
  56. rucio/common/dumper/consistency.py +497 -0
  57. rucio/common/dumper/data_models.py +362 -0
  58. rucio/common/dumper/path_parsing.py +75 -0
  59. rucio/common/exception.py +1208 -0
  60. rucio/common/extra.py +31 -0
  61. rucio/common/logging.py +420 -0
  62. rucio/common/pcache.py +1409 -0
  63. rucio/common/plugins.py +185 -0
  64. rucio/common/policy.py +93 -0
  65. rucio/common/schema/__init__.py +200 -0
  66. rucio/common/schema/generic.py +416 -0
  67. rucio/common/schema/generic_multi_vo.py +395 -0
  68. rucio/common/stomp_utils.py +423 -0
  69. rucio/common/stopwatch.py +55 -0
  70. rucio/common/test_rucio_server.py +154 -0
  71. rucio/common/types.py +483 -0
  72. rucio/common/utils.py +1688 -0
  73. rucio/core/__init__.py +13 -0
  74. rucio/core/account.py +496 -0
  75. rucio/core/account_counter.py +236 -0
  76. rucio/core/account_limit.py +425 -0
  77. rucio/core/authentication.py +620 -0
  78. rucio/core/config.py +437 -0
  79. rucio/core/credential.py +224 -0
  80. rucio/core/did.py +3004 -0
  81. rucio/core/did_meta_plugins/__init__.py +252 -0
  82. rucio/core/did_meta_plugins/did_column_meta.py +331 -0
  83. rucio/core/did_meta_plugins/did_meta_plugin_interface.py +165 -0
  84. rucio/core/did_meta_plugins/elasticsearch_meta.py +407 -0
  85. rucio/core/did_meta_plugins/filter_engine.py +672 -0
  86. rucio/core/did_meta_plugins/json_meta.py +240 -0
  87. rucio/core/did_meta_plugins/mongo_meta.py +229 -0
  88. rucio/core/did_meta_plugins/postgres_meta.py +352 -0
  89. rucio/core/dirac.py +237 -0
  90. rucio/core/distance.py +187 -0
  91. rucio/core/exporter.py +59 -0
  92. rucio/core/heartbeat.py +363 -0
  93. rucio/core/identity.py +301 -0
  94. rucio/core/importer.py +260 -0
  95. rucio/core/lifetime_exception.py +377 -0
  96. rucio/core/lock.py +577 -0
  97. rucio/core/message.py +288 -0
  98. rucio/core/meta_conventions.py +203 -0
  99. rucio/core/monitor.py +448 -0
  100. rucio/core/naming_convention.py +195 -0
  101. rucio/core/nongrid_trace.py +136 -0
  102. rucio/core/oidc.py +1463 -0
  103. rucio/core/permission/__init__.py +161 -0
  104. rucio/core/permission/generic.py +1124 -0
  105. rucio/core/permission/generic_multi_vo.py +1144 -0
  106. rucio/core/quarantined_replica.py +224 -0
  107. rucio/core/replica.py +4483 -0
  108. rucio/core/replica_sorter.py +362 -0
  109. rucio/core/request.py +3091 -0
  110. rucio/core/rse.py +2079 -0
  111. rucio/core/rse_counter.py +185 -0
  112. rucio/core/rse_expression_parser.py +459 -0
  113. rucio/core/rse_selector.py +304 -0
  114. rucio/core/rule.py +4484 -0
  115. rucio/core/rule_grouping.py +1620 -0
  116. rucio/core/scope.py +181 -0
  117. rucio/core/subscription.py +362 -0
  118. rucio/core/topology.py +490 -0
  119. rucio/core/trace.py +375 -0
  120. rucio/core/transfer.py +1531 -0
  121. rucio/core/vo.py +169 -0
  122. rucio/core/volatile_replica.py +151 -0
  123. rucio/daemons/__init__.py +13 -0
  124. rucio/daemons/abacus/__init__.py +13 -0
  125. rucio/daemons/abacus/account.py +116 -0
  126. rucio/daemons/abacus/collection_replica.py +124 -0
  127. rucio/daemons/abacus/rse.py +117 -0
  128. rucio/daemons/atropos/__init__.py +13 -0
  129. rucio/daemons/atropos/atropos.py +242 -0
  130. rucio/daemons/auditor/__init__.py +289 -0
  131. rucio/daemons/auditor/hdfs.py +97 -0
  132. rucio/daemons/auditor/srmdumps.py +355 -0
  133. rucio/daemons/automatix/__init__.py +13 -0
  134. rucio/daemons/automatix/automatix.py +304 -0
  135. rucio/daemons/badreplicas/__init__.py +13 -0
  136. rucio/daemons/badreplicas/minos.py +322 -0
  137. rucio/daemons/badreplicas/minos_temporary_expiration.py +171 -0
  138. rucio/daemons/badreplicas/necromancer.py +196 -0
  139. rucio/daemons/bb8/__init__.py +13 -0
  140. rucio/daemons/bb8/bb8.py +353 -0
  141. rucio/daemons/bb8/common.py +759 -0
  142. rucio/daemons/bb8/nuclei_background_rebalance.py +153 -0
  143. rucio/daemons/bb8/t2_background_rebalance.py +153 -0
  144. rucio/daemons/cache/__init__.py +13 -0
  145. rucio/daemons/cache/consumer.py +133 -0
  146. rucio/daemons/common.py +405 -0
  147. rucio/daemons/conveyor/__init__.py +13 -0
  148. rucio/daemons/conveyor/common.py +562 -0
  149. rucio/daemons/conveyor/finisher.py +529 -0
  150. rucio/daemons/conveyor/poller.py +394 -0
  151. rucio/daemons/conveyor/preparer.py +205 -0
  152. rucio/daemons/conveyor/receiver.py +179 -0
  153. rucio/daemons/conveyor/stager.py +133 -0
  154. rucio/daemons/conveyor/submitter.py +403 -0
  155. rucio/daemons/conveyor/throttler.py +532 -0
  156. rucio/daemons/follower/__init__.py +13 -0
  157. rucio/daemons/follower/follower.py +101 -0
  158. rucio/daemons/hermes/__init__.py +13 -0
  159. rucio/daemons/hermes/hermes.py +534 -0
  160. rucio/daemons/judge/__init__.py +13 -0
  161. rucio/daemons/judge/cleaner.py +159 -0
  162. rucio/daemons/judge/evaluator.py +185 -0
  163. rucio/daemons/judge/injector.py +162 -0
  164. rucio/daemons/judge/repairer.py +154 -0
  165. rucio/daemons/oauthmanager/__init__.py +13 -0
  166. rucio/daemons/oauthmanager/oauthmanager.py +198 -0
  167. rucio/daemons/reaper/__init__.py +13 -0
  168. rucio/daemons/reaper/dark_reaper.py +282 -0
  169. rucio/daemons/reaper/reaper.py +739 -0
  170. rucio/daemons/replicarecoverer/__init__.py +13 -0
  171. rucio/daemons/replicarecoverer/suspicious_replica_recoverer.py +626 -0
  172. rucio/daemons/rsedecommissioner/__init__.py +13 -0
  173. rucio/daemons/rsedecommissioner/config.py +81 -0
  174. rucio/daemons/rsedecommissioner/profiles/__init__.py +24 -0
  175. rucio/daemons/rsedecommissioner/profiles/atlas.py +60 -0
  176. rucio/daemons/rsedecommissioner/profiles/generic.py +452 -0
  177. rucio/daemons/rsedecommissioner/profiles/types.py +93 -0
  178. rucio/daemons/rsedecommissioner/rse_decommissioner.py +280 -0
  179. rucio/daemons/storage/__init__.py +13 -0
  180. rucio/daemons/storage/consistency/__init__.py +13 -0
  181. rucio/daemons/storage/consistency/actions.py +848 -0
  182. rucio/daemons/tracer/__init__.py +13 -0
  183. rucio/daemons/tracer/kronos.py +511 -0
  184. rucio/daemons/transmogrifier/__init__.py +13 -0
  185. rucio/daemons/transmogrifier/transmogrifier.py +762 -0
  186. rucio/daemons/undertaker/__init__.py +13 -0
  187. rucio/daemons/undertaker/undertaker.py +137 -0
  188. rucio/db/__init__.py +13 -0
  189. rucio/db/sqla/__init__.py +52 -0
  190. rucio/db/sqla/constants.py +206 -0
  191. rucio/db/sqla/migrate_repo/__init__.py +13 -0
  192. rucio/db/sqla/migrate_repo/env.py +110 -0
  193. rucio/db/sqla/migrate_repo/versions/01eaf73ab656_add_new_rule_notification_state_progress.py +70 -0
  194. rucio/db/sqla/migrate_repo/versions/0437a40dbfd1_add_eol_at_in_rules.py +47 -0
  195. rucio/db/sqla/migrate_repo/versions/0f1adb7a599a_create_transfer_hops_table.py +59 -0
  196. rucio/db/sqla/migrate_repo/versions/102efcf145f4_added_stuck_at_column_to_rules.py +43 -0
  197. rucio/db/sqla/migrate_repo/versions/13d4f70c66a9_introduce_transfer_limits.py +91 -0
  198. rucio/db/sqla/migrate_repo/versions/140fef722e91_cleanup_distances_table.py +76 -0
  199. rucio/db/sqla/migrate_repo/versions/14ec5aeb64cf_add_request_external_host.py +43 -0
  200. rucio/db/sqla/migrate_repo/versions/156fb5b5a14_add_request_type_to_requests_idx.py +50 -0
  201. rucio/db/sqla/migrate_repo/versions/1677d4d803c8_split_rse_availability_into_multiple.py +68 -0
  202. rucio/db/sqla/migrate_repo/versions/16a0aca82e12_create_index_on_table_replicas_path.py +40 -0
  203. rucio/db/sqla/migrate_repo/versions/1803333ac20f_adding_provenance_and_phys_group.py +45 -0
  204. rucio/db/sqla/migrate_repo/versions/1a29d6a9504c_add_didtype_chck_to_requests.py +60 -0
  205. rucio/db/sqla/migrate_repo/versions/1a80adff031a_create_index_on_rules_hist_recent.py +40 -0
  206. rucio/db/sqla/migrate_repo/versions/1c45d9730ca6_increase_identity_length.py +140 -0
  207. rucio/db/sqla/migrate_repo/versions/1d1215494e95_add_quarantined_replicas_table.py +73 -0
  208. rucio/db/sqla/migrate_repo/versions/1d96f484df21_asynchronous_rules_and_rule_approval.py +74 -0
  209. rucio/db/sqla/migrate_repo/versions/1f46c5f240ac_add_bytes_column_to_bad_replicas.py +43 -0
  210. rucio/db/sqla/migrate_repo/versions/1fc15ab60d43_add_message_history_table.py +50 -0
  211. rucio/db/sqla/migrate_repo/versions/2190e703eb6e_move_rse_settings_to_rse_attributes.py +134 -0
  212. rucio/db/sqla/migrate_repo/versions/21d6b9dc9961_add_mismatch_scheme_state_to_requests.py +64 -0
  213. rucio/db/sqla/migrate_repo/versions/22cf51430c78_add_availability_column_to_table_rses.py +39 -0
  214. rucio/db/sqla/migrate_repo/versions/22d887e4ec0a_create_sources_table.py +64 -0
  215. rucio/db/sqla/migrate_repo/versions/25821a8a45a3_remove_unique_constraint_on_requests.py +51 -0
  216. rucio/db/sqla/migrate_repo/versions/25fc855625cf_added_unique_constraint_to_rules.py +41 -0
  217. rucio/db/sqla/migrate_repo/versions/269fee20dee9_add_repair_cnt_to_locks.py +43 -0
  218. rucio/db/sqla/migrate_repo/versions/271a46ea6244_add_ignore_availability_column_to_rules.py +44 -0
  219. rucio/db/sqla/migrate_repo/versions/277b5fbb41d3_switch_heartbeats_executable.py +53 -0
  220. rucio/db/sqla/migrate_repo/versions/27e3a68927fb_remove_replicas_tombstone_and_replicas_.py +38 -0
  221. rucio/db/sqla/migrate_repo/versions/2854cd9e168_added_rule_id_column.py +47 -0
  222. rucio/db/sqla/migrate_repo/versions/295289b5a800_processed_by_and__at_in_requests.py +45 -0
  223. rucio/db/sqla/migrate_repo/versions/2962ece31cf4_add_nbaccesses_column_in_the_did_table.py +45 -0
  224. rucio/db/sqla/migrate_repo/versions/2af3291ec4c_added_replicas_history_table.py +57 -0
  225. rucio/db/sqla/migrate_repo/versions/2b69addda658_add_columns_for_third_party_copy_read_.py +45 -0
  226. rucio/db/sqla/migrate_repo/versions/2b8e7bcb4783_add_config_table.py +69 -0
  227. rucio/db/sqla/migrate_repo/versions/2ba5229cb54c_add_submitted_at_to_requests_table.py +43 -0
  228. rucio/db/sqla/migrate_repo/versions/2cbee484dcf9_added_column_volume_to_rse_transfer_.py +42 -0
  229. rucio/db/sqla/migrate_repo/versions/2edee4a83846_add_source_to_requests_and_requests_.py +47 -0
  230. rucio/db/sqla/migrate_repo/versions/2eef46be23d4_change_tokens_pk.py +46 -0
  231. rucio/db/sqla/migrate_repo/versions/2f648fc909f3_index_in_rule_history_on_scope_name.py +40 -0
  232. rucio/db/sqla/migrate_repo/versions/3082b8cef557_add_naming_convention_table_and_closed_.py +67 -0
  233. rucio/db/sqla/migrate_repo/versions/30d5206e9cad_increase_oauthrequest_redirect_msg_.py +37 -0
  234. rucio/db/sqla/migrate_repo/versions/30fa38b6434e_add_index_on_service_column_in_the_message_table.py +44 -0
  235. rucio/db/sqla/migrate_repo/versions/3152492b110b_added_staging_area_column.py +77 -0
  236. rucio/db/sqla/migrate_repo/versions/32c7d2783f7e_create_bad_replicas_table.py +60 -0
  237. rucio/db/sqla/migrate_repo/versions/3345511706b8_replicas_table_pk_definition_is_in_.py +72 -0
  238. rucio/db/sqla/migrate_repo/versions/35ef10d1e11b_change_index_on_table_requests.py +42 -0
  239. rucio/db/sqla/migrate_repo/versions/379a19b5332d_create_rse_limits_table.py +65 -0
  240. rucio/db/sqla/migrate_repo/versions/384b96aa0f60_created_rule_history_tables.py +133 -0
  241. rucio/db/sqla/migrate_repo/versions/3ac1660a1a72_extend_distance_table.py +55 -0
  242. rucio/db/sqla/migrate_repo/versions/3ad36e2268b0_create_collection_replicas_updates_table.py +76 -0
  243. rucio/db/sqla/migrate_repo/versions/3c9df354071b_extend_waiting_request_state.py +60 -0
  244. rucio/db/sqla/migrate_repo/versions/3d9813fab443_add_a_new_state_lost_in_badfilesstatus.py +44 -0
  245. rucio/db/sqla/migrate_repo/versions/40ad39ce3160_add_transferred_at_to_requests_table.py +43 -0
  246. rucio/db/sqla/migrate_repo/versions/4207be2fd914_add_notification_column_to_rules.py +64 -0
  247. rucio/db/sqla/migrate_repo/versions/42db2617c364_create_index_on_requests_external_id.py +40 -0
  248. rucio/db/sqla/migrate_repo/versions/436827b13f82_added_column_activity_to_table_requests.py +43 -0
  249. rucio/db/sqla/migrate_repo/versions/44278720f774_update_requests_typ_sta_upd_idx_index.py +44 -0
  250. rucio/db/sqla/migrate_repo/versions/45378a1e76a8_create_collection_replica_table.py +78 -0
  251. rucio/db/sqla/migrate_repo/versions/469d262be19_removing_created_at_index.py +41 -0
  252. rucio/db/sqla/migrate_repo/versions/4783c1f49cb4_create_distance_table.py +59 -0
  253. rucio/db/sqla/migrate_repo/versions/49a21b4d4357_create_index_on_table_tokens.py +44 -0
  254. rucio/db/sqla/migrate_repo/versions/4a2cbedda8b9_add_source_replica_expression_column_to_.py +43 -0
  255. rucio/db/sqla/migrate_repo/versions/4a7182d9578b_added_bytes_length_accessed_at_columns.py +49 -0
  256. rucio/db/sqla/migrate_repo/versions/4bab9edd01fc_create_index_on_requests_rule_id.py +40 -0
  257. rucio/db/sqla/migrate_repo/versions/4c3a4acfe006_new_attr_account_table.py +63 -0
  258. rucio/db/sqla/migrate_repo/versions/4cf0a2e127d4_adding_transient_metadata.py +43 -0
  259. rucio/db/sqla/migrate_repo/versions/4df2c5ddabc0_remove_temporary_dids.py +55 -0
  260. rucio/db/sqla/migrate_repo/versions/50280c53117c_add_qos_class_to_rse.py +45 -0
  261. rucio/db/sqla/migrate_repo/versions/52153819589c_add_rse_id_to_replicas_table.py +43 -0
  262. rucio/db/sqla/migrate_repo/versions/52fd9f4916fa_added_activity_to_rules.py +43 -0
  263. rucio/db/sqla/migrate_repo/versions/53b479c3cb0f_fix_did_meta_table_missing_updated_at_.py +45 -0
  264. rucio/db/sqla/migrate_repo/versions/5673b4b6e843_add_wfms_metadata_to_rule_tables.py +47 -0
  265. rucio/db/sqla/migrate_repo/versions/575767d9f89_added_source_history_table.py +58 -0
  266. rucio/db/sqla/migrate_repo/versions/58bff7008037_add_started_at_to_requests.py +45 -0
  267. rucio/db/sqla/migrate_repo/versions/58c8b78301ab_rename_callback_to_message.py +106 -0
  268. rucio/db/sqla/migrate_repo/versions/5f139f77382a_added_child_rule_id_column.py +55 -0
  269. rucio/db/sqla/migrate_repo/versions/688ef1840840_adding_did_meta_table.py +50 -0
  270. rucio/db/sqla/migrate_repo/versions/6e572a9bfbf3_add_new_split_container_column_to_rules.py +47 -0
  271. rucio/db/sqla/migrate_repo/versions/70587619328_add_comment_column_for_subscriptions.py +43 -0
  272. rucio/db/sqla/migrate_repo/versions/739064d31565_remove_history_table_pks.py +41 -0
  273. rucio/db/sqla/migrate_repo/versions/7541902bf173_add_didsfollowed_and_followevents_table.py +91 -0
  274. rucio/db/sqla/migrate_repo/versions/7ec22226cdbf_new_replica_state_for_temporary_.py +72 -0
  275. rucio/db/sqla/migrate_repo/versions/810a41685bc1_added_columns_rse_transfer_limits.py +49 -0
  276. rucio/db/sqla/migrate_repo/versions/83f991c63a93_correct_rse_expression_length.py +43 -0
  277. rucio/db/sqla/migrate_repo/versions/8523998e2e76_increase_size_of_extended_attributes_.py +43 -0
  278. rucio/db/sqla/migrate_repo/versions/8ea9122275b1_adding_missing_function_based_indices.py +53 -0
  279. rucio/db/sqla/migrate_repo/versions/90f47792bb76_add_clob_payload_to_messages.py +45 -0
  280. rucio/db/sqla/migrate_repo/versions/914b8f02df38_new_table_for_lifetime_model_exceptions.py +68 -0
  281. rucio/db/sqla/migrate_repo/versions/94a5961ddbf2_add_estimator_columns.py +45 -0
  282. rucio/db/sqla/migrate_repo/versions/9a1b149a2044_add_saml_identity_type.py +94 -0
  283. rucio/db/sqla/migrate_repo/versions/9a45bc4ea66d_add_vp_table.py +54 -0
  284. rucio/db/sqla/migrate_repo/versions/9eb936a81eb1_true_is_true.py +72 -0
  285. rucio/db/sqla/migrate_repo/versions/a08fa8de1545_transfer_stats_table.py +55 -0
  286. rucio/db/sqla/migrate_repo/versions/a118956323f8_added_vo_table_and_vo_col_to_rse.py +76 -0
  287. rucio/db/sqla/migrate_repo/versions/a193a275255c_add_status_column_in_messages.py +47 -0
  288. rucio/db/sqla/migrate_repo/versions/a5f6f6e928a7_1_7_0.py +121 -0
  289. rucio/db/sqla/migrate_repo/versions/a616581ee47_added_columns_to_table_requests.py +59 -0
  290. rucio/db/sqla/migrate_repo/versions/a6eb23955c28_state_idx_non_functional.py +52 -0
  291. rucio/db/sqla/migrate_repo/versions/a74275a1ad30_added_global_quota_table.py +54 -0
  292. rucio/db/sqla/migrate_repo/versions/a93e4e47bda_heartbeats.py +64 -0
  293. rucio/db/sqla/migrate_repo/versions/ae2a56fcc89_added_comment_column_to_rules.py +49 -0
  294. rucio/db/sqla/migrate_repo/versions/b0070f3695c8_add_deletedidmeta_table.py +57 -0
  295. rucio/db/sqla/migrate_repo/versions/b4293a99f344_added_column_identity_to_table_tokens.py +43 -0
  296. rucio/db/sqla/migrate_repo/versions/b5493606bbf5_fix_primary_key_for_subscription_history.py +41 -0
  297. rucio/db/sqla/migrate_repo/versions/b7d287de34fd_removal_of_replicastate_source.py +91 -0
  298. rucio/db/sqla/migrate_repo/versions/b818052fa670_add_index_to_quarantined_replicas.py +40 -0
  299. rucio/db/sqla/migrate_repo/versions/b8caac94d7f0_add_comments_column_for_subscriptions_.py +43 -0
  300. rucio/db/sqla/migrate_repo/versions/b96a1c7e1cc4_new_bad_pfns_table_and_bad_replicas_.py +143 -0
  301. rucio/db/sqla/migrate_repo/versions/bb695f45c04_extend_request_state.py +76 -0
  302. rucio/db/sqla/migrate_repo/versions/bc68e9946deb_add_staging_timestamps_to_request.py +50 -0
  303. rucio/db/sqla/migrate_repo/versions/bf3baa1c1474_correct_pk_and_idx_for_history_tables.py +72 -0
  304. rucio/db/sqla/migrate_repo/versions/c0937668555f_add_qos_policy_map_table.py +55 -0
  305. rucio/db/sqla/migrate_repo/versions/c129ccdb2d5_add_lumiblocknr_to_dids.py +43 -0
  306. rucio/db/sqla/migrate_repo/versions/ccdbcd48206e_add_did_type_column_index_on_did_meta_.py +65 -0
  307. rucio/db/sqla/migrate_repo/versions/cebad904c4dd_new_payload_column_for_heartbeats.py +47 -0
  308. rucio/db/sqla/migrate_repo/versions/d1189a09c6e0_oauth2_0_and_jwt_feature_support_adding_.py +146 -0
  309. rucio/db/sqla/migrate_repo/versions/d23453595260_extend_request_state_for_preparer.py +104 -0
  310. rucio/db/sqla/migrate_repo/versions/d6dceb1de2d_added_purge_column_to_rules.py +44 -0
  311. rucio/db/sqla/migrate_repo/versions/d6e2c3b2cf26_remove_third_party_copy_column_from_rse.py +43 -0
  312. rucio/db/sqla/migrate_repo/versions/d91002c5841_new_account_limits_table.py +103 -0
  313. rucio/db/sqla/migrate_repo/versions/e138c364ebd0_extending_columns_for_filter_and_.py +49 -0
  314. rucio/db/sqla/migrate_repo/versions/e59300c8b179_support_for_archive.py +104 -0
  315. rucio/db/sqla/migrate_repo/versions/f1b14a8c2ac1_postgres_use_check_constraints.py +29 -0
  316. rucio/db/sqla/migrate_repo/versions/f41ffe206f37_oracle_global_temporary_tables.py +74 -0
  317. rucio/db/sqla/migrate_repo/versions/f85a2962b021_adding_transfertool_column_to_requests_.py +47 -0
  318. rucio/db/sqla/migrate_repo/versions/fa7a7d78b602_increase_refresh_token_size.py +43 -0
  319. rucio/db/sqla/migrate_repo/versions/fb28a95fe288_add_replicas_rse_id_tombstone_idx.py +37 -0
  320. rucio/db/sqla/migrate_repo/versions/fe1a65b176c9_set_third_party_copy_read_and_write_.py +43 -0
  321. rucio/db/sqla/migrate_repo/versions/fe8ea2fa9788_added_third_party_copy_column_to_rse_.py +43 -0
  322. rucio/db/sqla/models.py +1743 -0
  323. rucio/db/sqla/sautils.py +55 -0
  324. rucio/db/sqla/session.py +529 -0
  325. rucio/db/sqla/types.py +206 -0
  326. rucio/db/sqla/util.py +543 -0
  327. rucio/gateway/__init__.py +13 -0
  328. rucio/gateway/account.py +345 -0
  329. rucio/gateway/account_limit.py +363 -0
  330. rucio/gateway/authentication.py +381 -0
  331. rucio/gateway/config.py +227 -0
  332. rucio/gateway/credential.py +70 -0
  333. rucio/gateway/did.py +987 -0
  334. rucio/gateway/dirac.py +83 -0
  335. rucio/gateway/exporter.py +60 -0
  336. rucio/gateway/heartbeat.py +76 -0
  337. rucio/gateway/identity.py +189 -0
  338. rucio/gateway/importer.py +46 -0
  339. rucio/gateway/lifetime_exception.py +121 -0
  340. rucio/gateway/lock.py +153 -0
  341. rucio/gateway/meta_conventions.py +98 -0
  342. rucio/gateway/permission.py +74 -0
  343. rucio/gateway/quarantined_replica.py +79 -0
  344. rucio/gateway/replica.py +538 -0
  345. rucio/gateway/request.py +330 -0
  346. rucio/gateway/rse.py +632 -0
  347. rucio/gateway/rule.py +437 -0
  348. rucio/gateway/scope.py +100 -0
  349. rucio/gateway/subscription.py +280 -0
  350. rucio/gateway/vo.py +126 -0
  351. rucio/rse/__init__.py +96 -0
  352. rucio/rse/protocols/__init__.py +13 -0
  353. rucio/rse/protocols/bittorrent.py +194 -0
  354. rucio/rse/protocols/cache.py +111 -0
  355. rucio/rse/protocols/dummy.py +100 -0
  356. rucio/rse/protocols/gfal.py +708 -0
  357. rucio/rse/protocols/globus.py +243 -0
  358. rucio/rse/protocols/http_cache.py +82 -0
  359. rucio/rse/protocols/mock.py +123 -0
  360. rucio/rse/protocols/ngarc.py +209 -0
  361. rucio/rse/protocols/posix.py +250 -0
  362. rucio/rse/protocols/protocol.py +361 -0
  363. rucio/rse/protocols/rclone.py +365 -0
  364. rucio/rse/protocols/rfio.py +145 -0
  365. rucio/rse/protocols/srm.py +338 -0
  366. rucio/rse/protocols/ssh.py +414 -0
  367. rucio/rse/protocols/storm.py +195 -0
  368. rucio/rse/protocols/webdav.py +594 -0
  369. rucio/rse/protocols/xrootd.py +302 -0
  370. rucio/rse/rsemanager.py +881 -0
  371. rucio/rse/translation.py +260 -0
  372. rucio/tests/__init__.py +13 -0
  373. rucio/tests/common.py +280 -0
  374. rucio/tests/common_server.py +149 -0
  375. rucio/transfertool/__init__.py +13 -0
  376. rucio/transfertool/bittorrent.py +200 -0
  377. rucio/transfertool/bittorrent_driver.py +50 -0
  378. rucio/transfertool/bittorrent_driver_qbittorrent.py +134 -0
  379. rucio/transfertool/fts3.py +1600 -0
  380. rucio/transfertool/fts3_plugins.py +152 -0
  381. rucio/transfertool/globus.py +201 -0
  382. rucio/transfertool/globus_library.py +181 -0
  383. rucio/transfertool/mock.py +89 -0
  384. rucio/transfertool/transfertool.py +221 -0
  385. rucio/vcsversion.py +11 -0
  386. rucio/version.py +45 -0
  387. rucio/web/__init__.py +13 -0
  388. rucio/web/rest/__init__.py +13 -0
  389. rucio/web/rest/flaskapi/__init__.py +13 -0
  390. rucio/web/rest/flaskapi/authenticated_bp.py +27 -0
  391. rucio/web/rest/flaskapi/v1/__init__.py +13 -0
  392. rucio/web/rest/flaskapi/v1/accountlimits.py +236 -0
  393. rucio/web/rest/flaskapi/v1/accounts.py +1103 -0
  394. rucio/web/rest/flaskapi/v1/archives.py +102 -0
  395. rucio/web/rest/flaskapi/v1/auth.py +1644 -0
  396. rucio/web/rest/flaskapi/v1/common.py +426 -0
  397. rucio/web/rest/flaskapi/v1/config.py +304 -0
  398. rucio/web/rest/flaskapi/v1/credentials.py +213 -0
  399. rucio/web/rest/flaskapi/v1/dids.py +2340 -0
  400. rucio/web/rest/flaskapi/v1/dirac.py +116 -0
  401. rucio/web/rest/flaskapi/v1/export.py +75 -0
  402. rucio/web/rest/flaskapi/v1/heartbeats.py +127 -0
  403. rucio/web/rest/flaskapi/v1/identities.py +285 -0
  404. rucio/web/rest/flaskapi/v1/import.py +132 -0
  405. rucio/web/rest/flaskapi/v1/lifetime_exceptions.py +312 -0
  406. rucio/web/rest/flaskapi/v1/locks.py +358 -0
  407. rucio/web/rest/flaskapi/v1/main.py +91 -0
  408. rucio/web/rest/flaskapi/v1/meta_conventions.py +241 -0
  409. rucio/web/rest/flaskapi/v1/metrics.py +36 -0
  410. rucio/web/rest/flaskapi/v1/nongrid_traces.py +97 -0
  411. rucio/web/rest/flaskapi/v1/ping.py +88 -0
  412. rucio/web/rest/flaskapi/v1/redirect.py +366 -0
  413. rucio/web/rest/flaskapi/v1/replicas.py +1894 -0
  414. rucio/web/rest/flaskapi/v1/requests.py +998 -0
  415. rucio/web/rest/flaskapi/v1/rses.py +2250 -0
  416. rucio/web/rest/flaskapi/v1/rules.py +854 -0
  417. rucio/web/rest/flaskapi/v1/scopes.py +159 -0
  418. rucio/web/rest/flaskapi/v1/subscriptions.py +650 -0
  419. rucio/web/rest/flaskapi/v1/templates/auth_crash.html +80 -0
  420. rucio/web/rest/flaskapi/v1/templates/auth_granted.html +82 -0
  421. rucio/web/rest/flaskapi/v1/traces.py +137 -0
  422. rucio/web/rest/flaskapi/v1/types.py +20 -0
  423. rucio/web/rest/flaskapi/v1/vos.py +278 -0
  424. rucio/web/rest/main.py +18 -0
  425. rucio/web/rest/metrics.py +27 -0
  426. rucio/web/rest/ping.py +27 -0
  427. rucio-37.0.0rc1.data/data/rucio/etc/alembic.ini.template +71 -0
  428. rucio-37.0.0rc1.data/data/rucio/etc/alembic_offline.ini.template +74 -0
  429. rucio-37.0.0rc1.data/data/rucio/etc/globus-config.yml.template +5 -0
  430. rucio-37.0.0rc1.data/data/rucio/etc/ldap.cfg.template +30 -0
  431. rucio-37.0.0rc1.data/data/rucio/etc/mail_templates/rule_approval_request.tmpl +38 -0
  432. rucio-37.0.0rc1.data/data/rucio/etc/mail_templates/rule_approved_admin.tmpl +4 -0
  433. rucio-37.0.0rc1.data/data/rucio/etc/mail_templates/rule_approved_user.tmpl +17 -0
  434. rucio-37.0.0rc1.data/data/rucio/etc/mail_templates/rule_denied_admin.tmpl +6 -0
  435. rucio-37.0.0rc1.data/data/rucio/etc/mail_templates/rule_denied_user.tmpl +17 -0
  436. rucio-37.0.0rc1.data/data/rucio/etc/mail_templates/rule_ok_notification.tmpl +19 -0
  437. rucio-37.0.0rc1.data/data/rucio/etc/rse-accounts.cfg.template +25 -0
  438. rucio-37.0.0rc1.data/data/rucio/etc/rucio.cfg.atlas.client.template +43 -0
  439. rucio-37.0.0rc1.data/data/rucio/etc/rucio.cfg.template +241 -0
  440. rucio-37.0.0rc1.data/data/rucio/etc/rucio_multi_vo.cfg.template +217 -0
  441. rucio-37.0.0rc1.data/data/rucio/requirements.server.txt +297 -0
  442. rucio-37.0.0rc1.data/data/rucio/tools/bootstrap.py +34 -0
  443. rucio-37.0.0rc1.data/data/rucio/tools/merge_rucio_configs.py +144 -0
  444. rucio-37.0.0rc1.data/data/rucio/tools/reset_database.py +40 -0
  445. rucio-37.0.0rc1.data/scripts/rucio +133 -0
  446. rucio-37.0.0rc1.data/scripts/rucio-abacus-account +74 -0
  447. rucio-37.0.0rc1.data/scripts/rucio-abacus-collection-replica +46 -0
  448. rucio-37.0.0rc1.data/scripts/rucio-abacus-rse +78 -0
  449. rucio-37.0.0rc1.data/scripts/rucio-admin +97 -0
  450. rucio-37.0.0rc1.data/scripts/rucio-atropos +60 -0
  451. rucio-37.0.0rc1.data/scripts/rucio-auditor +206 -0
  452. rucio-37.0.0rc1.data/scripts/rucio-automatix +50 -0
  453. rucio-37.0.0rc1.data/scripts/rucio-bb8 +57 -0
  454. rucio-37.0.0rc1.data/scripts/rucio-cache-client +141 -0
  455. rucio-37.0.0rc1.data/scripts/rucio-cache-consumer +42 -0
  456. rucio-37.0.0rc1.data/scripts/rucio-conveyor-finisher +58 -0
  457. rucio-37.0.0rc1.data/scripts/rucio-conveyor-poller +66 -0
  458. rucio-37.0.0rc1.data/scripts/rucio-conveyor-preparer +37 -0
  459. rucio-37.0.0rc1.data/scripts/rucio-conveyor-receiver +44 -0
  460. rucio-37.0.0rc1.data/scripts/rucio-conveyor-stager +76 -0
  461. rucio-37.0.0rc1.data/scripts/rucio-conveyor-submitter +139 -0
  462. rucio-37.0.0rc1.data/scripts/rucio-conveyor-throttler +104 -0
  463. rucio-37.0.0rc1.data/scripts/rucio-dark-reaper +53 -0
  464. rucio-37.0.0rc1.data/scripts/rucio-dumper +160 -0
  465. rucio-37.0.0rc1.data/scripts/rucio-follower +44 -0
  466. rucio-37.0.0rc1.data/scripts/rucio-hermes +54 -0
  467. rucio-37.0.0rc1.data/scripts/rucio-judge-cleaner +89 -0
  468. rucio-37.0.0rc1.data/scripts/rucio-judge-evaluator +137 -0
  469. rucio-37.0.0rc1.data/scripts/rucio-judge-injector +44 -0
  470. rucio-37.0.0rc1.data/scripts/rucio-judge-repairer +44 -0
  471. rucio-37.0.0rc1.data/scripts/rucio-kronos +44 -0
  472. rucio-37.0.0rc1.data/scripts/rucio-minos +53 -0
  473. rucio-37.0.0rc1.data/scripts/rucio-minos-temporary-expiration +50 -0
  474. rucio-37.0.0rc1.data/scripts/rucio-necromancer +120 -0
  475. rucio-37.0.0rc1.data/scripts/rucio-oauth-manager +63 -0
  476. rucio-37.0.0rc1.data/scripts/rucio-reaper +83 -0
  477. rucio-37.0.0rc1.data/scripts/rucio-replica-recoverer +248 -0
  478. rucio-37.0.0rc1.data/scripts/rucio-rse-decommissioner +66 -0
  479. rucio-37.0.0rc1.data/scripts/rucio-storage-consistency-actions +74 -0
  480. rucio-37.0.0rc1.data/scripts/rucio-transmogrifier +77 -0
  481. rucio-37.0.0rc1.data/scripts/rucio-undertaker +76 -0
  482. rucio-37.0.0rc1.dist-info/METADATA +92 -0
  483. rucio-37.0.0rc1.dist-info/RECORD +487 -0
  484. rucio-37.0.0rc1.dist-info/WHEEL +5 -0
  485. rucio-37.0.0rc1.dist-info/licenses/AUTHORS.rst +100 -0
  486. rucio-37.0.0rc1.dist-info/licenses/LICENSE +201 -0
  487. rucio-37.0.0rc1.dist-info/top_level.txt +1 -0
rucio/gateway/did.py ADDED
@@ -0,0 +1,987 @@
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 copy import deepcopy
16
+ from typing import TYPE_CHECKING, Any, Optional
17
+
18
+ import rucio.gateway.permission
19
+ from rucio.common.constants import RESERVED_KEYS
20
+ from rucio.common.exception import AccessDenied, InvalidObject, RucioException
21
+ from rucio.common.schema import validate_schema
22
+ from rucio.common.types import InternalAccount, InternalScope
23
+ from rucio.common.utils import gateway_update_return_dict
24
+ from rucio.core import did, naming_convention
25
+ from rucio.core import meta_conventions as meta_convention_core
26
+ from rucio.core.rse import get_rse_id
27
+ from rucio.db.sqla.constants import DIDType
28
+ from rucio.db.sqla.session import read_session, stream_session, transactional_session
29
+
30
+ if TYPE_CHECKING:
31
+ from collections.abc import Iterable, Iterator, Mapping, Sequence
32
+
33
+ from sqlalchemy.orm import Session
34
+
35
+
36
+ @stream_session
37
+ def list_dids(
38
+ scope: str,
39
+ filters: 'Mapping[Any, Any]',
40
+ did_type: str = 'collection',
41
+ ignore_case: bool = False,
42
+ limit: Optional[int] = None,
43
+ offset: Optional[int] = None,
44
+ long: bool = False,
45
+ recursive: bool = False,
46
+ vo: str = 'def',
47
+ *,
48
+ session: "Session"
49
+ ) -> 'Iterator[dict[str, Any]]':
50
+ """
51
+ List dids in a scope.
52
+
53
+ :param scope: The scope name.
54
+ :param filters: Filter arguments in form supported by the filter engine.
55
+ :param did_type: The type of the did: all(container, dataset, file), collection(dataset or container), dataset, container
56
+ :param ignore_case: Ignore case distinctions.
57
+ :param limit: The maximum number of DIDs returned.
58
+ :param offset: Offset number.
59
+ :param long: Long format option to display more information for each DID.
60
+ :param recursive: Recursively list DIDs content.
61
+ :param vo: The VO to act on.
62
+ :param session: The database session in use.
63
+ """
64
+ internal_scope = InternalScope(scope, vo=vo)
65
+
66
+ # replace account and scope in filters with internal representation
67
+ for or_group in filters:
68
+ if 'account' in or_group:
69
+ or_group['account'] = InternalAccount(or_group['account'], vo=vo)
70
+ if 'scope' in or_group:
71
+ or_group['account'] = InternalScope(or_group['scope'], vo=vo)
72
+
73
+ result = did.list_dids(scope=internal_scope, filters=filters, did_type=did_type, ignore_case=ignore_case,
74
+ limit=limit, offset=offset, long=long, recursive=recursive, session=session)
75
+
76
+ for d in result:
77
+ yield gateway_update_return_dict(d, session=session)
78
+
79
+
80
+ @transactional_session
81
+ def add_did(
82
+ scope: str,
83
+ name: str,
84
+ did_type: str,
85
+ issuer: str,
86
+ account: Optional[str] = None,
87
+ statuses: Optional[dict[str, str]] = None,
88
+ meta: Optional[dict[str, str]] = None,
89
+ rules: Optional['Sequence[dict[str, Any]]'] = None,
90
+ lifetime: Optional[str] = None,
91
+ dids: Optional['Sequence[dict[str, Any]]'] = None,
92
+ rse: Optional[str] = None,
93
+ vo: str = 'def',
94
+ *,
95
+ session: "Session"
96
+ ) -> None:
97
+ """
98
+ Add data did.
99
+
100
+ :param scope: The scope name.
101
+ :param name: The data identifier name.
102
+ :param did_type: The data identifier type.
103
+ :param issuer: The issuer account.
104
+ :param account: The account owner. If None, then issuer is selected as owner.
105
+ :param statuses: Dictionary with statuses, e.g.g {'monotonic':True}.
106
+ :meta: Meta-data associated with the data identifier is represented using key/value pairs in a dictionary.
107
+ :rules: Replication rules associated with the data did. A list of dictionaries, e.g., [{'copies': 2, 'rse_expression': 'TIERS1'}, ].
108
+ :param lifetime: DID's lifetime (in seconds).
109
+ :param dids: The content.
110
+ :param rse: The RSE name when registering replicas.
111
+ :param vo: The VO to act on.
112
+ :param session: The database session in use.
113
+ """
114
+ statuses = statuses or {}
115
+ meta = meta or {}
116
+ rules = rules or []
117
+ dids = dids or []
118
+ v_did = {'name': name, 'type': did_type.upper(), 'scope': scope}
119
+ validate_schema(name='did', obj=v_did, vo=vo)
120
+ validate_schema(name='dids', obj=dids, vo=vo)
121
+ validate_schema(name='rse', obj=rse, vo=vo)
122
+ kwargs = {'scope': scope, 'name': name, 'type': did_type, 'issuer': issuer, 'account': account, 'statuses': statuses, 'meta': meta, 'rules': rules, 'lifetime': lifetime}
123
+ auth_result = rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='add_did', kwargs=kwargs, session=session)
124
+ if not auth_result.allowed:
125
+ raise AccessDenied('Account %s can not add data identifier to scope %s. %s' % (issuer, scope, auth_result.message))
126
+
127
+ owner_account = None if account is None else InternalAccount(account, vo=vo)
128
+ issuer_account = InternalAccount(issuer, vo=vo)
129
+ internal_scope = InternalScope(scope, vo=vo)
130
+ for d in dids:
131
+ d['scope'] = InternalScope(d['scope'], vo=vo)
132
+ for r in rules:
133
+ r['account'] = InternalAccount(r['account'], vo=vo)
134
+
135
+ rse_id = None
136
+ if rse is not None:
137
+ rse_id = get_rse_id(rse=rse, vo=vo, session=session)
138
+
139
+ if did_type == 'DATASET':
140
+ # naming_convention validation
141
+ extra_meta = naming_convention.validate_name(scope=internal_scope, name=name, did_type='D', session=session)
142
+
143
+ # merge extra_meta with meta
144
+ for k in extra_meta or {}:
145
+ if k not in meta:
146
+ meta[k] = extra_meta[k]
147
+ elif meta[k] != extra_meta[k]:
148
+ print("Provided metadata %s doesn't match the naming convention: %s != %s" % (k, meta[k], extra_meta[k]))
149
+ raise InvalidObject("Provided metadata %s doesn't match the naming convention: %s != %s" % (k, meta[k], extra_meta[k]))
150
+
151
+ # Validate metadata
152
+ meta_convention_core.validate_meta(meta=meta, did_type=DIDType[did_type.upper()], session=session)
153
+
154
+ return did.add_did(scope=internal_scope, name=name, did_type=DIDType[did_type.upper()], account=owner_account or issuer_account,
155
+ statuses=statuses, meta=meta, rules=rules, lifetime=lifetime,
156
+ dids=dids, rse_id=rse_id, session=session)
157
+
158
+
159
+ @transactional_session
160
+ def add_dids(
161
+ dids: 'Sequence[dict[str, Any]]',
162
+ issuer: str,
163
+ vo: str = 'def',
164
+ *,
165
+ session: "Session"
166
+ ) -> None:
167
+ """
168
+ Bulk Add did.
169
+
170
+ :param dids: A list of dids.
171
+ :param issuer: The issuer account.
172
+ :param vo: The VO to act on.
173
+ :param session: The database session in use.
174
+ """
175
+ for d in dids:
176
+ if 'rse' in d:
177
+ rse_id = None
178
+ if d['rse'] is not None:
179
+ rse_id = get_rse_id(rse=d['rse'], vo=vo, session=session)
180
+ d['rse_id'] = rse_id
181
+
182
+ kwargs = {'issuer': issuer, 'dids': dids}
183
+ auth_result = rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='add_dids', kwargs=kwargs, session=session)
184
+ if not auth_result.allowed:
185
+ raise AccessDenied('Account %s can not bulk add data identifier. %s' % (issuer, auth_result.message))
186
+
187
+ issuer_account = InternalAccount(issuer, vo=vo)
188
+ for d in dids:
189
+ d['scope'] = InternalScope(d['scope'], vo=vo)
190
+ if 'account' in d.keys():
191
+ d['account'] = InternalAccount(d['account'], vo=vo)
192
+ if 'dids' in d.keys():
193
+ for child in d['dids']:
194
+ child['scope'] = InternalScope(child['scope'], vo=vo)
195
+ return did.add_dids(dids, account=issuer_account, session=session)
196
+
197
+
198
+ @transactional_session
199
+ def attach_dids(
200
+ scope: str,
201
+ name: str,
202
+ attachment: dict[str, Any],
203
+ issuer: str,
204
+ vo='def',
205
+ *,
206
+ session: "Session"
207
+ ) -> None:
208
+ """
209
+ Append content to data did.
210
+
211
+ :param attachment: The attachment.
212
+ :param issuer: The issuer account.
213
+ :param vo: The VO to act on.
214
+ :param session: The database session in use.
215
+ """
216
+ validate_schema(name='attachment', obj=attachment, vo=vo)
217
+
218
+ rse_id = None
219
+ if 'rse' in attachment:
220
+ if attachment['rse'] is not None:
221
+ rse_id = get_rse_id(rse=attachment['rse'], vo=vo, session=session)
222
+ attachment['rse_id'] = rse_id
223
+
224
+ kwargs = {'scope': scope, 'name': name, 'attachment': attachment}
225
+ auth_result = rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='attach_dids', kwargs=kwargs, session=session)
226
+ if not auth_result.allowed:
227
+ raise AccessDenied('Account %s can not add data identifiers to %s:%s. %s' % (issuer, scope, name, auth_result.message))
228
+
229
+ internal_scope = InternalScope(scope, vo=vo)
230
+ issuer_account = InternalAccount(issuer, vo=vo)
231
+ if 'account' in attachment.keys():
232
+ attachment['account'] = InternalAccount(attachment['account'], vo=vo)
233
+ for d in attachment['dids']:
234
+ d['scope'] = InternalScope(d['scope'], vo=vo)
235
+ if 'account' in d.keys():
236
+ d['account'] = InternalAccount(d['account'], vo=vo)
237
+
238
+ if rse_id is not None:
239
+ dids = did.attach_dids(scope=internal_scope, name=name, dids=attachment['dids'],
240
+ account=attachment.get('account', issuer_account), rse_id=rse_id, session=session)
241
+ else:
242
+ dids = did.attach_dids(scope=internal_scope, name=name, dids=attachment['dids'],
243
+ account=attachment.get('account', issuer_account), session=session)
244
+
245
+ return dids
246
+
247
+
248
+ @transactional_session
249
+ def attach_dids_to_dids(
250
+ attachments: 'Sequence[dict[str, Any]]',
251
+ issuer: str,
252
+ ignore_duplicate: bool = False,
253
+ vo: str = 'def',
254
+ *,
255
+ session: "Session"
256
+ ) -> None:
257
+ """
258
+ Append content to dids.
259
+
260
+ :param attachments: The contents.
261
+ :param issuer: The issuer account.
262
+ :param ignore_duplicate: If True, ignore duplicate entries.
263
+ :param vo: The VO to act on.
264
+ :param session: The database session in use.
265
+ """
266
+ validate_schema(name='attachments', obj=attachments, vo=vo)
267
+
268
+ for a in attachments:
269
+ if 'rse' in a:
270
+ rse_id = None
271
+ if a['rse'] is not None:
272
+ rse_id = get_rse_id(rse=a['rse'], vo=vo, session=session)
273
+ a['rse_id'] = rse_id
274
+
275
+ auth_result = rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='attach_dids_to_dids', kwargs={'attachments': attachments}, session=session)
276
+ if not auth_result.allowed:
277
+ raise AccessDenied('Account %s can not add data identifiers. %s' % (issuer, auth_result.message))
278
+
279
+ issuer_account = InternalAccount(issuer, vo=vo)
280
+ for attachment in attachments:
281
+ attachment['scope'] = InternalScope(attachment['scope'], vo=vo)
282
+ for d in attachment['dids']:
283
+ d['scope'] = InternalScope(d['scope'], vo=vo)
284
+ if 'account' in d.keys():
285
+ d['account'] = InternalAccount(d['account'], vo=vo)
286
+
287
+ return did.attach_dids_to_dids(attachments=attachments, account=issuer_account,
288
+ ignore_duplicate=ignore_duplicate, session=session)
289
+
290
+
291
+ @transactional_session
292
+ def detach_dids(
293
+ scope: str,
294
+ name: str,
295
+ dids: 'Sequence[dict[str, Any]]',
296
+ issuer: str,
297
+ vo: str = 'def',
298
+ *,
299
+ session: "Session"
300
+ ) -> None:
301
+ """
302
+ Detach data identifier
303
+
304
+ :param scope: The scope name.
305
+ :param name: The data identifier name.
306
+ :param dids: The content.
307
+ :param issuer: The issuer account.
308
+ :param vo: The VO to act on.
309
+ :param session: The database session in use.
310
+ """
311
+ kwargs = {'scope': scope, 'name': name, 'dids': dids, 'issuer': issuer}
312
+ auth_result = rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='detach_dids', kwargs=kwargs, session=session)
313
+ if not auth_result.allowed:
314
+ raise AccessDenied('Account %s can not detach data identifiers from %s:%s. %s' % (issuer, scope, name, auth_result.message))
315
+
316
+ internal_scope = InternalScope(scope, vo=vo)
317
+ for d in dids:
318
+ d['scope'] = InternalScope(d['scope'], vo=vo)
319
+
320
+ return did.detach_dids(scope=internal_scope, name=name, dids=dids, session=session)
321
+
322
+
323
+ @stream_session
324
+ def list_new_dids(
325
+ did_type: Optional[str] = None,
326
+ thread: Optional[int] = None,
327
+ total_threads: Optional[int] = None,
328
+ chunk_size: int = 1000,
329
+ vo: str = 'def',
330
+ *,
331
+ session: "Session"
332
+ ) -> 'Iterator[dict[str, Any]]':
333
+ """
334
+ List recent identifiers.
335
+
336
+ :param did_type : The DID type.
337
+ :param thread: The assigned thread for this necromancer.
338
+ :param total_threads: The total number of threads of all necromancers.
339
+ :param chunk_size: Number of requests to return per yield.
340
+ :param vo: The VO to act on.
341
+ :param session: The database session in use.
342
+ """
343
+ dids = did.list_new_dids(did_type=did_type and DIDType[did_type.upper()], thread=thread, total_threads=total_threads, chunk_size=chunk_size, session=session)
344
+ for d in dids:
345
+ if d['scope'].vo == vo:
346
+ yield gateway_update_return_dict(d, session=session)
347
+
348
+
349
+ @transactional_session
350
+ def set_new_dids(
351
+ dids: 'Sequence[dict[str, Any]]',
352
+ new_flag: bool = True,
353
+ vo: str = 'def',
354
+ *,
355
+ session: "Session"
356
+ ) -> bool:
357
+ """
358
+ Set/reset the flag new
359
+
360
+ :param scope: The scope name.
361
+ :param name: The data identifier name.
362
+ :param new_flag: A boolean to flag new DIDs.
363
+ :param vo: The VO to act on.
364
+ :param session: The database session in use.
365
+ """
366
+ for d in dids:
367
+ d['scope'] = InternalScope(d['scope'], vo=vo)
368
+
369
+ return did.set_new_dids(dids, new_flag, session=session)
370
+
371
+
372
+ @stream_session
373
+ def list_content(
374
+ scope: str,
375
+ name: str,
376
+ vo: str = 'def',
377
+ *,
378
+ session: "Session"
379
+ ) -> 'Iterator[dict[str, Any]]':
380
+ """
381
+ List data identifier contents.
382
+
383
+ :param scope: The scope name.
384
+ :param name: The data identifier name.
385
+ :param vo: The VO to act on.
386
+ :param session: The database session in use.
387
+ """
388
+
389
+ internal_scope = InternalScope(scope, vo=vo)
390
+
391
+ dids = did.list_content(scope=internal_scope, name=name, session=session)
392
+ for d in dids:
393
+ yield gateway_update_return_dict(d, session=session)
394
+
395
+
396
+ @stream_session
397
+ def list_content_history(
398
+ scope: str,
399
+ name: str,
400
+ vo='def',
401
+ *,
402
+ session: "Session"
403
+ ) -> 'Iterator[dict[str, Any]]':
404
+ """
405
+ List data identifier contents history.
406
+
407
+ :param scope: The scope name.
408
+ :param name: The data identifier name.
409
+ :param vo: The VO to act on.
410
+ :param session: The database session in use.
411
+ """
412
+
413
+ internal_scope = InternalScope(scope, vo=vo)
414
+
415
+ dids = did.list_content_history(scope=internal_scope, name=name, session=session)
416
+
417
+ for d in dids:
418
+ yield gateway_update_return_dict(d, session=session)
419
+
420
+
421
+ @stream_session
422
+ def bulk_list_files(
423
+ dids: 'Iterable[dict[str, Any]]',
424
+ long: bool = False,
425
+ vo: str = 'def',
426
+ *,
427
+ session: "Session"
428
+ ) -> 'Iterator[dict[str, Any]]':
429
+ """
430
+ List file contents of a list of data identifiers.
431
+
432
+ :param dids: A list of DIDs.
433
+ :param long: A boolean to choose if more metadata are returned or not.
434
+ :param vo: The VO to act on.
435
+ :param session: The database session in use.
436
+ """
437
+
438
+ for did_ in dids:
439
+ did_['scope'] = InternalScope(did_['scope'], vo=vo)
440
+
441
+ for file_ in did.bulk_list_files(dids=dids, long=long, session=session):
442
+ yield gateway_update_return_dict(file_, session=session)
443
+
444
+
445
+ @stream_session
446
+ def list_files(
447
+ scope: str,
448
+ name: str,
449
+ long: bool,
450
+ vo: str = 'def',
451
+ *,
452
+ session: "Session"
453
+ ) -> 'Iterator[dict[str, Any]]':
454
+ """
455
+ List data identifier file contents.
456
+
457
+ :param scope: The scope name.
458
+ :param name: The data identifier name.
459
+ :param long: A boolean to choose if GUID is returned or not.
460
+ :param vo: The VO to act on.
461
+ :param session: The database session in use.
462
+ """
463
+
464
+ internal_scope = InternalScope(scope, vo=vo)
465
+
466
+ dids = did.list_files(scope=internal_scope, name=name, long=long, session=session)
467
+
468
+ for d in dids:
469
+ yield gateway_update_return_dict(d, session=session)
470
+
471
+
472
+ @stream_session
473
+ def scope_list(
474
+ scope: str,
475
+ name: Optional[str] = None,
476
+ recursive: bool = False,
477
+ vo: str = 'def',
478
+ *,
479
+ session: "Session"
480
+ ) -> 'Iterator[dict[str, Any]]':
481
+ """
482
+ List data identifiers in a scope.
483
+
484
+ :param scope: The scope name.
485
+ :param name: The data identifier name.
486
+ :param recursive: boolean, True or False.
487
+ :param vo: The VO to act on.
488
+ :param session: The database session in use.
489
+ """
490
+
491
+ internal_scope = InternalScope(scope, vo=vo)
492
+
493
+ dids = did.scope_list(internal_scope, name=name, recursive=recursive, session=session)
494
+
495
+ for d in dids:
496
+ ret_did = deepcopy(d)
497
+ ret_did['scope'] = ret_did['scope'].external
498
+ if ret_did['parent'] is not None:
499
+ ret_did['parent']['scope'] = ret_did['parent']['scope'].external
500
+ yield ret_did
501
+
502
+
503
+ @read_session
504
+ def get_did(scope: str, name: str, dynamic_depth: Optional[DIDType] = None, vo: str = 'def', *, session: "Session") -> "dict[str, Any]":
505
+ """
506
+ Retrieve a single data did.
507
+
508
+ :param scope: The scope name.
509
+ :param name: The data identifier name.
510
+ :param dynamic_depth: the DID type to use as source for estimation of this DIDs length/bytes.
511
+ If set to None, or to a value which doesn't make sense (ex: requesting depth = CONTAINER for a did of type DATASET)
512
+ will not compute the size dynamically.
513
+ :param vo: The VO to act on.
514
+ :return did: Dictionary containing {'name', 'scope', 'type'}, Exception otherwise
515
+ :param session: The database session in use.
516
+ """
517
+
518
+ internal_scope = InternalScope(scope, vo=vo)
519
+
520
+ d = did.get_did(scope=internal_scope, name=name, dynamic_depth=dynamic_depth, session=session)
521
+ return gateway_update_return_dict(d, session=session)
522
+
523
+
524
+ @transactional_session
525
+ def set_metadata(
526
+ scope: str,
527
+ name: str,
528
+ key: str,
529
+ value: Any,
530
+ issuer: str,
531
+ recursive: bool = False,
532
+ vo: str = 'def',
533
+ *,
534
+ session: "Session"
535
+ ) -> None:
536
+ """
537
+ Add metadata to data did.
538
+
539
+ :param scope: The scope name.
540
+ :param name: The data identifier name.
541
+ :param key: the key.
542
+ :param value: the value.
543
+ :param issuer: The issuer account.
544
+ :param recursive: Option to propagate the metadata update to content.
545
+ :param vo: The VO to act on.
546
+ :param session: The database session in use.
547
+ """
548
+ kwargs = {'scope': scope, 'name': name, 'key': key, 'value': value, 'issuer': issuer}
549
+
550
+ if key in RESERVED_KEYS:
551
+ raise AccessDenied('Account %s can not change this metadata value to data identifier %s:%s' % (issuer, scope, name))
552
+
553
+ auth_result = rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='set_metadata', kwargs=kwargs, session=session)
554
+ if not auth_result.allowed:
555
+ raise AccessDenied('Account %s can not add metadata to data identifier %s:%s. %s' % (issuer, scope, name, auth_result.message))
556
+
557
+ internal_scope = InternalScope(scope, vo=vo)
558
+ return did.set_metadata(scope=internal_scope, name=name, key=key, value=value, recursive=recursive, session=session)
559
+
560
+
561
+ @transactional_session
562
+ def set_metadata_bulk(
563
+ scope: str,
564
+ name: str,
565
+ meta: dict[str, Any],
566
+ issuer: str,
567
+ recursive: bool = False,
568
+ vo: str = 'def',
569
+ *,
570
+ session: "Session"
571
+ ) -> None:
572
+ """
573
+ Add metadata to data did.
574
+
575
+ :param scope: The scope name.
576
+ :param name: The data identifier name.
577
+ :param meta: the key-values.
578
+ :param issuer: The issuer account.
579
+ :param recursive: Option to propagate the metadata update to content.
580
+ :param vo: The VO to act on.
581
+ :param session: The database session in use.
582
+ """
583
+ kwargs = {'scope': scope, 'name': name, 'meta': meta, 'issuer': issuer}
584
+
585
+ for key in meta:
586
+ if key in RESERVED_KEYS:
587
+ raise AccessDenied('Account %s can not change the value of the metadata key %s to data identifier %s:%s' % (issuer, key, scope, name))
588
+
589
+ auth_result = rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='set_metadata_bulk', kwargs=kwargs, session=session)
590
+ if not auth_result.allowed:
591
+ raise AccessDenied('Account %s can not add metadata to data identifier %s:%s. %s' % (issuer, scope, name, auth_result.message))
592
+
593
+ internal_scope = InternalScope(scope, vo=vo)
594
+ return did.set_metadata_bulk(scope=internal_scope, name=name, meta=meta, recursive=recursive, session=session)
595
+
596
+
597
+ @transactional_session
598
+ def set_dids_metadata_bulk(
599
+ dids: 'Iterable[dict[str, Any]]',
600
+ issuer: str,
601
+ recursive: bool = False,
602
+ vo: str = 'def',
603
+ *,
604
+ session: "Session"
605
+ ) -> None:
606
+ """
607
+ Add metadata to a list of data identifiers.
608
+
609
+ :param issuer: The issuer account.
610
+ :param dids: A list of dids including metadata.
611
+ :param recursive: Option to propagate the metadata update to content.
612
+ :param vo: The VO to act on.
613
+ :param session: The database session in use.
614
+ """
615
+
616
+ for entry in dids:
617
+ kwargs = {'scope': entry['scope'], 'name': entry['name'], 'meta': entry['meta'], 'issuer': issuer}
618
+ auth_result = rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='set_metadata_bulk', kwargs=kwargs, session=session)
619
+ if not auth_result.allowed:
620
+ raise AccessDenied('Account %s can not add metadata to data identifier %s:%s. %s' % (issuer, entry['scope'], entry['name'], auth_result.message))
621
+ entry['scope'] = InternalScope(entry['scope'], vo=vo)
622
+ meta = entry['meta']
623
+ for key in meta:
624
+ if key in RESERVED_KEYS:
625
+ raise AccessDenied('Account %s can not change the value of the metadata key %s to data identifier %s:%s' % (issuer, key, entry['scope'], entry['name']))
626
+
627
+ return did.set_dids_metadata_bulk(dids=dids, recursive=recursive, session=session)
628
+
629
+
630
+ @read_session
631
+ def get_metadata(
632
+ scope: str,
633
+ name: str,
634
+ plugin: str = 'DID_COLUMN',
635
+ vo: str = 'def',
636
+ *,
637
+ session: "Session"
638
+ ) -> dict[str, Any]:
639
+ """
640
+ Get data identifier metadata
641
+
642
+ :param scope: The scope name.
643
+ :param name: The data identifier name.
644
+ :param vo: The VO to act on.
645
+ :param plugin: The metadata plugin to query, 'ALL' for all available plugins
646
+ :param session: The database session in use.
647
+ """
648
+
649
+ internal_scope = InternalScope(scope, vo=vo)
650
+
651
+ d = did.get_metadata(scope=internal_scope, name=name, plugin=plugin, session=session)
652
+ return gateway_update_return_dict(d, session=session)
653
+
654
+
655
+ @stream_session
656
+ def get_metadata_bulk(
657
+ dids: 'Iterable[dict[str, Any]]',
658
+ inherit: bool = False,
659
+ plugin: str = 'DID_COLUMN',
660
+ vo: str = 'def',
661
+ *,
662
+ session: "Session"
663
+ ) -> 'Iterator[dict[str, Any]]':
664
+ """
665
+ Get metadata for a list of dids
666
+ :param dids: A list of dids.
667
+ :param inherit: A boolean. If set to true, the metadata of the parent are concatenated.
668
+ :param plugin: The metadata plugin to query, 'ALL' for all available plugins
669
+ :param vo: The VO to act on.
670
+ :param session: The database session in use.
671
+ """
672
+
673
+ validate_schema(name='dids', obj=dids, vo=vo)
674
+ for entry in dids:
675
+ entry['scope'] = InternalScope(entry['scope'], vo=vo)
676
+ meta = did.get_metadata_bulk(dids, inherit=inherit, plugin=plugin, session=session)
677
+ for met in meta:
678
+ yield gateway_update_return_dict(met, session=session)
679
+
680
+
681
+ @transactional_session
682
+ def delete_metadata(
683
+ scope: str,
684
+ name: str,
685
+ key: str,
686
+ vo: str = 'def',
687
+ *,
688
+ session: "Session"
689
+ ) -> None:
690
+ """
691
+ Delete a key from the metadata column
692
+
693
+ :param scope: the scope of did
694
+ :param name: the name of the did
695
+ :param key: the key to be deleted
696
+ :param vo: The VO to act on.
697
+ :param session: The database session in use.
698
+ """
699
+
700
+ internal_scope = InternalScope(scope, vo=vo)
701
+ return did.delete_metadata(scope=internal_scope, name=name, key=key, session=session)
702
+
703
+
704
+ @transactional_session
705
+ def set_status(
706
+ scope: str,
707
+ name: str,
708
+ issuer: str,
709
+ vo: str = 'def',
710
+ *,
711
+ session: "Session",
712
+ **kwargs
713
+ ) -> None:
714
+ """
715
+ Set data identifier status
716
+
717
+ :param scope: The scope name.
718
+ :param name: The data identifier name.
719
+ :param issuer: The issuer account.
720
+ :param kwargs: Keyword arguments of the form status_name=value.
721
+ :param vo: The VO to act on.
722
+ :param session: The database session in use.
723
+ """
724
+
725
+ auth_result = rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='set_status', kwargs={'scope': scope, 'name': name, 'issuer': issuer}, session=session)
726
+ if not auth_result.allowed:
727
+ raise AccessDenied('Account %s can not set status on data identifier %s:%s. %s' % (issuer, scope, name, auth_result.message))
728
+
729
+ internal_scope = InternalScope(scope, vo=vo)
730
+
731
+ return did.set_status(scope=internal_scope, name=name, session=session, **kwargs)
732
+
733
+
734
+ @stream_session
735
+ def get_dataset_by_guid(
736
+ guid: str,
737
+ vo: str = 'def',
738
+ *,
739
+ session: "Session"
740
+ ) -> 'Iterator[dict[str, Any]]':
741
+ """
742
+ Get the parent datasets for a given GUID.
743
+ :param guid: The GUID.
744
+ :param vo: The VO to act on.
745
+ :param session: The database session in use.
746
+
747
+ :returns: A did
748
+ """
749
+ dids = did.get_dataset_by_guid(guid=guid, session=session)
750
+
751
+ for d in dids:
752
+ if d['scope'].vo != vo:
753
+ raise RucioException('GUID unavailable on VO {}'.format(vo))
754
+ yield gateway_update_return_dict(d, session=session)
755
+
756
+
757
+ @stream_session
758
+ def list_parent_dids(
759
+ scope: str,
760
+ name: str,
761
+ vo: str = 'def',
762
+ *,
763
+ session: "Session"
764
+ ) -> 'Iterator[dict[str, Any]]':
765
+ """
766
+ List parent datasets and containers of a did.
767
+
768
+ :param scope: The scope.
769
+ :param name: The name.
770
+ :param vo: The VO to act on.
771
+ :param session: The database session in use.
772
+ """
773
+
774
+ internal_scope = InternalScope(scope, vo=vo)
775
+
776
+ dids = did.list_parent_dids(scope=internal_scope, name=name, session=session)
777
+
778
+ for d in dids:
779
+ yield gateway_update_return_dict(d, session=session)
780
+
781
+
782
+ @transactional_session
783
+ def create_did_sample(
784
+ input_scope: str,
785
+ input_name: str,
786
+ output_scope: str,
787
+ output_name: str,
788
+ issuer: str,
789
+ nbfiles: str,
790
+ vo: str = 'def',
791
+ *,
792
+ session: "Session"
793
+ ):
794
+ """
795
+ Create a sample from an input collection.
796
+
797
+ :param input_scope: The scope of the input DID.
798
+ :param input_name: The name of the input DID.
799
+ :param output_scope: The scope of the output dataset.
800
+ :param output_name: The name of the output dataset.
801
+ :param account: The account.
802
+ :param nbfiles: The number of files to register in the output dataset.
803
+ :param issuer: The issuer account.
804
+ :param vo: The VO to act on.
805
+ :param session: The database session in use.
806
+ """
807
+ kwargs = {'issuer': issuer, 'scope': output_scope}
808
+ auth_result = rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='create_did_sample', kwargs=kwargs, session=session)
809
+ if not auth_result.allowed:
810
+ raise AccessDenied('Account %s can not bulk add data identifier. %s' % (issuer, auth_result.message))
811
+
812
+ input_internal_scope = InternalScope(input_scope, vo=vo)
813
+ output_internal_scope = InternalScope(output_scope, vo=vo)
814
+
815
+ issuer_account = InternalAccount(issuer, vo=vo)
816
+
817
+ return did.create_did_sample(input_scope=input_internal_scope, input_name=input_name, output_scope=output_internal_scope, output_name=output_name,
818
+ account=issuer_account, nbfiles=nbfiles, session=session)
819
+
820
+
821
+ @transactional_session
822
+ def resurrect(
823
+ dids: 'Iterable[dict[str, Any]]',
824
+ issuer: str,
825
+ vo: str = 'def',
826
+ *,
827
+ session: "Session"
828
+ ) -> None:
829
+ """
830
+ Resurrect DIDs.
831
+
832
+ :param dids: A list of dids.
833
+ :param issuer: The issuer account.
834
+ :param vo: The VO to act on.
835
+ :param session: The database session in use.
836
+ """
837
+ kwargs = {'issuer': issuer}
838
+ auth_result = rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='resurrect', kwargs=kwargs, session=session)
839
+ if not auth_result.allowed:
840
+ raise AccessDenied('Account %s can not resurrect data identifiers. %s' % (issuer, auth_result.message))
841
+ validate_schema(name='dids', obj=dids, vo=vo)
842
+
843
+ for d in dids:
844
+ d['scope'] = InternalScope(d['scope'], vo=vo)
845
+
846
+ return did.resurrect(dids=dids, session=session)
847
+
848
+
849
+ @stream_session
850
+ def list_archive_content(
851
+ scope: str,
852
+ name: str,
853
+ vo: str = 'def',
854
+ *,
855
+ session: "Session"
856
+ ) -> 'Iterator[dict[str, Any]]':
857
+ """
858
+ List archive contents.
859
+
860
+ :param scope: The archive scope name.
861
+ :param name: The archive data identifier name.
862
+ :param vo: The VO to act on.
863
+ :param session: The database session in use.
864
+ """
865
+
866
+ internal_scope = InternalScope(scope, vo=vo)
867
+
868
+ dids = did.list_archive_content(scope=internal_scope, name=name, session=session)
869
+ for d in dids:
870
+ yield gateway_update_return_dict(d, session=session)
871
+
872
+
873
+ @transactional_session
874
+ def add_did_to_followed(
875
+ scope: str,
876
+ name: str,
877
+ account: str,
878
+ *,
879
+ session: "Session",
880
+ vo: str = 'def'
881
+ ) -> None:
882
+ """
883
+ Mark a did as followed by the given account
884
+
885
+ :param scope: The scope name.
886
+ :param name: The data identifier name.
887
+ :param account: The account owner.
888
+ :param session: The database session in use.
889
+ """
890
+ internal_scope = InternalScope(scope, vo=vo)
891
+ internal_account = InternalAccount(account, vo=vo)
892
+ return did.add_did_to_followed(scope=internal_scope, name=name, account=internal_account, session=session)
893
+
894
+
895
+ @transactional_session
896
+ def add_dids_to_followed(
897
+ dids: 'Iterable[Mapping[str, Any]]',
898
+ account: str,
899
+ *,
900
+ session: "Session",
901
+ vo: str = 'def'
902
+ ) -> None:
903
+ """
904
+ Bulk mark datasets as followed
905
+
906
+ :param dids: A list of dids.
907
+ :param account: The account owner.
908
+ :param session: The database session in use.
909
+ """
910
+ internal_account = InternalAccount(account, vo=vo)
911
+ return did.add_dids_to_followed(dids=dids, account=internal_account, session=session)
912
+
913
+
914
+ @stream_session
915
+ def get_users_following_did(
916
+ name: str,
917
+ scope: str,
918
+ *,
919
+ session: "Session",
920
+ vo: str = 'def'
921
+ ) -> 'Iterator[dict[str, str]]':
922
+ """
923
+ Return list of users following a did
924
+
925
+ :param scope: The scope name.
926
+ :param name: The data identifier name.
927
+ :param session: The database session in use.
928
+ """
929
+ internal_scope = InternalScope(scope, vo=vo)
930
+ users = did.get_users_following_did(name=name, scope=internal_scope, session=session)
931
+ for user in users:
932
+ user['user'] = user['user'].external
933
+ yield user
934
+
935
+
936
+ @transactional_session
937
+ def remove_did_from_followed(
938
+ scope: str,
939
+ name: str,
940
+ account: str,
941
+ issuer: str,
942
+ *,
943
+ session: "Session",
944
+ vo: str = 'def'
945
+ ) -> None:
946
+ """
947
+ Mark a did as not followed
948
+
949
+ :param scope: The scope name.
950
+ :param name: The data identifier name.
951
+ :param account: The account owner.
952
+ :param session: The database session in use.
953
+ :param issuer: The issuer account
954
+ """
955
+ kwargs = {'scope': scope, 'issuer': issuer}
956
+ auth_result = rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='remove_did_from_followed', kwargs=kwargs, session=session)
957
+ if not auth_result.allowed:
958
+ raise AccessDenied('Account %s can not remove data identifiers from followed table. %s' % (issuer, auth_result.message))
959
+
960
+ internal_scope = InternalScope(scope, vo=vo)
961
+ internal_account = InternalAccount(account, vo=vo)
962
+ return did.remove_did_from_followed(scope=internal_scope, name=name, account=internal_account, session=session)
963
+
964
+
965
+ @transactional_session
966
+ def remove_dids_from_followed(
967
+ dids: 'Iterable[Mapping[str, Any]]',
968
+ account: str,
969
+ issuer: str,
970
+ *,
971
+ session: "Session",
972
+ vo: str = 'def'
973
+ ) -> None:
974
+ """
975
+ Bulk mark datasets as not followed
976
+
977
+ :param dids: A list of dids.
978
+ :param account: The account owner.
979
+ :param session: The database session in use.
980
+ """
981
+ kwargs = {'dids': dids, 'issuer': issuer}
982
+ auth_result = rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='remove_dids_from_followed', kwargs=kwargs, session=session)
983
+ if not auth_result.allowed:
984
+ raise AccessDenied('Account %s can not bulk remove data identifiers from followed table. %s' % (issuer, auth_result.message))
985
+
986
+ internal_account = InternalAccount(account, vo=vo)
987
+ return did.remove_dids_from_followed(dids=dids, account=internal_account, session=session)