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
@@ -0,0 +1,185 @@
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
+ from typing import TYPE_CHECKING
15
+
16
+ from sqlalchemy import and_, delete, select
17
+ from sqlalchemy.exc import NoResultFound
18
+
19
+ from rucio.common.exception import CounterNotFound
20
+ from rucio.db.sqla import filter_thread_work, models
21
+ from rucio.db.sqla.session import read_session, transactional_session
22
+
23
+ if TYPE_CHECKING:
24
+ from sqlalchemy.orm import Session
25
+
26
+
27
+ @transactional_session
28
+ def add_counter(rse_id, *, session: "Session"):
29
+ """
30
+ Creates the specified counter for a rse_id.
31
+
32
+ :param rse_id: The id of the RSE.
33
+ :param session: The database session in use.
34
+ """
35
+ models.RSEUsage(rse_id=rse_id, source='rucio', files=0, used=0).\
36
+ save(session=session)
37
+
38
+
39
+ @transactional_session
40
+ def increase(rse_id, files, bytes_, *, session: "Session"):
41
+ """
42
+ Increments the specified counter by the specified amount.
43
+
44
+ :param rse_id: The id of the RSE.
45
+ :param files: The number of added files.
46
+ :param bytes_: The number of added bytes.
47
+ :param session: The database session in use.
48
+ """
49
+ models.UpdatedRSECounter(rse_id=rse_id, files=files, bytes=bytes_).\
50
+ save(session=session)
51
+
52
+
53
+ @transactional_session
54
+ def decrease(rse_id, files, bytes_, *, session: "Session"):
55
+ """
56
+ Decreases the specified counter by the specified amount.
57
+
58
+ :param rse_id: The id of the RSE.
59
+ :param files: The number of removed files.
60
+ :param bytes_: The number of removed bytes.
61
+ :param session: The database session in use.
62
+ """
63
+ return increase(rse_id=rse_id, files=-files, bytes_=-bytes_, session=session)
64
+
65
+
66
+ @transactional_session
67
+ def del_counter(rse_id, *, session: "Session"):
68
+ """
69
+ Delete specified counter.
70
+
71
+ :param rse_id: The id of the RSE.
72
+ :param session: The database session in use.
73
+ """
74
+
75
+ stmt = delete(
76
+ models.RSEUsage
77
+ ).where(
78
+ and_(models.RSEUsage.rse_id == rse_id,
79
+ models.RSEUsage.source == 'rucio')
80
+ ).execution_options(
81
+ synchronize_session=False
82
+ )
83
+ session.execute(stmt)
84
+
85
+
86
+ @read_session
87
+ def get_counter(rse_id, *, session: "Session"):
88
+ """
89
+ Returns current values of the specified counter or raises CounterNotFound if the counter does not exist.
90
+
91
+ :param rse_id: The id of the RSE.
92
+ :param session: The database session in use.
93
+ :returns: A dictionary with total and bytes.
94
+ :raises CounterNotFound: If the counter does not exist.
95
+ :returns: A dictionary with total and bytes.
96
+ """
97
+
98
+ try:
99
+ stmt = select(
100
+ models.RSEUsage.used,
101
+ models.RSEUsage.files,
102
+ models.RSEUsage.updated_at
103
+ ).where(
104
+ and_(models.RSEUsage.rse_id == rse_id,
105
+ models.RSEUsage.source == 'rucio')
106
+ )
107
+ usage_bytes, usage_files, usage_updated_at = session.execute(stmt).one()
108
+ return {
109
+ 'bytes': usage_bytes,
110
+ 'files': usage_files,
111
+ 'updated_at': usage_updated_at
112
+ }
113
+ except NoResultFound:
114
+ raise CounterNotFound()
115
+
116
+
117
+ @read_session
118
+ def get_updated_rse_counters(total_workers, worker_number, *, session: "Session"):
119
+ """
120
+ Get updated rse_counters.
121
+
122
+ :param total_workers: Number of total workers.
123
+ :param worker_number: id of the executing worker.
124
+ :param session: Database session in use.
125
+ :returns: List of rse_ids whose rse_counters need to be updated.
126
+ """
127
+ stmt = select(
128
+ models.UpdatedRSECounter.rse_id
129
+ ).distinct(
130
+ )
131
+
132
+ stmt = filter_thread_work(session=session, query=stmt, total_threads=total_workers, thread_id=worker_number, hash_variable='rse_id')
133
+ return session.execute(stmt).scalars().all()
134
+
135
+
136
+ @transactional_session
137
+ def update_rse_counter(rse_id, *, session: "Session"):
138
+ """
139
+ Read the updated_rse_counters and update the rse_counter.
140
+
141
+ :param rse_id: The rse_id to update.
142
+ :param session: Database session in use.
143
+ """
144
+
145
+ stmt = select(
146
+ models.UpdatedRSECounter
147
+ ).where(
148
+ models.UpdatedRSECounter.rse_id == rse_id
149
+ )
150
+ updated_rse_counters = session.execute(stmt).scalars().all()
151
+ sum_bytes = sum([updated_rse_counter.bytes for updated_rse_counter in updated_rse_counters])
152
+ sum_files = sum([updated_rse_counter.files for updated_rse_counter in updated_rse_counters])
153
+
154
+ try:
155
+ stmt = select(
156
+ models.RSEUsage
157
+ ).where(
158
+ and_(models.RSEUsage.rse_id == rse_id,
159
+ models.RSEUsage.source == 'rucio')
160
+ )
161
+ rse_counter = session.execute(stmt).scalar_one()
162
+ rse_counter.used = (rse_counter.used or 0) + sum_bytes
163
+ rse_counter.files = (rse_counter.files or 0) + sum_files
164
+ except NoResultFound:
165
+ models.RSEUsage(rse_id=rse_id,
166
+ used=sum_bytes,
167
+ files=sum_files,
168
+ source='rucio').save(session=session)
169
+
170
+ for update in updated_rse_counters:
171
+ update.delete(flush=False, session=session)
172
+
173
+
174
+ @transactional_session
175
+ def fill_rse_counter_history_table(*, session: "Session"):
176
+ """
177
+ Fill the RSE usage history table with the current usage.
178
+
179
+ :param session: Database session in use.
180
+ """
181
+ stmt = select(
182
+ models.RSEUsage
183
+ )
184
+ for usage in session.execute(stmt).scalars().all():
185
+ models.RSEUsageHistory(rse_id=usage['rse_id'], used=usage['used'], files=usage['files'], source=usage['source']).save(session=session)
@@ -0,0 +1,459 @@
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 abc
16
+ import re
17
+ from hashlib import sha256
18
+ from typing import TYPE_CHECKING, Any
19
+
20
+ from dogpile.cache.api import NoValue
21
+
22
+ from rucio.common.cache import MemcacheRegion
23
+ from rucio.common.exception import InvalidRSEExpression, RSEWriteBlocked
24
+ from rucio.core.rse import get_rse_attribute, get_rses_with_attribute, list_rses
25
+ from rucio.db.sqla.session import transactional_session
26
+
27
+ if TYPE_CHECKING:
28
+ from sqlalchemy.orm import Session
29
+
30
+
31
+ DEFAULT_RSE_ATTRIBUTE = r'([A-Za-z0-9]+([_-][A-Za-z0-9]+)*)'
32
+ RSE_ATTRIBUTE = r'([A-Za-z0-9\._-]+[=<>][A-Za-z0-9_-]+)'
33
+ PRIMITIVE = r'(\(*(%s|%s|%s)\)*)' % (RSE_ATTRIBUTE, DEFAULT_RSE_ATTRIBUTE, r'\*')
34
+ UNION = r'(\|%s)' % (PRIMITIVE)
35
+ INTERSECTION = r'(\&%s)' % (PRIMITIVE)
36
+ COMPLEMENT = r'(\\%s)' % (PRIMITIVE)
37
+
38
+ PATTERN = r'^%s(%s|%s|%s)*' % (PRIMITIVE, UNION, INTERSECTION, COMPLEMENT)
39
+
40
+ REGION = MemcacheRegion(expiration_time=600)
41
+
42
+
43
+ @transactional_session
44
+ def parse_expression(expression, filter_=None, *, session: "Session"):
45
+ """
46
+ Parse a RSE expression and return the list of RSE dictionaries.
47
+
48
+ :param expression: RSE expression, e.g: 'CERN|BNL'.
49
+ :param filter_: Availability filter (dictionary) used for the RSEs. e.g.: {'availability_write': True}
50
+ :param session: Database session in use.
51
+ :returns: A list of rse dictionaries.
52
+ :raises: InvalidRSEExpression, RSENotFound, RSEWriteBlocked
53
+ """
54
+ result = REGION.get(sha256(expression.encode()).hexdigest())
55
+ if type(result) is NoValue:
56
+ # Evaluate the correctness of the parentheses
57
+ parantheses_open_count = 0
58
+ parantheses_close_count = 0
59
+ for char in expression:
60
+ if (char == '('):
61
+ parantheses_open_count += 1
62
+ elif (char == ')'):
63
+ parantheses_close_count += 1
64
+ if (parantheses_close_count > parantheses_open_count):
65
+ raise InvalidRSEExpression('Problem with parentheses.')
66
+ if (parantheses_open_count != parantheses_close_count):
67
+ raise InvalidRSEExpression('Problem with parentheses.')
68
+
69
+ # Check the expression pattern
70
+ match = re.match(PATTERN, expression)
71
+ if match is None:
72
+ raise InvalidRSEExpression('Expression does not comply to RSE Expression syntax')
73
+ else:
74
+ if match.group() != expression:
75
+ raise InvalidRSEExpression('Expression does not comply to RSE Expression syntax')
76
+ result_tuple = __resolve_term_expression(expression)[0].resolve_elements(session=session)
77
+ # result_tuple = ([rse_ids], {rse_id: {rse_info}})
78
+ result = []
79
+ for rse in list(result_tuple[0]):
80
+ result.append(result_tuple[1][rse])
81
+ REGION.set(sha256(expression.encode()).hexdigest(), result)
82
+
83
+ # Filter for VO
84
+ vo_result = []
85
+ if filter_ and filter_.get('vo'):
86
+ filter_ = filter_.copy() # Make a copy so we can pop('vo') without affecting the object `filter` outside this function
87
+ vo = filter_.pop('vo')
88
+ for rse in result:
89
+ if rse.get('vo') == vo:
90
+ vo_result.append(rse)
91
+ else:
92
+ vo_result = result
93
+
94
+ if not vo_result:
95
+ raise InvalidRSEExpression('RSE Expression resulted in an empty set.')
96
+
97
+ # Filter
98
+ final_result = []
99
+ if filter_:
100
+ for rse in vo_result:
101
+ if filter_.get('availability_write', False):
102
+ if rse.get('availability_write'):
103
+ final_result.append(rse)
104
+ if not final_result:
105
+ raise RSEWriteBlocked('RSE excluded; not available for writing.')
106
+ else:
107
+ final_result = vo_result
108
+
109
+ # final_result = [{rse-info}]
110
+ return final_result
111
+
112
+
113
+ def __resolve_term_expression(expression):
114
+ """
115
+ Resolves a Term Expression and returns an object of type BaseExpressionElement
116
+
117
+ :param subexpression: String of the term expression.
118
+ :returns: Tuple of BaseExpressionElement, term Expression string
119
+ """
120
+
121
+ left_term = None
122
+ operator = None
123
+ original_expression = expression
124
+
125
+ while True:
126
+ if len(expression) == 0:
127
+ return (left_term, original_expression)
128
+ elif expression[0] == "(":
129
+ if left_term is None:
130
+ left_term, termexpression = __resolve_term_expression(__extract_term(expression))
131
+ expression = expression[len(termexpression) + 2:]
132
+ continue
133
+ else:
134
+ right_term, termexpression = __resolve_term_expression(__extract_term(expression))
135
+ expression = expression[len(termexpression) + 2:]
136
+ operator.set_left_term(left_term)
137
+ operator.set_right_term(right_term)
138
+ left_term = operator
139
+ operator = None
140
+ continue
141
+ elif expression[0] == "\\":
142
+ operator = ComplementOperator()
143
+ expression = expression[1:]
144
+ continue
145
+ elif expression[0] == "&":
146
+ operator = IntersectOperator()
147
+ expression = expression[1:]
148
+ continue
149
+ elif expression[0] == "|":
150
+ operator = UnionOperator()
151
+ expression = expression[1:]
152
+ continue
153
+ else:
154
+ if (left_term is None):
155
+ left_term, primitiveexpression = __resolve_primitive_expression(expression)
156
+ expression = expression[len(primitiveexpression):]
157
+ continue
158
+ else:
159
+ right_term, primitiveexpression = __resolve_primitive_expression(expression)
160
+ expression = expression[len(primitiveexpression):]
161
+ operator.set_left_term(left_term)
162
+ operator.set_right_term(right_term)
163
+ left_term = operator
164
+ operator = None
165
+ continue
166
+
167
+
168
+ def __resolve_primitive_expression(expression):
169
+ """
170
+ Resolve a primitive expression and return a RSEAttribute object
171
+
172
+ :param expression: String of the expression
173
+ :returns: Tuple of RSEAttribute, primitive expression
174
+ """
175
+ primitiveexpression = re.match(PRIMITIVE, expression).group()
176
+ if ('=' in primitiveexpression):
177
+ keyvalue = primitiveexpression.split("=")
178
+ return (RSEAttributeEqualCheck(keyvalue[0], keyvalue[1]), primitiveexpression)
179
+ elif ('<' in primitiveexpression):
180
+ keyvalue = primitiveexpression.split("<")
181
+ return (RSEAttributeSmallerCheck(keyvalue[0], keyvalue[1]), primitiveexpression)
182
+ elif ('>' in primitiveexpression):
183
+ keyvalue = primitiveexpression.split(">")
184
+ return (RSEAttributeLargerCheck(keyvalue[0], keyvalue[1]), primitiveexpression)
185
+ elif ('*' in primitiveexpression):
186
+ return (RSEAll(), primitiveexpression)
187
+ else:
188
+ return (RSEAttributeEqualCheck(key=primitiveexpression), primitiveexpression)
189
+
190
+
191
+ def __extract_term(expression):
192
+ """
193
+ Extract a term from an expression with parentheses
194
+
195
+ :param expression: The expression starting with a '('
196
+ :return: The extracted term string
197
+ """
198
+ open_parantheses = 0
199
+ i = 0
200
+ for char in expression:
201
+ if (char == '('):
202
+ open_parantheses += 1
203
+ elif (char == ')'):
204
+ open_parantheses -= 1
205
+ if (open_parantheses == 0):
206
+ return expression[1:i]
207
+ i = i + 1
208
+ raise SystemError('This point in the code should not be reachable')
209
+
210
+
211
+ class BaseExpressionElement(metaclass=abc.ABCMeta):
212
+ @abc.abstractmethod
213
+ def resolve_elements(self, session):
214
+ """
215
+ Resolve the ExpressionElement and return a set of RSE ids
216
+
217
+ :param session: Database session in use
218
+ :returns: (Set of RSE ids, Dictionary of RSE dicts)
219
+ :rtype: (Set of Strings, Dictionary of RSE dicts organized by rse_id)
220
+ """
221
+ pass
222
+
223
+
224
+ class RSEAll(BaseExpressionElement):
225
+ """
226
+ Representation of all RSEs
227
+ """
228
+
229
+ def resolve_elements(self, session):
230
+ """
231
+ Inherited from :py:func:`BaseExpressionElement.resolve_elements`
232
+ """
233
+ output = list_rses(session=session)
234
+ if not output:
235
+ return (set(), {})
236
+ rse_dict = {}
237
+ for rse in output:
238
+ rse_dict[rse['id']] = rse
239
+ return (set([rse['id'] for rse in output]), rse_dict)
240
+
241
+
242
+ class RSEAttributeEqualCheck(BaseExpressionElement):
243
+ """
244
+ Representation of an RSE Attribute with Equal Check
245
+ """
246
+
247
+ def __init__(self, key, value=True):
248
+ """
249
+ Creates an RSEAttribute representation
250
+
251
+ :param key: Key of the RSE Attribute.
252
+ :param value: Value of the RSE Attribute.
253
+ """
254
+ self.key = key
255
+ self.value = value
256
+
257
+ def resolve_elements(self, session):
258
+ """
259
+ Inherited from :py:func:`BaseExpressionElement.resolve_elements`
260
+ """
261
+ output = list_rses({self.key: self.value}, session=session)
262
+ if not output:
263
+ return (set(), {})
264
+ rse_dict = {}
265
+ for rse in output:
266
+ rse_dict[rse['id']] = rse
267
+ return (set([rse['id'] for rse in output]), rse_dict)
268
+
269
+
270
+ class RSEAttributeSmallerCheck(BaseExpressionElement):
271
+ """
272
+ Representation of an RSE Attribute with Smaller (<) Check
273
+ """
274
+
275
+ def __init__(self, key, value=True):
276
+ """
277
+ Creates an RSEAttribute representation
278
+
279
+ :param key: Key of the RSE Attribute.
280
+ :param value: Value of the RSE Attribute.
281
+ """
282
+ self.key = key
283
+ self.value = value
284
+
285
+ def resolve_elements(self, session):
286
+ """
287
+ Inherited from :py:func:`BaseExpressionElement.resolve_elements`
288
+ """
289
+ rse_list: list[dict[str, Any]] = get_rses_with_attribute(key=self.key, session=session)
290
+ if not rse_list:
291
+ return (set(), {})
292
+
293
+ output = []
294
+ rse_dict = {}
295
+ for rse in rse_list:
296
+ try:
297
+ if float(get_rse_attribute(rse['id'], self.key, session=session)) < float(self.value): # type: ignore (get_rse_attribute could return None)
298
+ rse_dict[rse['id']] = rse
299
+ output.append(rse['id'])
300
+ except ValueError:
301
+ continue
302
+ return (set(output), rse_dict)
303
+
304
+
305
+ class RSEAttributeLargerCheck(BaseExpressionElement):
306
+ """
307
+ Representation of an RSE Attribute with Larger (>) Check
308
+ """
309
+
310
+ def __init__(self, key, value=True):
311
+ """
312
+ Creates an RSEAttribute representation
313
+
314
+ :param key: Key of the RSE Attribute.
315
+ :param value: Value of the RSE Attribute.
316
+ """
317
+ self.key = key
318
+ self.value = value
319
+
320
+ def resolve_elements(self, session):
321
+ """
322
+ Inherited from :py:func:`BaseExpressionElement.resolve_elements`
323
+ """
324
+ rse_list: list[dict[str, Any]] = get_rses_with_attribute(key=self.key, session=session)
325
+ if not rse_list:
326
+ return (set(), {})
327
+
328
+ output = []
329
+ rse_dict = {}
330
+ for rse in rse_list:
331
+ try:
332
+ if float(get_rse_attribute(rse['id'], self.key, session=session)) > float(self.value): # type: ignore (get_rse_attribute could return None)
333
+ rse_dict[rse['id']] = rse
334
+ output.append(rse['id'])
335
+ except ValueError:
336
+ continue
337
+ return (set(output), rse_dict)
338
+
339
+
340
+ class BaseRSEOperator(BaseExpressionElement, metaclass=abc.ABCMeta):
341
+ @abc.abstractmethod
342
+ def set_left_term(self, left_term):
343
+ """
344
+ Set the left site of the term
345
+
346
+ :param left_term: Left term
347
+ """
348
+ pass
349
+
350
+ @abc.abstractmethod
351
+ def set_right_term(self, right_term):
352
+ """
353
+ Set the right site of the term
354
+
355
+ :param left_term: Left term
356
+ """
357
+ pass
358
+
359
+
360
+ class ComplementOperator(BaseRSEOperator):
361
+ """
362
+ Representation of the complement operator
363
+ """
364
+
365
+ def __init__(self):
366
+ """
367
+ Create a ComplementOperator representation
368
+ """
369
+
370
+ self.left_term = None
371
+ self.right_term = None
372
+
373
+ def set_left_term(self, left_term):
374
+ """
375
+ Inherited from :py:func:`BaseRSEOperator.set_left_term`
376
+ """
377
+ self.left_term = left_term
378
+
379
+ def set_right_term(self, right_term):
380
+ """
381
+ Inherited from :py:func:`BaseRSEOperator.set_right_term`
382
+ """
383
+ self.right_term = right_term
384
+
385
+ def resolve_elements(self, session):
386
+ """
387
+ Inherited from :py:func:`BaseExpressionElement.resolve_elements`
388
+ """
389
+ left_term_tuple = self.left_term.resolve_elements(session=session)
390
+ right_term_tuple = self.right_term.resolve_elements(session=session)
391
+ return (left_term_tuple[0] - right_term_tuple[0], dict(list(left_term_tuple[1].items()) + list(right_term_tuple[1].items())))
392
+
393
+
394
+ class UnionOperator(BaseRSEOperator):
395
+ """
396
+ Representation of the or operator
397
+ """
398
+
399
+ def __init__(self):
400
+ """
401
+ Create a UnionOperator representation
402
+ """
403
+
404
+ self.left_term = None
405
+ self.right_term = None
406
+
407
+ def set_left_term(self, left_term):
408
+ """
409
+ Inherited from :py:func:`BaseRSEOperator.set_left_term`
410
+ """
411
+ self.left_term = left_term
412
+
413
+ def set_right_term(self, right_term):
414
+ """
415
+ Inherited from :py:func:`BaseRSEOperator.set_right_term`
416
+ """
417
+ self.right_term = right_term
418
+
419
+ def resolve_elements(self, session):
420
+ """
421
+ Inherited from :py:func:`BaseExpressionElement.resolve_elements`
422
+ """
423
+ left_term_tuple = self.left_term.resolve_elements(session=session)
424
+ right_term_tuple = self.right_term.resolve_elements(session=session)
425
+ return (left_term_tuple[0] | right_term_tuple[0], dict(list(left_term_tuple[1].items()) + list(right_term_tuple[1].items())))
426
+
427
+
428
+ class IntersectOperator(BaseRSEOperator):
429
+ """
430
+ Representation of the intersect operator
431
+ """
432
+
433
+ def __init__(self):
434
+ """
435
+ Create a IntersectOperator representation
436
+ """
437
+
438
+ self.left_term = None
439
+ self.right_term = None
440
+
441
+ def set_left_term(self, left_term):
442
+ """
443
+ Inherited from :py:func:`BaseRSEOperator.set_left_term`
444
+ """
445
+ self.left_term = left_term
446
+
447
+ def set_right_term(self, right_term):
448
+ """
449
+ Inherited from :py:func:`BaseRSEOperator.set_right_term`
450
+ """
451
+ self.right_term = right_term
452
+
453
+ def resolve_elements(self, session):
454
+ """
455
+ Inherited from :py:func:`BaseExpressionElement.resolve_elements`
456
+ """
457
+ left_term_tuple = self.left_term.resolve_elements(session=session)
458
+ right_term_tuple = self.right_term.resolve_elements(session=session)
459
+ return (left_term_tuple[0] & right_term_tuple[0], dict(list(left_term_tuple[1].items()) + list(right_term_tuple[1].items())))