rucio 32.8.6__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of rucio might be problematic. Click here for more details.

Files changed (481) hide show
  1. rucio/__init__.py +18 -0
  2. rucio/alembicrevision.py +16 -0
  3. rucio/api/__init__.py +14 -0
  4. rucio/api/account.py +266 -0
  5. rucio/api/account_limit.py +287 -0
  6. rucio/api/authentication.py +302 -0
  7. rucio/api/config.py +218 -0
  8. rucio/api/credential.py +60 -0
  9. rucio/api/did.py +726 -0
  10. rucio/api/dirac.py +71 -0
  11. rucio/api/exporter.py +60 -0
  12. rucio/api/heartbeat.py +62 -0
  13. rucio/api/identity.py +160 -0
  14. rucio/api/importer.py +46 -0
  15. rucio/api/lifetime_exception.py +95 -0
  16. rucio/api/lock.py +131 -0
  17. rucio/api/meta.py +85 -0
  18. rucio/api/permission.py +72 -0
  19. rucio/api/quarantined_replica.py +69 -0
  20. rucio/api/replica.py +528 -0
  21. rucio/api/request.py +220 -0
  22. rucio/api/rse.py +601 -0
  23. rucio/api/rule.py +335 -0
  24. rucio/api/scope.py +89 -0
  25. rucio/api/subscription.py +255 -0
  26. rucio/api/temporary_did.py +49 -0
  27. rucio/api/vo.py +112 -0
  28. rucio/client/__init__.py +16 -0
  29. rucio/client/accountclient.py +413 -0
  30. rucio/client/accountlimitclient.py +155 -0
  31. rucio/client/baseclient.py +929 -0
  32. rucio/client/client.py +77 -0
  33. rucio/client/configclient.py +113 -0
  34. rucio/client/credentialclient.py +54 -0
  35. rucio/client/didclient.py +691 -0
  36. rucio/client/diracclient.py +48 -0
  37. rucio/client/downloadclient.py +1674 -0
  38. rucio/client/exportclient.py +44 -0
  39. rucio/client/fileclient.py +51 -0
  40. rucio/client/importclient.py +42 -0
  41. rucio/client/lifetimeclient.py +74 -0
  42. rucio/client/lockclient.py +99 -0
  43. rucio/client/metaclient.py +137 -0
  44. rucio/client/pingclient.py +45 -0
  45. rucio/client/replicaclient.py +444 -0
  46. rucio/client/requestclient.py +109 -0
  47. rucio/client/rseclient.py +664 -0
  48. rucio/client/ruleclient.py +287 -0
  49. rucio/client/scopeclient.py +88 -0
  50. rucio/client/subscriptionclient.py +161 -0
  51. rucio/client/touchclient.py +78 -0
  52. rucio/client/uploadclient.py +871 -0
  53. rucio/common/__init__.py +14 -0
  54. rucio/common/cache.py +74 -0
  55. rucio/common/config.py +796 -0
  56. rucio/common/constants.py +92 -0
  57. rucio/common/constraints.py +18 -0
  58. rucio/common/didtype.py +187 -0
  59. rucio/common/dumper/__init__.py +306 -0
  60. rucio/common/dumper/consistency.py +449 -0
  61. rucio/common/dumper/data_models.py +325 -0
  62. rucio/common/dumper/path_parsing.py +65 -0
  63. rucio/common/exception.py +1092 -0
  64. rucio/common/extra.py +37 -0
  65. rucio/common/logging.py +404 -0
  66. rucio/common/pcache.py +1387 -0
  67. rucio/common/policy.py +84 -0
  68. rucio/common/schema/__init__.py +143 -0
  69. rucio/common/schema/atlas.py +411 -0
  70. rucio/common/schema/belleii.py +406 -0
  71. rucio/common/schema/cms.py +478 -0
  72. rucio/common/schema/domatpc.py +399 -0
  73. rucio/common/schema/escape.py +424 -0
  74. rucio/common/schema/generic.py +431 -0
  75. rucio/common/schema/generic_multi_vo.py +410 -0
  76. rucio/common/schema/icecube.py +404 -0
  77. rucio/common/schema/lsst.py +423 -0
  78. rucio/common/stomp_utils.py +160 -0
  79. rucio/common/stopwatch.py +56 -0
  80. rucio/common/test_rucio_server.py +148 -0
  81. rucio/common/types.py +158 -0
  82. rucio/common/utils.py +1946 -0
  83. rucio/core/__init__.py +14 -0
  84. rucio/core/account.py +426 -0
  85. rucio/core/account_counter.py +171 -0
  86. rucio/core/account_limit.py +357 -0
  87. rucio/core/authentication.py +563 -0
  88. rucio/core/config.py +386 -0
  89. rucio/core/credential.py +218 -0
  90. rucio/core/did.py +3102 -0
  91. rucio/core/did_meta_plugins/__init__.py +250 -0
  92. rucio/core/did_meta_plugins/did_column_meta.py +326 -0
  93. rucio/core/did_meta_plugins/did_meta_plugin_interface.py +116 -0
  94. rucio/core/did_meta_plugins/filter_engine.py +573 -0
  95. rucio/core/did_meta_plugins/json_meta.py +215 -0
  96. rucio/core/did_meta_plugins/mongo_meta.py +199 -0
  97. rucio/core/did_meta_plugins/postgres_meta.py +317 -0
  98. rucio/core/dirac.py +208 -0
  99. rucio/core/distance.py +164 -0
  100. rucio/core/exporter.py +59 -0
  101. rucio/core/heartbeat.py +263 -0
  102. rucio/core/identity.py +290 -0
  103. rucio/core/importer.py +248 -0
  104. rucio/core/lifetime_exception.py +377 -0
  105. rucio/core/lock.py +474 -0
  106. rucio/core/message.py +241 -0
  107. rucio/core/meta.py +190 -0
  108. rucio/core/monitor.py +441 -0
  109. rucio/core/naming_convention.py +154 -0
  110. rucio/core/nongrid_trace.py +124 -0
  111. rucio/core/oidc.py +1339 -0
  112. rucio/core/permission/__init__.py +107 -0
  113. rucio/core/permission/atlas.py +1333 -0
  114. rucio/core/permission/belleii.py +1076 -0
  115. rucio/core/permission/cms.py +1166 -0
  116. rucio/core/permission/escape.py +1076 -0
  117. rucio/core/permission/generic.py +1128 -0
  118. rucio/core/permission/generic_multi_vo.py +1148 -0
  119. rucio/core/quarantined_replica.py +190 -0
  120. rucio/core/replica.py +3627 -0
  121. rucio/core/replica_sorter.py +368 -0
  122. rucio/core/request.py +2241 -0
  123. rucio/core/rse.py +1835 -0
  124. rucio/core/rse_counter.py +155 -0
  125. rucio/core/rse_expression_parser.py +460 -0
  126. rucio/core/rse_selector.py +277 -0
  127. rucio/core/rule.py +3419 -0
  128. rucio/core/rule_grouping.py +1473 -0
  129. rucio/core/scope.py +152 -0
  130. rucio/core/subscription.py +316 -0
  131. rucio/core/temporary_did.py +188 -0
  132. rucio/core/topology.py +448 -0
  133. rucio/core/trace.py +361 -0
  134. rucio/core/transfer.py +1233 -0
  135. rucio/core/vo.py +151 -0
  136. rucio/core/volatile_replica.py +123 -0
  137. rucio/daemons/__init__.py +14 -0
  138. rucio/daemons/abacus/__init__.py +14 -0
  139. rucio/daemons/abacus/account.py +106 -0
  140. rucio/daemons/abacus/collection_replica.py +113 -0
  141. rucio/daemons/abacus/rse.py +107 -0
  142. rucio/daemons/atropos/__init__.py +14 -0
  143. rucio/daemons/atropos/atropos.py +243 -0
  144. rucio/daemons/auditor/__init__.py +261 -0
  145. rucio/daemons/auditor/hdfs.py +86 -0
  146. rucio/daemons/auditor/srmdumps.py +284 -0
  147. rucio/daemons/automatix/__init__.py +14 -0
  148. rucio/daemons/automatix/automatix.py +281 -0
  149. rucio/daemons/badreplicas/__init__.py +14 -0
  150. rucio/daemons/badreplicas/minos.py +311 -0
  151. rucio/daemons/badreplicas/minos_temporary_expiration.py +173 -0
  152. rucio/daemons/badreplicas/necromancer.py +200 -0
  153. rucio/daemons/bb8/__init__.py +14 -0
  154. rucio/daemons/bb8/bb8.py +356 -0
  155. rucio/daemons/bb8/common.py +762 -0
  156. rucio/daemons/bb8/nuclei_background_rebalance.py +147 -0
  157. rucio/daemons/bb8/t2_background_rebalance.py +146 -0
  158. rucio/daemons/c3po/__init__.py +14 -0
  159. rucio/daemons/c3po/algorithms/__init__.py +14 -0
  160. rucio/daemons/c3po/algorithms/simple.py +131 -0
  161. rucio/daemons/c3po/algorithms/t2_free_space.py +125 -0
  162. rucio/daemons/c3po/algorithms/t2_free_space_only_pop.py +127 -0
  163. rucio/daemons/c3po/algorithms/t2_free_space_only_pop_with_network.py +279 -0
  164. rucio/daemons/c3po/c3po.py +342 -0
  165. rucio/daemons/c3po/collectors/__init__.py +14 -0
  166. rucio/daemons/c3po/collectors/agis.py +108 -0
  167. rucio/daemons/c3po/collectors/free_space.py +62 -0
  168. rucio/daemons/c3po/collectors/jedi_did.py +48 -0
  169. rucio/daemons/c3po/collectors/mock_did.py +46 -0
  170. rucio/daemons/c3po/collectors/network_metrics.py +63 -0
  171. rucio/daemons/c3po/collectors/workload.py +110 -0
  172. rucio/daemons/c3po/utils/__init__.py +14 -0
  173. rucio/daemons/c3po/utils/dataset_cache.py +40 -0
  174. rucio/daemons/c3po/utils/expiring_dataset_cache.py +45 -0
  175. rucio/daemons/c3po/utils/expiring_list.py +63 -0
  176. rucio/daemons/c3po/utils/popularity.py +82 -0
  177. rucio/daemons/c3po/utils/timeseries.py +76 -0
  178. rucio/daemons/cache/__init__.py +14 -0
  179. rucio/daemons/cache/consumer.py +191 -0
  180. rucio/daemons/common.py +391 -0
  181. rucio/daemons/conveyor/__init__.py +14 -0
  182. rucio/daemons/conveyor/common.py +530 -0
  183. rucio/daemons/conveyor/finisher.py +492 -0
  184. rucio/daemons/conveyor/poller.py +372 -0
  185. rucio/daemons/conveyor/preparer.py +198 -0
  186. rucio/daemons/conveyor/receiver.py +206 -0
  187. rucio/daemons/conveyor/stager.py +127 -0
  188. rucio/daemons/conveyor/submitter.py +379 -0
  189. rucio/daemons/conveyor/throttler.py +468 -0
  190. rucio/daemons/follower/__init__.py +14 -0
  191. rucio/daemons/follower/follower.py +97 -0
  192. rucio/daemons/hermes/__init__.py +14 -0
  193. rucio/daemons/hermes/hermes.py +738 -0
  194. rucio/daemons/judge/__init__.py +14 -0
  195. rucio/daemons/judge/cleaner.py +149 -0
  196. rucio/daemons/judge/evaluator.py +172 -0
  197. rucio/daemons/judge/injector.py +154 -0
  198. rucio/daemons/judge/repairer.py +144 -0
  199. rucio/daemons/oauthmanager/__init__.py +14 -0
  200. rucio/daemons/oauthmanager/oauthmanager.py +199 -0
  201. rucio/daemons/reaper/__init__.py +14 -0
  202. rucio/daemons/reaper/dark_reaper.py +272 -0
  203. rucio/daemons/reaper/light_reaper.py +255 -0
  204. rucio/daemons/reaper/reaper.py +701 -0
  205. rucio/daemons/replicarecoverer/__init__.py +14 -0
  206. rucio/daemons/replicarecoverer/suspicious_replica_recoverer.py +487 -0
  207. rucio/daemons/storage/__init__.py +14 -0
  208. rucio/daemons/storage/consistency/__init__.py +14 -0
  209. rucio/daemons/storage/consistency/actions.py +753 -0
  210. rucio/daemons/tracer/__init__.py +14 -0
  211. rucio/daemons/tracer/kronos.py +513 -0
  212. rucio/daemons/transmogrifier/__init__.py +14 -0
  213. rucio/daemons/transmogrifier/transmogrifier.py +753 -0
  214. rucio/daemons/undertaker/__init__.py +14 -0
  215. rucio/daemons/undertaker/undertaker.py +137 -0
  216. rucio/db/__init__.py +14 -0
  217. rucio/db/sqla/__init__.py +38 -0
  218. rucio/db/sqla/constants.py +192 -0
  219. rucio/db/sqla/migrate_repo/__init__.py +14 -0
  220. rucio/db/sqla/migrate_repo/env.py +111 -0
  221. rucio/db/sqla/migrate_repo/versions/01eaf73ab656_add_new_rule_notification_state_progress.py +71 -0
  222. rucio/db/sqla/migrate_repo/versions/0437a40dbfd1_add_eol_at_in_rules.py +50 -0
  223. rucio/db/sqla/migrate_repo/versions/0f1adb7a599a_create_transfer_hops_table.py +61 -0
  224. rucio/db/sqla/migrate_repo/versions/102efcf145f4_added_stuck_at_column_to_rules.py +46 -0
  225. rucio/db/sqla/migrate_repo/versions/13d4f70c66a9_introduce_transfer_limits.py +93 -0
  226. rucio/db/sqla/migrate_repo/versions/140fef722e91_cleanup_distances_table.py +78 -0
  227. rucio/db/sqla/migrate_repo/versions/14ec5aeb64cf_add_request_external_host.py +46 -0
  228. rucio/db/sqla/migrate_repo/versions/156fb5b5a14_add_request_type_to_requests_idx.py +53 -0
  229. rucio/db/sqla/migrate_repo/versions/1677d4d803c8_split_rse_availability_into_multiple.py +69 -0
  230. rucio/db/sqla/migrate_repo/versions/16a0aca82e12_create_index_on_table_replicas_path.py +42 -0
  231. rucio/db/sqla/migrate_repo/versions/1803333ac20f_adding_provenance_and_phys_group.py +46 -0
  232. rucio/db/sqla/migrate_repo/versions/1a29d6a9504c_add_didtype_chck_to_requests.py +61 -0
  233. rucio/db/sqla/migrate_repo/versions/1a80adff031a_create_index_on_rules_hist_recent.py +42 -0
  234. rucio/db/sqla/migrate_repo/versions/1c45d9730ca6_increase_identity_length.py +141 -0
  235. rucio/db/sqla/migrate_repo/versions/1d1215494e95_add_quarantined_replicas_table.py +75 -0
  236. rucio/db/sqla/migrate_repo/versions/1d96f484df21_asynchronous_rules_and_rule_approval.py +75 -0
  237. rucio/db/sqla/migrate_repo/versions/1f46c5f240ac_add_bytes_column_to_bad_replicas.py +46 -0
  238. rucio/db/sqla/migrate_repo/versions/1fc15ab60d43_add_message_history_table.py +51 -0
  239. rucio/db/sqla/migrate_repo/versions/2190e703eb6e_move_rse_settings_to_rse_attributes.py +135 -0
  240. rucio/db/sqla/migrate_repo/versions/21d6b9dc9961_add_mismatch_scheme_state_to_requests.py +65 -0
  241. rucio/db/sqla/migrate_repo/versions/22cf51430c78_add_availability_column_to_table_rses.py +42 -0
  242. rucio/db/sqla/migrate_repo/versions/22d887e4ec0a_create_sources_table.py +66 -0
  243. rucio/db/sqla/migrate_repo/versions/25821a8a45a3_remove_unique_constraint_on_requests.py +54 -0
  244. rucio/db/sqla/migrate_repo/versions/25fc855625cf_added_unique_constraint_to_rules.py +43 -0
  245. rucio/db/sqla/migrate_repo/versions/269fee20dee9_add_repair_cnt_to_locks.py +46 -0
  246. rucio/db/sqla/migrate_repo/versions/271a46ea6244_add_ignore_availability_column_to_rules.py +47 -0
  247. rucio/db/sqla/migrate_repo/versions/277b5fbb41d3_switch_heartbeats_executable.py +54 -0
  248. rucio/db/sqla/migrate_repo/versions/27e3a68927fb_remove_replicas_tombstone_and_replicas_.py +39 -0
  249. rucio/db/sqla/migrate_repo/versions/2854cd9e168_added_rule_id_column.py +48 -0
  250. rucio/db/sqla/migrate_repo/versions/295289b5a800_processed_by_and__at_in_requests.py +47 -0
  251. rucio/db/sqla/migrate_repo/versions/2962ece31cf4_add_nbaccesses_column_in_the_did_table.py +48 -0
  252. rucio/db/sqla/migrate_repo/versions/2af3291ec4c_added_replicas_history_table.py +59 -0
  253. rucio/db/sqla/migrate_repo/versions/2b69addda658_add_columns_for_third_party_copy_read_.py +47 -0
  254. rucio/db/sqla/migrate_repo/versions/2b8e7bcb4783_add_config_table.py +72 -0
  255. rucio/db/sqla/migrate_repo/versions/2ba5229cb54c_add_submitted_at_to_requests_table.py +46 -0
  256. rucio/db/sqla/migrate_repo/versions/2cbee484dcf9_added_column_volume_to_rse_transfer_.py +45 -0
  257. rucio/db/sqla/migrate_repo/versions/2edee4a83846_add_source_to_requests_and_requests_.py +48 -0
  258. rucio/db/sqla/migrate_repo/versions/2eef46be23d4_change_tokens_pk.py +48 -0
  259. rucio/db/sqla/migrate_repo/versions/2f648fc909f3_index_in_rule_history_on_scope_name.py +42 -0
  260. rucio/db/sqla/migrate_repo/versions/3082b8cef557_add_naming_convention_table_and_closed_.py +69 -0
  261. rucio/db/sqla/migrate_repo/versions/30fa38b6434e_add_index_on_service_column_in_the_message_table.py +46 -0
  262. rucio/db/sqla/migrate_repo/versions/3152492b110b_added_staging_area_column.py +78 -0
  263. rucio/db/sqla/migrate_repo/versions/32c7d2783f7e_create_bad_replicas_table.py +62 -0
  264. rucio/db/sqla/migrate_repo/versions/3345511706b8_replicas_table_pk_definition_is_in_.py +74 -0
  265. rucio/db/sqla/migrate_repo/versions/35ef10d1e11b_change_index_on_table_requests.py +44 -0
  266. rucio/db/sqla/migrate_repo/versions/379a19b5332d_create_rse_limits_table.py +67 -0
  267. rucio/db/sqla/migrate_repo/versions/384b96aa0f60_created_rule_history_tables.py +134 -0
  268. rucio/db/sqla/migrate_repo/versions/3ac1660a1a72_extend_distance_table.py +58 -0
  269. rucio/db/sqla/migrate_repo/versions/3ad36e2268b0_create_collection_replicas_updates_table.py +79 -0
  270. rucio/db/sqla/migrate_repo/versions/3c9df354071b_extend_waiting_request_state.py +61 -0
  271. rucio/db/sqla/migrate_repo/versions/3d9813fab443_add_a_new_state_lost_in_badfilesstatus.py +45 -0
  272. rucio/db/sqla/migrate_repo/versions/40ad39ce3160_add_transferred_at_to_requests_table.py +46 -0
  273. rucio/db/sqla/migrate_repo/versions/4207be2fd914_add_notification_column_to_rules.py +65 -0
  274. rucio/db/sqla/migrate_repo/versions/42db2617c364_create_index_on_requests_external_id.py +42 -0
  275. rucio/db/sqla/migrate_repo/versions/436827b13f82_added_column_activity_to_table_requests.py +46 -0
  276. rucio/db/sqla/migrate_repo/versions/44278720f774_update_requests_typ_sta_upd_idx_index.py +46 -0
  277. rucio/db/sqla/migrate_repo/versions/45378a1e76a8_create_collection_replica_table.py +80 -0
  278. rucio/db/sqla/migrate_repo/versions/469d262be19_removing_created_at_index.py +43 -0
  279. rucio/db/sqla/migrate_repo/versions/4783c1f49cb4_create_distance_table.py +61 -0
  280. rucio/db/sqla/migrate_repo/versions/49a21b4d4357_create_index_on_table_tokens.py +47 -0
  281. rucio/db/sqla/migrate_repo/versions/4a2cbedda8b9_add_source_replica_expression_column_to_.py +46 -0
  282. rucio/db/sqla/migrate_repo/versions/4a7182d9578b_added_bytes_length_accessed_at_columns.py +52 -0
  283. rucio/db/sqla/migrate_repo/versions/4bab9edd01fc_create_index_on_requests_rule_id.py +42 -0
  284. rucio/db/sqla/migrate_repo/versions/4c3a4acfe006_new_attr_account_table.py +65 -0
  285. rucio/db/sqla/migrate_repo/versions/4cf0a2e127d4_adding_transient_metadata.py +46 -0
  286. rucio/db/sqla/migrate_repo/versions/50280c53117c_add_qos_class_to_rse.py +47 -0
  287. rucio/db/sqla/migrate_repo/versions/52153819589c_add_rse_id_to_replicas_table.py +45 -0
  288. rucio/db/sqla/migrate_repo/versions/52fd9f4916fa_added_activity_to_rules.py +46 -0
  289. rucio/db/sqla/migrate_repo/versions/53b479c3cb0f_fix_did_meta_table_missing_updated_at_.py +48 -0
  290. rucio/db/sqla/migrate_repo/versions/5673b4b6e843_add_wfms_metadata_to_rule_tables.py +50 -0
  291. rucio/db/sqla/migrate_repo/versions/575767d9f89_added_source_history_table.py +59 -0
  292. rucio/db/sqla/migrate_repo/versions/58bff7008037_add_started_at_to_requests.py +48 -0
  293. rucio/db/sqla/migrate_repo/versions/58c8b78301ab_rename_callback_to_message.py +108 -0
  294. rucio/db/sqla/migrate_repo/versions/5f139f77382a_added_child_rule_id_column.py +57 -0
  295. rucio/db/sqla/migrate_repo/versions/688ef1840840_adding_did_meta_table.py +51 -0
  296. rucio/db/sqla/migrate_repo/versions/6e572a9bfbf3_add_new_split_container_column_to_rules.py +50 -0
  297. rucio/db/sqla/migrate_repo/versions/70587619328_add_comment_column_for_subscriptions.py +46 -0
  298. rucio/db/sqla/migrate_repo/versions/739064d31565_remove_history_table_pks.py +42 -0
  299. rucio/db/sqla/migrate_repo/versions/7541902bf173_add_didsfollowed_and_followevents_table.py +93 -0
  300. rucio/db/sqla/migrate_repo/versions/7ec22226cdbf_new_replica_state_for_temporary_.py +73 -0
  301. rucio/db/sqla/migrate_repo/versions/810a41685bc1_added_columns_rse_transfer_limits.py +52 -0
  302. rucio/db/sqla/migrate_repo/versions/83f991c63a93_correct_rse_expression_length.py +45 -0
  303. rucio/db/sqla/migrate_repo/versions/8523998e2e76_increase_size_of_extended_attributes_.py +46 -0
  304. rucio/db/sqla/migrate_repo/versions/8ea9122275b1_adding_missing_function_based_indices.py +54 -0
  305. rucio/db/sqla/migrate_repo/versions/90f47792bb76_add_clob_payload_to_messages.py +48 -0
  306. rucio/db/sqla/migrate_repo/versions/914b8f02df38_new_table_for_lifetime_model_exceptions.py +70 -0
  307. rucio/db/sqla/migrate_repo/versions/94a5961ddbf2_add_estimator_columns.py +48 -0
  308. rucio/db/sqla/migrate_repo/versions/9a1b149a2044_add_saml_identity_type.py +95 -0
  309. rucio/db/sqla/migrate_repo/versions/9a45bc4ea66d_add_vp_table.py +55 -0
  310. rucio/db/sqla/migrate_repo/versions/9eb936a81eb1_true_is_true.py +74 -0
  311. rucio/db/sqla/migrate_repo/versions/a118956323f8_added_vo_table_and_vo_col_to_rse.py +78 -0
  312. rucio/db/sqla/migrate_repo/versions/a193a275255c_add_status_column_in_messages.py +49 -0
  313. rucio/db/sqla/migrate_repo/versions/a5f6f6e928a7_1_7_0.py +124 -0
  314. rucio/db/sqla/migrate_repo/versions/a616581ee47_added_columns_to_table_requests.py +60 -0
  315. rucio/db/sqla/migrate_repo/versions/a6eb23955c28_state_idx_non_functional.py +53 -0
  316. rucio/db/sqla/migrate_repo/versions/a74275a1ad30_added_global_quota_table.py +56 -0
  317. rucio/db/sqla/migrate_repo/versions/a93e4e47bda_heartbeats.py +67 -0
  318. rucio/db/sqla/migrate_repo/versions/ae2a56fcc89_added_comment_column_to_rules.py +50 -0
  319. rucio/db/sqla/migrate_repo/versions/b4293a99f344_added_column_identity_to_table_tokens.py +46 -0
  320. rucio/db/sqla/migrate_repo/versions/b7d287de34fd_removal_of_replicastate_source.py +92 -0
  321. rucio/db/sqla/migrate_repo/versions/b818052fa670_add_index_to_quarantined_replicas.py +42 -0
  322. rucio/db/sqla/migrate_repo/versions/b8caac94d7f0_add_comments_column_for_subscriptions_.py +46 -0
  323. rucio/db/sqla/migrate_repo/versions/b96a1c7e1cc4_new_bad_pfns_table_and_bad_replicas_.py +147 -0
  324. rucio/db/sqla/migrate_repo/versions/bb695f45c04_extend_request_state.py +78 -0
  325. rucio/db/sqla/migrate_repo/versions/bc68e9946deb_add_staging_timestamps_to_request.py +53 -0
  326. rucio/db/sqla/migrate_repo/versions/bf3baa1c1474_correct_pk_and_idx_for_history_tables.py +74 -0
  327. rucio/db/sqla/migrate_repo/versions/c0937668555f_add_qos_policy_map_table.py +56 -0
  328. rucio/db/sqla/migrate_repo/versions/c129ccdb2d5_add_lumiblocknr_to_dids.py +46 -0
  329. rucio/db/sqla/migrate_repo/versions/ccdbcd48206e_add_did_type_column_index_on_did_meta_.py +68 -0
  330. rucio/db/sqla/migrate_repo/versions/cebad904c4dd_new_payload_column_for_heartbeats.py +48 -0
  331. rucio/db/sqla/migrate_repo/versions/d1189a09c6e0_oauth2_0_and_jwt_feature_support_adding_.py +149 -0
  332. rucio/db/sqla/migrate_repo/versions/d23453595260_extend_request_state_for_preparer.py +106 -0
  333. rucio/db/sqla/migrate_repo/versions/d6dceb1de2d_added_purge_column_to_rules.py +47 -0
  334. rucio/db/sqla/migrate_repo/versions/d6e2c3b2cf26_remove_third_party_copy_column_from_rse.py +45 -0
  335. rucio/db/sqla/migrate_repo/versions/d91002c5841_new_account_limits_table.py +105 -0
  336. rucio/db/sqla/migrate_repo/versions/e138c364ebd0_extending_columns_for_filter_and_.py +52 -0
  337. rucio/db/sqla/migrate_repo/versions/e59300c8b179_support_for_archive.py +106 -0
  338. rucio/db/sqla/migrate_repo/versions/f1b14a8c2ac1_postgres_use_check_constraints.py +30 -0
  339. rucio/db/sqla/migrate_repo/versions/f41ffe206f37_oracle_global_temporary_tables.py +75 -0
  340. rucio/db/sqla/migrate_repo/versions/f85a2962b021_adding_transfertool_column_to_requests_.py +49 -0
  341. rucio/db/sqla/migrate_repo/versions/fa7a7d78b602_increase_refresh_token_size.py +45 -0
  342. rucio/db/sqla/migrate_repo/versions/fb28a95fe288_add_replicas_rse_id_tombstone_idx.py +38 -0
  343. rucio/db/sqla/migrate_repo/versions/fe1a65b176c9_set_third_party_copy_read_and_write_.py +44 -0
  344. rucio/db/sqla/migrate_repo/versions/fe8ea2fa9788_added_third_party_copy_column_to_rse_.py +46 -0
  345. rucio/db/sqla/models.py +1834 -0
  346. rucio/db/sqla/sautils.py +48 -0
  347. rucio/db/sqla/session.py +470 -0
  348. rucio/db/sqla/types.py +207 -0
  349. rucio/db/sqla/util.py +521 -0
  350. rucio/rse/__init__.py +97 -0
  351. rucio/rse/protocols/__init__.py +14 -0
  352. rucio/rse/protocols/cache.py +123 -0
  353. rucio/rse/protocols/dummy.py +112 -0
  354. rucio/rse/protocols/gfal.py +701 -0
  355. rucio/rse/protocols/globus.py +243 -0
  356. rucio/rse/protocols/gsiftp.py +93 -0
  357. rucio/rse/protocols/http_cache.py +83 -0
  358. rucio/rse/protocols/mock.py +124 -0
  359. rucio/rse/protocols/ngarc.py +210 -0
  360. rucio/rse/protocols/posix.py +251 -0
  361. rucio/rse/protocols/protocol.py +530 -0
  362. rucio/rse/protocols/rclone.py +365 -0
  363. rucio/rse/protocols/rfio.py +137 -0
  364. rucio/rse/protocols/srm.py +339 -0
  365. rucio/rse/protocols/ssh.py +414 -0
  366. rucio/rse/protocols/storm.py +207 -0
  367. rucio/rse/protocols/webdav.py +547 -0
  368. rucio/rse/protocols/xrootd.py +295 -0
  369. rucio/rse/rsemanager.py +752 -0
  370. rucio/tests/__init__.py +14 -0
  371. rucio/tests/common.py +244 -0
  372. rucio/tests/common_server.py +132 -0
  373. rucio/transfertool/__init__.py +14 -0
  374. rucio/transfertool/fts3.py +1484 -0
  375. rucio/transfertool/globus.py +200 -0
  376. rucio/transfertool/globus_library.py +182 -0
  377. rucio/transfertool/mock.py +81 -0
  378. rucio/transfertool/transfertool.py +212 -0
  379. rucio/vcsversion.py +11 -0
  380. rucio/version.py +46 -0
  381. rucio/web/__init__.py +14 -0
  382. rucio/web/rest/__init__.py +14 -0
  383. rucio/web/rest/flaskapi/__init__.py +14 -0
  384. rucio/web/rest/flaskapi/authenticated_bp.py +28 -0
  385. rucio/web/rest/flaskapi/v1/__init__.py +14 -0
  386. rucio/web/rest/flaskapi/v1/accountlimits.py +234 -0
  387. rucio/web/rest/flaskapi/v1/accounts.py +1088 -0
  388. rucio/web/rest/flaskapi/v1/archives.py +100 -0
  389. rucio/web/rest/flaskapi/v1/auth.py +1642 -0
  390. rucio/web/rest/flaskapi/v1/common.py +385 -0
  391. rucio/web/rest/flaskapi/v1/config.py +305 -0
  392. rucio/web/rest/flaskapi/v1/credentials.py +213 -0
  393. rucio/web/rest/flaskapi/v1/dids.py +2204 -0
  394. rucio/web/rest/flaskapi/v1/dirac.py +116 -0
  395. rucio/web/rest/flaskapi/v1/export.py +77 -0
  396. rucio/web/rest/flaskapi/v1/heartbeats.py +129 -0
  397. rucio/web/rest/flaskapi/v1/identities.py +263 -0
  398. rucio/web/rest/flaskapi/v1/import.py +133 -0
  399. rucio/web/rest/flaskapi/v1/lifetime_exceptions.py +315 -0
  400. rucio/web/rest/flaskapi/v1/locks.py +360 -0
  401. rucio/web/rest/flaskapi/v1/main.py +83 -0
  402. rucio/web/rest/flaskapi/v1/meta.py +226 -0
  403. rucio/web/rest/flaskapi/v1/metrics.py +37 -0
  404. rucio/web/rest/flaskapi/v1/nongrid_traces.py +97 -0
  405. rucio/web/rest/flaskapi/v1/ping.py +89 -0
  406. rucio/web/rest/flaskapi/v1/redirect.py +366 -0
  407. rucio/web/rest/flaskapi/v1/replicas.py +1866 -0
  408. rucio/web/rest/flaskapi/v1/requests.py +841 -0
  409. rucio/web/rest/flaskapi/v1/rses.py +2204 -0
  410. rucio/web/rest/flaskapi/v1/rules.py +824 -0
  411. rucio/web/rest/flaskapi/v1/scopes.py +161 -0
  412. rucio/web/rest/flaskapi/v1/subscriptions.py +646 -0
  413. rucio/web/rest/flaskapi/v1/templates/auth_crash.html +80 -0
  414. rucio/web/rest/flaskapi/v1/templates/auth_granted.html +82 -0
  415. rucio/web/rest/flaskapi/v1/tmp_dids.py +115 -0
  416. rucio/web/rest/flaskapi/v1/traces.py +100 -0
  417. rucio/web/rest/flaskapi/v1/vos.py +280 -0
  418. rucio/web/rest/main.py +19 -0
  419. rucio/web/rest/metrics.py +28 -0
  420. rucio-32.8.6.data/data/rucio/etc/alembic.ini.template +71 -0
  421. rucio-32.8.6.data/data/rucio/etc/alembic_offline.ini.template +74 -0
  422. rucio-32.8.6.data/data/rucio/etc/globus-config.yml.template +5 -0
  423. rucio-32.8.6.data/data/rucio/etc/ldap.cfg.template +30 -0
  424. rucio-32.8.6.data/data/rucio/etc/mail_templates/rule_approval_request.tmpl +38 -0
  425. rucio-32.8.6.data/data/rucio/etc/mail_templates/rule_approved_admin.tmpl +4 -0
  426. rucio-32.8.6.data/data/rucio/etc/mail_templates/rule_approved_user.tmpl +17 -0
  427. rucio-32.8.6.data/data/rucio/etc/mail_templates/rule_denied_admin.tmpl +6 -0
  428. rucio-32.8.6.data/data/rucio/etc/mail_templates/rule_denied_user.tmpl +17 -0
  429. rucio-32.8.6.data/data/rucio/etc/mail_templates/rule_ok_notification.tmpl +19 -0
  430. rucio-32.8.6.data/data/rucio/etc/rse-accounts.cfg.template +25 -0
  431. rucio-32.8.6.data/data/rucio/etc/rucio.cfg.atlas.client.template +42 -0
  432. rucio-32.8.6.data/data/rucio/etc/rucio.cfg.template +257 -0
  433. rucio-32.8.6.data/data/rucio/etc/rucio_multi_vo.cfg.template +234 -0
  434. rucio-32.8.6.data/data/rucio/requirements.txt +55 -0
  435. rucio-32.8.6.data/data/rucio/tools/bootstrap.py +34 -0
  436. rucio-32.8.6.data/data/rucio/tools/merge_rucio_configs.py +147 -0
  437. rucio-32.8.6.data/data/rucio/tools/reset_database.py +40 -0
  438. rucio-32.8.6.data/scripts/rucio +2540 -0
  439. rucio-32.8.6.data/scripts/rucio-abacus-account +75 -0
  440. rucio-32.8.6.data/scripts/rucio-abacus-collection-replica +47 -0
  441. rucio-32.8.6.data/scripts/rucio-abacus-rse +79 -0
  442. rucio-32.8.6.data/scripts/rucio-admin +2434 -0
  443. rucio-32.8.6.data/scripts/rucio-atropos +61 -0
  444. rucio-32.8.6.data/scripts/rucio-auditor +199 -0
  445. rucio-32.8.6.data/scripts/rucio-automatix +51 -0
  446. rucio-32.8.6.data/scripts/rucio-bb8 +58 -0
  447. rucio-32.8.6.data/scripts/rucio-c3po +86 -0
  448. rucio-32.8.6.data/scripts/rucio-cache-client +135 -0
  449. rucio-32.8.6.data/scripts/rucio-cache-consumer +43 -0
  450. rucio-32.8.6.data/scripts/rucio-conveyor-finisher +59 -0
  451. rucio-32.8.6.data/scripts/rucio-conveyor-poller +67 -0
  452. rucio-32.8.6.data/scripts/rucio-conveyor-preparer +38 -0
  453. rucio-32.8.6.data/scripts/rucio-conveyor-receiver +44 -0
  454. rucio-32.8.6.data/scripts/rucio-conveyor-stager +77 -0
  455. rucio-32.8.6.data/scripts/rucio-conveyor-submitter +140 -0
  456. rucio-32.8.6.data/scripts/rucio-conveyor-throttler +105 -0
  457. rucio-32.8.6.data/scripts/rucio-dark-reaper +54 -0
  458. rucio-32.8.6.data/scripts/rucio-dumper +159 -0
  459. rucio-32.8.6.data/scripts/rucio-follower +45 -0
  460. rucio-32.8.6.data/scripts/rucio-hermes +55 -0
  461. rucio-32.8.6.data/scripts/rucio-judge-cleaner +90 -0
  462. rucio-32.8.6.data/scripts/rucio-judge-evaluator +138 -0
  463. rucio-32.8.6.data/scripts/rucio-judge-injector +45 -0
  464. rucio-32.8.6.data/scripts/rucio-judge-repairer +45 -0
  465. rucio-32.8.6.data/scripts/rucio-kronos +45 -0
  466. rucio-32.8.6.data/scripts/rucio-light-reaper +53 -0
  467. rucio-32.8.6.data/scripts/rucio-minos +54 -0
  468. rucio-32.8.6.data/scripts/rucio-minos-temporary-expiration +51 -0
  469. rucio-32.8.6.data/scripts/rucio-necromancer +121 -0
  470. rucio-32.8.6.data/scripts/rucio-oauth-manager +64 -0
  471. rucio-32.8.6.data/scripts/rucio-reaper +84 -0
  472. rucio-32.8.6.data/scripts/rucio-replica-recoverer +249 -0
  473. rucio-32.8.6.data/scripts/rucio-storage-consistency-actions +75 -0
  474. rucio-32.8.6.data/scripts/rucio-transmogrifier +78 -0
  475. rucio-32.8.6.data/scripts/rucio-undertaker +77 -0
  476. rucio-32.8.6.dist-info/METADATA +83 -0
  477. rucio-32.8.6.dist-info/RECORD +481 -0
  478. rucio-32.8.6.dist-info/WHEEL +5 -0
  479. rucio-32.8.6.dist-info/licenses/AUTHORS.rst +94 -0
  480. rucio-32.8.6.dist-info/licenses/LICENSE +201 -0
  481. rucio-32.8.6.dist-info/top_level.txt +1 -0
@@ -0,0 +1,155 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright European Organization for Nuclear Research (CERN) since 2012
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ from typing import TYPE_CHECKING
16
+
17
+ from sqlalchemy.orm.exc import NoResultFound
18
+
19
+ from rucio.common.exception import CounterNotFound
20
+ from rucio.db.sqla import models, filter_thread_work
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
+ session.query(models.RSEUsage).filter_by(rse_id=rse_id, source='rucio').\
76
+ delete(synchronize_session=False)
77
+
78
+
79
+ @read_session
80
+ def get_counter(rse_id, *, session: "Session"):
81
+ """
82
+ Returns current values of the specified counter or raises CounterNotFound if the counter does not exist.
83
+
84
+ :param rse_id: The id of the RSE.
85
+ :param session: The database session in use.
86
+ :returns: A dictionary with total and bytes.
87
+ :raises CounterNotFound: If the counter does not exist.
88
+ :returns: A dictionary with total and bytes.
89
+ """
90
+
91
+ try:
92
+ counter = session.query(models.RSEUsage).\
93
+ filter_by(rse_id=rse_id, source='rucio').one()
94
+ return {'bytes': counter.used,
95
+ 'files': counter.files,
96
+ 'updated_at': counter.updated_at}
97
+ except NoResultFound:
98
+ raise CounterNotFound()
99
+
100
+
101
+ @read_session
102
+ def get_updated_rse_counters(total_workers, worker_number, *, session: "Session"):
103
+ """
104
+ Get updated rse_counters.
105
+
106
+ :param total_workers: Number of total workers.
107
+ :param worker_number: id of the executing worker.
108
+ :param session: Database session in use.
109
+ :returns: List of rse_ids whose rse_counters need to be updated.
110
+ """
111
+ query = session.query(models.UpdatedRSECounter.rse_id).\
112
+ distinct(models.UpdatedRSECounter.rse_id)
113
+
114
+ query = filter_thread_work(session=session, query=query, total_threads=total_workers, thread_id=worker_number, hash_variable='rse_id')
115
+ results = query.all()
116
+ return [result.rse_id for result in results]
117
+
118
+
119
+ @transactional_session
120
+ def update_rse_counter(rse_id, *, session: "Session"):
121
+ """
122
+ Read the updated_rse_counters and update the rse_counter.
123
+
124
+ :param rse_id: The rse_id to update.
125
+ :param session: Database session in use.
126
+ """
127
+
128
+ updated_rse_counters = session.query(models.UpdatedRSECounter).filter_by(rse_id=rse_id).all()
129
+ sum_bytes = sum([updated_rse_counter.bytes for updated_rse_counter in updated_rse_counters])
130
+ sum_files = sum([updated_rse_counter.files for updated_rse_counter in updated_rse_counters])
131
+
132
+ try:
133
+ rse_counter = session.query(models.RSEUsage).filter_by(rse_id=rse_id, source='rucio').one()
134
+ rse_counter.used = (rse_counter.used or 0) + sum_bytes
135
+ rse_counter.files = (rse_counter.files or 0) + sum_files
136
+ except NoResultFound:
137
+ models.RSEUsage(rse_id=rse_id,
138
+ used=sum_bytes,
139
+ files=sum_files,
140
+ source='rucio').save(session=session)
141
+
142
+ for update in updated_rse_counters:
143
+ update.delete(flush=False, session=session)
144
+
145
+
146
+ @transactional_session
147
+ def fill_rse_counter_history_table(*, session: "Session"):
148
+ """
149
+ Fill the RSE usage history table with the current usage.
150
+
151
+ :param session: Database session in use.
152
+ """
153
+ RSEUsageHistory = models.RSEUsageHistory
154
+ for usage in session.query(models.RSEUsage).all():
155
+ RSEUsageHistory(rse_id=usage['rse_id'], used=usage['used'], files=usage['files'], source=usage['source']).save(session=session)
@@ -0,0 +1,460 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright European Organization for Nuclear Research (CERN) since 2012
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ import abc
17
+ import re
18
+ from hashlib import sha256
19
+ from typing import TYPE_CHECKING
20
+
21
+ from dogpile.cache.api import NoValue
22
+
23
+ from rucio.common.cache import make_region_memcached
24
+ from rucio.common.exception import InvalidRSEExpression, RSEWriteBlocked
25
+ from rucio.core.rse import list_rses, get_rses_with_attribute, get_rse_attribute
26
+ from rucio.db.sqla.session import transactional_session
27
+
28
+ if TYPE_CHECKING:
29
+ from sqlalchemy.orm import Session
30
+
31
+
32
+ DEFAULT_RSE_ATTRIBUTE = r'([A-Za-z0-9]+([_-][A-Za-z0-9]+)*)'
33
+ RSE_ATTRIBUTE = r'([A-Za-z0-9\._-]+[=<>][A-Za-z0-9_-]+)'
34
+ PRIMITIVE = r'(\(*(%s|%s|%s)\)*)' % (RSE_ATTRIBUTE, DEFAULT_RSE_ATTRIBUTE, r'\*')
35
+ UNION = r'(\|%s)' % (PRIMITIVE)
36
+ INTERSECTION = r'(\&%s)' % (PRIMITIVE)
37
+ COMPLEMENT = r'(\\%s)' % (PRIMITIVE)
38
+
39
+ PATTERN = r'^%s(%s|%s|%s)*' % (PRIMITIVE, UNION, INTERSECTION, COMPLEMENT)
40
+
41
+ REGION = make_region_memcached(expiration_time=600)
42
+
43
+
44
+ @transactional_session
45
+ def parse_expression(expression, filter_=None, *, session: "Session"):
46
+ """
47
+ Parse a RSE expression and return the list of RSE dictionaries.
48
+
49
+ :param expression: RSE expression, e.g: 'CERN|BNL'.
50
+ :param filter_: Availability filter (dictionary) used for the RSEs. e.g.: {'availability_write': True}
51
+ :param session: Database session in use.
52
+ :returns: A list of rse dictionaries.
53
+ :raises: InvalidRSEExpression, RSENotFound, RSEWriteBlocked
54
+ """
55
+ result = REGION.get(sha256(expression.encode()).hexdigest())
56
+ if type(result) is NoValue:
57
+ # Evaluate the correctness of the parentheses
58
+ parantheses_open_count = 0
59
+ parantheses_close_count = 0
60
+ for char in expression:
61
+ if (char == '('):
62
+ parantheses_open_count += 1
63
+ elif (char == ')'):
64
+ parantheses_close_count += 1
65
+ if (parantheses_close_count > parantheses_open_count):
66
+ raise InvalidRSEExpression('Problem with parantheses.')
67
+ if (parantheses_open_count != parantheses_close_count):
68
+ raise InvalidRSEExpression('Problem with parantheses.')
69
+
70
+ # Check the expression pattern
71
+ match = re.match(PATTERN, expression)
72
+ if match is None:
73
+ raise InvalidRSEExpression('Expression does not comply to RSE Expression syntax')
74
+ else:
75
+ if match.group() != expression:
76
+ raise InvalidRSEExpression('Expression does not comply to RSE Expression syntax')
77
+ result_tuple = __resolve_term_expression(expression)[0].resolve_elements(session=session)
78
+ # result_tuple = ([rse_ids], {rse_id: {rse_info}})
79
+ result = []
80
+ for rse in list(result_tuple[0]):
81
+ result.append(result_tuple[1][rse])
82
+ REGION.set(sha256(expression.encode()).hexdigest(), result)
83
+
84
+ # Filter for VO
85
+ vo_result = []
86
+ if filter_ and filter_.get('vo'):
87
+ filter_ = filter_.copy() # Make a copy so we can pop('vo') without affecting the object `filter` outside this function
88
+ vo = filter_.pop('vo')
89
+ for rse in result:
90
+ if rse.get('vo') == vo:
91
+ vo_result.append(rse)
92
+ else:
93
+ vo_result = result
94
+
95
+ if not vo_result:
96
+ raise InvalidRSEExpression('RSE Expression resulted in an empty set.')
97
+
98
+ # Filter
99
+ final_result = []
100
+ if filter_:
101
+ for rse in vo_result:
102
+ if filter_.get('availability_write', False):
103
+ if rse.get('availability_write'):
104
+ final_result.append(rse)
105
+ if not final_result:
106
+ raise RSEWriteBlocked('RSE excluded; not available for writing.')
107
+ else:
108
+ final_result = vo_result
109
+
110
+ # final_result = [{rse-info}]
111
+ return final_result
112
+
113
+
114
+ def __resolve_term_expression(expression):
115
+ """
116
+ Resolves a Term Expression and returns an object of type BaseExpressionElement
117
+
118
+ :param subexpression: String of the term expression.
119
+ :returns: Tuple of BaseExpressionElement, term Expression string
120
+ """
121
+
122
+ left_term = None
123
+ operator = None
124
+ original_expression = expression
125
+
126
+ while True:
127
+ if len(expression) == 0:
128
+ return (left_term, original_expression)
129
+ elif expression[0] == "(":
130
+ if left_term is None:
131
+ left_term, termexpression = __resolve_term_expression(__extract_term(expression))
132
+ expression = expression[len(termexpression) + 2:]
133
+ continue
134
+ else:
135
+ right_term, termexpression = __resolve_term_expression(__extract_term(expression))
136
+ expression = expression[len(termexpression) + 2:]
137
+ operator.set_left_term(left_term)
138
+ operator.set_right_term(right_term)
139
+ left_term = operator
140
+ operator = None
141
+ continue
142
+ elif expression[0] == "\\":
143
+ operator = ComplementOperator()
144
+ expression = expression[1:]
145
+ continue
146
+ elif expression[0] == "&":
147
+ operator = IntersectOperator()
148
+ expression = expression[1:]
149
+ continue
150
+ elif expression[0] == "|":
151
+ operator = UnionOperator()
152
+ expression = expression[1:]
153
+ continue
154
+ else:
155
+ if (left_term is None):
156
+ left_term, primitiveexpression = __resolve_primitive_expression(expression)
157
+ expression = expression[len(primitiveexpression):]
158
+ continue
159
+ else:
160
+ right_term, primitiveexpression = __resolve_primitive_expression(expression)
161
+ expression = expression[len(primitiveexpression):]
162
+ operator.set_left_term(left_term)
163
+ operator.set_right_term(right_term)
164
+ left_term = operator
165
+ operator = None
166
+ continue
167
+
168
+
169
+ def __resolve_primitive_expression(expression):
170
+ """
171
+ Resolve a primitive expression and return a RSEAttribute object
172
+
173
+ :param expression: String of the expresssion
174
+ :returns: Tuple of RSEAttribute, primitive expression
175
+ """
176
+ primitiveexpression = re.match(PRIMITIVE, expression).group()
177
+ if ('=' in primitiveexpression):
178
+ keyvalue = primitiveexpression.split("=")
179
+ return (RSEAttributeEqualCheck(keyvalue[0], keyvalue[1]), primitiveexpression)
180
+ elif ('<' in primitiveexpression):
181
+ keyvalue = primitiveexpression.split("<")
182
+ return (RSEAttributeSmallerCheck(keyvalue[0], keyvalue[1]), primitiveexpression)
183
+ elif ('>' in primitiveexpression):
184
+ keyvalue = primitiveexpression.split(">")
185
+ return (RSEAttributeLargerCheck(keyvalue[0], keyvalue[1]), primitiveexpression)
186
+ elif ('*' in primitiveexpression):
187
+ return (RSEAll(), primitiveexpression)
188
+ else:
189
+ return (RSEAttributeEqualCheck(key=primitiveexpression), primitiveexpression)
190
+
191
+
192
+ def __extract_term(expression):
193
+ """
194
+ Extract a term from an expression with parantheses
195
+
196
+ :param expression: The expression starting with a '('
197
+ :return: The extracted term string
198
+ """
199
+ open_parantheses = 0
200
+ i = 0
201
+ for char in expression:
202
+ if (char == '('):
203
+ open_parantheses += 1
204
+ elif (char == ')'):
205
+ open_parantheses -= 1
206
+ if (open_parantheses == 0):
207
+ return expression[1:i]
208
+ i = i + 1
209
+ raise SystemError('This point in the code should not be reachable')
210
+
211
+
212
+ class BaseExpressionElement(object, metaclass=abc.ABCMeta):
213
+ @abc.abstractmethod
214
+ def resolve_elements(self, session):
215
+ """
216
+ Resolve the ExpressionElement and return a set of RSE ids
217
+
218
+ :param session: Database session in use
219
+ :returns: (Set of RSE ids, Dictionary of RSE dicts)
220
+ :rtype: (Set of Strings, Dictionary of RSE dicts organized by rse_id)
221
+ """
222
+ pass
223
+
224
+
225
+ class RSEAll(BaseExpressionElement):
226
+ """
227
+ Representation of all RSEs
228
+ """
229
+
230
+ def resolve_elements(self, session):
231
+ """
232
+ Inherited from :py:func:`BaseExpressionElement.resolve_elements`
233
+ """
234
+ output = list_rses(session=session)
235
+ if not output:
236
+ return (set(), {})
237
+ rse_dict = {}
238
+ for rse in output:
239
+ rse_dict[rse['id']] = rse
240
+ return (set([rse['id'] for rse in output]), rse_dict)
241
+
242
+
243
+ class RSEAttributeEqualCheck(BaseExpressionElement):
244
+ """
245
+ Representation of an RSE Attribute with Equal Check
246
+ """
247
+
248
+ def __init__(self, key, value=True):
249
+ """
250
+ Creates an RSEAttribute representation
251
+
252
+ :param key: Key of the RSE Attribute.
253
+ :param value: Value of the RSE Attribute.
254
+ """
255
+ self.key = key
256
+ self.value = value
257
+
258
+ def resolve_elements(self, session):
259
+ """
260
+ Inherited from :py:func:`BaseExpressionElement.resolve_elements`
261
+ """
262
+ output = list_rses({self.key: self.value}, session=session)
263
+ if not output:
264
+ return (set(), {})
265
+ rse_dict = {}
266
+ for rse in output:
267
+ rse_dict[rse['id']] = rse
268
+ return (set([rse['id'] for rse in output]), rse_dict)
269
+
270
+
271
+ class RSEAttributeSmallerCheck(BaseExpressionElement):
272
+ """
273
+ Representation of an RSE Attribute with Smaller (<) Check
274
+ """
275
+
276
+ def __init__(self, key, value=True):
277
+ """
278
+ Creates an RSEAttribute representation
279
+
280
+ :param key: Key of the RSE Attribute.
281
+ :param value: Value of the RSE Attribute.
282
+ """
283
+ self.key = key
284
+ self.value = value
285
+
286
+ def resolve_elements(self, session):
287
+ """
288
+ Inherited from :py:func:`BaseExpressionElement.resolve_elements`
289
+ """
290
+ rse_list = get_rses_with_attribute(key=self.key, session=session)
291
+ if not rse_list:
292
+ return (set(), {})
293
+
294
+ output = []
295
+ rse_dict = {}
296
+ for rse in rse_list:
297
+ try:
298
+ if float(get_rse_attribute(rse['id'], self.key, session=session)) < float(self.value):
299
+ rse_dict[rse['id']] = rse
300
+ output.append(rse['id'])
301
+ except ValueError:
302
+ continue
303
+ return (set(output), rse_dict)
304
+
305
+
306
+ class RSEAttributeLargerCheck(BaseExpressionElement):
307
+ """
308
+ Representation of an RSE Attribute with Larger (>) Check
309
+ """
310
+
311
+ def __init__(self, key, value=True):
312
+ """
313
+ Creates an RSEAttribute representation
314
+
315
+ :param key: Key of the RSE Attribute.
316
+ :param value: Value of the RSE Attribute.
317
+ """
318
+ self.key = key
319
+ self.value = value
320
+
321
+ def resolve_elements(self, session):
322
+ """
323
+ Inherited from :py:func:`BaseExpressionElement.resolve_elements`
324
+ """
325
+ rse_list = get_rses_with_attribute(key=self.key, session=session)
326
+ if not rse_list:
327
+ return (set(), {})
328
+
329
+ output = []
330
+ rse_dict = {}
331
+ for rse in rse_list:
332
+ try:
333
+ if float(get_rse_attribute(rse['id'], self.key, session=session)) > float(self.value):
334
+ rse_dict[rse['id']] = rse
335
+ output.append(rse['id'])
336
+ except ValueError:
337
+ continue
338
+ return (set(output), rse_dict)
339
+
340
+
341
+ class BaseRSEOperator(BaseExpressionElement, metaclass=abc.ABCMeta):
342
+ @abc.abstractmethod
343
+ def set_left_term(self, left_term):
344
+ """
345
+ Set the left site of the term
346
+
347
+ :param left_term: Left term
348
+ """
349
+ pass
350
+
351
+ @abc.abstractmethod
352
+ def set_right_term(self, right_term):
353
+ """
354
+ Set the right site of the term
355
+
356
+ :param left_term: Left term
357
+ """
358
+ pass
359
+
360
+
361
+ class ComplementOperator(BaseRSEOperator):
362
+ """
363
+ Representation of the complement operator
364
+ """
365
+
366
+ def __init__(self):
367
+ """
368
+ Create a ComplementOperator representation
369
+ """
370
+
371
+ self.left_term = None
372
+ self.right_term = None
373
+
374
+ def set_left_term(self, left_term):
375
+ """
376
+ Inherited from :py:func:`BaseRSEOperator.set_left_term`
377
+ """
378
+ self.left_term = left_term
379
+
380
+ def set_right_term(self, right_term):
381
+ """
382
+ Inherited from :py:func:`BaseRSEOperator.set_right_term`
383
+ """
384
+ self.right_term = right_term
385
+
386
+ def resolve_elements(self, session):
387
+ """
388
+ Inherited from :py:func:`BaseExpressionElement.resolve_elements`
389
+ """
390
+ left_term_tuple = self.left_term.resolve_elements(session=session)
391
+ right_term_tuple = self.right_term.resolve_elements(session=session)
392
+ return (left_term_tuple[0] - right_term_tuple[0], dict(list(left_term_tuple[1].items()) + list(right_term_tuple[1].items())))
393
+
394
+
395
+ class UnionOperator(BaseRSEOperator):
396
+ """
397
+ Representation of the or operator
398
+ """
399
+
400
+ def __init__(self):
401
+ """
402
+ Create a UnionOperator representation
403
+ """
404
+
405
+ self.left_term = None
406
+ self.right_term = None
407
+
408
+ def set_left_term(self, left_term):
409
+ """
410
+ Inherited from :py:func:`BaseRSEOperator.set_left_term`
411
+ """
412
+ self.left_term = left_term
413
+
414
+ def set_right_term(self, right_term):
415
+ """
416
+ Inherited from :py:func:`BaseRSEOperator.set_right_term`
417
+ """
418
+ self.right_term = right_term
419
+
420
+ def resolve_elements(self, session):
421
+ """
422
+ Inherited from :py:func:`BaseExpressionElement.resolve_elements`
423
+ """
424
+ left_term_tuple = self.left_term.resolve_elements(session=session)
425
+ right_term_tuple = self.right_term.resolve_elements(session=session)
426
+ return (left_term_tuple[0] | right_term_tuple[0], dict(list(left_term_tuple[1].items()) + list(right_term_tuple[1].items())))
427
+
428
+
429
+ class IntersectOperator(BaseRSEOperator):
430
+ """
431
+ Representation of the intersect operator
432
+ """
433
+
434
+ def __init__(self):
435
+ """
436
+ Create a IntersectOperator representation
437
+ """
438
+
439
+ self.left_term = None
440
+ self.right_term = None
441
+
442
+ def set_left_term(self, left_term):
443
+ """
444
+ Inherited from :py:func:`BaseRSEOperator.set_left_term`
445
+ """
446
+ self.left_term = left_term
447
+
448
+ def set_right_term(self, right_term):
449
+ """
450
+ Inherited from :py:func:`BaseRSEOperator.set_right_term`
451
+ """
452
+ self.right_term = right_term
453
+
454
+ def resolve_elements(self, session):
455
+ """
456
+ Inherited from :py:func:`BaseExpressionElement.resolve_elements`
457
+ """
458
+ left_term_tuple = self.left_term.resolve_elements(session=session)
459
+ right_term_tuple = self.right_term.resolve_elements(session=session)
460
+ return (left_term_tuple[0] & right_term_tuple[0], dict(list(left_term_tuple[1].items()) + list(right_term_tuple[1].items())))